/* ===================================================================
 * Shared floating-surface chrome — the two tiers that sit above the
 * page: the scrimmed MODAL tier (inconsistency #94) and the scrimless
 * POPOVER tier below it (efficiency #230).
 *
 * ── Modal tier — scrim + panel ─────────────────────────────────────
 *
 * Core ships three dialogs and a single carcass session can cross two of
 * them (Customise unit → Save design), so their scrim, radius and shadow
 * must match. The now-retired Door Style modal's treatment was originally
 * the only one on the theme's own tokens, so it was promoted here; the
 * three that remain consume these two classes:
 *
 *   .core-approval-overlay / .core-approval-modal        (core-approval-modal.css)
 *   .{slug}-customise-modal / …__dialog                  (core-room.css)
 *   .csd-modal__backdrop / .csd-modal__panel             (core-saved-designs.css)
 *
 * The Theme's dialogs wear the panel and the rhythm too (efficiency #568 —
 * the Theme loads this sheet through `register_control_layer()`), each
 * keeping its own placement: the basket drawer and mobile nav are DRAWERS
 * (header.css), the crossing dialog is a MODAL (journey-scope.css), and the
 * cookie card is a non-modal corner panel with no scrim (cookie-consent.css).
 * The search takeover and the gallery lightbox are deliberate exceptions —
 * no panel — and take only the square close, `.core-btn--close`.
 *
 * Chrome, plus the one header / body / footer rhythm every dialog shares
 * (`.core-modal-header` / `-title` / `-body` / `-footer`, 2026-09-27 — the
 * three had drifted to three paddings and two divider tones). No
 * positioning, sizing or transitions: those stay in each modal's own
 * stylesheet, which is loaded after this one (every
 * consumer declares `core-modal` as a style dep), so a local override at
 * equal specificity still wins — that is what keeps the full-screen
 * mobile sheets' `border-radius: 0` working.
 *
 * ── Popover tier — one chrome, no scrim ────────────────────────────
 *
 * Everything that floats WITHOUT a scrim: the configurator popup, the
 * planner's per-unit and wall-feature popovers, the click-to-edit
 * dimension popup. Before efficiency #230 these carried six chrome
 * bodies across three radii and three shadows, so panels on one
 * conceptual tier read as different heights — exactly what Design.md
 * §6.1 closes the elevation scale against. Consumers:
 *
 *   .core-popup / .sheet-cutout-popover                  (core-configurator.css)
 *   .{slug}-room-popover                                 (core-room-popover.css)
 *   .{slug}-feature-popover                              (core-room-popover.css)
 *   .core-room-dim-popup                                 (core-room-dims.css)
 *
 * Three deliberate NON-consumers, each verified against Design.md
 * rather than assumed — don't "align" them in a later sweep:
 *
 *   .cms-listbox (core-material-swatch.css) is a dropdown listbox,
 *   which §6.1 seats on rung 3 WITH the modal panels, not rung 2. It is
 *   body-appended above --z-modal for the same reason. Its --shadow-3
 *   is correct.
 *
 *   .core-popover.is-bottom-sheet (below) keeps its raw upward-cast
 *   recipe — §6.1's sanctioned exception, since every rung casts
 *   downward and would be clipped off-screen there (inconsistency
 *   #105). Its two-class selector outranks .core-popover regardless of
 *   load order.
 *
 *   .core-room-style-picker__popover is an unmounted shell; its chrome
 *   was stripped rather than folded, with a note in place for whoever
 *   mounts it.
 *
 * Radius is --r-md because §5.2 reserves --r-lg for modal panels alone;
 * the border steps up to --rule-strong (the modal's --rule is enough
 * only because a scrim already separates it) — a popover has to define
 * its own edge over a busy canvas.
 *
 * ── Both tiers ─────────────────────────────────────────────────────
 *
 * Chrome ONLY — no positioning, sizing, layout or transitions. Those stay
 * in each consumer's own stylesheet, which is loaded after this one (every
 * consumer declares `core-modal` as a style dep), so a local override at
 * equal specificity still wins — that is what keeps the full-screen
 * mobile sheets' `border-radius: 0` working.
 *
 * Tokens: --scrim/--ink/--paper/--rule/--rule-strong/--r-md/--r-lg come from the
 * theme's main.css, which is loaded network-wide; --shadow-2/--shadow-3
 * come from the plugin's own core-tokens.css (a dep of this handle), so
 * both tiers keep their lift on any theme — inconsistency #105. This file
 * defines none of its own.
 * =================================================================== */

.core-modal-scrim {
    background: var(--scrim);
    backdrop-filter: blur(2px);
}

.core-modal-panel {
    background: var(--paper);
    border: 1px solid var(--rule);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-3);
}

/* Header / body / footer — one rhythm for every dialog (§7.10): a 16/20px
   header and a 12/20px footer, each divided from a 20px body by a 1px Rule.
   The footer is a right-aligned row of actions; a dialog whose footer
   stacks something above its actions (the approval modal's checkbox)
   overrides `display` locally and keeps the padding and divider. */
.core-modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-3);
    padding: var(--sp-4) var(--sp-5);
    border-bottom: 1px solid var(--rule);
}

.core-modal-title {
    margin: 0;
    font-size: var(--fs-18);
    font-weight: var(--fw-semibold);
    color: var(--ink);
}

.core-modal-body {
    padding: var(--sp-5);
}

.core-modal-footer {
    display: flex;
    justify-content: flex-end;
    gap: var(--sp-2);
    padding: var(--sp-3) var(--sp-5);
    border-top: 1px solid var(--rule);
}

/* Full-screen sheets on a phone (§7.10): the side padding steps down a rung. */
@media (width < 640px) {
    .core-modal-header,
    .core-modal-body,
    .core-modal-footer {
        padding-inline: var(--sp-4);
    }
}

/* Rung 2 of the three-rung scale — "raised", where §6.1 seats popovers,
   tooltips and toolbars. The driver.js coach-mark popover is joined by
   selector because the library builds its own markup; its placement lives in
   `core-tutorial.css`. */
.core-popover,
.driver-popover {
    background: var(--paper);
    border: 1px solid var(--rule-strong);
    border-radius: var(--r-md);
    box-shadow: var(--shadow-2);
}

/* The two presentation modes a planner popover takes instead of floating
   (efficiency #628 — the unit popover and the price breakdown each carried a
   copy). Their JS sets the flag from the one `bottomSheetActive()` test.
   These are this tier's one exception to "chrome only": the mode IS a
   placement, so it lives with the chrome it strips or reshapes.

   In the rail the host's own `.core-room-planner__rail` paper and border are
   the panel, so a second frame and shadow would double it. */
.core-popover.is-in-rail {
    position: static;
    width: auto;
    max-width: none;
    max-height: none;
    overflow: visible;
    background: var(--paper);
    border: 0;
    border-radius: 0;
    box-shadow: none;
}

/* Flush on the bottom edge of a narrow / coarse-pointer viewport. Left /
   right / bottom are pinned by the JS (unit popover) or the consumer (price
   breakdown); this owns the paint and the scroll. The shadow is the one raw
   elevation recipe left in the frontend sheets, and deliberately so
   (inconsistency #105): the lift has to cast UPWARD over the planner, and
   every rung of the --shadow-1/2/3 scale casts downward, where it would be
   clipped off-screen. Don't "align" this one. */
.core-popover.is-bottom-sheet {
    width: 100%;
    max-width: none;
    max-height: 80vh;  /* fallback for UAs without dynamic-viewport units */
    max-height: 80dvh; /* mobile-toolbar-aware where supported */
    overflow-y: auto;
    border-radius: var(--r-lg) var(--r-lg) 0 0;
    box-shadow: 0 -8px 32px rgb(0 0 0 / 0.18);
}

/* Toast — one chrome for every transient notice (2026-09-27: the saved-designs
   toast and the room planner's notice had drifted to two radii, two paddings
   and one shadow between them). Rung 3 like the modal panel, because it floats
   above everything. Placement, entrance motion and colour variants stay with
   each consumer: `.csd-toast` (core-saved-designs.css) and `.{slug}-notice`
   (core-room.css); the entrance both share is `--float` below. */
.core-toast {
    background: var(--ink);
    color: var(--paper);
    padding: var(--sp-3) var(--sp-5);
    border-radius: var(--r-md);
    font-size: var(--fs-14);
    line-height: var(--lh-compact);
    box-shadow: var(--shadow-3);
}

/* The shared entrance: centred on its anchor, faded out and dropped one
   `--sp-2` until `.is-visible` (efficiency #628 — the two consumers had
   drifted to 0.5rem and 20px), and never in the way of a click. Each
   consumer keeps its own anchor (`position`, `bottom`), width cap and
   z-tier: the room notice floats over the plan, the saved-designs toast is
   fixed to the viewport. */
.core-toast--float {
    left: 50%;
    transform: translateX(-50%) translateY(var(--sp-2));
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--dur-base) var(--ease), transform var(--dur-base) var(--ease);
}

.core-toast--float.is-visible {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
}

/* In-page confirm — the one "are you sure?" (core-inline-confirm.js), because
   Design.md non-negotiable 5 bans customer-facing browser dialogs (issue
   #448). Seated in the flow right after whatever asked: the Style step's
   switch confirm, a saved design's Delete, the room planner's style reset.
   Paper with a Rule Strong hairline, and a strip of joined `.core-btn--seg`
   buttons below it (core-controls.css) — the style pill's grammar. */
.core-confirm {
    margin: var(--sp-2) 0 var(--sp-4);
    padding: var(--sp-3);
    border: 1px solid var(--rule-strong);
    border-radius: var(--r-sm);
    background: var(--paper);
    font-size: var(--fs-13);
    color: var(--ink);
}

.core-confirm__text {
    margin: 0;
    line-height: var(--lh-compact);
}

.core-confirm__name {
    font-weight: var(--fw-semibold);
}

.core-confirm__actions {
    display: flex;
    margin-top: var(--sp-3);
}

