/* Deployed copy of /public/maestrox/glass.css (the design-system handoff).
   The source-of-truth file there carries an @import url('tokens.css') at
   the top; in this deployed copy it's stripped because layouts already
   <link> tokens before this file. Patch the deployed version inline as
   the portal evolves — same pattern as maestrox-components.css. */

/* =========================================================================
   MAESTROX — Glass Component Library
   Frosted panels for modals, sheets, popovers, toasts, sticky headers,
   and the command palette. Designed to live on top of the existing portal
   without rebuilding it.

   Works against:
     • cream/ivory canvas (the default desktop)
     • dark canvas (sidebar, video pages, splash)
     • image/video backdrops (login)

   Backdrop blur is GPU-expensive — use generously on infrequent surfaces
   (modals, sheets), sparingly on always-visible chrome (sticky headers
   use less blur with higher opacity).
   ========================================================================= */


/* =========================================================================
   PRIMITIVES
   ========================================================================= */

/* Base glass — opacity tuned for the cream/ivory canvas. Most surfaces use this. */
.glass {
  background: rgba(255, 252, 244, 0.72);
  backdrop-filter: blur(28px) saturate(1.4);
  -webkit-backdrop-filter: blur(28px) saturate(1.4);
  border: 1px solid rgba(200, 169, 94, 0.20);
  border-radius: 4px;
  box-shadow:
    0 30px 80px rgba(10, 8, 5, 0.18),
    0 10px 30px rgba(10, 8, 5, 0.10),
    inset 0 1px 0 rgba(255, 255, 255, 0.6);
  position: relative;
  color: var(--fg-1);
}

/* Dark glass — for use against bright backgrounds, video backdrops, splash screens */
.glass.dark {
  background: rgba(15, 12, 8, 0.62);
  border-color: rgba(200, 169, 94, 0.18);
  box-shadow:
    0 30px 80px rgba(0, 0, 0, 0.55),
    0 10px 30px rgba(0, 0, 0, 0.35),
    inset 0 1px 0 rgba(255, 255, 255, 0.04);
  color: var(--fg-on-dark);
}

/* Inner gold hairline — the "plate" ring from the login card */
.glass.ringed::before {
  content: "";
  position: absolute;
  inset: 8px;
  border: 0.5px solid rgba(200, 169, 94, 0.18);
  pointer-events: none;
  border-radius: 2px;
}

/* =========================================================================
   1 · MODAL — centered dialog with backdrop dim
   ========================================================================= */

.glass-modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 1000;
  background: rgba(10, 8, 5, 0.45);
  /* Heavier backdrop blur (4px → 16px) so the gold canvas + cards
   * behind the modal soften visibly. Pairs with the working-surface
   * 92% card opacity so the modal's blur sees actual gradient bleeding
   * through. Was too subtle at 4px when cards were 100% opaque —
   * Drew flagged the diff vs the canvas.html reference. */
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  animation: fade-in 200ms var(--ease) both;
}
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }

.glass-modal {
  width: 100%;
  max-width: 480px;
  padding: 36px 36px 28px;
  animation: modal-in 320ms cubic-bezier(.2,.7,.2,1) both;
}
@keyframes modal-in {
  from { opacity: 0; transform: translateY(16px) scale(0.97); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

.glass-modal .head {
  display: flex; align-items: center; gap: 12px;
  margin-bottom: 18px;
}
.glass-modal .head .mark {
  width: 32px; height: 32px;
  background: var(--fg-1);
  color: var(--gold);
  border-radius: 4px;
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 700;
  font-size: 18px;
  flex-shrink: 0;
}
.glass-modal h2 {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 22px;
  line-height: 1.15;
  color: inherit;
  margin: 0;
}
.glass-modal .body {
  font-size: 14px;
  line-height: 1.6;
  color: rgba(0, 0, 0, 0.7);
  margin-bottom: 22px;
}
.glass.dark .glass-modal .body { color: rgba(243, 234, 212, 0.7); }
.glass-modal .actions {
  display: flex; justify-content: flex-end; gap: 8px;
}

/* =========================================================================
   2 · SHEET — slides from bottom (mobile) or right (desktop)
   ========================================================================= */

.glass-sheet-backdrop {
  position: fixed;
  inset: 0;
  z-index: 900;
  background: rgba(10, 8, 5, 0.45);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  animation: fade-in 200ms var(--ease) both;
}

.glass-sheet {
  width: 100%;
  max-width: 560px;
  padding: 8px 24px 24px;
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
  border-top-left-radius: 16px;
  border-top-right-radius: 16px;
  animation: sheet-in 320ms cubic-bezier(.2,.7,.2,1) both;
  max-height: 85vh;
  overflow-y: auto;
}
@keyframes sheet-in {
  from { transform: translateY(100%); }
  to   { transform: translateY(0); }
}

.glass-sheet .handle {
  width: 40px; height: 4px;
  background: rgba(0, 0, 0, 0.15);
  border-radius: 2px;
  margin: 0 auto 16px;
}
.glass.dark .glass-sheet .handle { background: rgba(255, 255, 255, 0.18); }

.glass-sheet .head {
  display: flex; align-items: center; justify-content: space-between;
  padding-bottom: 12px;
  border-bottom: 1px solid rgba(200, 169, 94, 0.12);
  margin-bottom: 16px;
}
.glass-sheet .head h3 {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 18px;
  display: inline-flex; align-items: center; gap: 8px;
}
.glass-sheet .head h3::before {
  content: "M";
  width: 20px; height: 20px;
  background: var(--fg-1);
  color: var(--gold);
  border-radius: 3px;
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 700;
  font-size: 13px;
}
.glass-sheet .head .close {
  font-size: 13px; font-weight: 600;
  color: rgba(0, 0, 0, 0.55);
  cursor: pointer;
  background: transparent; border: 0;
  letter-spacing: 0.02em;
}
.glass.dark .glass-sheet .head .close { color: rgba(243, 234, 212, 0.55); }

/* Desktop variant — slide from right */
@media (min-width: 880px) {
  .glass-sheet.from-right-on-desktop {
    width: 480px;
    max-width: none;
    max-height: 100vh;
    height: 100vh;
    border-radius: 0;
    margin-left: auto;
    animation-name: sheet-in-right;
  }
  .glass-sheet-backdrop.from-right-on-desktop {
    align-items: stretch;
    justify-content: flex-end;
  }
}
@keyframes sheet-in-right {
  from { transform: translateX(100%); }
  to   { transform: translateX(0); }
}

/* =========================================================================
   3 · POPOVER — small floating panel anchored to a trigger
   ========================================================================= */

.glass-popover {
  position: absolute;
  z-index: 800;
  min-width: 200px;
  max-width: 320px;
  padding: 6px;
  border-radius: 6px;
  font-size: 13px;
  animation: popover-in 180ms cubic-bezier(.2,.7,.2,1) both;
  transform-origin: top left;
}
@keyframes popover-in {
  from { opacity: 0; transform: translateY(-4px) scale(0.96); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

.glass-popover ul { list-style: none; margin: 0; padding: 0; }
.glass-popover li {
  padding: 8px 12px;
  display: flex; align-items: center; gap: 10px;
  cursor: pointer;
  border-radius: 3px;
  font-weight: 500;
  color: inherit;
  -webkit-tap-highlight-color: transparent;
}
.glass-popover li:hover { background: rgba(200, 169, 94, 0.14); }
.glass-popover li .icon {
  width: 16px; height: 16px;
  color: var(--gold);
}
.glass-popover li .label { flex: 1; }
.glass-popover li .shortcut {
  font-family: var(--font-mono, monospace);
  font-size: 11px;
  color: rgba(0, 0, 0, 0.45);
  padding: 2px 6px;
  background: rgba(0, 0, 0, 0.06);
  border-radius: 3px;
}
.glass.dark .glass-popover li .shortcut {
  color: rgba(243, 234, 212, 0.55);
  background: rgba(255, 255, 255, 0.08);
}
.glass-popover .divider {
  height: 1px;
  background: rgba(200, 169, 94, 0.16);
  margin: 4px 0;
}

/* =========================================================================
   4 · TOAST — bottom-right pill with optional action
   ========================================================================= */

.glass-toast-stack {
  position: fixed;
  bottom: 24px;
  right: 24px;
  z-index: 950;
  display: flex; flex-direction: column;
  gap: 10px;
  pointer-events: none;
}
.glass-toast-stack > * { pointer-events: auto; }

.glass-toast {
  min-width: 280px;
  max-width: 400px;
  padding: 12px 16px 12px 14px;
  display: flex; align-items: center; gap: 12px;
  border-radius: 8px;
  animation: toast-in 280ms cubic-bezier(.2,.7,.2,1) both;
}
@keyframes toast-in {
  from { opacity: 0; transform: translateX(20px); }
  to   { opacity: 1; transform: translateX(0); }
}

.glass-toast .swatch {
  width: 28px; height: 28px;
  background: var(--gold);
  color: var(--fg-on-gold);
  border-radius: 6px;
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 700;
  font-size: 15px;
  flex-shrink: 0;
}
.glass-toast .swatch.success { background: var(--success); color: white; }
.glass-toast .swatch.danger  { background: var(--danger); color: white; }
.glass-toast .swatch.info    { background: var(--info); color: white; }

.glass-toast .body { flex: 1; min-width: 0; }
.glass-toast .body .title {
  font-size: 13px; font-weight: 600;
  color: inherit;
  margin-bottom: 1px;
}
.glass-toast .body .meta {
  font-size: 11.5px;
  color: rgba(0, 0, 0, 0.55);
}
.glass.dark .glass-toast .body .meta { color: rgba(243, 234, 212, 0.55); }
.glass-toast .undo {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--gold);
  background: transparent;
  border: 0;
  padding: 6px 10px;
  cursor: pointer;
  border-radius: 4px;
}
.glass-toast .undo:hover { background: rgba(200, 169, 94, 0.12); }

/* =========================================================================
   5 · STICKY HEADER — translucent strip that reveals on scroll
   Less blur than other surfaces because it's always visible
   ========================================================================= */

.glass-sticky-header {
  position: sticky;
  top: 0;
  z-index: 700;
  padding: 14px 24px;
  /* PERF (2026-05-22): dropped backdrop-filter — see
     .page-header--sticky note below. Same pattern: sticky always-
     visible element + blur = repaint pain. */
  background: rgba(255, 252, 244, 0.96);
  border-bottom: 1px solid rgba(200, 169, 94, 0.18);
  display: flex; align-items: center; gap: 16px;
}
.glass-sticky-header.dark {
  background: rgba(15, 12, 8, 0.86);
  border-bottom-color: rgba(200, 169, 94, 0.18);
  color: var(--fg-on-dark);
}
.glass-sticky-header .crumb {
  font-family: var(--font-body);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: rgba(0, 0, 0, 0.55);
}
.glass-sticky-header.dark .crumb { color: rgba(243, 234, 212, 0.65); }
.glass-sticky-header h1 {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 22px;
  line-height: 1;
  flex: 1;
  margin: 0;
}
.glass-sticky-header .actions {
  display: flex; gap: 8px;
}

/* Faint gold hairline that fades in/out at edges */
.glass-sticky-header::after {
  content: "";
  position: absolute;
  bottom: 0; left: 24px; right: 24px;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--gold-soft), transparent);
  opacity: 0.5;
}

/* =========================================================================
   6 · COMMAND PALETTE — top-center search overlay (⌘K)
   ========================================================================= */

.glass-command-backdrop {
  position: fixed;
  inset: 0;
  z-index: 1100;
  background: rgba(10, 8, 5, 0.45);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 12vh 24px 24px;
  animation: fade-in 160ms var(--ease) both;
}
/* Respect the [hidden] attribute. Without this, .glass-command-
   backdrop's display:flex wins over the user-agent [hidden]{display:
   none} so the palette renders on every page load. PR4 used
   <div data-command-palette hidden> expecting [hidden] to keep it
   dismissed; reinstate that behavior here. The brief's reference
   markup avoided this trap by using inline style="display:none"
   instead — we use the attribute so CSP stays clean.
   Same trap for modal + sheet backdrops, fixed defensively. */
.glass-command-backdrop[hidden],
.glass-modal-backdrop[hidden],
.glass-sheet-backdrop[hidden] {
  display: none !important;
}

.glass-command {
  width: 100%;
  max-width: 560px;
  padding: 0;
  border-radius: 10px;
  overflow: hidden;
  animation: command-in 240ms cubic-bezier(.2,.7,.2,1) both;
}
@keyframes command-in {
  from { opacity: 0; transform: translateY(-8px) scale(0.98); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

.glass-command .search {
  display: flex; align-items: center; gap: 12px;
  padding: 16px 18px;
  border-bottom: 1px solid rgba(200, 169, 94, 0.16);
}
.glass-command .search svg { width: 18px; height: 18px; color: rgba(0, 0, 0, 0.45); stroke-width: 1.8; fill: none; stroke: currentColor; }
.glass.dark .glass-command .search svg { color: rgba(243, 234, 212, 0.55); }
.glass-command .search input {
  /* !important defensively beats body.mx2-side input[type='text'] in
     mx2.css (specificity 0,2,2) and body.mx2-side input[readonly] +
     base.css's element-level input rules. Without these, the command
     palette search field renders as a normal opaque form input
     instead of the inline-transparent search bar. */
  flex: 1 !important;
  background: transparent !important;
  border: 0 !important;
  border-radius: 0 !important;
  outline: none !important;
  box-shadow: none !important;
  padding: 0 !important;
  font-family: var(--font-body) !important;
  font-size: 16px !important;
  color: inherit !important;
  letter-spacing: 0.005em !important;
  width: auto !important;
}
.glass-command .search .key {
  font-family: var(--font-mono, monospace);
  font-size: 10px;
  padding: 3px 6px;
  background: rgba(0, 0, 0, 0.06);
  border-radius: 3px;
  color: rgba(0, 0, 0, 0.5);
}
.glass.dark .glass-command .search .key {
  background: rgba(255, 255, 255, 0.08);
  color: rgba(243, 234, 212, 0.6);
}
.glass-command .results { max-height: 380px; overflow-y: auto; padding: 6px; }
.glass-command .group-label {
  padding: 8px 12px 4px;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--gold);
}
.glass-command .row {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 12px;
  border-radius: 4px;
  cursor: pointer;
  font-size: 13.5px;
}
.glass-command .row.is-active {
  background: rgba(200, 169, 94, 0.16);
}
.glass-command .row .icon { width: 16px; height: 16px; color: var(--gold); flex-shrink: 0; }
.glass-command .row .label { flex: 1; font-weight: 500; }
.glass-command .row .meta {
  font-size: 11px;
  color: rgba(0, 0, 0, 0.45);
}
.glass.dark .glass-command .row .meta { color: rgba(243, 234, 212, 0.55); }

/* =========================================================================
   REDUCED MOTION
   ========================================================================= */

@media (prefers-reduced-motion: reduce) {
  .glass-modal,
  .glass-sheet,
  .glass-popover,
  .glass-toast,
  .glass-command,
  .glass-modal-backdrop,
  .glass-sheet-backdrop,
  .glass-command-backdrop {
    animation-duration: 1ms !important;
  }
}

/* =========================================================================
   COMPAT LAYER — apply glass treatment to existing modal class names
   (PR2 of the glass rollout, CLAUDE_BRIEF_GLASS.md).

   The brief asked us to "wrap the contents in .glass.glass-modal.ringed"
   — but the portal has 10+ established modal patterns, each with its own
   markup, dismiss logic, ARIA wiring, and focus management. Touching every
   EJS template risks regressing those behaviors for no functional gain.

   Instead we apply the glass treatment via CSS to the existing modal
   class names. Same visual result, zero markup changes, zero behavior
   regression risk. The brief's head-pattern (italic "M" mark + h2 title)
   is NOT applied here — most existing modal heads carry their own
   bespoke layout; converting them is per-modal markup work we'll do as
   each gets revisited.

   !important is intentional: page-scoped composer.css loads AFTER this
   file in the cascade, so without !important the legacy opaque-background
   rules would win.
   ========================================================================= */

/* Backdrops — soften the dim layer with a heavier blur so the modal
   sits on something photographic, not a flat wash. Bumped 4px → 16px
   to match the canvas.html reference (the cards behind a modal clearly
   soften). Pairs with the 92%-opacity working-surface cards so the
   gold canvas refracts through the blur. */
.ai-plan-preview-backdrop,
.asset-dupe-modal-backdrop,
.batch-gen-backdrop,
.composer-cosimo-preview-backdrop,
.composer-library-modal-backdrop,
.composer-library-preview-backdrop,
.composer-snapshot-preview-backdrop,
.social-quick-edit-backdrop,
.modal-overlay {
  backdrop-filter: blur(16px) !important;
  -webkit-backdrop-filter: blur(16px) !important;
}

/* Light-glass cards — sit on a cream/ivory canvas. Lower the background
   opacity + add the blur + bump shadow so they read as frosted plate. */
.asset-dupe-modal,
.avatar-crop-modal,
.batch-gen-modal,
.discussion-subscribers__modal,
.gallery-download-modal,
.idle-logout-modal,
.move-folder-modal,
.modal-card {
  background: rgba(255, 252, 244, 0.78) !important;
  backdrop-filter: blur(28px) saturate(1.4) !important;
  -webkit-backdrop-filter: blur(28px) saturate(1.4) !important;
  border: 1px solid rgba(200, 169, 94, 0.20) !important;
  box-shadow:
    0 30px 80px rgba(10, 8, 5, 0.18),
    0 10px 30px rgba(10, 8, 5, 0.10),
    inset 0 1px 0 rgba(255, 255, 255, 0.6) !important;
  position: relative;
}
/* Drew, 2026-05-22: the gallery-picker backdrop is the FULL-VIEWPORT
   overlay (NOT just the card), so applying blur(28px) frosts the
   entire page behind too aggressively. Cut it in half. The cream
   tint + dark overlay still read as "modal active" without making
   the user's page context unrecognizable. */
.move-folder-modal {
  backdrop-filter: blur(14px) saturate(1.2) !important;
  -webkit-backdrop-filter: blur(14px) saturate(1.2) !important;
}

/* Dark-glass cards — composer-family modals sit on dark stone surfaces.
   The asset-modal also goes dark because it's a media viewer overlaid
   on a dimmed canvas. */
.asset-modal__inner,
.composer-cosimo-preview-modal,
.composer-library-modal {
  background: rgba(15, 12, 8, 0.72) !important;
  backdrop-filter: blur(28px) saturate(1.4) !important;
  -webkit-backdrop-filter: blur(28px) saturate(1.4) !important;
  border: 1px solid rgba(200, 169, 94, 0.18) !important;
  box-shadow:
    0 30px 80px rgba(0, 0, 0, 0.55),
    0 10px 30px rgba(0, 0, 0, 0.35),
    inset 0 1px 0 rgba(255, 255, 255, 0.04) !important;
  position: relative;
}

/* Inner gold hairline — the "plate" ring that gives the card depth.
   Inset 8px from the modal edge so it doesn't fight existing border-
   radius. pointer-events:none keeps it transparent to clicks.

   Skipped on .asset-modal__inner: the asset-modal carries internal
   bars / nav arrows that already overlap the edge zone, and an extra
   ring would crowd them. */
.asset-dupe-modal::before,
.avatar-crop-modal::before,
.batch-gen-modal::before,
.discussion-subscribers__modal::before,
.gallery-download-modal::before,
.idle-logout-modal::before,
.move-folder-modal::before,
.composer-cosimo-preview-modal::before,
.composer-library-modal::before,
.modal-card::before {
  content: "";
  position: absolute;
  inset: 8px;
  border: 0.5px solid rgba(200, 169, 94, 0.18);
  pointer-events: none;
  border-radius: 2px;
  z-index: 0;
}
/* Children must sit above the ::before ring so they remain clickable. */
.asset-dupe-modal > *,
.avatar-crop-modal > *,
.batch-gen-modal > *,
.discussion-subscribers__modal > *,
.gallery-download-modal > *,
.idle-logout-modal > *,
.move-folder-modal > *,
.composer-cosimo-preview-modal > *,
.composer-library-modal > * {
  position: relative;
  z-index: 1;
}

/* =========================================================================
   STICKY PAGE-HEADER OPT-IN (PR6 of glass rollout)

   Add .page-header--sticky to any <header class="page-header"> on a long
   scrolling page. The whole header sticks to the top of the viewport
   with a glass treatment (lower blur than modal glass — sticky surfaces
   are always visible so we trade blur strength for perf).

   Opted in by:
     - mx2/client-reports/show.ejs (Reports drill-in)
     - mx2/social/show.ejs        (Post detail / approval queue)
     - client/social/show.ejs     (Post detail, client side)
     - mx2/assets/folder.ejs      (Gallery view, admin)
     - client/assets/folder.ejs   (Gallery view, client)

   If we find the rich page-headers (with date toolbars / KPI strips)
   stick too heavily, the future move is to extract a slim row + apply
   sticky only to that. For v1 we accept the full-header sticky and
   iterate. ============================================================ */
.page-header--sticky {
  position: sticky;
  top: 0;
  z-index: 700;
  /* PERF (2026-05-22): dropped backdrop-filter. Sticky element on
     every page means every scroll pixel + every paint underneath
     forced a GPU re-composite of the blurred region. Bumped alpha
     to 0.96 so the header still reads as opaque-ish over whatever's
     beneath without the GPU cost. */
  background: rgba(255, 252, 244, 0.96);
  border-bottom: 1px solid rgba(200, 169, 94, 0.18);
  /* Drew, 2026-05-22 (round 2): full-bleed across the .content column
     on both client + admin layouts. The cream background stretches
     from the sidebar's right edge to the viewport's right edge; the
     header-row content (title + status pill) sits at the same
     x-position as the rest of the page below via matching inner
     padding.

     Math:
       margin-left: calc((100% - 100vw + sidebar-w) / 2)
         100% = .content-inner's resolved width (containing block).
         When viewport = 1920, sidebar = 232, content-inner = 1240,
         this resolves to -224 — exactly the auto margin .content-inner
         carries on each side, so the header reaches .content's edge.
       padding-left: calc((100vw - 100% - sidebar-w) / 2)
         Symmetric to the negative margin — pushes the header content
         back to where the page column starts. */
  margin-left: calc((100% - 100vw + var(--sidebar-w, 0px)) / 2);
  margin-right: calc((100% - 100vw + var(--sidebar-w, 0px)) / 2);
  padding-top: 16px;
  padding-bottom: 16px;
  padding-left: calc((100vw - 100% - var(--sidebar-w, 0px)) / 2);
  padding-right: calc((100vw - 100% - var(--sidebar-w, 0px)) / 2);
  margin-bottom: 24px;
}
/* The plain page-header margin is set elsewhere; when --sticky also
   applies we replace it (not stack it). */
.page-header.page-header--sticky { margin-bottom: 24px; }

/* Mobile: no fixed sidebar, so drop the sidebar-w correction. The
   sticky header still goes edge-to-edge with the viewport. */
@media (max-width: 720px) {
  .page-header--sticky {
    margin-left: calc((100% - 100vw) / 2);
    margin-right: calc((100% - 100vw) / 2);
    padding-left: calc((100vw - 100%) / 2);
    padding-right: calc((100vw - 100%) / 2);
  }
}
/* Faint gold hairline that fades at the edges — same as .glass-sticky-
   header's ::after, ported in via this scoped selector so existing
   page-header markup needs no restructure. */
.page-header--sticky::after {
  content: "";
  position: absolute;
  bottom: 0;
  left: 24px;
  right: 24px;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--gold-soft, rgba(200,169,94,0.55)), transparent);
  opacity: 0.5;
  pointer-events: none;
}
/* Some pages render the page-header inside a layout column that already
   carries overflow rules. Reset overflow on the sticky header's parent
   chain if needed via a body-class opt-in is too invasive — leaving as
   a known limitation. If sticky doesn't engage on a target page, the
   nearest scrolling ancestor probably has overflow:hidden|auto. */

/* =========================================================================
   SHEET COMPAT LAYER (PR3 of glass rollout)

   Apply glass treatment to the existing .m-sheet bottom-sheet primitive
   (used for the date-range picker, share menu, filter panels, etc.).
   Inherits the same layout choreography (slide-up on mobile, centered-
   modal on desktop ≥768px) from maestrox-mobile.css; this only changes
   the visual treatment to frosted glass.

   .m-more-sheet (legacy alias for the mobile More tab) gets the same
   treatment so the full mobile sheet family is consistent.
   ========================================================================= */
.m-sheet,
.m-more-sheet {
  background: rgba(255, 252, 244, 0.78) !important;
  backdrop-filter: blur(28px) saturate(1.4) !important;
  -webkit-backdrop-filter: blur(28px) saturate(1.4) !important;
  border: 1px solid rgba(200, 169, 94, 0.20) !important;
  box-shadow:
    0 30px 80px rgba(10, 8, 5, 0.18),
    0 10px 30px rgba(10, 8, 5, 0.10),
    inset 0 1px 0 rgba(255, 255, 255, 0.6) !important;
}
/* Backdrops behind the sheets — heavier blur so the gold canvas behind
   refracts visibly when a sheet opens. 4px → 16px to match the modal
   compat upgrade and the canvas.html reference. */
.m-sheet-backdrop,
.m-more-backdrop {
  backdrop-filter: blur(16px) !important;
  -webkit-backdrop-filter: blur(16px) !important;
}
/* Inner gold hairline ring — matches the modal compat treatment. */
.m-sheet::before,
.m-more-sheet::before {
  content: "";
  position: absolute;
  inset: 8px;
  border: 0.5px solid rgba(200, 169, 94, 0.18);
  pointer-events: none;
  border-radius: 2px;
  z-index: 0;
}
.m-sheet > *,
.m-more-sheet > * {
  position: relative;
  z-index: 1;
}
