/*
 * Bulk recipient entry (business mode) on the gift card buy page.
 *
 * Deliberately not @imported into style.css like the theme's other stylesheets
 * — this is enqueued only on product 6666 alongside the grid libraries, which
 * must not load site-wide.
 */

/* Declared high up rather than on the components — the delivery choice block and
   the modal are siblings of #ecoswap-bulk-div, not descendants, so a scoped
   declaration would leave them with undefined vars. Names are prefixed and this
   file only loads on the buy page.

   RE-POINTED AT THE CURRENT DESIGN SYSTEM 2026-09-11.
   These used to be the old Ecoswap palette — teal #00514b, mint #00f0a7, the
   blue-grey neutrals — which is what made the business section look like a
   different site from the panel above it. The names are kept because ~800 lines
   reference them; only the values moved.

   ── ON `body`, NOT `:root`, AND THAT IS LOAD-BEARING ────────────────────────
   --gcp-* are declared on `.postid-6666`, which IS the body element. `:root` is
   <html> — the body's ANCESTOR — and custom properties only inherit DOWNWARD.
   Read from :root, every var(--gcp-*) below resolved to nothing; a declaration
   whose var() is undefined is invalid at computed-value time, so the surfaces
   fell back to `transparent` and the spreadsheet view lost its background
   entirely. It presented as a layout bug and was a scoping one.

   Every reference also carries a LITERAL FALLBACK for the same reason: if the
   --gcp-* block is ever moved or renamed this degrades to the right colours
   instead of silently going transparent again.

   The two danger colours are deliberately NOT re-pointed: they carry meaning
   rather than brand, and the design system has no error colour to map them to. */
body {
    /* The old teal was the brand accent; the current design's equivalent is ink.
       Headings, checked pills and links all land on it. */
    --es-teal: var(--gcp-ink, #101011);
    --es-teal-dark: #2a2a2c;                 /* matches the Add to Basket hover */
    /* Was mint, and used only for focus rings. Kept as the same teal the gift
       card panel already draws its focus rings in, so the two match. */
    --es-mint: #00514b;
    --es-ink: var(--gcp-ink, #101011);
    --es-muted: var(--gcp-ink-soft, #8d8b8b);
    /* NOT --gcp-line. That is #8d8b8b drawn at 0.5px; at the 1px borders this
       file uses it reads far too heavy. #d6d6d6 is the 1px neutral the value
       control already uses for its option dividers. */
    --es-line: #d6d6d6;
    --es-surface: var(--gcp-surface, #ffffff);
    --es-surface-alt: var(--gcp-control-bg, #f5f5f5);
    --es-danger: #b3261e;
    --es-danger-bg: #fdecea;
    --es-radius: var(--gcp-radius, 8px);
}

/* The business section had no font-family of its own, so it inherited OceanWP's
   customizer face while the panel around it rendered in Geist.

   Listed individually because the spreadsheet modal and the date picker are both
   moved to be direct children of <body> at runtime, so no single wrapper contains
   all of these. The ids are the ones the PHP actually emits — the modal is
   `#ecoswap-bulk-modal`, and an earlier version of this rule guessed
   `#ecoswap-bulk-grid-modal`, which matches nothing and silently left the whole
   spreadsheet view in the wrong face. */
#ecoswap-delivery-choice-div,
#ecoswap-bulk-div,
#ecoswap-bulk-modal,
#ecoswap-bulk-preview-wrap,
#ecoswap-bulk-datepicker {
    font-family: var(--gcp-font, 'Geist', system-ui, sans-serif);
}


/* Hidden until the buyer type toggle selects Business. */
#ecoswap-delivery-choice-div,
#ecoswap-bulk-div {
    display: none;
}

#ecoswap-bulk-div {
    margin-bottom: 24px;
}

.ecoswap-bulk-section-head {
    margin-bottom: 12px;
}

.ecoswap-bulk-field-title {
    margin: 0 0 2px 0 !important;
    font-weight: 700;
    font-size: 16px;
    color: var(--es-teal);
}

.ecoswap-bulk-hint {
    margin: 0;
    font-size: 13px;
    line-height: 1.5;
    color: var(--es-muted);
}

/* Separates a second hint from the one above it, since the base rule
   zeroes all margins. */
.ecoswap-bulk-hint-tip {
    margin-top: 4px;
}


/* ------------------------------------------------------------------
   Send to me / send direct
   ------------------------------------------------------------------ */

#ecoswap-delivery-choice-div {
    margin-bottom: 20px;
}

/* THE PILL ITSELF IS STYLED IN giftCardProduct.css, NOT HERE.
   It shares one rule set with Now/Later and Personal/Business — see the
   "Segmented toggles" block there. The copy that used to live here painted it in
   the old teal and mint, which is exactly why it stopped matching the other two.
   Deleting it rather than re-colouring it leaves the control with one owner.

   What stays here is only what is specific to THIS instance: its outer spacing,
   and hiding the radios. The other two toggles get their radios hidden by
   ecoswapGiftCard.css; this one has no equivalent, so it keeps its own. */
.ecoswap-delivery-choice-inner {
    margin: 8px 0 10px;
}

.ecoswap-delivery-choice-inner input[type="radio"] {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
}

.ecoswap-delivery-choice-label {
    cursor: pointer;
}

#ecoswap-buyer-email-div {
    margin-top: 8px;
}

/* Only while "Send to me" is chosen (ecoswap_bulk_recipients.js). */
#ecoswap-buyer-email-div[hidden] {
    display: none;
}

#ecoswap-buyer-email-div input {
    width: 100%;
    max-width: 340px;
    border-radius: 10px;
}


/* ------------------------------------------------------------------
   Recipient cards
   ------------------------------------------------------------------ */

.ecoswap-bulk-card {
    position: relative;
    background-color: var(--es-surface);
    border: 1px solid var(--es-line);
    border-radius: var(--es-radius);
    padding: 14px 16px 16px;
    margin-bottom: 12px;
    transition: border-color .15s ease, box-shadow .15s ease;
}

.ecoswap-bulk-card:hover {
    border-color: var(--gcp-ink-soft);
    box-shadow: 0 2px 10px rgba(16, 16, 17, .06);
}

.ecoswap-bulk-card:focus-within {
    border-color: var(--es-teal);
    box-shadow: 0 0 0 3px rgba(16, 16, 17, .10);
}

.ecoswap-bulk-card-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 12px;
}

.ecoswap-bulk-card-index {
    font-size: 12px;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--es-muted);
}

/* Every <button> on this screen is written with a DOUBLED class (0,2,0) and
   its states restated at 0,3,0. OceanWP's customizer (`body button`, 0,1,1)
   and Elementor's Site Settings -> Buttons (`.elementor-kit-N button`, 0,1,1;
   `button:hover` / `button:focus`, 0,2,1, loading after this sheet) both paint
   every <button> on the site, and a single class loses to either. */
.ecoswap-bulk-remove-row.ecoswap-bulk-remove-row {
    min-height: 0;
    margin: 0;
    padding: 2px 4px;
    border: none;
    border-radius: 0;
    font-family: inherit;
    font-size: 13px;
    font-weight: inherit;
    letter-spacing: inherit;
    text-transform: none;
    text-shadow: none;
    cursor: pointer;
    text-decoration: underline;
}

.ecoswap-bulk-remove-row.ecoswap-bulk-remove-row,
.ecoswap-bulk-remove-row.ecoswap-bulk-remove-row:focus:not(:hover) {
    background: none;
    box-shadow: none;
    color: var(--es-muted);
}

.ecoswap-bulk-remove-row.ecoswap-bulk-remove-row:hover,
.ecoswap-bulk-remove-row.ecoswap-bulk-remove-row:active {
    background: none;
    box-shadow: none;
    color: var(--es-danger);
}

.ecoswap-bulk-card-grid {
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    gap: 12px;
}

.ecoswap-bulk-field {
    display: flex;
    flex-direction: column;
    margin: 0;
    min-width: 0;
}

.ecoswap-bulk-field.is-email { grid-column: span 3; }
.ecoswap-bulk-field.is-name { grid-column: span 3; }
.ecoswap-bulk-field.is-value { grid-column: span 2; }
.ecoswap-bulk-field.is-from { grid-column: span 2; }
.ecoswap-bulk-field.is-design { grid-column: span 2; }
.ecoswap-bulk-field.is-date { grid-column: span 3; }
.ecoswap-bulk-field.is-message { grid-column: 1 / -1; }

.ecoswap-bulk-field-label {
    margin-bottom: 4px;
    font-size: 12px;
    font-weight: 600;
    color: var(--es-muted);
}

#ecoswap-bulk-div .ecoswap-bulk-field input,
#ecoswap-bulk-div .ecoswap-bulk-field select,
#ecoswap-bulk-div .ecoswap-bulk-field textarea {
    width: 100%;
    margin: 0 !important;
    padding: 9px 11px;
    font-size: 14px;
    color: var(--es-ink);
    background-color: var(--es-surface);
    border: 1px solid var(--es-line);
    border-radius: 10px;
    box-shadow: none;
    transition: border-color .15s ease, box-shadow .15s ease;
}

#ecoswap-bulk-div .ecoswap-bulk-field textarea {
    resize: vertical;
    min-height: 60px;
}

#ecoswap-bulk-div .ecoswap-bulk-field input:focus,
#ecoswap-bulk-div .ecoswap-bulk-field select:focus,
#ecoswap-bulk-div .ecoswap-bulk-field textarea:focus {
    outline: none;
    border-color: var(--es-teal);
    box-shadow: 0 0 0 3px rgba(16, 16, 17, .12);
}

.ecoswap-bulk-field-error {
    min-height: 0;
    font-size: 12px;
    color: var(--es-danger);
}

.ecoswap-bulk-field.has-error .ecoswap-bulk-field-error {
    margin-top: 4px;
}

#ecoswap-bulk-div .ecoswap-bulk-field.has-error input,
#ecoswap-bulk-div .ecoswap-bulk-field.has-error select,
#ecoswap-bulk-div .ecoswap-bulk-field.has-error textarea {
    border-color: var(--es-danger);
    background-color: var(--es-danger-bg);
}


/* Send date trigger — looks like an input, shows either the chosen date or
   "Send Now", and opens the shared popover. */
.ecoswap-bulk-date-trigger.ecoswap-bulk-date-trigger {
    width: 100%;
    min-height: 0;
    margin: 0;
    padding: 9px 11px;
    font-family: inherit;
    font-size: 14px;
    font-weight: 400;
    line-height: inherit;
    letter-spacing: inherit;
    text-transform: none;
    text-shadow: none;
    text-align: left;
    border: 1px solid var(--es-line);
    border-radius: 10px;
    cursor: pointer;
    transition: border-color .15s ease, box-shadow .15s ease;
}

/* Colours for every state at once: the trigger is meant to look like an input,
   so the fill and label never change — only the border and focus ring do. */
.ecoswap-bulk-date-trigger.ecoswap-bulk-date-trigger,
.ecoswap-bulk-date-trigger.ecoswap-bulk-date-trigger:hover,
.ecoswap-bulk-date-trigger.ecoswap-bulk-date-trigger:focus,
.ecoswap-bulk-date-trigger.ecoswap-bulk-date-trigger:active {
    color: var(--es-ink);
    background-color: var(--es-surface);
    background-image: none;
}

.ecoswap-bulk-date-trigger.ecoswap-bulk-date-trigger:hover {
    border-color: var(--gcp-ink-soft);
}

.ecoswap-bulk-date-trigger.ecoswap-bulk-date-trigger:focus {
    outline: none;
    border-color: var(--es-teal);
    box-shadow: 0 0 0 3px rgba(16, 16, 17, .12);
}

/* One more class than the state rules above, so "Send Now" keeps its weight and
   colour under the cursor and while focused. */
.ecoswap-bulk-date-trigger.ecoswap-bulk-date-trigger.is-now,
.ecoswap-bulk-date-trigger.ecoswap-bulk-date-trigger.is-now:hover,
.ecoswap-bulk-date-trigger.ecoswap-bulk-date-trigger.is-now:focus,
.ecoswap-bulk-date-trigger.ecoswap-bulk-date-trigger.is-now:active {
    font-weight: 600;
    color: var(--es-teal);
}


/* ------------------------------------------------------------------
   Collapsed summary (more than cfg.collapseAfter recipients)
   ------------------------------------------------------------------ */

.ecoswap-bulk-collapsed {
    padding: 18px 20px;
    background-color: var(--es-surface-alt);
    border: 1px solid var(--es-line);
    border-radius: var(--es-radius);
}

.ecoswap-bulk-collapsed-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 14px;
    margin-bottom: 12px;
}

.ecoswap-bulk-collapsed-head strong {
    font-size: 18px;
    color: var(--es-teal);
}

.ecoswap-bulk-collapsed-head span {
    font-size: 14px;
    color: var(--es-muted);
}

.ecoswap-bulk-collapsed-head .ecoswap-bulk-collapsed-errors {
    padding: 3px 10px;
    font-size: 12px;
    font-weight: 600;
    color: var(--es-danger);
    background-color: var(--es-danger-bg);
    border-radius: 999px;
}

.ecoswap-bulk-collapsed-list {
    margin: 0 0 16px;
    padding: 0;
    list-style: none;
    font-size: 13px;
    line-height: 1.7;
    color: var(--es-ink);
}

.ecoswap-bulk-collapsed-list li {
    padding-left: 14px;
    border-left: 2px solid var(--es-line);
}

.ecoswap-bulk-collapsed-more {
    color: var(--es-muted);
    font-style: italic;
}

.ecoswap-bulk-collapsed-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

#ecoswap-bulk-collapse {
    margin-top: 2px;
}


/* ------------------------------------------------------------------
   Buttons
   ------------------------------------------------------------------ */

.ecoswap-bulk-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 4px;
}

/* MIGRATED ONTO stylesheets/tokens.css 2026-09-15.
 *
 * Less of a change than it looks: --es-teal was re-pointed at --gcp-ink back on
 * 2026-09-11, so these buttons were ALREADY drawing in #101011. What actually
 * moves is the shape (10px radius -> the system's pill), the weight (600 -> the
 * export's 500) and the hover behaviour.
 *
 * THE SIZES STAY COMPACT. This screen has three size tiers already — the action
 * row, the date picker's 8/12 pair and the mobile flex:1 — and the export's
 * 46px pill would push every row taller and break the spreadsheet toolbar. So
 * the size tokens are overridden locally and only the colour and shape come
 * from the system. No min-height is set, exactly as before: height here comes
 * from padding alone, which is what lets the date picker tier be smaller.
 *
 * THE THREE LEVELS ARE PRESERVED, mapped onto the export's three variants:
 *   primary   -> Button_Black    (ink fill)
 *   secondary -> Button_Grey 200 (grey fill, ink border on hover)
 *   ghost     -> Button_White    plus a resting --es-line border
 *
 * Ghost keeps a border at rest ON PURPOSE. tokens.css documents that the
 * export's White variant has no resting border and is therefore invisible on a
 * white surface — it is drawn on grey and meant for dark sections. This screen
 * is white, so ghost gets the 1px --es-line back or it becomes floating text. */
/* The tokens stay on ONE class so the compact tier further down
   (`.ecoswap-bulk-datepicker-actions .ecoswap-bulk-btn`, 0,2,0) still outranks
   them. The properties are on the doubled class below. */
.ecoswap-bulk-btn {
    --wv-btn-pad-y: 10px;
    --wv-btn-pad-x: 18px;
    --wv-btn-size: 14px;
}

/* Doubled — see the note at .ecoswap-bulk-remove-row. */
.ecoswap-bulk-btn.ecoswap-bulk-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    padding: var(--wv-btn-pad-y) var(--wv-btn-pad-x);
    font-size: var(--wv-btn-size);
    font-weight: var(--wv-btn-weight, 500);
    line-height: 1;
    letter-spacing: var(--wv-btn-tracking, -0.01em);
    border-radius: var(--wv-btn-radius, 9999px);
    border: var(--wv-btn-border-w, 1px) solid transparent;
    min-height: 0;
    margin: 0;
    font-family: var(--wv-btn-font, inherit);
    font-style: normal;
    text-transform: none;
    text-decoration: none;
    text-shadow: none;
    box-shadow: none;
    cursor: pointer;
    transition:
        background-color var(--wv-btn-duration, 150ms) ease,
        color var(--wv-btn-duration, 150ms) ease,
        border-color var(--wv-btn-duration, 150ms) ease;
}

@media (prefers-reduced-motion: reduce) {
    .ecoswap-bulk-btn.ecoswap-bulk-btn {
        transition: none;
    }
}

.ecoswap-bulk-btn.ecoswap-bulk-btn-primary,
.ecoswap-bulk-btn.ecoswap-bulk-btn-primary:focus:not(:hover, :active, [disabled], [aria-disabled="true"]) {
    background-color: var(--wv-ink, #101011);
    color: var(--wv-white, #fff);
    border-color: transparent;
}

/* NOTE: this is the export's inversion, NOT the #2a2a2c lift that Add to Basket
   uses on the same page. The two conventions disagree and the export is the
   newer of the two — worth eyeballing side by side before this ships. */
.ecoswap-bulk-btn.ecoswap-bulk-btn-primary:hover:not(:where([disabled], [aria-disabled="true"])),
.ecoswap-bulk-btn.ecoswap-bulk-btn-primary:active:not(:where([disabled], [aria-disabled="true"])) {
    background-color: transparent;
    color: var(--wv-ink, #101011);
    border-color: var(--wv-ink, #101011);
}

.ecoswap-bulk-btn.ecoswap-bulk-btn-secondary,
.ecoswap-bulk-btn.ecoswap-bulk-btn-secondary:focus:not(:hover, :active, [disabled], [aria-disabled="true"]) {
    background-color: var(--wv-grey-200, #f5f5f5);
    color: var(--wv-ink, #101011);
    border-color: transparent;
}

.ecoswap-bulk-btn.ecoswap-bulk-btn-secondary:hover:not(:where([disabled], [aria-disabled="true"])),
.ecoswap-bulk-btn.ecoswap-bulk-btn-secondary:active:not(:where([disabled], [aria-disabled="true"])) {
    background-color: var(--wv-grey-200, #f5f5f5);
    color: var(--wv-ink, #101011);
    border-color: var(--wv-ink, #101011);
}

.ecoswap-bulk-btn.ecoswap-bulk-btn-ghost,
.ecoswap-bulk-btn.ecoswap-bulk-btn-ghost:focus:not(:hover, :active, [disabled], [aria-disabled="true"]) {
    background-color: var(--wv-white, #ffffff);
    border-color: var(--es-line, #d6d6d6);
    color: var(--wv-ink, #101011);
}

.ecoswap-bulk-btn.ecoswap-bulk-btn-ghost:hover:not(:where([disabled], [aria-disabled="true"])),
.ecoswap-bulk-btn.ecoswap-bulk-btn-ghost:active:not(:where([disabled], [aria-disabled="true"])) {
    background-color: var(--wv-grey-200, #f5f5f5);
    border-color: var(--wv-ink, #101011);
    color: var(--wv-ink, #101011);
}

/* All three, from the export's disabled states. The screen had none at all, and
   the bulk actions do get disabled while a CSV parse is in flight — until now
   that was communicated by the attribute alone, with no visual change. */
.ecoswap-bulk-btn.ecoswap-bulk-btn[disabled],
.ecoswap-bulk-btn.ecoswap-bulk-btn[aria-disabled="true"] {
    background-color: var(--wv-grey-300, #e5e5e5);
    color: var(--wv-grey-400, #c4c4c4);
    border-color: transparent;
    cursor: not-allowed;
}

.ecoswap-bulk-btn.ecoswap-bulk-btn-primary[disabled],
.ecoswap-bulk-btn.ecoswap-bulk-btn-primary[aria-disabled="true"] {
    background-color: var(--wv-grey-500, #8d8b8b);
    color: var(--wv-grey-300, #e5e5e5);
}


/* ------------------------------------------------------------------
   Stats + messages
   ------------------------------------------------------------------ */

#ecoswap-bulk-inline-summary {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 14px;
}

.ecoswap-bulk-stat {
    display: inline-flex;
    align-items: baseline;
    gap: 5px;
    padding: 7px 14px;
    font-size: 13px;
    color: var(--es-teal);
    background-color: var(--es-surface-alt);
    border: 1px solid var(--es-line);
    border-radius: 999px;
}

.ecoswap-bulk-stat strong {
    font-size: 15px;
    font-weight: 700;
}

.ecoswap-bulk-errors {
    margin-top: 12px;
}

.ecoswap-bulk-error-list {
    margin: 0;
    padding: 12px 14px 12px 30px;
    font-size: 13px;
    line-height: 1.6;
    color: var(--es-danger);
    background-color: var(--es-danger-bg);
    border: 1px solid #f3c9c5;
    border-radius: 10px;
}

.ecoswap-bulk-notice {
    padding: 11px 14px;
    margin-bottom: 10px;
    font-size: 13px;
    color: #7a4b00;
    background-color: #fff6e6;
    border: 1px solid #ffd899;
    border-radius: 10px;
}


/* ------------------------------------------------------------------
   Bulk grid modal
   ------------------------------------------------------------------ */

#ecoswap-bulk-modal {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 100000;
    padding: 24px;
    background-color: rgba(16, 16, 17, .55);
    -webkit-backdrop-filter: blur(2px);
    backdrop-filter: blur(2px);
}

#ecoswap-bulk-modal.is-open {
    display: flex;
    align-items: center;
    justify-content: center;
}

body.ecoswap-bulk-modal-open {
    overflow: hidden;
}

.ecoswap-bulk-modal-panel {
    display: flex;
    flex-direction: column;
    width: 100%;
    max-width: 1400px;
    max-height: 100%;
    background-color: var(--es-surface);
    border-radius: 18px;
    box-shadow: 0 24px 60px rgba(0, 0, 0, .3);
    overflow: hidden;
}

.ecoswap-bulk-modal-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 20px;
    padding: 20px 24px;
    border-bottom: 1px solid var(--es-line);
}

.ecoswap-bulk-modal-header h3 {
    margin: 0 0 4px 0;
    font-size: 19px;
    color: var(--es-teal);
}

.ecoswap-bulk-modal-close.ecoswap-bulk-modal-close {
    flex: none;
    width: 34px;
    height: 34px;
    min-height: 0;
    margin: 0;
    padding: 0;
    font-family: inherit;
    font-size: 24px;
    font-weight: 400;
    line-height: 1;
    letter-spacing: normal;
    text-transform: none;
    text-shadow: none;
    border: none;
    border-radius: 50%;
    cursor: pointer;
}

.ecoswap-bulk-modal-close.ecoswap-bulk-modal-close,
.ecoswap-bulk-modal-close.ecoswap-bulk-modal-close:focus:not(:hover) {
    color: var(--es-muted);
    background-color: transparent;
    background-image: none;
    box-shadow: none;
}

.ecoswap-bulk-modal-close.ecoswap-bulk-modal-close:hover,
.ecoswap-bulk-modal-close.ecoswap-bulk-modal-close:active {
    background-color: var(--es-surface-alt);
    background-image: none;
    color: var(--es-ink);
    box-shadow: none;
}

.ecoswap-bulk-modal-body {
    flex: 1;
    padding: 18px 24px;
    overflow: auto;
}

#ecoswap-bulk-grid {
    overflow: auto;
}

.ecoswap-bulk-grid-actions {
    margin-top: 10px;
}


/* Send date picker — our own popover, so the cell can hold "Send Now" and a
   single click always opens something. Above the modal's stacking context. */
#ecoswap-bulk-datepicker {
    display: none;
    position: fixed;
    z-index: 100010;
    min-width: 240px;
    padding: 14px;
    background-color: var(--es-surface);
    border: 1px solid var(--es-line);
    border-radius: 12px;
    box-shadow: 0 12px 32px rgba(0, 0, 0, .22);
}

#ecoswap-bulk-datepicker label {
    display: block;
    margin-bottom: 6px;
    font-size: 12px;
    font-weight: 600;
    color: var(--es-muted);
}

#ecoswap-bulk-datepicker input {
    width: 100%;
    margin: 0 0 12px !important;
    padding: 8px 10px;
    font-size: 14px;
    border: 1px solid var(--es-line);
    border-radius: 8px;
}

.ecoswap-bulk-datepicker-actions {
    display: flex;
    gap: 8px;
}

/* The compact tier. Expressed as token overrides rather than as direct padding
   and font-size so it stays a SIZE change and cannot drift into overriding
   anything else the base rule derives from those tokens. */
.ecoswap-bulk-datepicker-actions .ecoswap-bulk-btn {
    --wv-btn-pad-y: 8px;
    --wv-btn-pad-x: 12px;
    --wv-btn-size: 13px;

    flex: 1;
}

.ecoswap-bulk-modal-footer {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    padding: 14px 24px;
    background-color: var(--es-surface-alt);
    border-top: 1px solid var(--es-line);
}

#ecoswap-bulk-summary {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

.ecoswap-bulk-modal-footer .ecoswap-bulk-stat {
    background-color: var(--es-surface);
}

.ecoswap-bulk-footer-actions {
    display: flex;
    align-items: center;
    gap: 16px;
}

#ecoswap-bulk-errors-only-label {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin: 0;
    font-size: 13px;
    color: var(--es-muted);
    cursor: pointer;
}

#ecoswap-bulk-errors-only-label input {
    margin: 0;
}

.ecoswap-bulk-no-errors {
    color: #0a7a53;
    border-color: #b7ecd6;
}

.ecoswap-bulk-has-errors {
    color: var(--es-danger);
    background-color: var(--es-danger-bg);
    border-color: #f3c9c5;
    font-weight: 600;
}


/* Jspreadsheet, toned down to match the rest of the page. v5 uses jss_*
   class names — the v4 .jexcel selectors no longer match anything. */
#ecoswap-bulk-grid .jss_container {
    max-width: 100%;
}

#ecoswap-bulk-grid .jss_worksheet > thead > tr > td {
    background-color: var(--es-surface-alt);
    color: var(--es-teal);
    font-weight: 700;
    font-size: 12px;
    letter-spacing: .03em;
    border-color: var(--es-line);
    padding: 8px 6px;
}

/* "(Optional)" gets a line of its own under the column name, and italics so it
   reads as an aside rather than part of the label. Split out of the title by
   splitOptionalHeaders() in the bulk JS — jspreadsheet writes headers with
   textContent, so this cannot come from the columns config.

   The header row has no fixed height, so it simply grows to two lines; the
   vendor's `overflow: hidden` on the cell has nothing to clip. Weight and
   letter-spacing are reset because the header rule above sets both, and the
   aside should not inherit the label's emphasis. */
#ecoswap-bulk-grid .ecoswap-bulk-col-optional {
    display: block;
    font-style: italic;
    font-weight: 400;
    letter-spacing: 0;
    color: var(--es-muted);
}

#ecoswap-bulk-grid .jss_worksheet > tbody > tr > td {
    font-size: 13px;
    color: var(--es-ink);
    border-color: var(--es-line);
    padding: 7px 8px;
}

/* Applied as a class rather than via setStyle, which can't clear itself. */
#ecoswap-bulk-grid .jss_worksheet > tbody > tr > td.ecoswap-bulk-cell-error {
    background-color: #ffe1e1;
    color: var(--es-danger);
}


/* ------------------------------------------------------------------
   Email preview
   ------------------------------------------------------------------ */

#ecoswap-bulk-preview-wrap {
    display: none;
    margin-bottom: 20px;
}

/* Sits between the preview modal's head and its scrolling body (a flex
   column), so it must not grow or shrink with the email beneath it. */
#ecoswap-bulk-preview-nav {
    flex: 0 0 auto;
    padding: 10px 18px;
    border-bottom: 1px solid #e6e6e6;
    background: #ffffff;
    text-align: center;
}

.ecoswap-bulk-preview-controls {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 14px;
}

.ecoswap-bulk-preview-arrow.ecoswap-bulk-preview-arrow {
    /* Flex-centres the SVG chevron. padding: 0 because the theme's default
       button padding would otherwise push it off-centre inside the 34px. */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    width: 34px;
    height: 34px;
    padding: 0;
    line-height: 0;
    color: var(--es-teal);
    background-color: var(--es-surface-alt);
    border: 1px solid var(--es-line);
    border-radius: 50%;
    min-height: 0;
    margin: 0;
    box-shadow: none;
    cursor: pointer;
    transition: background-color .15s ease, color .15s ease;
}

.ecoswap-bulk-preview-arrow.ecoswap-bulk-preview-arrow:focus:not(:hover, :active),
.ecoswap-bulk-preview-arrow.ecoswap-bulk-preview-arrow:disabled:hover,
.ecoswap-bulk-preview-arrow.ecoswap-bulk-preview-arrow:disabled:active {
    color: var(--es-teal);
    background-color: var(--es-surface-alt);
    border-color: var(--es-line);
    box-shadow: none;
}

.ecoswap-bulk-preview-arrow.ecoswap-bulk-preview-arrow:hover:not(:disabled),
.ecoswap-bulk-preview-arrow.ecoswap-bulk-preview-arrow:active:not(:disabled) {
    background-color: var(--es-teal);
    border-color: var(--es-line);
    color: #fff;
    box-shadow: none;
}

.ecoswap-bulk-preview-arrow.ecoswap-bulk-preview-arrow:disabled {
    opacity: .35;
    cursor: default;
}

#ecoswap-bulk-preview-counter {
    min-width: 70px;
    font-size: 13px;
    font-weight: 600;
    color: var(--es-muted);
}

#ecoswap-bulk-preview-note {
    display: none;
    margin: 10px 0 0;
    font-size: 12px;
    font-style: italic;
    color: var(--es-muted);
}


/* ------------------------------------------------------------------
   Mobile
   ------------------------------------------------------------------ */

#ecoswap-bulk-mobile-notice {
    display: none;
    padding: 12px 14px;
    margin-top: 12px;
    font-size: 13px;
    line-height: 1.5;
    color: var(--es-muted);
    background-color: var(--es-surface-alt);
    border: 1px dashed var(--es-line);
    border-radius: 10px;
}

@media (max-width: 700px) {
    .ecoswap-bulk-card-grid {
        grid-template-columns: 1fr;
    }

    .ecoswap-bulk-field.is-email,
    .ecoswap-bulk-field.is-name,
    .ecoswap-bulk-field.is-value,
    .ecoswap-bulk-field.is-from,
    .ecoswap-bulk-field.is-design,
    .ecoswap-bulk-field.is-date {
        grid-column: 1 / -1;
    }

    .ecoswap-bulk-actions .ecoswap-bulk-btn {
        flex: 1;
    }
}


/* ------------------------------------------------------------------
   Business-only invoice additions
   ------------------------------------------------------------------ */

#ecoswap-invoice-company-div,
#ecoswap-invoice-po-div {
    margin-top: 10px;
}

#ecoswap-invoice-company-div input,
#ecoswap-invoice-po-div input {
    width: 100%;
    max-width: 340px;
    border-radius: 10px;
}

.ecoswap-invoice-note {
    margin: 10px 0 0;
    font-size: 13px;
    line-height: 1.5;
    color: var(--es-muted);
}

.ecoswap-invoice-note a {
    color: var(--es-teal);
    text-decoration: underline;
}


/* ------------------------------------------------------------------
   Design picker — card artwork rather than a name
   ------------------------------------------------------------------ */

/* The real <select> still holds the value and is still what everything reads;
   it is hidden rather than removed. Not `display: none` on a whim — it must stay
   focusable-adjacent and, more importantly, keep working if the tiles fail to
   render for any reason. */
.ecoswap-bulk-design-native {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

/* The closed control. Deliberately the same height and border treatment as the
   text inputs beside it, so the row reads as one set of fields. */
.ecoswap-bulk-design {
    position: relative;
}

.ecoswap-bulk-design-trigger.ecoswap-bulk-design-trigger {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    min-height: 0;
    margin: 0;
    padding: 6px 11px;
    border: 1px solid var(--es-line);
    border-radius: 10px;
    font-family: inherit;
    font-size: inherit;
    font-weight: inherit;
    line-height: inherit;
    letter-spacing: inherit;
    text-transform: none;
    text-shadow: none;
    cursor: pointer;
    text-align: left;
}

.ecoswap-bulk-design-trigger.ecoswap-bulk-design-trigger,
.ecoswap-bulk-design-trigger.ecoswap-bulk-design-trigger:hover,
.ecoswap-bulk-design-trigger.ecoswap-bulk-design-trigger:focus,
.ecoswap-bulk-design-trigger.ecoswap-bulk-design-trigger:active {
    background-color: var(--es-surface);
    background-image: none;
    border-color: var(--es-line);
    color: var(--es-ink);
    box-shadow: none;
}

.ecoswap-bulk-design-trigger:focus-visible {
    outline: 2px solid var(--es-mint);
    outline-offset: 2px;
}

.ecoswap-bulk-design-caret {
    flex: none;
    margin-left: auto;
    width: 0;
    height: 0;
    border-left: 5px solid transparent;
    border-right: 5px solid transparent;
    border-top: 5px solid var(--es-muted);
}

/* Open state is a CLASS, not [hidden]: the UA stylesheet's [hidden] rule loses
   to any author `display`, so a menu declared display:flex would stay on screen
   with the attribute set. */
.ecoswap-bulk-design-menu {
    display: none;
    position: absolute;
    z-index: 20;
    top: calc(100% + 4px);

    /* ── SIZED TO ITS CONTENTS, NOT TO THE TRIGGER ──────────────────────────
       The design field is two of the card's six columns — inside the 440px
       panel that works out at about 100px, of which the 46px thumbnail and the
       caret take most — so a menu matched to the trigger showed a thumbnail and
       two ellipsised characters of every name. A popover is not obliged to
       match the width of the control it hangs off.

       `width: max-content` sizes it to the longest design label, which is
       registry-driven free text and can be anything. `min-width: 100%` keeps it
       from ever being NARROWER than the trigger — and because min-width always
       beats max-width, the full-width field at the 700px breakpoint still gets
       a full-width menu rather than one clipped to the cap. The cap itself
       stops one long label dragging the menu off the card, and the 100vw term
       stops it running off the left of a narrow viewport.

       RIGHT-ANCHORED, and that is load-bearing: `is-design` spans the last two
       of the six columns, so the field sits flush with the card's right edge
       and the menu has to grow LEFTWARDS. Anchored left it would overhang the
       card, the panel and then the page.

       Note a scrollbar appears here once there are more than ~6 designs, and
       max-content sizing does not reserve room for it — on a platform with
       classic (space-taking) scrollbars the longest label loses ~15px to
       ellipsis. Left alone deliberately: the alternative is a nested scroll
       container, which is real structure for one truncated name. */
    right: 0;
    left: auto;
    width: max-content;
    min-width: 100%;
    max-width: min(320px, calc(100vw - 32px));

    max-height: 260px;
    overflow-y: auto;
    padding: 4px;
    background-color: var(--es-surface);
    border: 1px solid var(--es-line);
    border-radius: var(--es-radius);
    box-shadow: 0 6px 20px rgba(16, 16, 17, .12);
}

.ecoswap-bulk-design.is-open .ecoswap-bulk-design-menu {
    display: block;
}

.ecoswap-bulk-design-option.ecoswap-bulk-design-option {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    min-height: 0;
    margin: 0;
    padding: 5px 6px;
    border: 0;
    border-radius: 8px;
    font-family: inherit;
    font-size: inherit;
    font-weight: inherit;
    line-height: inherit;
    letter-spacing: inherit;
    text-transform: none;
    text-shadow: none;
    cursor: pointer;
    text-align: left;
}

.ecoswap-bulk-design-option.ecoswap-bulk-design-option,
.ecoswap-bulk-design-option.ecoswap-bulk-design-option:focus:not(:hover) {
    background: none;
    color: var(--es-ink);
    box-shadow: none;
}

/* .is-selected is one class more than the focus rule above, so the selected
   row keeps its fill while focused. */
.ecoswap-bulk-design-option.ecoswap-bulk-design-option:hover,
.ecoswap-bulk-design-option.ecoswap-bulk-design-option:active,
.ecoswap-bulk-design-option.ecoswap-bulk-design-option.is-selected,
.ecoswap-bulk-design-option.ecoswap-bulk-design-option.is-selected:focus {
    background: var(--es-surface-alt);
    color: var(--es-ink);
    box-shadow: none;
}

.ecoswap-bulk-design-option:focus-visible {
    outline: 2px solid var(--es-mint);
    outline-offset: -2px;
}

/* The gift card's own proportions, so the artwork is recognisable rather than
   squashed into a square. Matches --gcp-card-aspect. */
.ecoswap-bulk-design-img {
    flex: none;
    display: block;
    width: 46px;
    aspect-ratio: 1.595;
    object-fit: cover;
    border-radius: 3px;
    background-color: var(--es-surface-alt);
}

/* The fallback chip when a design has no artwork: same box, flat colour. */
.ecoswap-bulk-design-img.is-flat {
    border: 1px solid var(--es-line);
}

.ecoswap-bulk-design-name {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 13px;
    line-height: 1.3;
    color: var(--es-ink);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ecoswap-bulk-design-option.is-selected .ecoswap-bulk-design-name {
    font-weight: 600;
}

/* ── The spreadsheet's own dropdown ──────────────────────────────────────────
   jSuites renders an item's image into .jdropdown-image when the source is
   objects rather than strings. Sized here to the card's proportions; the library
   only ships a square default. */
.jdropdown-image {
    width: 46px;
    height: 29px;
    object-fit: cover;
    border-radius: 3px;
}

/* The grid cell: thumbnail in front of the label the cell already shows. */
td.ecoswap-bulk-design-cell {
    display: flex;
    align-items: center;
    gap: 6px;
}

td.ecoswap-bulk-design-cell .ecoswap-bulk-design-img {
    flex: none;
    width: 38px;
}
