/* Slate — campaign editor styles (ported from cms-original/index.html).
   Loaded only by the editor page. Variable aliases at the top map the
   original CMS token names onto the live --aq-* tokens so the rules
   below work unchanged. */

/* Reset the prototype's old .ce-app grid rule (defined in
   campaign-editor.css) which pinned the whole editor into a 64px
   column. The shell is a flex column holding the topbar + ce-body. */
.ce-app {
  display: flex !important;
  flex-direction: column !important;
  grid-template-columns: none !important;
  grid-template-rows: none !important;
  width: 100% !important;
  height: 100% !important;
  min-height: 0;
}
.ce-app > .ce-shell {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  width: 100%;
}
/* Original .ce-body is a 3-col grid (rail + left + main). Per-element
   properties are surfaced in the LEFT panel via data-left-mode rather
   than a separate right inspector — matches the cms-original layout.
   The .ce-right aside stays in the DOM but is display:none. */
.ce-app .ce-body {
  /* The .ce-left aside is now portalled OUT of here into #aq-page-rail
     so this body only contains the canvas zone. Single column,
     transparent, edge to edge inside .aq-main. */
  grid-template-columns: minmax(0, 1fr) !important;
  gap: 0 !important;
  padding: 0 !important;
  margin: 0 !important;
  background: transparent !important;
  border: 0 !important;
  border-radius: 0 !important;
  box-shadow: none !important;
  flex: 1 1 0;
  min-height: 0;
}
/* CE_TopBar — second header row inside .aq-main, sitting below
   .aq-topbar (breadcrumbs). Hairline below matches the .aq-topbar's
   own border-bottom so the two stack as one unified card header. */
.ce-app > .ce-shell > .ce-topbar {
  height: 48px;
  flex-shrink: 0;
  padding: 0 24px;
  background: transparent;
  border-bottom: 1px solid var(--aq-line);
}
body.ce-left-collapsed .ce-app .ce-body {
  grid-template-columns: minmax(0, 1fr) !important;
}
body.ce-left-collapsed .ce-left { display: none; }
/* Right pane intentionally hidden — all per-layout controls live in the
   top floating toolbar (see CE_OverlayToolbar / .ce-overlay-toolbar)
   matching cms-original's pill-dock pattern. */
.ce-app .ce-right { display: none !important; }
/* Editor tools rail — REPLACES the global Sidebar on the campaign
   editor route. app.jsx swaps <Sidebar /> for <div id="aq-page-rail"
   class="aq-sidebar aq-page-rail" /> when route === 'campaign'. The
   .aq-sidebar class gives it the dashboard sidebar's exact width,
   background and chrome; the editor portals its <aside class="ce-left">
   into the div via ReactDOM.createPortal. Result: identical dashboard
   layout, with editor tools where the app nav would be. */
.aq-page-rail {
  /* Inherit width/flex/bg from .aq-sidebar (applied via dual class
     in app.jsx); just make sure the portalled child can fill it. */
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.aq-page-rail .ce-left {
  width: 100%;
  height: 100%;
  background: transparent !important;
  border: 0 !important;
  border-radius: 0 !important;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
}
/* Canvas zone — flat. The preview screen's bezel is the only visible
   box on the page. */
.ce-app .ce-center {
  display: flex !important;
  flex-direction: column !important;
  background: transparent !important;
  border: 0 !important;
  border-radius: 0 !important;
  overflow: hidden !important;
  box-shadow: none !important;
}
/* CE_TopBar — internal header at the top of the canvas zone, hairline
   divider, no card. */
.ce-app .ce-center > .ce-topbar {
  background: transparent;
  border-bottom: 1px solid var(--aq-line, rgba(255,255,255,0.06));
  padding: 8px 14px;
}
/* Selection mode swaps the left panel to the per-element Properties
   form when an element is clicked on the canvas. */
body[data-ce-panel="selection"] .ce-left-mode[data-left-mode="selection"] {
  display: block !important;
}

/* Editor preview iframe — the kiosk display dims species photos to
   brightness 0.55 so on-card text reads. Inside the editor preview
   the curator wants to see what's actually behind their overlay, so
   we lift the dimming via an override that only fires for the
   in-editor iframe (parent .ce-preview-frame-wrapper). The override
   posts through via the iframe's same-origin-load on the React side. */

/* The page background carries an SVG fractalNoise dither (styles.css
   line 209+) — looks like grain, especially loud against light mode's
   cream wash. Inside the campaign editor the cream surface around the
   canvas should read clean, so swap the noise-textured backgrounds
   for plain colour while ce-editor-active is on the body. */
body.ce-editor-active {
  background: var(--aq-page) !important;
}
/* Editor uses the SAME main-panel gradient as the dashboard so the two
   pages share one chrome language. Earlier this forced a flat colour
   to avoid uneven banding across separate topbar / canvas / dock
   zones — but those zones have since been merged into a single
   continuous surface, so the dashboard gradient now reads cleanly. */
body.ce-editor-active .aq-main {
  background: var(--aq-main-grad) !important;
}
body.ce-editor-active .aq-atmosphere { display: none !important; }
/* Drop the hairline divider between the page topbar (breadcrumbs +
   actions) and the editor canvas so the whole interior reads as ONE
   continuous surface, matching the dashboard's main panel pattern. */
body.ce-editor-active .aq-topbar {
  border-bottom: 0 !important;
  background: transparent !important;
}
/* Wider sidebar ONLY on the campaign editor — the global default
   (232px) is what the dashboard / lists / settings pages need. The
   editor needs more room to fit the icon rail + template thumbnail
   grid + frame title side-by-side. */
body.ce-editor-active .aq-sidebar {
  width: 450px;
}
/* Global app Topbar stays — breadcrumbs (Slate / Campaigns / id) +
   notification bell + settings cog are part of every route's chrome,
   and the editor uses the same pattern as the dashboard. */

/* Original CMS computes --ce-preview-scale in JS via applyCePreviewScale()
   to shrink the bezel-sized frame (1920×1080 intrinsic) to fit the
   pane. We don't run that loop yet — clamp the frame to its container
   so the species strip + bottom dock stay on-screen. The React-side
   inline transform: scale(${zoom}) still handles user-controlled zoom. */
.ce-app .ce-center {
  min-height: 0 !important;
  overflow: hidden !important;
}
.ce-app .ce-preview-frame-wrapper {
  flex: 1 1 0 !important;
  min-height: 0 !important;
  overflow: hidden !important;
  /* Centre the frame and let aspect-ratio compute its dimensions
     against the container — prevents the 16:9 box from being squashed
     into a wider rectangle when both width AND height are 100%. */
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
}
.ce-app .ce-preview-frame-wrapper .ce-preview-frame {
  /* True 16:9 sizing: take 100% of the available height, derive width
     via aspect-ratio. If the derived width exceeds the parent, max-
     width:100% clamps and the height adjusts so the ratio is honoured.
     Setting both width:100% and height:100% (the previous code) defeats
     aspect-ratio in some browsers and made the kiosk read too wide. */
  width: auto !important;
  height: 100% !important;
  max-width: 100% !important;
  max-height: 100% !important;
  aspect-ratio: 16 / 9 !important;
  transform-origin: center center !important;
}
.ce-app .ce-preview-frame.ce-aspect-9-16 {
  aspect-ratio: 9 / 16 !important;
  /* Portrait kiosks (1080×1920): clamp to height first, derive width. */
  height: 100% !important;
  width: auto !important;
  max-width: 100% !important;
}

.ce-app { /* token alias scope */
  --surface: var(--aq-surface);
  --surface-2: var(--aq-surface-2);
  --surface-3: var(--aq-surface-3);
  --border: var(--aq-line);
  --border-hover: var(--aq-line-strong);
  --text: var(--aq-text-muted);
  --text-bright: var(--aq-text);
  --text-dim: var(--aq-text-dim);
  --bg: var(--aq-bg);
  --bg-deep: var(--aq-surface-2);
  --brand-primary: var(--aq-accent);
  --aqua-glow: color-mix(in srgb, var(--aq-accent) 20%, transparent);
  --red: var(--aq-danger);
  --green: var(--aq-success);
  --orange: var(--aq-warn, #F2C879);
}

        .ce-shell { display:flex; flex-direction:column; height:100%; min-height:0; }
        .ce-topbar {
          /* Sits inside .aq-main as the second header row beneath
             .aq-topbar (breadcrumbs). Fully transparent so .aq-main's
             gradient surface shows through unbroken — the user wants
             the entire centre to read as one continuous surface, with
             only a hairline divider between rows. */
          display:flex; align-items:center; gap:12px; padding:10px 18px;
          background: transparent;
          border-bottom: 1px solid var(--aq-line, rgba(255,255,255,0.06));
          position: relative; z-index: 5;
        }
        .ce-name-input {
          flex:1; font-size:17px; font-weight:600; background:transparent;
          border:1px solid transparent; color:var(--text-bright); padding:6px 10px; border-radius:6px;
        }
        .ce-name-input:focus { border-color:var(--border); outline:none; background:var(--bg-deep); }
        .ce-status-badge {
          padding:5px 12px; border-radius:99px; font-size:10px; text-transform:uppercase;
          letter-spacing:1px; font-weight:700;
          background:rgba(241,245,249,0.06); color:var(--text-dim);
          border:1px solid rgba(241,245,249,0.10);
          box-shadow: 0 1px 0 rgba(255,255,255,0.04) inset;
        }
        .ce-status-badge.live       { color:#86efac; border-color:#065f46; }
        .ce-status-badge.paused     { color:#fbbf24; border-color:#b45309; }
        .ce-status-badge.archived   { color:var(--text-dim); }
        .ce-status-badge.pending_review { color:#93c5fd; border-color:#1e40af; }
        .ce-status-badge.approved   { color:#86efac; border-color:#065f46; }
        .ce-status-badge.changes_requested { color:#fca5a5; border-color:#991b1b; }

        /* Mode pill — Takeover (aqua) / Overlay (violet). Sits next to
           the status badge in the editor topbar, gives one-glance
           confirmation of the campaign kind. Set by ceOnEnter() based
           on ceState.creationMode or derived from the first creative's
           layout via OVERLAY_LAYOUTS. */

        .ce-topbar-actions { display:flex; gap:6px; align-items:center; flex-wrap:wrap; justify-content:flex-end; }
        @media (max-width: 900px) {
          .ce-topbar { flex-wrap:wrap; gap:8px; }
          .ce-name-input { min-width:160px; order:-1; }
          .ce-topbar-actions { width:100%; justify-content:flex-end; }
        }
        /* Phase 55a: overflow menu for secondary actions */
        .ce-overflow-wrap { position: relative; }
        .ce-overflow-menu {
          position: absolute; top: calc(100% + 6px); right: 0;
          min-width: 220px;
          background: var(--surface);
          border: 1px solid var(--border);
          border-radius: 10px;
          box-shadow: 0 12px 36px rgba(0,0,0,0.5), 0 0 0 1px rgba(255,255,255,0.04);
          padding: 6px;
          z-index: 120;
          display: flex; flex-direction: column; gap: 2px;
        }
        .ce-overflow-menu[hidden] { display: none; }
        .ce-overflow-menu button[role="menuitem"] {
          display: flex; align-items: center; gap: 10px;
          padding: 8px 12px; background: transparent;
          border: 0; border-radius: 6px; color: var(--text);
          font-size: 13px; font-weight: 500; text-align: left;
          cursor: pointer; transition: background .12s ease;
        }
        .ce-overflow-menu button[role="menuitem"]:hover {
          background: rgba(241, 245, 249, 0.1); color: var(--text-bright);
        }
        .ce-overflow-menu button[role="menuitem"] i {
          width: 14px; text-align: center; color: var(--text-dim);
        }
        .ce-overflow-sep {
          border: 0; border-top: 1px solid var(--border);
          margin: 4px 6px;
        }
        /* Save button with inline status — changes color + label
           based on ceSaveStatus state. Replaces the old pill beside
           the button. */
        .ce-save-btn[data-save-state="saving"] {
          filter: saturate(0.9);
        }
        .ce-save-btn[data-save-state="saved"] {
          background: rgba(74, 222, 128, 0.15);
          color: #86efac;
          border-color: rgba(74, 222, 128, 0.3);
        }
        .ce-save-btn[data-save-state="dirty"] {
          background: rgba(251, 191, 36, 0.14);
          color: #fbbf24;
          border-color: rgba(251, 191, 36, 0.3);
        }
        .ce-save-btn[data-save-state="error"] {
          background: rgba(239, 68, 68, 0.14);
          color: #fca5a5;
          border-color: rgba(239, 68, 68, 0.3);
        }

        /* Save status indicator (2026-04-19) */
        .ce-save-status {
          font-size:11px; color:var(--text-dim); padding:4px 8px; border-radius:99px;
          background:transparent; min-width:70px; display:inline-flex; align-items:center;
          gap:6px; justify-content:center; transition:all .2s;
        }
        .ce-save-status[data-state="saving"] { color:#fbbf24; }
        .ce-save-status[data-state="saving"]::before {
          content:""; width:8px; height:8px; border-radius:50%;
          background:#fbbf24; box-shadow:0 0 0 0 rgba(251,191,36,0.7);
          animation:ce-pulse 1.2s infinite;
        }
        .ce-save-status[data-state="saved"] { color:#4ade80; }
        .ce-save-status[data-state="saved"]::before {
          content:"✓"; font-weight:700;
        }
        .ce-save-status[data-state="dirty"] { color:#f97316; }
        .ce-save-status[data-state="dirty"]::before {
          content:""; width:8px; height:8px; border-radius:50%; background:#f97316;
        }
        .ce-save-status[data-state="error"] { color:#fca5a5; }
        .ce-save-status[data-state="error"]::before { content:"⚠"; }
        @keyframes ce-pulse {
          0%{ box-shadow:0 0 0 0 rgba(251,191,36,0.6);} 70%{ box-shadow:0 0 0 8px rgba(251,191,36,0);} 100%{ box-shadow:0 0 0 0 rgba(251,191,36,0);}
        }
        /* Phase 58e: top-right action cluster — Canva-ish polish.
           Icon-only ghosts (undo / redo / overflow) read as a related
           group; the labelled actions (Preview / Publish / Save) carry
           a subtle drop shadow so they lift off the bar. */
        .ce-topbar-actions .btn,
        .ce-topbar-actions .btn-sm {
          min-height:38px; min-width:38px;
          font-weight: 600; letter-spacing:.01em;
        }
        .ce-topbar-actions button[title]:not(:has(span)),
        .ce-topbar-actions .ce-icon-btn {
          min-width:38px; min-height:38px; padding:8px;
          display:inline-flex; align-items:center; justify-content:center;
          background:rgba(241,245,249,0.04); color:var(--text-dim);
          border:1px solid rgba(241,245,249,0.08);
          border-radius:10px; cursor:pointer; font-size:14px;
          transition:background .12s ease, color .12s ease, border-color .12s ease, transform .08s ease;
        }
        .ce-topbar-actions button[title]:not(:has(span)):hover,
        .ce-topbar-actions .ce-icon-btn:hover {
          background:rgba(241,245,249,0.10); color:var(--text-bright);
          border-color:rgba(241,245,249,0.16);
        }
        .ce-topbar-actions button[title]:not(:has(span)):active {
          transform: translateY(1px);
        }
        .ce-topbar-actions button[disabled] { opacity:.32; cursor:not-allowed; }
        /* Visual divider between the icon group and the labelled actions —
           a tiny dot sits to the left of the labelled actions row. */
        .ce-topbar-actions::before {
          /* No-op: marker for any future absolute children. */
          content: none;
        }
        /* Labelled CTAs (Preview / Publish / Save) get a soft elevation
           and a tighter rounded shape so they read as the primary
           controls in this row. */
        .ce-topbar-actions #cePreviewBtn,
        .ce-topbar-actions #ceSaveBtn,
        .ce-topbar-actions .btn-primary {
          border-radius: 10px;
          padding: 0 14px;
          box-shadow: 0 6px 14px rgba(0,0,0,0.22), 0 1px 0 rgba(255,255,255,0.04) inset;
        }
        .ce-topbar-actions #cePreviewBtn:hover,
        .ce-topbar-actions #ceSaveBtn:hover {
          box-shadow: 0 8px 18px rgba(0,0,0,0.32), 0 1px 0 rgba(255,255,255,0.06) inset;
        }

        /* Phase 23/55b: editor columns. Thin nav rail · left panel · preview ·
           right panel. Rail is flush (no panel chrome) so icons sit near
           the left edge; active state is per-button only. */
        /* 3-column editor body: rail · left mode panel · canvas. The
           old right-inspector column was retired — Properties moved
           into the canvas top toolbar, Schedule/Targets are rail
           panels, Live is now a rail panel too, leaving the canvas
           the full remaining width. */
        .ce-body { display:grid; grid-template-columns:76px 440px minmax(0,1fr); flex:1; min-height:0; }
        /* Collapsed mode — hide the secondary panel and let the canvas
           fill the space, leaving just the icon rail on the left. */
        body.ce-left-collapsed .ce-body { grid-template-columns: 76px minmax(0, 1fr); }
        body.ce-left-collapsed .ce-left { display: none; }
        body.ce-left-collapsed #ceCollapseLeftBtn i { transform: rotate(180deg); }
        /* Original CMS hid .ce-right entirely; the React rewrite uses it
           for the Schedule / Targets / Properties / Live tabs instead. */
        /* .ce-right { display:none !important; } */
        /* Back button retired from the rail — it lives at the topbar
           far-left now (.ce-topbar-back). */
        .ce-rail-back, .ce-rail-divider { display: none !important; }
        /* Topbar Back button — far-left, square, pulls focus the way
           a Canva-style "exit" affordance does. */
        .ce-topbar-back {
          width: 36px; height: 36px; flex-shrink: 0;
          display: inline-flex; align-items: center; justify-content: center;
          border: 1px solid var(--border);
          background: var(--surface-2, transparent);
          color: var(--text-dim);
          border-radius: 8px; cursor: pointer; font-size: 13px;
          margin-right: 14px;
          transition: all .15s;
        }
        .ce-topbar-back:hover {
          background: var(--surface);
          color: var(--text-bright);
          border-color: var(--border-hover, var(--border));
        }
        .ce-rail {
          display: flex; flex-direction: column; align-items: stretch;
          /* Small horizontal inset so the rounded active state has room
             to breathe without re-creating the original phantom border.
             padding-top matches the side panel so the rail icons and
             panel content share a visual baseline. */
          padding: 16px 4px 14px 4px;
          gap: 4px;
          overflow-y: auto;
          scrollbar-width: none;
          background: transparent;
          border-right: none;
        }
        .ce-rail::-webkit-scrollbar { display: none; }
        .ce-rail-btn {
          display: flex; flex-direction: column; align-items: center;
          gap: 3px;
          width: 100%;
          max-width: none;
          align-self: stretch;
          padding: 10px 4px;
          background: transparent; border: 0;
          color: var(--text-dim);
          font-size: 9px; font-weight: 600; letter-spacing: 0.04em;
          cursor: pointer;
          border-radius: 10px;
          transition: color .15s ease, background .15s ease,
                      box-shadow .15s ease, transform .15s ease;
        }
        .ce-rail-btn i { font-size: 14px; line-height: 1; }
        .ce-rail-label {
          text-transform: uppercase;
          white-space: nowrap;
          letter-spacing: 0.02em;
        }
        .ce-rail-btn:hover {
          color: var(--text-bright);
          background: rgba(241, 245, 249, 0.06);
        }
        .ce-rail-btn.is-active {
          color: var(--text-bright);
          background: rgba(241, 245, 249, 0.10);
        }
        .ce-rail-btn.is-active:hover {
          background: rgba(241, 245, 249, 0.14);
        }
        .ce-rail-spacer { flex: 1 1 auto; align-self: stretch; min-height: 8px; }
        /* Phase 57e/57f: divider retired — Back + tools sit on the
           same rail without a hairline between them. Spacing alone
           carries the visual separation. */
        .ce-rail-divider {
          height: 6px;
        }

        /* Phase 58c: contextual pill docks ABOVE the preview in its
           own row (centred), always visible for the current card.
           Contents rendered from the layout schema so every relevant
           control for the card type is reachable without clicking
           onto each element. */
        .ce-pill-dock {
          display: flex; justify-content: center;
          padding: 12px 18px 6px;
          min-height: 0;
        }
        .ce-preview-pill {
          display: flex; align-items: center; flex-wrap: wrap;
          gap: 8px;
          padding: 6px 10px;
          background: rgba(12, 18, 28, 0.96);
          backdrop-filter: blur(18px);
          -webkit-backdrop-filter: blur(18px);
          border: 1px solid rgba(255, 255, 255, 0.1);
          border-radius: 999px;
          box-shadow: 0 12px 36px rgba(0, 0, 0, 0.5),
                      0 0 0 1px rgba(241, 245, 249, 0.12) inset;
          max-width: calc(100% - 32px);
        }
        .ce-preview-pill[hidden] { display: none; }
        .ce-pill-group { display: flex; align-items: center; gap: 6px; }
        .ce-pill-sep {
          width: 1px; height: 18px;
          background: rgba(255,255,255,0.1);
        }
        .ce-pill-swatch {
          width: 24px; height: 24px;
          border-radius: 50%;
          border: 2px solid rgba(255,255,255,0.14);
          background: var(--cp-accent, #00c8b4);
          cursor: pointer;
          padding: 0;
          transition: border-color .15s ease, transform .15s ease;
        }
        .ce-pill-swatch:hover { border-color: rgba(255,255,255,0.35); transform: scale(1.05); }
        .ce-pill-colour-input {
          width: 0; height: 0; padding: 0; border: 0;
          opacity: 0; pointer-events: none;
          position: absolute;
        }
        .ce-pill-icon {
          color: var(--text-dim); font-size: 12px; width: 14px; text-align: center;
        }
        .ce-pill-link-input {
          flex: 0 1 180px;
          min-width: 100px;
          padding: 4px 8px;
          background: rgba(255,255,255,0.05);
          border: 1px solid rgba(255,255,255,0.08);
          border-radius: 999px;
          color: var(--text);
          font-size: 12px;
          outline: none;
        }
        .ce-pill-link-input:focus {
          border-color: rgba(241, 245, 249, 0.55);
          background: rgba(255,255,255,0.08);
        }
        /* Non-text slots that open the contextual pill on click —
           matching hover / focus feel of the contenteditable ones. */
        .ce-pill-target {
          outline: 2px dashed transparent;
          outline-offset: 3px;
          border-radius: 4px;
          transition: outline-color .15s ease, background-color .15s ease;
        }
        .ce-pill-target:hover  { outline-color: rgba(241, 245, 249, 0.55); }
        .ce-pill-target:focus  { outline: 2px solid rgba(241, 245, 249, 0.9); outline-offset: 3px; }

        /* Group visibility controlled by data-slot-kind. Each
           kind reveals only its relevant group(s). Accent colour
           swatch shows for ALL kinds (left-most group). */
        .ce-preview-pill .ce-pill-group#cePillLinkGroup,
        .ce-preview-pill .ce-pill-group#cePillUrlGroup,
        .ce-preview-pill .ce-pill-group#cePillQrGroup,
        .ce-preview-pill .ce-pill-group#cePillCountdownGroup,
        .ce-preview-pill .ce-pill-group#cePillStatGroup,
        .ce-preview-pill .ce-pill-group#cePillProgressGroup,
        .ce-preview-pill .ce-pill-group#cePillPriceGroup {
          display: none;
        }
        /* Show the pill separator only when any extra group is visible. */
        .ce-preview-pill[data-slot-kind="text"] .ce-pill-sep,
        .ce-preview-pill[data-slot-kind="logo"] .ce-pill-sep { display: none; }
        .ce-preview-pill[data-slot-kind="button"]     .ce-pill-group#cePillLinkGroup     { display: flex; }
        .ce-preview-pill[data-slot-kind="image"]      .ce-pill-group#cePillUrlGroup      { display: flex; }
        .ce-preview-pill[data-slot-kind="video"]      .ce-pill-group#cePillUrlGroup      { display: flex; }
        .ce-preview-pill[data-slot-kind="media"]      .ce-pill-group#cePillUrlGroup      { display: flex; }
        .ce-preview-pill[data-slot-kind="qr"]         .ce-pill-group#cePillQrGroup       { display: flex; }
        .ce-preview-pill[data-slot-kind="countdown"]  .ce-pill-group#cePillCountdownGroup{ display: flex; }
        .ce-preview-pill[data-slot-kind="stat"]       .ce-pill-group#cePillStatGroup     { display: flex; }
        .ce-preview-pill[data-slot-kind="progress_bar"].ce-pill-group#cePillProgressGroup{ display: flex; }
        .ce-preview-pill[data-slot-kind="progress_bar"] .ce-pill-group#cePillProgressGroup { display: flex; }
        .ce-preview-pill[data-slot-kind="price"]      .ce-pill-group#cePillPriceGroup    { display: flex; }
        .ce-preview-pill[data-slot-kind="badge"]      .ce-pill-group#cePillPriceGroup    { display: flex; }
        .ce-rail-btn.ce-rail-back {
          color: var(--text);
        }
        .ce-rail-btn.ce-rail-back:hover {
          color: var(--text-bright);
          background: rgba(255, 255, 255, 0.05);
        }

        /* Flash a section when the rail jumps to it so the eye lands. */
        .ce-section-flash {
          animation: ceSectionFlash 0.8s ease-out;
        }
        @keyframes ceSectionFlash {
          0%   { background: transparent; }
          30%  { background: rgba(241, 245, 249, 0.18); }
          100% { background: transparent; }
        }

        .ce-left, .ce-right {
          /* Phase 57/57f: panels flatten onto the editor body.
             Zero borders — sections are implied by their own
             internal headers + spacing. */
          background: transparent;
          border: 0;
          overflow-y: auto;
        }
        .ce-left {
          padding-left: 16px;
          padding-right: 16px;
          /* Was 26px — reduced so the Templates icon strip + Full
             screen/Overlay tabs sit at the same vertical height as the
             topbar's "Slate / Campaigns / Edit" row. Bug feedback
             a2a1a0bb. */
          padding-top: 8px;
        }
        .ce-right { border: 0; }

        /* Phase 51: custom scrollbar on the campaign editor sidebars +
           any other scrollable sub-surface inside them. The browser
           default (chunky grey track + light thumb) reads as OS chrome
           and clashes with the dark editor surface. This gives a
           thin, semi-transparent cyan thumb on a transparent track —
           present but unobtrusive. Firefox uses scrollbar-width; Chrome
           / Safari use the ::-webkit-scrollbar pseudo set. */
        .ce-left, .ce-right, .ce-layout-picker {
          scrollbar-width: thin;
          scrollbar-color: rgba(241, 245, 249, 0.35) transparent;
        }
        .ce-left::-webkit-scrollbar,
        .ce-right::-webkit-scrollbar,
        .ce-layout-picker::-webkit-scrollbar {
          width: 8px;
          height: 8px;
        }
        .ce-left::-webkit-scrollbar-track,
        .ce-right::-webkit-scrollbar-track,
        .ce-layout-picker::-webkit-scrollbar-track {
          background: transparent;
        }
        .ce-left::-webkit-scrollbar-thumb,
        .ce-right::-webkit-scrollbar-thumb,
        .ce-layout-picker::-webkit-scrollbar-thumb {
          background: rgba(241, 245, 249, 0.28);
          border-radius: 4px;
          border: 2px solid transparent;
          background-clip: padding-box;
          transition: background-color .15s ease;
        }
        .ce-left::-webkit-scrollbar-thumb:hover,
        .ce-right::-webkit-scrollbar-thumb:hover,
        .ce-layout-picker::-webkit-scrollbar-thumb:hover {
          background: rgba(241, 245, 249, 0.65);
          background-clip: padding-box;
        }
        .ce-left::-webkit-scrollbar-corner,
        .ce-right::-webkit-scrollbar-corner {
          background: transparent;
        }
        .ce-left, .ce-right {
          -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 16px, #000 calc(100% - 24px), transparent 100%);
          mask-image: linear-gradient(to bottom, transparent 0, #000 16px, #000 calc(100% - 24px), transparent 100%);
        }

        /* Narrow desktop / tablet: stack preview first, horizontal icon
           rail, then left + right panels in-flow (no slide-over drawers —
           topbar toggles for those were removed as non-functional). */
        @media (max-width: 1279px) {
          .ce-body,
          body[data-ce-panel="schedule"] .ce-body,
          body[data-ce-panel="targets"] .ce-body {
            display: flex;
            flex-direction: column;
            grid-template-columns: unset !important;
            position: relative;
            overflow-y: auto;
            overflow-x: hidden;
            min-height: 0;
            flex: 1;
          }
          .ce-center { order: -1; flex: 1 1 280px; min-height: 220px; }
          .ce-rail {
            flex: 0 0 auto; flex-direction: row; flex-wrap: wrap;
            align-items: center; align-content: flex-start;
            gap: 4px 6px; width: 100%; max-height: none;
            padding: 8px 8px 10px; overflow-x: auto; overflow-y: hidden;
            border-bottom: 1px solid rgba(255, 255, 255, 0.06);
          }
          .ce-rail-spacer { flex: 1 1 8px; min-width: 8px; min-height: 0; height: 0; align-self: stretch; }
          .ce-left, .ce-right {
            position: relative; top: auto; bottom: auto;
            left: auto !important; right: auto !important;
            width: 100% !important; max-width: none; z-index: 1;
            transform: none !important; transition: none; box-shadow: none;
            max-height: min(52vh, 560px); min-height: 0; flex: 0 1 auto;
            -webkit-mask-image: none; mask-image: none;
          }
        }
        /* The .ce-preview-skeleton (placeholder shimmer shown while the
           creative is loading) was mis-extracted from cms-original as
           ".ce-center" — fixed here so it actually targets the
           skeleton, not the centre column. */
        .ce-preview-skeleton {
          position:absolute; inset:0; display:flex; flex-direction:column;
          justify-content:center; padding:10%; animation:ce-skel-pulse 1.5s ease-in-out infinite;
          pointer-events:none;
        }
        .ce-preview-frame.ce-preview-ready .ce-preview-skeleton { display:none; }
        @keyframes ce-skel-pulse { 0%,100%{opacity:.6;} 50%{opacity:1;} }
        .ce-zoom-controls {
          display:flex; gap:4px; align-items:center; font-size:11px; color:var(--text-dim);
        }
        .ce-zoom-controls button {
          min-width:28px; min-height:28px; padding:4px; background:var(--surface-2);
          border:1px solid var(--border); border-radius:6px; color:var(--text);
          cursor:pointer; font-size:13px; display:inline-flex; align-items:center; justify-content:center;
        }
        .ce-zoom-controls button:hover { background:var(--border); }
        .ce-center {
          /* Phase 58e: stage matches the editor's main bg so the
             canvas pane blends in with the rail, topbar and dock —
             one continuous dark surface. The earlier cream-paper
             backdrop made the canvas look like a separate document
             window pasted into a dark editor; the curator wanted
             one cohesive surface instead. */
          position: relative;
          background: var(--bg);
          border-left: 1px solid rgba(255,255,255,0.06);
          display:flex; flex-direction:column; min-width:0;
        }

        /* Phase 23: section headers at 60% opacity so they fade back behind
           the preview. Brighten on hover/focus so scanning is still easy. */
        .ce-section-title {
          padding:14px 16px 6px; font-size:10px; text-transform:uppercase;
          letter-spacing:1.2px; color:var(--text-dim);
          opacity: 0.6;
          transition: opacity var(--aqos-d-2, 0.2s) var(--aqos-ease-out, ease);
        }
        .ce-section-title:hover,
        .ce-section-title[data-collapsed="true"] { opacity: 0.95; }
        .ce-left:hover .ce-section-title,
        .ce-right:hover .ce-section-title { opacity: 0.85; }
        /* Collapsible sections (2026-04-19): click a section title to toggle.
           The ::before chevron indicates collapsed state. Sections with
           data-collapsible="true" get the interactive behaviour. */
        .ce-section-title[data-collapsible="true"] {
          cursor:pointer; user-select:none; display:flex; align-items:center;
          gap:8px; transition:color .15s;
        }
        .ce-section-title[data-collapsible="true"]:hover { color:var(--text-bright); }
        .ce-section-title[data-collapsible="true"]::before {
          content:"▾"; font-size:9px; display:inline-block;
          transition:transform .15s; color:var(--text-dim);
        }
        .ce-section-title[data-collapsible="true"][data-collapsed="true"]::before {
          transform:rotate(-90deg);
        }
        .ce-section-body[data-collapsed="true"] { display:none; }
        .ce-section-summary {
          font-size:10px; color:var(--text-dim); text-transform:none;
          letter-spacing:0; font-weight:400; margin-left:auto;
        }

        /* Templates pane mode switch — bare two-button selector.
           Per Sarah's feedback ("the grey backdrop on the full screen
           button is too much, make it more subtle like the rest of the
           app"), the active state lost its panel-style background. The
           selection now reads via a 2px accent underline + brighter text,
           matching the hairline-tab pattern used elsewhere in the app. */
        .ce-tpl-mode-switch {
          display: grid;
          grid-template-columns: 1fr 1fr;
          gap: 0;
          padding: 0;
          margin: 0 12px 12px;
          background: transparent;
          border-bottom: 1px solid var(--aq-line);
        }
        .ce-tpl-mode-btn {
          display: inline-flex; align-items: center; justify-content: center;
          gap: 6px;
          background: transparent; border: 0;
          color: var(--text-dim);
          font-size: 12px; font-weight: 500; letter-spacing: 0.02em;
          padding: 8px 10px;
          border-radius: 0;
          /* 2px transparent baseline reserves the underline space so the
             button doesn't shift vertically when its active state lights
             up the border. */
          border-bottom: 2px solid transparent;
          margin-bottom: -1px;   /* overlap the switch's bottom hairline */
          cursor: pointer;
          transition: color .15s ease, border-color .15s ease;
        }
        .ce-tpl-mode-btn i { font-size: 11px; opacity: 0.85; }
        .ce-tpl-mode-btn:hover { color: var(--text-bright); }
        .ce-tpl-mode-btn.is-active {
          color: var(--text-bright);
          font-weight: 600;
          border-bottom-color: var(--aq-accent, #00c8b4);
          background: transparent;
        }

        /* ── Daypart visual grid ───────────────────────────────────
           7 days × 24 hours. Click or click-drag to paint hours.
           Cells store as a 7×24 boolean matrix; serialised back to
           the existing daypart_json wire format on every change. */
        .dp-presets { display:flex; flex-wrap:wrap; gap:4px; margin-bottom:10px; }
        .dp-presets .btn-xs {
          font-size:12px; padding:7px 12px; border-radius:6px;
          background:rgba(255,255,255,0.04); color:var(--text-dim);
          border:1px solid var(--border); min-height:32px;
        }
        .dp-presets .btn-xs:hover { background:rgba(255,255,255,0.08); color:var(--text-bright); }
        .dp-grid {
          display:grid;
          grid-template-columns:32px repeat(24, 1fr);
          gap:1px; background:var(--border); border:1px solid var(--border); border-radius:6px;
          overflow:hidden; user-select:none; -webkit-user-select:none;
        }
        .ce-right-rail-compact .dp-grid {
          grid-template-columns: 24px repeat(24, 1fr);
        }
        .ce-right-rail-compact .dp-grid .dp-hour-label {
          font-size: 7px;
          padding: 1px 0;
        }
        .ce-right-rail-compact .dp-grid .dp-day-label {
          font-size: 8px;
          padding: 0 2px;
        }
        .ce-right-rail-compact .dp-cell {
          min-height: 10px;
        }
        .dp-grid .dp-corner { background:var(--bg-deep); }
        .dp-grid .dp-hour-label,
        .dp-grid .dp-day-label {
          background:var(--bg-deep); color:var(--text-dim); text-align:center;
          font-size:9px; padding:2px 0; font-variant-numeric:tabular-nums;
          display:flex; align-items:center; justify-content:center;
        }
        .dp-grid .dp-day-label { font-size:10px; padding:0 4px; text-transform:uppercase; letter-spacing:0.5px; }
        .dp-cell {
          background:rgba(255,255,255,0.04); cursor:pointer;
          aspect-ratio:1; transition:background 0.06s;
          min-height:14px;
        }
        .dp-cell:hover { background:rgba(241, 245, 249,0.18); }
        .dp-cell.on   { background:var(--aqua,#f1f5f9); }
        .dp-cell.on:hover { background:#00d8f0; }
        .dp-summary {
          margin-top:8px; font-size:11px; color:var(--text-dim); line-height:1.5;
          padding:8px 10px; background:rgba(255,255,255,0.02); border-radius:6px;
          min-height:18px;
        }
        .dp-summary .dp-day { color:var(--text); font-weight:500; margin-right:4px; }
        .dp-summary .dp-windows { color:var(--aqua,#f1f5f9); font-variant-numeric:tabular-nums; }

        /* ── Bulk actions bar (Phase 3.1) ────────────────────────── */
        .campaigns-bulk-bar {
          display:flex; align-items:center; gap:8px;
          padding:10px 14px; margin-bottom:10px;
          background:rgba(241, 245, 249,0.08);
          border:1px solid rgba(241, 245, 249,0.3);
          border-radius:8px;
        }
        .campaign-select-check {
          width:16px; height:16px; accent-color:var(--aqua,#f1f5f9); cursor:pointer;
        }

        /* ── Version history rows (Phase 2.3) ────────────────────── */
        .version-row {
          display:flex; justify-content:space-between; align-items:center;
          padding:10px 12px; background:var(--surface);
          border:1px solid var(--border); border-radius:8px; margin-bottom:6px;
        }

        /* ── Contrast reel (Phase 2.2) ───────────────────────────── */
        .ce-contrast-reel {
          padding:10px 16px; background:var(--surface);
          border-top:1px solid var(--border);
          display:flex; gap:10px; align-items:center; flex-wrap:wrap;
        }
        .ce-contrast-reel-label {
          font-size:10px; text-transform:uppercase; letter-spacing:1.2px;
          color:var(--text-dim); font-weight:600;
        }
        .ce-contrast-reel-thumbs {
          display:flex; gap:6px; flex:1; min-width:0; overflow-x:auto; padding:2px;
        }
        .ce-contrast-thumb {
          width:48px; height:48px; border-radius:6px; flex-shrink:0;
          background-size:cover; background-position:center;
          background-color:var(--bg-deep); cursor:pointer;
          border:2px solid transparent; transition:all .15s; position:relative;
        }
        .ce-contrast-thumb:hover { transform:scale(1.05); }
        .ce-contrast-thumb.active {
          border-color:var(--aqua,#f1f5f9);
          box-shadow:0 0 8px rgba(241, 245, 249,0.5);
        }
        .ce-contrast-warning {
          font-size:11px; padding:4px 10px; border-radius:99px;
          background:rgba(255,193,7,0.15); color:#ffd89b;
          border:1px solid rgba(255,193,7,0.3);
        }

        /* ── AI copy assist (Phase 2.1) ──────────────────────────── */
        .ce-ai-btn {
          font-size:11px; font-weight:600; padding:6px 12px; margin-left:6px;
          border-radius:99px; cursor:pointer; vertical-align:middle;
          background:linear-gradient(135deg,#7e3ff2,#5e2cd4); color:#fff;
          border:none; line-height:1.4; min-height:28px; min-width:32px;
          display:inline-flex; align-items:center; gap:4px;
        }
        .ce-ai-btn:hover { filter:brightness(1.15); }
        .ce-ai-suggestions { margin-top:6px; display:flex; flex-direction:column; gap:4px; }
        .ce-ai-suggestion {
          display:flex; gap:8px; align-items:flex-start; text-align:left;
          padding:8px 10px; background:rgba(126,63,242,0.07);
          border:1px solid rgba(126,63,242,0.2); border-radius:6px;
          color:var(--text); font-size:12px; cursor:pointer; line-height:1.4;
        }
        .ce-ai-suggestion:hover { background:rgba(126,63,242,0.12); border-color:rgba(126,63,242,0.5); }
        .ce-ai-rank {
          font-weight:700; color:#a78bfa; min-width:14px; text-align:center;
        }
        .ce-ai-loading {
          padding:8px 10px; font-size:11px; color:var(--text-dim);
          background:rgba(126,63,242,0.04); border-radius:6px;
        }
        .ce-ai-close {
          font-size:10px; padding:2px 8px; background:transparent;
          color:var(--text-dim); border:1px solid var(--border); border-radius:4px;
          cursor:pointer;
        }
        .ce-ai-close:hover { color:var(--text-bright); }

        /* ── Asset library (Phase 1.5) ───────────────────────────── */
        .asset-drop {
          border:2px dashed var(--border); border-radius:10px;
          padding:20px; text-align:center; background:var(--bg-deep);
          transition:all .15s;
        }
        .asset-drop.dragover {
          border-color:var(--aqua,#f1f5f9); background:rgba(241, 245, 249,0.08);
        }
        .asset-grid {
          display:grid; grid-template-columns:repeat(auto-fill,minmax(160px,1fr)); gap:10px;
          max-height:400px; overflow-y:auto;
        }
        .asset-tile {
          position:relative; border-radius:8px; overflow:hidden;
          background:var(--bg-deep); border:1px solid var(--border);
          aspect-ratio:1/1; cursor:pointer; transition:all .12s;
        }
        .asset-tile:hover { border-color:var(--aqua,#f1f5f9); transform:translateY(-2px); }
        .asset-tile img, .asset-tile video {
          width:100%; height:100%; object-fit:cover; display:block;
        }
        .asset-tile-name {
          position:absolute; bottom:0; left:0; right:0;
          padding:6px 8px; font-size:10px; color:#fff;
          background:linear-gradient(to top, rgba(0,0,0,0.75), rgba(0,0,0,0));
          white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
        }
        .asset-tile-actions {
          position:absolute; top:6px; right:6px; display:flex; gap:4px;
          opacity:0; transition:opacity .12s;
        }
        .asset-tile:hover .asset-tile-actions { opacity:1; }
        .asset-tile-actions button {
          padding:4px 8px; font-size:10px; border-radius:4px;
          background:rgba(0,0,0,0.7); color:#fff; border:1px solid rgba(255,255,255,0.2);
          cursor:pointer;
        }
        .asset-tile-actions button:hover { background:var(--aqua,#f1f5f9); color:#001a3d; border-color:transparent; }

        /* ── Template gallery (Phase 1.4) ────────────────────────── */
        .template-gallery-grid {
          display:grid; grid-template-columns:repeat(auto-fill,minmax(220px,1fr)); gap:14px;
        }
        .template-card {
          background:var(--surface); border:1px solid var(--border);
          border-radius:10px; overflow:hidden; cursor:pointer;
          transition:all .15s; text-align:left;
        }
        .template-card:hover {
          border-color:var(--aqua,#f1f5f9);
          transform:translateY(-2px);
          box-shadow:0 8px 24px rgba(0,0,0,0.3);
        }
        .template-thumb {
          height:130px; display:flex; align-items:center; justify-content:center;
          color:#fff; padding:14px; position:relative;
        }
        .template-thumb-title {
          font-size:22px; font-weight:800; letter-spacing:0.5px;
          text-shadow:0 2px 8px rgba(0,0,0,0.35);
        }
        .template-mode-pill {
          position:absolute; top:8px; right:8px;
          padding:2px 8px; border-radius:99px;
          font-size:9px; font-weight:600; letter-spacing:1px; text-transform:uppercase;
          background:rgba(0,0,0,0.4); color:#fff;
        }
        .template-body { padding:12px 14px; }
        .template-name  { font-weight:600; color:var(--text-bright); margin-bottom:4px; font-size:14px; }
        .template-desc  { font-size:12px; color:var(--text-dim); line-height:1.45; }

        /* ── Brand palette swatches (Phase 1.3) ──────────────────── */
        .ce-brand-palette {
          display:flex; flex-wrap:wrap; gap:5px; margin-bottom:6px;
        }
        .ce-brand-swatch {
          width:24px; height:24px; border-radius:6px; cursor:pointer;
          border:2px solid transparent; transition:transform .1s, border-color .15s;
          position:relative;
        }
        .ce-brand-swatch:hover  { transform:scale(1.1); }
        .ce-brand-swatch.active { border-color:#fff; box-shadow:0 0 0 2px var(--aqua,#f1f5f9); }
        .ce-brand-swatch[title]::after {
          content:attr(data-label); position:absolute; top:100%; left:50%;
          transform:translateX(-50%); white-space:nowrap;
          font-size:9px; color:var(--text-dim); opacity:0;
          transition:opacity .15s; pointer-events:none; margin-top:2px;
        }
        .ce-brand-swatch:hover[title]::after { opacity:1; }

        /* ── Campaign mode picker (Phase 1.2) ────────────────────── */
        .campaign-mode-grid {
          display:grid; grid-template-columns:1fr 1fr; gap:16px; margin-top:8px;
        }
        .campaign-mode-card {
          background:var(--surface); border:2px solid var(--border);
          border-radius:12px; padding:16px; cursor:pointer; text-align:left;
          color:var(--text); transition:all .15s; font-family:inherit;
        }
        .campaign-mode-card:hover {
          border-color:var(--aqua,#f1f5f9);
          background:rgba(241, 245, 249,0.06);
          transform:translateY(-2px);
          box-shadow:0 8px 24px rgba(0,0,0,0.3);
        }
        .campaign-mode-preview {
          height:120px; border-radius:8px; margin-bottom:12px;
          position:relative; overflow:hidden;
          background:linear-gradient(135deg,#0a2540 0%,#1e4060 100%);
          display:flex; flex-direction:column; align-items:center; justify-content:center;
        }
        .campaign-mode-preview.mode-takeover {
          background:linear-gradient(135deg,#ff6b4a 0%,#c4380e 100%);
        }
        .campaign-mode-preview .campaign-mode-title {
          font-size:28px; font-weight:800; color:#fff; letter-spacing:1px;
        }
        .campaign-mode-preview .campaign-mode-sub {
          font-size:12px; color:rgba(255,255,255,0.85); letter-spacing:2px; text-transform:uppercase;
        }
        .campaign-mode-preview.mode-overlay::before {
          content:''; position:absolute; inset:0;
          background-image:linear-gradient(45deg,rgba(255,255,255,0.06) 25%, transparent 25%, transparent 50%,rgba(255,255,255,0.06) 50%,rgba(255,255,255,0.06) 75%, transparent 75%);
          background-size:24px 24px;
        }
        .campaign-mode-preview .campaign-mode-overlay-badge {
          position:absolute; top:12px; left:12px; padding:6px 12px;
          background:#ff6b4a; color:#fff; border-radius:99px;
          font-size:11px; font-weight:700; letter-spacing:1px;
          z-index:1;
        }
        .campaign-mode-preview .campaign-mode-name {
          position:absolute; bottom:12px; left:12px;
          font-size:14px; font-weight:600; color:#fff; z-index:1;
          font-style:italic; opacity:0.9;
        }
        .campaign-mode-card .campaign-mode-label {
          font-size:14px; font-weight:600; color:var(--text-bright); margin-bottom:6px;
        }
        .campaign-mode-card .campaign-mode-desc {
          font-size:12px; color:var(--text-dim); line-height:1.5;
        }
        /* Mode picker polish — eyebrow, per-card tag, examples list. */
        .campaign-mode-eyebrow {
          font-size:10.5px; font-weight:700; letter-spacing:1.2px;
          text-transform:uppercase; color:var(--aqua);
          margin-bottom:4px;
        }
        .campaign-mode-tag {
          display:inline-flex; align-items:center; gap:5px;
          padding:3px 9px; border-radius:99px;
          font-size:10.5px; font-weight:700; letter-spacing:.7px;
          text-transform:uppercase;
          border:1px solid transparent; margin-bottom:8px;
        }
        .campaign-mode-tag::before {
          content:''; width:5px; height:5px; border-radius:50%; background:currentColor;
        }
        .campaign-mode-tag.tag-takeover {
          color:var(--aqua); background:var(--aqua-glow); border-color:var(--border-hover);
        }
        .campaign-mode-tag.tag-overlay {
          color:var(--purple);
          background:color-mix(in srgb, var(--purple) 14%, transparent);
          border-color:color-mix(in srgb, var(--purple) 32%, transparent);
        }
        .campaign-mode-card .campaign-mode-examples-label {
          font-size:10px; font-weight:600; letter-spacing:.7px;
          text-transform:uppercase; color:var(--text-dim);
          margin-top:14px; margin-bottom:5px;
        }
        .campaign-mode-card .campaign-mode-examples {
          list-style:none; padding:0; margin:0;
          font-size:12px; color:var(--text);
        }
        .campaign-mode-card .campaign-mode-examples li {
          padding:2px 0; display:flex; align-items:center; gap:6px;
        }
        .campaign-mode-card[data-mode="takeover"] .campaign-mode-examples li::before {
          content:'•'; color:var(--aqua);
        }
        .campaign-mode-card[data-mode="overlay"] .campaign-mode-examples li::before {
          content:'•'; color:var(--purple);
        }
        .campaign-mode-help {
          color:var(--aqua); cursor:pointer; font-weight:600;
        }
        .campaign-mode-help:hover { text-decoration:underline; }

        /* ── Campaigns list redesign ─────────────────────────────────
           Stats row + filter pills + status-striped data table + hover
           row actions. Built on the existing CMS chrome tokens — no
           --aqua / --bg redefinitions. */
        .cmp-stats {
          display:grid; grid-template-columns:repeat(5,1fr);
          gap:14px; margin-bottom:18px;
        }
        @media (max-width: 1100px) { .cmp-stats { grid-template-columns:repeat(2,1fr); } }
        .cmp-stat-card {
          background:var(--surface); border:1px solid var(--border);
          border-radius:10px; padding:14px 16px;
        }
        .cmp-stat-card .label {
          font-size:11px; font-weight:600; letter-spacing:1.2px;
          text-transform:uppercase; color:var(--text-dim);
          margin-bottom:8px;
        }
        .cmp-stat-card .value {
          font-size:24px; font-weight:700; color:var(--text-bright);
          letter-spacing:-.02em; line-height:1;
        }
        .cmp-stat-card .delta { font-size:11px; color:var(--text-dim); margin-top:6px; }
        .cmp-stat-card.hero {
          grid-column:span 2;
          background:linear-gradient(135deg, rgba(249,115,22,0.08), var(--surface));
          border-color:rgba(249,115,22,0.35);
          display:flex; align-items:center; gap:16px;
        }
        .cmp-stat-card.hero .meta { flex:1; }
        .cmp-stat-card.hero .meta .label { color:var(--orange); font-weight:700; }
        .cmp-stat-card.hero .meta .sub { font-size:12px; color:var(--text-dim); margin-top:4px; }
        .cmp-stat-card.hero .num {
          font-size:34px; font-weight:700; color:var(--orange); line-height:1;
          font-variant-numeric:tabular-nums;
        }
        .cmp-stat-card.hero.empty { background:var(--surface); border-color:var(--border); }
        .cmp-stat-card.hero.empty .num { color:var(--text-dim); font-size:26px; }
        .cmp-stat-card.hero.empty .meta .label { color:var(--text-dim); }
        .cmp-stat-card.hero .cta { padding:5px 11px; font-size:12px; }

        /* Filter pills (replaces status dropdown) */
        .cmp-pills {
          display:inline-flex; flex-wrap:wrap; gap:2px;
          padding:3px; background:var(--surface-2);
          border:1px solid var(--border); border-radius:8px;
        }
        .cmp-pill {
          padding:5px 11px; border-radius:6px;
          font-size:12px; font-weight:600;
          background:transparent; border:1px solid transparent;
          color:var(--text-dim); cursor:pointer; font-family:inherit;
          transition:all .15s; white-space:nowrap;
        }
        .cmp-pill:hover { color:var(--text); }
        .cmp-pill.active {
          background:var(--text-bright); color:var(--bg);
          font-weight:700;
        }
        .cmp-pill .count { opacity:.55; margin-left:5px; font-weight:600; }
        .cmp-pill.active .count { color:var(--bg); }

        /* Decorations on the existing .data-table when used for campaigns */
        .data-table.cmp-list td.stripe-cell {
          position:relative; padding-left:18px;
        }
        .data-table.cmp-list td.stripe-cell::before {
          content:''; position:absolute; left:0; top:0; bottom:0;
          width:3px; background:transparent;
        }
        .data-table.cmp-list tr.row-live      td.stripe-cell::before { background:var(--green); }
        .data-table.cmp-list tr.row-scheduled td.stripe-cell::before,
        .data-table.cmp-list tr.row-approved  td.stripe-cell::before { background:var(--blue); }
        .data-table.cmp-list tr.row-pending_review td.stripe-cell::before { background:var(--orange); }
        .data-table.cmp-list tr.row-paused    td.stripe-cell::before { background:#fb923c; }
        .data-table.cmp-list tr.row-draft     td.stripe-cell::before { background:var(--text-dim); opacity:.5; }
        .data-table.cmp-list tr.row-archived  td.stripe-cell::before,
        .data-table.cmp-list tr.row-ended     td.stripe-cell::before { background:var(--text-dim); opacity:.25; }

        /* Status dot beside campaign name */
        .cmp-dot {
          display:inline-block; width:9px; height:9px; border-radius:50%;
          flex-shrink:0; box-shadow:0 0 0 3px rgba(255,255,255,0.04);
          vertical-align:middle;
        }
        .cmp-dot.live      { background:var(--green); box-shadow:0 0 0 3px rgba(74,222,128,0.18), 0 0 8px rgba(74,222,128,0.4); }
        .cmp-dot.scheduled,
        .cmp-dot.approved  { background:var(--blue);  box-shadow:0 0 0 3px rgba(59,130,246,0.18); }
        .cmp-dot.pending_review { background:var(--orange); box-shadow:0 0 0 3px rgba(249,115,22,0.18); }
        .cmp-dot.paused    { background:#fb923c; box-shadow:0 0 0 3px rgba(251,146,60,0.18); }
        .cmp-dot.draft     { background:var(--text-dim); opacity:.5; }
        .cmp-dot.archived,
        .cmp-dot.ended     { background:var(--text-dim); opacity:.35; }

        /* Status badge pill */
        .cmp-badge {
          display:inline-flex; align-items:center; gap:5px;
          padding:3px 8px; border-radius:99px;
          font-size:10.5px; font-weight:600; letter-spacing:0.7px;
          text-transform:uppercase; border:1px solid transparent; white-space:nowrap;
        }
        .cmp-badge::before { content:''; width:5px; height:5px; border-radius:50%; background:currentColor; }
        .cmp-badge.live      { color:var(--green);  background:rgba(74,222,128,0.13);  border-color:rgba(74,222,128,0.28); }
        .cmp-badge.scheduled,
        .cmp-badge.approved  { color:var(--blue);   background:rgba(59,130,246,0.13);  border-color:rgba(59,130,246,0.28); }
        .cmp-badge.pending_review { color:var(--orange); background:rgba(249,115,22,0.13);  border-color:rgba(249,115,22,0.28); }
        .cmp-badge.draft, .cmp-badge.paused,
        .cmp-badge.archived, .cmp-badge.ended {
          color:var(--text-dim); background:var(--surface-2); border-color:var(--border);
        }

        .cmp-empty-cell { color:var(--text-dim); font-style:italic; font-size:12px; }

        /* Tooltip on campaign name (Updated by …) */
        .cmp-name-wrap { position:relative; display:inline-block; }
        .cmp-name-wrap:hover .cmp-tip { opacity:1; transform:translateY(0); pointer-events:auto; }
        .cmp-tip {
          position:absolute; bottom:calc(100% + 6px); left:0;
          background:var(--surface-3, #0e1419); color:var(--text-bright);
          border:1px solid var(--border); padding:5px 9px;
          border-radius:6px; font-size:11.5px; white-space:nowrap;
          font-style:normal; font-weight:500;
          opacity:0; transform:translateY(2px);
          transition:opacity .15s, transform .15s;
          pointer-events:none; z-index:50;
          box-shadow:0 8px 20px rgba(0,0,0,0.4);
        }

        /* Hover row actions */
        .cmp-row-actions {
          display:inline-flex; gap:2px; align-items:center; justify-content:flex-end;
          position:relative;
        }
        .cmp-row-actions .quick {
          opacity:0; transform:translateX(4px);
          transition:opacity .15s, transform .15s;
          display:inline-flex; gap:2px;
        }
        .data-table.cmp-list tbody tr:hover .cmp-row-actions .quick {
          opacity:1; transform:translateX(0);
        }
        .cmp-row-actions .overflow { opacity:.55; transition:opacity .15s; }
        .data-table.cmp-list tbody tr:hover .cmp-row-actions .overflow { opacity:1; }
        .cmp-action-btn {
          width:26px; height:26px;
          display:inline-flex; align-items:center; justify-content:center;
          background:transparent; border:1px solid transparent;
          color:var(--text-dim); cursor:pointer;
          border-radius:5px; font-size:11.5px;
          font-family:inherit; transition:all .15s;
        }
        .cmp-action-btn:hover {
          background:var(--surface-2); color:var(--text-bright); border-color:var(--border);
        }
        .cmp-action-btn.danger:hover {
          color:var(--red); border-color:rgba(239,68,68,0.4); background:rgba(239,68,68,0.08);
        }

        /* Overflow ⋯ popover */
        .cmp-overflow-menu {
          position:absolute; right:0; top:calc(100% + 4px);
          background:var(--surface); border:1px solid var(--border);
          border-radius:8px; padding:4px; min-width:180px;
          z-index:100; box-shadow:0 12px 28px rgba(0,0,0,0.5);
        }
        .cmp-overflow-menu button {
          display:flex; align-items:center; gap:8px;
          width:100%; background:transparent; border:none;
          color:var(--text); padding:7px 10px; border-radius:6px;
          font-size:12.5px; cursor:pointer; font-family:inherit; text-align:left;
        }
        .cmp-overflow-menu button:hover { background:var(--surface-2); color:var(--text-bright); }
        .cmp-overflow-menu button.danger { color:var(--red); }
        .cmp-overflow-menu button.danger:hover { background:rgba(239,68,68,0.08); }
        .cmp-overflow-menu .sep { height:1px; background:var(--border); margin:4px 0; }

        /* ── Approval drawer ─────────────────────────────────────────
           Slides in from the right when a reviewer clicks an in-review
           campaign in the list. Replaces the previous behaviour of
           opening the full editor for review decisions. */
        .cmp-drawer-overlay {
          position:fixed; inset:0; display:none; z-index:200;
        }
        .cmp-drawer-overlay.active { display:block; }
        .cmp-drawer-backdrop {
          position:absolute; inset:0;
          background:rgba(0,0,0,0.4);
          backdrop-filter:blur(2px);
          -webkit-backdrop-filter:blur(2px);
          animation:cmpDrawerFade .15s ease-out;
        }
        @keyframes cmpDrawerFade { from {opacity:0} to {opacity:1} }
        @keyframes cmpDrawerSlide { from {transform:translateX(100%)} to {transform:translateX(0)} }
        .cmp-drawer {
          position:absolute; right:0; top:0; bottom:0;
          width:460px; max-width:100vw;
          background:var(--surface);
          border-left:1px solid var(--border);
          display:flex; flex-direction:column;
          box-shadow:-10px 0 40px rgba(0,0,0,0.5);
          animation:cmpDrawerSlide .2s ease-out;
        }
        .cmp-drawer-header {
          padding:18px 22px; border-bottom:1px solid var(--border);
          display:flex; align-items:flex-start; justify-content:space-between; gap:12px;
        }
        .cmp-drawer-eyebrow {
          font-size:11px; font-weight:600; letter-spacing:1.2px;
          text-transform:uppercase; color:var(--text-dim);
          margin-bottom:3px;
        }
        .cmp-drawer-header h2 {
          font-size:15px; font-weight:600; color:var(--text-bright);
          line-height:1.3;
        }
        .cmp-drawer-tabs {
          display:flex; gap:0;
          border-bottom:1px solid var(--border);
          padding:0 22px;
        }
        .cmp-drawer-tab {
          padding:11px 14px; font-size:13px; font-weight:600;
          color:var(--text-dim); cursor:pointer;
          border:none; background:transparent;
          border-bottom:2px solid transparent;
          margin-bottom:-1px; font-family:inherit;
          transition:color .15s, border-color .15s;
        }
        .cmp-drawer-tab:hover { color:var(--text); }
        .cmp-drawer-tab.active { color:var(--aqua); border-bottom-color:var(--aqua); }
        .cmp-drawer-body { flex:1; overflow-y:auto; padding:22px; }
        .cmp-drawer-footer {
          padding:14px 22px; border-top:1px solid var(--border);
          display:flex; gap:8px; align-items:center;
        }
        .cmp-summary-row {
          display:flex; padding:8px 0;
          border-bottom:1px solid var(--border); font-size:13px;
        }
        .cmp-summary-row:last-child { border-bottom:none; }
        .cmp-summary-row .lbl {
          width:90px; color:var(--text-dim);
          text-transform:uppercase; letter-spacing:.8px;
          font-size:10.5px; font-weight:600; padding-top:3px;
        }
        .cmp-summary-row .val { flex:1; color:var(--text); }
        .cmp-avatar-card {
          display:flex; align-items:center; gap:10px;
          padding:12px; background:var(--surface-2);
          border:1px solid var(--border);
          border-radius:8px; margin-bottom:18px;
        }
        .cmp-avatar {
          width:34px; height:34px; border-radius:50%;
          background:var(--surface-3, #2a3038);
          display:inline-flex; align-items:center; justify-content:center;
          font-size:12px; font-weight:700; color:var(--text-bright);
          flex-shrink:0;
        }
        .cmp-tab-stub {
          text-align:center; padding:40px 20px; color:var(--text-dim);
        }
        .cmp-tab-stub .icon {
          font-size:32px; opacity:0.4; margin-bottom:10px; display:block;
        }
        .cmp-tab-stub h3 { color:var(--text-bright); font-size:14px; margin-bottom:6px; }
        .cmp-tab-stub p { font-size:12.5px; line-height:1.5; max-width:280px; margin:0 auto; }

        /* ── Split "+ New campaign" button on the list header ──────
           Three segments — Takeover / Overlay / ▾ — sharing one pill
           border. The first two skip the mode-picker modal and call
           createCampaignWithMode() directly; ▾ opens the modal. */
        .cmp-split-btn {
          display:inline-flex; border-radius:8px; overflow:hidden;
          border:1px solid var(--brand-primary);
          background:var(--brand-primary);
        }
        .cmp-split-btn button {
          background:transparent; border:none;
          color:var(--brand-primary-ink); font-weight:600;
          font-size:13px; padding:8px 14px;
          cursor:pointer; font-family:inherit;
          display:inline-flex; align-items:center; gap:5px;
          transition:background .15s;
        }
        .cmp-split-btn button:hover { background:rgba(0,0,0,0.12); }
        .cmp-split-btn .divider { width:1px; background:rgba(0,0,0,0.2); flex-shrink:0; }
        .cmp-split-btn .more { padding:8px 10px; }

        /* ── Loading skeleton (shimmer placeholders for the list) ── */
        @keyframes cmpShimmer {
          0%   { background-position: -400px 0; }
          100% { background-position:  400px 0; }
        }
        .cmp-skel {
          display:inline-block;
          background:linear-gradient(90deg,
            var(--surface-2) 0%,
            color-mix(in srgb, var(--surface-2) 50%, var(--surface-3) 50%) 50%,
            var(--surface-2) 100%);
          background-size:800px 100%;
          border-radius:4px;
          height:12px; width:100%;
          animation:cmpShimmer 1.4s linear infinite;
          vertical-align:middle;
        }

        /* ── Live performance view ────────────────────────────────
           Read-only screen reached by clicking a Live row in the list.
           Real data: name, status, dates, creatives (variant split via
           weight), targets. Placeholder: impressions, CTR, engagements,
           per-screen perf — these need an analytics layer that isn't
           shipped yet. Placeholders are clearly labelled rather than
           mocked, so the screen tells the truth about what's measured. */
        .cmp-perf-header {
          display:flex; align-items:flex-start; justify-content:space-between;
          margin-bottom:18px; gap:16px; flex-wrap:wrap;
        }
        .cmp-perf-header .crumb {
          color:var(--text-dim); font-size:13px; font-weight:500; margin-bottom:4px;
        }
        .cmp-perf-header .crumb a { color:var(--text-dim); cursor:pointer; }
        .cmp-perf-header .crumb a:hover { color:var(--text); }
        .cmp-perf-header .crumb .sep { opacity:.5; margin:0 8px; }
        .cmp-perf-header h1 {
          display:flex; align-items:center; gap:10px;
          font-size:22px; font-weight:700; color:var(--text-bright);
          margin:0;
        }
        .cmp-perf-actions { display:flex; gap:8px; align-items:center; }
        .cmp-perf-toolbar {
          display:flex; align-items:center; gap:14px;
          margin-bottom:18px; flex-wrap:wrap;
        }
        .cmp-perf-grid {
          display:grid; grid-template-columns:2fr 1fr; gap:18px;
          margin-bottom:18px;
        }
        @media (max-width: 1100px) { .cmp-perf-grid { grid-template-columns:1fr; } }
        .cmp-perf-panel {
          background:var(--surface); border:1px solid var(--border);
          border-radius:10px; overflow:hidden;
        }
        .cmp-perf-panel-header {
          padding:14px 18px;
          border-bottom:1px solid var(--border);
          display:flex; align-items:center; justify-content:space-between;
          gap:10px;
        }
        .cmp-perf-panel-header h2 {
          font-size:14px; font-weight:600; color:var(--text-bright);
          margin:0;
        }
        .cmp-perf-panel-body { padding:18px 22px; }
        .cmp-chart-placeholder {
          height:200px; display:flex;
          align-items:center; justify-content:center;
          flex-direction:column; gap:8px;
          background:linear-gradient(180deg, transparent, rgba(255,255,255,0.02));
          border:1px dashed var(--border);
          border-radius:8px;
          color:var(--text-dim); font-size:13px; text-align:center;
          padding:0 24px; line-height:1.5;
        }
        .cmp-chart-placeholder .icon { font-size:24px; opacity:.4; }
        .cmp-variant-bar { margin-bottom:14px; }
        .cmp-variant-bar:last-of-type { margin-bottom:0; }
        .cmp-variant-bar-head {
          display:flex; justify-content:space-between; align-items:center;
          font-size:12.5px; margin-bottom:6px; color:var(--text);
        }
        .cmp-variant-bar-head .label { font-weight:600; display:flex; align-items:center; gap:6px; }
        .cmp-variant-bar-head .winner-tag {
          font-size:9px; padding:1px 5px;
          background:var(--aqua-glow); color:var(--aqua);
          border-radius:99px; font-weight:700; letter-spacing:.5px;
        }
        .cmp-variant-bar-head .ctr {
          color:var(--text-dim); font-size:12px;
        }
        .cmp-variant-bar-track {
          height:8px; background:var(--surface-2);
          border-radius:99px; overflow:hidden;
        }
        .cmp-variant-bar-fill {
          height:100%; border-radius:99px; transition:width .5s;
        }
        .cmp-variant-bar-meta {
          font-size:11px; color:var(--text-dim); margin-top:4px;
        }
        .cmp-perf-stub-note {
          font-size:11.5px; color:var(--text-dim);
          padding:8px 12px; margin-top:10px;
          background:var(--surface-2);
          border:1px solid var(--border);
          border-radius:6px; line-height:1.5;
        }

        /* ── Targeting checklist ─────────────────────────────────── */
        .ce-target-search {
          width:100%; padding:6px 10px; font-size:12px;
          background:var(--bg-deep); color:var(--text);
          border:1px solid var(--border); border-radius:6px;
          margin-bottom:6px;
        }
        .ce-target-quick {
          display:flex; gap:4px; flex-wrap:wrap; margin-bottom:6px;
        }
        .ce-target-quick button {
          font-size:10px; padding:3px 8px; border-radius:99px;
          background:rgba(255,255,255,0.04); color:var(--text-dim);
          border:1px solid var(--border); cursor:pointer;
        }
        .ce-target-quick button:hover { background:rgba(255,255,255,0.08); color:var(--text-bright); }
        .ce-target-list {
          max-height:260px; overflow-y:auto;
          border:1px solid var(--border); border-radius:6px;
          background:var(--bg-deep); padding:4px 0;
        }
        .ce-target-list .ce-target-group {
          padding:6px 10px 2px; font-size:10px; text-transform:uppercase;
          letter-spacing:1px; color:var(--text-dim); font-weight:600;
          background:rgba(255,255,255,0.02);
        }
        .ce-target-list label.ce-target-opt {
          display:flex; align-items:center; gap:8px;
          padding:6px 12px; cursor:pointer; font-size:12px;
          color:var(--text);
        }
        .ce-target-list label.ce-target-opt:hover { background:rgba(241, 245, 249,0.08); }
        .ce-target-list label.ce-target-opt.already {
          opacity:0.45; cursor:default;
        }
        .ce-target-list label.ce-target-opt input {
          accent-color:var(--aqua,#f1f5f9); width:14px; height:14px;
        }
        .ce-target-list .ce-target-code {
          font-variant-numeric:tabular-nums; font-size:10px; color:var(--text-dim); margin-left:auto;
        }
        .ce-target-list .ce-target-empty {
          padding:12px; text-align:center; color:var(--text-dim); font-size:11px;
        }

        .ce-creative-tabs { padding:4px 16px 8px; display:flex; flex-wrap:wrap; gap:6px; }
        .ce-creative-tab {
          padding:6px 10px 6px 12px; border-radius:99px; border:1px solid var(--border);
          background:var(--bg-deep); font-size:11px; cursor:pointer; display:inline-flex;
          align-items:center; gap:6px; color:var(--text-dim); transition:all .12s;
        }
        .ce-creative-tab:hover { color:var(--text-bright); border-color:var(--aqua); }
        .ce-creative-tab.active { background:var(--aqua); color:#001a3d; border-color:var(--aqua); }
        .ce-creative-tab .ce-tab-x { opacity:0.5; cursor:pointer; padding:0 2px; }
        .ce-creative-tab .ce-tab-x:hover { opacity:1; color:#ef4444; }
        .ce-creative-tab.active .ce-tab-x { color:#001a3d; }

        /* v1 design: A/B variants bar — chips with weight % + winner
           badge if analytics are available. The bar lives above the
           creative-tabs row and labels the section as "A/B". */
        .ce-variants-bar {
          display:flex; align-items:center; gap:10px;
          padding:8px 16px; border-bottom:1px solid var(--border);
          background:rgba(255,255,255,0.02);
          font-size:12px; flex-wrap:wrap;
        }
        /* Phase 58e: when the campaign has no extra creatives /
           variants the bar renders empty — its padding + border-
           bottom + slightly-lighter bg created a visible strip
           above the Full screen / Overlay segmented control with
           no content in it. Collapse the bar when empty. */
        .ce-variants-bar:empty {
          padding: 0;
          border: 0;
          background: transparent;
        }
        .ce-variants-bar .vb-label {
          font-size:10.5px; font-weight:700; letter-spacing:.7px;
          text-transform:uppercase; color:var(--text-dim);
        }
        .ce-creative-tab .vb-weight {
          opacity:.55; font-weight:500;
          padding-left:4px; border-left:1px solid currentColor;
          margin-left:2px;
        }
        .ce-creative-tab .vb-winner {
          font-size:9px; padding:1px 5px;
          background:#22c55e; color:#062c14;
          border-radius:99px; font-weight:700;
          letter-spacing:.4px; margin-left:4px;
        }
        .ce-creative-tab.active .vb-winner { background:#86efac; color:#062c14; }
        .ce-variants-bar .vb-add {
          padding:4px 9px; border-radius:99px;
          background:transparent; border:1px dashed var(--border);
          color:var(--text-dim); font-size:11px;
          cursor:pointer; font-family:inherit;
        }
        .ce-variants-bar .vb-add:hover { color:var(--text); border-color:var(--text-dim); }
        .ce-variants-bar .vb-status {
          margin-left:auto; font-size:11px; color:var(--text-dim);
          font-style:italic;
        }

        /* Canvas frame wrapper — transparent so the parent .ce-center
           lighter-blue surface shows through. Previously had a dark
           gridded backdrop which made the wrapper read as a separate
           darker pane inside the canvas column ("two blues"). */
        .ce-preview-frame-wrapper.ce-bezel-standard {
          background: transparent;
          position: relative;
        }
        /* Phase 54a: single-column picker so each thumbnail gets the
           full sidebar width (~240–250px) instead of a cramped half.
           Matches Canva-style template pickers where every preview
           has room to show the composition + real content at a
           readable scale. */
        .ce-layout-picker { display:grid; grid-template-columns:1fr; gap:8px; padding:2px 12px 8px; }
        .ce-left-mode { display:none; }
        body[data-ce-panel="takeover"] .ce-left-mode[data-left-mode="templates"],
        body[data-ce-panel="overlay"] .ce-left-mode[data-left-mode="templates"],
        body[data-ce-panel="elements"] .ce-left-mode[data-left-mode="elements"],
        body[data-ce-panel="text"] .ce-left-mode[data-left-mode="text"],
        body[data-ce-panel="uploads"] .ce-left-mode[data-left-mode="uploads"],
        body[data-ce-panel="background"] .ce-left-mode[data-left-mode="background"],
        /* Phase 58e: Canvas merged into Background — any "canvas"
           panel request resolves to the Background pane. */
        body[data-ce-panel="canvas"] .ce-left-mode[data-left-mode="background"],
        body[data-ce-panel="brand"] .ce-left-mode[data-left-mode="brand"],
        body[data-ce-panel="layers"] .ce-left-mode[data-left-mode="layers"],
        body[data-ce-panel="live"]   .ce-left-mode[data-left-mode="live"],
        /* Phase 58e: Schedule + Targets render in the LEFT panel
           because the right-inspector column is hidden in v0. The
           panes themselves live in a hidden .ce-right wrapper for
           legacy reasons; ceRelocateSchedTargetsToLeft() moves them
           into the matching .ce-left-mode containers at editor
           enter. The CSS just makes them visible when their rail
           button is the active panel. */
        body[data-ce-panel="schedule"] .ce-left-mode[data-left-mode="schedule"],
        body[data-ce-panel="targets"]  .ce-left-mode[data-left-mode="targets"] {
          display:block;
        }
        /* Schedule + Targets panes have their own padding / layout
           inside the .ce-right context. When relocated they need a
           reasonable inset so the content doesn't sit flush against
           the left panel edge. */
        .ce-left-mode[data-left-mode="schedule"] > *,
        .ce-left-mode[data-left-mode="targets"]  > * {
          padding: 12px 14px;
        }
        /* Layers list — Photoshop-style row per slot in the active
           creative's layout. Click a row to focus the matching field
           in the right inspector. */
        .ce-layers-list { padding: 6px 12px 12px; display:flex; flex-direction:column; gap:2px; }
        .ce-layer {
          display:flex; align-items:center; gap:10px;
          padding:7px 10px; border-radius:6px;
          font-size:12.5px; color:var(--text);
          cursor:pointer; border:1px solid transparent;
          transition: background .12s, border-color .12s;
        }
        .ce-layer:hover { background: rgba(255,255,255,0.04); border-color: var(--border); }
        .ce-layer.active {
          background: var(--aqua-glow); color: var(--aqua);
          border-color: var(--border-hover);
        }
        .ce-layer .ico {
          width:18px; height:18px;
          display:inline-flex; align-items:center; justify-content:center;
          font-size:11px; font-weight:700;
          background: var(--surface-2); border:1px solid var(--border);
          border-radius:4px; color: var(--text-dim);
          flex-shrink:0;
        }
        .ce-layer.active .ico { background: var(--aqua-glow); color: var(--aqua); border-color: var(--border-hover); }
        .ce-layer .name { flex:1; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
        .ce-layer .preview {
          font-size:10.5px; color:var(--text-dim);
          max-width:120px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
          font-style:italic;
        }
        .ce-layer .vis {
          opacity:0; font-size:11px; color:var(--text-dim);
          transition: opacity .12s;
        }
        .ce-layer:hover .vis, .ce-layer.active .vis { opacity:.7; }
        .ce-layers-empty {
          padding:14px 12px; text-align:center;
          color:var(--text-dim); font-size:12px; line-height:1.5;
        }

        /* AI write helper — ✨ button glued to the top-right of every
           text input/textarea in the right inspector. Clicking opens a
           tiny suggestion panel with three alternatives. Replace the
           hardcoded suggestions with a real /ai/suggest call when that
           endpoint exists. */
        .ce-ai-input-wrap { position: relative; }
        .ce-ai-btn {
          position: absolute; top: 4px; right: 4px;
          width: 24px; height: 24px; padding: 0;
          border: 1px solid rgba(167,139,250,.4);
          background: linear-gradient(135deg, #a78bfa, #7c3aed);
          border-radius: 5px; color: #fff; font-size: 11px;
          cursor: pointer; z-index: 5;
          display: inline-flex; align-items: center; justify-content: center;
          opacity: .82; transition: opacity .15s, transform .12s;
        }
        .ce-ai-btn:hover { opacity: 1; transform: scale(1.06); }
        .ce-ai-suggest-panel {
          position: absolute; top: calc(100% + 4px); right: 0;
          width: 260px; z-index: 200;
          background: linear-gradient(135deg, rgba(167,139,250,0.14), rgba(241,245,249,0.04));
          border: 1px solid rgba(167,139,250,0.32);
          border-radius: 8px; padding: 10px;
          box-shadow: 0 12px 28px rgba(0,0,0,0.5);
        }
        .ce-ai-suggest-panel .h {
          border: 1px solid rgba(251, 191, 36, 0.3);
          border-radius: 6px; color: #fbbf24;
          font-size: 11.5px; line-height: 1.4;
          width: 100%; text-align: left; cursor: pointer;
          font-family: inherit;
        }
        .ce-perf-warning:hover { background: rgba(251, 191, 36, 0.18); }
        .ce-left-mode-heading {
          display:flex; align-items:center; justify-content:space-between;
        }
        .ce-left-panel-card {
          /* Sarah feedback: "in Live the content is on a box, which
             looks good styling, can you use the same styling for the
             boxes in brand, background and uploads". Unified with
             .ce-perf-section so all four panels share one visual
             treatment — 8px radius, var(--border) hairline, faint
             surface tint. */
          margin: 12px 16px; padding: 12px;
          border: 1px solid var(--border); border-radius: 8px;
          background: rgba(255,255,255,0.02);
        }
        .ce-left-panel-card h4 {
          margin:0 0 4px; font-size:13px; color:var(--text-bright);
        }
        .ce-left-panel-card p {
          margin:0 0 10px; font-size:11px; line-height:1.45; color:var(--text-dim);
        }

        /* Phase 58/58a: rail mode — takeover + overlay show the layout
           picker only; content shows copy/slots only. Schedule + targets
           hide .ce-left and use .ce-right. */
        body[data-ce-panel="takeover"] .ce-section-body[data-section="content"],
        body[data-ce-panel="takeover"] .ce-section-title[data-section="content"],
        body[data-ce-panel="overlay"]  .ce-section-body[data-section="content"],
        body[data-ce-panel="overlay"]  .ce-section-title[data-section="content"] {
          display: none !important;
        }
        /* Phase 58e: Schedule + Targets render INSIDE the left panel
           via the .ce-left-mode mechanism (the panes are relocated
           there at editor enter from the hidden .ce-right wrapper).
           So the left column stays visible — no special grid override
           needed. The pre-58e rules that hid .ce-left and reserved a
           280px right column have been retired because the right
           inspector column was already hidden globally, leaving the
           sidebar blank in schedule/targets mode. */
        /* Tighten the creatives/section stack in the left column. */
        .ce-section-title { margin-top: 10px; }
        .ce-creative-tabs { padding: 4px 12px; }

        /* ── Phase 53b: real-render layout thumbnails (Canva-style) ──
           Renders the live cp-slide + cp-overlay markup inside a
           16:9 shell, then overrides vw-based text sizes with
           explicit px values tuned for thumb scale. Every rule is
           scoped to .ce-thumb-live with !important so it only
           affects the picker — the kiosk + main preview keep their
           real vw-based sizing.

           The big idea: the layout's COMPOSITION (where title/CTA/
           QR/cards/progress bar sit) is what makes one layout
           visually distinct from another. Text content is
           secondary. Forcing readable text at thumb scale lets the
           composition shine through. */
        .ce-thumb-live {
          /* 16:9 card with sharp edges, true mini-canvas. The inner
             renders at full 1920×1080 production size and is CSS-
             scaled down via transform: scale(...) computed from
             container-query units, so every layout looks identical
             to what it'll be on the kiosk — text, spacing, padding,
             everything — just smaller. */
          position: relative;
          width: 100%;
          aspect-ratio: 16 / 9;
          border-radius: 0;
          overflow: hidden;
          background: #06090f;
          border: 1px solid rgba(120, 200, 255, 0.12);
          transition: border-color .15s ease, box-shadow .15s ease;
          container-type: inline-size;
        }
        .ce-layout-card:hover .ce-thumb-live {
          border-color: rgba(241, 245, 249, 0.55);
        }
        .ce-layout-card.selected .ce-thumb-live {
          border-color: rgba(241, 245, 249, 0.85);
          box-shadow: 0 0 0 2px rgba(241, 245, 249, 0.3);
        }
        .ce-thumb-live-inner {
          position: absolute;
          top: 0; left: 0;
          width: 1920px;
          height: 1080px;
          /* 100cqw = card width; 100cqw / 1920px = unitless scale ratio. */
          transform: scale(calc(100cqw / 1920px));
          transform-origin: top left;
        }
        /* Overlay-mode backdrop — a mocked kiosk species card sits
           below the cp-overlay markup so the curator sees the overlay
           anchored against a real species-page composition (cut-out
           photo + name + scientific name + accent stripe + chips),
           matching what the visitor will see in production. */
        .ce-thumb-overlay-bg-fallback {
          position: absolute; inset: 0; z-index: 0;
          background:
            radial-gradient(ellipse at 30% 30%, rgba(45,212,191,0.32), transparent 55%),
            radial-gradient(ellipse at 75% 70%, rgba(59,130,246,0.28), transparent 60%),
            linear-gradient(135deg, #02101f 0%, #061a2b 60%, #02060f 100%);
        }
        .ce-thumb-live-inner.ce-thumb-overlay-mode > .cp-overlay,
        .ce-thumb-popup-inner.ce-thumb-overlay-mode > .cp-overlay {
          position: absolute;
          z-index: 2;
        }
        /* Real kiosk preview iframe sized to 1920×1080 inside the
           thumb's inner box (which is itself transform-scaled to fit
           the card). pointer-events:none so clicks hit the overlay
           markup on top, not the iframe. */
        .ce-thumb-kiosk-iframe {
          position: absolute; inset: 0; z-index: 0;
          width: 1920px; height: 1080px;
          border: 0;
          /* Subtle aqua gradient backdrop so the thumb has visible content
             before the iframe finishes its first paint. Once the kiosk
             page loads it covers this placeholder completely. */
          background:
            radial-gradient(ellipse at 30% 30%, rgba(45,212,191,0.18), transparent 55%),
            radial-gradient(ellipse at 75% 70%, rgba(59,130,246,0.18), transparent 60%),
            linear-gradient(135deg, #02101f 0%, #06182b 60%, #020912 100%);
          pointer-events: none;
        }
        /* Static species-card mock used as the picker thumb backdrop —
           cheap to render, never blocks on iframe loads. Sized to
           match the 1920×1080 inner so the parent transform-scale
           shrinks it correctly per thumb. */
        .ce-thumb-species-card {
          position: absolute; inset: 0; z-index: 0;
          display: flex;
          background:
            radial-gradient(ellipse at 12% 25%, rgba(45,212,191,0.18), transparent 55%),
            radial-gradient(ellipse at 80% 85%, rgba(59,130,246,0.22), transparent 60%),
            linear-gradient(135deg, #02101f 0%, #06182b 60%, #020912 100%);
          overflow: hidden;
        }
        .ce-thumb-species-card .ce-tsc-stripe {
          position: absolute; left: 0; top: 0; bottom: 0;
          width: 8px;
          opacity: 0.95;
        }
        .ce-thumb-species-card .ce-tsc-text {
          position: relative; z-index: 1;
          flex: 1;
          padding: 100px 80px;
          display: flex; flex-direction: column; gap: 20px;
          color: #fff;
          font-family: 'Inter', system-ui, sans-serif;
        }
        .ce-thumb-species-card .ce-tsc-eyebrow {
          font-size: 22px; font-weight: 900; letter-spacing: 4px;
          color: var(--cp-accent, #2dd4bf);
          text-transform: uppercase;
        }
        .ce-thumb-species-card .ce-tsc-name {
          font-size: 168px; font-weight: 900;
          line-height: 0.92; letter-spacing: -3px;
          color: #ffffff;
        }
        .ce-thumb-species-card .ce-tsc-sci {
          font-size: 44px; font-weight: 500; font-style: italic;
          color: rgba(255,255,255,0.66);
        }
        .ce-thumb-species-card .ce-tsc-chips {
          display: flex; gap: 12px; margin-top: 12px;
        }
        .ce-thumb-species-card .ce-tsc-chip {
          font-size: 22px; font-weight: 700; letter-spacing: 1px;
          padding: 12px 24px; border-radius: 999px;
          background: rgba(255,255,255,0.08);
          border: 1px solid rgba(255,255,255,0.16);
          color: rgba(255,255,255,0.85);
        }
        .ce-thumb-species-card .ce-tsc-photo {
          position: absolute; right: -120px; bottom: -60px;
          width: 60%; height: 110%;
          object-fit: contain; object-position: right bottom;
          filter: drop-shadow(0 24px 60px rgba(0,0,0,0.55));
          z-index: 0;
          opacity: 0.96;
        }
        .ce-thumb-overlay-bg-fallback {
          position: absolute; inset: 0; z-index: 0;
          background:
            radial-gradient(ellipse at 30% 30%, rgba(45,212,191,0.32), transparent 55%),
            radial-gradient(ellipse at 75% 70%, rgba(59,130,246,0.28), transparent 60%),
            linear-gradient(135deg, #02101f 0%, #061a2b 60%, #02060f 100%);
        }
        .ce-thumb-live-inner.ce-thumb-overlay-mode > .cp-overlay {
          position: absolute;
          z-index: 2;
        }
        .ce-layout-group-label {
          grid-column:1/-1; padding:8px 2px 2px; font-size:9px; text-transform:uppercase;
          letter-spacing:1.4px; color:var(--text-dim); opacity:0.7;
        }
        /* When an overlay layout is selected, the preview hosts a real
           species page (via /display/__preview__) in an iframe and renders
           the overlay creative on a layer that sits on top of it. The
           iframe fills the frame; the overlay layer is absolute-positioned
           inside the frame so the overlay renderer's position classes
           (top-left, bottom, etc) anchor to the preview, not the viewport. */
        .ce-preview-frame.ce-preview-overlay { background:#06090f; }

        /* ── Phase 42/43: drag-and-drop overlay placement ─────────────
           One silhouette per allowed position for the layout being
           dragged. Each silhouette is the real overlay markup, sized +
           positioned by the kiosk's placement engine — so the curator
           sees the EXACT footprint the overlay will occupy. The
           container is just an absolute layer that lets the
           silhouettes catch drag/drop events; positioning is on the
           silhouettes themselves via inline style from applyPlacement. */
        .ce-overlay-drop-zones {
          position: absolute; inset: 0;
          display: none;
          z-index: 50;
          pointer-events: none;
        }
        .ce-overlay-drop-zones.is-active { display: block; }
        /* Silhouette wrapper — fills the area its child overlay
           occupies. The child .cp-overlay is the rendered ghost; the
           wrapper sits at the same coordinates so drag events on the
           wrapper feel like they're on the overlay itself. */
        .ce-overlay-target {
          position: absolute; inset: 0;
          pointer-events: none;
        }
        .ce-overlay-target .cp-overlay {
          pointer-events: auto;
          opacity: 0.45;
          outline: 2px dashed rgba(241, 245, 249, 0.55);
          outline-offset: 2px;
          transition: opacity .15s ease, outline-color .15s ease,
                      transform .15s ease, filter .15s ease;
          cursor: copy;
        }
        .ce-overlay-target.is-hover .cp-overlay {
          opacity: 0.95;
          outline: 2px solid rgba(241, 245, 249, 1);
          outline-offset: 3px;
          filter: drop-shadow(0 4px 18px rgba(241, 245, 249, 0.45));
          transform: scale(1.03);
          z-index: 2;
        }
        /* Subtle "drop here" label that fades in over the hovered
           silhouette so the curator knows what they're committing to. */
        .ce-overlay-target .cp-overlay::after {
          content: attr(data-cp-label);
          position: absolute; inset: auto 8px 8px auto;
          font-size: 9px; font-weight: 700; letter-spacing: 1.4px;
          text-transform: uppercase;
          color: rgba(241, 245, 249, 0.95);
          background: rgba(0, 0, 0, 0.55);
          padding: 3px 6px; border-radius: 4px;
          opacity: 0; transition: opacity .15s ease;
          pointer-events: none;
        }
        .ce-overlay-target.is-hover .cp-overlay::after { opacity: 1; }
        /* Frame is "armed" while a drag is in progress — adds a gentle
           cyan ring so the curator knows the drop is targeting here. */
        .ce-preview-frame.ce-preview-drop-armed {
          box-shadow: 0 0 0 2px rgba(241, 245, 249,0.45),
                      0 0 28px rgba(241, 245, 249,0.18);
        }
        /* The species iframe normally accepts clicks (so the curator can
           tap species tabs etc.). While a drag is in progress we disable
           its pointer-events so dragover/drop bubble through to the
           drop zones above. Restored when the drag ends. */
        .ce-preview-frame.ce-preview-drop-armed .ce-preview-species-iframe {
          pointer-events: none;
        }
        /* Layout-card drag affordances */
        .ce-layout-card.ce-layout-card-draggable { cursor: grab; }
        .ce-layout-card.ce-layout-card-draggable:active { cursor: grabbing; }
        .ce-layout-drag-hint {
          display: inline-flex; align-items: center; gap: 4px;
          margin-left: 6px;
          font-size: 9px; color: rgba(190, 220, 235, 0.55);
        }
        /* Tiny on-brand pill the cursor carries while dragging an
           overlay card. Off-screen at create-time; the browser
           snapshots it for the drag image then we remove it. */
        .ce-overlay-drag-ghost {
          display: inline-flex; align-items: center; gap: 8px;
          padding: 8px 14px;
          background: linear-gradient(135deg, rgba(241, 245, 249,0.98), rgba(0,140,170,0.98));
          color: #001a3d;
          font-family: var(--aqos-ff-sans);
          font-size: 13px; font-weight: 600; letter-spacing: 0.02em;
          border-radius: 999px;
          box-shadow: 0 8px 24px rgba(0,0,0,0.35),
                      0 0 0 1px rgba(255,255,255,0.18) inset;
          white-space: nowrap;
          pointer-events: none;
        }
        .ce-overlay-drag-ghost i { font-size: 11px; opacity: 0.85; }
        /* Replacement for the position dropdown — read-only chip
           showing the current anchor + a hint to use drag-to-reposition. */
        .ce-position-chip {
          display: inline-flex; align-items: center; gap: 8px;
          padding:0; min-height:0; overflow:hidden;
        }

        /* Single bottom-right control bubble — device, pause, guides, zoom.
           The left-side species chip is hidden (see .ce-preview-context-chip
           rule below) so the bar reads as one floating dock pinned right. */
        .ce-preview-bottom-bar {
          position: absolute;
          bottom: 18px;
          right: 16px;
          z-index: 45;
          display: flex;
          align-items: center;
          justify-content: flex-end;
          gap: 12px;
          pointer-events: none;
        }
        .ce-preview-bottom-bar > * {
          pointer-events: auto;
        }
        .ce-preview-bottom-bar .ce-preview-context-chip { display: none; }
        .ce-preview-context-chip {
          display: flex;
          align-items: center;
          flex: 0 1 auto;
          min-width: 0;
        }
        .ce-preview-species-chip {
          display: inline-flex; align-items: center; gap: 8px;
          padding: 5px 10px 5px 12px;
          font-size: 11px; color: var(--text-dim);
          background: rgba(12, 18, 28, 0.7);
          backdrop-filter: blur(12px);
          -webkit-backdrop-filter: blur(12px);
          border: 1px solid rgba(255, 255, 255, 0.08);
          border-radius: 999px;
        }
        .ce-preview-species-chip > i { font-size: 10px; color: var(--aqua); }
        .ce-preview-species-prefix {
          text-transform: uppercase;
          letter-spacing: 1.4px;
          font-weight: 600;
          font-size: 9px;
          opacity: 0.7;
        }
        .ce-preview-species-chip > #cePreviewSpeciesName {
          color: var(--text-bright);
          font-weight: 500;
          max-width: 140px;
          white-space: nowrap;
          overflow: hidden;
          text-overflow: ellipsis;
        }
        .ce-preview-species-swap {
          background: transparent;
          border: 0;
          color: var(--text-dim);
          cursor: pointer;
          padding: 2px 4px;
          border-radius: 999px;
          font-size: 10px;
          transition: color .15s ease, background .15s ease;
        }
        .ce-preview-species-swap:hover {
          color: var(--text-bright);
          background: rgba(241, 245, 249, 0.12);
        }

        /* Phase 58e: control dock — controls on the lower right, NOT
           wrapped in a single pill. Each control (or tightly-related
           group) carries its own subtle dark backdrop so they read
           as floating chips on any canvas colour. The zoom cluster
           stays grouped because - 100% + Fit is one coherent unit. */
        .ce-preview-dock {
          display: flex;
          align-items: center;
          flex-shrink: 0;
          gap: 6px;
          padding: 0;
          background: transparent;
          border: 0;
          border-radius: 0;
          box-shadow: none;
          backdrop-filter: none;
          -webkit-backdrop-filter: none;
        }
        .ce-preview-dock-group {
          display: flex; align-items: center;
          gap: 2px;
          padding: 3px;
          background: rgba(12, 18, 28, 0.82);
          backdrop-filter: blur(12px);
          -webkit-backdrop-filter: blur(12px);
          border: 1px solid rgba(255, 255, 255, 0.08);
          border-radius: 999px;
          box-shadow: 0 6px 16px rgba(0, 0, 0, 0.35);
        }
        .ce-preview-dock-sep {
          /* The original outer pill bar used these to subdivide a
             single container. With each group now its own pill they
             are redundant. */
          display: none;
        }
        .ce-preview-dock .ce-chip {
          padding: 6px 10px;
          font-size: 11px;
          min-height: 28px;
          background: transparent;
          border: 0;
          color: rgba(241, 245, 249, 0.78);
          border-radius: 999px;
          transition: background .12s ease, color .12s ease;
        }
        .ce-preview-dock .ce-chip:hover {
          background: rgba(241, 245, 249, 0.10);
          color: #ffffff;
        }
        .ce-preview-dock .ce-chip.active {
          background: rgba(241, 245, 249, 0.16);
          color: #ffffff;
        }
        .ce-preview-dock select.ce-chip-select {
          padding-right: 24px;
        }
        /* Override the global select.ce-chip-select.active rule (which
           paints a near-white pill + dark navy text — fine on the
           old ribbon, but inside the dock the ribbon itself is dark,
           so the global active state reads as a blown-out blob). The
           dock keeps a translucent-white pill + white text + white
           dropdown caret, matching every other active chip beside it. */
        .ce-preview-dock select.ce-chip-select.active {
          background:
            linear-gradient(45deg, transparent 50%, #ffffff 50%) calc(100% - 14px) 52% / 5px 5px no-repeat,
            rgba(241, 245, 249, 0.16);
          color: #ffffff;
          border-color: transparent;
        }
        .ce-preview-dock select.ce-chip-select.active option {
          /* Dropdown menu is the OS-rendered popup so its text/bg
             stays the legacy dark-on-light treatment for legibility. */
          background: var(--surface, #111827);
          color: var(--text, #eaf2ff);
        }
        .ce-preview-dock .ce-zoom-controls {
          display: flex; align-items: center; gap: 2px;
        }
        .ce-preview-dock .ce-zoom-controls > * {
          padding: 4px 8px;
          font-size: 11px;
        }
        .ce-preview-dock .ce-zoom-controls > button {
          background: transparent;
          border: 0;
          color: rgba(241, 245, 249, 0.78);
          cursor: pointer;
          border-radius: 999px;
          min-height: 28px; min-width: 28px;
          transition: background .12s ease, color .12s ease;
        }
        .ce-preview-dock .ce-zoom-controls > button:hover {
          background: rgba(241, 245, 249, 0.10);
          color: #ffffff;
        }
        .ce-preview-dock #ceZoomLevel {
          min-width: 42px; text-align: center;
          color: #ffffff; font-variant-numeric: tabular-nums;
          font-size: 11px; font-weight: 600;
        }
        /* Phase 18: editor canvas is now a container-query root with the
           same container-name as the kiosk (species-card), so every
           @container species-card (…) rule in responsive.css fires for
        .ce-ai-suggest-panel .h {
          font-size: 10px; color: var(--purple);
          text-transform: uppercase; letter-spacing: .7px;
          font-weight: 700; margin-bottom: 6px;
          display: flex; align-items: center; gap: 5px;
        }
        .ce-ai-suggest-panel .opt {
          background: var(--surface); border: 1px solid var(--border);
          border-radius: 5px; padding: 7px 10px; margin: 4px 0;
          cursor: pointer; color: var(--text); font-size: 12.5px;
          line-height: 1.4; transition: all 0.12s;
        }
        .ce-ai-suggest-panel .opt:hover {
          border-color: rgba(167,139,250,.6);
          background: var(--surface-2);
          color: var(--text-bright);
        }
        .ce-ai-suggest-panel .footer {
          font-size: 10.5px; color: var(--text-dim);
          margin-top: 6px; text-align: center; font-style: italic;
        }

        /* Position picker — 3×3 safe-zone grid for overlay creatives.
           Cells the renderer supports are clickable; the rest are
           reserved (species card, bottom bar) and shown red/disabled. */
        .ce-position-picker {
          margin: 6px 0 14px;
          padding: 12px;
          border: 1px solid var(--border);
          border-radius: 8px;
          background: rgba(255,255,255,0.02);
        }
        .ce-position-picker-h {
          font-size: 10.5px; color: var(--text-dim);
          text-transform: uppercase; letter-spacing: .8px;
          font-weight: 600; margin-bottom: 8px;
          display: flex; align-items: center; justify-content: space-between;
        }
        .ce-position-picker-grid {
          display: grid; grid-template-columns: 1fr 1fr 1fr;
          gap: 4px; aspect-ratio: 16/9;
          background: var(--bg-deep, #06090f);
          padding: 6px; border-radius: 6px;
        }
        .ce-position-cell {
          display: flex; align-items: center; justify-content: center;
          border: 1.5px solid;
          border-radius: 4px; cursor: pointer;
          font-size: 13px; font-weight: 700;
          transition: all .12s;
          font-family: inherit;
        }
        .ce-position-cell.safe {
          border-color: rgba(74,222,128,0.3);
          background: rgba(74,222,128,0.05);
          color: #4ade80;
        }
        .ce-position-cell.safe:hover { background: rgba(74,222,128,0.12); }
        .ce-position-cell.active {
          border-color: var(--aqua) !important;
          background: var(--aqua-glow) !important;
          color: var(--aqua) !important;
        }
        .ce-position-cell.reserved {
          border-color: rgba(239,68,68,0.3);
          background: rgba(239,68,68,0.05);
          color: #ef4444;
          cursor: not-allowed;
          opacity: .55;
        }
        .ce-position-picker-legend {
          margin-top: 8px; font-size: 11px; color: var(--text-dim);
          line-height: 1.5;
        }
        .ce-position-picker-legend .dot {
          display: inline-block; width: 7px; height: 7px;
          border-radius: 50%; vertical-align: middle; margin-right: 4px;
        }

        /* Coverage map — dot grid showing how many screens this campaign
           reaches. One dot per target; color by scope. Until /screens
           and zone aggregation are wired, this visualises the target
           rules themselves rather than per-screen coverage. */
        .ce-coverage-map {
          margin: 12px 16px 12px;
          padding: 12px; border: 1px solid var(--border);
          border-radius: 8px;
          background: rgba(255,255,255,0.02);
        }
        .ce-coverage-map .h {
          font-size: 10.5px; color: var(--text-dim);
          text-transform: uppercase; letter-spacing: .8px;
          font-weight: 600; margin-bottom: 8px;
          display: flex; align-items: center; justify-content: space-between;
        }
        .ce-coverage-grid {
          display: grid; grid-template-columns: repeat(10, 1fr);
          gap: 4px; margin: 8px 0;
        }
        .ce-coverage-dot {
          aspect-ratio: 1; border-radius: 3px;
          background: var(--surface-2); opacity: .35;
          transition: opacity .15s, transform .12s;
        }
        .ce-coverage-dot.lit { background: var(--aqua); opacity: 1; }
        .ce-coverage-dot.lit-site { background: #60a5fa; opacity: 1; }
        .ce-coverage-dot.lit-zone { background: var(--purple); opacity: 1; }
        .ce-coverage-dot.lit-org  { background: var(--orange); opacity: 1; }
        .ce-coverage-dot.lit-species { background: #fbbf24; opacity: 1; }
        .ce-coverage-summary {
          font-size: 11.5px; color: var(--text-dim);
          line-height: 1.5; margin-top: 6px;
        }
        .ce-coverage-summary strong { color: var(--text-bright); font-weight: 600; }
        .ce-coverage-empty {
          padding: 16px 8px; text-align: center;
          font-size: 11.5px; color: var(--text-dim); font-style: italic;
        }

        /* Auto-rule preview — shows the campaign's auto-trigger
           expression in monospace, with a "would have fired N× last
           week" insight. Today the campaigns table doesn't link to a
           rule, so this is a placeholder until that wiring exists. */
        .ce-auto-rule {
          margin: 12px 16px 12px;
          padding: 12px; border: 1px solid var(--border);
          border-radius: 8px;
          background: rgba(255,255,255,0.02);
        }
        .ce-auto-rule .h {
          font-size: 10.5px; color: var(--text-dim);
          text-transform: uppercase; letter-spacing: .8px;
          font-weight: 600; margin-bottom: 8px;
          display: flex; align-items: center; justify-content: space-between;
        }
        .ce-auto-rule .body {
          font-size: 12px; color: var(--text-dim); line-height: 1.5;
          margin-bottom: 8px;
        }
        .ce-auto-rule .expr {
          background: var(--bg-deep, #06090f); border: 1px solid var(--border);
          border-radius: 6px; padding: 8px 10px;
          font-variant-numeric: tabular-nums;
          font-size: 11.5px; color: var(--text); line-height: 1.6;
        }
        .ce-auto-rule .expr strong { color: var(--aqua); font-weight: 600; }
        .ce-auto-rule .insight {
          font-size: 11px; color: var(--text-dim);
          margin-top: 6px;
        }
        .ce-auto-rule .empty {
          padding: 14px 8px; text-align: center;
          font-size: 12px; color: var(--text-dim); line-height: 1.5;
        }
        .ce-auto-rule .empty a {
          color: var(--aqua); font-weight: 600; cursor: pointer;
          text-decoration: none;
        }
        .ce-auto-rule .empty a:hover { text-decoration: underline; }

        /* Live performance rail — compact sidebar version of the
           full perf view. Placeholders are clearly labelled until
           analytics ship. */
        .ce-perf-section {
          margin: 12px 16px; padding: 12px;
          border: 1px solid var(--border); border-radius: 8px;
          background: rgba(255,255,255,0.02);
        }
        .ce-perf-section .h {
          font-size: 10.5px; color: var(--text-dim);
          text-transform: uppercase; letter-spacing: .8px;
          font-weight: 600; margin-bottom: 8px;
          display: flex; align-items: center; justify-content: space-between;
        }
        .ce-perf-spark {
          height: 32px; display: flex; align-items: flex-end; gap: 2px;
          margin-bottom: 8px;
          background: rgba(255,255,255,0.02);
          border-radius: 6px; padding: 4px;
          opacity: .35;
        }
        .ce-perf-spark .b {
          flex: 1; background: var(--aqua); opacity: .5;
          border-radius: 1px;
        }
        .ce-perf-stat-row {
          display: flex; align-items: baseline; justify-content: space-between;
          font-size: 12px; padding: 6px 0;
          border-bottom: 1px dashed var(--border);
        }
        .ce-perf-stat-row:last-child { border-bottom: none; }
        .ce-perf-stat-row .lbl { color: var(--text); }
        .ce-perf-stat-row .v {
          font-weight: 700; color: var(--text-bright);
          font-variant-numeric: tabular-nums;
        }
        .ce-perf-stat-row.placeholder .v { color: var(--text-dim); font-weight: 500; }
        .ce-perf-warning {
          margin-top: 10px; padding: 8px 10px;
          background: rgba(251, 191, 36, 0.1);
          border: 1px solid rgba(251, 191, 36, 0.3);
          border-radius: 6px; color: #fbbf24;
          font-size: 11.5px; line-height: 1.4;
          width: 100%; text-align: left; cursor: pointer;
          font-family: inherit;
        }
        .ce-perf-warning:hover { background: rgba(251, 191, 36, 0.18); }
        .ce-left-mode-heading {
          display:flex; align-items:center; justify-content:space-between;
        }
        .ce-left-panel-card {
          /* Sarah feedback: "in Live the content is on a box, which
             looks good styling, can you use the same styling for the
             boxes in brand, background and uploads". Unified with
             .ce-perf-section so all four panels share one visual
             treatment — 8px radius, var(--border) hairline, faint
             surface tint. */
          margin: 12px 16px; padding: 12px;
          border: 1px solid var(--border); border-radius: 8px;
          background: rgba(255,255,255,0.02);
        }
        .ce-left-panel-card h4 {
          margin:0 0 4px; font-size:13px; color:var(--text-bright);
        }
        .ce-left-panel-card p {
          margin:0 0 10px; font-size:11px; line-height:1.45; color:var(--text-dim);
        }

        /* Phase 58/58a: rail mode — takeover + overlay show the layout
           picker only; content shows copy/slots only. Schedule + targets
           hide .ce-left and use .ce-right. */
        body[data-ce-panel="takeover"] .ce-section-body[data-section="content"],
        body[data-ce-panel="takeover"] .ce-section-title[data-section="content"],
        body[data-ce-panel="overlay"]  .ce-section-body[data-section="content"],
        body[data-ce-panel="overlay"]  .ce-section-title[data-section="content"] {
          display: none !important;
        }
        /* Phase 58e: Schedule + Targets render INSIDE the left panel
           via the .ce-left-mode mechanism (the panes are relocated
           there at editor enter from the hidden .ce-right wrapper).
           So the left column stays visible — no special grid override
           needed. The pre-58e rules that hid .ce-left and reserved a
           280px right column have been retired because the right
           inspector column was already hidden globally, leaving the
           sidebar blank in schedule/targets mode. */
        /* Tighten the creatives/section stack in the left column. */
        .ce-section-title { margin-top: 10px; }
        .ce-creative-tabs { padding: 4px 12px; }

        /* ── Phase 53b: real-render layout thumbnails (Canva-style) ──
           Renders the live cp-slide + cp-overlay markup inside a
           16:9 shell, then overrides vw-based text sizes with
           explicit px values tuned for thumb scale. Every rule is
           scoped to .ce-thumb-live with !important so it only
           affects the picker — the kiosk + main preview keep their
           real vw-based sizing.

           The big idea: the layout's COMPOSITION (where title/CTA/
           QR/cards/progress bar sit) is what makes one layout
           visually distinct from another. Text content is
           secondary. Forcing readable text at thumb scale lets the
           composition shine through. */
        .ce-thumb-live {
          /* 16:9 card with sharp edges, true mini-canvas. The inner
             renders at full 1920×1080 production size and is CSS-
             scaled down via transform: scale(...) computed from
             container-query units, so every layout looks identical
             to what it'll be on the kiosk — text, spacing, padding,
             everything — just smaller. */
          position: relative;
          width: 100%;
          aspect-ratio: 16 / 9;
          border-radius: 0;
          overflow: hidden;
          background: #06090f;
          border: 1px solid rgba(120, 200, 255, 0.12);
          transition: border-color .15s ease, box-shadow .15s ease;
          container-type: inline-size;
        }
        .ce-layout-card:hover .ce-thumb-live {
          border-color: rgba(241, 245, 249, 0.55);
        }
        .ce-layout-card.selected .ce-thumb-live {
          border-color: rgba(241, 245, 249, 0.85);
          box-shadow: 0 0 0 2px rgba(241, 245, 249, 0.3);
        }
        .ce-thumb-live-inner {
          position: absolute;
          top: 0; left: 0;
          width: 1920px;
          height: 1080px;
          /* 100cqw = card width; 100cqw / 1920px = unitless scale ratio. */
          transform: scale(calc(100cqw / 1920px));
          transform-origin: top left;
        }
        /* Overlay-mode backdrop — a mocked kiosk species card sits
           below the cp-overlay markup so the curator sees the overlay
           anchored against a real species-page composition (cut-out
           photo + name + scientific name + accent stripe + chips),
           matching what the visitor will see in production. */
        .ce-thumb-overlay-bg-fallback {
          position: absolute; inset: 0; z-index: 0;
          background:
            radial-gradient(ellipse at 30% 30%, rgba(45,212,191,0.32), transparent 55%),
            radial-gradient(ellipse at 75% 70%, rgba(59,130,246,0.28), transparent 60%),
            linear-gradient(135deg, #02101f 0%, #061a2b 60%, #02060f 100%);
        }
        .ce-thumb-live-inner.ce-thumb-overlay-mode > .cp-overlay,
        .ce-thumb-popup-inner.ce-thumb-overlay-mode > .cp-overlay {
          position: absolute;
          z-index: 2;
        }
        /* Real kiosk preview iframe sized to 1920×1080 inside the
           thumb's inner box (which is itself transform-scaled to fit
           the card). pointer-events:none so clicks hit the overlay
           markup on top, not the iframe. */
        .ce-thumb-kiosk-iframe {
          position: absolute; inset: 0; z-index: 0;
          width: 1920px; height: 1080px;
          border: 0;
          /* Subtle aqua gradient backdrop so the thumb has visible content
             before the iframe finishes its first paint. Once the kiosk
             page loads it covers this placeholder completely. */
          background:
            radial-gradient(ellipse at 30% 30%, rgba(45,212,191,0.18), transparent 55%),
            radial-gradient(ellipse at 75% 70%, rgba(59,130,246,0.18), transparent 60%),
            linear-gradient(135deg, #02101f 0%, #06182b 60%, #020912 100%);
          pointer-events: none;
        }
        /* Static species-card mock used as the picker thumb backdrop —
           cheap to render, never blocks on iframe loads. Sized to
           match the 1920×1080 inner so the parent transform-scale
           shrinks it correctly per thumb. */
        .ce-thumb-species-card {
          position: absolute; inset: 0; z-index: 0;
          display: flex;
          background:
            radial-gradient(ellipse at 12% 25%, rgba(45,212,191,0.18), transparent 55%),
            radial-gradient(ellipse at 80% 85%, rgba(59,130,246,0.22), transparent 60%),
            linear-gradient(135deg, #02101f 0%, #06182b 60%, #020912 100%);
          overflow: hidden;
        }
        .ce-thumb-species-card .ce-tsc-stripe {
          position: absolute; left: 0; top: 0; bottom: 0;
          width: 8px;
          opacity: 0.95;
        }
        .ce-thumb-species-card .ce-tsc-text {
          position: relative; z-index: 1;
          flex: 1;
          padding: 100px 80px;
          display: flex; flex-direction: column; gap: 20px;
          color: #fff;
          font-family: 'Inter', system-ui, sans-serif;
        }
        .ce-thumb-species-card .ce-tsc-eyebrow {
          font-size: 22px; font-weight: 900; letter-spacing: 4px;
          color: var(--cp-accent, #2dd4bf);
          text-transform: uppercase;
        }
        .ce-thumb-species-card .ce-tsc-name {
          font-size: 168px; font-weight: 900;
          line-height: 0.92; letter-spacing: -3px;
          color: #ffffff;
        }
        .ce-thumb-species-card .ce-tsc-sci {
          font-size: 44px; font-weight: 500; font-style: italic;
          color: rgba(255,255,255,0.66);
        }
        .ce-thumb-species-card .ce-tsc-chips {
          display: flex; gap: 12px; margin-top: 12px;
        }
        .ce-thumb-species-card .ce-tsc-chip {
          font-size: 22px; font-weight: 700; letter-spacing: 1px;
          padding: 12px 24px; border-radius: 999px;
          background: rgba(255,255,255,0.08);
          border: 1px solid rgba(255,255,255,0.16);
          color: rgba(255,255,255,0.85);
        }
        .ce-thumb-species-card .ce-tsc-photo {
          position: absolute; right: -120px; bottom: -60px;
          width: 60%; height: 110%;
          object-fit: contain; object-position: right bottom;
          filter: drop-shadow(0 24px 60px rgba(0,0,0,0.55));
          z-index: 0;
          opacity: 0.96;
        }
        .ce-thumb-overlay-bg-fallback {
          position: absolute; inset: 0; z-index: 0;
          background:
            radial-gradient(ellipse at 30% 30%, rgba(45,212,191,0.32), transparent 55%),
            radial-gradient(ellipse at 75% 70%, rgba(59,130,246,0.28), transparent 60%),
            linear-gradient(135deg, #02101f 0%, #061a2b 60%, #02060f 100%);
        }
        .ce-thumb-live-inner.ce-thumb-overlay-mode > .cp-overlay {
          position: absolute;
          z-index: 2;
        }
        .ce-layout-group-label {
          grid-column:1/-1; padding:8px 2px 2px; font-size:9px; text-transform:uppercase;
          letter-spacing:1.4px; color:var(--text-dim); opacity:0.7;
        }
        /* When an overlay layout is selected, the preview hosts a real
           species page (via /display/__preview__) in an iframe and renders
           the overlay creative on a layer that sits on top of it. The
           iframe fills the frame; the overlay layer is absolute-positioned
           inside the frame so the overlay renderer's position classes
           (top-left, bottom, etc) anchor to the preview, not the viewport. */
        .ce-preview-frame.ce-preview-overlay { background:#06090f; }

        /* ── Phase 42/43: drag-and-drop overlay placement ─────────────
           One silhouette per allowed position for the layout being
           dragged. Each silhouette is the real overlay markup, sized +
           positioned by the kiosk's placement engine — so the curator
           sees the EXACT footprint the overlay will occupy. The
           container is just an absolute layer that lets the
           silhouettes catch drag/drop events; positioning is on the
           silhouettes themselves via inline style from applyPlacement. */
        .ce-overlay-drop-zones {
          position: absolute; inset: 0;
          display: none;
          z-index: 50;
          pointer-events: none;
        }
        .ce-overlay-drop-zones.is-active { display: block; }
        /* Silhouette wrapper — fills the area its child overlay
           occupies. The child .cp-overlay is the rendered ghost; the
           wrapper sits at the same coordinates so drag events on the
           wrapper feel like they're on the overlay itself. */
        .ce-overlay-target {
          position: absolute; inset: 0;
          pointer-events: none;
        }
        .ce-overlay-target .cp-overlay {
          pointer-events: auto;
          opacity: 0.45;
          outline: 2px dashed rgba(241, 245, 249, 0.55);
          outline-offset: 2px;
          transition: opacity .15s ease, outline-color .15s ease,
                      transform .15s ease, filter .15s ease;
          cursor: copy;
        }
        .ce-overlay-target.is-hover .cp-overlay {
          opacity: 0.95;
          outline: 2px solid rgba(241, 245, 249, 1);
          outline-offset: 3px;
          filter: drop-shadow(0 4px 18px rgba(241, 245, 249, 0.45));
          transform: scale(1.03);
          z-index: 2;
        }
        /* Subtle "drop here" label that fades in over the hovered
           silhouette so the curator knows what they're committing to. */
        .ce-overlay-target .cp-overlay::after {
          content: attr(data-cp-label);
          position: absolute; inset: auto 8px 8px auto;
          font-size: 9px; font-weight: 700; letter-spacing: 1.4px;
          text-transform: uppercase;
          color: rgba(241, 245, 249, 0.95);
          background: rgba(0, 0, 0, 0.55);
          padding: 3px 6px; border-radius: 4px;
          opacity: 0; transition: opacity .15s ease;
          pointer-events: none;
        }
        .ce-overlay-target.is-hover .cp-overlay::after { opacity: 1; }
        /* Frame is "armed" while a drag is in progress — adds a gentle
           cyan ring so the curator knows the drop is targeting here. */
        .ce-preview-frame.ce-preview-drop-armed {
          box-shadow: 0 0 0 2px rgba(241, 245, 249,0.45),
                      0 0 28px rgba(241, 245, 249,0.18);
        }
        /* The species iframe normally accepts clicks (so the curator can
           tap species tabs etc.). While a drag is in progress we disable
           its pointer-events so dragover/drop bubble through to the
           drop zones above. Restored when the drag ends. */
        .ce-preview-frame.ce-preview-drop-armed .ce-preview-species-iframe {
          pointer-events: none;
        }
        /* Layout-card drag affordances */
        .ce-layout-card.ce-layout-card-draggable { cursor: grab; }
        .ce-layout-card.ce-layout-card-draggable:active { cursor: grabbing; }
        .ce-layout-drag-hint {
          display: inline-flex; align-items: center; gap: 4px;
          margin-left: 6px;
          font-size: 9px; color: rgba(190, 220, 235, 0.55);
        }
        /* Tiny on-brand pill the cursor carries while dragging an
           overlay card. Off-screen at create-time; the browser
           snapshots it for the drag image then we remove it. */
        .ce-overlay-drag-ghost {
          display: inline-flex; align-items: center; gap: 8px;
          padding: 8px 14px;
          background: linear-gradient(135deg, rgba(241, 245, 249,0.98), rgba(0,140,170,0.98));
          color: #001a3d;
          font-family: var(--aqos-ff-sans);
          font-size: 13px; font-weight: 600; letter-spacing: 0.02em;
          border-radius: 999px;
          box-shadow: 0 8px 24px rgba(0,0,0,0.35),
                      0 0 0 1px rgba(255,255,255,0.18) inset;
          white-space: nowrap;
          pointer-events: none;
        }
        .ce-overlay-drag-ghost i { font-size: 11px; opacity: 0.85; }
        /* Replacement for the position dropdown — read-only chip
           showing the current anchor + a hint to use drag-to-reposition. */
        .ce-position-chip {
          display: inline-flex; align-items: center; gap: 8px;
          padding: 7px 11px; border-radius: 8px;
          background: rgba(241, 245, 249, 0.08);
          border: 1px solid rgba(241, 245, 249, 0.22);
          color: var(--text);
          font-size: 12px;
        }
        .ce-position-chip-value {
          font-weight: 600; letter-spacing: 0.02em;
          color: var(--text-bright, #fff);
          text-transform: capitalize;
        }
        .ce-position-chip-hint {
          font-size: 10px; color: var(--text-dim);
          letter-spacing: 1px; text-transform: uppercase;
          margin-left: auto;
        }
        /* Phase 25b: iframe is now a real live kiosk, so clicks must go
           through (tap species tabs, switch tiers, touch controls).
           Overlay layer on top stays pointer-events:none so the curator's
           overlay doesn't swallow clicks intended for the kiosk. */
        .ce-preview-frame .ce-preview-species-iframe {
          position:absolute; inset:0; width:100%; height:100%;
          border:0; background:#06090f; display:block;
          pointer-events:auto;
        }
        .ce-preview-frame .ce-preview-overlay-layer {
          position:absolute; inset:0; pointer-events:none; z-index:2;
        }
        /* Small loading hint while the species iframe boots — fades when the
           iframe reports preview-ready via postMessage. */
        .ce-preview-frame .ce-preview-loading {
          position:absolute; top:50%; left:50%; transform:translate(-50%,-50%);
          font-size:11px; color:rgba(255,255,255,0.35); letter-spacing:1.4px; text-transform:uppercase;
          font-family:system-ui,sans-serif; pointer-events:none;
          transition:opacity .25s ease; z-index:1;
        }
        .ce-preview-frame.ce-preview-ready .ce-preview-loading { opacity:0; }
        /* The thumbnail IS the card — no outer chrome. The .ce-thumb-live
           inside provides the visible surface (see selected/hover rules
           on .ce-layout-card.selected .ce-thumb-live above). */
        .ce-layout-card {
          border:0; padding:0; background:transparent;
          cursor:pointer;
          display:flex; flex-direction:column; gap:6px;
        }

        /* Hover-preview popup — floats outside the side panel, anchored
           via JS to the hovered card. Same transform-scale render as
           the thumb so it's a true 3× mini-canvas at this size. */
        .ce-thumb-popup {
          position: fixed;
          /* High enough to win against any modal/iframe/preview frame.
             Was 5000 — bumped because the canvas preview frame's
             stacking context was rendering above it on some routes. */
          z-index: 99999;
          /* Was 480px — bumped 25% to 600px per Sarah feedback so
             the hover preview is more legible without a click. The
             positioning math in CE_LayoutPicker.onCardEnter uses the
             same 600 constant. */
          width: 600px;
          aspect-ratio: 16 / 9;
          background: #06090f;
          border: 1px solid rgba(255,255,255,0.18);
          border-radius: 10px;
          overflow: hidden;
          pointer-events: none;
          opacity: 0;
          transform: scale(0.96);
          transition: opacity .15s ease, transform .15s ease;
          box-shadow: 0 24px 60px rgba(0,0,0,0.55);
          container-type: inline-size;
          /* Force own stacking context — guarantees the popup is never
             clipped by an ancestor's overflow:hidden / transform that
             might otherwise create a containing block. */
          isolation: isolate;
        }
        .ce-thumb-popup.is-visible {
          opacity: 1;
          transform: scale(1);
        }
        .ce-thumb-popup-inner {
          position: absolute;
          top: 0; left: 0;
          width: 1920px;
          height: 1080px;
          transform: scale(calc(100cqw / 1920px));
          transform-origin: top left;
        }
        .ce-layout-thumb {
          height:40px; border-radius:4px;
          background:linear-gradient(135deg, #1e3a5f, #0f1f3d);
          display:flex; align-items:center; justify-content:center;
          color:rgba(255,255,255,0.4); font-size:10px; margin-bottom:6px;
        }
        .ce-layout-name { font-size:12px; font-weight:600; color:var(--text-bright); }

        .ce-preview-toolbar {
          /* Phase 56: flat toolbar — no background contrast, no
             bottom border. Sits on the centre pane like a menu row. */
          display:flex; justify-content:space-between; align-items:center; gap:12px;
          padding:10px 18px; background:transparent; border-bottom:0;
          flex-wrap:wrap;
        }
        .ce-preview-label { font-size:11px; text-transform:uppercase; letter-spacing:1.2px; color:var(--text-dim); }

        /* Preview Context picker — lets the designer choose what species
           (if any) is shown behind the overlay preview. Phase 0: design-time
           only, no schema change; drives the existing species iframe. */
        .ce-preview-context {
          display:flex; align-items:center; gap:6px; flex-wrap:wrap;
        }
        .ce-preview-context-label {
          font-size:11px; color:var(--text-dim); text-transform:uppercase; letter-spacing:1px;
        }
        .ce-preview-select {
          background:var(--bg-deep); color:var(--text-bright);
          border:1px solid var(--border); border-radius:6px;
          padding:5px 10px; font-size:12px; cursor:pointer; min-width:150px;
        }
        .ce-preview-select:hover { border-color:var(--aqua); }
        .ce-preview-select:focus { outline:none; border-color:var(--aqua); }
        .ce-aspect-toggle { display:flex; gap:4px; }
        .ce-chip {
          padding:5px 12px; border-radius:99px; border:1px solid var(--border);
          background:transparent; color:var(--text-dim); font-size:11px;
          cursor:pointer; transition:all .15s;
        }
        .ce-chip:hover { color:var(--text-bright); }
        .ce-chip.active { background:var(--aqua); color:#001a3d; border-color:var(--aqua); }

        /* Phase 28: chip-styled <select>. Native dropdown arrow kept but
           tinted to match the chip palette. Active state adopts the
           same filled look as an active chip. */
        select.ce-chip-select {
          -webkit-appearance: none; appearance: none;
          padding: 5px 28px 5px 12px;
          font-family: inherit;
          background:
            linear-gradient(45deg, transparent 50%, currentColor 50%) calc(100% - 14px) 52% / 5px 5px no-repeat,
            transparent;
          color: var(--text-dim);
        }
        select.ce-chip-select.active {
          background:
            linear-gradient(45deg, transparent 50%, #001a3d 50%) calc(100% - 14px) 52% / 5px 5px no-repeat,
            var(--aqua);
          color: #001a3d; border-color: var(--aqua);
        }
        select.ce-chip-select:focus-visible {
          outline: 2px solid var(--aqua); outline-offset: 2px;
        }
        select.ce-chip-select option {
          background: var(--surface, #111827); color: var(--text, #eaf2ff);
        }

        .ce-preview-frame-wrapper {
          /* Phase 58e: preview never scrolls — always fits inside
             its available space via transform-scale in JS. Padding
             zeroed so the canvas reaches the bottom of the column.
             container-type: size lets the @container species-card (...)
             rule in responsive.css fire for editor preview, live
             preview, AND the kiosk — one rendering target. */
          flex:1; display:flex; align-items:center; justify-content:center;
          padding:0; min-height:0; overflow:hidden;
        }
        /* Phase 31: no max-width/max-height clamps — bezel keeps its
           intrinsic pixel size (3840 for Large etc) so container
           queries fire correctly, and applyCePreviewScale() CSS-
           scales the frame to fit the pane. */
        .ce-preview-frame {
          /* Phase 58e: photorealistic kiosk bezel. The canvas keeps
             its full intrinsic dimensions — bezel paints OUTSIDE
             via stacked box-shadows so screen content is never
             covered. Bezel thickness is intentionally chunky (32px
             matte ring) so it stays visible after the frame is
             transform-scaled to fit the pane.
             Layers, outer to inner:
              · 36px outer back-face (deepest dark)
              · 1px white outer rim hairline (catches ambient light)
              · 32px matte-black bezel ring
              · 1px metal trim highlight on top edge
              · 1px metal trim shadow on bottom edge
              · Inner 1px screen-edge groove
              · Multi-layered drop shadow → wall-mounted feel.
             Plus a top-down glass reflection via ::before so the
             canvas reads as glass under display lighting and a
             tiny camera-style sensor dot via ::after for a
             "this is real hardware" anchor. */
          position:relative; background:#000; border-radius:10px;
          box-shadow:
            inset 0 0 0 1px rgba(255,255,255,0.04),
            inset 0 1px 6px rgba(0,0,0,0.55),
            0 0 0 32px #0a0c10,
            0 -1px 0 32px rgba(150,170,200,0.22),
            0 1px 0 32px rgba(0,0,0,0.65),
            0 0 0 36px #040507,
            0 0 0 37px rgba(255,255,255,0.06),
            0 60px 120px -16px rgba(0,0,0,0.70),
            0 24px 48px -8px rgba(0,0,0,0.55),
            0 8px 18px -4px rgba(0,0,0,0.40);
          container-type: size;
          container-name: species-card;
          overflow:hidden;
        }
        /* Glass-screen reflection — soft top-down highlight + a
           more concentrated angled glint. Sits as a non-clickable
           overlay above the canvas so curators still interact
           normally with the elements underneath. */
        .ce-preview-frame::before {
          content: '';
          position: absolute; inset: 0;
          pointer-events: none;
          border-radius: inherit;
          background:
            linear-gradient(180deg, rgba(255,255,255,0.05) 0%, rgba(255,255,255,0) 22%),
            linear-gradient(118deg, rgba(255,255,255,0) 60%, rgba(255,255,255,0.025) 72%, rgba(255,255,255,0) 78%);
          z-index: 6;
          mix-blend-mode: screen;
        }
        /* Tiny camera-style sensor dot centred above the screen on
           the bezel — pure decoration, anchors the "this is a real
           device" read. ::after sits above the box-shadow bezel so
           it has somewhere to render (the bezel is paint, not DOM). */
        .ce-preview-frame::after {
          content: '';
          position: absolute;
          top: -8px; left: 50%;
          transform: translateX(-50%);
          width: 5px; height: 5px;
          border-radius: 50%;
          background:
            radial-gradient(circle at 35% 35%, rgba(80,140,200,0.8) 0%, rgba(20,40,60,0.95) 55%, #000 100%);
          box-shadow: 0 0 0 1px rgba(0,0,0,0.6), 0 1px 2px rgba(0,0,0,0.6);
          pointer-events: none;
          z-index: 7;
        }
        /* Phase 50: inline-editable title / CTA on the preview.
           contenteditable gets a subtle dashed outline on hover so
           curators know the element is editable. Focus solidifies
           the outline. Empty state renders data-placeholder via a
           pseudo element so the slot still reads "tap here" when
           there's no copy yet. */
        .ce-preview-frame [contenteditable][data-ce-slot],
        .ce-preview-overlay-layer [contenteditable][data-ce-slot] {
          cursor: text;
          outline: 1.5px dashed transparent;
          outline-offset: 3px;
          border-radius: 4px;
          transition: outline-color .15s ease, background-color .15s ease;
          min-width: 1.5em;
          min-height: 1em;
        }
        .ce-preview-frame [contenteditable][data-ce-slot]:hover,
        .ce-preview-overlay-layer [contenteditable][data-ce-slot]:hover {
          outline-color: rgba(241, 245, 249, 0.55);
          background: rgba(241, 245, 249, 0.06);
        }
        .ce-preview-frame [contenteditable][data-ce-slot]:focus,
        .ce-preview-overlay-layer [contenteditable][data-ce-slot]:focus {
          outline: 2px solid rgba(241, 245, 249, 0.9);
          background: rgba(241, 245, 249, 0.08);
        }
        /* Empty state: render the placeholder in the same box so the
           curator sees a hint the field exists even when no copy is
           set. :empty won't hit when the inline text was explicitly
           cleared with a ZWSP — contenteditable collapses to truly
           empty, so :empty::before does the job. */
        .ce-preview-frame [contenteditable][data-ce-slot]:empty::before,
        .ce-preview-overlay-layer [contenteditable][data-ce-slot]:empty::before {
          content: attr(data-placeholder);
          color: rgba(255,255,255,0.35);
          font-style: italic;
          pointer-events: none;
        }
        /* Conservation-badge progress bar — drag-to-set raised value
           in the editor preview. Only inside the preview overlay layer;
           production kiosks render the bar non-interactive. !important
           overrides the inline cursor:pointer that wirePillOnly stamps
           on every pill-target node — we want a resize cue on the bar
           because dragging now changes the value. The track relaxes its
           overflow:hidden so the fill's grab-handle pseudo can poke out
           the top/bottom of the bar — that's how the curator sees it's
           a knob to grab, not a static fill. */
        .ce-preview-overlay-layer .cp-ov-cons-track {
          cursor: ew-resize !important;
          touch-action: none;
          overflow: visible;
        }
        .ce-preview-overlay-layer .cp-ov-cons-track:hover {
          box-shadow: 0 0 0 2px rgba(45,212,191,0.45);
        }
        /* Visible grab handle pinned to the leading edge of the fill —
           sits at exactly the current `raised` position so it doubles
           as a value indicator. Pseudo-element so it tracks the fill's
           width:N% without any extra JS. Pointer events bubble through
           to the parent track, where the existing drag handler fires. */
        .ce-preview-overlay-layer .cp-ov-cons-fill {
          position: relative;
          overflow: visible;
        }
        .ce-preview-overlay-layer .cp-ov-cons-fill::after {
          content: "";
          position: absolute;
          right: -12px;
          top: 50%;
          transform: translateY(-50%);
          width: 24px;
          height: 24px;
          border-radius: 50%;
          /* High-contrast thumb: white core + dark navy ring + soft
             white halo. Reads as a knob on ANY fill colour (the dark
             ring breaks white-on-white; the white core breaks
             dark-on-dark) and on any panel backdrop. The CSS var
             `--aqua` in this theme resolves to off-white, so the
             colours are hardcoded here on purpose. */
          background: #ffffff;
          border: 3px solid #0c1e35;
          box-shadow:
            0 0 0 2px rgba(255,255,255,0.55),
            0 3px 8px rgba(0,0,0,0.55);
          cursor: ew-resize;
          pointer-events: none; /* clicks fall through to the track */
          transition: transform .12s ease, box-shadow .12s ease;
        }
        .ce-preview-overlay-layer .cp-ov-cons-track:hover .cp-ov-cons-fill::after {
          transform: translateY(-50%) scale(1.18);
          box-shadow:
            0 0 0 2px rgba(255,255,255,0.7),
            0 4px 12px rgba(0,0,0,0.65),
            0 0 0 6px rgba(45,212,191,0.35);
        }
        /* When the goal is 0 the bar reads 0% with no fill — render a
           ghost handle on the leading edge of the track itself so the
           curator still sees something to grab. */
        .ce-preview-overlay-layer .cp-ov-cons-track:not(:has(.cp-ov-cons-fill[style*="%"]))::before {
          content: "";
          position: absolute;
          left: 0; top: 50%;
          transform: translateY(-50%);
          width: 20px; height: 20px;
          border-radius: 50%;
          background: #ffffff;
          border: 3px solid var(--cp-accent, #2dd4bf);
          opacity: 0.55;
          pointer-events: none;
        }
        /* Phase 58e: editor-only AUTO badge for stat / progress
           figures whose format='auto'. The renderer stamps
           data-cp-auto-format="1" on the wrapping element; this CSS
           pins a small "AUTO" pill so the UK curator (or whoever
           designs the creative) sees that the figure will localise
           on each kiosk per its site currency. Kiosk markup carries
           the same attribute but no rule scoped to .ce-preview-frame
           or .ce-preview-overlay-layer matches there → invisible at
           production. The pill sits absolutely on the upper-right of
           the figure so it doesn't reflow the rendered text. */
        .ce-preview-frame [data-cp-auto-format],
        .ce-preview-overlay-layer [data-cp-auto-format] {
          position: relative;
        }
        .ce-preview-frame [data-cp-auto-format]::after,
        .ce-preview-overlay-layer [data-cp-auto-format]::after {
          content: 'AUTO';
          position: absolute;
          top: -10px;
          right: -8px;
          font-size: 9px; font-weight: 800; letter-spacing: 0.08em;
          padding: 2px 6px;
          background: rgba(45,212,191,0.95);
          color: #001a3d;
          border-radius: 999px;
          box-shadow: 0 2px 6px rgba(0,0,0,0.4);
          pointer-events: none;
          /* Inherit nothing — the parent stat-value can be huge
             (96px+) and it would scale the badge too. */
          font-family: 'Inter', system-ui, sans-serif;
          line-height: 1;
          text-shadow: none;
          white-space: nowrap;
          z-index: 5;
        }
        /* Phase 58e: when the curator selects the canvas itself
           (clicks empty space inside it), show the same selection
           affordance elements get — a thin aqua outline — so the
           canvas reads as the active editing target. Inset shadow
           rather than outline so it respects border-radius and
           doesn't bleed past the rounded corners. */
        .ce-preview-frame .cp-element-canvas.ce-canvas-selected {
          box-shadow: inset 0 0 0 2px var(--aqua, #2dd4bf);
        }
        .ce-preview-frame .cp-element-canvas.ce-canvas-selected::after {
          content: 'CANVAS';
          position: absolute; left: 0; top: -22px;
          padding: 2px 8px; border-radius: 999px;
          background: var(--aqua, #2dd4bf); color: #001a3d;
          font-size: 10px; font-weight: 800; letter-spacing: .04em;
          text-transform: uppercase;
          pointer-events: none; z-index: 5;
        }
        .ce-preview-frame .cp-el { pointer-events:auto; cursor:grab; outline:1.5px solid transparent; outline-offset:4px; }
        .ce-preview-frame .cp-el.ce-el-locked { cursor:not-allowed; }
        .ce-preview-frame .cp-el:hover { outline-color:rgba(241,245,249,0.45); }
        .ce-preview-frame .cp-el.ce-el-selected { outline:2px solid var(--aqua); box-shadow:0 0 0 1px rgba(0,200,180,0.25); }
        .ce-preview-frame .cp-el.ce-el-multi-selected { outline:2px solid rgba(241,245,249,0.78); }
        .ce-preview-frame .cp-el.ce-el-selected::before {
          content: attr(data-element-type);
          position:absolute; left:0; top:-24px; padding:2px 7px; border-radius:999px;
          background:rgba(0,200,180,0.95); color:#001a3d; font-size:10px; font-weight:800; letter-spacing:.04em; text-transform:uppercase;
        }
        .ce-el-delete {
          position:absolute; right:-13px; top:-13px; width:26px; height:26px; border-radius:50%; border:0;
          background:#ef4444; color:white; display:none; align-items:center; justify-content:center;
          font-size:13px; z-index:50; cursor:pointer; box-shadow:0 8px 18px rgba(0,0,0,0.35);
        }
        .cp-el.ce-el-selected > .ce-el-delete { display:flex; }

        /* Locked element — visible lock badge in the corner +
           grab-not-allowed cursor so curators get clear feedback that
           the element won't respond to drag / resize / delete. */
        .cp-el.ce-el-locked { cursor: not-allowed !important; }
        .cp-el.ce-el-locked > .ce-el-delete,
        .cp-el.ce-el-locked > .ce-el-resize { display: none !important; }
        .cp-el.ce-el-locked::after {
          content: '\f023'; /* fa-lock */
          font-family: 'Font Awesome 6 Free';
          font-weight: 900;
          position: absolute;
          top: 6px; left: 6px;
          width: 22px; height: 22px;
          display: flex; align-items: center; justify-content: center;
          background: rgba(20, 22, 30, 0.85);
          color: rgba(255,255,255,0.9);
          border: 1px solid rgba(255,255,255,0.18);
          border-radius: 50%;
          font-size: 10px;
          z-index: 4;
          pointer-events: none;
          backdrop-filter: blur(6px);
        }
        /* Phase 58e: linking is feature-flagged off until the UX
           is settled. CSS belt to the JS feature-flag braces — even
           if a stale node sneaks through, the visible affordances
           are hidden everywhere. */
        body .ce-el-link-handle,
        body .ce-toolbar-link {
          display: none !important;
        }
        /* Phase 58e: chain-icon link handle on linkable elements
           (stat / progress). Sits above the element box; always
           visible (faded) so curators can see at a glance which
           figures are linkable. Brightens on hover. When the
           element already has a binding, the handle goes solid
           aqua so its linked-state is unambiguous. */
        .ce-el-link-handle {
          position:absolute; left:50%; top:-30px;
          transform:translateX(-50%);
          width:26px; height:26px; border-radius:50%;
          border:1px solid rgba(45,212,191,0.5);
          background:rgba(2,10,23,0.92);
          color:rgba(45,212,191,0.85);
          background-size:5% 5%;
          mask-image:linear-gradient(rgba(0,0,0,0.85), rgba(0,0,0,0.85));
        }
        .ce-left-tools-panel { padding:0 16px 16px; }
        .ce-element-toolbox { display:flex; flex-direction:column; gap:14px; margin:6px 0 14px; }
        .ce-element-tool-group { display:flex; flex-direction:column; gap:7px; }
        .ce-element-tool-group-title {
          font-size:10px; font-weight:800; letter-spacing:.08em; text-transform:uppercase;
          color:var(--text-dim); opacity:.8;
        }
        .ce-element-tool-grid { display:grid; grid-template-columns:1fr 1fr; gap:7px; }

        /* Drill-through Elements pane (Canva-style). Top level shows a
           3-per-row grid of icon tiles; clicking one re-renders the
           panel with that category's items + a back arrow header. */
        .ce-elements-cat-list {
          display:grid;
          grid-template-columns: repeat(3, 1fr);
          gap:8px;
          margin:6px 0 14px;
        }
        .ce-elements-cat-card {
          /* Borderless tile — the icon-wrap holds the per-category
             colour as a soft radial backdrop blob, so the grid feels
             distinct without re-introducing hard rectangle frames. */
          display:flex; flex-direction:column;
          align-items:center; justify-content:center;
          gap:10px;
          aspect-ratio: 1 / 1;
          padding:6px;
          min-width: 0;
          background:transparent;
          border:0;
          color:var(--text); font-size:12px; font-weight:600;
          line-height:1.15; text-align:center;
          cursor:pointer;
          transition: color .15s ease, transform .15s ease;
        }
        .ce-elements-cat-card:hover {
          color:var(--text-bright);
          transform: translateY(-2px);
        }
        .ce-elements-cat-card .lbl {
          display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical;
          overflow:hidden;
        }
        .ce-cat-icon-wrap {
          position:relative;
          width:60px; height:60px;
          display:flex; align-items:center; justify-content:center;
          border-radius:14px;
          /* Sarah feedback: "the colourful element folder icons don't
             match the app, come up with something more subtle". Replaced
             the per-category hue radial-gradient with a uniform muted
             surface tile + hairline border, so the rail reads as one
             cohesive set of monochrome chips. The category's hue is
             retained only as a faint icon tint, applied at low alpha. */
          background: rgba(255,255,255,0.04);
          box-shadow: inset 0 0 0 1px rgba(255,255,255,0.06);
          transition: background .18s ease, box-shadow .18s ease;
        }
        .ce-elements-cat-card:hover .ce-cat-icon-wrap {
          background: rgba(255,255,255,0.07);
          box-shadow: inset 0 0 0 1px rgba(255,255,255,0.12);
        }
        .ce-cat-icon-wrap i {
          color: var(--aq-text-dim);
          font-size:20px;
          transition: color .15s ease;
        }
        .ce-elements-cat-card:hover .ce-cat-icon-wrap i {
          color: var(--aq-text);
        }

        /* AI compose-creative thumb — gradient + sparkle glyph so the
           tile reads as "magic generation" not "another template". */
        .ce-thumb-live .ce-ai-thumb {
          width:100%; height:100%;
          display:flex; flex-direction:column; align-items:center; justify-content:center;
          gap:6px;
          background:
            radial-gradient(circle at 25% 25%, rgba(167,139,250,0.4), transparent 50%),
            radial-gradient(circle at 80% 70%, rgba(45,212,191,0.4), transparent 55%),
            linear-gradient(135deg, #1a0f3d 0%, #0b1424 100%);
          color: rgba(255,255,255,0.95);
          font-size: 11.5px; font-weight: 700; letter-spacing: 0.04em;
        }
        .ce-thumb-live .ce-ai-thumb i {
          font-size: 28px;
          color: #fff;
          filter: drop-shadow(0 0 12px rgba(167,139,250,0.65));
        }
        /* AI composer modal — suggestion chips + textarea polish. */
        .ce-ai-suggest {
          background: rgba(255,255,255,0.05);
          border: 1px solid rgba(255,255,255,0.10);
          color: var(--text-dim);
          font-size: 11px; line-height: 1.3;
          padding: 6px 10px; border-radius: 99px;
          cursor: pointer;
          text-align: left;
          transition: background .12s ease, color .12s ease, border-color .12s ease;
        }
        .ce-ai-suggest:hover {
          background: rgba(167,139,250,0.12);
          border-color: rgba(167,139,250,0.40);
          color: var(--text-bright);
        }
        #ceAiBrief:focus {
          border-color: var(--aqua, #2dd4bf) !important;
          outline: none;
        }

        /* Lines & shapes picker — 3-up grid of variant tiles. The
           preview span renders a stylised mini version of the shape
           via background + border-radius (no SVG/icon needed). */
        .ce-shape-grid {
          display:grid;
          grid-template-columns: repeat(3, 1fr);
          gap:10px;
          padding-bottom:14px;
        }
        .ce-shape-tile {
          aspect-ratio: 1 / 1;
          background:transparent;
          border:0;
          padding:8px;
          display:flex; flex-direction:column;
          align-items:center; justify-content:center;
          gap:8px;
          color:var(--text-dim); font-size:10.5px; font-weight:600;
          line-height:1.15; text-align:center;
          cursor:pointer;
          transition: color .12s ease, transform .12s ease;
        }
        .ce-shape-tile:hover {
          color:var(--text-bright);
          transform: translateY(-1px);
        }
        .ce-shape-tile:hover .ce-shape-preview { background-color: var(--aqua, #2dd4bf); }
        .ce-shape-preview {
          background: rgba(255,255,255,0.55);
          transition: background-color .15s ease;
        }
        .ce-shape-preview-rect      { width:62%; height:42%; border-radius:0; }
        .ce-shape-preview-rounded   { width:62%; height:42%; border-radius:8px; }
        .ce-shape-preview-circle    { width:42%; height:42%; border-radius:50%; }
        .ce-shape-preview-pill      { width:62%; height:18%; border-radius:99px; }
        .ce-shape-preview-square    { width:42%; height:42%; border-radius:0; }
        .ce-shape-preview-line-h    { width:62%; height:2px;  border-radius:99px; }
        .ce-shape-preview-line-v    { width:2px; height:42%;  border-radius:99px; }
        .ce-shape-preview-thickline { width:62%; height:5px;  border-radius:99px; }

        /* Species row thumb — small rounded image showing the actual
           species cut-out. Falls back to the emoji span when the
           species has no thumb_url. */
        .ce-species-row .thumb {
          width:34px; height:34px; flex-shrink:0;
          object-fit:contain;
          background:rgba(255,255,255,0.04);
          border-radius:8px;
          padding:2px;
        }
        .ce-elements-cat-header {
          display:flex; align-items:center; gap:10px;
          margin:6px 0 10px;
          font-size:12px; font-weight:700;
          color:var(--text-bright); text-transform:uppercase; letter-spacing:.06em;
        }
        .ce-elements-cat-back {
          background:rgba(255,255,255,0.04);
          border:1px solid rgba(255,255,255,0.10);
          color:var(--text);
          border-radius:8px; width:28px; height:28px;
          display:inline-flex; align-items:center; justify-content:center;
          cursor:pointer; font-size:11px;
          transition:background .15s ease;
        }
        .ce-elements-cat-back:hover { background:rgba(255,255,255,0.10); }

        /* Icon picker — search box + categorised grid of FA icon tiles. */
        .ce-icon-search {
          width:calc(100% - 12px);
          margin: 0 0 12px;
          padding:8px 12px;
          background:rgba(255,255,255,0.05);
          border:1px solid rgba(255,255,255,0.10);
          border-radius:8px;
          color:var(--text); font-size:12.5px;
          outline:none;
        }
        .ce-icon-search:focus {
          border-color:var(--aqua, #2dd4bf);
          background:rgba(255,255,255,0.08);
        }
        .ce-icon-picker { display:flex; flex-direction:column; gap:14px; padding-bottom:14px; }
        .ce-icon-group-title {
          font-size:10px; font-weight:800; letter-spacing:.08em; text-transform:uppercase;
          color:var(--text-dim); opacity:.8;
          margin-bottom:6px;
        }
        .ce-icon-grid {
          display:grid;
          grid-template-columns: repeat(5, 1fr);
          gap:6px;
        }
        .ce-icon-tile {
          aspect-ratio:1/1;
          background:transparent;
          border:0;
          color:var(--text); font-size:20px;
          display:flex; align-items:center; justify-content:center;
          cursor:grab;
          transition: color .12s ease, transform .12s ease;
        }
        .ce-icon-tile:hover {
          color:var(--aqua, #2dd4bf);
          transform: scale(1.08);
        }
        .ce-icon-tile:active { cursor:grabbing; }

        /* IUCN status picker — 3-up grid of canonical-colour cards. */
        .ce-iucn-grid {
          display:grid;
          grid-template-columns: repeat(3, 1fr);
          gap:8px;
          padding-bottom:14px;
        }
        .ce-iucn-card {
          aspect-ratio: 1 / 1;
          border:0; border-radius:10px;
          padding:10px 6px;
          display:flex; flex-direction:column;
          align-items:center; justify-content:center;
          gap:4px;
          cursor:pointer;
          transition: transform .12s ease, box-shadow .12s ease;
        }
        .ce-iucn-card:hover {
          transform: translateY(-1px);
          box-shadow: 0 6px 18px -8px rgba(0,0,0,0.55);
        }
        .ce-iucn-card .code {
          font-size: 18px; font-weight: 900; letter-spacing: 0.04em;
        }
        .ce-iucn-card .lbl {
          font-size: 10px; font-weight: 600; line-height: 1.15;
          text-align:center; opacity: .92;
          display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical;
          overflow:hidden;
        }

        /* Species media drill-in — 2-up grid of photo/video thumbs.
           Click a thumb to drop the asset onto the canvas. */
        .ce-species-media-grid {
          display:grid;
          grid-template-columns: repeat(2, 1fr);
          gap:8px;
          padding-bottom:14px;
        }
        .ce-species-media-tile {
          position:relative;
          aspect-ratio: 4/3;
          background:rgba(0,0,0,0.20);
          border:0; padding:0;
          border-radius:6px;
          overflow:hidden;
          cursor:pointer;
          transition: transform .12s ease;
        }
        .ce-species-media-tile:hover { transform: scale(1.03); }
        .ce-species-media-tile img,
        .ce-species-media-tile video {
          width:100%; height:100%;
          object-fit:cover;
          display:block;
        }
        .ce-species-media-badge {
          position:absolute; bottom:6px; right:6px;
          width:24px; height:24px;
          background:rgba(0,0,0,0.65);
          color:#fff;
          border-radius:99px;
          font-size:9px;
          display:flex; align-items:center; justify-content:center;
          backdrop-filter:blur(4px);
        }

        /* Sticker recents grid — auto-playing Lottie tiles. */
        .ce-sticker-grid {
          display:grid;
          grid-template-columns: repeat(3, 1fr);
          gap:6px;
          padding-bottom:14px;
        }
        .ce-sticker-tile {
          position:relative;
          aspect-ratio:1/1;
          background:transparent;
          border:0;
          padding:6px;
          cursor:pointer;
          overflow:hidden;
          transition: transform .12s ease;
        }
        .ce-sticker-tile:hover { transform: scale(1.06); }
        .ce-sticker-remove {
          position:absolute; top:2px; right:2px;
          width:18px; height:18px;
          background:rgba(0,0,0,0.55);
          border:0; color:#fff;
          border-radius:6px;
          font-size:12px; line-height:1;
          cursor:pointer;
          display:flex; align-items:center; justify-content:center;
          opacity:0; transition:opacity .12s ease;
        }
        .ce-sticker-tile:hover .ce-sticker-remove { opacity:1; }

        /* Lottie URL paste preview — sits between the URL input and
           the recents grid; lets the curator confirm the animation
           before committing it to their library. */
        .ce-lottie-preview {
          position:relative;
          width:100%; aspect-ratio:16/9;
          background:rgba(255,255,255,0.04);
          border:1px dashed rgba(255,255,255,0.18);
          border-radius:10px;
          margin-bottom:14px;
          overflow:hidden;
        }
        .ce-lottie-preview-label {
          position:absolute; top:6px; left:8px;
          font-size:9.5px; font-weight:700;
          letter-spacing:0.08em; text-transform:uppercase;
          color:var(--text-dim);
          background:rgba(0,0,0,0.30);
          padding:2px 6px; border-radius:99px;
          pointer-events:none;
        }

        /* Species card picker — dense row list, accent stripe on the
           left so the row colour matches what'll land on the canvas. */
        .ce-species-list {
          display:flex; flex-direction:column;
          gap:4px;
          padding-bottom:14px;
        }
        .ce-species-row {
          /* Borderless row — only the accent stripe on the left signals
             the species; hover lifts the text and stripe weight. */
          display:flex; align-items:center; gap:10px;
          padding:8px 0 8px 10px;
          background:transparent;
          border:0;
          cursor:pointer;
          text-align:left;
          transition: transform .12s ease, padding-left .12s ease;
        }
        .ce-species-row:hover { transform: translateX(2px); }
        .ce-species-row:hover .names strong { color: var(--text-bright); }
        .ce-species-row .emoji {
          font-size:18px; line-height:1; flex-shrink:0;
        }
        .ce-species-row .names {
          display:flex; flex-direction:column; gap:1px; min-width:0;
        }
        .ce-species-row .names strong {
          color:var(--text-bright);
          font-size:13px; font-weight:600;
          overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
        }
        .ce-species-row .names em {
          color:var(--text-dim);
          font-size:11px; font-style:italic;
          overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
        }
        .ce-element-tool {
          /* Borderless tool card — the preview tile inside is the
             visual affordance; surrounding box chrome was redundant. */
          border:0;
          background:transparent;
          color:var(--text);
          padding:0; text-align:left; cursor:pointer; font-size:12px;
          display:flex; flex-direction:column; gap:4px;
          transition: transform .12s ease;
        }
        .ce-element-tool:hover { color:var(--text-bright); transform: translateY(-1px); }
        .ce-element-tool:hover .ce-tool-preview {
          border-color: rgba(255,255,255,0.18);
          box-shadow: 0 8px 24px -10px rgba(0,0,0,0.50);
        }
        .ce-element-tool i { color:var(--aqua); margin-right:6px; width:14px; text-align:center; }
        .ce-element-tool span { display:block; font-weight:700; }
        .ce-element-tool small { display:block; color:var(--text-dim); font-size:10px; line-height:1.25; }
        /* Tool previews — real mini-renderings of each element type so
           the picker reads like a Canva-style preview grid instead of
           abstract placeholder shapes. Each preview is a small block
           with its own styled inner content (set via _ceToolPreview).
           Hover lifts the inner just slightly for a tactile read. */
        .ce-tool-preview {
          display:flex; align-items:center; justify-content:center;
          height: 64px; margin-bottom: 8px; border-radius:10px;
          background: linear-gradient(135deg, rgba(255,255,255,0.06), rgba(255,255,255,0.02));
          border:1px solid rgba(255,255,255,0.06);
          position:relative; overflow:hidden;
          padding: 8px 10px;
          color: rgba(255,255,255,0.95);
        }
        /* Text-style previews — show real type, real weight. */
        .ce-tool-preview .prv-text {
          display:block; width:100%; line-height:1.1; color: rgba(255,255,255,0.96);
          overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
        }
        .ce-tool-preview-heading    .prv-text { font-size: 22px; font-weight: 800; letter-spacing:-0.01em; }
        .ce-tool-preview-subheading .prv-text { font-size: 15px; font-weight: 600; }
        .ce-tool-preview-body_text  .prv-text {
          font-size: 9.5px; font-weight: 400; white-space: normal; line-height: 1.35;
          display:-webkit-box; -webkit-line-clamp:3; -webkit-box-orient:vertical;
        }
        .ce-tool-preview-button .prv-button {
          background: var(--aqua, #2dd4bf); color: #001a3d;
          font-weight: 800; font-size: 10.5px;
          padding: 6px 12px; border-radius: 99px;
          letter-spacing: 0.04em; text-transform: uppercase;
        }
        /* Image / video — mini landscape so it visibly says "photo". */
        .ce-tool-preview-image,
        .ce-tool-preview-video {
          padding: 0; background: transparent; border: 0;
        }
        .ce-tool-preview-image .prv-photo,
        .ce-tool-preview-video .prv-photo {
          display:block; width:100%; height:100%; border-radius:10px; overflow:hidden;
          /* Sunset gradient + soft glowing sun in the upper right. */
          background:
            radial-gradient(circle at 78% 28%, #fef3c7 0%, rgba(254,243,199,0.6) 4%, transparent 18%),
            linear-gradient(180deg, #fbbf24 0%, #fb7185 35%, #1e3a8a 75%, #0f172a 100%);
          position: relative;
        }
        .ce-tool-preview-image .prv-photo::before,
        .ce-tool-preview-video .prv-photo::before {
          /* Mountain silhouette via clip-path, anchored to the bottom. */
          content: ""; position: absolute; left:0; right:0; bottom:0;
          height: 52%;
          background: #0b1424;
          clip-path: polygon(
            0% 100%, 0% 55%, 14% 30%, 28% 60%, 42% 18%, 58% 50%,
            72% 28%, 86% 58%, 100% 38%, 100% 100%
          );
        }
        .ce-tool-preview-video .prv-play {
          position:absolute; top:50%; left:50%; transform:translate(-50%,-50%);
          width:22px; height:22px; border-radius:50%;
          background: rgba(0,0,0,0.55);
          color:#fff; font-size:9px;
          display:flex; align-items:center; justify-content:center;
          backdrop-filter: blur(2px);
        }
        /* Logo — sponsor-style mark on a tinted backdrop. */
        .ce-tool-preview-logo .prv-logo {
          font-weight: 900; font-size: 12px; letter-spacing: 0.18em;
          color: rgba(255,255,255,0.95);
          background: linear-gradient(135deg, var(--aqua, #2dd4bf), #3b82f6);
          padding: 8px 14px; border-radius: 6px;
        }
        /* QR — tiny grid of dots that reads as a code at a glance. */
        .ce-tool-preview-qr .prv-qr {
          display:grid; grid-template-columns: repeat(7, 1fr); gap:1.5px;
          width:36px; height:36px;
          padding:3px; background:#fff; border-radius:4px;
        }
        .ce-tool-preview-qr .prv-qr i { background:#0f172a; border-radius:1px; }
        /* Progress bar — actual track + fill + label. */
        .ce-tool-preview-progress {
          flex-direction: column; align-items: stretch; gap: 5px;
        }
        .ce-tool-preview-progress .prv-progress-label {
          font-size: 9.5px; font-weight: 700; letter-spacing: 0.06em;
          color: rgba(255,255,255,0.78);
          display:flex; justify-content:space-between;
        }
        .ce-tool-preview-progress .prv-progress {
          height: 6px; border-radius: 99px;
          background: rgba(255,255,255,0.18);
          overflow: hidden;
        }
        .ce-tool-preview-progress .prv-progress-fill {
          height: 100%; width: 62%;
          background: var(--aqua, #2dd4bf);
          border-radius: 99px;
        }
        /* Stat — big tabular number + label like real cp-stat. */
        .ce-tool-preview-stat {
          flex-direction: column; gap: 0; align-items: flex-start;
        }
        .ce-tool-preview-stat .prv-stat-val {
          font-size: 22px; font-weight: 800;
          font-variant-numeric: tabular-nums;
          line-height: 1;
        }
        .ce-tool-preview-stat .prv-stat-lbl {
          font-size: 9.5px; color: rgba(255,255,255,0.55);
          letter-spacing: 0.08em; text-transform: uppercase;
          margin-top: 4px;
        }
        /* Countdown — tabular-nums so digits stay column-aligned. */
        .ce-tool-preview-countdown .prv-countdown {
          font-variant-numeric: tabular-nums;
          font-size: 18px; font-weight: 800; letter-spacing: 0.02em;
          color: var(--aqua, #2dd4bf);
        }
        /* Shape — solid rounded rect representing what a shape element looks like. */
        .ce-tool-preview-shape .prv-shape {
          width: 56%; height: 56%;
          background: var(--aqua, #2dd4bf);
          border-radius: 8px;
        }
        .ce-left-canvas-actions {
          display:grid; grid-template-columns:1fr 1fr; gap:7px; margin-top:10px;
        }
        .ce-left-canvas-actions button {
          min-height:34px; border-radius:10px; border:1px solid var(--border);
          background:rgba(255,255,255,0.04); color:var(--text); font-size:11px; cursor:pointer;
        }
        .ce-left-canvas-actions button:hover { border-color:var(--aqua); color:var(--aqua); }
        .ce-inspector-empty {
          padding:18px 14px; border:1px dashed var(--border); border-radius:14px;
          color:var(--text-dim); font-size:12px; line-height:1.45; background:rgba(255,255,255,0.03);
        }
        .ce-inspector-summary {
          margin:4px 0 14px; padding:14px; border:1px solid rgba(255,255,255,0.08); border-radius:16px;
          background:rgba(255,255,255,0.035);
        }
        .ce-inspector-kicker {
          font-size:10px; font-weight:800; letter-spacing:.08em; text-transform:uppercase;
          color:var(--text-dim); margin-bottom:3px;
        }
        .ce-inspector-title {
          font-size:14px; font-weight:800; color:var(--text-bright); display:flex; justify-content:space-between; gap:8px;
        }
        .ce-inspector-section {
          border-top:1px solid var(--border); padding:0; margin:0;
        }
        .ce-inspector-section summary {
          list-style:none; cursor:pointer; padding:13px 2px; display:flex; align-items:center; justify-content:space-between;
          color:var(--text-bright); font-size:12px; font-weight:800;
        }
        .ce-inspector-section summary::-webkit-details-marker { display:none; }
        .ce-inspector-section summary::after { content:'+'; color:var(--text-dim); font-size:16px; font-weight:700; }
        .ce-inspector-section[open] summary::after { content:'–'; }
        .ce-inspector-section-body { padding:0 0 14px; }
        .ce-control-grid-2 { display:grid; grid-template-columns:1fr 1fr; gap:8px; }
        .ce-control-row { display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
        .ce-icon-row { display:flex; gap:6px; flex-wrap:wrap; }
        .ce-icon-row .btn, .ce-chip-row .btn { min-width:30px; justify-content:center; }
        .ce-chip-row { display:flex; gap:6px; flex-wrap:wrap; margin-top:8px; }
        .ce-inspector-section .form-group { margin:0 0 10px !important; }
        .ce-right-pane[data-pane="content"] .ce-rail-microcopy {
          margin:2px 10px 12px;
          font-size:11px;
        }
        .ce-right-pane[data-pane="content"] .ce-content-fields {
          padding:0 12px 16px;
        }
        .ce-right-pane[data-pane="content"] input,
        .ce-right-pane[data-pane="content"] textarea,
        .ce-right-pane[data-pane="content"] select {
          border-radius:10px;
          background:rgba(255,255,255,0.045);
          border-color:rgba(255,255,255,0.10);
        }
        .ce-right-pane[data-pane="content"] label {
          letter-spacing:.04em;
        }

        /* Phase 47: orientation chip buttons in the screen editor.
           Radio is hidden; the label chrome becomes the toggle. */
        .screen-orient-opt {
          display: flex; align-items: center; justify-content: center; gap: 8px;
          padding: 10px 12px; border-radius: 10px;
          background: var(--surface);
          border: 1px solid var(--border);
          cursor: pointer;
          font-size: 12px; font-weight: 600; color: var(--text-dim);
          transition: all .15s ease;
        }
        .screen-orient-opt:hover { color: var(--text-bright); border-color: rgba(241, 245, 249,0.35); }
        .screen-orient-opt input { position: absolute; opacity: 0; pointer-events: none; }
        .screen-orient-opt:has(input:checked) {
          background: rgba(241, 245, 249, 0.1);
          border-color: rgba(241, 245, 249, 0.6);
          color: var(--text-bright);
          box-shadow: 0 0 0 1px rgba(241, 245, 249, 0.3) inset;
        }
        .screen-orient-opt:has(input:disabled) {
          opacity: 0.5; cursor: not-allowed;
        }

        /* Phase 24: aspect-size rules neutralised. The three ce-bezel-*
           modes (landscape / portrait / mobile) own all sizing now —
           letting the old .ce-aspect-* rules also apply causes width/
           aspect-ratio conflicts when swapping device modes. Shape is
           driven by the bezel classes; the aspect class stays on the
           element only so the underlying layout engine knows its
           internal aspect. */
        .ce-aspect-16-9, .ce-aspect-9-16, .ce-aspect-1-1 { /* noop */ }

        /* Phase 27: five device frames matching the surface buckets.
           Phone → iPhone bezel.
           Tablet → slim bezel (14-24" monitor).
           Standard → TV bezel on a stand.
           Large → bigger TV bezel (slightly thicker).
           Portrait → vertical display bezel. */
        .ce-preview-frame-wrapper {
          display: flex; align-items: center; justify-content: center;
          padding: 32px; min-height: 0; overflow: auto;
        }
        .ce-preview-frame.ce-device-phone,
        .ce-preview-frame.ce-device-tablet,
        .ce-preview-frame.ce-device-standard,
        .ce-preview-frame.ce-device-large,
        .ce-preview-frame.ce-device-portrait,
        /* legacy aliases */
        .ce-preview-frame.ce-device-landscape,
        .ce-preview-frame.ce-device-mobile {
          aspect-ratio: auto;
        }

        /* Phase 31: bezels render at INTRINSIC pixel size. JS computes
           a --ce-preview-scale based on available pane space and
           transform: scale() shrinks the rendered frame to fit without
           changing the iframe's internal dimensions. That way container
           queries inside the kiosk fire at the TRUE size (3840 for
           Large, not the 1800 the old clamp produced) and the curator
           sees the real Large layout visually scaled down. */
        .ce-preview-frame {
          transform-origin: top left;
          transform: scale(var(--ce-preview-scale, 1));
        }

        /* Phase 56: bezel chrome stripped entirely. Each device class
           still sets its intrinsic pixel size (so kiosk container
           queries fire at the real 1920/3840/etc. width and the
           transform-scale in JS can shrink it to fit the pane) but
           no longer draws the chunky device frame. The preview is
           now a flat rectangle on the editor surface with a single
           1px border from .ce-preview-frame above. No box-shadow,
           no inset highlights, no faux phone notch, no chin.
           Notch/side-button detail + heavy drop-shadow belonged in
           a 'presentation mode' later; they were adding visual
           weight the editor didn't need. */
        /* Phase 58e: device-class rules set ONLY the intrinsic
           dimensions + corner radius now. The flat 1px box-shadow
           that used to live here was overriding the photoreal
           bezel painted by the base .ce-preview-frame selector,
           leaving curators with a pancake-flat preview. Bezel
           styling now flows from the base selector for every
           device. */
        .ce-bezel-phone .ce-preview-frame,
        .ce-bezel-mobile .ce-preview-frame /* legacy alias */ {
          width: 390px; height: 844px;
          padding: 0; border: 0; border-radius: 24px;
          position: relative;
          background: #000;
          flex-shrink: 0;
        }
        .ce-bezel-tablet .ce-preview-frame {
          width: 1024px; height: 768px;
          padding: 0; border: 0; border-radius: 12px;
          position: relative;
          flex-shrink: 0;
        }
        .ce-bezel-standard .ce-preview-frame,
        .ce-bezel-landscape .ce-preview-frame /* legacy alias */ {
          width: 1920px; height: 1080px;
          padding: 0; border: 0; border-radius: 10px;
          position: relative;
          flex-shrink: 0;
        }

        /* Large kiosk — intrinsic 3840×2160 (50"+ lobby / 4K).
           Scaled down visually to fit the pane, but the iframe inside
           actually renders at 3840 so container queries fire Large. */
        .ce-bezel-large .ce-preview-frame {
          width: 3840px; height: 2160px;
          padding: 0; border: 0; border-radius: 10px;
          position: relative;
          flex-shrink: 0;
        }
        .ce-bezel-portrait .ce-preview-frame {
          width: 1080px; height: 1920px;
          padding: 0; border: 0; border-radius: 10px;
          position: relative;
          flex-shrink: 0;
        }

        /* The wrapper needs to accommodate the scaled frame. When the frame
           is scaled < 1 its bounding box is still the intrinsic size, so
           we use a wrapper-level approach: set margin-bottom compensation
           via JS. Simpler: overflow:hidden on the wrapper + place frame
           with top-left origin so only the visible-scaled area shows. */
        .ce-preview-frame-wrapper {
          /* Phase 58e: padding bumped from 24px → 80px so the
             32px+ bezel + drop-shadow have room to render outside
             the frame's box without being clipped by overflow.
             overflow:hidden remains so a wildly-misscaled frame
             can't bleed into the surrounding panes. */
          overflow: hidden;
          justify-content: center; align-items: center;
          padding: 80px;
        }

        /* Active chip = brand primary */
        .ce-device-toggle .ce-chip.active {
          background: var(--brand-primary);
          color: #fff; border-color: transparent;
        }

        /* Phase 20: guides overlay — rule-of-thirds + central safe zone.
           Rendered over the preview frame when toggled on. Pure visual
           aid; doesn't affect layout. */
        .ce-preview-frame.ce-guides-on::after {
          content: ''; position: absolute; inset: 0; pointer-events: none; z-index: 9;
          background:
            linear-gradient(to right, transparent 33%, rgba(255,107,74,0.25) 33%, rgba(255,107,74,0.25) calc(33% + 1px), transparent calc(33% + 1px)),
            linear-gradient(to right, transparent 66%, rgba(255,107,74,0.25) 66%, rgba(255,107,74,0.25) calc(66% + 1px), transparent calc(66% + 1px)),
            linear-gradient(to bottom, transparent 33%, rgba(255,107,74,0.25) 33%, rgba(255,107,74,0.25) calc(33% + 1px), transparent calc(33% + 1px)),
            linear-gradient(to bottom, transparent 66%, rgba(255,107,74,0.25) 66%, rgba(255,107,74,0.25) calc(66% + 1px), transparent calc(66% + 1px));
        }

        /* ── Canvas-top pill bar (port of cms-original lines 6157-6394) ─
           Verbatim copy of the original CMS's elevated, pill-shaped
           toolbar that floats above the canvas with all per-element
           controls. Light only when something is selected; sub-labels
           tag input groups (LABEL / URL / FILL / etc.); buttons,
           selects, and number/text inputs all share the same rounded
           pill aesthetic. */
        .ce-canvas-top-toolbar {
          min-height:48px; margin:10px auto -16px; padding:6px 14px;
          width: max-content; max-width: calc(100% - 32px);
          align-self: center;
          display:inline-flex; align-items:center; justify-content:center; gap:6px; flex-wrap:wrap;
          border:1px solid rgba(255,255,255,0.10); border-radius:999px;
          background:linear-gradient(180deg, rgba(20,30,46,0.94), rgba(8,14,24,0.94));
          backdrop-filter:saturate(1.4) blur(18px);
          -webkit-backdrop-filter:saturate(1.4) blur(18px);
          box-shadow:
            0 1px 0 rgba(255,255,255,0.06) inset,
            0 0 0 1px rgba(0,0,0,0.25),
            0 18px 44px rgba(0,0,0,0.45),
            0 4px 12px rgba(0,0,0,0.35);
          z-index:3;
        }
        .ce-canvas-top-toolbar.is-empty { opacity:.72; }
        .ce-canvas-top-toolbar .ce-toolbar-sublabel {
          font-size: 9.5px; font-weight: 800; letter-spacing: 1.4px;
          color: var(--text-dim); text-transform: uppercase;
          padding: 0 6px 0 2px;
        }
        .ce-canvas-top-toolbar button,
        .ce-canvas-top-toolbar select,
        .ce-canvas-top-toolbar input[type="color"] {
          height:30px; border-radius:999px; border:1px solid rgba(255,255,255,0.12);
          background:rgba(255,255,255,0.06); color:var(--text); font-size:11px;
        }
        .ce-canvas-top-toolbar button { padding:0 10px; cursor:pointer; }
        .ce-canvas-top-toolbar button:hover { border-color:var(--aqua, #2dd4bf); color:var(--aqua, #2dd4bf); }
        .ce-canvas-top-toolbar select { padding:0 28px 0 10px; max-width:150px; }
        .ce-canvas-top-toolbar input[type="color"] { width:34px; padding:3px; }
        .ce-canvas-top-toolbar .ce-toolbar-label {
          font-size:11px; font-weight:800; color:var(--text-dim); text-transform:capitalize; padding:0 8px;
        }
        .ce-canvas-top-toolbar .ce-toolbar-sep { width:1px; height:20px; background:rgba(255,255,255,0.10); margin:0 2px; }
        .ce-canvas-top-toolbar input[type="number"] {
          height:30px; border-radius:999px;
          border:1px solid rgba(255,255,255,0.12);
          background:rgba(255,255,255,0.06); color:var(--text);
          font-size:11px; padding:0 10px; text-align:center;
          min-width: 64px; width: 64px;
        }
        .ce-canvas-top-toolbar input[type="number"]:focus {
          border-color:var(--aqua, #2dd4bf); outline:0;
        }
        .ce-canvas-top-toolbar input[type="text"],
        .ce-canvas-top-toolbar input[type="url"],
        .ce-canvas-top-toolbar input[type="search"],
        .ce-canvas-top-toolbar input[type="email"],
        .ce-canvas-top-toolbar input[type="datetime-local"] {
          height: 30px; border-radius: 999px;
          border: 1px solid rgba(255,255,255,0.12);
          background: rgba(255,255,255,0.06);
          color: var(--text);
          font-size: 11px; padding: 0 12px;
          font-family: inherit;
          transition: border-color .12s ease, background .12s ease;
        }
        .ce-canvas-top-toolbar input[type="text"]::placeholder,
        .ce-canvas-top-toolbar input[type="url"]::placeholder,
        .ce-canvas-top-toolbar input[type="search"]::placeholder,
        .ce-canvas-top-toolbar input[type="email"]::placeholder {
          color: rgba(241,245,249,0.36);
        }
        .ce-canvas-top-toolbar input[type="text"]:hover,
        .ce-canvas-top-toolbar input[type="url"]:hover,
        .ce-canvas-top-toolbar input[type="search"]:hover,
        .ce-canvas-top-toolbar input[type="email"]:hover,
        .ce-canvas-top-toolbar input[type="datetime-local"]:hover {
          border-color: rgba(255,255,255,0.20);
          background: rgba(255,255,255,0.08);
        }
        .ce-canvas-top-toolbar input[type="text"]:focus,
        .ce-canvas-top-toolbar input[type="url"]:focus,
        .ce-canvas-top-toolbar input[type="search"]:focus,
        .ce-canvas-top-toolbar input[type="email"]:focus,
        .ce-canvas-top-toolbar input[type="datetime-local"]:focus {
          border-color: var(--aqua, #2dd4bf);
          outline: 0;
          background: rgba(255,255,255,0.10);
        }
        .ce-canvas-top-toolbar button.is-active {
          background: var(--aqua-glow, rgba(45,212,191,0.18));
          color: var(--aqua, #5eead4);
          border-color: rgba(45,212,191,0.4);
        }
        .ce-canvas-top-toolbar .ce-toolbar-advanced {
          position: relative; display: inline-flex;
        }
        .ce-canvas-top-toolbar .ce-toolbar-advanced > summary {
          list-style: none; cursor: pointer;
          height: 30px; min-width: 30px; padding: 0 10px;
          display: inline-flex; align-items: center; justify-content: center;
          background: rgba(241,245,249,0.04);
          border: 1px solid rgba(241,245,249,0.08);
          border-radius: 999px;
          color: var(--text-dim);
          transition: background .12s ease, color .12s ease, border-color .12s ease;
        }
        .ce-canvas-top-toolbar .ce-toolbar-advanced > summary::-webkit-details-marker { display: none; }
        .ce-canvas-top-toolbar .ce-toolbar-advanced > summary::marker { content: ''; }
        .ce-canvas-top-toolbar .ce-toolbar-advanced > summary:hover {
          background: rgba(241,245,249,0.10);
          color: var(--text-bright);
          border-color: rgba(241,245,249,0.16);
        }
        .ce-canvas-top-toolbar .ce-toolbar-advanced[open] > summary {
          background: rgba(45,212,191,0.18);
          color: var(--aqua, #2dd4bf);
          border-color: rgba(45,212,191,0.4);
        }
        .ce-canvas-top-toolbar .ce-toolbar-advanced-popover {
          position: absolute; top: calc(100% + 10px); right: 0;
          z-index: 1500; min-width: 220px;
          padding: 12px;
          display: flex; flex-direction: column; gap: 10px;
          background: linear-gradient(180deg, rgba(20,30,46,0.96), rgba(8,14,24,0.96));
          border: 1px solid rgba(255,255,255,0.10);
          border-radius: 12px;
          backdrop-filter: saturate(1.4) blur(18px);
          -webkit-backdrop-filter: saturate(1.4) blur(18px);
          box-shadow:
            0 1px 0 rgba(255,255,255,0.06) inset,
            0 0 0 1px rgba(0,0,0,0.25),
            0 18px 44px rgba(0,0,0,0.45);
        }
        .ce-canvas-top-toolbar .ce-toolbar-advanced-popover label {
          display: flex; align-items: center; justify-content: space-between;
          gap: 12px;
          font-size: 11px; font-weight: 600; color: var(--text-dim);
          text-transform: uppercase; letter-spacing: 0.06em;
        }
        .ce-canvas-top-toolbar .ce-toolbar-advanced-popover input[type="number"] {
          width: 80px; min-width: 80px;
        }

/* ───────────────────────────────────────────────────────────────────
   Phone-mode bezel — Sarah feedback bdd90bb4: "when selecting the
   phone icon, can we have it display on an actual iphone frame?"
   The frame is pure CSS (no SVG asset) so it scales cleanly with the
   curator's zoom. Wraps the existing .ce-preview-frame; the frame
   itself stays free of phone-specific styling so non-phone modes
   look unchanged.
   ─────────────────────────────────────────────────────────────────── */
.ce-preview-frame.ce-aspect-iphone {
  /* iPhone 15-class aspect (≈19.5:9). The exact figure is 9 / 19.5 but
     CSS aspect-ratio accepts decimals fine. */
  aspect-ratio: 9 / 19.5 !important;
  height: 92% !important;
  width: auto !important;
  max-width: 100% !important;
  max-height: 92% !important;
  /* Drop the kiosk's dark interior so the phone bezel below shows
     through the rounded screen mask. */
  background: #000 !important;
  border-radius: 36px;
  overflow: hidden;
  box-shadow:
    0 0 0 4px rgba(255,255,255,0.04),  /* outer halo */
    0 0 0 10px #1c1d22,                /* aluminum band */
    0 0 0 11px #000,                   /* outer black ring */
    0 24px 60px rgba(0,0,0,0.55);      /* lifted shadow */
}
/* Dynamic Island — pill-shaped pseudo-element pinned to the top of
   the screen mask. Sized + positioned to match the iPhone 15 visual
   weight (≈30% wide, ≈4% tall, ≈2.5% from top). */
.ce-preview-frame.ce-aspect-iphone::before {
  content: '';
  position: absolute;
  top: 2.2%;
  left: 50%;
  transform: translateX(-50%);
  width: 32%;
  height: 3.8%;
  background: #000;
  border-radius: 999px;
  z-index: 50;
  pointer-events: none;
  box-shadow: 0 0 0 1px rgba(255,255,255,0.04) inset;
}
/* Side buttons — tiny visual cues (volume + power) to make the bezel
   feel like a real device. Positioned just outside the screen mask. */
.ce-preview-frame.ce-aspect-iphone::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  border-radius: 36px;
  /* Side buttons drawn with a stack of inset box-shadows so the
     "metal" frame reads as one continuous element. */
  box-shadow:
    inset 4px 28% 0 -2px rgba(255,255,255,0.06),  /* power button hint */
    inset -4px 18% 0 -2px rgba(255,255,255,0.06); /* volume button hint */
  z-index: 49;
}
.ce-preview-frame-wrapper.ce-bezel-phone {
  /* Centre + breathe — the phone is much taller than wide, so the
     wrapper needs vertical padding to keep the bezel off the toolbar. */
  padding: 24px 0;
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
}

/* Overlay-card thumbnails (Sarah feedback 7028ef97). The renderer's
   .cp-overlay strip uses px-based font sizes calibrated for a 1920px-
   wide canvas — at thumbnail scale (~250px) the text becomes microscopic.
   Override to em-relative sizes inside the thumbnail card so the strip
   stays legible. The parent sets font-size:6px which scales the em values
   to a thumbnail-appropriate weight without redoing the whole renderer. */
.ce-thumb-overlay-card .cp-slide,
.ce-thumb-overlay-card .cp-overlay {
  font-size: inherit !important;
}
.ce-thumb-overlay-card .cp-ov-cons-title {
  font-size: 1.5em !important;
  font-weight: 700;
  letter-spacing: 0.02em;
}
.ce-thumb-overlay-card .cp-ov-cons-stat {
  font-size: 1.2em !important;
  display: inline-flex;
  gap: 0.4em;
  align-items: baseline;
}
.ce-thumb-overlay-card .cp-ov-cons-stat-value {
  font-size: 1.6em !important;
  font-weight: 800;
}
.ce-thumb-overlay-card .cp-ov-cons-stat-label {
  font-size: 1em !important;
  opacity: 0.7;
}
.ce-thumb-overlay-card .cp-ov-cons-pct {
  font-size: 1.4em !important;
  font-weight: 700;
}
.ce-thumb-overlay-card .cp-ov-cons-track {
  height: 3px;
  border-radius: 2px;
}
.ce-thumb-overlay-card .cp-ov-pill-label,
.ce-thumb-overlay-card .cp-ov-pill-clock,
.ce-thumb-overlay-card .cp-ov-corner-title,
.ce-thumb-overlay-card .cp-ov-ticker-text {
  font-size: 1.3em !important;
}
.ce-thumb-overlay-card .cp-overlay {
  padding: 0.6em 1em;
}
.ce-thumb-overlay-card .cp-overlay.cp-overlay-pos-top    { top: 5%;    }
.ce-thumb-overlay-card .cp-overlay.cp-overlay-pos-bottom { bottom: 5%; }
