/* LeadX Smart Form — public render styles */

*,
*::before,
*::after {
    box-sizing: border-box;
}

.lxsf-body {
    margin: 0;
    padding: 0;
    min-height: 100vh;
    color: var(--lxsf-text, #1e293b);
    font-size: var(--lxsf-font-size, 16px);
    font-family: var(--lxsf-font-family, "Nunito", sans-serif);
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
    background: var(--lxsf-bg, transparent);
    position: relative;
}

/* Every renderable element inside the smart-form app pulls font-family
   from --lxsf-font-family directly. Body-level inheritance alone isn't
   enough:
   - form controls (input/textarea/select/button) have user-agent styles
     that block plain inheritance in some browsers;
   - a legacy inline `<style>` block (lxf_font_html) sets body font-
     family with !important, which can shadow the var-driven cascade in
     narrow cases.
   Explicitly re-declaring the var on the app scope guarantees the font
   picked in Design panel actually reaches every visible text node. */
.lxsf-body,
.lxsf-body .lxsf-app,
.lxsf-body .lxsf-app *,
.lxsf-body input,
.lxsf-body textarea,
.lxsf-body select,
.lxsf-body button,
.lxsf-body optgroup {
    font-family: var(--lxsf-font-family, "Nunito", sans-serif);
}

/* Direct-link "view" mode applies the Embed Link Design background
   (color / gradient / image chosen by the customer under settings
   > view_page). Embed iframe stays transparent so the host page's
   bg always shows through. */
.lxsf-body--view {
    background: #ffffff;
    /* Solid white background as requested */
}

/* SVG overlay pattern — tiled inside the main right-side inset panel */
.lxsf-body--view .lxsf-vp-main::before {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
    background-image: var(--lxsf-vp-pattern, none);
    background-repeat: repeat;
    opacity: var(--lxsf-vp-pattern-opacity, 0.06);
    z-index: 0;
    border-radius: 20px 0 0 20px;
    /* Match the rounded corners of the inset panel */
}

.lxsf-body--view>* {
    position: relative;
    z-index: 1;
}

/* View-page header / footer / form-head-strip text colors —
   Text Colours knob was retired from the Embed Link Design surface;
   these are hard-coded to the previous defaults so the shipping
   look is preserved without the customer-facing option. */
.lxsf-body--view .lxsf-header,
.lxsf-body--view .lxsf-header-name,
.lxsf-body--view .lxsf-visit-btn {
    color: #1e293b;
}

.lxsf-body--view .lxsf-footer,
.lxsf-body--view .lxsf-footer a {
    color: #94a3b8;
}

.lxsf-body--embed {
    background: transparent;
}

.lxsf-header {
    padding: 16px 24px;
    background: #fff;
    border-bottom: 1px solid #e5e7eb;
    font-size: 16px;
    font-weight: 700;
}

.lxsf-header-name a {
    color: inherit;
    text-decoration: none;
}

.lxsf-footer {
    text-align: center;
    padding: 14px 16px;
    font-size: 12px;
    color: #94a3b8;
}

/* Stage — just a block container. No min-height (was eating space the
   visitor never asked for), no align-items / justify-content
   centering (was being driven by --lxsf-card-align which the schema
   doesn't expose anymore). The form's own card_align var still wins
   inside .lxsf-app if a customer sets it. */
.lxsf-stage {
    padding: 32px 0;
}

/* Builder preview — iframe is shorter than the viewport, so the regular
   100vh vertical-center logic creates a huge dead band above the form.
   Anchor the form to the top and use a normal block padding instead. */
.lxsf-stage[data-mode="preview"] {
    min-height: 0;
    align-items: flex-start;
    padding: 24px;
}

/* Form card — fully customizable via design vars. The card_bg can be a
   solid color, gradient, image, or transparent. An optional overlay tint
   and backdrop blur layer on top via the ::before pseudo.
   Padding, border and radius all support per-side values composed by the
   renderer (e.g. "8px 16px 8px 16px" for padding). */
.lxsf-app {
    position: relative;
    width: 100%;
    max-width: var(--lxsf-max-width, 100%);
    /* New schema sets a compound --lxsf-card-margin ("Tpx Rpx Bpx Lpx").
       Legacy per-side vars stay as a fallback for old saved forms. */
    margin: var(--lxsf-card-margin,
            var(--lxsf-card-mt, 40px) var(--lxsf-card-mr, 0) var(--lxsf-card-mb, 40px) var(--lxsf-card-ml, 0));
    background: var(--lxsf-card-bg, transparent);
    padding: var(--lxsf-card-padding, 0);
    border-radius: var(--lxsf-card-radius, 0);
    /* Per-side borders — `border` shorthand can't take 4 widths, so we apply
       each side independently. Each var resolves to "Npx solid color" or "none". */
    border-top: var(--lxsf-card-border-top, var(--lxsf-card-border, none));
    border-right: var(--lxsf-card-border-right, var(--lxsf-card-border, none));
    border-bottom: var(--lxsf-card-border-bottom, var(--lxsf-card-border, none));
    border-left: var(--lxsf-card-border-left, var(--lxsf-card-border, none));
    box-shadow: var(--lxsf-card-shadow, none);
    overflow: hidden;
}

/* Page wrapper (the surrounding stage) — schema-driven padding, margin,
   border, radius. Page padding pads the inside of the wrapper (around the
   form card), separate from the wrapper's outer margin. */
.lxsf-stage {
    background: var(--lxsf-page-bg, transparent);
    padding: var(--lxsf-page-padding, 0);
    margin: var(--lxsf-page-margin, 0);
    border-top: var(--lxsf-page-border-top, none);
    border-right: var(--lxsf-page-border-right, none);
    border-bottom: var(--lxsf-page-border-bottom, none);
    border-left: var(--lxsf-page-border-left, none);
    border-radius: var(--lxsf-page-radius, 0);
}

.lxsf-app::before {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: var(--lxsf-card-overlay, transparent);
    backdrop-filter: blur(var(--lxsf-card-blur, 0px));
    -webkit-backdrop-filter: blur(var(--lxsf-card-blur, 0px));
    border-radius: inherit;
    z-index: 0;
}

.lxsf-app>* {
    position: relative;
    z-index: 1;
}

/* ── Single step / screen card ─────────────────────────────────────
   Animation is fully driven by CSS vars set in applyDesign():
     --lxsf-anim-in-name   : keyframe name (e.g. lxsf-fade-in)
     --lxsf-anim-in-dur    : duration in ms
     --lxsf-anim-in-delay  : delay in ms
     --lxsf-anim-in-ease   : timing function
   Same set with -out- prefix for the leaving screen (applied via the
   .lxsf-exit-active class added by advance()/back()). */
.lxsf-screen {
    animation-name: var(--lxsf-anim-in-name, lxsf-fade-in);
    animation-duration: var(--lxsf-anim-in-dur, 280ms);
    animation-delay: var(--lxsf-anim-in-delay, 0ms);
    animation-timing-function: var(--lxsf-anim-in-ease, ease-out);
    animation-fill-mode: both;
}

.lxsf-screen.lxsf-exit-active {
    animation-name: var(--lxsf-anim-out-name, lxsf-fade-out);
    animation-duration: var(--lxsf-anim-out-dur, 250ms);
    animation-delay: var(--lxsf-anim-out-delay, 0ms);
    animation-timing-function: var(--lxsf-anim-out-ease, ease-in);
    animation-fill-mode: both;
}

/* ── step_slide (direction-aware) ─────────────────────────────────
   The regular slide-left / slide-right options are STATIC — same
   keyframe regardless of nav direction. step_slide is the premium
   Typeform-style variant that flips direction based on how the
   visitor is moving through the form:

     forward  → outgoing screen slides out to the LEFT,
                incoming screen slides in from the RIGHT
     backward → mirror (outgoing to right, incoming from left)

   Implementation: the JS sets `data-anim-in="step_slide"` and
   `data-nav="forward"|"backward"` on every .lxsf-screen at render
   time, and these attribute selectors pin the correct keyframe
   name — no dynamic --lxsf-anim-in-name toggle needed on nav.

   Reuses the existing slide-left / slide-right keyframes so no new
   keyframe blocks are required. */
.lxsf-screen[data-anim-in="step_slide"][data-nav="forward"] {
    animation-name: lxsf-slide-left-in;
}
.lxsf-screen[data-anim-in="step_slide"][data-nav="backward"] {
    animation-name: lxsf-slide-right-in;
}
.lxsf-screen[data-anim-out="step_slide"][data-nav="forward"].lxsf-exit-active {
    animation-name: lxsf-slide-left-out;
}
.lxsf-screen[data-anim-out="step_slide"][data-nav="backward"].lxsf-exit-active {
    animation-name: lxsf-slide-right-out;
}
/* Note: .lxsf-app already has overflow:hidden (line ~151) so sliding
   screens can't spill outside the card during transition. */

/* ── Animation keyframes (in + out per type) ─────────────────────── */
@keyframes lxsf-fade-in {
    from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

@keyframes lxsf-fade-out {
    from {
        opacity: 1;
    }

    to {
        opacity: 0;
    }
}

@keyframes lxsf-slide-up-in {
    from {
        opacity: 0;
        transform: translateY(30px);
    }

    to {
        opacity: 1;
        transform: translateY(0);
    }
}

@keyframes lxsf-slide-up-out {
    from {
        opacity: 1;
        transform: translateY(0);
    }

    to {
        opacity: 0;
        transform: translateY(-30px);
    }
}

@keyframes lxsf-slide-down-in {
    from {
        opacity: 0;
        transform: translateY(-30px);
    }

    to {
        opacity: 1;
        transform: translateY(0);
    }
}

@keyframes lxsf-slide-down-out {
    from {
        opacity: 1;
        transform: translateY(0);
    }

    to {
        opacity: 0;
        transform: translateY(30px);
    }
}

@keyframes lxsf-slide-left-in {
    from {
        opacity: 0;
        transform: translateX(30px);
    }

    to {
        opacity: 1;
        transform: translateX(0);
    }
}

@keyframes lxsf-slide-left-out {
    from {
        opacity: 1;
        transform: translateX(0);
    }

    to {
        opacity: 0;
        transform: translateX(-30px);
    }
}

@keyframes lxsf-slide-right-in {
    from {
        opacity: 0;
        transform: translateX(-30px);
    }

    to {
        opacity: 1;
        transform: translateX(0);
    }
}

@keyframes lxsf-slide-right-out {
    from {
        opacity: 1;
        transform: translateX(0);
    }

    to {
        opacity: 0;
        transform: translateX(30px);
    }
}

/* zoom-in: incoming screen grows into place / outgoing shrinks away */
@keyframes lxsf-zoom-in-in {
    from {
        opacity: 0;
        transform: scale(0.85);
    }

    to {
        opacity: 1;
        transform: scale(1);
    }
}

@keyframes lxsf-zoom-in-out {
    from {
        opacity: 1;
        transform: scale(1);
    }

    to {
        opacity: 0;
        transform: scale(0.85);
    }
}

/* zoom-out: incoming starts big and settles, outgoing inflates as it leaves */
@keyframes lxsf-zoom-out-in {
    from {
        opacity: 0;
        transform: scale(1.15);
    }

    to {
        opacity: 1;
        transform: scale(1);
    }
}

@keyframes lxsf-zoom-out-out {
    from {
        opacity: 1;
        transform: scale(1);
    }

    to {
        opacity: 0;
        transform: scale(1.15);
    }
}

/* Bounce variants use a back-out / back-in cubic-bezier inside the keyframe
   itself so they read as springy even with linear easing. The screen-level
   timing function still multiplies. */
@keyframes lxsf-bounce-in-in {
    0% {
        opacity: 0;
        transform: scale(0.3);
    }

    60% {
        opacity: 1;
        transform: scale(1.06);
    }

    80% {
        transform: scale(0.97);
    }

    100% {
        opacity: 1;
        transform: scale(1);
    }
}

@keyframes lxsf-bounce-in-out {
    0% {
        opacity: 1;
        transform: scale(1);
    }

    20% {
        transform: scale(0.97);
    }

    100% {
        opacity: 0;
        transform: scale(0.3);
    }
}

@keyframes lxsf-bounce-out-in {
    0% {
        opacity: 0;
        transform: scale(1.3);
    }

    60% {
        opacity: 1;
        transform: scale(0.95);
    }

    100% {
        opacity: 1;
        transform: scale(1);
    }
}

@keyframes lxsf-bounce-out-out {
    0% {
        opacity: 1;
        transform: scale(1);
    }

    100% {
        opacity: 0;
        transform: scale(1.3);
    }
}

@keyframes lxsf-bounce-up-in {
    0% {
        opacity: 0;
        transform: translateY(60px);
    }

    60% {
        opacity: 1;
        transform: translateY(-12px);
    }

    80% {
        transform: translateY(6px);
    }

    100% {
        transform: translateY(0);
    }
}

@keyframes lxsf-bounce-up-out {
    0% {
        opacity: 1;
        transform: translateY(0);
    }

    20% {
        transform: translateY(12px);
    }

    100% {
        opacity: 0;
        transform: translateY(-60px);
    }
}

@keyframes lxsf-bounce-down-in {
    0% {
        opacity: 0;
        transform: translateY(-60px);
    }

    60% {
        opacity: 1;
        transform: translateY(12px);
    }

    80% {
        transform: translateY(-6px);
    }

    100% {
        transform: translateY(0);
    }
}

@keyframes lxsf-bounce-down-out {
    0% {
        opacity: 1;
        transform: translateY(0);
    }

    20% {
        transform: translateY(-12px);
    }

    100% {
        opacity: 0;
        transform: translateY(60px);
    }
}

/* `none` — pseudo-keyframe so animation-name has SOMETHING to bind to,
   while the screen instantly renders without movement. */
@keyframes lxsf-none-in {

    from,
    to {
        opacity: 1;
        transform: none;
    }
}

@keyframes lxsf-none-out {

    from,
    to {
        opacity: 0;
        transform: none;
    }
}

.lxsf-screen-head {
    margin-bottom: 24px;
}

.lxsf-q-num {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 12px;
    color: var(--lxsf-muted, #94a3b8);
    margin-bottom: 8px;
    font-weight: 500;
}

.lxsf-q-num svg {
    width: 14px;
    height: 14px;
}

.lxsf-title {
    /* Per-element label_* keys override heading_* legacy defaults */
    font-size: var(--lxsf-label-font-size, var(--lxsf-heading-size, clamp(22px, 3.5vw, 32px)));
    font-weight: var(--lxsf-label-font-weight, var(--lxsf-heading-weight, 700));
    color: var(--lxsf-label-color, var(--lxsf-text, #1e293b));
    padding: var(--lxsf-label-padding, 0);
    margin: var(--lxsf-label-margin, 0);
    line-height: 1.25;
}

.lxsf-required-star {
    color: #dc2626;
    margin-left: 4px;
    font-weight: 400;
}

.lxsf-desc {
    font-size: var(--lxsf-desc-font-size, 14px);
    font-weight: var(--lxsf-desc-font-weight, 400);
    color: var(--lxsf-desc-color, var(--lxsf-muted, #6b7280));
    padding: var(--lxsf-desc-padding, 0);
    margin: var(--lxsf-desc-margin, 8px 0 0);
    line-height: 1.55;
}

.lxsf-desc--above {
    /* When desc sits above the title, default to a bottom-only gap instead of
       the top-gap that the default rule uses. Schema margin overrides this. */
    margin: var(--lxsf-desc-margin, 0 0 8px);
}

/* ── Typewriter caret ──────────────────────────────────────────
   The title is filled in character-by-character by JS (see
   typewriter() in lxf-smart-form.js). A blinking caret sits at
   the current write position while typing and is removed shortly
   after the text finishes. */
.lxsf-caret {
    display: inline-block;
    width: 0.08em;
    min-width: 2px;
    height: 1em;
    margin-left: 2px;
    vertical-align: -0.15em;
    /* Solid dark caret — always the label's color, never faded by
       currentColor's alpha. The blink flips opacity instantly at the
       midpoint (no interpolation), so it snaps on/off rather than
       fading to gray in between. */
    background-color: var(--lxsf-label-color, var(--lxsf-text, #0f172a));
    border-radius: 1px;
    animation: lxsf-caret-blink 1s linear infinite;
}

@keyframes lxsf-caret-blink {
    0%, 49%   { opacity: 1; }
    50%, 100% { opacity: 0; }
}

/* Descriptions AND the whole screen body (inputs, choices, buttons,
   etc.) stay hidden until the title finishes typing and JS adds the
   fade-in class — otherwise the rest of the screen would flash into
   view before the title reveal completes. */
.lxsf-desc,
.lxsf-desc--above,
.lxsf-screen-body {
    opacity: 0;
}

.lxsf-desc.lxsf-fade-in,
.lxsf-desc--above.lxsf-fade-in,
.lxsf-screen-body.lxsf-fade-in {
    /* Standard Material-style curve — smooth acceleration & deceleration
       (no aggressive tail that reads as a snap). translate3d forces a
       compositor layer so opacity/transform run on the GPU and text
       doesn't repaint every frame during the rise. */
    animation: lxsf-desc-fade-in 650ms cubic-bezier(0.4, 0, 0.2, 1) both;
    will-change: opacity, transform;
}

/* Small stagger — body follows the desc by a hair so both feel like
   part of the same wave rather than a double-hit. */
.lxsf-screen-body.lxsf-fade-in {
    animation-delay: 80ms;
}

/* Backward-nav snap — visitor already saw this screen play out once,
   so we skip the typewriter + rise-in reveal and just make the desc /
   body appear at their final opacity. Sits alongside .lxsf-fade-in on
   the same targets so it beats the base opacity:0 rule but doesn't
   run any keyframe. Between-step slide transition still plays. */
.lxsf-desc.lxsf-fade-in-instant,
.lxsf-desc--above.lxsf-fade-in-instant,
.lxsf-screen-body.lxsf-fade-in-instant {
    opacity: 1;
    animation: none;
}

@keyframes lxsf-desc-fade-in {
    from {
        opacity: 0;
        transform: translate3d(0, 10px, 0);
    }
    to {
        opacity: 1;
        transform: translate3d(0, 0, 0);
    }
}

@media (prefers-reduced-motion: reduce) {
    .lxsf-caret { display: none; }
    .lxsf-desc,
    .lxsf-desc--above,
    .lxsf-screen-body { opacity: 1; animation: none !important; }
}

/* ── Inputs ─────────────────────────────────────────────────────
   Three style variants driven by [data-input-style]:
   - underline (default) : flat, bottom border only
   - boxed                : full border with rounded corners
   - minimal              : no border, just text
   ────────────────────────────────────────────────────────────── */
.lxsf-input,
.lxsf-textarea,
.lxsf-select {
    width: 100%;
    max-width: var(--lxsf-input-max-width, 520px);
    /* TRBL padding wins over the single-value legacy --lxsf-input-padding. */
    padding: var(--lxsf-input-padding, 12px 0);
    background: var(--lxsf-input-bg, transparent);
    font-size: var(--lxsf-input-font-size, 20px);
    font-family: inherit;
    color: var(--lxsf-input-text, #1e293b);
    outline: none;
    transition: border-color 0.2s;
}

.lxsf-textarea {
    height: var(--lxsf-textarea-height, auto);
}

.lxsf-select {
    font-size: var(--lxsf-select-font-size, var(--lxsf-input-font-size, 20px));
    max-width: var(--lxsf-select-max-width, var(--lxsf-input-max-width, 520px));
}

/* ── Custom dropdown (Typeform-style) ────────────────────────────
   Replaces native <select> with an underlined trigger button + a
   floating panel that holds a search input and clickable option
   cards. Theme is driven by the form's existing CSS vars so the
   dropdown inherits whatever palette the builder chose. */
.lxsf-dd {
    position: relative;
    width: 100%;
    max-width: var(--lxsf-select-max-width, var(--lxsf-input-max-width, 520px));
}

.lxsf-dd-trigger {
    width: 100%;
    background: var(--lxsf-input-bg, transparent);
    border: none;
    padding: var(--lxsf-input-padding, 12px 0);
    font-size: var(--lxsf-select-font-size, var(--lxsf-input-font-size, 20px));
    color: var(--lxsf-input-text, #1e293b);
    font-family: inherit;
    text-align: left;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    outline: none;
    transition: border-color 0.2s;
}

/* Open state — trigger gets swapped out entirely; the panel renders
   in its place. */
.lxsf-dd--open .lxsf-dd-trigger {
    display: none;
}

/* Underline variant trigger */
:root[data-input-style="underline"] .lxsf-dd-trigger {
    border-bottom: var(--lxsf-input-border-width, 2px) solid var(--lxsf-border, #94a3b8);
    border-radius: 0;
    padding-left: 0;
    padding-right: 0;
}

/* Boxed variant trigger */
:root[data-input-style="boxed"] .lxsf-dd-trigger {
    border: var(--lxsf-input-border-width, 2px) solid var(--lxsf-border, #cbd5e1);
    border-radius: var(--lxsf-input-radius, 8px);
}

.lxsf-dd--open .lxsf-dd-trigger,
:root[data-input-style="underline"] .lxsf-dd--open .lxsf-dd-trigger {
    border-color: var(--lxsf-input-focus, var(--lxsf-accent, #111827));
}

.lxsf-dd-value {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.lxsf-dd-placeholder {
    color: var(--lxsf-placeholder-color, var(--lxsf-placeholder, #cbd5e1));
    opacity: 0.85;
}

.lxsf-dd-chev {
    display: inline-flex;
    align-items: center;
    color: inherit;
    opacity: 0.7;
    transition: transform 0.2s ease, opacity 0.2s ease;
    flex-shrink: 0;
}

.lxsf-dd-chev svg {
    width: 20px;
    height: 20px;
}

.lxsf-dd--open .lxsf-dd-chev {
    transform: rotate(180deg);
    opacity: 1;
}

/* Panel — appears in place of the trigger when open. Same width, no
   extra margin (it visually replaces the select box, doesn't sit
   below it). Light surface, subtle border, scrollable option list. */
.lxsf-dd-panel {
    display: none;
    background: var(--lxsf-dd-panel-bg, #ffffff);
    border: 1px solid var(--lxsf-dd-panel-border, rgba(15, 23, 42, 0.10));
    border-radius: 12px;
    padding: 14px;
    box-shadow: 0 4px 14px -4px rgba(15, 23, 42, 0.08);
    max-height: 380px;
    flex-direction: column;
    gap: 10px;
}

.lxsf-dd--open .lxsf-dd-panel {
    display: flex;
}

/* Search row */
.lxsf-dd-search-wrap {
    position: relative;
    display: flex;
    align-items: center;
    border-bottom: 1px solid var(--lxsf-dd-divider, rgba(15, 23, 42, 0.10));
    padding: 4px 0 8px;
}

.lxsf-dd-search {
    flex: 1;
    background: transparent;
    border: none;
    outline: none;
    font-size: 15px;
    color: #0f172a;
    font-family: inherit;
    padding: 4px 32px 4px 0;
}

.lxsf-dd-search::placeholder {
    color: #94a3b8;
    opacity: 1;
}

.lxsf-dd-search-icon {
    position: absolute;
    right: 0;
    top: 50%;
    transform: translateY(-50%);
    color: #64748b;
    pointer-events: none;
}

.lxsf-dd-search-icon svg {
    width: 18px;
    height: 18px;
}

/* Option list (scrollable) */
.lxsf-dd-options {
    display: flex;
    flex-direction: column;
    gap: 6px;
    overflow-y: auto;
    max-height: 300px;
    padding-right: 2px;
}

.lxsf-dd-option {
    width: 100%;
    background: var(--lxsf-dd-option-bg, #f8fafc);
    border: 1.5px solid transparent;
    border-radius: 8px;
    padding: 12px 14px;
    text-align: left;
    color: #1e293b;
    font-family: inherit;
    font-size: 15px;
    cursor: pointer;
    transition: background 0.12s ease, border-color 0.12s ease, transform 0.12s ease;
}

/* Staggered fade+slide entrance for dropdown options — every time
   the panel opens, each option pops in slightly delayed relative to
   the one above it (~35ms per row). Gives the "cascade" feel of
   native macOS/iOS dropdowns without a JS orchestrator. */
.lxsf-dd--open .lxsf-dd-option {
    animation: lxsf-dd-option-in 260ms cubic-bezier(0.16, 1, 0.3, 1) both;
}

.lxsf-dd--open .lxsf-dd-option:nth-child(1)  { animation-delay: 0ms;   }
.lxsf-dd--open .lxsf-dd-option:nth-child(2)  { animation-delay: 35ms;  }
.lxsf-dd--open .lxsf-dd-option:nth-child(3)  { animation-delay: 70ms;  }
.lxsf-dd--open .lxsf-dd-option:nth-child(4)  { animation-delay: 105ms; }
.lxsf-dd--open .lxsf-dd-option:nth-child(5)  { animation-delay: 140ms; }
.lxsf-dd--open .lxsf-dd-option:nth-child(6)  { animation-delay: 175ms; }
.lxsf-dd--open .lxsf-dd-option:nth-child(7)  { animation-delay: 210ms; }
.lxsf-dd--open .lxsf-dd-option:nth-child(8)  { animation-delay: 245ms; }
.lxsf-dd--open .lxsf-dd-option:nth-child(9)  { animation-delay: 280ms; }
.lxsf-dd--open .lxsf-dd-option:nth-child(10) { animation-delay: 315ms; }
/* Options beyond 10 all fire together at the 10-item cap to avoid a
   1-second stagger on long lists (Countries etc.). */
.lxsf-dd--open .lxsf-dd-option:nth-child(n+11) { animation-delay: 315ms; }

@keyframes lxsf-dd-option-in {
    from {
        opacity: 0;
        transform: translateY(-6px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

@media (prefers-reduced-motion: reduce) {
    .lxsf-dd--open .lxsf-dd-option { animation: none !important; }
    .lxsf-textarea { transition: border-color 0.2s ease, box-shadow 0.2s ease !important; }
}

.lxsf-dd-option:hover {
    background: var(--lxsf-dd-option-hover, #f1f5f9);
}

.lxsf-dd-option--selected {
    border-color: var(--lxsf-accent, #111827);
    background: var(--lxsf-dd-option-selected, #ffffff);
    font-weight: 600;
    color: #0f172a;
}

.lxsf-dd-empty {
    padding: 18px 4px;
    text-align: center;
    color: #94a3b8;
    font-size: 14px;
}

/* Slim scrollbar styling for the options list. */
.lxsf-dd-options::-webkit-scrollbar {
    width: 6px;
}

.lxsf-dd-options::-webkit-scrollbar-track {
    background: transparent;
}

.lxsf-dd-options::-webkit-scrollbar-thumb {
    background: rgba(15, 23, 42, 0.18);
    border-radius: 3px;
}

.lxsf-dd-options::-webkit-scrollbar-thumb:hover {
    background: rgba(15, 23, 42, 0.28);
}

.lxsf-input::placeholder,
.lxsf-textarea::placeholder {
    color: var(--lxsf-placeholder-color, var(--lxsf-placeholder, #cbd5e1));
    font-size: var(--lxsf-placeholder-font-size, inherit);
    font-weight: var(--lxsf-placeholder-font-weight, inherit);
}

.lxsf-textarea {
    /* No forced min-height — the textarea starts the same height as a
       regular text input. When the customer sets `rows` in field config
       or `--lxsf-textarea-height` in design, those take over. */
    resize: var(--lxsf-textarea-resize, vertical);
    /* Smooth autosize — JS updates `height` inline as the visitor
       types; this transition makes each row-growth feel liquid instead
       of snapping. Duration tuned so multi-line paste still feels
       responsive (fast) but single-char typing shows the ease. */
    transition: height 0.18s cubic-bezier(0.4, 0, 0.2, 1),
                border-color 0.2s ease,
                box-shadow 0.2s ease,
                background-size 0.35s cubic-bezier(0.16, 1, 0.3, 1);
}

/* ── Live validity badge (tick / cross) ────────────────────────────
   Wraps text-like inputs (email / phone / URL / number) with an
   inline shell so a validity indicator can sit at the right edge.
   JS sets data-state on the badge as the visitor types:
     empty   → no icon (neutral)
     valid   → green check draws in
     invalid → red X strokes in
   The check + cross share one badge slot; CSS shows/hides via
   data-state so state changes are a single attribute flip.
   Both icons animate their strokes on state-in via stroke-dashoffset
   so the mark "draws" rather than pops. */
.lxsf-input-shell {
    position: relative;
    display: block;
    width: 100%;
    max-width: var(--lxsf-input-max-width, 520px);
}

/* Room for the validity badge — !important because the per-variant
   :root[data-input-style="..."] rules have higher specificity than
   `.lxsf-input-shell .lxsf-input` alone and would otherwise re-set
   padding-right: 0 on the underline variant, letting the badge
   overlap the last few characters. */
.lxsf-input-shell .lxsf-input {
    padding-right: 40px !important;
    width: 100%;
    max-width: 100%;
}

.lxsf-validity {
    position: absolute;
    right: 4px;
    top: 50%;
    transform: translateY(-50%);
    width: 24px;
    height: 24px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
    background: transparent;
    color: transparent;
    transition: background 0.2s ease, color 0.2s ease, transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.lxsf-validity[data-state="valid"] {
    background: rgba(22, 163, 74, 0.15);
    color: #16a34a;
    transform: translateY(-50%) scale(1);
    animation: lxsf-validity-pop 320ms cubic-bezier(0.34, 1.56, 0.64, 1);
}

.lxsf-validity[data-state="invalid"] {
    background: rgba(220, 38, 38, 0.12);
    color: #dc2626;
    transform: translateY(-50%) scale(1);
    animation: lxsf-validity-pop 320ms cubic-bezier(0.34, 1.56, 0.64, 1);
}

@keyframes lxsf-validity-pop {
    0%   { transform: translateY(-50%) scale(0.6); }
    60%  { transform: translateY(-50%) scale(1.15); }
    100% { transform: translateY(-50%) scale(1); }
}

.lxsf-validity-icon {
    position: absolute;
    width: 14px;
    height: 14px;
    opacity: 0;
    transition: opacity 0.15s ease;
}

.lxsf-validity[data-state="valid"] .lxsf-validity-icon--check {
    opacity: 1;
    /* Draw-in effect on the polyline — stroke-dasharray covers the
       full path length (~24 units at 24×24 viewBox), then dashoffset
       animates from that length to 0 revealing the mark left-to-right. */
    stroke-dasharray: 24;
    stroke-dashoffset: 24;
    animation: lxsf-validity-draw 260ms cubic-bezier(0.4, 0, 0.2, 1) 60ms forwards;
}

.lxsf-validity[data-state="invalid"] .lxsf-validity-icon--cross {
    opacity: 1;
    /* Two-line X drawn together — dasharray equals the sum of both
       diagonal lengths so they both fill in a single tick. */
    stroke-dasharray: 20;
    stroke-dashoffset: 20;
    animation: lxsf-validity-draw 260ms cubic-bezier(0.4, 0, 0.2, 1) 60ms forwards;
}

@keyframes lxsf-validity-draw {
    to { stroke-dashoffset: 0; }
}

@media (prefers-reduced-motion: reduce) {
    .lxsf-validity,
    .lxsf-validity[data-state="valid"],
    .lxsf-validity[data-state="invalid"] {
        animation: none !important;
        transition: background 0.15s ease, color 0.15s ease !important;
    }
    .lxsf-validity-icon {
        animation: none !important;
        stroke-dashoffset: 0 !important;
    }
}

/* Underline variant (default) — bottom border only.
   Focus adds a "sliding underline" — a gradient background pinned to
   the bottom edge that expands from 0 → 100% width when the input
   gets focus, then shrinks back on blur. Uses background-size
   transitions instead of a pseudo-element (native <input> can't have
   ::before / ::after). The original border-bottom stays as the
   resting-state divider. */
:root[data-input-style="underline"] .lxsf-input,
:root[data-input-style="underline"] .lxsf-textarea,
:root[data-input-style="underline"] .lxsf-select {
    border: none;
    border-bottom: var(--lxsf-input-border-width, 2px) solid var(--lxsf-border, #94a3b8);
    border-radius: 0;
    padding-left: 0;
    padding-right: 0;
    background-image: linear-gradient(
        to right,
        var(--lxsf-input-focus, var(--lxsf-accent, #1e293b)),
        var(--lxsf-input-focus, var(--lxsf-accent, #1e293b))
    );
    background-repeat: no-repeat;
    background-position: bottom left;
    /* Height matches border-bottom so the sliding line sits directly
       ON TOP of the resting divider, replacing it visually. */
    background-size: 0% var(--lxsf-input-border-width, 2px);
    transition: background-size 0.35s cubic-bezier(0.16, 1, 0.3, 1),
                border-color 0.2s ease;
}

:root[data-input-style="underline"] .lxsf-input:focus,
:root[data-input-style="underline"] .lxsf-textarea:focus,
:root[data-input-style="underline"] .lxsf-select:focus {
    background-size: 100% var(--lxsf-input-border-width, 2px);
}

/* Boxed variant — full border + radius. Per-side border vars
   (set by setBorder() in JS) win over the single-value legacy fallback. */
:root[data-input-style="boxed"] .lxsf-input,
:root[data-input-style="boxed"] .lxsf-textarea,
:root[data-input-style="boxed"] .lxsf-select {
    border-top: var(--lxsf-input-border-top, var(--lxsf-input-border-width, 2px) solid var(--lxsf-border, #cbd5e1));
    border-right: var(--lxsf-input-border-right, var(--lxsf-input-border-width, 2px) solid var(--lxsf-border, #cbd5e1));
    border-bottom: var(--lxsf-input-border-bottom, var(--lxsf-input-border-width, 2px) solid var(--lxsf-border, #cbd5e1));
    border-left: var(--lxsf-input-border-left, var(--lxsf-input-border-width, 2px) solid var(--lxsf-border, #cbd5e1));
    border-radius: var(--lxsf-input-radius, 6px);
}

/* Boxed focus — border color change + soft outer glow ring so focus
   feedback matches the underline variant's "slide" energy without a
   pseudo-element. Ring uses a semi-transparent accent color so it
   works on any theme. */
:root[data-input-style="boxed"] .lxsf-input,
:root[data-input-style="boxed"] .lxsf-textarea,
:root[data-input-style="boxed"] .lxsf-select {
    transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

:root[data-input-style="boxed"] .lxsf-input:focus,
:root[data-input-style="boxed"] .lxsf-textarea:focus,
:root[data-input-style="boxed"] .lxsf-select:focus {
    border-color: var(--lxsf-input-focus, var(--lxsf-accent, #1e293b));
    box-shadow: 0 0 0 4px var(--lxsf-input-focus-ring, rgba(30, 41, 59, 0.12));
}

/* Minimal variant — no border, blends into background */
:root[data-input-style="minimal"] .lxsf-input,
:root[data-input-style="minimal"] .lxsf-textarea,
:root[data-input-style="minimal"] .lxsf-select {
    border: none;
    border-radius: var(--lxsf-input-radius, 6px);
}

.lxsf-inline-label {
    font-size: var(--lxsf-inline-label-font-size, 14px);
    font-weight: var(--lxsf-inline-label-font-weight, 500);
    color: var(--lxsf-inline-label-color, var(--lxsf-muted, #6b7280));
    padding: var(--lxsf-inline-label-padding, 0);
    margin: var(--lxsf-inline-label-margin, 18px 0 6px);
}

.lxsf-inline-desc {
    font-size: var(--lxsf-inline-desc-font-size, 13px);
    font-weight: var(--lxsf-inline-desc-font-weight, 400);
    color: var(--lxsf-inline-desc-color, var(--lxsf-muted, #6b7280));
    padding: var(--lxsf-inline-desc-padding, 0);
    margin: var(--lxsf-inline-desc-margin, 12px 0 8px);
    line-height: 1.45;
}

.lxsf-inline-desc--bottom {
    margin-top: 14px !important;
    /* Premium gap to prevent text from sticking to the underline border */
    margin-bottom: 8px !important;
}

/* Info-icon tooltip on inline label */
.lxsf-info-icon {
    position: relative;
    display: inline-flex;
    align-items: center;
    margin-left: 4px;
    color: #94a3b8;
    cursor: help;
    outline: none;
    vertical-align: middle;
}

.lxsf-info-icon:hover,
.lxsf-info-icon:focus {
    color: #475569;
}

.lxsf-info-icon::after {
    content: attr(data-tip);
    position: absolute;
    bottom: 100%;
    left: 50%;
    transform: translate(-50%, -6px);
    background: #1e293b;
    color: #fff;
    font-size: 12px;
    line-height: 1.4;
    padding: 7px 10px;
    border-radius: 4px;
    max-width: 280px;
    min-width: 140px;
    width: max-content;
    white-space: normal;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.15s, transform 0.15s;
    z-index: 20;
}

.lxsf-info-icon::before {
    content: '';
    position: absolute;
    bottom: 100%;
    left: 50%;
    transform: translate(-50%, 0);
    border: 5px solid transparent;
    border-top-color: #1e293b;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.15s;
}

.lxsf-info-icon:hover::after,
.lxsf-info-icon:focus::after {
    opacity: 1;
    transform: translate(-50%, -2px);
}

.lxsf-info-icon:hover::before,
.lxsf-info-icon:focus::before {
    opacity: 1;
}

.lxsf-input-hint {
    font-size: 12px;
    color: var(--lxsf-muted, #94a3b8);
    margin: 6px 0 0;
}

/* ── Date input (split) ────────────────────────────────────────── */
.lxsf-date {
    display: inline-flex;
    align-items: flex-end;
    gap: 10px;
    font-size: 22px;
}

.lxsf-date-part {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.lxsf-date-label {
    font-size: 14px;
    color: var(--lxsf-muted, #94a3b8);
    font-weight: 500;
}

.lxsf-date-input {
    width: 70px;
    border: none;
    border-bottom: 2px solid var(--lxsf-border, #94a3b8);
    background: transparent;
    font-size: 22px;
    font-family: inherit;
    padding: 4px 0;
    text-align: left;
    outline: none;
}

.lxsf-date-input:focus {
    border-color: var(--lxsf-accent, #1e293b);
}

.lxsf-date-input--year {
    width: 92px;
}

.lxsf-date-sep {
    font-size: 22px;
    color: var(--lxsf-muted, #94a3b8);
    padding-bottom: 4px;
}

/* ── Choice ────────────────────────────────────────────────────── */
.lxsf-choices {
    display: flex;
    flex-direction: column;
    gap: var(--lxsf-choice-gap, 10px);
    width: 100%;
    max-width: var(--lxsf-choice-max-width, 520px);
}

/* Inline layout — plain radio / checkbox lists only. Picture mode uses
   its own `.lxsf-pic-grid` container and is not affected by this rule.
   Items shrink to content-fit so multiple chips can wrap on one row. */
.lxsf-body[data-choice-layout="inline"] .lxsf-choices {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: flex-start;
}
.lxsf-body[data-choice-layout="inline"] .lxsf-choice {
    width: auto;
    flex: 0 0 auto;
}

/* "Other" free-text input revealed below the choices when allow_other is on. */
.lxsf-other-wrap {
    margin-top: 12px;
    width: 100%;
    max-width: var(--lxsf-choice-max-width, 520px);
}

.lxsf-other-input {
    width: 100%;
}

.lxsf-choice {
    display: flex;
    align-items: center;
    gap: var(--lxsf-choice-gap, 8px);
    width: 100%;
    padding: var(--lxsf-choice-padding, 10px);
    /* position:relative + overflow:hidden — hosts the .lxsf-ripple
       span injected on click. Also lets .lxsf-just-picked keyframe
       transforms clip cleanly if the card ends up scaled slightly
       past its natural bounds. */
    position: relative;
    overflow: hidden;
    background: var(--lxsf-choice-bg, rgba(255, 255, 255, 0.7));
    /* Per-side border vars (set by setBorder() in JS) win over the single-value
       legacy shorthand below. */
    border-top: var(--lxsf-choice-border-top, var(--lxsf-choice-border-width, 2px) solid var(--lxsf-border, #cbd5e1));
    border-right: var(--lxsf-choice-border-right, var(--lxsf-choice-border-width, 2px) solid var(--lxsf-border, #cbd5e1));
    border-bottom: var(--lxsf-choice-border-bottom, var(--lxsf-choice-border-width, 2px) solid var(--lxsf-border, #cbd5e1));
    border-left: var(--lxsf-choice-border-left, var(--lxsf-choice-border-width, 2px) solid var(--lxsf-border, #cbd5e1));
    border-radius: var(--lxsf-choice-radius, 6px);
    cursor: pointer;
    font-size: var(--lxsf-choice-font-size, 18px);
    text-align: left;
    color: var(--lxsf-text, #1e293b);
    font-family: inherit;
    transition: all 0.15s;
}

.lxsf-choice:not(.lxsf-choice--selected):hover {
    border-color: #94a3b8;
}

.lxsf-choice--selected {
    border-color: var(--lxsf-choice-selected-border, var(--lxsf-accent, #7c3aed));
    background: var(--lxsf-choice-selected-bg, rgba(124, 58, 237, 0.08));
    color: var(--lxsf-choice-selected-text, var(--lxsf-text, #1e293b));
}

.lxsf-choice-label {
    flex: 1;
}

/* ── Fancy radio / checkbox indicator ──────────────────────────
   Replaces the old A/B/C/D letter chips. Used by .lxsf-choice
   (radio/checkbox lists, yes-no) and .lxsf-pic-foot (picture cards). */
.lxsf-choice-input {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 15px;
    height: 15px;
    flex-shrink: 0;
    background: #ffffff;
    border: 1.5px solid var(--lxsf-border, #cbd5e1);
    color: #fff;
    transition: all 0.15s;
}

.lxsf-choice-input--radio {
    margin-top: -1px;
    border-radius: 50%;
}

.lxsf-choice-input--checkbox {
    margin-top: -1px;
    border-radius: 5px;
}

.lxsf-choice-input-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: transparent;
    transition: background 0.15s;
}

.lxsf-choice-input svg {
    width: 11px;
    height: 11px;
    stroke: transparent;
    transition: stroke 0.15s;
}

/* Selected look — works whether the indicator sits inside a selected
   .lxsf-choice / .lxsf-pic-card OR carries its own --selected modifier. */
.lxsf-choice--selected .lxsf-choice-input,
.lxsf-pic-card--selected .lxsf-choice-input,
.lxsf-choice-input--selected {
    background: var(--lxsf-accent, #7c3aed);
    border-color: var(--lxsf-accent, #7c3aed);
}

.lxsf-choice--selected .lxsf-choice-input-dot,
.lxsf-pic-card--selected .lxsf-choice-input-dot,
.lxsf-choice-input--selected .lxsf-choice-input-dot {
    background: #ffffff;
}

.lxsf-choice--selected .lxsf-choice-input svg,
.lxsf-pic-card--selected .lxsf-choice-input svg,
.lxsf-choice-input--selected svg {
    stroke: #ffffff;
}

/* ── Choice card click micro-interactions ──────────────────────────
   Fired on every click of .lxsf-choice or .lxsf-pic-card by the JS
   helper `triggerChoiceFx()`:
     - Card scale-bounce (`.lxsf-just-picked` for ~400ms)
     - Ripple expanding from the click point (span injected + removed)
     - Checkmark / dot spring-in when the selected state commits
       (attached to the selected-state selectors above so it plays
       every time selection changes, not just once). */
@keyframes lxsf-card-bounce {
    0%   { transform: scale(1); }
    35%  { transform: scale(1.08); }
    70%  { transform: scale(0.98); }
    100% { transform: scale(1); }
}

.lxsf-choice.lxsf-just-picked,
.lxsf-pic-card.lxsf-just-picked {
    /* Overshoot + settle. `cubic-bezier(0.34, 1.56, 0.64, 1)` is the
       "material" spring curve — a slight overshoot past 1.0 before
       settling — which pairs with the intermediate 1.08/0.98 stops
       to give a physical "click" feel. */
    animation: lxsf-card-bounce 380ms cubic-bezier(0.34, 1.56, 0.64, 1);
}

/* Checkmark / radio dot spring-in when selection commits. The dot
   and svg both flip visibility via the earlier selected-state rules;
   this keyframe adds the transient scale bounce on top. */
@keyframes lxsf-mark-pop {
    0%   { transform: scale(0); }
    60%  { transform: scale(1.35); }
    100% { transform: scale(1); }
}

.lxsf-choice--selected .lxsf-choice-input-dot,
.lxsf-pic-card--selected .lxsf-choice-input-dot,
.lxsf-choice-input--selected .lxsf-choice-input-dot,
.lxsf-choice--selected .lxsf-choice-input svg,
.lxsf-pic-card--selected .lxsf-choice-input svg,
.lxsf-choice-input--selected svg {
    animation: lxsf-mark-pop 320ms cubic-bezier(0.68, -0.55, 0.27, 1.55) both;
}

/* Ripple — positioned absolutely inside the card at click coords via
   inline styles (see triggerChoiceFx()). Diameter is set so the
   circle expands to cover the whole card. `currentColor` inherits
   the card's text color so it tints correctly on both light and
   dark card themes. */
.lxsf-ripple {
    position: absolute;
    border-radius: 50%;
    transform: translate(-50%, -50%) scale(0);
    background: currentColor;
    opacity: 0.18;
    pointer-events: none;
    animation: lxsf-ripple 600ms ease-out;
}

@keyframes lxsf-ripple {
    to {
        transform: translate(-50%, -50%) scale(1);
        opacity: 0;
    }
}

@media (prefers-reduced-motion: reduce) {
    .lxsf-choice.lxsf-just-picked,
    .lxsf-pic-card.lxsf-just-picked,
    .lxsf-ripple,
    .lxsf-choice--selected .lxsf-choice-input-dot,
    .lxsf-pic-card--selected .lxsf-choice-input-dot,
    .lxsf-choice--selected .lxsf-choice-input svg,
    .lxsf-pic-card--selected .lxsf-choice-input svg {
        animation: none !important;
    }
}

/* ── Opinion scale ─────────────────────────────────────────────── */
/* inline-flex column → the wrapper shrinks to the numbers row's width,
   so the labels row (left / mid / right) constrains to the same span
   instead of stretching across the whole screen. */
.lxsf-scale {
    display: inline-flex;
    flex-direction: column;
    align-items: stretch;
    margin: var(--lxsf-scale-margin, 8px 0 0);
    padding: var(--lxsf-scale-padding, 0);
    max-width: var(--lxsf-scale-max-width, none);
}

.lxsf-scale-row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--lxsf-scale-gap, 6px);
}

.lxsf-scale-num {
    /* Schema-driven item size — `scale_item_width` (numUnit) becomes the
       fixed width AND height of each tile. flex-grow stays off so the
       configured size wins; flex-shrink: 1 lets them collapse on narrow
       viewports. Without an explicit width, falls back to flex:1 sizing. */
    flex: 0 0 var(--lxsf-scale-item-width, 44px);
    width: var(--lxsf-scale-item-width, 44px);
    height: var(--lxsf-scale-item-width, 44px);
    background: var(--lxsf-scale-bg, #ffffff);
    border-top: var(--lxsf-scale-border-top, 1.5px solid var(--lxsf-border, #cbd5e1));
    border-right: var(--lxsf-scale-border-right, 1.5px solid var(--lxsf-border, #cbd5e1));
    border-bottom: var(--lxsf-scale-border-bottom, 1.5px solid var(--lxsf-border, #cbd5e1));
    border-left: var(--lxsf-scale-border-left, 1.5px solid var(--lxsf-border, #cbd5e1));
    border-radius: var(--lxsf-scale-radius, 6px);
    font-size: var(--lxsf-scale-item-font, 14px);
    font-weight: 600;
    cursor: pointer;
    color: var(--lxsf-scale-text, #475569);
    font-family: inherit;
    transition: all 0.15s;
}

.lxsf-scale-num:hover {
    border-color: var(--lxsf-accent, #1e293b);
}

.lxsf-scale-num--selected {
    border-color: var(--lxsf-scale-selected-border, var(--lxsf-scale-selected, var(--lxsf-accent, #7c3aed)));
    background: var(--lxsf-scale-selected-bg, var(--lxsf-scale-selected, var(--lxsf-accent, #7c3aed)));
    color: var(--lxsf-scale-selected-text, var(--lxsf-btn-text, #ffffff));
}

.lxsf-scale-labels {
    display: flex;
    justify-content: space-between;
    font-size: var(--lxsf-scale-label-font-size, 12px);
    font-weight: var(--lxsf-scale-label-font-weight, 500);
    color: var(--lxsf-scale-label-color, var(--lxsf-muted, #94a3b8));
    padding: var(--lxsf-scale-label-padding, 0);
    margin: var(--lxsf-scale-label-margin, 8px 0 0);
}

.lxsf-scale-labels span {
    flex: 1;
}

.lxsf-scale-labels span:nth-child(2) {
    text-align: center;
}

.lxsf-scale-labels span:last-child {
    text-align: right;
}

/* ── Picture choice grid ─────────────────────────────────────────
   Cards are fixed-width by default (175px each, with an `auto-fill`
   so the row wraps cleanly at any container width). Override via the
   --lxsf-picture-card-width var if the customer set a custom card width. */
.lxsf-pic-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, var(--lxsf-picture-card-width, 175px));
    gap: var(--lxsf-picture-gap, 8px);
}

.lxsf-pic-card {
    background: var(--lxsf-picture-bg, var(--lxsf-choice-bg, rgba(255, 255, 255, 0.7)));
    border-top: var(--lxsf-picture-border-top, 1.5px solid var(--lxsf-border, #cbd5e1));
    border-right: var(--lxsf-picture-border-right, 1.5px solid var(--lxsf-border, #cbd5e1));
    border-bottom: var(--lxsf-picture-border-bottom, 1.5px solid var(--lxsf-border, #cbd5e1));
    border-left: var(--lxsf-picture-border-left, 1.5px solid var(--lxsf-border, #cbd5e1));
    border-radius: var(--lxsf-picture-radius, 6px);
    padding: var(--lxsf-picture-padding, 8px);
    cursor: pointer;
    font-family: inherit;
    text-align: left;
    transition: all 0.15s;
    display: flex;
    flex-direction: column;
    gap: 8px;
    width: 100%;
    /* Ripple host — same as .lxsf-choice. */
    position: relative;
    overflow: hidden;
}

.lxsf-pic-card:not(.lxsf-pic-card--selected):hover {
    border-color: #94a3b8;
}

.lxsf-pic-card--selected {
    border-color: var(--lxsf-picture-selected-border, var(--lxsf-accent, #7c3aed));
    background: var(--lxsf-picture-selected-bg, var(--lxsf-choice-selected, rgba(124, 58, 237, 0.08)));
}

.lxsf-pic-img {
    width: 100%;
    aspect-ratio: var(--lxsf-picture-aspect, 1 / 1);
    border-radius: 6px;
    overflow: hidden;
    /* Honour the schema's picture bg so the empty/Other image area
       matches the card's bg colour (the customer-flagged "white-only"
       hardcoding is gone). Falls back to white when unset, which is the
       schema default anyway. */
    background: var(--lxsf-picture-bg, #ffffff);
    display: flex;
    align-items: center;
    justify-content: center;
}

.lxsf-pic-img img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.lxsf-pic-img--empty {
    color: #cbd5e1;
}

.lxsf-pic-img--empty svg {
    width: 38%;
    height: 38%;
    max-width: 72px;
    max-height: 72px;
    display: block;
}

/* "Other" placeholder reads slightly bolder than the empty-image glyph so
   it doesn't look like a broken card. */
.lxsf-pic-img--other {
    color: #94a3b8;
}

.lxsf-pic-img--other svg {
    width: 42%;
    height: 42%;
}

.lxsf-pic-foot {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 0 2px 2px;
}

.lxsf-pic-label {
    font-size: var(--lxsf-picture-label-size, 14px);
    color: var(--lxsf-picture-label-color, var(--lxsf-text, #1e293b));
    flex: 1;
    line-height: 1.3;
}

.lxsf-pic-card--selected .lxsf-choice-letter {
    background: var(--lxsf-accent, #1e293b);
    color: #fff;
}

/* ── Range slider (Modern variant) ─────────────────────────────────
   Native `<input type=range>` re-skinned for a Typeform-style feel:
     - Filled track segment from min → current value (gradient stop
       driven by the --lxsf-range-pos CSS var 0..1 set by JS)
     - Big thumb with subtle shadow + hover/active glow
     - Value bubble floats ABOVE the thumb, follows it during drag
       via the same --lxsf-range-pos var (positioned in the
       track-wrap so it lines up with the thumb travel range)
   Vendor-prefixed webkit / moz thumb+track rules keep parity across
   Chromium and Firefox — no way around the two rule sets. */
.lxsf-range {
    margin-top: 32px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    width: var(--lxsf-range-width, 100%);
    max-width: var(--lxsf-range-max-width, 520px);
}

.lxsf-range-track-wrap {
    position: relative;
    padding: 22px 0 6px 0;
    /* Cache the visible thumb SIZE (length, not color — the color is
       --lxsf-range-thumb which applyDesign already sets from the
       schema). Both the fill gradient and the bubble use this to
       compute the "safe inner range" so positions never overhang. */
    --lxsf-range-thumb-sz: var(--lxsf-range-thumb-size, 22px);
    --lxsf-range-pos: 0;
}

.lxsf-range-value {
    position: absolute;
    top: -6px;
    /* Nudge left by the pos fraction across the entire track. Add
       thumb/2 offset so the bubble centers on the thumb regardless
       of value (thumb travel is inset by thumb width on each side
       so it never overhangs the track). */
    left: calc(
        var(--lxsf-range-thumb-sz) / 2
        + (100% - var(--lxsf-range-thumb-sz)) * var(--lxsf-range-pos)
    );
    transform: translateX(-50%);
    background: var(--lxsf-range-value-bg, var(--lxsf-accent, #1e293b));
    color: var(--lxsf-range-value-text, #ffffff);
    font-size: var(--lxsf-range-value-size, 14px);
    font-weight: 700;
    line-height: 1;
    padding: 6px 10px;
    border-radius: 6px;
    white-space: nowrap;
    pointer-events: none;
    box-shadow: 0 4px 12px -2px rgba(15, 23, 42, 0.25);
    transition: left 0.08s ease-out;
}

.lxsf-range-value::after {
    content: '';
    position: absolute;
    top: 100%;
    left: 50%;
    transform: translateX(-50%);
    border: 4px solid transparent;
    border-top-color: var(--lxsf-range-value-bg, var(--lxsf-accent, #1e293b));
}

/* Base range input — kill the native chrome so our custom track +
   thumb rules can take over. Background is a gradient split at the
   current --lxsf-range-pos so the filled segment shows the accent
   color and the rest of the track stays neutral. */
.lxsf-range-slider {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    width: 100%;
    height: var(--lxsf-range-track-height, 6px);
    background: linear-gradient(
        to right,
        var(--lxsf-range-fill, var(--lxsf-accent, #1e293b)) 0%,
        var(--lxsf-range-fill, var(--lxsf-accent, #1e293b)) calc(var(--lxsf-range-pos) * 100%),
        var(--lxsf-range-track, #e2e8f0) calc(var(--lxsf-range-pos) * 100%),
        var(--lxsf-range-track, #e2e8f0) 100%
    );
    border-radius: 999px;
    outline: none;
    cursor: grab;
}

.lxsf-range-slider:active {
    cursor: grabbing;
}

/* Chromium / Edge / Safari thumb */
.lxsf-range-slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: var(--lxsf-range-thumb-size, 22px);
    height: var(--lxsf-range-thumb-size, 22px);
    background: var(--lxsf-range-thumb, #ffffff);
    border: 3px solid var(--lxsf-range-fill, var(--lxsf-accent, #1e293b));
    border-radius: 50%;
    box-shadow: 0 3px 10px -2px rgba(15, 23, 42, 0.35);
    cursor: grab;
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.lxsf-range-slider:hover::-webkit-slider-thumb {
    transform: scale(1.12);
    box-shadow: 0 4px 14px -2px rgba(15, 23, 42, 0.45),
                0 0 0 6px rgba(0, 0, 0, 0.05);
}

.lxsf-range-slider:active::-webkit-slider-thumb {
    transform: scale(1.18);
    box-shadow: 0 4px 14px -2px rgba(15, 23, 42, 0.5),
                0 0 0 8px rgba(0, 0, 0, 0.08);
}

/* Firefox thumb + track */
.lxsf-range-slider::-moz-range-thumb {
    width: var(--lxsf-range-thumb-size, 22px);
    height: var(--lxsf-range-thumb-size, 22px);
    background: var(--lxsf-range-thumb, #ffffff);
    border: 3px solid var(--lxsf-range-fill, var(--lxsf-accent, #1e293b));
    border-radius: 50%;
    box-shadow: 0 3px 10px -2px rgba(15, 23, 42, 0.35);
    cursor: grab;
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.lxsf-range-slider:hover::-moz-range-thumb {
    transform: scale(1.12);
    box-shadow: 0 4px 14px -2px rgba(15, 23, 42, 0.45),
                0 0 0 6px rgba(0, 0, 0, 0.05);
}

.lxsf-range-slider:active::-moz-range-thumb {
    transform: scale(1.18);
}

.lxsf-range-slider::-moz-range-track {
    background: transparent;    /* the input itself already carries the gradient */
    height: var(--lxsf-range-track-height, 6px);
    border-radius: 999px;
    border: none;
}

.lxsf-range-minmax {
    display: flex;
    justify-content: space-between;
    font-size: 12px;
    font-weight: 500;
    color: var(--lxsf-muted, #94a3b8);
    padding: 0 2px;
}

@media (prefers-reduced-motion: reduce) {
    .lxsf-range-value { transition: none !important; }
    .lxsf-range-slider::-webkit-slider-thumb,
    .lxsf-range-slider::-moz-range-thumb {
        transition: none !important;
    }
}

/* ── Single checkbox ───────────────────────────────────────────── */
.lxsf-single-check {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    cursor: pointer;
    padding: 12px;
    border: 1.5px solid var(--lxsf-border, #cbd5e1);
    border-radius: 8px;
}

.lxsf-single-check:has(input:checked) {
    border-color: var(--lxsf-accent, #1e293b);
    background: var(--lxsf-choice-selected, rgba(124, 58, 237, 0.04));
}

.lxsf-single-check input {
    width: 18px;
    height: 18px;
    margin-top: 2px;
    accent-color: var(--lxsf-accent, #1e293b);
}

.lxsf-single-check-label {
    font-size: 15px;
    color: var(--lxsf-text, #1e293b);
}

/* ── File upload ───────────────────────────────────────────────── */
.lxsf-file {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    padding: 14px 18px;
    border: 1.5px dashed var(--lxsf-border, #cbd5e1);
    border-radius: 8px;
    background: var(--lxsf-choice-bg, rgba(255, 255, 255, 0.6));
    cursor: pointer;
    font-size: 14px;
    color: var(--lxsf-text, #1e293b);
}

.lxsf-file:hover {
    border-color: var(--lxsf-accent, #1e293b);
}

.lxsf-file-icon {
    font-size: 18px;
}

.lxsf-file-name {
    font-weight: 500;
}

/* ── reCAPTCHA placeholder ─────────────────────────────────────── */
.lxsf-recaptcha-wrap {
    margin-top: 8px;
}

.lxsf-recaptcha-box {
    padding: 16px;
    border: 1.5px dashed #cbd5e1;
    border-radius: 8px;
    text-align: center;
    color: #94a3b8;
    font-size: 13px;
}

/* ── Yes/No ────────────────────────────────────────────────────── */
.lxsf-yesno {
    display: flex;
    gap: var(--lxsf-yesno-gap, 12px);
    /* Left-aligned (matches the rest of the form's left-aligned
       content). Was centered which felt inconsistent next to the
       left-aligned label/desc rows above. */
    justify-content: flex-start;
    width: 100%;
    max-width: var(--lxsf-yesno-max-width, 520px);
}

.lxsf-yesno .lxsf-choice {
    flex: 1;
    max-width: 240px;
    /* Constrain buttons from stretching too wide */
    justify-content: center;
    /* Schema vars (yesno_*) win over the choice_* defaults for these buttons. */
    font-size: var(--lxsf-yesno-font-size, 18px);
    font-weight: var(--lxsf-yesno-font-weight, 600);
    color: var(--lxsf-yesno-text, var(--lxsf-text, #1e293b));
    background: var(--lxsf-yesno-bg, var(--lxsf-choice-bg, #ffffff));
    padding: var(--lxsf-yesno-padding, var(--lxsf-choice-padding, 12px));
    margin: var(--lxsf-yesno-margin, 0);
    border-radius: var(--lxsf-yesno-radius, var(--lxsf-choice-radius, 6px));
    border-top: var(--lxsf-yesno-border-top, var(--lxsf-choice-border-top, 2px solid var(--lxsf-border, #cbd5e1)));
    border-right: var(--lxsf-yesno-border-right, var(--lxsf-choice-border-right, 2px solid var(--lxsf-border, #cbd5e1)));
    border-bottom: var(--lxsf-yesno-border-bottom, var(--lxsf-choice-border-bottom, 2px solid var(--lxsf-border, #cbd5e1)));
    border-left: var(--lxsf-yesno-border-left, var(--lxsf-choice-border-left, 2px solid var(--lxsf-border, #cbd5e1)));
}

.lxsf-yesno .lxsf-choice--selected {
    background: var(--lxsf-yesno-selected-bg, var(--lxsf-choice-selected-bg, var(--lxsf-accent, #7c3aed)));
    border-color: var(--lxsf-yesno-selected-border, var(--lxsf-choice-selected-border, var(--lxsf-accent, #7c3aed)));
    color: var(--lxsf-yesno-selected-text, var(--lxsf-choice-selected-text, #ffffff));
}

/* ── Buttons & nav alignment ───────────────────────────────────── */
.lxsf-actions {
    display: flex;
    align-items: center;
    gap: 14px;
    margin-top: 42px;
    flex-wrap: wrap;
}

.lxsf-actions[data-align="left"] {
    justify-content: flex-start;
}

.lxsf-actions[data-align="center"] {
    justify-content: center;
}

.lxsf-actions[data-align="right"] {
    justify-content: flex-end;
}

.lxsf-actions[data-align="between"] {
    justify-content: space-between;
    width: 100%;
}

.lxsf-actions[data-align="between"] .lxsf-back-btn {
    margin-right: auto;
}

.lxsf-btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: var(--lxsf-btn-padding, 8px 20px);
    background: var(--lxsf-accent, #1e293b);
    color: var(--lxsf-btn-text, #fff);
    font-size: 15px;
    font-weight: 700;
    border: none;
    border-radius: var(--lxsf-btn-radius, 6px);
    cursor: pointer;
    font-family: inherit;
    transition: opacity 0.15s, transform 0.2s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.2s ease;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}

.lxsf-btn:hover {
    opacity: 0.95;
    transform: scale(1.03);
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12);
}

.lxsf-btn:active {
    transform: scale(0.98);
}

/* Embed mode (iframe host) — the iframe boundary clips anything that
   overflows, so scale + shadow both get truncated near the edges.
   Use a subtle brightness filter instead — no size change, no shadow
   bleed, just a light "pop" that reads as interactive. Standalone
   /form/view/{slug} pages (.lxsf-body--view) keep the full scale +
   shadow since there's no clipping there. */
.lxsf-body--embed .lxsf-btn:hover {
    transform: none;
    box-shadow: none;
    opacity: 1;
    filter: brightness(1.1);
}

.lxsf-body--embed .lxsf-btn:active {
    transform: none;
    filter: brightness(0.95);
}

.lxsf-btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.lxsf-btn-icon svg {
    width: var(--lxsf-btn-icon-size, 16px);
    height: var(--lxsf-btn-icon-size, 16px);
    display: block;
}

/* Back button variants — driven by [data-back-style] on the button.
   Default padding is 0 so the button sits flush next to the OK CTA;
   the design panel's back_btn_padding TRBL overrides this when a
   customer wants breathing room around it. */
.lxsf-back-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 0;
    font-size: 14px;
    font-weight: 600;
    color: var(--lxsf-back-btn-text, #64748b);
    border-radius: var(--lxsf-btn-radius, 6px);
    cursor: pointer;
    font-family: inherit;
    background: var(--lxsf-back-btn-bg, transparent);
    border: none;
    transition: opacity 0.15s;
}

.lxsf-back-btn[data-back-style="ghost"] {
    background: transparent;
    border: none;
}

.lxsf-back-btn[data-back-style="outline"] {
    background: transparent;
    border: 1.5px solid var(--lxsf-border, #cbd5e1);
}

.lxsf-back-btn[data-back-style="solid"] {
    background: var(--lxsf-back-btn-bg, #e2e8f0);
    border: none;
}

.lxsf-back-btn:hover {
    opacity: 0.85;
}

.lxsf-back-btn .lxsf-btn-icon svg {
    /* Match the primary CTA's floor of 20px so the back arrow reads
       at the same visual weight as the forward arrow. Users who
       explicitly set a larger btn_icon_size still get their value. */
    width:  max(20px, var(--lxsf-btn-icon-size, 20px));
    height: max(20px, var(--lxsf-btn-icon-size, 20px));
}

.lxsf-btn-meta {
    font-size: 12px;
    color: var(--lxsf-muted, #94a3b8);
}

/* ── Row arrows (floating prev/next chevron pair) ─────────────────
   Anchored to the form card (.lxsf-app — has position:relative) instead
   of the viewport. The previous `position: fixed` made the arrows stick
   to the browser corner where they overlapped the form's submit button
   when the form took most of the screen. Anchoring inside the card
   keeps them clear of the form chrome at every viewport width.
   Each arrow still uses the standard button inline-style pipeline
   (applyBtnStyle with prefix='arrow') so colours, border, radius all
   come from the schema. */
.lxsf-arrows {
    position: absolute;
    display: flex;
    /* Default stacking is vertical — `[data-orientation="horizontal"]`
       flips the chevrons side-by-side. The renderer sets the attribute
       from the schema's `arrows_orientation` key. */
    flex-direction: column;
    z-index: 30;
    pointer-events: auto;
}

.lxsf-arrows[data-orientation="horizontal"] {
    flex-direction: row;
}

.lxsf-arrows[data-orientation="vertical"] {
    flex-direction: column;
}

.lxsf-arrows[data-pos="bottom-right"] {
    right: 24px;
    bottom: 24px;
}

.lxsf-arrows[data-pos="bottom-left"] {
    left: 24px;
    bottom: 24px;
}

.lxsf-arrows[data-pos="top-right"] {
    right: 24px;
    top: 24px;
}

.lxsf-arrows[data-pos="top-left"] {
    left: 24px;
    top: 24px;
}

/* Row arrow button — kept structural only. Every visual property
   (padding, border, radius, bg, text colour, font-size, hover) is
   driven from the schema via applyBtnStyle() in lxf-smart-form.js, so
   we must NOT hardcode width/height/background/border here or those
   inline styles get silently overridden by these rules (the previous
   fixed 38×34 swallowed the schema's padding). */
.lxsf-arrow {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    font-family: inherit;
    line-height: 1;
    transition: background 0.15s, color 0.15s, border-color 0.15s, transform 0.1s;
    box-shadow: 0 2px 6px rgba(15, 23, 42, 0.08);
}

/* Hover lift — schema's hover vars (set inline via applyBtnStyle) win
   when non-empty; otherwise fall back to the purple accent.
   `!important` is needed because applyBtnStyle writes the base bg /
   border / colour as INLINE styles on the button, and a plain CSS
   :hover rule can't override an inline style without it. */
.lxsf-arrow:hover:not(:disabled) {
    background: var(--lxsf-arrow-hover-bg, #7c3aed) !important;
    color: var(--lxsf-arrow-hover-text, #ffffff) !important;
    border-color: var(--lxsf-arrow-hover-border, #7c3aed) !important;
}

.lxsf-arrow:active:not(:disabled) {
    transform: translateY(1px);
}

.lxsf-arrow:disabled {
    opacity: 0.45;
    cursor: not-allowed;
}

/* ── Welcome screen ────────────────────────────────────────────── */
/* Text alignment for welcome / thank-you / statement screens.
   `.lxsf-actions` (which is flex) still centers/aligns via its own
   data-align attribute, so buttons are not affected by these rules. */
.lxsf-welcome {
    text-align: var(--lxsf-welcome-align, left);
}

.lxsf-thankyou {
    text-align: var(--lxsf-thankyou-align, left);
}

.lxsf-screen[data-step-type="statement"] {
    text-align: var(--lxsf-statement-align, left);
}

.lxsf-welcome .lxsf-title {
    font-size: var(--lxsf-welcome-title-font-size, clamp(28px, 4.5vw, 44px));
    font-weight: var(--lxsf-welcome-title-font-weight, 700);
    color: var(--lxsf-welcome-title-color, var(--lxsf-text, #1e293b));
    padding: var(--lxsf-welcome-title-padding, 0);
    margin: var(--lxsf-welcome-title-margin, 0);
}

.lxsf-welcome .lxsf-desc {
    font-size: var(--lxsf-welcome-desc-font-size, 16px);
    font-weight: var(--lxsf-welcome-desc-font-weight, 400);
    color: var(--lxsf-welcome-desc-color, var(--lxsf-muted, #6b7280));
    padding: var(--lxsf-welcome-desc-padding, 0);
    margin: var(--lxsf-welcome-desc-margin, 8px 0 0);
}

.lxsf-welcome-meta,
.lxsf-thankyou-meta {
    display: block;
    font-size: var(--lxsf-welcome-meta-font-size, 13px);
    font-weight: var(--lxsf-welcome-meta-font-weight, 500);
    color: var(--lxsf-welcome-meta-color, var(--lxsf-muted, #94a3b8));
    padding: var(--lxsf-welcome-meta-padding, 0);
    margin: var(--lxsf-welcome-meta-margin, 10px 0 0);
}

/* Thank-You can override via its own var prefix */
.lxsf-thankyou-meta {
    font-size: var(--lxsf-thankyou-meta-font-size, 13px);
    font-weight: var(--lxsf-thankyou-meta-font-weight, 500);
    color: var(--lxsf-thankyou-meta-color, var(--lxsf-muted, #94a3b8));
    padding: var(--lxsf-thankyou-meta-padding, 0);
    margin: var(--lxsf-thankyou-meta-margin, 10px 0 0);
}

/* ── Thank you screen ──────────────────────────────────────────── */
.lxsf-thankyou .lxsf-title {
    font-size: var(--lxsf-thankyou-title-font-size, clamp(28px, 4.5vw, 44px));
    font-weight: var(--lxsf-thankyou-title-font-weight, 700);
    color: var(--lxsf-thankyou-title-color, var(--lxsf-text, #1e293b));
    padding: var(--lxsf-thankyou-title-padding, 0);
    margin: var(--lxsf-thankyou-title-margin, 0);
}

.lxsf-thankyou .lxsf-desc {
    font-size: var(--lxsf-thankyou-desc-font-size, 16px);
    font-weight: var(--lxsf-thankyou-desc-font-weight, 400);
    color: var(--lxsf-thankyou-desc-color, var(--lxsf-muted, #6b7280));
    padding: var(--lxsf-thankyou-desc-padding, 0);
    margin: var(--lxsf-thankyou-desc-margin, 8px 0 0);
}

/* ── Progress bar (segmented, inline inside the screen) ─────────
   Form is split into N sections by Statement steps. Each section
   gets its own segment in the track with a configurable gap between
   them; the current section's title is shown above (or below) the
   track as a caption. Forms without any Statement render as a single
   segment with no caption. */
/* Wrapper holds caption + track. Only outer spacing (margin) + the
   wrapper-specific bg live here — the bar's own padding / border belong
   on .lxsf-progress-track below. */
/* Wrapper holds caption + track. Owns ONLY the layout gap (between bar
   and the form content above/below it via the --top/--bottom modifiers)
   and the optional wrapper-bg. The schema's progress_margin / _padding
   / _border / _radius all apply on the .lxsf-progress-track below — so
   tweaking them in Design only affects the visible bar, not the
   wrapper that holds caption + bar. */
.lxsf-progress {
    width: 100%;
    background: var(--lxsf-progress-wrap-bg, transparent);
    border-radius: var(--lxsf-progress-wrap-radius, 0);
    /* Lets the hover tooltip dock against the bar's top edge. */
    position: relative;
}

.lxsf-progress--top {
    margin-bottom: var(--lxsf-progress-gap, 18px);
}

.lxsf-progress--bottom {
    margin-top: var(--lxsf-progress-gap, 18px);
}

/* The visible bar itself — schema's progress_padding / progress_margin /
   progress_border all apply HERE, not on the caption+bar wrapper above.
   That way the customer's "padding/margin" tweaks only affect the bar,
   exactly as expected. */
.lxsf-progress-track {
    display: flex;
    align-items: stretch;
    gap: var(--lxsf-progress-segment-gap, 6px);
    width: 100%;
    /* Default height applies to the inner content area now that padding
       lives on the track — keep the original 4px so old saved forms
       render at the same size. */
    height: var(--lxsf-progress-height, 4px);
    background: var(--lxsf-progress-bg, transparent);
    padding: var(--lxsf-progress-padding, 0);
    margin: var(--lxsf-progress-margin, 0);
    border-top: var(--lxsf-progress-border-top, none);
    border-right: var(--lxsf-progress-border-right, none);
    border-bottom: var(--lxsf-progress-border-bottom, none);
    border-left: var(--lxsf-progress-border-left, none);
    /* Use border-box so padding doesn't blow up the track's overall
       height beyond what the height var set. */
    box-sizing: content-box;
}

.lxsf-progress-segment {
    flex: 1;
    background: var(--lxsf-progress-track, rgba(0, 0, 0, 0.08));
    border-radius: var(--lxsf-progress-radius, 99px);
    overflow: hidden;
    position: relative;
    /* Click-to-jump — each segment is a <button>. Strip its native chrome
       so it visually reads as a bar tick instead of a button. */
    border: none;
    padding: 0;
    cursor: pointer;
    font: inherit;
    color: inherit;
    transition: transform 0.12s ease, filter 0.12s ease;
}

.lxsf-progress-segment:hover {
    filter: brightness(1.06);
    transform: translateY(-1px);
}

.lxsf-progress-segment:active {
    transform: translateY(0);
}

.lxsf-progress-segment:focus {
    outline: none;
}

.lxsf-progress-segment:focus-visible {
    box-shadow: 0 0 0 2px var(--lxsf-progress-fill, var(--lxsf-accent, #7c3aed));
}

/* Validation failure — this step's segment paints red until the field
   clears. The fill itself flips to a 100% red bar so the red is visible
   even on a step the visitor hasn't reached yet. */
.lxsf-progress-segment--error {
    background: var(--lxsf-progress-error-bg, #fee2e2);
}

.lxsf-progress-segment--error .lxsf-progress-fill {
    background: var(--lxsf-progress-error, #dc2626) !important;
    width: 100% !important;
}

.lxsf-progress-fill {
    height: 100%;
    width: 0;
    background: var(--lxsf-progress-fill, var(--lxsf-accent, #1e293b));
    transition: width 0.35s cubic-bezier(.22, .9, .3, 1);
}

/* Continuous mode — single bar. The track itself is the colored "rail";
   the inner fill grows with overall progress (curVis / total). */
.lxsf-progress-track--continuous {
    background: var(--lxsf-progress-track, rgba(0, 0, 0, 0.08));
    border-radius: var(--lxsf-progress-radius, 99px);
    overflow: hidden;
    display: block;
}

.lxsf-progress-track--continuous .lxsf-progress-fill {
    border-radius: inherit;
}

/* Hover tooltip — sits above the bar, hidden by default, revealed on
   hover/focus of the wrapper or track. Works for both modes. */
.lxsf-progress-tip {
    position: absolute;
    bottom: 100%;
    left: 50%;
    transform: translate(-50%, -2px);
    background: #0f172a;
    color: #ffffff;
    font-size: 11px;
    font-weight: 600;
    line-height: 1;
    padding: 6px 10px;
    border-radius: 6px;
    white-space: nowrap;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.15s ease, transform 0.15s ease;
    z-index: 30;
    box-shadow: 0 4px 12px -2px rgba(15, 23, 42, 0.18);
}

.lxsf-progress-tip::after {
    content: '';
    position: absolute;
    top: 100%;
    left: 50%;
    transform: translateX(-50%);
    border: 4px solid transparent;
    border-top-color: #0f172a;
}

.lxsf-progress:hover .lxsf-progress-tip,
.lxsf-progress:focus-within .lxsf-progress-tip {
    opacity: 1;
    transform: translate(-50%, -6px);
}

/* When the progress bar sits at the TOP of the form, the default
   tooltip position (above the bar) clips outside the iframe. Flip it
   below the bar instead — arrow points up, offset direction inverted.
   Bottom-positioned bars keep the default above-the-bar tooltip since
   there's plenty of room upward within the form.

   IMPORTANT: `top: 100%` on the outer .lxsf-progress wrap includes the
   statement caption sitting below the bar, so the tip drops way down
   the screen on statement-tagged steps. Anchor to the track's height
   instead — 4px default plus a small 6px breathing gap = ~10px below
   the bar's bottom edge, well above the caption regardless of length. */
.lxsf-progress--top .lxsf-progress-tip {
    bottom: auto;
    top: calc(var(--lxsf-progress-height, 4px) + 6px);
    transform: translate(-50%, 2px);
}

.lxsf-progress--top .lxsf-progress-tip::after {
    top: auto;
    bottom: 100%;
    border-top-color: transparent;
    border-bottom-color: #0f172a;
}

.lxsf-progress--top:hover .lxsf-progress-tip,
.lxsf-progress--top:focus-within .lxsf-progress-tip {
    transform: translate(-50%, 6px);
}

/* Section caption — text from the current Statement step's label */
.lxsf-progress-text {
    font-size: var(--lxsf-progress-text-size, 13px);
    font-weight: var(--lxsf-progress-text-weight, 500);
    color: var(--lxsf-progress-text-color, var(--lxsf-muted, #64748b));
    padding: var(--lxsf-progress-text-padding, 0);
    margin: var(--lxsf-progress-text-margin, 0);
    line-height: 1.4;
}

.lxsf-progress-text--above {
    margin: 0 0 8px;
}

/* Legacy single-bar class kept for back-compat with old saved markup —
   harmless if not used. */
.lxsf-progress-bar {
    height: 100%;
    background: var(--lxsf-progress-fill, var(--lxsf-accent, #1e293b));
    transition: width 0.3s ease;
    width: 0;
}

/* ── Error / validation ────────────────────────────────────────── */
.lxsf-error {
    text-align: center;
    padding: 40px 20px;
    color: #b91c1c;
    font-size: 16px;
    max-width: 480px;
    margin: 0 auto;
}

.lxsf-error-icon {
    font-size: 36px;
    margin-bottom: 12px;
}

.lxsf-field-error {
    font-size: 13px;
    color: #dc2626;
    margin-top: 8px;
    font-weight: 500;
}

/* ── Submitting state ──────────────────────────────────────────── */
.lxsf-submitting {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}

.lxsf-spinner {
    display: inline-block;
    width: 14px;
    height: 14px;
    border: 2px solid currentColor;
    border-top-color: transparent;
    border-radius: 50%;
    animation: lxsf-spin 0.8s linear infinite;
}

@keyframes lxsf-spin {
    to {
        transform: rotate(360deg);
    }
}

@media (max-width: 600px) {
    .lxsf-stage {
        padding: 20px 16px;
    }

    .lxsf-input,
    .lxsf-textarea {
        font-size: 18px;
    }

    .lxsf-date-input {
        font-size: 18px;
        width: 56px;
    }

    .lxsf-date-input--year {
        width: 76px;
    }
}

/* ═════════════════════════════════════════════════════════════════════
   VIEW-MODE polish (shareable /form/view page + Builder Preview iframe).
   Previously these rules lived inline in form-smart.blade.php which meant
   the preview iframe loaded the CSS file WITHOUT them, so the builder
   preview looked drastically different from the live page. Moving them
   here keeps both surfaces visually identical (single source of truth).
   ════════════════════════════════════════════════════════════════════ */

/* ── View-mode page (shareable link) ─────────────────────────────
   A professional, calm-luxury treatment for the standalone /form/view
   landing page. Subtle radial spotlight behind the form, glassmorphic
   header/footer, and a refined card with multi-layer depth. */
/* ── View-mode page (shareable link) ─────────────────────────────
   Soft off-white background, flat top-left brand (logo + website
   name), a doodle wallpaper behind everything, and a frosted-glass
   card wrapping the form with colourful accent triangles peeking
   out of the corners. The form root itself stays under the
   builder's design schema — this layer is page chrome only. */
.lxsf-body--view {
    /* Body background is set to a fixed white surface near the top of
       this file — Page Background knob was retired from the Embed Link
       Design surface. */
    /* Viewport-native scroll layout — the browser's main window scrolls vertically.
       Sidebar, Header, and Footer remain fixed/sticky using fixed positioning, 
       while only the right-side main form area (.lxsf-vp-main) flows and expands naturally.
       Mobile fallback (< 900px) reverts to natural stacked layout. */
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    position: relative;
    overflow-x: hidden;
    overflow-y: auto;
}

/* Old hardcoded form-doodle wallpaper — deleted after the Embed
   Link Design feature landed. The identical rule now lives near the
   top of this file (line ~30) reading --lxsf-vp-pattern +
   --lxsf-vp-pattern-opacity, so the customer can swap patterns from
   Form Settings. The "form-icons" preset in
   lxf_view_page_pattern_uri() reproduces this original doodle mix. */

/* ─────────────────────────────────────────────────────────────────
   View-page 2-column layout — white sidebar (brand top, form info
   middle) on the LEFT, form area vertically centred on the RIGHT.
   Footer stays full-width at the bottom.
   ────────────────────────────────────────────────────────────────── */
.lxsf-body--view .lxsf-vp-layout {
    display: flex;
    flex-direction: row;
    flex: 1 1 auto;
    align-items: stretch;
    width: 100%;
    overflow: visible;
}

/* Left sidebar — white surface with the same page pattern tiled over
   it at a slightly higher opacity than the body so the "light vector"
   texture reads on a white base. Spans from the very top of the page
   to the footer boundary. */
/* Header on the view page — holds the website name, aligned at the top
   of the screen, with top/left/right 30px padding and bottom 20px padding.
   Transparent background so the stretched sidebar bg shows through on the left. */
.lxsf-body--view .lxsf-header-view {
    padding: 30px 30px 20px 30px;
    position: fixed;
    /* Keep it fixed at the absolute top of viewport */
    top: 0;
    left: 0;
    right: 0;
    z-index: 10;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    background: transparent;
    pointer-events: none;
    /* Let scrolls and clicks pass through to lower layers */
}

.lxsf-body--view .lxsf-vp-header-brand {
    display: flex;
    align-items: center;
    gap: 10px;
    pointer-events: auto;
    /* Re-enable pointer events for links */
}

/* Left sidebar — transparent container that lets the full viewport-height
   stretched backdrop shine through, ensuring the header brand above it
   shares the white column. Fixed in place on desktop. */
.lxsf-body--view .lxsf-vp-sidebar {
    width: 420px;
    flex-shrink: 0;
    background: transparent;
    padding: 40px 44px;
    display: flex;
    flex-direction: column;
    position: fixed;
    /* Keep sidebar locked at the left of the viewport */
    top: 0;
    bottom: 0;
    left: 0;
    z-index: 2;
    overflow: hidden;
    border-right: none;
}

/* Stretched white sidebar background that runs from the absolute top to the absolute
   bottom of the viewport. */
.lxsf-body--view .lxsf-vp-sidebar::before {
    content: '';
    position: absolute;
    inset: 0;
    background-color: #ffffff;
    z-index: -2;
    pointer-events: none;
    border-right: none;
    /* Removed sidebar right border as requested */
}

/* Stretched pattern layer overlaying the stretched white background. */
.lxsf-body--view .lxsf-vp-sidebar::after {
    content: '';
    position: absolute;
    inset: 0;
    background-image: var(--lxsf-vp-pattern, none);
    background-repeat: repeat;
    opacity: 0.08;
    pointer-events: none;
    z-index: -1;
}

.lxsf-body--view .lxsf-vp-sidebar>* {
    position: relative;
    z-index: 1;
}

/* Brand row anchored at the top of the sidebar. `WP Local2` + a
   small dot spacer that sits after the name. */
.lxsf-body--view .lxsf-vp-sidebar-brand {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: auto;
}

.lxsf-body--view .lxsf-vp-sidebar-name {
    font-size: 22px;
    font-weight: 800;
    color: #0f172a;
    letter-spacing: -0.3px;
    line-height: 1.2;
    text-decoration: none;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    display: inline-block;
}

a.lxsf-vp-sidebar-name--link {
    color: inherit;
    transition: opacity 0.15s ease;
}

a.lxsf-vp-sidebar-name--link:hover {
    opacity: 0.7;
    text-decoration: underline;
    text-underline-offset: 4px;
}

.lxsf-vp-sidebar-brand-logo {
    height: 32px;
    width: auto;
    max-width: 200px;
    object-fit: contain;
    display: block;
}

/* Anchor wrapper around the website logo — strips the default
   underline/color so the logo image stands on its own but the whole
   image remains clickable. */
.lxsf-vp-sidebar-brand-link {
    display: inline-flex;
    align-items: center;
    text-decoration: none;
    color: inherit;
}

.lxsf-vp-sidebar-brand-link:hover .lxsf-vp-sidebar-brand-logo {
    opacity: 0.85;
    transition: opacity 0.15s ease;
}

/* Small round dot next to the website name — matches the mockup's
   `WP Local2 •` treatment so the sidebar has a subtle bullet accent. */
.lxsf-vp-sidebar-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: #7c3aed;
    display: inline-block;
    flex-shrink: 0;
}

/* Form-info block centred inside the sidebar. Space between elements
   is controlled explicitly using element margins. */
.lxsf-body--view .lxsf-vp-sidebar-info {
    margin-top: auto;
    margin-bottom: auto;
    display: flex;
    flex-direction: column;
    gap: 0;
}

/* Right column — form itself centred vertically inside a beautiful, rounded floating panel.
   Flush on top, right, and bottom (margins: 0) and offset from the sidebar.
   Left corners are curved to 20px where the colored background meets the white sidebar.
   Pads inside to let the card stand out cleanly. Inherits the original body custom background. */
.lxsf-body--view .lxsf-vp-main {
    margin: 0 0 0 420px;
    /* Flush on top, right, and bottom; offset exactly by sidebar width (420px) */
    background: #f4f6fa;
    /* Fixed slate-tinted panel — Page Background knob was retired */
    border-radius: 20px 0 0 20px;
    /* Round only left-side corners where it meets the sidebar */
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 80px 40px;
    /* Breathing room padding inside the panel */
    min-width: 0;
    position: relative;
    z-index: 1;
    overflow: visible;
    /* Flow naturally to let the body scrollbar handle the overflow */
}

/* Frame around the form root. Width matches the form's configured
   max-width. Kept for structural spacing; the decorative accent
   triangles + circles are hidden on the view page. */
.lxsf-body--view .lxsf-frame {
    position: relative;
    width: 100%;
    max-width: var(--lxsf-max-width, 780px);
    z-index: 5;
}

/* Form info now lives INSIDE the sidebar — flat text stack, no card
   surface or shadow. The tag pill, title, description, and step-count
   pill sit vertically with subtle spacing driven by the sidebar's
   flex-gap. */
.lxsf-body--view .lxsf-form-head-meta {
    display: inline-flex;
    align-self: flex-start;
    align-items: center;
    gap: 0;
    margin-top: 24px;
    /* Increased margin-top as requested */
    padding: 0;
    /* Reset button styles to simple text */
    font-size: 15px;
    /* Increased font size */
    font-weight: 300;
    /* Set font-weight to 300 / thin */
    color: #64748b;
    /* Soft light gray color */
    background: transparent;
    /* No background */
    border: none;
    /* No border */
    border-radius: 0;
    white-space: nowrap;
    box-shadow: none;
    /* No shadow */
}

.lxsf-body--view .lxsf-form-head-meta-dash {
    margin-right: 8px;
    color: #94a3b8;
    font-size: 16px;
    font-weight: 400;
}

/* Small uppercase pill above the form name using a beautiful green theme (#008744)
   with explicit tight margin to the title below. */
.lxsf-body--view .lxsf-form-head-tag {
    display: inline-block;
    align-self: flex-start;
    margin: 0 0 8px;
    padding: 3px 9px;
    font-size: 10.5px;
    font-weight: 700;
    color: #008744;
    background: #eafaf1;
    border-radius: 4px;
    letter-spacing: 0.6px;
    text-transform: uppercase;
    line-height: 1.4;
}

/* Title element with wider margin to the description below. */
.lxsf-body--view .lxsf-form-head-title {
    margin: 0 0 16px;
    font-size: 22px;
    font-weight: 700;
    color: #0f172a;
    line-height: 1.25;
    letter-spacing: -0.4px;
    word-break: break-word;
}

.lxsf-body--view .lxsf-form-head-desc {
    margin: 0;
    font-size: 14px;
    color: #475569;
    line-height: 1.6;
    word-break: break-word;
    white-space: pre-wrap;
}

/* Below the 2-col breakpoint the sidebar stacks above the form
   (matches the mockup's mobile fallback), the fixed-viewport lock
   is released so the page can scroll normally, and the vp-main's
   internal scroll switches to natural page flow. */
@media (max-width: 900px) {
    .lxsf-body--view {
        height: auto;
        min-height: 100vh;
        overflow: visible;
    }

    .lxsf-body--view .lxsf-header-view {
        position: relative;
        /* Reset fixed positioning on mobile */
        padding: 24px 24px 12px 24px;
        pointer-events: auto;
        /* Reset pointer events */
    }

    .lxsf-body--view .lxsf-vp-layout {
        flex-direction: column;
        overflow: visible;
    }

    .lxsf-body--view .lxsf-vp-sidebar {
        position: relative;
        /* Reset fixed positioning on mobile */
        width: 100%;
        background: #ffffff;
        /* Restore solid white background on mobile */
        padding: 28px 24px;
        border-right: none;
        border-bottom: 1px solid rgba(15, 23, 42, 0.05);
    }

    .lxsf-body--view .lxsf-vp-sidebar::before {
        position: absolute;
        inset: 0;
        width: auto;
        height: auto;
        background-color: transparent;
        background-image: var(--lxsf-vp-pattern, none);
        opacity: 0.08;
        z-index: 0;
        border-right: none;
    }

    .lxsf-body--view .lxsf-vp-sidebar::after {
        display: none;
    }

    .lxsf-body--view .lxsf-vp-sidebar-brand {
        margin-bottom: 20px;
    }

    .lxsf-body--view .lxsf-vp-sidebar-info {
        margin-top: 0;
        margin-bottom: 0;
    }

    .lxsf-body--view .lxsf-vp-main {
        margin: 0;
        /* Reset margins on mobile */
        border-radius: 0;
        /* Full-width panel on mobile */
        background: #f4f6fa;
        padding: 24px 16px;
        overflow: visible;
    }

    .lxsf-body--view .lxsf-footer {
        position: relative;
        /* Reset fixed positioning on mobile */
        width: 100%;
        padding: 24px 16px;
        pointer-events: auto;
        /* Reset pointer events */
    }

    .lxsf-body--view .lxsf-preview-badge {
        position: relative;
        /* Reset fixed positioning on mobile */
        right: auto;
        top: auto;
        transform: none;
        margin-left: auto;
        /* Align right side of header on mobile */
        pointer-events: auto;
    }
}

@media (max-width: 600px) {
    .lxsf-body--view .lxsf-header-view {
        padding: 20px 20px 10px 20px;
    }

    .lxsf-body--view .lxsf-vp-sidebar {
        padding: 24px 20px;
    }

    .lxsf-body--view .lxsf-vp-sidebar-name {
        font-size: 18px;
    }

    .lxsf-body--view .lxsf-form-head-title {
        font-size: 18px;
    }

    .lxsf-body--view .lxsf-form-head-desc {
        font-size: 13px;
    }
}

/* Legacy triangles + circles are no longer rendered on the view
   page (the 2-col sidebar layout replaced the decorative frame).
   The animation keyframes + positional rules below stay in place
   as dead-but-harmless CSS in case a saved form still emits the
   markup somewhere — this rule keeps them invisible unconditionally. */
.lxsf-body--view .lxsf-triangle,
.lxsf-body--view .lxsf-circle {
    display: none !important;
}

.lxsf-body--view .lxsf-triangle {
    clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
    opacity: 0.92;
    will-change: transform;
}

.lxsf-body--view .lxsf-circle {
    border-radius: 50%;
    opacity: 0.85;
    will-change: transform;
}

@keyframes lxsf-spin-cw {
    from {
        transform: rotate(0deg);
    }

    to {
        transform: rotate(360deg);
    }
}

@keyframes lxsf-spin-ccw {
    from {
        transform: rotate(0deg);
    }

    to {
        transform: rotate(-360deg);
    }
}

@keyframes lxsf-float {

    0%,
    100% {
        transform: translateY(0);
    }

    50% {
        transform: translateY(-12px);
    }
}

@keyframes lxsf-pulse {

    0%,
    100% {
        transform: scale(1);
        opacity: 0.85;
    }

    50% {
        transform: scale(1.18);
        opacity: 1;
    }
}

/* Top-left triangle cluster */
.lxsf-body--view .lxsf-tri-1 {
    width: 64px;
    height: 64px;
    background: #ec4899;
    top: -28px;
    left: -46px;
    animation: lxsf-spin-cw 18s linear infinite;
}

.lxsf-body--view .lxsf-tri-2 {
    width: 34px;
    height: 34px;
    background: #3b82f6;
    top: 96px;
    left: -62px;
    opacity: 0.85;
    animation: lxsf-spin-ccw 12s linear infinite;
}

.lxsf-body--view .lxsf-tri-3 {
    width: 44px;
    height: 44px;
    background: #f97316;
    top: -38px;
    left: 118px;
    opacity: 0.88;
    animation: lxsf-spin-cw 22s linear infinite;
}

/* Bottom-right triangle cluster */
.lxsf-body--view .lxsf-tri-4 {
    width: 52px;
    height: 52px;
    background: #3b82f6;
    bottom: 76px;
    right: -56px;
    opacity: 0.88;
    animation: lxsf-spin-ccw 16s linear infinite;
}

.lxsf-body--view .lxsf-tri-5 {
    width: 32px;
    height: 32px;
    background: #ec4899;
    bottom: -22px;
    right: -36px;
    opacity: 0.85;
    animation: lxsf-spin-cw 10s linear infinite;
}

/* Circles — solid + outline mix for visual rhythm */
.lxsf-body--view .lxsf-c-2 {
    width: 38px;
    height: 38px;
    background: transparent;
    border: 3px solid #f97316;
    top: -16px;
    right: 30px;
    animation: lxsf-float 5s ease-in-out infinite;
}

.lxsf-body--view .lxsf-c-4 {
    width: 32px;
    height: 32px;
    background: transparent;
    border: 3px solid #ec4899;
    bottom: -14px;
    left: 220px;
    animation: lxsf-float 6s ease-in-out infinite;
    animation-delay: 0.5s;
}

/* Template preview mode — keep the original decorative palette but
   dial the opacity down so the shapes whisper rather than shout.
   The pulsing amber dot in the header already signals "preview" —
   the shapes don't need to compete with it. */
.lxsf-body--preview .lxsf-triangle,
.lxsf-body--preview .lxsf-circle {
    opacity: 0.4;
}

/* Extra category chips — when a template lives in more than one
   category, the first one fills the "ONLINE FORM" tag slot and the
   rest sit as small chips under the title. Keeps the head card
   single-line tag clean while still surfacing the full taxonomy. */
.lxsf-body--view .lxsf-form-head-extra-cats {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 10px;
}

.lxsf-body--view .lxsf-form-head-cat-chip {
    display: inline-flex;
    align-items: center;
    background: #f1f5f9;
    color: #64748b;
    border: 1px solid #e2e8f0;
    border-radius: 4px;
    padding: 2px 8px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.4px;
    text-transform: uppercase;
}

/* Respect reduced-motion preference — disable decorative motion
   for visitors who've opted out. */
@media (prefers-reduced-motion: reduce) {

    .lxsf-body--view .lxsf-triangle,
    .lxsf-body--view .lxsf-circle {
        animation: none !important;
    }
}

/* Header — flat top-left brand row. No bg, no shadow, no card. */
.lxsf-body--view .lxsf-header {
    background: transparent;
    box-shadow: none;
    border: none;
    border-radius: 0;
    padding: 18px 28px;
    margin: 0;
    width: 100%;
    max-width: none;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
}

.lxsf-body--view .lxsf-header::after {
    display: none;
}

/* Left-side brand cluster — logo + website name sit together. */
.lxsf-body--view .lxsf-header-brand {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
}

.lxsf-body--view .lxsf-header-logo {
    width: 28px;
    height: 28px;
    border-radius: 30px;
    object-fit: contain;
    background: #ffffff;
    border: 1px solid rgba(15, 23, 42, 0.06);
    padding: 2px;
    flex-shrink: 0;
}

/* Initials fallback when no website logo/favicon is available. */
.lxsf-body--view .lxsf-header-logo--initial {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 13px;
    font-weight: 700;
    color: #475569;
    text-transform: uppercase;
    letter-spacing: 0;
    background: #e2e8f0;
    border: none;
    padding: 0;
}

.lxsf-body--view .lxsf-header-name {
    font-size: 20px;
    font-weight: 700;
    letter-spacing: -0.2px;
    color: #1e293b;
    user-select: none;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    display: inline-block;
    padding: 4px 2px;
}

/* Link variant — same weight/size as the plain header name so the
   two never disagree on layout; underline appears on hover to make
   the affordance obvious without hurting the branded look. */
.lxsf-body--view .lxsf-header-name--link {
    text-decoration: none;
    cursor: pointer;
    color: inherit;
    transition: opacity 0.15s ease;
}

.lxsf-body--view .lxsf-header-name--link:hover {
    text-decoration: underline;
    text-underline-offset: 4px;
    opacity: 0.85;
}

/* Template-preview header — LeadXForms brand on the left, solid
   PREVIEW badge on the right. No avatar / favicon / website link
   because templates aren't bound to a real website. */
.lxsf-body--view .lxsf-header--preview .lxsf-header-brand {
    background: transparent;
    border: none;
    padding: 0;
    gap: 0;
}

.lxsf-body--view .lxsf-header-brand-logo {
    height: 42px;
    width: auto;
    display: block;
}

/* Inline preview indicator — rotated vertically and floating along the absolute
   right-hand margin of the screen on desktop. */
.lxsf-body--view .lxsf-preview-badge {
    position: fixed;
    right: 20px;
    /* Stay close to the right edge */
    top: 120px;
    transform: translateY(-50%) rotate(90deg);
    /* Vertical rotation! */
    transform-origin: right center;
    z-index: 9999;
    /* Float above everything! */
    display: inline-flex;
    align-items: center;
    gap: 10px;
    font-size: 12px;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 3px;
    /* Modern spaced letters for vertical look */
    color: #64748b;
    /* Soft elegant color */
    background: transparent;
    border: none;
    padding: 0;
    user-select: none;
    pointer-events: none;
    /* Let clicks pass through */
    white-space: nowrap;
}

.lxsf-body--view .lxsf-preview-dot {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: #7c3aed;
    box-shadow: 0 0 0 0 rgba(124, 58, 237, 0.6);
    animation: lxsf-preview-pulse 1.8s ease-in-out infinite;
    flex-shrink: 0;
    display: inline-block;
}

@keyframes lxsf-preview-pulse {
    0% {
        box-shadow: 0 0 0 0 rgba(124, 58, 237, 0.55);
    }

    70% {
        box-shadow: 0 0 0 6px rgba(124, 58, 237, 0);
    }

    100% {
        box-shadow: 0 0 0 0 rgba(124, 58, 237, 0);
    }
}

@media (prefers-reduced-motion: reduce) {
    .lxsf-body--view .lxsf-preview-dot {
        animation: none;
    }
}

/* "Visit website" pill — sleek glassy design with subtle hover elevation and neutral transition */
.lxsf-visit-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    font-weight: 600;
    color: #475569;
    background: rgba(255, 255, 255, 0.9);
    border: 1px solid rgba(226, 232, 240, 0.8);
    border-radius: 10px;
    padding: 6px 14px;
    text-decoration: none;
    white-space: nowrap;
    transition: all 0.25s cubic-bezier(0.16, 1, 0.3, 1);
    box-shadow:
        0 1px 2px 0 rgba(15, 23, 42, 0.02),
        0 0 0 1px rgba(255, 255, 255, 0.8) inset;
}

.lxsf-visit-btn:hover {
    border-color: #cbd5e1;
    color: #0f172a;
    background: #ffffff;
    transform: translateY(-1px);
    box-shadow:
        0 6px 14px -6px rgba(15, 23, 42, 0.08),
        0 0 0 1px rgba(255, 255, 255, 0.9) inset;
}

.lxsf-visit-btn svg {
    width: 14px;
    height: 14px;
    flex-shrink: 0;
    color: #64748b;
    transition: color 0.2s ease;
}

.lxsf-visit-btn:hover svg {
    color: #0f172a;
}

/* Stage — vertically centred, generous padding. Flex column so the
   form-name strip stacks ABOVE the form frame instead of sitting next
   to it (the default row direction made the head card slide off to
   one side of the welcome card). */
.lxsf-body--view .lxsf-stage {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 40px 16px;
}

/* Default-chrome card — glassy white surface wrapping the form when
   the builder's design says "no card". 85% opaque white + backdrop
   blur so the doodle wallpaper and accent triangles behind the form
   show through as a soft frosted wash. Matches the classic view
   page card spec (30px padding, 6px radius) for a consistent look
   across both renderers. */
.lxsf-body--view .lxsf-app--default-chrome {
    background: rgba(255, 255, 255, 0.85);
    backdrop-filter: blur(16px) saturate(140%);
    -webkit-backdrop-filter: blur(16px) saturate(140%);
    border: 1px solid rgba(255, 255, 255, 0.6);
    border-radius: 6px;
    box-shadow:
        0 1px 3px rgba(15, 23, 42, 0.04),
        0 12px 32px -12px rgba(15, 23, 42, 0.10);
    transition: none;
    width: 100%;
    max-width: 780px;
    padding: 30px;
    margin: 0 auto;
    position: relative;
    z-index: 2;
}

.lxsf-body--view .lxsf-app--default-chrome:hover {
    transform: none;
    box-shadow:
        0 1px 3px rgba(15, 23, 42, 0.04),
        0 12px 32px -12px rgba(15, 23, 42, 0.10);
}

/* Footer — split layout: copyright on the LEFT, "Powered by [logo]"
   on the RIGHT. Slim transparent layout that stays out of the way. */
.lxsf-body--view .lxsf-footer {
    padding: 10px 20px;
    /* Slimmer top/bottom and narrower left/right padding as requested */
    font-size: 12px;
    color: #64748b;
    background: transparent;
    /* Removed background as requested */
    border: none;
    border-top: none;
    /* Removed top border as requested */
    display: flex;
    align-items: center;
    justify-content: space-between;
    /* Restored split alignment */
    gap: 12px;
    margin-top: auto;
    flex-shrink: 0;
    position: fixed;
    /* Keep footer fixed at the absolute bottom of viewport */
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 10;
    pointer-events: none;
    /* Let scrolls and clicks pass through to lower layers */
}

.lxsf-body--view .lxsf-footer-left,
.lxsf-body--view .lxsf-footer-right {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    pointer-events: auto;
    /* Re-enable pointer events for copyright and brand links */
}

.lxsf-footer-separator {
    margin: 0 8px;
    color: #cbd5e1;
}

.lxsf-footer span,
.lxsf-footer-powered-text {
    font-weight: 500;
    letter-spacing: 0.1px;
}

.lxsf-footer-brand {
    display: inline-flex;
    align-items: center;
    text-decoration: none;
    opacity: 0.85;
    transition: opacity 0.15s ease, transform 0.15s ease;
}

.lxsf-footer-brand:hover {
    opacity: 1;
    transform: translateY(-0.5px);
}

.lxsf-footer-logo {
    height: 22px;
    width: auto;
    display: block;
}

@media (max-width: 600px) {
    .lxsf-body--view .lxsf-stage {
        padding: 24px 12px;
    }

    .lxsf-body--view .lxsf-header {
        padding: 14px 16px;
        gap: 10px;
    }

    .lxsf-body--view .lxsf-header-logo {
        width: 24px;
        height: 24px;
    }

    .lxsf-body--view .lxsf-header-name {
        font-size: 17px;
    }

    .lxsf-body--view .lxsf-app--default-chrome {
        padding: 22px 18px;
        border-radius: 6px;
    }

    /* Hide accent triangles + circles on small screens — they'd
       either crowd the card or get clipped by the viewport. */
    .lxsf-body--view .lxsf-triangle,
    .lxsf-body--view .lxsf-circle {
        display: none;
    }

    .lxsf-footer-logo {
        height: 18px;
    }
}

/* ── Custom radio / checkbox indicator (the smaller "auto" indicator
   variant rendered on choice rows when no per-element styling overrides). */
.lxsf-indicator {
    width: 16px;
    height: 16px;
    border: 1.5px solid #cbd5e1;
    flex-shrink: 0;
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: all 0.15s ease;
    box-sizing: border-box;
}

.lxsf-indicator--radio {
    border-radius: 50%;
}

.lxsf-indicator--checkbox {
    border-radius: 3px;
}

.lxsf-indicator--selected {
    background-color: var(--lxsf-choice-selected, #7c3aed) !important;
    border-color: var(--lxsf-choice-selected, #7c3aed) !important;
}

.lxsf-indicator--radio.lxsf-indicator--selected::after {
    content: '';
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: #ffffff;
}

.lxsf-indicator--checkbox.lxsf-indicator--selected::after {
    content: '✓';
    color: #ffffff;
    font-size: 11px;
    font-weight: bold;
    line-height: 1;
}

.lxsf-pic-indicator {
    position: absolute;
    top: 8px;
    right: 8px;
    background: rgba(255, 255, 255, 0.9);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
    z-index: 2;
}

/* Strip default browser outlines on focus (we use border-color instead) */
input:focus,
textarea:focus,
select:focus,
button:focus,
input:focus-visible,
textarea:focus-visible,
select:focus-visible,
button:focus-visible {
    outline: none !important;
    box-shadow: none !important;
}

/* Pretty validation error pill */
.lxsf-field-error {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 12.5px;
    color: #b91c1c;
    background: #fef2f2;
    border: 1px solid #fca5a5;
    padding: 6px 12px;
    border-radius: 6px;
    margin-top: 14px;
    font-weight: 600;
    box-shadow: 0 1px 2px 0 rgba(220, 38, 38, 0.04);
    animation: lxsf-err-shake 0.4s cubic-bezier(.36, .07, .19, .97) both;
}

.lxsf-field-error:empty {
    display: none;
}

/* Inline SVG glyph inside the validation pill — rendered by
   showError() in lxf-smart-form.js. Sized to match the pill text. */
.lxsf-field-error svg {
    width: 14px;
    height: 14px;
    flex-shrink: 0;
}

/* Big top-of-screen error icon (form-blocked / subscription error blades). */
.lxsf-error-icon svg {
    width: 48px;
    height: 48px;
    color: #dc2626;
}

/* Success glyph on the Thank-You screen — green circle-tick, sits above
   the title with a soft drop-in scale so it feels celebratory without
   being loud. */
.lxsf-success-icon {
    display: flex;
    justify-content: center;
    margin-bottom: 14px;
}

.lxsf-success-icon svg {
    width: 56px;
    height: 56px;
    color: #16a34a;
    animation: lxsf-success-pop 0.5s cubic-bezier(.34, 1.56, .64, 1) both;
}

@keyframes lxsf-success-pop {
    0% {
        opacity: 0;
        transform: scale(0.5);
    }

    60% {
        opacity: 1;
        transform: scale(1.08);
    }

    100% {
        opacity: 1;
        transform: scale(1);
    }
}

/* Row-arrow chevron SVG — size derives from the button's font-size so
   the schema's arrow_font_size still controls how big the chevron is.
   Uses 1em width/height for crisp scaling alongside the button label. */
.lxsf-arrow svg {
    width: 1em;
    height: 1em;
    display: block;
    flex-shrink: 0;
}

/* Primary button icon — sized via --lxsf-btn-icon-size so the legacy
   schema control still drives the icon dimensions. */
.lxsf-btn-icon {
    display: inline-flex;
    align-items: center;
    line-height: 1;
}

.lxsf-btn-icon svg {
    /* Floor the icon at 20px so a text+icon button reads well next
       to 16px text — old forms have --lxsf-btn-icon-size baked to
       14px which looked too tiny beside the label. max() lets users
       who explicitly set a larger value still get their bigger size. */
    width:  max(20px, var(--lxsf-btn-icon-size, 20px));
    height: max(20px, var(--lxsf-btn-icon-size, 20px));
    display: block;
}

/* Icon-only buttons (mode = 'icon') get a fixed 22px glyph so the
   arrow reads as an icon rather than a tiny mark. Kept small enough
   that the button's own height doesn't visibly grow beyond the
   text-button height (padding + 22px ≈ same as padding + 16px text
   line-height). Text+icon buttons stay at the default 14–16px so
   the icon matches the adjacent text. Applies to both the primary
   CTA (.lxsf-btn) and the inline Back button (.lxsf-back-btn). */
.lxsf-btn--icon-only .lxsf-btn-icon svg {
    width:  22px;
    height: 22px;
    stroke-width: 2.2;
}

@keyframes lxsf-err-shake {

    10%,
    90% {
        transform: translate3d(-1px, 0, 0);
    }

    20%,
    80% {
        transform: translate3d(2px, 0, 0);
    }

    30%,
    50%,
    70% {
        transform: translate3d(-3px, 0, 0);
    }

    40%,
    60% {
        transform: translate3d(3px, 0, 0);
    }
}

/* ───────────────────────────────────────────────────────────
   Advanced field types (time, rating, address, likert,
   ranking, signature). Visual language mirrors the classic
   form (.lxform-*) — re-implemented with .lxsf- prefix so the
   smart form's standalone stylesheet stays self-contained.
   ─────────────────────────────────────────────────────────── */

/* Rating — row of icon glyphs with pure-CSS hover/checked highlight
   (uses row-reverse + the sibling combinator). */
.lxsf-rating {
    display: inline-flex;
    flex-direction: row-reverse;
    gap: var(--lxsf-rating-gap, 6px);
    line-height: 1;
    color: var(--lxsf-rating-empty, #cbd5e1);
}

.lxsf-rating-radio {
    position: absolute;
    left: -9999px;
    opacity: 0;
    pointer-events: none;
}

.lxsf-rating-star {
    cursor: pointer;
    display: inline-flex;
    width: var(--lxsf-rating-size, 36px);
    height: var(--lxsf-rating-size, 36px);
    /* Slightly longer than before so the hover-cascade stagger below
       has room to breathe visually. */
    transition: color 0.2s ease, transform 0.18s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.lxsf-rating-star svg {
    width: 100%;
    height: 100%;
    pointer-events: none;
}

/* Per-icon filled colors. `--lxsf-rating-filled` (set by the Design
   panel) overrides ALL icons when present; otherwise the per-icon
   fallback in each var() wins. */
.lxsf-rating[data-icon="star"] .lxsf-rating-star:hover,
.lxsf-rating[data-icon="star"] .lxsf-rating-star:hover~.lxsf-rating-star,
.lxsf-rating[data-icon="star"] .lxsf-rating-radio:checked~.lxsf-rating-star {
    color: var(--lxsf-rating-filled, #f59e0b);
}

.lxsf-rating[data-icon="heart"] .lxsf-rating-star:hover,
.lxsf-rating[data-icon="heart"] .lxsf-rating-star:hover~.lxsf-rating-star,
.lxsf-rating[data-icon="heart"] .lxsf-rating-radio:checked~.lxsf-rating-star {
    color: var(--lxsf-rating-filled, #ef4444);
}

.lxsf-rating[data-icon="thumb"] .lxsf-rating-star:hover,
.lxsf-rating[data-icon="thumb"] .lxsf-rating-star:hover~.lxsf-rating-star,
.lxsf-rating[data-icon="thumb"] .lxsf-rating-radio:checked~.lxsf-rating-star {
    color: var(--lxsf-rating-filled, #2563eb);
}

.lxsf-rating[data-icon="fire"] .lxsf-rating-star:hover,
.lxsf-rating[data-icon="fire"] .lxsf-rating-star:hover~.lxsf-rating-star,
.lxsf-rating[data-icon="fire"] .lxsf-rating-radio:checked~.lxsf-rating-star {
    color: var(--lxsf-rating-filled, #f97316);
}

.lxsf-rating[data-icon="smile"] .lxsf-rating-star:hover,
.lxsf-rating[data-icon="smile"] .lxsf-rating-star:hover~.lxsf-rating-star,
.lxsf-rating[data-icon="smile"] .lxsf-rating-radio:checked~.lxsf-rating-star {
    color: var(--lxsf-rating-filled, #eab308);
}

.lxsf-rating-star:hover {
    transform: scale(1.12);
}

/* Emoji / smile icon type gets a bigger + playful hover (extra scale +
   slight tilt) because it reads as a face — subtle rotation adds
   personality that plain stars/hearts don't need. */
.lxsf-rating[data-icon="smile"] .lxsf-rating-star:hover {
    transform: scale(1.2) rotate(-6deg);
}

/* Left-to-right fill cascade on hover — each sibling AFTER the
   hovered star (which visually sits to its left under row-reverse)
   waits a hair longer before its color transition kicks in, so the
   fill ripples across the row instead of snapping all at once.
   Staircases 40ms → 160ms across up to 5 stars past the hovered
   one; forms with more stars still work, they just cap at 160ms. */
.lxsf-rating-star:hover ~ .lxsf-rating-star {
    transition-delay: 40ms;
}
.lxsf-rating-star:hover ~ .lxsf-rating-star ~ .lxsf-rating-star {
    transition-delay: 80ms;
}
.lxsf-rating-star:hover ~ .lxsf-rating-star ~ .lxsf-rating-star ~ .lxsf-rating-star {
    transition-delay: 120ms;
}
.lxsf-rating-star:hover ~ .lxsf-rating-star ~ .lxsf-rating-star ~ .lxsf-rating-star ~ .lxsf-rating-star {
    transition-delay: 160ms;
}

/* Selected star pop — bounce + wiggle for the ONE star the visitor
   just clicked (not the ones filled behind it). Uses adjacent
   sibling `+` so only the label directly after the checked input
   matches. Spring easing overshoots slightly at scale peaks for a
   physical "click landed" feel. */
@keyframes lxsf-rating-pop {
    0%   { transform: scale(1)    rotate(0);    }
    25%  { transform: scale(1.28) rotate(-8deg); }
    50%  { transform: scale(1.10) rotate(6deg);  }
    75%  { transform: scale(1.18) rotate(-3deg); }
    100% { transform: scale(1)    rotate(0);    }
}

.lxsf-rating-radio:checked + .lxsf-rating-star {
    animation: lxsf-rating-pop 480ms cubic-bezier(0.34, 1.56, 0.64, 1);
}

/* Smile icon pop is bigger + wigglier so the emoji face reads as
   "delighted" rather than just "selected". */
.lxsf-rating[data-icon="smile"] .lxsf-rating-radio:checked + .lxsf-rating-star {
    animation: lxsf-rating-pop-emoji 520ms cubic-bezier(0.34, 1.56, 0.64, 1);
}

@keyframes lxsf-rating-pop-emoji {
    0%   { transform: scale(1)    rotate(0);     }
    20%  { transform: scale(1.35) rotate(-12deg); }
    40%  { transform: scale(1.20) rotate(10deg);  }
    60%  { transform: scale(1.25) rotate(-6deg);  }
    80%  { transform: scale(1.15) rotate(3deg);   }
    100% { transform: scale(1)    rotate(0);     }
}

.lxsf-rating-radio:focus-visible+.lxsf-rating-star {
    outline: 2px solid #0f172a;
    outline-offset: 2px;
    border-radius: 4px;
}

@media (prefers-reduced-motion: reduce) {
    .lxsf-rating-star,
    .lxsf-rating-radio:checked + .lxsf-rating-star {
        transition: color 0.15s ease !important;
        animation: none !important;
    }
    .lxsf-rating-star:hover ~ .lxsf-rating-star,
    .lxsf-rating-star:hover ~ .lxsf-rating-star ~ .lxsf-rating-star,
    .lxsf-rating-star:hover ~ .lxsf-rating-star ~ .lxsf-rating-star ~ .lxsf-rating-star,
    .lxsf-rating-star:hover ~ .lxsf-rating-star ~ .lxsf-rating-star ~ .lxsf-rating-star ~ .lxsf-rating-star {
        transition-delay: 0 !important;
    }
}

/* Address composite */
.lxsf-address {
    display: flex;
    flex-direction: column;
    gap: var(--lxsf-addr-gap, 10px);
    width: 100%;
}

.lxsf-addr-row {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.lxsf-addr-row--multi {
    display: grid;
    grid-template-columns: 2fr 1.5fr 1fr;
    gap: var(--lxsf-addr-row-gap, 10px);
}

@media (max-width: 560px) {
    .lxsf-addr-row--multi {
        grid-template-columns: 1fr;
    }
}

.lxsf-addr-cell {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.lxsf-addr-lbl {
    font-size: var(--lxsf-addr-label-size, 12px);
    color: var(--lxsf-addr-label-color, #475569);
    font-weight: var(--lxsf-addr-label-weight, 500);
}

/* Address sub-input font size — independent default of 18px (smaller
   than the regular text input's 26 so all six sub-cells fit comfortably
   in one row on a typical card width). Placeholder pseudo-element
   overrides Typography → Placeholder's --lxsf-placeholder-font-size for
   address only, so the placeholder shrinks alongside the typed text. */
.lxsf-address .lxsf-input {
    font-size: var(--lxsf-addr-input-font-size, 18px);
}

.lxsf-address .lxsf-input::placeholder {
    font-size: var(--lxsf-addr-input-font-size, 18px);
}

/* Time picker — native input narrowed by default; design panel can
   tighten or widen via --lxsf-time-max-width. Targets the .lxsf-input
   that smart-form renders with type=time. */
.lxsf-input[type="time"] {
    max-width: var(--lxsf-time-max-width, 220px);
}

/* SR-only utility — keeps Likert column labels associated with
   each radio for screen readers without showing them visually. */
.lxsf-sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Likert — statements × scale columns. Mobile collapses each
   row to a stacked block with the column label inline via
   the cell's data-col attr. */
.lxsf-likert {
    width: 100%;
    border-collapse: collapse;
    font-size: 13px;
}

.lxsf-likert th,
.lxsf-likert td {
    padding: var(--lxsf-likert-cell-padding, 8px 6px);
    text-align: center;
    border-top: var(--lxsf-likert-border-top, 1px solid #e2e8f0);
    border-right: var(--lxsf-likert-border-right, 1px solid #e2e8f0);
    border-bottom: var(--lxsf-likert-border-bottom, 1px solid #e2e8f0);
    border-left: var(--lxsf-likert-border-left, 1px solid #e2e8f0);
}

.lxsf-likert th {
    font-weight: 600;
    color: var(--lxsf-likert-header-color, #334155);
    background: var(--lxsf-likert-header-bg, #f8fafc);
    font-size: var(--lxsf-likert-header-size, 12px);
}

.lxsf-likert-stmt {
    text-align: left !important;
    color: var(--lxsf-likert-stmt-color, #1e293b);
    font-weight: var(--lxsf-likert-stmt-weight, 500);
}

.lxsf-likert-cell input[type="radio"] {
    accent-color: var(--lxsf-likert-radio, currentColor);
}

.lxsf-likert-cell label {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    padding: 4px;
}

@media (max-width: 560px) {

    .lxsf-likert,
    .lxsf-likert thead,
    .lxsf-likert tbody,
    .lxsf-likert tr,
    .lxsf-likert td,
    .lxsf-likert th {
        display: block;
        border: none;
    }

    .lxsf-likert thead {
        display: none;
    }

    .lxsf-likert tbody tr {
        border: 1px solid #e2e8f0;
        border-radius: 8px;
        margin-bottom: 8px;
        padding: 8px;
    }

    .lxsf-likert-stmt {
        padding-bottom: 4px;
    }

    .lxsf-likert-cell {
        display: inline-flex !important;
        gap: 6px;
        padding: 4px;
    }

    .lxsf-likert-cell::after {
        content: attr(data-col);
        font-size: 11px;
        color: #64748b;
    }
}

/* Ranking — drag-to-reorder rows */
.lxsf-ranking {
    display: block;
    width: 100%;
}

.lxsf-ranking-list {
    display: flex;
    flex-direction: column;
    gap: var(--lxsf-ranking-gap, 6px);
    margin-top: 4px;
}

.lxsf-ranking-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: var(--lxsf-ranking-item-padding, 10px 14px);
    background: var(--lxsf-ranking-item-bg, #fff);
    border-top: var(--lxsf-ranking-item-border-top, 1px solid #cbd5e1);
    border-right: var(--lxsf-ranking-item-border-right, 1px solid #cbd5e1);
    border-bottom: var(--lxsf-ranking-item-border-bottom, 1px solid #cbd5e1);
    border-left: var(--lxsf-ranking-item-border-left, 1px solid #cbd5e1);
    border-radius: var(--lxsf-ranking-item-radius, 8px);
    cursor: grab;
    user-select: none;
    transition: background .12s ease, border-color .12s ease, transform .12s ease;
}

.lxsf-ranking-item:hover {
    background: var(--lxsf-ranking-hover-bg, #f8fafc);
    border-color: var(--lxsf-ranking-hover-border, #94a3b8);
}

.lxsf-ranking-item.is-dragging {
    opacity: .5;
    cursor: grabbing;
}

.lxsf-ranking-item.is-over {
    border-color: #0f172a;
    background: #f1f5f9;
}

.lxsf-ranking-handle {
    color: var(--lxsf-ranking-handle, #94a3b8);
    display: inline-flex;
    flex: 0 0 auto;
}

.lxsf-ranking-pos {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: var(--lxsf-ranking-pos-size, 22px);
    height: var(--lxsf-ranking-pos-size, 22px);
    background: var(--lxsf-ranking-pos-bg, #0f172a);
    color: var(--lxsf-ranking-pos-text, #fff);
    border-radius: 9999px;
    font-size: 11px;
    font-weight: 700;
}

.lxsf-ranking-lbl {
    flex: 1;
    font-size: var(--lxsf-ranking-label-size, 14px);
    color: var(--lxsf-ranking-label-color, #1e293b);
}

/* Signature pad */
.lxsf-signature {
    display: flex;
    flex-direction: column;
    gap: 6px;
    align-items: flex-start;
    max-width: 100%;
}

.lxsf-signature-canvas {
    width: 100%;
    max-width: var(--lxsf-sig-max-width, 420px);
    height: var(--lxsf-sig-height, 140px);
    background: var(--lxsf-sig-canvas-bg, #fff);
    border-top: var(--lxsf-sig-canvas-border-top, 1px solid #cbd5e1);
    border-right: var(--lxsf-sig-canvas-border-right, 1px solid #cbd5e1);
    border-bottom: var(--lxsf-sig-canvas-border-bottom, 1px solid #cbd5e1);
    border-left: var(--lxsf-sig-canvas-border-left, 1px solid #cbd5e1);
    border-radius: var(--lxsf-sig-canvas-radius, 8px);
    cursor: crosshair;
    touch-action: none;
    display: block;
}

.lxsf-signature-clear {
    font-size: 12px;
    padding: 4px 10px;
    background: var(--lxsf-sig-clear-bg, #f1f5f9);
    border: 1px solid var(--lxsf-sig-clear-border, #cbd5e1);
    border-radius: var(--lxsf-sig-clear-radius, 4px);
    color: var(--lxsf-sig-clear-text, #475569);
    cursor: pointer;
}

.lxsf-signature-clear:hover {
    background: #e2e8f0;
}