/* =========================================================================
   ChordHero Visual Editor — overlay styles.
   All selectors are prefixed `ve-` to avoid colliding with site CSS.
   ========================================================================= */

:root {
    --ve-brand:    #FF5733;   /* ChordHero orange */
    --ve-accent:   #1E40AF;   /* cobalt for active editor state */
    --ve-cream:    #fdf6ee;
    --ve-ink:      #1a1a1a;
    --ve-muted:    #6b6b6b;
    --ve-border:   #e6e1d8;
    --ve-success:  #1f8a4c;
    --ve-danger:   #c0392b;
    --ve-overlay:  rgba(15, 17, 22, 0.85);
}

/* =========================================================================
   Editable element hover affordance.
   When the editor is active, every [data-cms-id] element gets a dashed
   outline on hover plus a small ✎ badge. Clicking inside the box does
   nothing extra (preserves normal site behaviour); double-clicking opens
   the modal.
   ========================================================================= */
body.ve-active [data-cms-id] {
    /* NOTE: deliberately NOT setting position:relative here. Some
       editable elements (notably SliderPage) rely on their own
       position:fixed/absolute and we'd break their layout if we
       overrode it. The ensureDragHandle() helper in editor.js sets
       position:relative only on static-positioned elements, on first
       hover — which is the only time it's actually needed (to anchor
       the ✎ badge and ⋮⋮ handle). */
    transition: outline 0.12s ease, box-shadow 0.12s ease;
}
body.ve-active [data-cms-id]:hover {
    outline: 2px dashed var(--ve-accent);
    outline-offset: 4px;
    cursor: pointer;
}
/* While a bubble is open, suppress hover affordances on every other
   editable element. Otherwise their drag handles (which have higher
   z-index than the bubble) would poke through over the bubble. */
body.ve-editing [data-cms-id]:hover {
    outline: none;
    cursor: default;
}
body.ve-editing [data-cms-id] > .ve-drag-handle,
body.ve-editing [data-cms-id] .ve-drag-handle {
    opacity: 0 !important;
    pointer-events: none;
}
body.ve-editing [data-cms-id]:hover::after {
    display: none;
}
body.ve-active [data-cms-id]:hover::after {
    content: "✎ " attr(data-cms-element);
    position: absolute;
    top: 6px;
    right: 6px;
    background: var(--ve-accent);
    color: #fff;
    font: 600 11px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    padding: 5px 8px;
    border-radius: 4px;
    pointer-events: none;
    z-index: 999998;
    letter-spacing: 0.02em;
}

/* Drag handle (⋮⋮) — mirror of the ✎ pencil but on the left.
   Only this is draggable; the rest of the element is not.
   Avoids breaking normal page interaction. */
body.ve-active [data-cms-id] > .ve-drag-handle,
body.ve-active [data-cms-id] .ve-drag-handle {
    position: absolute;
    top: 6px;
    left: 6px;
    background: var(--ve-brand);
    color: #fff;
    font: 700 12px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    padding: 6px 8px;
    border-radius: 4px;
    cursor: grab;
    z-index: 999998;
    opacity: 0;
    transition: opacity 0.12s;
    user-select: none;
}
body.ve-active [data-cms-id]:hover > .ve-drag-handle {
    opacity: 1;
}
.ve-drag-handle:active { cursor: grabbing; }

/* News article pages: per-element editing is suppressed in favor of the
   single Edit Article entry point in the dock. Outlines, ✎ pseudo-element
   pills, and drag handles all disappear so the page reads as one unit. */
body.ve-news-article [data-cms-id]:hover {
    outline: none;
    cursor: default;
}
body.ve-news-article [data-cms-id]:hover::after { display: none; }
body.ve-news-article .ve-drag-handle { display: none !important; }

/* During an active drag */
body.ve-dragging [data-cms-id] {
    pointer-events: auto !important;
}
body.ve-dragging [data-cms-id].ve-drag-source {
    opacity: 0.4;
}

/* Toast at the top of the viewport. Used by drag/drop handlers when a
   user gesture is silently rejected (drop on non-sibling, no change,
   preflight slow, etc.). Without it those cases looked broken. */
.ve-toast {
    position: fixed;
    top: 16px;
    left: 50%;
    transform: translate(-50%, -120%);
    padding: 10px 18px;
    border-radius: 6px;
    font-size: 13px;
    font-weight: 500;
    color: #fff;
    background: var(--ve-ink);
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.18);
    pointer-events: none;
    opacity: 0;
    transition: transform 220ms cubic-bezier(0.16, 1, 0.3, 1),
                opacity 220ms ease-out;
    z-index: 1000000;
    max-width: 80vw;
    text-align: center;
}
.ve-toast.ve-toast-visible {
    transform: translate(-50%, 0);
    opacity: 1;
}
.ve-toast.ve-toast-error    { background: #dc3545; }
.ve-toast.ve-toast-success  { background: #198754; }
.ve-toast.ve-toast-info     { background: #0d6efd; }

/* Brief flash on the moved card after a successful reorder. Lets the user
   see exactly which element just landed in its new spot. */
[data-cms-id].ve-just-reordered {
    animation: ve-just-reordered-flash 0.9s ease-out;
}
@keyframes ve-just-reordered-flash {
    0%   { box-shadow: 0 0 0 4px rgba(255, 87, 51, 0.6); }
    100% { box-shadow: 0 0 0 0 rgba(255, 87, 51, 0); }
}
body.ve-dragging [data-cms-id].ve-drop-target {
    outline: 2px solid var(--ve-brand);
    outline-offset: 4px;
}
body.ve-dragging [data-cms-id].ve-drop-target.ve-drop-before::before {
    content: "";
    position: absolute;
    left: 0; right: 0;
    top: -8px;
    height: 4px;
    background: var(--ve-brand);
    border-radius: 2px;
    box-shadow: 0 0 8px rgba(255, 87, 51, 0.6);
    z-index: 999997;
}
body.ve-dragging [data-cms-id].ve-drop-target.ve-drop-after::after {
    content: "";
    position: absolute;
    left: 0; right: 0;
    bottom: -8px;
    height: 4px;
    background: var(--ve-brand);
    border-radius: 2px;
    box-shadow: 0 0 8px rgba(255, 87, 51, 0.6);
    z-index: 999997;
}
/* When a nested element is hovered, only highlight the nearest editable
   ancestor (handled in JS via stopPropagation on the hover target). */

/* =========================================================================
   Floating dock — small pill in the corner. Click to expand into a panel
   showing status / timer / lock; click outside or X to collapse.
   ========================================================================= */
.ve-dock {
    position: fixed;
    top: 12px;
    right: 12px;
    z-index: 999990;
    font: 600 12px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    color: #fff;
}
.ve-dock-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: var(--ve-accent);
    border: none;
    border-radius: 999px;
    padding: 8px 12px;
    cursor: pointer;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.22);
    color: #fff;
    font: inherit;
    transition: background 0.15s, transform 0.15s;
}
.ve-dock-pill:hover { background: #1c3aa3; transform: translateY(-1px); }
.ve-dock-pill::before {
    content: "✎";
    font-size: 14px;
    line-height: 1;
}
.ve-dock-pill .ve-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--ve-success);
    margin-left: 2px;
    box-shadow: 0 0 6px rgba(31, 138, 76, 0.6);
}

.ve-dock-panel {
    margin-top: 8px;
    background: #fff;
    color: var(--ve-ink);
    border: 1px solid var(--ve-border);
    border-radius: 10px;
    box-shadow: 0 12px 36px rgba(0, 0, 0, 0.18);
    padding: 14px 16px;
    min-width: 240px;
    font: 500 13px/1.4 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    display: none;
}
.ve-dock.expanded .ve-dock-panel { display: block; }
.ve-dock-panel-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 8px;
}
.ve-dock-panel-title {
    font-weight: 600;
    color: var(--ve-ink);
    font-size: 13px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.ve-dock-panel-close {
    background: transparent; border: none; cursor: pointer;
    color: var(--ve-muted); font-size: 18px; line-height: 1; padding: 0;
}
.ve-dock-panel-close:hover { color: var(--ve-ink); }
.ve-dock-panel .ve-dock-timer {
    color: var(--ve-muted);
    font-size: 12px;
    margin-bottom: 12px;
}
.ve-dock-panel button.ve-button {
    width: 100%;
}
/* Inline Promote ALL panel — always visible in the dock; the password
   itself is the friction layer (a stray click in the dock can't ship
   anything without re-entering the editor password). */
.ve-dock-promote-confirm {
    background: #fff8e6;
    border: 1px solid #f4b942;
    border-radius: 6px;
    padding: 10px;
    margin-bottom: 8px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.ve-dock-promote-help {
    font-size: 11px;
    color: #6b5a1f;
    line-height: 1.4;
}
.ve-dock-promote-pw {
    padding: 6px 10px;
    border: 1.5px solid #d8c895;
    border-radius: 5px;
    font-size: 13px;
    font-family: inherit;
    background: #fff;
}
.ve-dock-promote-pw:focus { outline: none; border-color: #198754; }
.ve-dock-promote-status {
    font-size: 11px;
    color: var(--ve-muted);
    min-height: 14px;
}
.ve-dock-promote-status.success { color: #198754; }
.ve-dock-promote-status.warn    { color: #b06b00; }
.ve-dock-promote-status.error   { color: var(--ve-danger); }
.ve-dock-promote-actions {
    display: flex;
}
/* Single Promote button now carries the full "this is the deploy CTA"
   weight — full-width inside the panel, slightly taller than the
   surrounding dock buttons so the action reads as confident. Solid
   green to match the deploy semantics (the icon-button .ve-button-promote
   rule only applies under .ve-button-icon, which this button isn't). */
.ve-dock-promote-actions .ve-button {
    flex: 1;
    width: auto;
    font-size: 13px;
    font-weight: 600;
    padding: 9px 10px;
    background: #198754;
    color: #fff;
    border-color: #198754;
}
.ve-dock-promote-actions .ve-button:hover {
    background: #14693f;
    border-color: #14693f;
}
.ve-dock-promote-actions .ve-button[disabled] {
    background: #198754;
    border-color: #198754;
    opacity: 0.55;
    cursor: wait;
}
/* Discard ALL — amber, visually distinct from green Promote so a tired
   operator doesn't confuse the two. Lower urgency than the red Lock-now
   below it. Staging-only action, so no inline confirm panel — just a
   browser confirm() at click time. */
.ve-dock-discard-all {
    background: #b06b00 !important;
    color: #fff !important;
    border-color: #b06b00 !important;
    margin-bottom: 4px;
    font-weight: 600;
}
.ve-dock-discard-all:hover {
    background: #8a5300 !important;
    border-color: #8a5300 !important;
}
.ve-dock-discard-all[disabled] {
    opacity: 0.6;
    cursor: not-allowed;
}
.ve-dock-discard-status {
    font-size: 11px;
    color: var(--ve-muted);
    min-height: 14px;
    margin-bottom: 8px;
}
.ve-dock-discard-status.success { color: #198754; }
.ve-dock-discard-status.error   { color: var(--ve-danger); }

/* =========================================================================
   Edit bubble — anchored near the double-clicked element.
   Resizable (browser-native), draggable by header, body scrolls.
   ========================================================================= */
.ve-bubble {
    /* Absolute (not fixed) so the bubble scrolls with the element it's
       anchored to. Coordinates are written in document space by JS.
       Wider default + max so the language chip row (5 langs incl. EN/JA/
       繁/简/KR) fits on one line and the icon-button footer doesn't wrap.
       resize: both is enabled so authors can shrink it back if they want. */
    position: absolute;
    z-index: 999995;
    width: 720px;
    min-width: 420px;
    max-width: min(960px, calc(100vw - 24px));
    min-height: 240px;
    max-height: calc(100vh - 24px);
    background: #fff;
    border: 1px solid var(--ve-border);
    border-radius: 12px;
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.32);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    resize: both;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
    color: var(--ve-ink);
}
/* Resize handle is the bottom-right; the resize CSS shows native browser
   handle but it's invisible-ish. Add a faint visual hint. */
.ve-bubble::after {
    content: "";
    position: absolute;
    right: 2px;
    bottom: 2px;
    width: 10px;
    height: 10px;
    border-right:  2px solid var(--ve-border);
    border-bottom: 2px solid var(--ve-border);
    pointer-events: none;
    opacity: 0.7;
}

.ve-modal-header {
    padding: 12px 16px;
    border-bottom: 1px solid var(--ve-border);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    background: var(--ve-cream);
    cursor: move;
    user-select: none;
}
.ve-modal-header h2 {
    margin: 0;
    font-size: 14px;
    font-weight: 600;
    color: var(--ve-ink);
}
.ve-modal-header .ve-modal-meta {
    font-size: 11px;
    color: var(--ve-muted);
    font-weight: 500;
    letter-spacing: 0.03em;
    margin-top: 2px;
}
.ve-modal-close {
    background: transparent;
    border: none;
    font-size: 22px;
    line-height: 1;
    color: var(--ve-muted);
    cursor: pointer;
    padding: 0 4px;
}
.ve-modal-close:hover { color: var(--ve-ink); }

.ve-modal-body {
    flex: 1;
    overflow-y: auto;
    padding: 14px 16px;
    background: #fafaf7;
}
.ve-modal-footer {
    padding: 10px 14px;
    border-top: 1px solid var(--ve-border);
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 10px;
    background: #fff;
}

/* form fields */
.ve-field {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-bottom: 14px;
    max-width: 100%;
}
.ve-field-label {
    font-size: 12px;
    font-weight: 600;
    color: var(--ve-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.ve-field-help {
    font-size: 12px;
    color: var(--ve-muted);
    margin-top: 2px;
}
.ve-field input[type=text],
.ve-field input[type=url],
.ve-field textarea,
.ve-field select {
    width: 100%;
    padding: 10px 12px;
    border: 1.5px solid var(--ve-border);
    border-radius: 8px;
    background: #fff;
    font-size: 14px;
    font-family: inherit;
    color: var(--ve-ink);
}
.ve-field textarea {
    resize: vertical;
    min-height: 90px;
    line-height: 1.5;
}
.ve-field textarea.ve-mono {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 13px;
    min-height: 180px;
}
.ve-field input:focus, .ve-field textarea:focus, .ve-field select:focus {
    outline: none;
    border-color: var(--ve-accent);
    box-shadow: 0 0 0 3px rgba(30, 64, 175, 0.16);
}

/* Image field — text input + upload button + drag-drop zone + preview. */
.ve-image {
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.ve-image-row {
    display: flex;
    gap: 6px;
    align-items: stretch;
}
.ve-image-row input[type=text] { flex: 1; }
.ve-image-upload-btn {
    padding: 0 12px;
    border: 1.5px solid var(--ve-border);
    background: #fff;
    border-radius: 8px;
    cursor: pointer;
    font-size: 13px;
    font-weight: 600;
    color: var(--ve-ink);
    transition: all 0.12s;
    white-space: nowrap;
}
.ve-image-upload-btn:hover { border-color: var(--ve-accent); color: var(--ve-accent); }
.ve-image-upload-btn:disabled { opacity: 0.55; cursor: wait; }

/* Discreet drop hint — small one-liner under the text input. The whole
   .ve-image field is also a drop target, so the user can drop a file
   anywhere over the field, not just on this hint line. */
.ve-image-dropzone {
    font-size: 11px;
    color: var(--ve-muted);
    padding: 2px 4px;
    border-radius: 4px;
    transition: all 0.15s;
    user-select: none;
    cursor: pointer;
    align-self: flex-start;
}
.ve-image-dropzone:hover { color: var(--ve-accent); }
.ve-image.ve-dragover                   { outline: 2px dashed var(--ve-brand); outline-offset: 4px; border-radius: 4px; }
.ve-image.ve-dragover .ve-image-dropzone {
    color: var(--ve-brand);
    font-weight: 600;
}

.ve-image-preview {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px;
    background: #fff;
    border: 1px solid var(--ve-border);
    border-radius: 6px;
}
.ve-image-preview img {
    max-width: 80px;
    max-height: 80px;
    object-fit: contain;
    border-radius: 4px;
    background: var(--ve-cream);
}
/* Video previews need more area than an 80px thumbnail to actually show
   what was uploaded, but should still sit comfortably next to the info
   column instead of blowing out the bubble. 280×160 is the cap; portrait
   clips letterbox inside it, landscape clips fill the width. */
.ve-image-preview video {
    width: 100%;
    max-width: 280px;
    max-height: 160px;
    object-fit: contain;
    border-radius: 4px;
    background: var(--ve-cream);
    flex-shrink: 0;
}
.ve-image-preview-info {
    font-size: 11px;
    color: var(--ve-muted);
    line-height: 1.4;
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}
.ve-image-status {
    font-size: 12px;
    color: var(--ve-muted);
}
.ve-image-status.error { color: var(--ve-danger); }
.ve-image-status.success { color: var(--ve-success); }

/* Aspect-ratio picker (used on Grid for child-card image aspect). */
.ve-aspect-buttons {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
}
.ve-aspect-btn {
    padding: 6px 12px;
    border: 1.5px solid var(--ve-border);
    background: #fff;
    color: var(--ve-ink);
    border-radius: 6px;
    cursor: pointer;
    font: 600 12px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    transition: all 0.12s;
    min-width: 44px;
    text-align: center;
}
.ve-aspect-btn:hover {
    border-color: var(--ve-accent);
    color: var(--ve-accent);
}
.ve-aspect-btn.active {
    background: var(--ve-accent);
    color: #fff;
    border-color: var(--ve-accent);
}
.ve-aspect-clear {
    color: var(--ve-muted);
}

/* Media-overlay editor (Hero + Carousel slide bubbles). Two compact rows:
   color picker + swatch + None button; then the opacity slider with a
   numeric % readout. The swatch shows a live preview of the chosen
   rgba/gradient so the operator can judge the tint without saving. */
.ve-media-overlay .ve-mo-row {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 6px;
    flex-wrap: wrap;
}
.ve-media-overlay .ve-mo-color-label,
.ve-media-overlay .ve-mo-opacity-label,
.ve-media-overlay .ve-mo-type-label {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    color: var(--ve-muted);
}
.ve-media-overlay input[type=color] {
    width: 36px;
    height: 28px;
    border: 1px solid var(--ve-border, #d0d4dc);
    border-radius: 6px;
    padding: 0;
    background: transparent;
    cursor: pointer;
}
.ve-media-overlay input[type=range] {
    flex: 1;
    min-width: 140px;
    cursor: pointer;
}
.ve-media-overlay .ve-mo-swatch {
    /* Inline JS sets the `background` shorthand on this element, so don't
       set any background here (it would be immediately overwritten). The
       white-ish bubble underneath stands in for "the media" — operators
       judge brightness/opacity, not exact contrast against their photo. */
    display: inline-block;
    width: 28px;
    height: 28px;
    border-radius: 6px;
    border: 1px solid var(--ve-border, #d0d4dc);
}
.ve-media-overlay .ve-mo-clear {
    font-size: 12px;
    padding: 4px 10px;
}
.ve-media-overlay [data-role=mo-opacity-value] {
    min-width: 36px;
    text-align: right;
    color: var(--ve-fg, #1d2433);
}

/* Per-field text formatting toolbar (align L/C/R + B/I). Stored under
   custom_settings.style.<title|subtitle|description>.{align|bold|italic}. */
.ve-text-format {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    margin-bottom: 2px;
}
.ve-fmt-btn {
    width: 26px;
    height: 26px;
    padding: 0;
    border: 1.5px solid var(--ve-border);
    background: #fff;
    color: var(--ve-ink);
    border-radius: 5px;
    cursor: pointer;
    font: 600 13px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: all 0.12s;
}
.ve-fmt-btn:hover {
    border-color: var(--ve-accent);
    color: var(--ve-accent);
}
.ve-fmt-btn.active {
    background: var(--ve-accent);
    color: #fff;
    border-color: var(--ve-accent);
}
.ve-fmt-sep {
    width: 1px;
    height: 18px;
    background: var(--ve-border);
    margin: 0 4px;
    display: inline-block;
}

/* Color button — the "A" sits above a swatch strip that mirrors the
   currently-selected color (or transparent when no override is set). */
.ve-fmt-btn.ve-fmt-color {
    width: 32px;
    flex-direction: column;
    gap: 2px;
    padding-top: 3px;
}
.ve-fmt-color-swatch {
    display: block;
    width: 18px;
    height: 4px;
    border-radius: 2px;
    background: transparent;
    border: 1px solid rgba(0, 0, 0, 0.15);
    box-sizing: border-box;
}
.ve-fmt-color-swatch-clear {
    background: linear-gradient(135deg, transparent 45%, #d33 45%, #d33 55%, transparent 55%);
}

/* Inline popover anchored to the toolbar button. The toolbar's parent
   is position:relative inside the field, so absolute here lands the
   popover under the button. */
.ve-text-format { position: relative; }
.ve-fmt-popover {
    position: absolute;
    top: 100%;
    left: 0;
    margin-top: 4px;
    background: #fff;
    border: 1.5px solid var(--ve-border);
    border-radius: 8px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
    z-index: 1000001;
    padding: 8px;
    min-width: 180px;
}
.ve-fmt-popover-color {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 4px;
}
.ve-fmt-color-opt {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 8px;
    border: 1px solid transparent;
    background: #fff;
    border-radius: 5px;
    cursor: pointer;
    font: 500 12px/1.2 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    color: var(--ve-ink);
    text-align: left;
}
.ve-fmt-color-opt:hover {
    border-color: var(--ve-border);
    background: #f8f8f8;
}
.ve-fmt-color-opt .ve-fmt-color-swatch {
    width: 14px;
    height: 14px;
    border-radius: 3px;
    flex-shrink: 0;
}
.ve-fmt-color-custom {
    grid-column: 1 / -1;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 8px;
    margin-top: 4px;
    border-top: 1px solid var(--ve-border);
    font: 500 12px/1.2 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    color: var(--ve-ink-faint, #666);
    cursor: pointer;
}
.ve-fmt-color-input {
    width: 28px;
    height: 24px;
    padding: 0;
    border: 1px solid var(--ve-border);
    border-radius: 4px;
    cursor: pointer;
}

/* Link popover — single-input + apply/cancel. */
.ve-fmt-popover-link {
    width: 280px;
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.ve-fmt-link-help {
    font-size: 11px;
    color: var(--ve-ink-faint, #666);
}
.ve-fmt-link-input {
    padding: 6px 10px;
    border: 1.5px solid var(--ve-border);
    border-radius: 6px;
    font-size: 13px;
    font-family: inherit;
}
.ve-fmt-link-input:focus { outline: none; border-color: var(--ve-brand); }
.ve-fmt-link-actions {
    display: flex;
    justify-content: flex-end;
    gap: 6px;
}
.ve-fmt-link-cancel,
.ve-fmt-link-apply {
    padding: 5px 12px;
    border: 1.5px solid var(--ve-border);
    background: #fff;
    border-radius: 5px;
    cursor: pointer;
    font: 600 12px/1.2 inherit;
}
.ve-fmt-link-apply {
    background: var(--ve-brand);
    border-color: var(--ve-brand);
    color: #fff;
}

/* Type picker popover — anchored to the bubble's footer ✚ button when
   the parent accepts multiple child types (Carousel: Card/Hero, etc.).
   Position is set inline by JS using viewport coords. */
.ve-type-picker {
    position: absolute;
    z-index: 1000002;
    min-width: 200px;
    background: #fff;
    border: 1.5px solid var(--ve-border);
    border-radius: 8px;
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.18);
    padding: 8px;
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.ve-type-picker-title {
    font: 500 11px/1.2 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    color: var(--ve-ink-faint, #666);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 4px 8px;
}
.ve-type-picker-opt {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 10px;
    border: 1.5px solid var(--ve-border);
    background: #fff;
    border-radius: 6px;
    cursor: pointer;
    font: 600 13px/1.2 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    color: var(--ve-ink);
    text-align: left;
    transition: all 0.12s;
}
.ve-type-picker-opt:hover {
    border-color: var(--ve-brand);
    background: #fff8f3;
    color: var(--ve-brand);
}
.ve-type-picker-cancel {
    margin-top: 4px;
    padding: 6px 10px;
    border: 1px solid transparent;
    background: transparent;
    border-radius: 5px;
    cursor: pointer;
    font: 500 12px/1.2 inherit;
    color: var(--ve-ink-faint, #666);
}
.ve-type-picker-cancel:hover {
    color: var(--ve-ink);
    background: #f5f5f5;
}

/* Image-position button group (Container's layout.imagePosition). */
.ve-image-position {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-top: 4px;
}
.ve-image-position-label {
    font-size: 11px;
    font-weight: 600;
    color: var(--ve-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    flex: 0 0 auto;
}
.ve-image-position-buttons {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
}
.ve-image-pos-btn {
    padding: 5px 12px;
    border: 1.5px solid var(--ve-border);
    background: #fff;
    border-radius: 6px;
    cursor: pointer;
    font: 600 12px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    color: var(--ve-ink);
    transition: all 0.12s;
}
.ve-image-pos-btn:hover {
    border-color: var(--ve-accent);
    color: var(--ve-accent);
}
.ve-image-pos-btn.active {
    background: var(--ve-accent);
    color: #fff;
    border-color: var(--ve-accent);
}

/* Children section — list of child rows + add-child mini-form. */
.ve-children {
    margin: 8px 0 14px;
    padding: 12px;
    background: var(--ve-cream);
    border-radius: 8px;
    border: 1px solid var(--ve-border);
}
.ve-children-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 8px;
    gap: 8px;
}
.ve-children-title {
    font-size: 12px;
    font-weight: 600;
    color: var(--ve-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.ve-children-count {
    font-weight: 500;
    text-transform: none;
    letter-spacing: 0;
    color: var(--ve-ink);
}
.ve-children-header .ve-button {
    padding: 6px 12px;
    font-size: 12px;
}
.ve-children-hint {
    font-size: 11px;
    color: var(--ve-muted);
    font-style: italic;
    text-align: right;
    max-width: 60%;
    line-height: 1.4;
}
.ve-children-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.ve-child {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
    background: #fff;
    border: 1px solid var(--ve-border);
    border-radius: 6px;
    cursor: pointer;
    font-size: 13px;
    transition: all 0.12s;
}
.ve-child:hover {
    border-color: var(--ve-accent);
    background: #f8faff;
}
.ve-child-type {
    font-size: 10px;
    font-weight: 700;
    color: var(--ve-accent);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    background: rgba(30, 64, 175, 0.08);
    padding: 2px 6px;
    border-radius: 3px;
    flex: 0 0 auto;
}
.ve-child-title {
    flex: 1;
    color: var(--ve-ink);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ve-child-arrow {
    font-size: 11px;
    color: var(--ve-muted);
    flex: 0 0 auto;
}
.ve-children-empty {
    font-size: 12px;
    color: var(--ve-muted);
    padding: 10px 12px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    background: rgba(0, 0, 0, 0.02);
    border-radius: 6px;
    border: 1px dashed var(--ve-border);
}
.ve-children-empty .ve-button {
    flex: 0 0 auto;
}

.ve-add-child-form { margin-top: 10px; padding-top: 10px; border-top: 1px dashed var(--ve-border); }
.ve-add-child-row {
    display: flex;
    gap: 6px;
}
.ve-add-child-type {
    flex: 0 0 auto;
    padding: 8px 10px;
    border: 1.5px solid var(--ve-border);
    border-radius: 8px;
    font: inherit;
    background: #fff;
    cursor: pointer;
    min-width: 100px;
}
.ve-add-child-title {
    flex: 1;
    padding: 8px 10px;
    border: 1.5px solid var(--ve-border);
    border-radius: 8px;
    font: inherit;
}
.ve-add-child-fixed-type {
    display: inline-flex;
    align-items: center;
    padding: 4px 10px;
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--ve-accent);
    background: rgba(30, 64, 175, 0.08);
    border-radius: 4px;
    flex: 0 0 auto;
}
.ve-add-child-form .ve-button {
    padding: 8px 14px;
    font-size: 13px;
}
.ve-add-child-status {
    font-size: 12px;
    margin-top: 6px;
    color: var(--ve-muted);
}
.ve-add-child-status.error   { color: var(--ve-danger); }
.ve-add-child-status.success { color: var(--ve-success); }

/* Collapsible Advanced section inside the bubble */
/* =========================================================================
   Translations section — language tab switcher
   ========================================================================= */
.ve-languages {
    margin-top: 6px;
    padding-top: 6px;
    border-top: 1px dashed var(--ve-border);
}
.ve-languages > summary {
    list-style: none;
    cursor: pointer;
    font-size: 12px;
    font-weight: 600;
    color: var(--ve-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 8px 0;
    user-select: none;
}
.ve-languages > summary::-webkit-details-marker { display: none; }
.ve-languages > summary::before {
    content: "▸";
    display: inline-block;
    margin-right: 8px;
    transition: transform 0.15s;
}
.ve-languages[open] > summary::before { transform: rotate(90deg); }
.ve-languages > summary:hover { color: var(--ve-ink); }
.ve-languages-body { padding-top: 8px; }

.ve-lang-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin-bottom: 12px;
}
.ve-lang-tab {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 5px 10px;
    border: 1.5px solid var(--ve-border);
    border-radius: 6px;
    background: transparent;
    font-size: 12px;
    font-weight: 600;
    color: var(--ve-muted);
    cursor: pointer;
    transition: background 0.12s, color 0.12s, border-color 0.12s;
    white-space: nowrap;
}
.ve-lang-tab:hover {
    border-color: var(--ve-accent);
    color: var(--ve-accent);
}
.ve-lang-tab.ve-lang-tab-active {
    background: var(--ve-accent);
    border-color: var(--ve-accent);
    color: #fff;
}
.ve-lang-name {
    font-size: 11px;
    font-weight: 400;
    opacity: 0.85;
}
.ve-lang-tab.ve-lang-tab-active .ve-lang-name { opacity: 1; }
.ve-lang-panel { display: block; }
.ve-lang-panel[hidden] { display: none; }

/* Session groups structured editor */
.ve-session-groups { margin-top: 4px; }
.ve-sg-langs {
    display: flex;
    gap: 4px;
    margin-bottom: 10px;
    padding: 4px;
    background: #f3f3f5;
    border-radius: 8px;
    width: fit-content;
}
.ve-sg-lang {
    padding: 4px 12px;
    font-size: 12px;
    font-weight: 600;
    background: transparent;
    border: none;
    border-radius: 6px;
    cursor: pointer;
    color: var(--ve-muted);
    transition: background 0.12s, color 0.12s;
    font-family: inherit;
    min-width: 36px;
}
.ve-sg-lang:hover:not(.active) { background: #fff; color: var(--ve-ink); }
.ve-sg-lang.active { background: var(--ve-brand); color: #fff; }
.ve-sg-list { display: flex; flex-direction: column; gap: 12px; margin-bottom: 10px; }

/* Step-labels editor — many keys grouped by step, each step in its own
   collapsible <details>. Keeps the bubble navigable when 60+ rows are
   in play. Row layout: default English label on the left as a hint,
   override input on the right; stacked on narrow widths. */
.ve-step-labels { margin-top: 4px; }
.ve-sl-list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 10px; }
.ve-sl-group {
    border: 1px solid var(--ve-border);
    border-radius: 8px;
    background: #fff;
}
.ve-sl-group > summary {
    padding: 10px 12px;
    font-size: 13px;
    font-weight: 600;
    color: var(--ve-ink);
    cursor: pointer;
    list-style: none;
    user-select: none;
    border-radius: 8px;
}
.ve-sl-group > summary::-webkit-details-marker { display: none; }
.ve-sl-group > summary::before {
    content: '▸';
    display: inline-block;
    width: 14px;
    color: var(--ve-muted);
    transition: transform 0.15s;
}
.ve-sl-group[open] > summary::before { transform: rotate(90deg); }
.ve-sl-group-count {
    margin-left: 6px;
    font-weight: 400;
    color: var(--ve-muted);
    font-size: 11px;
}
.ve-sl-group-body {
    padding: 4px 12px 12px 12px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    border-top: 1px solid var(--ve-border);
}
.ve-sl-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr);
    gap: 10px;
    align-items: start;
    font-size: 12px;
}
.ve-sl-row-label {
    padding-top: 8px;
    color: var(--ve-muted);
    line-height: 1.35;
    word-wrap: break-word;
}
.ve-sl-input {
    padding: 6px 10px;
    border: 1.5px solid var(--ve-border);
    border-radius: 6px;
    font-size: 13px;
    font-family: inherit;
    background: #fff;
    color: var(--ve-ink);
    width: 100%;
    box-sizing: border-box;
}
.ve-sl-input:focus { outline: none; border-color: var(--ve-brand); }
textarea.ve-sl-input { resize: vertical; min-height: 50px; }

/* Plan-overrides editor — reuses .ve-sg-group's card chrome but adds a
   second row underneath the label for the unit + pair prices. */
.ve-pl-label-input {
    flex: 1;
    min-width: 120px;
    padding: 6px 10px;
    border: 1.5px solid var(--ve-border);
    border-radius: 6px;
    font-size: 14px;
    font-weight: 600;
    font-family: inherit;
    background: #fff;
}
.ve-pl-price-row {
    display: flex;
    gap: 12px;
    flex-wrap: wrap;
}
.ve-pl-price-label {
    display: flex;
    flex-direction: column;
    gap: 4px;
    flex: 1 1 140px;
    font-size: 11px;
    font-weight: 500;
    color: var(--ve-ink-faint, #666);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.ve-pl-price-input {
    padding: 6px 10px;
    border: 1.5px solid var(--ve-border);
    border-radius: 6px;
    font-size: 13px;
    font-family: inherit;
    background: #fff;
    color: var(--ve-ink);
}
.ve-pl-price-input:focus { outline: none; border-color: var(--ve-brand); }
.ve-pl-promo-label {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-top: 10px;
    font-size: 11px;
    font-weight: 500;
    color: var(--ve-ink-faint, #666);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.ve-pl-promo-input {
    padding: 6px 10px;
    border: 1.5px solid var(--ve-border);
    border-radius: 6px;
    font-size: 13px;
    font-family: inherit;
    background: #fff;
    color: var(--ve-ink);
    resize: vertical;
    min-height: 38px;
}
.ve-pl-promo-input:focus { outline: none; border-color: var(--ve-brand); }
.ve-sg-group {
    border: 1.5px solid var(--ve-border);
    border-radius: 8px;
    padding: 12px;
    background: #fafafa;
}
.ve-sg-group-head {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 10px;
    flex-wrap: wrap;
}
.ve-sg-label-input {
    flex: 1;
    min-width: 120px;
    padding: 6px 10px;
    border: 1.5px solid var(--ve-border);
    border-radius: 6px;
    font-size: 13px;
    font-family: inherit;
    color: var(--ve-ink);
}
.ve-sg-label-input:focus { outline: none; border-color: var(--ve-brand); }
.ve-sg-type-btns { display: flex; gap: 0; border: 1.5px solid var(--ve-border); border-radius: 6px; overflow: hidden; }
.ve-sg-type-btn {
    padding: 5px 10px;
    font-size: 12px;
    font-weight: 600;
    background: #fff;
    border: none;
    cursor: pointer;
    color: var(--ve-muted);
    transition: background 0.12s, color 0.12s;
}
.ve-sg-type-btn + .ve-sg-type-btn { border-left: 1.5px solid var(--ve-border); }
.ve-sg-type-btn.active { background: var(--ve-brand); color: #fff; }
.ve-sg-type-btn:hover:not(.active) { background: #fff1ec; color: var(--ve-ink); }
.ve-sg-rm-group { font-size: 12px; padding: 5px 10px; color: #c00; }
.ve-sg-opts { display: flex; flex-direction: column; gap: 6px; margin-bottom: 8px; }
.ve-sg-option {
    display: flex;
    align-items: flex-start;
    gap: 6px;
}
.ve-sg-opt-input {
    flex: 1;
    padding: 6px 10px;
    border: 1.5px solid var(--ve-border);
    border-radius: 6px;
    font-size: 13px;
    line-height: 1.4;
    font-family: inherit;
    color: var(--ve-ink);
    resize: vertical;
    min-height: 32px;
}
.ve-sg-opt-input:focus { outline: none; border-color: var(--ve-brand); }
.ve-sg-rm-opt {
    flex-shrink: 0;
    width: 28px;
    height: 28px;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #c00;
    font-size: 16px;
    background: transparent;
    border: 1.5px solid #e8b0b0;
    border-radius: 6px;
}
.ve-sg-rm-opt:hover { background: #fdf0f0; }
.ve-sg-add-opt { font-size: 12px; padding: 4px 10px; margin-top: 2px; }
.ve-sg-add-group { margin-top: 4px; font-size: 13px; }

/* Form-layout editor — reuses .ve-sg-group's card chrome for consistency.
   Each block is a row with a type badge, edit controls, and an × remove.
   Headings show a text input; field rows show selected-field tags + a
   "+ Add field" select; step breaks render as a muted dashed divider. */
.ve-fl-list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 10px; }
.ve-fl-block {
    border: 1px solid var(--ve-border);
    border-radius: 8px;
    background: #fff;
}
.ve-fl-block-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 8px 12px;
    background: var(--ve-cream);
    border-bottom: 1px solid var(--ve-border);
    border-radius: 8px 8px 0 0;
}
.ve-fl-block-type {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--ve-muted);
}
.ve-fl-block-body {
    padding: 10px 12px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.ve-fl-input {
    padding: 6px 10px;
    border: 1.5px solid var(--ve-border);
    border-radius: 6px;
    font-size: 13px;
    font-family: inherit;
    background: #fff;
    width: 100%;
    box-sizing: border-box;
}
.ve-fl-input:focus { outline: none; border-color: var(--ve-brand); }
.ve-fl-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
.ve-fl-tag {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 4px 8px;
    background: #f3f4f6;
    border: 1px solid #e5e7eb;
    border-radius: 4px;
    font-size: 12px;
    color: var(--ve-ink);
}
.ve-fl-tag-x {
    cursor: pointer;
    color: var(--ve-muted);
    font-weight: 700;
    opacity: 0.6;
    transition: opacity 0.15s;
}
.ve-fl-tag-x:hover { opacity: 1; color: var(--ve-danger); }
.ve-fl-field-select {
    padding: 6px 8px;
    border: 1.5px solid var(--ve-border);
    border-radius: 6px;
    font-size: 12px;
    font-family: inherit;
    background: #fff;
    width: 100%;
}
.ve-fl-break {
    border-style: dashed;
    background: transparent;
}
.ve-fl-break .ve-fl-block-head {
    background: transparent;
    border-bottom: 1px dashed var(--ve-border);
}
.ve-fl-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 4px;
}
.ve-fl-actions .ve-button { font-size: 12px; padding: 6px 12px; }

.ve-advanced {
    margin-top: 6px;
    padding-top: 6px;
    border-top: 1px dashed var(--ve-border);
}
.ve-advanced > summary {
    list-style: none;
    cursor: pointer;
    font-size: 12px;
    font-weight: 600;
    color: var(--ve-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 8px 0;
    user-select: none;
}
.ve-advanced > summary::-webkit-details-marker { display: none; }
.ve-advanced > summary::before {
    content: "▸";
    display: inline-block;
    margin-right: 8px;
    transition: transform 0.15s;
}
.ve-advanced[open] > summary::before { transform: rotate(90deg); }
.ve-advanced > summary:hover { color: var(--ve-ink); }
.ve-advanced-body { padding-top: 8px; }

.ve-row-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 12px;
    padding: 8px 10px;
    background: var(--ve-cream);
    border-radius: 8px;
    font-size: 12px;
    color: var(--ve-muted);
    margin-bottom: 14px;
}
.ve-row-meta strong { color: var(--ve-ink); margin-right: 4px; }
.ve-meta-pair { display: inline-flex; align-items: center; gap: 0; }
.ve-meta-edit {
    background: transparent;
    border: 1px dashed transparent;
    padding: 2px 6px;
    font: inherit;
    color: var(--ve-ink);
    width: auto;
    min-width: 60px;
    border-radius: 4px;
    cursor: text;
}
.ve-meta-edit[readonly] {
    cursor: pointer;
}
.ve-meta-edit[readonly]:hover {
    border-color: var(--ve-border);
    background: #fff;
}
.ve-meta-edit:not([readonly]) {
    border-color: var(--ve-accent);
    background: #fff;
    box-shadow: 0 0 0 3px rgba(30, 64, 175, 0.16);
    outline: none;
}
/* Type dropdown — looks like a text label by default, reveals borders
   on hover/focus. Clicking opens the native dropdown. */
select.ve-meta-select {
    background: transparent;
    border: 1px dashed transparent;
    padding: 2px 6px;
    font: inherit;
    color: var(--ve-ink);
    cursor: pointer;
    border-radius: 4px;
}
select.ve-meta-select:hover {
    border-color: var(--ve-border);
    background: #fff;
}
select.ve-meta-select:focus {
    border-color: var(--ve-accent);
    background: #fff;
    box-shadow: 0 0 0 3px rgba(30, 64, 175, 0.16);
    outline: none;
}
.ve-meta-hint {
    flex-basis: 100%;
    font-size: 11px;
    color: var(--ve-muted);
    margin-top: 2px;
    opacity: 0.7;
}

.ve-button {
    padding: 10px 18px;
    border-radius: 8px;
    border: 1.5px solid var(--ve-border);
    background: #fff;
    color: var(--ve-ink);
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.15s;
    font-family: inherit;
}
.ve-button:hover { border-color: var(--ve-ink); }
.ve-button-primary {
    background: var(--ve-accent);
    color: #fff;
    border-color: var(--ve-accent);
}
.ve-button-primary:hover { background: #1c3aa3; border-color: #1c3aa3; }
.ve-button-danger {
    background: transparent;
    color: var(--ve-danger);
    border-color: transparent;
}
.ve-button-danger:hover { background: #fdf0ee; }
.ve-button:disabled { opacity: 0.55; cursor: wait; }

/* Compact icon-only variant for the modal footer. Square, fixed size,
   single glyph centered. The action label lives in the title attribute
   for hover discoverability. .ve-button-add tints additive actions blue
   so they read separately from Save (orange/primary) and Delete (red). */
.ve-button-icon {
    width: 40px;
    height: 40px;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 16px;
    line-height: 1;
}
.ve-button-icon.ve-button-add {
    background: #0066cc;
    color: #fff;
    border-color: #0066cc;
    font-size: 22px; /* the + glyph reads thinner than the others */
    font-weight: 400;
}
.ve-button-icon.ve-button-add:hover { background: #0052a3; border-color: #0052a3; }

/* Split add-row button: a wider main half ("＋ Add Slide") that runs the
   default sibling-add, plus a narrow chevron half that opens a picker for
   "Add a different element above" — see editor.js → addRow() +
   chooseAddAction(). The two halves are visually one control: shared
   background/border, divider line between them, only the outer corners
   are rounded. */
.ve-button-split {
    display: inline-flex;
    align-items: stretch;
    height: 40px;
}
.ve-button-split-main,
.ve-button-split-toggle {
    height: 40px;
    background: #0066cc;
    color: #fff;
    border: 1px solid #0066cc;
    cursor: pointer;
    transition: background 0.12s, border-color 0.12s;
    font: 500 13px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.ve-button-split-main {
    padding: 0 12px 0 10px;
    gap: 6px;
    border-radius: 6px 0 0 6px;
    border-right: 1px solid rgba(255, 255, 255, 0.25);
}
.ve-button-split-main-glyph {
    font-size: 18px;
    font-weight: 400;
    line-height: 1;
}
.ve-button-split-toggle {
    width: 26px;
    padding: 0;
    border-radius: 0 6px 6px 0;
    border-left: none;
    font-size: 11px;
}
.ve-button-split-main:hover,
.ve-button-split-toggle:hover {
    background: #0052a3;
    border-color: #0052a3;
}
.ve-button-split-main[disabled],
.ve-button-split-toggle[disabled] {
    opacity: 0.55;
    cursor: wait;
}
/* When the picker is open, keep the toggle visually depressed so the
   operator can see which control is anchoring the popover. */
.ve-button-split-toggle[aria-expanded="true"] {
    background: #0052a3;
    border-color: #0052a3;
}

/* Section divider + heading inside the add-action picker, for the
   "different element" group. Reuses .ve-type-picker. */
.ve-type-picker-divider {
    height: 1px;
    background: var(--ve-border);
    margin: 4px 2px;
}
/* Position-radio row (Above / Below) above the type list in the picker. */
.ve-type-picker-pos {
    display: flex;
    gap: 6px;
    padding: 2px 4px 6px;
}
.ve-type-picker-pos-opt {
    flex: 1;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 10px;
    border: 1.5px solid var(--ve-border);
    border-radius: 6px;
    cursor: pointer;
    font: 500 12px/1.2 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    color: var(--ve-ink);
    background: #fff;
    transition: border-color 0.12s, background 0.12s;
}
.ve-type-picker-pos-opt:hover {
    border-color: var(--ve-brand);
}
.ve-type-picker-pos-opt:has(input:checked) {
    border-color: var(--ve-brand);
    background: #fff8f3;
    color: var(--ve-brand);
}
.ve-type-picker-pos-opt input[type="radio"] {
    margin: 0;
    accent-color: var(--ve-brand);
}
.ve-button-icon.ve-button-danger {
    background: var(--ve-danger);
    color: #fff;
    border-color: var(--ve-danger);
}
.ve-button-icon.ve-button-danger:hover { background: #b02a37; border-color: #b02a37; }
.ve-button-icon.ve-button-primary {
    font-size: 18px;
}
/* Promote (🚀): solid green to read as a confident "publish to production"
   action. Distinct from the orange Save/Add buttons. */
.ve-button-icon.ve-button-promote {
    background: #198754;
    color: #fff;
    border-color: #198754;
    font-size: 14px;
}
.ve-button-icon.ve-button-promote:hover { background: #14693f; border-color: #14693f; }
.ve-button-icon.ve-button-promote[disabled] { background: #198754; opacity: 0.4; cursor: not-allowed; }
/* Reset (↻): amber outline — destructive of staging state but doesn't
   touch production, so it's a softer warning than the red Delete. */
.ve-button-icon.ve-button-warn {
    background: #fff8e6;
    color: #6b5a1f;
    border-color: #f4b942;
    font-size: 16px;
}
.ve-button-icon.ve-button-warn:hover { background: #f4b942; color: #fff; }
.ve-button-icon.ve-button-warn[disabled] { opacity: 0.5; cursor: not-allowed; }
/* Busy state: dim the glyph and show the spinner overlay (the same
   .ve-spinner used elsewhere). Used while an image upload blocks Save. */
.ve-button-busy {
    position: relative;
    color: transparent !important;
}
.ve-button-busy::after {
    content: "";
    position: absolute;
    width: 14px;
    height: 14px;
    border: 2px solid currentColor;
    border-top-color: transparent;
    border-radius: 50%;
    animation: ve-spin 0.8s linear infinite;
    color: #fff;
}
@keyframes ve-spin { to { transform: rotate(360deg); } }

.ve-status {
    font-size: 13px;
    color: var(--ve-muted);
}
.ve-status.error   { color: var(--ve-danger); }
.ve-status.success { color: var(--ve-success); }

.ve-save-progress {
    height: 3px;
    background: rgba(0,0,0,.1);
    border-radius: 3px;
    overflow: hidden;
    margin-bottom: 4px;
}
.ve-save-fill {
    height: 100%;
    background: var(--ve-accent, #2563eb);
    border-radius: 3px;
    transition: width .35s ease;
}

/* =========================================================================
   Crop preview modal — shown after picking/dropping an image, before
   uploading. User can drag the crop rectangle to reposition.
   ========================================================================= */
.ve-crop-backdrop {
    position: fixed;
    inset: 0;
    z-index: 1000000;
    background: rgba(15, 17, 22, 0.78);
    backdrop-filter: blur(3px);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
}
.ve-crop-card {
    background: #fff;
    border-radius: 12px;
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.45);
    padding: 18px;
    max-width: 96vw;
    max-height: 96vh;
    display: flex;
    flex-direction: column;
    gap: 14px;
    color: var(--ve-ink);
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
}
.ve-crop-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 13px;
    color: var(--ve-muted);
    gap: 12px;
}
.ve-crop-header strong { color: var(--ve-ink); }
.ve-crop-target {
    background: var(--ve-cream);
    color: var(--ve-accent);
    padding: 4px 10px;
    border-radius: 4px;
    font-weight: 600;
    font-size: 12px;
}
.ve-crop-stage {
    position: relative;
    background: #1a1a1a;
    border-radius: 6px;
    overflow: hidden;
    align-self: center;
}
.ve-crop-img {
    display: block;
    pointer-events: none;
    user-select: none;
}
.ve-crop-mask {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.55);
    pointer-events: none;
}
.ve-crop-rect {
    position: absolute;
    border: 2px solid var(--ve-brand);
    box-sizing: border-box;
    cursor: grab;
    box-shadow: 0 0 0 9999px rgba(0,0,0,0); /* placeholder; mask above does the dimming */
}
.ve-crop-rect:active { cursor: grabbing; }
.ve-crop-rect::after {
    /* small grid overlay for compositional reference */
    content: "";
    position: absolute;
    inset: 0;
    background:
      linear-gradient(to right,  transparent 33%, rgba(255,255,255,0.25) 33%, rgba(255,255,255,0.25) 33.4%, transparent 33.4%),
      linear-gradient(to right,  transparent 66%, rgba(255,255,255,0.25) 66%, rgba(255,255,255,0.25) 66.4%, transparent 66.4%),
      linear-gradient(to bottom, transparent 33%, rgba(255,255,255,0.25) 33%, rgba(255,255,255,0.25) 33.4%, transparent 33.4%),
      linear-gradient(to bottom, transparent 66%, rgba(255,255,255,0.25) 66%, rgba(255,255,255,0.25) 66.4%, transparent 66.4%);
    pointer-events: none;
}
.ve-crop-zoom {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 4px 8px;
}
.ve-crop-zoom-label {
    font-size: 12px;
    font-weight: 600;
    color: var(--ve-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    flex: 0 0 auto;
}
.ve-crop-zoom-slider {
    flex: 1;
    accent-color: var(--ve-brand);
    cursor: pointer;
}

.ve-crop-actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
}

/* =========================================================================
   Password prompt — small centered card on a dimmed backdrop, only used
   for the one-time password entry.
   ========================================================================= */
.ve-pw-backdrop {
    position: fixed;
    inset: 0;
    z-index: 999996;
    background: var(--ve-overlay);
    backdrop-filter: blur(3px);
    display: flex;
    align-items: center;
    justify-content: center;
}
.ve-pw-card {
    width: min(420px, 92vw);
    margin: auto;
    background: #fff;
    border-radius: 12px;
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.45);
    padding: 24px;
}
.ve-pw-title { font-size: 18px; font-weight: 600; margin: 0 0 6px; }
.ve-pw-help  { font-size: 13px; color: var(--ve-muted); margin: 0 0 18px; }
.ve-pw-input {
    width: 100%;
    padding: 12px;
    border: 1.5px solid var(--ve-border);
    border-radius: 8px;
    font-size: 14px;
}
.ve-pw-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 14px; }

/* Small spinner used during loads */
.ve-spinner {
    display: inline-block;
    width: 14px;
    height: 14px;
    border: 2px solid currentColor;
    border-right-color: transparent;
    border-radius: 50%;
    animation: ve-spin 0.7s linear infinite;
    vertical-align: -3px;
    margin-right: 8px;
}
@keyframes ve-spin { to { transform: rotate(360deg); } }

/* =============================================================================
   Translate-with-Claude panel
   Sits between the primary fields and the Translations tab strip. One-click
   fill-in of every other language's tab inputs.
   ========================================================================= */
.ve-translate-panel {
    margin: 14px 0 4px;
    border: 1px solid var(--ve-border);
    border-radius: 8px;
    background: linear-gradient(180deg, rgba(99, 102, 241, 0.04), transparent 70%);
}
.ve-translate-panel > summary {
    padding: 10px 12px;
    cursor: pointer;
    font-weight: 600;
    font-size: 13px;
    color: var(--ve-accent, #4f46e5);
    list-style: none;
    user-select: none;
}
.ve-translate-panel > summary::-webkit-details-marker { display: none; }
.ve-translate-panel > summary::before {
    content: "✦ ";
    color: var(--ve-brand, #ff5733);
}
.ve-translate-body {
    padding: 4px 12px 12px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.ve-translate-help {
    color: var(--ve-text-muted, #666);
    font-size: 12px;
    line-height: 1.4;
}
.ve-translate-source {
    font-size: 12px;
    color: var(--ve-text-muted, #666);
    line-height: 1.4;
}
.ve-translate-source strong {
    color: var(--ve-text, #111);
    font-weight: 700;
}
.ve-translate-source-hint {
    color: var(--ve-text-muted, #888);
    display: block;
    margin-top: 6px;
}
/* Source-language picker: a row of radio chips, one per language. */
.ve-translate-src-title {
    display: block;
    font-weight: 700;
    color: var(--ve-text, #111);
    margin-bottom: 6px;
}
.ve-translate-src-radios {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
.ve-translate-src-opt {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 4px 9px;
    border: 1px solid var(--ve-border, #d4d4d8);
    border-radius: 999px;
    background: #fff;
    cursor: pointer;
    font-size: 12px;
    line-height: 1;
    user-select: none;
    transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.ve-translate-src-opt:hover {
    border-color: var(--ve-brand, #ff5733);
}
.ve-translate-src-opt input[type="radio"] {
    margin: 0;
    accent-color: var(--ve-brand, #ff5733);
}
.ve-translate-src-opt.is-active {
    background: var(--ve-brand, #ff5733);
    border-color: var(--ve-brand, #ff5733);
    color: #fff;
    font-weight: 600;
}
.ve-translate-src-label {
    white-space: nowrap;
}
/* Whole-page translate toggle */
.ve-translate-wholepage {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    padding: 8px 10px;
    margin-top: 2px;
    border: 1px dashed var(--ve-border, #d4d4d8);
    border-radius: 8px;
    background: rgba(255, 87, 51, 0.04);
    font-size: 12px;
    line-height: 1.4;
    color: var(--ve-text, #111);
    cursor: pointer;
}
.ve-translate-wholepage input[type="checkbox"] {
    margin: 2px 0 0;
    flex: 0 0 auto;
    accent-color: var(--ve-brand, #ff5733);
}
.ve-translate-wholepage:has(input:checked) {
    border-style: solid;
    border-color: var(--ve-brand, #ff5733);
    background: rgba(255, 87, 51, 0.08);
}
.ve-translate-langs {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 10px;
}
.ve-translate-lang {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 9px;
    border: 1px solid var(--ve-border);
    border-radius: 999px;
    background: #fff;
    cursor: pointer;
    font-size: 12px;
    transition: background 0.12s, border-color 0.12s;
}
.ve-translate-lang:has(input:checked) {
    border-color: var(--ve-accent, #4f46e5);
    background: rgba(99, 102, 241, 0.08);
}
.ve-translate-lang input[type="checkbox"] {
    margin: 0;
    accent-color: var(--ve-accent, #4f46e5);
}
.ve-translate-lang-label {
    font-weight: 700;
    letter-spacing: 0.04em;
}
.ve-translate-lang-name {
    color: var(--ve-text-muted, #666);
}
.ve-translate-lang-filled {
    color: #16a34a;            /* default green = in sync */
    font-size: 9px;
    line-height: 1;
    margin-left: 2px;
    transition: color 0.15s;
}
/* Translation has a staging override → translated, waiting for promote. */
.ve-translate-lang-filled.state-pending  { color: #f59e0b; }
/* Source was edited but this lang wasn't re-translated → stale. */
.ve-translate-lang-filled.state-diverged { color: #dc2626; }
/* Explicit in_sync (kept distinct in case we want to differentiate later). */
.ve-translate-lang-filled.state-in_sync  { color: #16a34a; }
.ve-translate-lang-srctag {
    margin-left: 4px;
    padding: 1px 6px;
    border-radius: 999px;
    background: var(--ve-brand, #ff5733);
    color: #fff;
    font-size: 10px;
    line-height: 1.4;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    font-weight: 700;
}
.ve-translate-lang.is-source {
    border-style: dashed;
    background: rgba(255, 87, 51, 0.06);
    cursor: default;
}
.ve-translate-lang.is-source input[type="checkbox"] {
    opacity: 0.5;
    cursor: not-allowed;
}
.ve-translate-actions {
    display: flex;
    align-items: center;
    gap: 12px;
}
.ve-translate-status {
    font-size: 12px;
    color: var(--ve-text-muted, #666);
}
.ve-translate-status.success { color: #16a34a; }
.ve-translate-status.warn    { color: #b45309; }
.ve-translate-status.error   { color: #dc2626; }

/* =============================================================================
   Navigation editor affordances
   Nav <li>s are short and live in a tight flex/grid layout. The default
   drag handle + ✎ badge (with 4px outline-offset) push the menu around and
   look out of scale. Tighten everything when the editable target sits in
   the nav.
   ========================================================================= */
body.ve-active [data-cms-table="cms_navigation"]:hover {
    outline-offset: 1px;
    outline-width: 1px;
}
body.ve-active [data-cms-table="cms_navigation"]:hover::after {
    /* Compact pencil badge, no element-name suffix — there's no room. */
    content: "✎";
    top: 2px;
    right: 2px;
    padding: 2px 5px;
    font-size: 10px;
    line-height: 1;
    border-radius: 3px;
}
body.ve-active [data-cms-table="cms_navigation"] > .ve-drag-handle,
body.ve-active [data-cms-table="cms_navigation"] .ve-drag-handle {
    top: 2px;
    left: 2px;
    padding: 2px 4px;
    font-size: 10px;
    line-height: 1;
    border-radius: 3px;
}


/* =========================================================================
   News article unified editor — single bubble per article in cms_news.
   ========================================================================= */
.ve-news-bubble { width: 880px; max-width: min(1100px, calc(100vw - 24px)); }
.ve-news-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    padding: 8px 14px;
    border-bottom: 1px solid var(--ve-border);
    background: #f8f9fb;
    align-items: center;
}
.ve-news-tabs-sep {
    color: var(--ve-border);
    margin: 0 6px;
    font-weight: 700;
}
.ve-news-tab {
    background: transparent;
    border: 1px solid transparent;
    border-radius: 6px;
    padding: 5px 11px;
    font: 600 12px/1 inherit;
    color: var(--ve-ink-muted, #5b6470);
    cursor: pointer;
    transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.ve-news-tab:hover { background: #ecedf2; color: var(--ve-ink); }
.ve-news-tab.active {
    background: #fff;
    color: var(--ve-brand);
    border-color: var(--ve-border);
    box-shadow: 0 1px 0 #fff inset;
}
.ve-news-panel { padding: 12px 14px; }
.ve-news-panel .ve-field + .ve-field { margin-top: 14px; }
.ve-meta-chip {
    display: inline-block;
    background: #eef0f5;
    color: #5b6470;
    border-radius: 4px;
    padding: 2px 7px;
    font: 600 11px/1.4 inherit;
    margin-right: 6px;
}
.ve-news-featured {
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px dashed var(--ve-border);
    border-radius: 8px;
    min-height: 160px;
    margin: 8px 0;
    background: #fafbfd;
    overflow: hidden;
}
.ve-news-featured img { max-width: 100%; max-height: 280px; display: block; }
.ve-news-featured-empty { color: #8a93a0; font-size: 13px; }
.ve-drag-over { border-color: var(--ve-accent) !important; background: #eef2ff !important; }
.ve-news-gallery {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
    gap: 8px;
    margin: 8px 0;
}
.ve-news-gallery-item {
    border: 1px solid var(--ve-border);
    border-radius: 6px;
    overflow: hidden;
    background: #fafbfd;
    display: flex;
    flex-direction: column;
}
.ve-news-gallery-item img {
    width: 100%;
    aspect-ratio: 1 / 1;
    object-fit: cover;
    display: block;
}
.ve-news-gallery-name {
    font: 500 11px/1.3 inherit;
    color: #5b6470;
    padding: 4px 6px;
    text-align: center;
    word-break: break-all;
}
.ve-gallery-del {
    display: block;
    width: calc(100% - 12px);
    margin: 2px 6px 5px;
    padding: 2px 0;
    font-size: 11px;
    line-height: 1.4;
    background: transparent;
    color: var(--ve-danger);
    border: 1px solid var(--ve-danger);
    border-radius: 4px;
    cursor: pointer;
}
.ve-gallery-del:hover { background: var(--ve-danger); color: #fff; }
.ve-gallery-del:disabled { opacity: 0.55; cursor: wait; }
.ve-field-checkbox {
    display: flex;
    align-items: center;
    gap: 8px;
    font-weight: 500;
    cursor: pointer;
}

/* Add news article — listing-page-only button injected by the editor.
   Sits between the intro paragraph and the news grid. */
.ve-add-news-row {
    display: flex;
    justify-content: center;
    margin: 24px auto 16px;
    padding: 0 16px;
}
.ve-add-news-btn {
    background: var(--ve-brand);
    color: #fff;
    border: 0;
    border-radius: 6px;
    padding: 10px 18px;
    font: 600 14px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    cursor: pointer;
    box-shadow: 0 1px 2px rgba(0,0,0,0.08);
    transition: background 0.12s;
}
.ve-add-news-btn:hover { background: var(--ve-brand-hover, var(--ve-brand)); filter: brightness(0.95); }

/* Create-news bubble is a slimmer variant of the news editor bubble. */
.ve-create-news-bubble { width: 480px; min-width: 360px; min-height: auto; }

/* News-article references picker (Sources tab). */
.ve-refs-filter {
    width: 100%;
    margin-bottom: 8px;
}
.ve-refs-list {
    max-height: 320px;
    overflow-y: auto;
    border: 1px solid var(--ve-border);
    border-radius: 6px;
    padding: 4px 0;
    background: #fff;
}
.ve-refs-item {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    padding: 8px 10px;
    border-bottom: 1px solid #eef0f5;
    cursor: pointer;
    transition: background 0.1s;
}
.ve-refs-item:last-child { border-bottom: 0; }
.ve-refs-item:hover { background: #f8f9fb; }
.ve-refs-item input[type=checkbox] { margin-top: 3px; flex-shrink: 0; }
.ve-refs-text { flex: 1; min-width: 0; }
.ve-refs-head { font-size: 13px; line-height: 1.4; }
.ve-refs-pub {
    display: inline-block;
    background: #eef0f5;
    color: #5b6470;
    border-radius: 3px;
    padding: 1px 6px;
    font: 600 10px/1.4 inherit;
    margin-left: 6px;
}
.ve-refs-date { color: #8a93a0; font-size: 11px; margin-left: 6px; }
.ve-refs-linkrow { font-size: 11px; margin-top: 2px; word-break: break-all; }
.ve-refs-link { color: var(--ve-brand); text-decoration: none; }
.ve-refs-link:hover { text-decoration: underline; }
.ve-refs-add { margin-top: 8px; }
.ve-refs-add summary { cursor: pointer; font-weight: 600; color: var(--ve-brand); padding: 6px 0; }
.ve-refs-add-body {
    border: 1px solid var(--ve-border);
    border-radius: 6px;
    padding: 10px 12px;
    margin-top: 8px;
    background: #fafbfd;
}
.ve-refs-add-body .ve-field + .ve-field { margin-top: 8px; }
.ve-refs-legacy {
    border: 1px dashed var(--ve-border);
    border-radius: 6px;
    padding: 8px 12px;
    background: #fafbfd;
    color: #5b6470;
    font-size: 12px;
}
.ve-refs-legacy a { color: var(--ve-brand); }

.ve-refs-type {
    display: flex;
    gap: 16px;
}
.ve-refs-type label {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 13px;
    cursor: pointer;
}
.ve-refs-type input[type=radio] { margin: 0; }

/* Website type only needs Headline + Link — hide the article-only fields. */
.ve-refs-add-body[data-ref-type="website"] [data-website-hide] { display: none; }

.ve-refs-typechip {
    display: inline-block;
    border-radius: 3px;
    padding: 1px 6px;
    font: 700 9px/1.4 inherit;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin-right: 4px;
    vertical-align: middle;
}
.ve-refs-typechip-article { background: #e0eaff; color: #2c4dd8; }
.ve-refs-typechip-website { background: #e0f5ec; color: #1e8a5c; }

/* =========================================================================
   MOBILE / TOUCH RESPONSIVE
   The editor was originally desktop-only — fixed-width bubble, hover-gated
   affordances, mouse-only handlers. These overrides retrofit it for phones
   and tablets without rewriting every component.

   Two independent breakpoints applied per-rule:

     @media (max-width: 640px)
        Narrow viewports — collapse the bubble + popovers to full-screen
        layouts so nothing overflows the viewport. Catches phones in
        portrait (375–428px) and small tablets in split-view.

     @media (pointer: coarse)
        Touch-first input devices — unconditionally reveal hover-gated UI
        (drag handle, ✎ edit badge), enlarge tap targets to 44px+, raise
        input font-size to 16px so iOS Safari doesn't auto-zoom on focus.
        Applies to phones AND tablets — iPads with no attached pointer
        still get this even at desktop width.

   Companion JS lives in editor.js — makeDraggable() uses Pointer Events
   so the bubble drag handle works on touch, outside-tap dismissal listens
   for `pointerdown` (covers both), and `chooseAddAction`/`chooseChildType`
   clamp popover position to viewport bounds.
   ========================================================================= */

@media (max-width: 640px) {

    /* ---------------------------------------------------------------
       Bubble → full-screen drawer. Fixed positioning + safe-area inset
       handles the iOS notch. Overrides desktop's `position: absolute`
       + JS-set viewport coords, so the bubble can't land off-screen.
       --------------------------------------------------------------- */
    .ve-bubble,
    .ve-news-bubble,
    .ve-create-news-bubble,
    .ve-refs-bubble {
        position: fixed !important;
        top: 0 !important;
        left: 0 !important;
        right: 0 !important;
        width: 100vw !important;
        min-width: 0 !important;
        max-width: 100vw !important;
        height: 100vh !important;
        max-height: 100vh !important;
        border-radius: 0 !important;
        resize: none !important;
    }
    /* Hide the resize-corner pseudo — no resize on mobile. */
    .ve-bubble::after { display: none; }
    /* Header gets safe-area padding for the iOS notch. */
    .ve-modal-header {
        padding-top: max(12px, env(safe-area-inset-top, 12px));
        padding-left: max(16px, env(safe-area-inset-left, 16px));
        padding-right: max(16px, env(safe-area-inset-right, 16px));
    }
    /* Body scrolls; footer pinned at bottom. */
    .ve-modal-body {
        padding-left: max(14px, env(safe-area-inset-left, 14px));
        padding-right: max(14px, env(safe-area-inset-right, 14px));
    }

    /* ---------------------------------------------------------------
       Footer button row — wrap actions onto multiple lines instead of
       overflowing horizontally. The status div drops to its own line
       above the actions.
       --------------------------------------------------------------- */
    .ve-modal-footer {
        flex-wrap: wrap;
        gap: 8px;
        padding-bottom: max(10px, env(safe-area-inset-bottom, 10px));
        padding-left: max(14px, env(safe-area-inset-left, 14px));
        padding-right: max(14px, env(safe-area-inset-right, 14px));
    }
    .ve-modal-footer .ve-status {
        flex: 1 0 100%;
        order: -1;
    }
    .ve-modal-actions {
        display: flex;
        flex-wrap: wrap;
        justify-content: flex-end;
        gap: 6px;
        width: 100%;
    }
    /* Split-button on mobile: hide the inline label, keep just the + glyph
       so the footer row fits without wrapping repeatedly. The chevron
       remains visible — the picker still tells the user what they're
       adding via the type list. */
    .ve-button-split-main-label { display: none; }
    .ve-button-split-main      { padding: 0; width: 40px; }

    /* ---------------------------------------------------------------
       Popovers — type picker, format popovers — clamp to viewport so
       they don't render off the right edge at 375px. JS still positions
       via inline left/top, but the max-width + max-height + overflow
       here keeps them inside the viewport regardless.
       --------------------------------------------------------------- */
    .ve-type-picker,
    .ve-fmt-popover {
        max-width: calc(100vw - 16px);
        max-height: 80vh;
        overflow-y: auto;
        box-sizing: border-box;
        -webkit-overflow-scrolling: touch;
    }

    /* ---------------------------------------------------------------
       Dock panel — narrower on mobile so it doesn't crowd the viewport.
       Safe-area on the pill so it clears the iOS notch in landscape.
       --------------------------------------------------------------- */
    .ve-dock-pill {
        top: max(12px, env(safe-area-inset-top, 12px));
        right: max(12px, env(safe-area-inset-right, 12px));
    }
    .ve-dock-panel {
        width: calc(100vw - 24px);
        max-width: 360px;
        right: max(12px, env(safe-area-inset-right, 12px));
    }

    /* ---------------------------------------------------------------
       Toast — clear the notch + match dock positioning.
       --------------------------------------------------------------- */
    .ve-toast {
        top: max(16px, env(safe-area-inset-top, 16px));
        max-width: calc(100vw - 24px);
    }

    /* ---------------------------------------------------------------
       Multi-button row groups — keep predictable wrap; never let
       buttons go full-width-each on narrow screens.
       --------------------------------------------------------------- */
    .ve-aspect-buttons,
    .ve-image-position-buttons {
        flex-wrap: wrap;
        gap: 6px;
    }
    .ve-aspect-buttons > *,
    .ve-image-position-buttons > * {
        flex: 1 0 calc(33.333% - 6px);
        min-width: 0;
    }
}

@media (pointer: coarse) {

    /* ---------------------------------------------------------------
       Hover-gated affordances → always visible on touch.
       Without this the operator can't see what's editable or grab the
       reorder handle, because touch never fires `:hover`.
       --------------------------------------------------------------- */
    body.ve-active [data-cms-id] > .ve-drag-handle,
    body.ve-active [data-cms-id] .ve-drag-handle {
        opacity: 0.85;
    }
    /* Larger drag-handle hit area on touch (was 6px × 8px padding,
       ≈ 22px × 24px effective). Padding + 16px glyph + line-height 1
       gives 44 × 44px — the standard touch-target minimum. */
    body.ve-active [data-cms-id] > .ve-drag-handle,
    body.ve-active [data-cms-id] .ve-drag-handle {
        padding: 14px 14px;
        font-size: 16px;
    }
    /* ✎ edit badge always visible on touch, at lower opacity so it
       doesn't dominate the page when nothing's being edited. */
    body.ve-active [data-cms-id]::after {
        content: "✎ " attr(data-cms-element);
        position: absolute;
        top: 6px;
        right: 6px;
        background: var(--ve-accent);
        color: #fff;
        font: 600 11px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
        padding: 5px 8px;
        border-radius: 4px;
        pointer-events: none;
        z-index: 999998;
        letter-spacing: 0.02em;
        opacity: 0.7;
    }
    /* While editing, suppress everything else's badge + handle so they
       don't poke through the bubble. (Mirrors the desktop ve-editing rule.) */
    body.ve-editing [data-cms-id]::after,
    body.ve-editing [data-cms-id] > .ve-drag-handle,
    body.ve-editing [data-cms-id] .ve-drag-handle {
        opacity: 0 !important;
        pointer-events: none;
    }

    /* ---------------------------------------------------------------
       Touch targets — bump every sub-44px interactive control to a
       proper tap target. 44pt is Apple HIG; 48dp is Material. We use
       44px which is comfortable for both.
       --------------------------------------------------------------- */
    .ve-fmt-btn,
    .ve-button-icon,
    .ve-button-split-toggle {
        min-width: 44px;
        min-height: 44px;
    }
    .ve-button-split-toggle { width: 44px; }
    .ve-sg-rm-opt,
    .ve-mo-swatch,
    .ve-fl-tag-x {
        min-width: 44px;
        min-height: 44px;
    }
    .ve-modal-close,
    .ve-dock-panel-close {
        min-width: 44px;
        min-height: 44px;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        padding: 0;
    }
    .ve-dock-pill {
        min-width: 44px;
        min-height: 44px;
        padding: 10px 14px;
    }
    .ve-dock-pill::before { font-size: 16px; }
    /* Type-picker option chips — comfortable touch height. */
    .ve-type-picker-opt {
        min-height: 44px;
        padding: 12px 14px;
    }
    .ve-type-picker-pos-opt {
        min-height: 40px;
        padding: 10px 12px;
    }
    /* Children list rows — bigger tap target for "edit" / "remove". */
    .ve-child { padding: 12px 12px; }
    /* Format toolbar (B / I / Align / Link / Color) gets a comfortable row. */
    .ve-fmt-toolbar {
        gap: 4px;
    }

    /* ---------------------------------------------------------------
       Inputs at 16px+ → no iOS auto-zoom on focus. Every textfield in
       the editor is enumerated explicitly; class-based catch-all isn't
       safe because the dock + login + format popovers use their own
       class names.
       --------------------------------------------------------------- */
    .ve-field input[type=text],
    .ve-field input[type=url],
    .ve-field input[type=number],
    .ve-field input[type=password],
    .ve-field input[type=email],
    .ve-field input[type=search],
    .ve-field textarea,
    .ve-field select,
    .ve-fmt-link-input,
    .ve-sl-input,
    .ve-pl-price-input,
    .ve-pl-promo-input,
    .ve-sg-label-input,
    .ve-sg-opt-input,
    .ve-fl-input,
    .ve-fl-field-select,
    .ve-dock-promote-pw,
    .ve-pw-input {
        font-size: 16px;
    }

    /* ---------------------------------------------------------------
       Bubble — touch devices can't reach the native resize corner
       reliably; disable it. Desktop with a stylus on a coarse-pointer
       screen still loses resize, which is fine — the bubble already
       respects max-height: 100vh.
       --------------------------------------------------------------- */
    .ve-bubble { resize: none; }
}

/* ---------------------------------------------------------------------
   Touch-detect class — editor.js sets `body.ve-touch` on the first
   touch event so we can target devices that BOTH have a coarse pointer
   AND actually saw a touch (some desktops mis-report as coarse). Used
   in places where `pointer: coarse` is too aggressive.
   --------------------------------------------------------------------- */
body.ve-touch .ve-bubble::after { display: none; }

/* =========================================================================
   Conditional content rules + preview-as-country
   ========================================================================= */
.ve-dock-country { margin: 10px 0 6px; }
.ve-dock-country-row { display: flex; gap: 6px; align-items: center; }
.ve-dock-country-row input {
    width: 62px; text-transform: uppercase; text-align: center;
    padding: 6px 8px; border: 1px solid #d1d5db; border-radius: 6px; font-size: 13px;
}
.ve-preview-active { color: #b45309; font-weight: 600; }

.ve-rules-modal { max-width: 720px; }
.ve-rule { border: 1px solid #e5e7eb; border-radius: 8px; padding: 10px 12px; margin-bottom: 10px; }
.ve-rule-head { display: flex; justify-content: space-between; align-items: center; gap: 8px; flex-wrap: wrap; }
.ve-rule-active { display: flex; align-items: center; gap: 6px; }
.ve-rule-tags { display: flex; gap: 4px; flex-wrap: wrap; }
.ve-tag {
    font-size: 11px; padding: 2px 7px; border-radius: 10px;
    background: #f3f4f6; color: #374151; white-space: nowrap;
}
.ve-tag-country { background: #dbeafe; color: #1e40af; }
.ve-tag-compliance { background: #fee2e2; color: #991b1b; }
.ve-rule-grid {
    display: grid; grid-template-columns: 110px 1fr; gap: 6px 8px;
    align-items: center; margin-top: 8px;
}
.ve-rule-grid input {
    width: 100%; box-sizing: border-box; padding: 6px 8px;
    border: 1px solid #d1d5db; border-radius: 6px; font-size: 12px;
}
.ve-rule-actions { display: flex; justify-content: flex-end; align-items: center; gap: 8px; margin-top: 8px; }

/* ==========================================================================
   Immich picker
   Browsing photos.chordhero.com from inside the editor. The overlay sits
   above the bubble (z 1000000) because it is opened FROM the bubble and must
   cover it; anything lower renders behind the field it was launched from.
   ========================================================================== */

.ve-immich-btn { border-color: #cfd8e8; }
.ve-immich-btn:hover { border-color: var(--ve-accent); color: var(--ve-accent); }

.ve-immich-overlay {
    position: fixed;
    inset: 0;
    z-index: 1000002;
    background: var(--ve-overlay);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
}

.ve-immich-panel {
    width: min(920px, 100%);
    max-height: min(80vh, 720px);
    display: flex;
    flex-direction: column;
    background: #fff;
    border-radius: 14px;
    box-shadow: 0 24px 70px rgba(0, 0, 0, 0.45);
    overflow: hidden;
}

.ve-immich-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 16px;
    border-bottom: 1px solid var(--ve-border);
    font-size: 15px;
}
.ve-immich-close {
    border: 0;
    background: none;
    font-size: 22px;
    line-height: 1;
    cursor: pointer;
    color: var(--ve-muted);
    padding: 0 4px;
}
.ve-immich-close:hover { color: var(--ve-danger); }

.ve-immich-bar {
    display: flex;
    gap: 8px;
    padding: 12px 16px;
    border-bottom: 1px solid var(--ve-border);
}
.ve-immich-bar select,
.ve-immich-bar input {
    height: 34px;
    border: 1.5px solid var(--ve-border);
    border-radius: 8px;
    padding: 0 10px;
    font-size: 13px;
    font-family: inherit;
}
.ve-immich-bar select { max-width: 40%; }
.ve-immich-bar input  { flex: 1 1 auto; min-width: 0; }
.ve-immich-bar button {
    height: 34px;
    padding: 0 14px;
    border: 0;
    border-radius: 8px;
    background: var(--ve-accent);
    color: #fff;
    font-weight: 600;
    font-size: 13px;
    cursor: pointer;
}

/* auto-fill rather than auto-fit: with one result, auto-fit stretches the
   single tile across the whole row, which looks like a bug. */
.ve-immich-grid {
    flex: 1 1 auto;
    overflow-y: auto;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(132px, 1fr));
    gap: 10px;
    padding: 14px 16px;
    background: var(--ve-cream);
}

.ve-immich-tile {
    border: 1.5px solid transparent;
    background: #fff;
    border-radius: 10px;
    padding: 0;
    cursor: pointer;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    text-align: left;
    transition: border-color 0.12s, transform 0.12s;
}
.ve-immich-tile:hover  { border-color: var(--ve-accent); transform: translateY(-2px); }
.ve-immich-tile img {
    width: 100%;
    aspect-ratio: 1 / 1;
    object-fit: cover;
    display: block;
    background: #ece7de;
}
.ve-immich-tile span {
    font-size: 11px;
    color: var(--ve-muted);
    padding: 6px 8px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.ve-immich-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 16px;
    border-top: 1px solid var(--ve-border);
    font-size: 12px;
    color: var(--ve-muted);
}
.ve-immich-pager { display: flex; align-items: center; gap: 8px; }
.ve-immich-pager button {
    border: 1.5px solid var(--ve-border);
    background: #fff;
    border-radius: 6px;
    width: 28px;
    height: 26px;
    cursor: pointer;
}
.ve-immich-pager button:disabled { opacity: 0.4; cursor: default; }

/* Multi-select (gallery import). The selected state has to read at a glance
   across a 40-tile grid, so it is a filled border plus a badge rather than a
   hover-weight colour shift — hover already uses the accent border, and on a
   trackpad the pointer sits over a tile most of the time. */
.ve-immich-tile { position: relative; }
.ve-immich-tile.is-selected {
    border-color: var(--ve-accent);
    box-shadow: inset 0 0 0 2px var(--ve-accent);
}
.ve-immich-tile.is-selected::after {
    content: "✓";
    position: absolute;
    top: 6px;
    right: 6px;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: var(--ve-accent);
    color: #fff;
    font-size: 12px;
    line-height: 20px;
    text-align: center;
    pointer-events: none;
}
.ve-immich-hint { font-size: 12px; color: var(--ve-muted); }
.ve-immich-confirm {
    border: 0;
    background: var(--ve-accent);
    color: #fff;
    border-radius: 6px;
    padding: 7px 14px;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
}
.ve-immich-confirm:disabled { opacity: 0.45; cursor: default; }

/* ── Reference tags ───────────────────────────────────────────────────────
   cms_news_references.tags is a comma-separated string with no vocabulary
   behind it, so the picker's job is to make the tags already in use visible
   and clickable — typing a tag from memory is how "cyberport" and "Cyberport"
   both end up in the table. */
.ve-tags-chosen {
  display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
  min-height: 28px; margin-bottom: 6px;
}
.ve-tags-pool { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 8px; }
.ve-tag-chip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 9px; border-radius: 999px;
  background: #eef1f8; border: 1px solid #d6dced;
  font-size: 12px; line-height: 1.5; color: #2f3b57; white-space: nowrap;
}
.ve-tag-chip-add { cursor: pointer; background: #fff; }
.ve-tag-chip-add:hover { background: #eef1f8; border-color: #b9c4de; }
/* Read-only chips in the reference list — quieter, they are information
   rather than a control. */
.ve-tag-chip-static { background: #f4f5f7; border-color: #e3e5ea; color: #5f6b80; }
.ve-tag-x {
  border: 0; background: none; cursor: pointer; padding: 0 0 0 2px;
  font-size: 14px; line-height: 1; color: #7a8399;
}
.ve-tag-x:hover { color: #c0392b; }
.ve-refs-tagrow { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 5px; }

/* A product with no page of its own. Shown rather than hidden, so it is clear
   why it cannot be picked — two of the five active products have no page. */
.ve-tag-chip-disabled {
  opacity: .55; cursor: not-allowed;
  background: #f4f5f7; border-style: dashed; color: #7a8399;
}

/* Footer line under a truncated reference list. The list is capped at the most
   recent few so the panel loads quickly; this says so rather than letting the
   list look complete. */
.ve-refs-more {
  padding: 8px 12px; border-top: 1px solid #eceef3;
  background: #fafbfd; font-style: italic;
}

/* The empty-state line ("No recent news in the last 6 months…") is a bare
   .ve-field-help dropped straight into the list, which has no horizontal
   padding of its own — so its text started hard against the border while the
   filter input above it indents by 12px, and the two read as misaligned.
   12px matches that input's padding, so the two left edges line up. */
.ve-refs-list > .ve-field-help {
  padding: 8px 12px;
  margin-top: 0;
}
