/* ibv-warp-refs.css — Warp/RefClip prompt editor styles
   Replaces ibv-ref-dock styles from ref-dock.js
   CSS variable bridge: mockup --acc → project --ibv-accent */

/* ── Warp contenteditable prompt box ─────────────────────────── */
.ibv-warp-box {
  min-height: 72px;
  /* Grow to comfortably fit a long prompt (e.g. a 500–950 char Templates prompt
     applied here), then scroll — so it accommodates the prompt without pushing
     the composer/controls off-screen. */
  max-height: 55vh;
  overflow-y: auto;
  padding: 10px 12px;
  outline: none;
  font-size: 15px;
  line-height: 2.8;
  color: var(--ibv-text);
  word-break: break-word;
  cursor: text;
  white-space: pre-wrap;
}
/* Text warp chip — a boxed, editable, non-image warp element in the prompt
   (e.g. a template's swappable title word 谷雨). Serializes to {word}; braces
   are stripped before generation. */
.ibv-twarp-chip {
  display: inline-block;
  background: rgba(200,106,42,.14);
  border: 1px solid rgba(200,106,42,.55);
  border-radius: 4px;
  padding: 0 5px;
  margin: 0 1px;
  color: var(--ibv-accent, #c86a2a);
  font-weight: 600;
  line-height: 1.4;
  cursor: text;
  outline: none;
  white-space: nowrap;
}
.ibv-twarp-chip:hover { background: rgba(200,106,42,.22); }
.ibv-twarp-chip:focus {
  background: rgba(200,106,42,.26);
  outline: 2px solid var(--ibv-accent, #c86a2a);
  outline-offset: 1px;
}
.ibv-prompt-backdrop {
  display: none !important;
}
.ibv-warp-box:empty::before {
  content: 'Describe the image… drag a reference chip here to embed it in the prompt.';
  color: var(--ibv-muted);
  pointer-events: none;
}
/* 2026-07-20: this is the actual visible placeholder (the plain <textarea>
   this box overlays has its own {{ promptPlaceholder }}-bound placeholder
   attribute, but stays hidden behind this contenteditable div once
   warp-prompt.js mounts it) — CSS content: can't call translate(), so :lang()
   is the only way to localize it without wiring a data-placeholder attribute
   + JS through warp-prompt.js's box-creation code. */
html:lang(zh) .ibv-warp-box:empty::before {
  content: '描述你想要的画面。把参考图卡片拖进提示词框，或把历史记录卡片拖到这里加载完整设置。（⌘↵ 运行）';
}

/* Prompt History inline refclip/warp style. This mirrors only the history row
   behavior from the 2026-06-26 mockup, adapted to the current theme. */
.ibv-hist-entry {
  background: var(--warm, #ede8e1) !important;
  border-radius: 4px !important;
  overflow: hidden;
}
.ibv-hist-entry:hover {
  border-color: color-mix(in srgb, var(--border, #d7cdc3) 55%, var(--text, #2c2521)) !important;
}
.ibv-hist-entry > div[title^="Click to edit"]:not(.ibv-hist-content) {
  display: none !important;
}
.ibv-hist-content {
  padding: 7px 9px 7px 15px !important;
}
.ibv-hist-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 3px;
}
.ibv-hist-ts {
  font-size: 10px;
  color: var(--muted, #8a7f78);
  font-family: "JetBrains Mono", ui-monospace, monospace;
}
.ibv-hist-prompt-line {
  font-size: 13px;
  line-height: 2.3;
  color: var(--text, #2c2521);
  word-break: break-word;
  /* Full width now — actions moved to a bottom bar, no need to reserve room
     for absolutely-positioned buttons on the right (二期). */
}
/* Bottom action bar: timestamp/label left, action buttons right. Always
   visible (not hover-revealed) since it's the row's footer now. */
.ibv-hist-actionbar { border-top: 1px solid color-mix(in srgb, var(--border, #d7cdc3) 60%, transparent); margin-top: 2px; }
/* History warp/RefClip are GRAY (not the editor's orange) to signal they are
   read-only here — you edit in the composer, not in Prompt History. (B)
   inline-flex + align-items:center vertically centers the ⠿ grip, the mini-RC
   thumbnails and any inline gap text as one unit. (A) */
.ibv-hist-warp {
  display: inline-flex;
  align-items: center;
  border: 1px solid rgba(138, 127, 120, .45);
  background: rgba(138, 127, 120, .12);
  border-radius: 4px;
  padding: 2px 4px;
  margin: 0 1px;
  vertical-align: middle;
  cursor: grab;
}
.ibv-hist-warp:active,
.ibv-hist-mini-rc:active {
  cursor: grabbing;
}
.ibv-hist-warp-grip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 13px;
  height: 22px;
  background: var(--muted, #8a7f78);
  color: #fff;
  border-radius: 3px 0 0 3px;
  font-size: 9px;
  font-weight: 700;
  vertical-align: middle;
  margin-right: 2px;
  cursor: grab;
  font-size: 0;
}
.ibv-hist-warp-grip::before {
  content: '::';
  font-size: 9px;
}
.ibv-hist-mini-rc {
  display: inline-flex;
  align-items: center;
  justify-content: flex-start;
  position: relative;
  vertical-align: middle;
  width: 34px;
  height: 22px;
  border-radius: 3px;
  overflow: hidden;
  border: 1px solid rgba(0,0,0,.15);
  cursor: grab;
  flex-shrink: 0;
  background: var(--warm, #ede8e1);
  background-size: cover !important;
  background-position: center !important;
}
.ibv-hist-mini-rc + .ibv-hist-mini-rc {
  margin-left: 1px;
}
.ibv-hist-mini-rc.missing {
  background: rgba(0,0,0,.1) !important;
}
.ibv-hist-mini-rc .ibv-hist-mini-label {
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 6px;
  line-height: 1;
  color: var(--text, #2c2521);
  background: rgba(255,255,255,.78);
  border-top-right-radius: 3px;
  padding: 1px 2px;
  align-self: flex-end;
  pointer-events: none;
}
.ibv-hist-rc-mask {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 3px;
  background: repeating-linear-gradient(90deg,#222 0,#222 33%,#eee 33%,#eee 66%,#222 66%,#222 100%);
  pointer-events: none;
}
.ibv-hist-rc-crop {
  position: absolute;
  right: 0;
  top: 0;
  width: 0;
  height: 0;
  border-left: 7px solid transparent;
  border-top: 7px solid var(--muted, #8a7f78);
  pointer-events: none;
}
.ibv-hist-actions-gray button {
  color: var(--muted, #8a7f78) !important;
}
.ibv-hist-actions-gray button:hover {
  background: color-mix(in srgb, var(--border, #d7cdc3) 72%, transparent) !important;
  color: var(--text, #2c2521) !important;
}

/* ── Ref Wrapper (one warp = multiple RCs + text) ────────────── */
.ibv-ref-wrapper {
  /* Plain inline (not inline-flex): an inline-flex box is atomic for line-
     breaking purposes — it can never be sliced across two lines, only grow
     taller as a single unbroken rectangle. Feedback wants the opposite: when
     a warp's text is too long for one line, each visual line should look
     like its own boxed segment (border/background repeated per line) so it
     reads more naturally alongside whatever prompt text follows it — while
     staying ONE actual element the whole time (drag/click handlers, the data
     model, everything still targets this single node; only the rendering is
     sliced). Plain `inline` lets the browser's line-breaking fragment it
     normally, and box-decoration-break:clone (below) re-applies the border/
     background/padding to each resulting fragment. */
  display: inline;
  border: 1px solid rgba(200, 90, 52, .45);
  border-radius: 6px;
  background: rgba(200, 90, 52, .08);
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
  /* Warp is a visible container clearly larger than the RC chip(s) inside it
     (feedback: "Warp 需要大于 Refclip") — the orange frame margin makes the
     whole warp an obvious grab target distinct from the inner RefClip. */
  padding: 3px 4px;
  vertical-align: middle;
  margin: 0 2px;
  user-select: none;
  position: relative;
  line-height: 1;
}
.ibv-ref-wrapper.chip-hov,
.ibv-ref-wrapper:hover {
  border-color: var(--ibv-accent);
  background: rgba(200, 90, 52, .14);
}
.ibv-ref-wrapper.broken {
  border-color: rgba(138, 127, 120, .5) !important;
  background: rgba(138, 127, 120, .18) !important;
  opacity: .72;
}
.ibv-ref-wrapper.broken .ibv-chip-a { background: #8a7f78 !important; }

/* ── RC chip (one per image in warp) ────────────────────────── */
.ibv-rc-chip {
  display: inline-flex;
  align-items: stretch;
  height: 26px;
  background: transparent;
  vertical-align: middle;
  position: relative;
  top: -2px;
  overflow: visible;
  flex-shrink: 0;
}
.ibv-rc-chip + .ibv-rc-chip { margin-left: 2px; }

/* A: drag handle — solid orange box with the white RC number by default;
   on hover the number turns into the 6-dot ⠿ grip (centered) to signal drag.
   (revised per feedback: keep the number编号 visible; only reveal dots on hover) */
.ibv-chip-a {
  width: 18px;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: var(--ibv-accent, #c85a34);
  border-radius: 4px 0 0 4px;
  cursor: grab;
  font-size: 11px;
  font-weight: 700;
  color: #fff;
  flex-shrink: 0;
  position: relative;
  user-select: none;
}
.ibv-chip-a:active { cursor: grabbing; }
.ibv-chip-a::after {
  content: '';
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity .12s;
  pointer-events: none;
  /* 2 columns x 3 rows = 6 white dots, centered over the 18x26 handle.
     Origin at 0 0 so dots land at x=4.5/13.5 and y=4.33/13/21.67 (evenly inset,
     3 clean rows) instead of clipping half-dots against the top/bottom edges. */
  background: radial-gradient(circle, #fff 1.1px, transparent 1.1px);
  background-size: 9px 8.667px;
  background-position: 0px 0px;
}
/* On hover: hide the number, reveal the ⠿ dots (both centered). */
.ibv-chip-a:hover { color: transparent; }
.ibv-chip-a:hover::after { opacity: 1; }

/* ── Section (text-only warp, no image, 2026-07-11) ─────────────
   Same .ibv-ref-wrapper base (inline + box-decoration-break:clone, so long
   Section text still gets the "one bordered box per visual line" treatment)
   with a paler, more yellow accent so it reads as visually distinct from an
   image RC's warp at a glance. */
.ibv-section-wrapper {
  border-color: rgba(215, 163, 92, .5);
  background: var(--ibv-accent-section-soft, #f7ecd8);
}
.ibv-section-wrapper.chip-hov,
.ibv-section-wrapper:hover {
  border-color: var(--ibv-accent-section, #d7a35c);
  background: rgba(215, 163, 92, .22);
}
.ibv-section-chip {
  display: inline-flex;
  /* center (not stretch): the handle/toggle are a fixed 26px square, but the
     text run's own line-height is much shorter (see .ibv-section-text) — with
     align-items:stretch the handle/toggle used to fill the full row height
     while the text sat at its own natural (shorter) height inside that same
     row, so the two visually drifted out of vertical alignment with each
     other (2026-07-13 feedback item 4: "和文字上下居中对齐"). Centering
     everything on the same baseline row fixes that; the handle/toggle keep
     their 26px height via an explicit height rule now instead of stretch. */
  align-items: center;
  height: 26px;
  background: transparent;
  vertical-align: middle;
  position: relative;
  top: -2px;
  overflow: visible;
}
/* Lettered handle — mirrors .ibv-chip-a (18px, flex-centered, hover reveals
   the ⠿ grip dots) but with the paler section accent and a letter (A-Z, then
   AA/AB… past 26 — see toColumnLetters()) instead of a number. Leftmost
   element in the chip (2026-07-13 feedback item 3: handle/toggle swapped so
   the handle — the actual drag target — reads first, left-to-right). */
.ibv-chip-a-section {
  width: 18px;
  height: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: var(--ibv-accent-section, #d7a35c);
  border-radius: 4px 0 0 4px;
  cursor: grab;
  font-size: 11px;
  font-weight: 700;
  color: #fff;
  flex-shrink: 0;
  position: relative;
  user-select: none;
}
.ibv-chip-a-section:active { cursor: grabbing; }
.ibv-chip-a-section::after {
  content: '';
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity .12s;
  pointer-events: none;
  background: radial-gradient(circle, #fff 1.1px, transparent 1.1px);
  background-size: 9px 8.667px;
  background-position: 0px 0px;
}
.ibv-chip-a-section:hover { color: transparent; }
.ibv-chip-a-section:hover::after { opacity: 1; }
/* Compact/expand toggle — sits to the RIGHT of the handle now, same width, a
   plain outlined square (not the solid accent fill the handle itself uses,
   so the two don't visually merge into one wide handle). Squared off on both
   sides: the handle to its left already owns the chip's rounded left corner,
   and the text run follows immediately after with no radius of its own. */
.ibv-chip-toggle-section {
  width: 18px;
  height: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--ibv-bg-soft, #f0e8de);
  border: 1px solid rgba(215, 163, 92, .5);
  border-left: none;
  border-radius: 0;
  cursor: pointer;
  font-size: 10px;
  color: var(--ibv-accent-section, #d7a35c);
  flex-shrink: 0;
  user-select: none;
}
.ibv-chip-toggle-section:hover { background: rgba(215, 163, 92, .18); }
.ibv-section-text {
  display: inline;
  padding: 0 6px;
  font-size: 15px;
  /* Explicit line-height (was unset, so it inherited the parent
     .ibv-warp-box's line-height:2.8 straight onto the caret — a text
     cursor's rendered height tracks the line box it sits in, so the caret
     looked roughly twice normal size, 2026-07-13 feedback item 5. Matching
     .ibv-warp-gap's own 1.35 here fixes both the caret and keeps this text
     run's line height consistent with the rest of the warp's inline text). */
  line-height: 1.35;
  color: var(--ibv-text);
  white-space: normal;
  cursor: text;
  outline: none;
}

/* B: image thumbnail */
.ibv-chip-b {
  width: 62px;
  height: 26px;
  display: flex;
  position: relative;
  overflow: hidden;
  cursor: pointer;
  border-radius: 0 4px 4px 0;
  flex-shrink: 0;
}
.ibv-chip-b::after {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(200, 90, 52, 0);
  transition: background .15s;
  pointer-events: none;
  border-radius: 0 4px 4px 0;
}
.ibv-chip-b:hover::after { background: rgba(200, 90, 52, .35); }
.ibv-chip-b.drag-over::after { background: rgba(200, 90, 52, .6) !important; outline: 2px solid var(--ibv-accent); outline-offset: -2px; }
[data-dock-chip] span.drag-over {
  outline: 2px solid var(--ibv-accent);
  outline-offset: -2px;
}
.ibv-chip-b-slot {
  flex: 1;
  min-width: 0;
  position: relative;
  overflow: hidden;
}
.ibv-chip-b-slot img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
  pointer-events: none;
}
.ibv-chip-b-slot.ibv-chip-b-missing {
  background: rgba(0,0,0,.12);
  display: flex;
  align-items: center;
  justify-content: center;
}
/* Mask/crop indicator dots — upper-right of the thumbnail, stacked so both
   can show at once without colliding. Mask sits closest to the corner. */
.ibv-chip-b-slot.has-mask::after,
.ibv-chip-b-slot.has-crop::before {
  content: '';
  position: absolute;
  top: 2px;
  width: 6px; height: 6px;
  border-radius: 50%;
  pointer-events: none; z-index: 2;
  box-shadow: 0 0 0 1px rgba(0,0,0,.35);
}
.ibv-chip-b-slot.has-mask::after {
  right: 2px;
  background: var(--ibv-accent);
}
.ibv-chip-b-slot.has-crop::before {
  right: 10px;
  background: #fff;
}
/* Pending (saved-but-not-run) expand — bottom-left, amber, distinct from the
   mask/crop dots above so "queued, will run at generate time" doesn't read
   as "already has a mask/crop applied". A real element (not ::after) since
   has-mask already occupies that pseudo-element slot and a chip can have
   both a mask AND a pending expand queued at once. */
.ibv-chip-b-slot .ibv-pending-expand-dot {
  content: '';
  position: absolute;
  bottom: 2px; left: 2px;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: #b8862e;
  pointer-events: none; z-index: 2;
  box-shadow: 0 0 0 1px rgba(0,0,0,.35);
}

/* ── Role label (editable, after chips) ──────────────────────── */
.ibv-role-label {
  display: inline;
  padding: 1px 6px 1px 4px;
  font-size: 14px;
  font-weight: 400;
  vertical-align: middle;
  cursor: text;
  outline: none;
  color: var(--ibv-text);
  line-height: 1;
  min-width: 8px;
  white-space: nowrap;
  background: transparent;
}

/* ── Text gap between RCs inside warp ───────────────────────── */
.ibv-warp-gap {
  font-size: 15px;
  color: var(--ibv-text);
  padding: 0 3px;
  vertical-align: middle;
  position: relative;
  top: -2px;
  white-space: normal;
  line-height: 1.35;
  cursor: text;
  outline: none;
  user-select: text;
  /* Editable gap after the RC — stays in the DOM (typeable, droppable) but is
     not visually boxed; kept invisible per feedback, only the sizing/hit-target
     remains so it's still discoverable by cursor/focus behavior alone. Still a
     single logical line of text (no literal '\n' insertion, Enter is untouched
     — see makeWarpUnit's keydown handler); this is purely about letting long
     text WRAP visually at word boundaries instead of forcing the whole warp
     pill to grow wider without bound.
     display MUST be inline/inline-block, not inline-flex: makeWarpUnit() wraps
     every character (including spaces) of the gap's text in its own
     .ibv-warp-char span for drag/insert-point tracking. Under flex, each of
     those becomes an independent flex item — flex items don't wrap onto a new
     row based on white-space (that only governs text *within* a box; wrapping
     flex items themselves needs flex-wrap, which was never set, so they all
     stayed on one never-ending row), and worse, a flex item whose only content
     is a single space character collapsed to zero visible width, so words ran
     together with no gaps at all. Plain inline text flow lets the char spans
     wrap and space normally, same as any other text.
     display: inline, not inline-block: inline-block is ALSO atomic for line-
     breaking (same problem class as inline-flex, just one level up) — it can
     wrap its OWN content internally, but the .ibv-ref-wrapper's border-per-
     line cloning (box-decoration-break:clone, see .ibv-ref-wrapper) can only
     clone onto line fragments that the browser's line-breaking actually
     produces, and an atomic inline-block only ever contributes ONE fragment
     to its parent's line-breaking no matter how tall it grows internally —
     verified this produced exactly 2 boxes total (one holding only the RC
     chip, one holding the entire — internally multi-line — gap) instead of
     one box per visual line of text. Plain inline merges the chip and every
     char span into one continuous line-breaking flow, so each real visual
     line gets its own cloned box. min-width/min-height are dropped since
     plain inline elements ignore sized dimensions anyway (CSS spec, non-
     replaced inline boxes) — the empty-gap `<br>` fallback in makeWarpUnit()
     already gives an empty gap one line's worth of clickable height. */
  display: inline;
  border-radius: 3px;
  background: transparent;
  box-shadow: none;
}

/* ── Chip menu ───────────────────────────────────────────────── */
.ibv-chip-menu {
  position: fixed;
  background: var(--ibv-card);
  border: 1px solid var(--ibv-border);
  border-radius: 8px;
  box-shadow: 0 6px 24px rgba(0,0,0,.16);
  z-index: 9200;
  min-width: 210px;
  display: none;
  overflow: hidden;
  font-family: inherit;
}
.ibv-chip-menu.open { display: block; }
.ibv-menu-icons {
  display: flex;
  align-items: center;
  padding: 5px 7px;
  gap: 2px;
  border-bottom: 1px solid var(--ibv-border);
  background: var(--ibv-bg-soft);
}
.ibv-icon-btn {
  width: 30px; height: 28px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 5px;
  cursor: pointer;
  color: var(--ibv-text);
  position: relative;
  transition: background .1s;
  border: 1px solid transparent;
}
.ibv-icon-btn:hover { background: var(--ibv-border); border-color: var(--ibv-border-strong); }
.ibv-icon-btn:hover .ibv-itip { display: block; }
.ibv-menu-phrases-hint {
  font-size: 10px;
  font-weight: 700;
  color: var(--ibv-muted);
  text-transform: uppercase;
  letter-spacing: .06em;
  padding: 7px 10px 2px;
}
.ibv-menu-phrases {
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  gap: 4px;
  padding: 4px 8px 8px;
  max-width: 260px;
  /* 2026-07-25: RefClip phrase library can grow past 20+ entries — without a
     cap the whole .ibv-chip-menu popup stretches to fit them all and can run
     off-screen. Scroll within the phrase list itself so the icon row / remove
     item above and below stay put and reachable. */
  max-height: 180px;
  overflow-y: auto;
}
.ibv-menu-phrases:empty { display: none; }
.ibv-menu-phrase {
  border: 1px solid var(--ibv-border);
  background: var(--ibv-bg-soft);
  color: var(--ibv-text);
  border-radius: 999px;
  padding: 3px 9px;
  font-size: 11px;
  cursor: pointer;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ibv-menu-phrase:hover {
  border-color: var(--ibv-accent);
  background: var(--ibv-peach, rgba(200,90,52,.12));
  color: var(--ibv-accent);
}
.ibv-itip {
  display: none;
  position: absolute;
  bottom: calc(100% + 5px);
  left: 50%;
  transform: translateX(-50%);
  background: rgba(0,0,0,.72);
  color: #fff;
  font-size: 10px;
  padding: 3px 7px;
  border-radius: 3px;
  white-space: nowrap;
  pointer-events: none;
  z-index: 9300;
}
.ibv-chip-menu.below .ibv-itip { bottom: auto; top: calc(100% + 5px); }
.ibv-menu-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  cursor: pointer;
  font-size: 13px;
  color: var(--ibv-text);
  transition: background .1s;
}
.ibv-menu-item:hover { background: var(--ibv-bg); }
.ibv-menu-item.active { background: var(--ibv-accent-soft); color: var(--ibv-accent); }
.ibv-menu-item.remove { color: var(--ibv-danger); border-top: 1px solid var(--ibv-border); }
.ibv-menu-item.remove:hover { background: var(--ibv-danger-soft); }
.ibv-mdot {
  width: 6px; height: 6px;
  border-radius: 50%;
  border: 1.5px solid var(--ibv-muted);
  flex-shrink: 0;
}
.ibv-menu-item.active .ibv-mdot { background: var(--ibv-accent); border-color: var(--ibv-accent); }

/* ── Warp Dock ───────────────────────────────────────────────── */
#ibv-warp-dock {
  padding: 7px 10px;
  border-top: 1px solid var(--ibv-border);
  background: var(--ibv-bg-soft);
  display: flex;
  align-items: center;
  gap: 7px;
  flex-wrap: wrap;
  min-height: 44px;
}
#ibv-warp-dock.ibv-warp-disabled {
  opacity: .72;
  border-style: dashed;
}
.ibv-warp-dock-label {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ibv-muted);
  flex-shrink: 0;
}
.ibv-dock-wrap { position: relative; }
.ibv-dock-thumb {
  width: 36px; height: 36px;
  border-radius: 5px;
  border: 1.5px solid var(--ibv-border);
  overflow: hidden;
  cursor: pointer;
  transition: border-color .15s, box-shadow .15s;
  position: relative;
}
.ibv-dock-thumb:hover,
.ibv-dock-thumb.hl {
  border-color: var(--ibv-accent);
  box-shadow: 0 0 0 1.5px var(--ibv-accent);
}
.ibv-dock-img { display: block; width: 100%; height: 100%; object-fit: cover; }
.ibv-dock-num {
  position: absolute;
  left: 2px; top: 2px;
  min-width: 12px; height: 13px;
  padding: 0 2px;
  background: var(--ibv-accent);
  border-radius: 2px;
  color: #fff;
  font-size: 8px;
  font-weight: 700;
  display: flex; align-items: center; justify-content: center;
  z-index: 3;
  pointer-events: none;
}
.ibv-dock-stripe {
  position: absolute; bottom: 7px; right: 2px;
  width: 14px; height: 3px;
  background: repeating-linear-gradient(90deg,#222 0,#222 33%,#eee 33%,#eee 66%,#222 66%,#222 100%);
  border-radius: 1px; pointer-events: none; z-index: 2;
}
.ibv-dock-marker {
  position: absolute; bottom: 3px; right: 2px;
  width: 14px; height: 3px;
  background: var(--ibv-accent);
  border-radius: 1px; pointer-events: none; z-index: 2;
}
.ibv-dock-x {
  position: absolute; top: -5px; right: -5px;
  width: 14px; height: 14px;
  border-radius: 50%;
  background: var(--ibv-ink);
  color: #fff;
  font-size: 8px;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; z-index: 10;
}
.ibv-dock-x:hover { background: var(--ibv-danger); }
.ibv-dock-anchor { box-shadow: 0 0 0 1.5px var(--ibv-accent); }
.ibv-dock-handle {
  position: absolute;
  left: 2px; bottom: 2px;
  width: 14px; height: 12px;
  border-radius: 2px;
  background: rgba(0,0,0,.45);
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-size: 9px;
  z-index: 4; cursor: grab;
}
.ibv-dock-empty {
  font-size: 11px;
  color: var(--ibv-muted);
  font-style: italic;
}

/* ── Drop caret line ─────────────────────────────────────────── */
.ibv-drop-line {
  position: fixed;
  width: 2px; height: 28px;
  background: var(--ibv-accent);
  border-radius: 1px;
  pointer-events: none;
  z-index: 8999;
}

/* ── Flash hint (re-uses .mask-hint if present, else standalone) */
.ibv-flash-hint {
  position: fixed;
  top: 24px; left: 50%; transform: translateX(-50%);
  background: rgba(0,0,0,.68);
  color: #fff;
  font-size: 12px;
  padding: 6px 14px;
  border-radius: 20px;
  pointer-events: none;
  opacity: 0;
  transition: opacity .25s;
  white-space: nowrap;
  z-index: 9500;
}
.ibv-flash-hint.show { opacity: 1; }
