/**
 * Shared styling for the "helper" character widget (the output of
 * helper.js's init()). Loaded by both the live form (index.html) and the
 * admin builder's Helpers live preview (dash.ezlender.org/helpers.php) —
 * same reasoning as questions/form.css: one shared source so the preview
 * can never visually drift from what actually ships.
 *
 * .ez-helper itself is always position:absolute, positioned by one of the
 * four .ez-helper--<corner> modifier classes, relative to whatever
 * *host-page-defined* container it's mounted into — that container's own
 * positioning (position:fixed covering the live form's viewport; a
 * position:relative preview panel in the dash) is deliberately NOT defined
 * here, since it differs per host (see index.html's #helper-mount and
 * dash's css/helpers.css for each host's own mount-point rules).
 *
 * Relies on --primary being defined by the host page's own :root block
 * (both index.html's style.css and the dash's tokens.css already define
 * matching values), same as questions/form.css does.
 */
.ez-helper {
    position: absolute;
    display: flex;
    align-items: flex-end;
    gap: 10px;
    pointer-events: auto;
    /* Above .ez-helper-shine, its sibling in the mount. The shine is
       appended after the widget (helper.js builds it per message, long
       after init()), so without this it wins on DOM order alone and its
       band/border paint across the avatar circle and any bubble the
       highlighted field happens to sit behind. Both stay above the form
       itself either way — that's the mount's own z-index in the host
       page, a stacking context up from these two. */
    z-index: 2;
}
/* DOM order is [bubble, avatar] (see init()). For a corner widget the
   avatar belongs at the edge and the bubble should extend inward toward
   the center of the screen — so left-corner positions need row-reverse
   (avatar, being last in DOM, ends up first/leftmost) and right-corner
   positions need plain row (avatar ends up last/rightmost). Getting this
   backwards puts the bubble hugging the screen edge and the avatar
   floating toward the center, which is what shipped originally. */
.ez-helper--bottom-left { bottom: 20px; left: 20px; flex-direction: row-reverse; }
.ez-helper--bottom-right { bottom: 20px; right: 20px; flex-direction: row; }
.ez-helper--top-left { top: 20px; left: 20px; flex-direction: row-reverse; align-items: flex-start; }
.ez-helper--top-right { top: 20px; right: 20px; flex-direction: row; align-items: flex-start; }
/* Edge-center positions: still hugging the left/right edge (same 20px
   offset as the corners), but vertically at a fixed percentage down the
   container instead of anchored to its top/bottom — 25%/50%/75% for
   top-*-center/*-center/bottom-*-center respectively. translateY(-50%)
   centers the widget's own height on that percentage mark, rather than
   its top edge landing there (which would look off-center once the
   bubble's height changes between messages). align-items: center, not
   flex-start/flex-end, since there's no top/bottom edge for avatar and
   bubble to align against here — centering them on each other is what
   reads correctly at a floating vertical position. */
.ez-helper--top-left-center { left: 20px; top: 25%; transform: translateY(-50%); flex-direction: row-reverse; align-items: center; }
.ez-helper--left-center { left: 20px; top: 50%; transform: translateY(-50%); flex-direction: row-reverse; align-items: center; }
.ez-helper--bottom-left-center { left: 20px; top: 75%; transform: translateY(-50%); flex-direction: row-reverse; align-items: center; }
.ez-helper--top-right-center { right: 20px; top: 25%; transform: translateY(-50%); flex-direction: row; align-items: center; }
.ez-helper--right-center { right: 20px; top: 50%; transform: translateY(-50%); flex-direction: row; align-items: center; }
.ez-helper--bottom-right-center { right: 20px; top: 75%; transform: translateY(-50%); flex-direction: row; align-items: center; }

.ez-helper-avatar {
    width: 56px;
    height: 56px;
    border-radius: 50%;
    overflow: hidden;
    flex-shrink: 0;
    background: var(--primary, #2563eb);
    box-shadow: 0 4px 12px rgba(0,0,0,0.25);
}
.ez-helper-avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
/* Only present when a clickMessage is configured (helper.js's init) — an
   avatar with no line to say must not advertise itself as pressable. */
.ez-helper-avatar--clickable {
    cursor: pointer;
    transition: transform 0.15s ease-out;
}
.ez-helper-avatar--clickable:hover { transform: scale(1.06); }
.ez-helper-avatar--clickable:active { transform: scale(0.96); }
.ez-helper-avatar--clickable:focus-visible {
    outline: 3px solid var(--primary, #2563eb);
    outline-offset: 3px;
}

/* Pop-in / shrink-out: base rule is the exit state (also the initial
   state before the first message ever shows) and its own transition —
   quick, no overshoot, so an old message gets out of the way fast rather
   than lingering. Adding --visible (helper.js) flips both the target
   opacity/transform *and* the transition timing to the slower, bouncier
   entrance — CSS transitions always animate using whichever rule's
   `transition` is in effect at the moment the property change happens, so
   these can genuinely differ per direction. Keep EXIT_MS/ENTER_MS in
   helper.js in sync with the durations below if you change either. */
.ez-helper-bubble {
    position: relative;
    max-width: 240px;
    background: white;
    color: #1f2937;
    border-radius: 14px;
    padding: 12px 32px 12px 14px;
    font-size: 0.9rem;
    line-height: 1.4;
    box-shadow: 0 8px 20px rgba(0,0,0,0.18);
    opacity: 0;
    transform: scale(0.85);
    transition: opacity 0.12s ease-in, transform 0.12s ease-in;
}
.ez-helper-bubble[hidden] { display: none; }
.ez-helper-bubble--visible {
    opacity: 1;
    transform: scale(1);
    transition: opacity 0.22s cubic-bezier(0.34, 1.56, 0.64, 1), transform 0.22s cubic-bezier(0.34, 1.56, 0.64, 1);
}
/* Shrinks toward whichever side the avatar sits on (see the DOM-order
   comment above) rather than from a fixed center, so the bubble reads as
   collapsing back into the character instead of just shrinking in place. */
.ez-helper--bottom-left .ez-helper-bubble,
.ez-helper--top-left .ez-helper-bubble,
.ez-helper--top-left-center .ez-helper-bubble,
.ez-helper--left-center .ez-helper-bubble,
.ez-helper--bottom-left-center .ez-helper-bubble {
    transform-origin: left center;
}
.ez-helper--bottom-right .ez-helper-bubble,
.ez-helper--top-right .ez-helper-bubble,
.ez-helper--top-right-center .ez-helper-bubble,
.ez-helper--right-center .ez-helper-bubble,
.ez-helper--bottom-right-center .ez-helper-bubble {
    transform-origin: right center;
}
.ez-helper-bubble-text { white-space: pre-line; }
.ez-helper-dismiss {
    position: absolute;
    top: 6px;
    right: 8px;
    border: none;
    background: transparent;
    color: #9ca3af;
    font-size: 1.1rem;
    line-height: 1;
    cursor: pointer;
    padding: 2px;
}
.ez-helper-dismiss:hover { color: #4b5563; }

/* Built by helper.js's showHighlightShine() as an independent overlay
   <div> — positioned via inline styles (getBoundingClientRect() math) to
   match whichever .option-card/.checkbox-item/.input-wrapper/bare-input-
   or-select-or-textarea/.options/.checkbox-group/.btn-prev/.btn-next a
   message's highlight resolves to (render.js's existing DOM contract —
   see helper.js's resolveHighlight). Deliberately NOT a class/pseudo-
   element applied to the target itself: plain <input>/<select>/<textarea>
   are "replaced elements" per the CSS spec, and ::before/::after
   generated content never renders on those at all — an independent,
   always-a-plain-<div> overlay is the only way this reliably shows up
   regardless of the target's own element type.

   The sweep itself is the same effect the dash's questions editor puts on
   its clipboard button when it has items (css/questions.css's
   button.secondary.has-items::after / @keyframes clipboard-shimmer): a
   narrow diagonal gradient band, wider than it looks because both ends
   fade to transparent, travelling across an overflow:hidden box. Two
   differences from that one, both deliberate:
     - It plays ONCE (iteration-count 1 + `forwards`, no `infinite`).
       The clipboard button shimmers forever because it is advertising a
       standing state ("there's something in here"); a helper highlight is
       pointing at one thing at one moment, and a band cycling past the
       same field every few seconds reads as a glitch, not a pointer.
       Nothing resets it either — helper.js builds a brand-new overlay per
       message, so "once" is genuinely once per highlight.
     - The band is brand-tinted rather than white. The clipboard version
       sweeps white over a filled button; these targets are white/near-
       white form controls, where a white band over white is invisible.
   The static border is what carries the highlight for the rest of the
   message's life, after the one-shot sweep has finished and left. */
.ez-helper-shine {
    position: absolute;
    z-index: 1;
    box-sizing: border-box;
    border: 2px solid var(--primary, #2563eb);
    border-radius: 10px;
    overflow: hidden;
    pointer-events: none;
}
.ez-helper-shine-band {
    position: absolute;
    top: 0;
    left: -60%;
    width: 40%;
    height: 100%;
    /* Plain-rgba first, then the themed color-mix over the top: the
       fallback is what non-supporting browsers keep, and it matches
       --primary's own default anyway. */
    background: linear-gradient(120deg, transparent, rgba(37,99,235,0.38), transparent);
    background: linear-gradient(120deg, transparent, color-mix(in srgb, var(--primary, #2563eb) 40%, transparent), transparent);
    animation: ez-helper-shine-kf 1.15s ease-in-out 1 forwards;
}
@keyframes ez-helper-shine-kf {
    from { left: -60%; }
    to { left: 130%; }
}
@media (prefers-reduced-motion: reduce) {
    /* No travelling band at all — the highlight becomes purely the
       static border the sweep would otherwise have left behind, which
       already conveys "this one" without any motion. */
    .ez-helper-shine-band { display: none; }
    /* Keep the pointer cursor and focus ring, drop the springy scale. */
    .ez-helper-avatar--clickable { transition: none; }
    .ez-helper-avatar--clickable:hover,
    .ez-helper-avatar--clickable:active { transform: none; }
    /* Keep the opacity crossfade (still needed to actually swap between
       messages) but drop the scale/bounce and make it near-instant. */
    .ez-helper-bubble,
    .ez-helper-bubble--visible {
        transform: none;
        transition: opacity 0.01s linear;
    }
}

@media (max-width: 480px) {
    .ez-helper-avatar { width: 44px; height: 44px; }
    .ez-helper-bubble { max-width: calc(100vw - 90px); font-size: 0.85rem; padding: 10px 28px 10px 12px; }
    .ez-helper--bottom-left, .ez-helper--bottom-right { bottom: 12px; }
    .ez-helper--top-left, .ez-helper--top-right { top: 12px; }
    .ez-helper--bottom-left, .ez-helper--top-left,
    .ez-helper--top-left-center, .ez-helper--left-center, .ez-helper--bottom-left-center { left: 12px; }
    .ez-helper--bottom-right, .ez-helper--top-right,
    .ez-helper--top-right-center, .ez-helper--right-center, .ez-helper--bottom-right-center { right: 12px; }
}
