/* ============================================================
   PRODUCT DETAIL — the `cd-*` system
   ------------------------------------------------------------
   Lifted verbatim out of the inline <style> block in
   Areas/Customer/Views/Home/Details.cshtml so the full page and
   the popup on Products / USA Drops render from ONE source.

   That was the whole point of the exercise: the popup had to
   look like the prod detail view, and the only way to guarantee
   that permanently is for both to read the same rules. A copy
   would have matched on the day it was written and drifted by
   the next change.

   Everything above the MODAL LAYER divider is unchanged from
   the page (the `@@media` escapes became plain `@media` on the
   way out of Razor — that escaping only exists inside .cshtml).
   ============================================================ */

:root {
    --cd-page-bg: #f6f7f9; /* page wash — cool light gray */
    --cd-panel: #ffffff; /* card surfaces — pure white */
    --cd-soft: #f8f9fa; /* image well + input bg */
    --cd-border: #e5e7eb; /* hairlines — neutral gray */
    --cd-text-1: #111827; /* near-black headlines */
    --cd-text-2: #4b5563; /* body */
    --cd-text-3: #9ca3af; /* muted labels */
    --cd-blue: #1a3a5c; /* primary blue */
    --cd-blue-dark: #15314d;
    --cd-gold: #a07820; /* gold kickers — accent only */
    --cd-amber: #b87010;
    --cd-green: #1a7a50;
    /* --cd-cream was used by .cd-hero__category but never defined, so the
       pill fell back to transparent. Defined here rather than left broken. */
    --cd-cream: #fdfaf3;
    --cd-radius: 10px;
    --cd-radius-lg: 14px;
    --cd-shadow-sm: 0 1px 2px rgba(17, 24, 39, 0.04);
    --cd-shadow-md: 0 4px 12px rgba(17, 24, 39, 0.06);
}

.cd-page {
    background: var(--cd-page-bg);
    padding: 1.5rem 1rem 3rem;
    font-family: 'DM Sans', -apple-system, BlinkMacSystemFont, sans-serif;
    color: var(--cd-text-1);
}

.cd-shell {
    max-width: 1100px;
    margin: 0 auto;
}

.cd-back {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    background: var(--cd-panel);
    border: 1px solid var(--cd-border);
    color: var(--cd-text-2);
    padding: 0.5rem 1rem;
    border-radius: var(--cd-radius);
    text-decoration: none;
    font-size: 0.85rem;
    font-weight: 500;
    margin-bottom: 1.25rem;
    transition: all 0.15s;
}

    .cd-back:hover {
        background: var(--cd-soft);
        color: var(--cd-blue);
        border-color: var(--cd-blue);
        text-decoration: none;
    }

.cd-card {
    background: var(--cd-panel);
    border: 1px solid var(--cd-border);
    border-radius: var(--cd-radius-lg);
    box-shadow: var(--cd-shadow-sm);
    margin-bottom: 1.5rem;
    overflow: hidden;
}

.cd-kicker {
    font-family: 'JetBrains Mono', monospace;
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    color: var(--cd-gold);
    text-transform: uppercase;
}

/* ── HERO ──────────────────────────────────────────────── */
.cd-hero {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0;
}

@media (max-width: 768px) {
    .cd-hero {
        grid-template-columns: 1fr;
    }
}

.cd-hero__image-wrap {
    background: var(--cd-panel);
    border-right: 1px solid var(--cd-border);
    position: relative;
    overflow: hidden;
}

@media (max-width: 768px) {
    .cd-hero__image-wrap {
        border-right: none;
        border-bottom: 1px solid var(--cd-border);
    }
}

.cd-hero__image-wrap > .carousel,
.cd-hero__image-wrap > img {
    width: 100%;
    height: 100%;
    min-height: 420px;
}

@media (max-width: 768px) {
    .cd-hero__image-wrap > .carousel,
    .cd-hero__image-wrap > img {
        min-height: 320px;
    }
}

.cd-hero__image-wrap > img {
    object-fit: contain;
    padding: 2rem;
    display: block;
}

.cd-hero__image-wrap .carousel-inner,
.cd-hero__image-wrap .carousel-item {
    width: 100%;
    height: 100%;
}

.cd-hero__image-wrap .carousel-item {
    display: none;
    padding: 2rem;
}

    .cd-hero__image-wrap .carousel-item.active {
        display: flex;
        align-items: center;
        justify-content: center;
    }

    .cd-hero__image-wrap .carousel-item img {
        max-width: 100%;
        max-height: 360px;
        object-fit: contain;
        display: block;
        margin: 0 auto;
    }

.cd-hero__image-wrap .carousel-control-prev-icon,
.cd-hero__image-wrap .carousel-control-next-icon {
    background-color: rgba(28, 26, 23, 0.5);
    border-radius: 50%;
    padding: 1.25rem;
    background-size: 50%;
    background-position: center;
    background-repeat: no-repeat;
}

.cd-hero__image-wrap .carousel-indicators [data-bs-target] {
    background-color: var(--cd-text-3);
    opacity: 0.5;
}

.cd-hero__image-wrap .carousel-indicators .active {
    background-color: var(--cd-blue);
    opacity: 1;
}

.cd-hero__badge {
    position: absolute;
    top: 1rem;
    left: 1rem;
    z-index: 3;
    font-family: 'JetBrains Mono', monospace;
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    padding: 0.45rem 0.85rem;
    border-radius: 6px;
    box-shadow: var(--cd-shadow-sm);
}

.cd-hero__info {
    padding: 2.5rem;
    display: flex;
    flex-direction: column;
}

@media (max-width: 768px) {
    .cd-hero__info {
        padding: 1.75rem;
    }
}

.cd-hero__brand {
    font-family: 'JetBrains Mono', monospace;
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--cd-blue);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    margin-bottom: 0.6rem;
}

.cd-hero__name {
    font-family: 'Playfair Display', Georgia, serif;
    font-size: 2rem;
    font-weight: 700;
    color: var(--cd-text-1);
    margin: 0 0 0.85rem 0;
    line-height: 1.15;
    letter-spacing: -0.015em;
    text-wrap: balance;
}

@media (max-width: 768px) {
    .cd-hero__name {
        font-size: 1.65rem;
    }
}

.cd-hero__category {
    display: inline-block;
    background: var(--cd-cream);
    color: var(--cd-gold);
    font-family: 'JetBrains Mono', monospace;
    font-size: 0.7rem;
    font-weight: 600;
    padding: 0.35rem 0.85rem;
    border-radius: 999px;
    border: 1px solid var(--cd-border);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    margin-bottom: 1.5rem;
    align-self: flex-start;
}

.cd-price {
    margin-bottom: 1.25rem;
}

.cd-price__label {
    font-family: 'JetBrains Mono', monospace;
    font-size: 0.65rem;
    font-weight: 600;
    color: var(--cd-text-3);
    letter-spacing: 0.1em;
    text-transform: uppercase;
    margin-bottom: 0.3rem;
}

.cd-price__value {
    font-size: 1.65rem;
    font-weight: 700;
    color: var(--cd-text-1);
    font-variant-numeric: tabular-nums;
    line-height: 1.2;
}

.cd-price__value--strike {
    text-decoration: line-through;
    color: var(--cd-text-3);
    font-size: 1rem;
    font-weight: 500;
    margin-left: 0.6rem;
}

.cd-price__countdown {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    margin-top: 0.55rem;
    padding: 0.4rem 0.75rem;
    background: #fef9ed;
    border: 1px solid #f3d8a8;
    border-radius: 6px;
    font-family: 'JetBrains Mono', monospace;
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--cd-amber);
    letter-spacing: 0.04em;
}

.cd-description {
    color: var(--cd-text-2);
    font-size: 0.95rem;
    line-height: 1.65;
    margin: 0 0 1.5rem 0;
    padding-bottom: 1.5rem;
    border-bottom: 1px solid var(--cd-border);
}

.cd-controls {
    display: flex;
    gap: 0.85rem;
    flex-wrap: wrap;
    margin-bottom: 1.5rem;
    align-items: flex-end;
}

.cd-control {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}

.cd-control__label {
    font-family: 'JetBrains Mono', monospace;
    font-size: 0.65rem;
    font-weight: 600;
    color: var(--cd-text-3);
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.cd-control input,
.cd-control select {
    background: var(--cd-soft);
    border: 1px solid var(--cd-border);
    border-radius: var(--cd-radius);
    padding: 0.55rem 0.85rem;
    font-family: inherit;
    font-size: 0.95rem;
    color: var(--cd-text-1);
    min-width: 100px;
}

    .cd-control input:focus,
    .cd-control select:focus {
        outline: none;
        border-color: var(--cd-blue);
        box-shadow: 0 0 0 2px rgba(26, 58, 92, 0.1);
    }

.cd-actions {
    display: flex;
    gap: 0.75rem;
    flex-wrap: wrap;
    margin-top: auto;
}

.cd-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 0.85rem 1.4rem;
    border-radius: var(--cd-radius);
    font-size: 0.92rem;
    font-weight: 600;
    text-decoration: none;
    border: 1px solid transparent;
    cursor: pointer;
    font-family: inherit;
    letter-spacing: 0.02em;
    transition: all 0.15s;
    flex: 1 1 auto;
}

.cd-btn--primary {
    background: var(--cd-text-1);
    color: #fff;
    border-color: var(--cd-text-1);
}

    .cd-btn--primary:hover {
        background: var(--cd-blue);
        color: #fff;
        border-color: var(--cd-blue);
        text-decoration: none;
        transform: translateY(-1px);
        box-shadow: var(--cd-shadow-md);
    }

.cd-btn--secondary {
    background: var(--cd-panel);
    color: var(--cd-blue);
    border-color: var(--cd-blue);
}

    .cd-btn--secondary:hover {
        background: var(--cd-blue);
        color: #fff;
        border-color: var(--cd-blue);
        text-decoration: none;
    }

.cd-btn[disabled],
.cd-btn--disabled {
    opacity: 0.5;
    cursor: not-allowed;
    pointer-events: none;
}

/* ── QR CARD ───────────────────────────────────────────── */
.cd-qr {
    display: grid;
    grid-template-columns: 160px 1fr;
    gap: 1.5rem;
    padding: 1.5rem;
    align-items: center;
}

@media (max-width: 600px) {
    .cd-qr {
        grid-template-columns: 1fr;
        text-align: center;
    }
}

.cd-qr__image {
    background: var(--cd-soft);
    border: 1px solid var(--cd-border);
    border-radius: var(--cd-radius);
    padding: 0.65rem;
}

    .cd-qr__image img {
        width: 100%;
        height: auto;
        display: block;
    }

@media (max-width: 600px) {
    .cd-qr__image {
        max-width: 180px;
        margin: 0 auto;
    }
}

.cd-qr__copy-kicker {
    font-family: 'JetBrains Mono', monospace;
    font-size: 0.7rem;
    font-weight: 600;
    color: var(--cd-gold);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    margin-bottom: 0.5rem;
}

.cd-qr__copy-title {
    font-family: 'Playfair Display', Georgia, serif;
    font-size: 1.15rem;
    font-weight: 600;
    color: var(--cd-text-1);
    margin: 0 0 0.4rem 0;
}

.cd-qr__copy-body {
    color: var(--cd-text-2);
    font-size: 0.88rem;
    line-height: 1.55;
    margin: 0;
}

/* ── REVIEWS WRAPPER ───────────────────────────────────── */
.cd-reviews {
    padding: 2rem;
}

@media (max-width: 600px) {
    .cd-reviews {
        padding: 1.25rem;
    }
}


/* ════════════════════════════════════════════════════════
   MODAL LAYER — `cdm-*`
   --------------------------------------------------------
   Everything below is new. It is a FRAME only: it positions
   and scrolls the dialog and supplies the close affordance.
   The contents are the same `cd-*` markup the page renders,
   which is why the popup reads as the prod detail view
   rather than as a lookalike.
   ════════════════════════════════════════════════════════ */

.cdm-overlay {
    position: fixed;
    inset: 0;
    z-index: 2400; /* above the checkout drawer (1600) and its scrim */
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 2rem 1rem;
    background: rgba(17, 24, 39, 0.55);
    -webkit-backdrop-filter: blur(3px);
    backdrop-filter: blur(3px);
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.18s ease, visibility 0.18s ease;
}

    .cdm-overlay.is-open {
        opacity: 1;
        visibility: visible;
    }

/* Its own class rather than an inline style: the drawer manages the same
   property, and one of them clearing the other's lock is how you get a
   page that scrolls behind an open overlay. */
body.pd-modal-open {
    overflow: hidden;
}

.cdm-dialog {
    position: relative;
    width: min(100%, 1000px);
    max-height: calc(100vh - 4rem);
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    background: var(--cd-page-bg);
    border-radius: 16px;
    box-shadow: 0 24px 60px rgba(17, 24, 39, 0.28);
    font-family: 'DM Sans', -apple-system, BlinkMacSystemFont, sans-serif;
    color: var(--cd-text-1);
    transform: translateY(12px) scale(0.985);
    transition: transform 0.2s cubic-bezier(0.22, 1, 0.36, 1);
}

/*  🔴 `none`, NOT `translateY(0) scale(1)` — AND THE DIFFERENCE IS NOT COSMETIC.
    An identity transform is still a transform, and a transformed element becomes
    the CONTAINING BLOCK for every `position: fixed` descendant. So anything
    inside the panel that expects to cover the SCREEN gets trapped inside this
    dialog instead: clipped at its edges and scrolling with it.

    That is not hypothetical. Beauty Aura's video viewer is
    `.sf-vw { position: fixed; inset: 0 }`, and Beauty Aura now opens as a panel
    — tapping a video would have opened the viewer inside a 940px box. It is the
    same trap CD-136 already caught twice with the mobile bottom bar and a
    filtered navbar ancestor.

    Transitions treat `none` as the identity matrix, so the open animation still
    runs exactly as before; the containing block simply stops existing once the
    dialog is at rest, which is the only time a viewer is ever opened from it. */
.cdm-overlay.is-open .cdm-dialog {
    transform: none;
}

/* The dialog owns the card's outer margin, so the last card inside
   must not add another one — otherwise the popup ends in dead space. */
.cdm-dialog .cd-card {
    margin: 0;
    border-radius: 0;
    border-left: 0;
    border-right: 0;
    border-top: 0;
    box-shadow: none;
}

.cdm-dialog .cd-card:first-of-type {
    border-top-left-radius: 16px;
    border-top-right-radius: 16px;
}

.cdm-dialog .cd-card:last-child {
    border-bottom: 0;
    border-bottom-left-radius: 16px;
    border-bottom-right-radius: 16px;
}

/* The page gives the hero a 420px image well. In a dialog that is
   capped by viewport height, so it comes down a little. */
.cdm-dialog .cd-hero__image-wrap > .carousel,
.cdm-dialog .cd-hero__image-wrap > img {
    min-height: 380px;
}

.cdm-dialog .cd-hero__info {
    padding: 2.25rem 2.25rem 2rem;
}

/* The ingredients-only popup carries one card, not a hero — 1000px would
   leave the INCI list stranded in whitespace. */
.cdm-dialog--narrow {
    width: min(100%, 620px);
}

/*  Panel popups (orders, metrics) carry drawer-width content — the
    sf-dw-* bodies are authored for a 420px column, so a 1000px dialog
    strands them in whitespace. */
.cdm-dialog--panel {
    width: min(100%, 560px);
    background: #faf5ef;
    /*  Nothing inside may push the dialog sideways. The order-details body is
        authored for a full page; dropped into a narrow dialog its widest child
        produced a horizontal scrollbar under the content — a popup you have to
        scroll sideways to read reads as broken, not as dense. */
    overflow-x: hidden;
}

.cdm-dialog--panel .sf-dw-body,
.cdm-dialog--panel .sf-dw-foot {
    padding: 16px;
}

/*  PAGE-AUTHORED CONTENT NEEDS PAGE WIDTH.
    /mall/mis-pedidos is written for the 420px drawer and looks right at 560.
    /Customer/Order/Details is a full page — its header, status tiles and
    line-item table assume room, and at 560 the balance card collapsed into a
    six-word-per-line column. The trigger says which it is via
    data-panel-size="wide"; the default stays narrow. */
.cdm-dialog--wide {
    width: min(100%, 940px);
}

/* ══════════════════════════════════════════════════════════════════
   .pnl-view — A FULL-PAGE VIEW, RENDERED INSIDE A DIALOG.

   The wrapper _PanelLayout puts around a control-panel view. It exists so the
   corrections a popup needs live HERE and never in the view's own stylesheet:
   each of these views still has to render correctly as a page, and editing its
   CSS to suit the dialog would quietly break the page to fix the popup.

   Kept to what is structurally necessary. A page view opens with a Bootstrap
   container whose gutter assumes a viewport edge; inside the dialog that gutter
   lands on top of the dialog's own padding and the content sits in a trench.

   The rules below the container reset were added after seeing all ten panels
   open side by side. Each one fixes something that was visibly wrong, and each
   is here rather than in a view's own stylesheet because every one of these
   views still has to render correctly as a full page. */
.pnl-view > .container,
.pnl-view > .container-fluid {
    padding-left: 0;
    padding-right: 0;
    max-width: none;
}

/*  1 — THE SHEET NEEDS A MARGIN.

    With none, every view's outermost card ran hard into the dialog on all four
    sides: dark headers bled past the rounded corners, cards lost their radius
    and shadow entirely, and the whole thing read as a page that had been cut
    out with scissors rather than a panel. 20px is enough for a card's shadow
    to resolve against white.

    Top is smaller because the close control above it already supplies the
    upper margin — see 4. */
.pnl-view {
    padding: 4px 20px 24px;
}

/*  2 — A TOP-LEVEL ROW'S NEGATIVE GUTTER WOULD EAT THAT MARGIN.

    Bootstrap pulls .row 12px wider than its parent on each side and gives the
    gutter back as column padding. Against a viewport edge that is invisible;
    against the margin just added it cancels it, and on the profile — whose
    header is a flex row with a button stack on the right — it pushed the
    buttons past the card, where .profile-card's own overflow:hidden CLIPPED
    THEM MID-WORD. "EDITAR PE", "MI CÓDIGO", "SEGURIDAD DE L".

    Only the outermost row. Nested ones are laying out fields inside a card and
    their gutters are doing exactly what they should. */
.pnl-view > .row,
.pnl-view > .container > .row,
.pnl-view > .container-fluid > .row {
    margin-left: 0;
    margin-right: 0;
}

/*  3 — THE PAGE'S OWN WIDTH CAP IS THE DIALOG'S JOB NOW.

    A view that centres itself in a browser window (row.justify-content-center
    → col-lg-8 col-xl-7) was doing it twice: the dialog centres it, and then the
    column narrowed it to ~58% of the dialog. On the profile that left roughly
    540px for a header built to hold an avatar, a name block AND three action
    buttons — which is the other half of why they were clipped.

    But NOT released to the full dialog either. That fraction was a deliberate
    choice — these two views are a profile card and an application form, and
    both read better in a column than stretched across 900px. Acceso Profesional
    already proved it: at col-xl-8 of the dialog it was the one panel that
    needed nothing. So the intent is kept and the number is re-picked for this
    frame: a reading column wide enough to hold the profile header, centred.

    :only-child is the test on purpose. It says "this row exists to centre one
    column", which is exactly the pattern being corrected. A row with siblings
    is a real grid and is left alone. */
.pnl-view > .row > [class*="col-"]:only-child,
.pnl-view > .container > .row > [class*="col-"]:only-child,
.pnl-view > .container-fluid > .row > [class*="col-"]:only-child {
    flex: 0 0 100%;
    max-width: 820px;
    margin-inline: auto;
}

/*  4 — THE OUTERMOST TWO-COLUMN SPLIT BECOMES ONE COLUMN.

    🔴 THE REASON THE PAGE DOES NOT FIX THIS ITSELF. Bootstrap's col-lg and
    col-xl rules collapse on @media (max-width: …), and a media query measures
    the VIEWPORT, never this dialog.
    On a desktop browser it is 1920px wide no matter how narrow this dialog is,
    so "form beside a help panel" stayed side by side inside 940px and gave the
    help panel 313px. Contactar Soporte and Recomendar un Producto both rendered
    their tips column as a squeezed strip pinned to the dialog's top-right
    corner, under the close button; Panel de Salud squeezed a four-column table
    into the same strip and grew a horizontal scrollbar inside it.

    Stacking is not a compromise — it is what these pages already do on a narrow
    window. This just triggers it on the dialog's width instead of the screen's.

    :first-child:nth-last-child(2) selects a column that is one of EXACTLY TWO,
    and the sibling combinator takes the other. That precision matters: Panel de
    Salud's KPI strip is four col-lg-3 tiles in a top-level row, and a blunter
    rule would have stacked those into a four-storey tower.

    🔴 AND ONLY col-lg / col-xl SPLITS. A col-md split was authored to survive
    down to 768px, so it already fits this dialog and stacking it would be
    damage, not repair — Seguridad de la cuenta is a col-md-3 nav beside a
    col-md-9 panel, and collapsing that turned a tidy sidebar into a stack of
    full-width bars above the form. col-lg and col-xl splits are the ones that
    need ≥992px and ≥1200px respectively and therefore do NOT fit. */
.pnl-view > .row > [class*="col-lg-"]:first-child:nth-last-child(2),
.pnl-view > .row > [class*="col-lg-"]:first-child:nth-last-child(2) ~ [class*="col-"],
.pnl-view > .row > [class*="col-xl-"]:first-child:nth-last-child(2),
.pnl-view > .row > [class*="col-xl-"]:first-child:nth-last-child(2) ~ [class*="col-"],
.pnl-view > .container > .row > [class*="col-lg-"]:first-child:nth-last-child(2),
.pnl-view > .container > .row > [class*="col-lg-"]:first-child:nth-last-child(2) ~ [class*="col-"],
.pnl-view > .container > .row > [class*="col-xl-"]:first-child:nth-last-child(2),
.pnl-view > .container > .row > [class*="col-xl-"]:first-child:nth-last-child(2) ~ [class*="col-"],
.pnl-view > .container-fluid > .row > [class*="col-lg-"]:first-child:nth-last-child(2),
.pnl-view > .container-fluid > .row > [class*="col-lg-"]:first-child:nth-last-child(2) ~ [class*="col-"],
.pnl-view > .container-fluid > .row > [class*="col-xl-"]:first-child:nth-last-child(2),
.pnl-view > .container-fluid > .row > [class*="col-xl-"]:first-child:nth-last-child(2) ~ [class*="col-"] {
    flex: 0 0 100%;
    max-width: 100%;
}

/*  THE CREAM FRAME IS FOR DRAWER PANELS, NOT FOR PAGE VIEWS.

    .cdm-dialog--panel paints #faf5ef because the panels it was built for
    (_StorefrontOrders, _BalancePanel) are sf-* cream surfaces that match it. A
    control-panel view brings its OWN card — white body, dark gradient header —
    so the cream survives only as a band along the bottom edge where the view's
    content stops short of the dialog. It reads as an unfinished sheet.

    :has() rather than a modifier class on the dialog: _PanelModal sets its
    classes from the LINK that was clicked, and which frame the response used is
    the server's decision, not the link's. Asking what actually arrived is the
    only test that cannot fall out of step. Same feature _MallShell already
    depends on for its FAB rules. */
.cdm-dialog--panel:has(.pnl-view) {
    background: #fff;
}

/*  5 — THE CLOSE CONTROL GETS ITS OWN STRIP, AND STAYS PUT.

    Two faults, one cause: .cdm-close is position:absolute inside a dialog that
    SCROLLS, so it belongs to the top of the content rather than to the frame.

      · It scrolled away. Recomendar un Producto and Contactar Soporte are
        taller than the dialog; a few notches down and there was no way out of
        the popup on screen at all — Escape and the backdrop still worked, but
        nothing said so.

      · It landed on whatever the view happened to put in its top-right corner.
        Panel de Salud's "Próxima · No hay citas próximas", the tips columns,
        the profile's button stack — all of them sat under it.

    Sticky instead, as a real element in the dialog's flow. It is already the
    first child, so it lays out at the top; margin-left:auto pushes it right,
    and the 36px + 14px it occupies IS the reserved strip — no content can be
    beneath it because nothing is laid out there. Then it pins as she scrolls.

    display:flex, not the inherited inline-flex: auto margins only resolve on a
    block-level box.

    Scoped to :has(.pnl-view) so the product-detail popup and the drawer panels
    — which are short, and whose corners are deliberately clear — keep the
    absolute button they were designed around. */
.cdm-dialog--panel:has(.pnl-view) .cdm-close {
    position: sticky;
    top: 14px;
    right: auto;                 /* the base rule's inset is for the absolute box */
    display: flex;
    margin: 14px 14px 0 auto;
}

/*  Belt and braces for injected page markup: anything that declares a fixed
    width wider than the dialog gets clamped rather than overflowing. */
.cdm-dialog--panel img,
.cdm-dialog--panel table,
.cdm-dialog--panel pre {
    max-width: 100%;
}

.cdm-dialog--panel table {
    display: block;
    overflow-x: auto;
}

/*  …but display:block also makes a table shrink to its content, and a page
    view's tables are laid out to fill the card they sit in. Panel de Salud's
    "Ritmo de belleza" ended up as a 280px stub floating in a 900px card.
    Give the block its width back; overflow-x above still catches a table that
    genuinely does not fit. */
.pnl-view table {
    width: 100%;
}

/*  The details page centres itself in a browser window with its own max-width.
    Inside a dialog that leaves the content floating in a channel, so the cap
    is released and the dialog's width governs. Its own side padding STAYS —
    the dialog has none of its own, and stripping it would put the header hard
    against the edge.

    🔴 The page's grids collapse on @media (max-width: …), which measures the
    VIEWPORT, not this dialog. On a desktop browser the two-column layout
    therefore applies no matter how narrow the dialog is — which is why the
    balance card rendered six words per line at 560px. Giving the dialog the
    width the layout was authored for is the fix; forcing a one-column layout
    here would just be a second place to keep in step. */
.cdm-dialog--panel .cpc-shell {
    max-width: none;
    margin: 0;
    padding-bottom: 24px;
}

.cdm-close {
    position: absolute;
    top: 0.85rem;
    right: 0.85rem;
    z-index: 5;
    width: 36px;
    height: 36px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    border: 1px solid var(--cd-border);
    background: rgba(255, 255, 255, 0.92);
    color: var(--cd-text-2);
    font-size: 1.15rem;
    line-height: 1;
    cursor: pointer;
    box-shadow: var(--cd-shadow-sm);
    transition: all 0.15s;
}

    .cdm-close:hover {
        background: var(--cd-text-1);
        border-color: var(--cd-text-1);
        color: #fff;
    }

    .cdm-close:focus-visible {
        outline: 2px solid var(--cd-blue);
        outline-offset: 2px;
    }

/* Loading + error states — the dialog opens immediately and fills in,
   so a slow round trip never looks like a dead click. */
.cdm-state {
    padding: 4rem 2rem;
    text-align: center;
    font-family: 'JetBrains Mono', monospace;
    font-size: 0.78rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--cd-text-3);
    background: var(--cd-panel);
    border-radius: 16px;
}

.cdm-spinner {
    width: 26px;
    height: 26px;
    margin: 0 auto 1rem;
    border: 2px solid var(--cd-border);
    border-top-color: var(--cd-blue);
    border-radius: 50%;
    animation: cdm-spin 0.7s linear infinite;
}

@keyframes cdm-spin {
    to {
        transform: rotate(360deg);
    }
}

/* ── INGREDIENTS ───────────────────────────────────────
   Used by the popup on Products / USA Drops AND by the
   standalone Ingredients popup on the professional
   storefront detail page, which is otherwise untouched. */
.cd-ing {
    padding: 1.75rem 2.25rem 2rem;
}

@media (max-width: 600px) {
    .cd-ing {
        padding: 1.5rem 1.25rem;
    }
}

.cd-ing__title {
    font-family: 'Playfair Display', Georgia, serif;
    font-size: 1.3rem;
    font-weight: 600;
    color: var(--cd-text-1);
    margin: 0 0 0.35rem 0;
}

.cd-ing__sub {
    font-size: 0.85rem;
    color: var(--cd-text-2);
    margin: 0 0 1.25rem 0;
    line-height: 1.55;
}

.cd-ing__flags {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-bottom: 1.25rem;
}

.cd-flag {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.35rem 0.75rem;
    border-radius: 999px;
    font-family: 'JetBrains Mono', monospace;
    font-size: 0.68rem;
    font-weight: 600;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    border: 1px solid transparent;
}

/* Semantic, and deliberately not the accent gold: "free of" is a
   different kind of statement from "contains", and a shopper
   scanning for one should not have to read to tell them apart. */
.cd-flag--yes {
    background: #edf7f1;
    border-color: #bfe0cd;
    color: var(--cd-green);
}

.cd-flag--no {
    background: #fdf1ee;
    border-color: #f3cec3;
    color: #a8442a;
}

.cd-flag--neutral {
    background: var(--cd-soft);
    border-color: var(--cd-border);
    color: var(--cd-text-2);
}

.cd-ing__list {
    background: var(--cd-soft);
    border: 1px solid var(--cd-border);
    border-radius: var(--cd-radius);
    padding: 1rem 1.15rem;
    font-size: 0.85rem;
    line-height: 1.7;
    color: var(--cd-text-2);
    word-break: break-word;
}

.cd-ing__label {
    font-family: 'JetBrains Mono', monospace;
    font-size: 0.65rem;
    font-weight: 600;
    color: var(--cd-text-3);
    letter-spacing: 0.1em;
    text-transform: uppercase;
    margin-bottom: 0.45rem;
}

.cd-ing__meta {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: 1rem 1.5rem;
    margin-top: 1.25rem;
    padding-top: 1.25rem;
    border-top: 1px solid var(--cd-border);
}

.cd-ing__meta dt {
    font-family: 'JetBrains Mono', monospace;
    font-size: 0.62rem;
    font-weight: 600;
    color: var(--cd-text-3);
    letter-spacing: 0.09em;
    text-transform: uppercase;
    margin-bottom: 0.25rem;
}

.cd-ing__meta dd {
    font-size: 0.88rem;
    color: var(--cd-text-1);
    margin: 0;
}

.cd-ing__empty {
    font-size: 0.88rem;
    color: var(--cd-text-3);
    font-style: italic;
}

/* ── INFORMACIÓN PANEL ─────────────────────────────────────
   The Foundry ingredient explanations, swapped into the same
   dialog as the product detail. */

.cd-ing__eyebrow {
    font-family: 'JetBrains Mono', monospace;
    font-size: 0.7rem;
    font-weight: 600;
    color: var(--cd-blue);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    margin-bottom: 0.35rem;
}

.cd-alert {
    display: flex;
    gap: 0.75rem;
    align-items: flex-start;
    padding: 0.9rem 1rem;
    margin-bottom: 1.25rem;
    background: #fef9ed;
    border: 1px solid #f3d8a8;
    border-radius: var(--cd-radius);
}

.cd-alert__icon {
    flex: 0 0 20px;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: var(--cd-amber);
    color: #fff;
    font-weight: 700;
    font-size: 0.8rem;
    line-height: 20px;
    text-align: center;
}

.cd-alert__body {
    font-size: 0.86rem;
    line-height: 1.55;
    color: #7a4c11;
}

.cd-inglist {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    margin-bottom: 1.5rem;
}

.cd-ingcard {
    border: 1px solid var(--cd-border);
    border-radius: var(--cd-radius);
    background: var(--cd-panel);
    overflow: hidden;
}

.cd-ingcard[open] {
    border-color: #d7dce3;
    box-shadow: var(--cd-shadow-sm);
}

.cd-ingcard__hd {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.75rem 0.9rem;
    cursor: pointer;
    list-style: none;
}

.cd-ingcard__hd::-webkit-details-marker {
    display: none;
}

.cd-ingcard__hd:hover {
    background: var(--cd-soft);
}

.cd-ingcard__name {
    flex: 1 1 auto;
    min-width: 0;
}

.cd-ingcard__dn {
    display: block;
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--cd-text-1);
}

.cd-ingcard__inci {
    display: block;
    font-family: 'JetBrains Mono', monospace;
    font-size: 0.68rem;
    color: var(--cd-text-3);
    letter-spacing: 0.03em;
    margin-top: 0.1rem;
}

.cd-ingcard__pills {
    display: flex;
    gap: 0.35rem;
    flex-shrink: 0;
}

.cd-ingcard__chev {
    color: var(--cd-text-3);
    font-size: 1rem;
    transition: transform 0.15s ease;
}

.cd-ingcard[open] .cd-ingcard__chev {
    transform: rotate(180deg);
}

.cd-ingcard__bd {
    padding: 0 0.9rem 0.9rem;
    border-top: 1px solid var(--cd-border);
}

.cd-ingcard__exp {
    font-size: 0.86rem;
    line-height: 1.6;
    color: var(--cd-text-2);
    margin: 0.75rem 0 0;
}

.cd-ingcard__row {
    display: flex;
    gap: 0.6rem;
    margin-top: 0.65rem;
    font-size: 0.82rem;
    line-height: 1.55;
}

.cd-ingcard__rowl {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    flex: 0 0 auto;
    font-family: 'JetBrains Mono', monospace;
    font-size: 0.65rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--cd-text-3);
    padding-top: 0.15rem;
}

.cd-ingcard__rowv {
    color: var(--cd-text-2);
}

/* Harm level. Severity is carried by COLOUR AND WORD, never colour alone —
   the level has to survive a greyscale screenshot and a colour-blind reader,
   because this is the one panel where the reading is a safety judgement. */
.cd-harm {
    display: inline-flex;
    align-items: baseline;
    gap: 0.3rem;
    padding: 0.22rem 0.5rem;
    border-radius: 999px;
    border: 1px solid transparent;
    font-family: 'JetBrains Mono', monospace;
    font-size: 0.6rem;
    font-weight: 600;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    white-space: nowrap;
}

.cd-harm__l {
    opacity: 0.72;
}

.cd-harm--none {
    background: var(--cd-soft);
    border-color: var(--cd-border);
    color: var(--cd-text-3);
}

.cd-harm--low {
    background: #edf7f1;
    border-color: #bfe0cd;
    color: var(--cd-green);
}

.cd-harm--moderate {
    background: #fef9ed;
    border-color: #f3d8a8;
    color: var(--cd-amber);
}

.cd-harm--high {
    background: #fdf1ee;
    border-color: #f3cec3;
    color: #a8442a;
}

.cd-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    display: inline-block;
}

.cd-dot--none {
    background: var(--cd-text-3);
}

.cd-dot--low {
    background: var(--cd-green);
}

.cd-dot--moderate {
    background: var(--cd-amber);
}

.cd-dot--high {
    background: #a8442a;
}

@media (max-width: 560px) {
    .cd-ingcard__hd {
        flex-wrap: wrap;
    }

    .cd-ingcard__pills {
        flex-basis: 100%;
        order: 3;
    }
}

/* Back to the product, from the información panel. */
.cdm-back {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    margin: 1rem 0 0 1.25rem;
    padding: 0.45rem 0.9rem;
    background: var(--cd-panel);
    border: 1px solid var(--cd-border);
    border-radius: var(--cd-radius);
    color: var(--cd-text-2);
    font-family: inherit;
    font-size: 0.82rem;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.15s;
}

    .cdm-back:hover {
        background: var(--cd-soft);
        color: var(--cd-blue);
        border-color: var(--cd-blue);
    }

@media (prefers-reduced-motion: reduce) {
    .cdm-overlay,
    .cdm-dialog,
    .cd-btn,
    .cdm-close {
        transition: none;
    }

    .cdm-spinner {
        animation: none;
    }
}

/* ══════════════════════════════════════════════════════════════════
   USA DROPS — the two-payment promise, stated where she decides.

   The grid card already carries a chip and a ship date (.vf-drop-chip /
   .vf-ship, vf-catalog.css). The DETAIL view carried neither, so every fact
   that makes a preorder different from a shelf product disappeared the moment
   she tapped the card — and the first mention of the 60/40 split was the cart
   drawer, after she had already added it.

   NAVY, NOT GOLD. Navy is what a USA Drop already wears: the tab wordmark, the
   tile chip, the calendar mark. Gold is ValoraFi's own accent and would say
   the wrong thing on an imported line.

   Deliberately quiet — a tinted panel with a hairline, not a warning box. This
   is the shape of the deal, not an alarm.
   ══════════════════════════════════════════════════════════════════ */
.cd-drop {
    margin: -0.4rem 0 1.25rem;
    padding: 0.85rem 1rem;
    border: 1px solid rgba(26, 58, 92, 0.22);
    border-radius: var(--cd-radius);
    background: rgba(26, 58, 92, 0.045);
}

.cd-drop__chip {
    display: inline-block;
    font-family: 'JetBrains Mono', monospace;
    font-size: 0.6rem;
    font-weight: 700;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    padding: 3px 8px;
    border-radius: 5px;
    background: var(--cd-blue);
    color: #fff;
}

.cd-drop__eta {
    margin-top: 0.55rem;
    font-size: 0.85rem;
    color: var(--cd-text-2);
}

.cd-drop__eta b {
    color: var(--cd-text-1);
    font-weight: 700;
}

/* THE SPLIT. Two rows that must visibly add up to the price above them — a
   customer who cannot reconcile her own basket does not press the button. */
.cd-drop__split {
    margin-top: 0.7rem;
    display: flex;
    flex-direction: column;
    gap: 0.32rem;
}

.cd-drop__row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 1rem;
    font-size: 0.85rem;
    color: var(--cd-text-2);
}

.cd-drop__row b {
    font-variant-numeric: tabular-nums;
    color: var(--cd-text-1);
    font-weight: 700;
}

/* The one she pays today reads first. */
.cd-drop__row--now {
    color: var(--cd-text-1);
    font-weight: 600;
}

.cd-drop__note {
    margin: 0.65rem 0 0;
    font-size: 0.78rem;
    line-height: 1.45;
    color: var(--cd-text-3);
}

/* ══════════════════════════════════════════════════════════════════════════
   PANEL BOOTSTRAP FALLBACK — 17 Aug 2026

   🔴 NOT EVERY HOST THAT OPENS A PANEL LOADS bootstrap.css.

   _PanelModal is mounted on five surfaces, and only three of them link
   Bootstrap: _Layout, _MallShell and _ShellLayout do; the PROFESSIONAL
   STOREFRONT and /r/{slug} do not — they load bootstrap-ICONS and the
   bootstrap bundle JS (for the offcanvas) and nothing else, because their own
   design was never built on Bootstrap and importing it would restyle the
   storefront itself.

   The result was visible and reported: the same Mi Código QR panel showed
   proper outlined buttons when opened from the Mall and a bare underlined link
   when opened from /store/{handle}. One control, two appearances, decided by
   which page happened to be underneath — which is the exact thing the shell
   unification exists to stop.

   🔴 :where() IS THE WHOLE TRICK — IT MAKES THESE RULES ZERO-SPECIFICITY.
   :where(.pnl-view .btn) matches with specificity (0,0,0), so ANY other rule
   beats it: Bootstrap's own .btn (0,1,0) where Bootstrap is loaded, and a
   view's own .btn-regenerate (0,1,0) everywhere. These therefore apply ONLY
   when nothing else has spoken — a true fallback, not an override.

   That matters more than tidiness: a normal .pnl-view .btn rule would be
   (0,2,0) and would silently restyle every panel already shipped and verified
   on the Mall. This cannot.

   Scoped to .pnl-view throughout, so the host page is untouchable either way.
   ══════════════════════════════════════════════════════════════════════════ */

:where(.pnl-view .btn) {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .4rem;
    padding: .375rem .75rem;
    border: 1px solid transparent;
    border-radius: .375rem;
    background: transparent;
    font-size: 1rem;
    font-weight: 400;
    line-height: 1.5;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    transition: color .15s, background-color .15s, border-color .15s;
}

:where(.pnl-view .btn-sm) { padding: .25rem .5rem; font-size: .875rem; border-radius: .25rem; }

/* The two outline variants the control-panel views actually use. Values are
   Bootstrap 5's own, so a panel looks the same whichever host it opened on. */
:where(.pnl-view .btn-outline-primary)   { color: #0d6efd; border-color: #0d6efd; }
:where(.pnl-view .btn-outline-primary:hover)   { color: #fff; background-color: #0d6efd; }
:where(.pnl-view .btn-outline-secondary) { color: #6c757d; border-color: #6c757d; }
:where(.pnl-view .btn-outline-secondary:hover) { color: #fff; background-color: #6c757d; }
:where(.pnl-view .btn-outline-danger)    { color: #dc3545; border-color: #dc3545; }
:where(.pnl-view .btn-outline-danger:hover)    { color: #fff; background-color: #dc3545; }
:where(.pnl-view .btn-primary)   { color: #fff; background-color: #0d6efd; border-color: #0d6efd; }
:where(.pnl-view .btn-secondary) { color: #fff; background-color: #6c757d; border-color: #6c757d; }
:where(.pnl-view .btn-warning)   { color: #000; background-color: #ffc107; border-color: #ffc107; }
:where(.pnl-view .btn:disabled), :where(.pnl-view .btn[disabled]) { opacity: .65; cursor: default; }

/* Alerts — every converted view renders its saved/failed message as one, and
   without this an error reads as ordinary body text. */
:where(.pnl-view .alert) {
    position: relative;
    padding: .75rem 1rem;
    margin-bottom: 1rem;
    border: 1px solid transparent;
    border-radius: .375rem;
}
:where(.pnl-view .alert-success) { color: #0f5132; background-color: #d1e7dd; border-color: #badbcc; }
:where(.pnl-view .alert-danger)  { color: #842029; background-color: #f8d7da; border-color: #f5c2c7; }
:where(.pnl-view .alert-warning) { color: #664d03; background-color: #fff3cd; border-color: #ffecb5; }
:where(.pnl-view .alert-info)    { color: #055160; background-color: #cff4fc; border-color: #b6effb; }

/* Form controls — Documentos and Datos de Pago are forms first. An unstyled
   <select> next to a styled <input> is the tell that this file is missing. */
:where(.pnl-view .form-control), :where(.pnl-view .form-select) {
    display: block;
    width: 100%;
    padding: .375rem .75rem;
    border: 1px solid #dee2e6;
    border-radius: .375rem;
    background-color: #fff;
    font-size: 1rem;
    line-height: 1.5;
    color: #212529;
}
:where(.pnl-view .form-control:focus), :where(.pnl-view .form-select:focus) {
    outline: 0;
    border-color: #86b7fe;
    box-shadow: 0 0 0 .25rem rgba(13,110,253,.25);
}
:where(.pnl-view .form-label) { margin-bottom: .5rem; }

:where(.pnl-view .badge) {
    display: inline-block;
    padding: .35em .65em;
    border-radius: .375rem;
    font-size: .75em;
    font-weight: 700;
    line-height: 1;
    text-align: center;
    white-space: nowrap;
}

/* ══════════════════════════════════════════════════════════════════════════
   AURA-VIDEO TILES ON A PROFILE, INSIDE A DIALOG — 18 Aug 2026

   Reported by GT: "the profile view videos are super thin and look distorted
   in the my knowledge section", with Revisar Videos Aura named as the look to
   match.

   🔴 SAME ROOT CAUSE AS THE col-lg NOTE ABOVE: Bootstrap's col-* breakpoints
   measure the VIEWPORT, which is 1920 no matter how narrow the dialog is. So
   col-md-3 stays four-across inside a 940px popup — and on a profile this grid
   sits in the narrower of two columns, leaving each tile around 140px. The
   frames are aspect-ratio 9/16, so 140px wide renders a 249px-tall sliver.
   Nothing is "distorted" in the CSS sense; the box is simply far too narrow
   for a portrait video.

   Two across in the dialog puts a tile at roughly the width Revisar Videos
   Aura gives it on the page, which is the comparison GT drew. Below 700px the
   panel is a phone-width sheet and one across is the honest answer.

   Scoped to .pnl-view, so the FULL PAGE grid is untouched — it was never
   wrong, it just has the whole viewport to lay out in.
   ══════════════════════════════════════════════════════════════════════════ */

.pnl-view .prodet-kn-col {
    flex: 0 0 50%;
    max-width: 50%;
}

@media (max-width: 700px) {
    .pnl-view .prodet-kn-col {
        flex: 0 0 100%;
        max-width: 100%;
    }
}

/* ══════════════════════════════════════════════════════════════════════════
   STAND-IN MODAL — FOR HOSTS THAT DELIBERATELY HAVE NO BOOTSTRAP — 18 Aug 2026

   Partner to window.vfModal in control-panel.js. _MallShell loads Bootstrap
   only behind ShellChrome, so a profile opened from a storefront or the Mall
   home has no .modal rules at all: the element is a plain div, always in flow,
   and "open recommended products" appeared to do nothing.

   🔴 EVERY RULE HERE IS GATED ON .vf-mdl, WHICH ONLY vfModal ADDS, AND ONLY
   WHEN BOOTSTRAP IS ABSENT. So this cannot override the real Bootstrap modal
   on the hosts that have one — the class is simply never present there. That
   is why these are plain selectors and not :where(): they need to win against
   nothing, so they may as well be legible.

   z-index 2600 clears .cdm-overlay at 2400. The overlay carries a
   backdrop-filter, which makes it the containing block for position:fixed
   descendants — harmless here, because the overlay is itself inset:0, so
   "fixed" still resolves to the full viewport.
   ══════════════════════════════════════════════════════════════════════════ */

.modal.vf-mdl {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 2600;
    overflow-y: auto;
    padding: 24px 12px;
    background: rgba(16, 20, 32, .55);
    -webkit-backdrop-filter: blur(2px);
    backdrop-filter: blur(2px);
}

.modal.vf-mdl.vf-mdl-open { display: block; }

body.vf-mdl-lock { overflow: hidden; }

.modal.vf-mdl .modal-dialog { margin: 0 auto; width: 100%; max-width: 720px; }
.modal.vf-mdl .modal-dialog.modal-lg { max-width: 900px; }
.modal.vf-mdl .modal-dialog.modal-xl { max-width: 1140px; }

.modal.vf-mdl .modal-content {
    display: flex;
    flex-direction: column;
    background: #fff;
    border-radius: 14px;
    box-shadow: 0 24px 60px rgba(0, 0, 0, .35);
    overflow: hidden;
    max-height: calc(100vh - 48px);
}

.modal.vf-mdl .modal-header {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: 1rem 1.15rem;
    border-bottom: 1px solid #e9ecef;
    flex: 0 0 auto;
}

.modal.vf-mdl .modal-title { margin: 0; font-weight: 700; }
.modal.vf-mdl .modal-body { padding: 1.15rem; overflow-y: auto; flex: 1 1 auto; }

.modal.vf-mdl .modal-footer {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: .5rem;
    padding: .85rem 1.15rem;
    border-top: 1px solid #e9ecef;
    flex: 0 0 auto;
}

/* Bootstrap's .btn-close is a background-image glyph on a bare button. With no
   Bootstrap the button is invisible, so draw the × as text instead. */
.modal.vf-mdl .btn-close {
    margin-left: auto;
    width: 32px;
    height: 32px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: #6c757d;
    font-size: 0;
    cursor: pointer;
    flex: 0 0 auto;
}

.modal.vf-mdl .btn-close::before { content: "\00d7"; font-size: 22px; line-height: 32px; }
.modal.vf-mdl .btn-close:hover { background: #f1f3f5; color: #212529; }

/* The grid inside. #recGrid is row/col-* markup, which without Bootstrap
   stacks one card per line down a very long page. Scoped to .vf-mdl for the
   same reason as everything above. */
.modal.vf-mdl .row { display: flex; flex-wrap: wrap; margin: 0 -.5rem; }
.modal.vf-mdl .row > [class*="col-"] { padding: 0 .5rem; margin-bottom: 1rem; flex: 0 0 50%; max-width: 50%; }
.modal.vf-mdl .d-none { display: none !important; }
.modal.vf-mdl .input-group { display: flex; align-items: stretch; }
.modal.vf-mdl .input-group > .form-control { flex: 1 1 auto; min-width: 0; }

@media (min-width: 576px) {
    .modal.vf-mdl .row > [class*="col-sm-4"] { flex: 0 0 33.3333%; max-width: 33.3333%; }
}

@media (min-width: 768px) {
    .modal.vf-mdl .row > [class*="col-md-3"] { flex: 0 0 25%; max-width: 25%; }
}

@media (min-width: 992px) {
    .modal.vf-mdl .row > [class*="col-lg-2"] { flex: 0 0 16.6667%; max-width: 16.6667%; }
}
