/*
 * Glass Modals — single source of truth for popup / modal / dialog styling.
 *
 * Two universal rules every popup on the site MUST follow (see AGENTS.md):
 *   1. CENTERING — on desktop / tablet (≥933px) the popup overlay treats the
 *      sidebar edge as x=0. The popup is centered inside the main-content
 *      viewport, never across (sidebar+content). On phone (≤932px) the
 *      sidebar becomes off-canvas and the popup re-centers across the full
 *      viewport — the layout-sidebar-width variable defined in
 *      sidebar-layout.css drops to 0 automatically.
 *   2. GLOSSY — every popup panel (the visible card) uses the canonical
 *      glassy recipe: rgba(17,26,34,0.18) + 20px blur + thin white border +
 *      12px radius + soft shadow. Per-page gradient fills (#1a1a2e/#16213e
 *      etc.) are forcibly overridden here so the look is uniform.
 *
 * Selectors covered (every popup variant in use across the site):
 *   Backdrop / overlay layer (full-screen, gets sidebar offset on desktop):
 *     .modal                        → mydecks / investigators / admin / ocr-* / etc.
 *     .modal-backdrop               → friends invite
 *     .upgrade-modal-backdrop       → deck-dashboard
 *     .upgrade-modal-container      → deck-dashboard upgrade flow
 *     .upgrade-modal                → mydecks upgrade flow
 *     .add-friend-modal             → campaign-log
 *     .city-notes-modal             → campaign-log
 *     .odds-calc-modal              → deck-dashboard odds calculator
 *     .legal-disclaimer-overlay     → legal-disclaimer.js (JS-injected)
 *     .investigator-popup,
 *     .investigator-detail          → investigators page
 *     dialog::backdrop              → native <dialog> backdrop
 *
 *   Panel / card layer (the visible glass surface, gets glossy recipe):
 *     .modal-content, .modal-panel
 *     .upgrade-modal-content, .upgrade-modal-panel
 *     .add-friend-modal-content
 *     .city-notes-modal-content
 *     .odds-calc-panel
 *     .legal-disclaimer-panel
 *     .prebuilt-cards-modal-shell
 *     dialog.modal, dialog.cev2-modal
 *     .popup, .toast               → notification toasts
 *
 * Loading order: include this file AFTER liquid-glass.css and AFTER
 * mobile-optimized.css on every page that has a popup.
 */

/* ===========================================================================
   1. SIDEBAR-AWARE CENTERING (desktop / tablet ≥ 933px)
   ===========================================================================
   On phone the sidebar collapses and `--layout-sidebar-width` is 0, so this
   block is gated behind min-width: 933px. The variable resolves to 240px
   (desktop) or 220px (tablet 769–1024px) per sidebar-layout.css. */
@media (min-width: 933px) {
  :root {
    --modal-sidebar-offset: var(--layout-sidebar-width, 240px);
  }

  /* Full-screen overlay containers: pin them to the right of the sidebar
     using `inset` so the box runs from the sidebar edge to the right edge
     of the viewport. Most of these elements use `display:flex;
     align-items:center; justify-content:center` to center their inner
     panel — adjusting the box itself shifts the centering math
     automatically and sidesteps the 100vw-scrollbar-gutter edge case. */
  .modal,
  .modal-backdrop,
  .upgrade-modal,
  .upgrade-modal-backdrop,
  .upgrade-modal-container,
  .add-friend-modal,
  .city-notes-modal,
  .odds-calc-modal,
  .legal-disclaimer-overlay,
  .investigator-popup,
  .investigator-detail,
  .cdm-overlay {
    left: var(--modal-sidebar-offset) !important;
    right: 0 !important;
    width: auto !important;
    max-width: none !important;
  }

  /* Native <dialog> elements are centered by the browser; nudge them right
     by half the sidebar so visual center sits inside main-content. */
  dialog.modal,
  dialog.cev2-modal,
  dialog#loginDialog,
  dialog#cardEditDialog {
    margin-left: calc(50% + var(--modal-sidebar-offset) / 2) !important;
    transform: translateX(-50%) !important;
    left: auto !important;
    right: auto !important;
  }

  /* Inline-styled fixed popup panels (deck-dashboard upgrade panel uses
     `style="position:fixed;top:50%;left:57% !important;transform:translate(-50%,-50%)"`
     and similar). Override the inline left so the panel re-centers inside
     main-content rather than at an arbitrary 57%. */
  .upgrade-modal-panel[style*="position:fixed"],
  .upgrade-modal-panel[style*="position: fixed"],
  .modal-content[style*="position:fixed"],
  .modal-content[style*="position: fixed"],
  .modal-panel[style*="position:fixed"],
  .modal-panel[style*="position: fixed"] {
    left: calc(50% + var(--modal-sidebar-offset) / 2) !important;
    transform: translate(-50%, -50%) !important;
  }

  /* Deck-dashboard upgrade modal — the per-page CSS uses `#upgradeModal
     .upgrade-modal-panel { left: 57% !important }` which has higher
     specificity than a single class. Match it with the same specificity
     and feed the actual sidebar-aware center value. The `57%` was a
     hardcoded approximation of "viewport center shifted by half the
     sidebar"; we replace it with the math so it adapts to viewport size. */
  #upgradeModal .upgrade-modal-panel,
  #upgradeModal.upgrade-modal-container .upgrade-modal-panel {
    left: calc(50% + var(--modal-sidebar-offset) / 2) !important;
    transform: translate(-50%, -50%) !important;
  }

  /* mydecks.html upgrade modal uses a different markup
     (`<div id="upgradeModal" class="upgrade-modal">`+ `.upgrade-modal-content`).
     The container is full-screen, the content is the panel — match both. */
  #upgradeModal.upgrade-modal {
    left: var(--modal-sidebar-offset) !important;
    right: 0 !important;
    width: auto !important;
    max-width: none !important;
  }

  /* Defensive catch-all: any element acting as a popup overlay (role +
     aria-modal) gets the sidebar offset. This handles future popups that
     use ARIA semantics instead of one of our recognized classes. */
  [role="dialog"][aria-modal="true"]:not(dialog):not(.modal-content):not(.modal-panel):not(.upgrade-modal-panel):not(.upgrade-modal-content):not(.add-friend-modal-content):not(.city-notes-modal-content):not(.odds-calc-panel):not(.legal-disclaimer-panel):not(.prebuilt-cards-modal-shell) {
    left: var(--modal-sidebar-offset) !important;
    right: 0 !important;
    width: auto !important;
    max-width: none !important;
  }
}

/* ===========================================================================
   2. BACKDROP / OVERLAY DIM LAYER
   =========================================================================== */

.modal-backdrop,
.upgrade-modal-backdrop {
  background: rgba(8, 12, 16, 0.55) !important;
  backdrop-filter: blur(8px) saturate(140%) !important;
  -webkit-backdrop-filter: blur(8px) saturate(140%) !important;
}

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .modal-backdrop,
  .upgrade-modal-backdrop {
    background: rgba(8, 12, 16, 0.78) !important;
  }
}

dialog::backdrop {
  background: rgba(8, 12, 16, 0.55);
  backdrop-filter: blur(8px) saturate(140%);
  -webkit-backdrop-filter: blur(8px) saturate(140%);
}

/* Per-page custom overlay backgrounds are overridden here so the dim level
   is uniform site-wide (campaign-log used `rgba(0,0,0,0.75)`, deck-dashboard
   odds calc used `rgba(0,0,0,0.55)`, legal disclaimer used `rgba(2,5,10,0.92)`
   — they're all consolidated to the canonical 0.55/0.78 fallback). */
.add-friend-modal,
.city-notes-modal,
.odds-calc-modal,
.legal-disclaimer-overlay {
  background: rgba(8, 12, 16, 0.55) !important;
  backdrop-filter: blur(8px) saturate(140%) !important;
  -webkit-backdrop-filter: blur(8px) saturate(140%) !important;
}

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .add-friend-modal,
  .city-notes-modal,
  .odds-calc-modal,
  .legal-disclaimer-overlay {
    background: rgba(8, 12, 16, 0.78) !important;
  }
}

/* The desktop full-screen `.modal` overlay (mydecks / admin / etc.). On
   phones, mobile-optimized.css forces a near-solid background to power the
   full-screen treatment — leave that alone. Only soften on desktop so the
   glass panel inside reads as actually translucent. */
@media (min-width: 933px) {
  .modal,
  .upgrade-modal,
  .upgrade-modal-container {
    background: rgba(8, 12, 16, 0.55) !important;
    backdrop-filter: blur(8px) saturate(140%) !important;
    -webkit-backdrop-filter: blur(8px) saturate(140%) !important;
  }
  @supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .modal,
    .upgrade-modal,
    .upgrade-modal-container {
      background: rgba(8, 12, 16, 0.78) !important;
    }
  }
}

/* ===========================================================================
   3. POPUP PANEL — THE GLASSY CARD ITSELF
   ===========================================================================
   This is the universal "the popup is glossy" rule. ANY popup panel listed
   below (regardless of which page renders it) gets the canonical glassy
   recipe with !important so per-page solid / gradient fills cannot win. */

.modal-content,
.modal-panel,
.upgrade-modal-panel,
.upgrade-modal-content,
.add-friend-modal-content,
.city-notes-modal-content,
.odds-calc-panel,
.legal-disclaimer-panel,
.prebuilt-cards-modal-shell,
.cdm-panel,
dialog.modal,
dialog.cev2-modal {
  background: rgba(17, 26, 34, 0.18) !important;
  backdrop-filter: blur(20px) saturate(180%) !important;
  -webkit-backdrop-filter: blur(20px) saturate(180%) !important;
  border: 1px solid rgba(255, 255, 255, 0.15) !important;
  border-radius: 12px !important;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.25) !important;
  color: #ffffff !important;
}

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .modal-content,
  .modal-panel,
  .upgrade-modal-panel,
  .upgrade-modal-content,
  .add-friend-modal-content,
  .city-notes-modal-content,
  .odds-calc-panel,
  .legal-disclaimer-panel,
  .prebuilt-cards-modal-shell,
  .cdm-panel,
  dialog.modal,
  dialog.cev2-modal {
    background: rgba(17, 26, 34, 0.62) !important;
  }
}

/* Native <dialog> elements need a transparent border-color override
   because most browsers paint a default 0 border, which would clash with
   the glassy look once color is forced. */
dialog.modal,
dialog.cev2-modal {
  color: #ffffff !important;
}

/* ===========================================================================
   4. POPUP HEADINGS — white-bold per AGENTS.md
   =========================================================================== */

.modal-content h1, .modal-content h2, .modal-content h3, .modal-content h4,
.modal-panel h1, .modal-panel h2, .modal-panel h3, .modal-panel h4,
.upgrade-modal-panel h1, .upgrade-modal-panel h2,
.upgrade-modal-panel h3, .upgrade-modal-panel h4,
.upgrade-modal-content h1, .upgrade-modal-content h2,
.upgrade-modal-content h3, .upgrade-modal-content h4,
.add-friend-modal-content h1, .add-friend-modal-content h2,
.add-friend-modal-content h3, .add-friend-modal-content h4,
.city-notes-modal-content h1, .city-notes-modal-content h2,
.city-notes-modal-content h3, .city-notes-modal-content h4,
.odds-calc-panel h1, .odds-calc-panel h2,
.odds-calc-panel h3, .odds-calc-panel h4,
.legal-disclaimer-panel h1, .legal-disclaimer-panel h2,
.legal-disclaimer-panel h3, .legal-disclaimer-panel h4,
dialog.modal h1, dialog.modal h2, dialog.modal h3, dialog.modal h4,
.modal-title,
.modal-header,
.modal-header h1, .modal-header h2, .modal-header h3, .modal-header h4 {
  color: #ffffff;
  font-weight: 700;
}

/* ===========================================================================
   5. POPUP CLOSE BUTTON — small glassy circle
   =========================================================================== */

.modal-content .modal-close,
.modal-panel .modal-close,
.upgrade-modal-panel .modal-close,
.upgrade-modal-content .modal-close,
.add-friend-modal-content .add-friend-modal-close,
.city-notes-modal-content .city-notes-modal-close,
.odds-calc-panel .odds-calc-close,
dialog.modal .modal-close {
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.18);
  color: #ffffff;
  border-radius: 50%;
  transition: background 0.18s ease, border-color 0.18s ease;
}

.modal-content .modal-close:hover,
.modal-panel .modal-close:hover,
.upgrade-modal-panel .modal-close:hover,
.upgrade-modal-content .modal-close:hover,
.add-friend-modal-content .add-friend-modal-close:hover,
.city-notes-modal-content .city-notes-modal-close:hover,
.odds-calc-panel .odds-calc-close:hover,
dialog.modal .modal-close:hover {
  background: rgba(var(--accent-rgb), 0.22);
  border-color: rgba(var(--accent-rgb), 0.45);
}

/* ===========================================================================
   6. PRIMARY BUTTON INSIDE A POPUP — accent recipe
   ===========================================================================
   Pages historically defined `.btn-primary` differently. Inside a popup we
   standardise on the project accent so an "Invite", "Save", "Confirm"
   button always reads as teal regardless of which page rendered the popup. */

.modal-content .btn-primary,
.modal-panel .btn-primary,
.upgrade-modal-panel .btn-primary,
.upgrade-modal-content .btn-primary,
.add-friend-modal-content .btn-primary,
.city-notes-modal-content .btn-primary,
.odds-calc-panel .btn-primary,
.legal-disclaimer-panel .btn-primary,
dialog.modal .btn-primary,
.modal-content button.primary,
.modal-panel button.primary,
.upgrade-modal-panel button.primary,
.upgrade-modal-content button.primary,
.add-friend-modal-content button.primary,
.city-notes-modal-content button.primary,
dialog.modal button.primary {
  background: rgba(var(--accent-rgb), 0.22) !important;
  border: 1px solid rgba(var(--accent-rgb), 0.45) !important;
  color: #ffffff !important;
  -webkit-text-fill-color: #ffffff !important;
}

.modal-content .btn-primary:hover,
.modal-panel .btn-primary:hover,
.upgrade-modal-panel .btn-primary:hover,
.upgrade-modal-content .btn-primary:hover,
.add-friend-modal-content .btn-primary:hover,
.city-notes-modal-content .btn-primary:hover,
.odds-calc-panel .btn-primary:hover,
.legal-disclaimer-panel .btn-primary:hover,
dialog.modal .btn-primary:hover,
.modal-content button.primary:hover,
.modal-panel button.primary:hover,
.upgrade-modal-panel button.primary:hover,
.upgrade-modal-content button.primary:hover,
.add-friend-modal-content button.primary:hover,
.city-notes-modal-content button.primary:hover,
dialog.modal button.primary:hover {
  background: rgba(var(--accent-rgb), 0.32) !important;
  border-color: var(--accent) !important;
}

.modal-content .btn-primary:disabled,
.modal-panel .btn-primary:disabled,
.upgrade-modal-panel .btn-primary:disabled,
.upgrade-modal-content .btn-primary:disabled,
.add-friend-modal-content .btn-primary:disabled,
.city-notes-modal-content .btn-primary:disabled,
dialog.modal .btn-primary:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* Form fields inside a popup — accent focus ring (no halo, per the
   `input:focus` rule in liquid-glass.css). */
.modal-content input:focus,
.modal-content select:focus,
.modal-content textarea:focus,
.modal-panel input:focus,
.modal-panel select:focus,
.modal-panel textarea:focus,
.upgrade-modal-panel input:focus,
.upgrade-modal-panel select:focus,
.upgrade-modal-panel textarea:focus,
.upgrade-modal-content input:focus,
.upgrade-modal-content select:focus,
.upgrade-modal-content textarea:focus,
.add-friend-modal-content input:focus,
.add-friend-modal-content select:focus,
.add-friend-modal-content textarea:focus,
.city-notes-modal-content input:focus,
.city-notes-modal-content select:focus,
.city-notes-modal-content textarea:focus,
.odds-calc-panel input:focus,
.odds-calc-panel select:focus,
.odds-calc-panel textarea:focus,
dialog.modal input:focus,
dialog.modal select:focus,
dialog.modal textarea:focus {
  outline: none;
  border-color: var(--accent-border) !important;
  box-shadow: 0 0 0 2px rgba(var(--accent-rgb), 0.18) !important;
}

/* ===========================================================================
   7. INDEX LOGIN DIALOG POLISH
   =========================================================================== */
dialog#loginDialog #loginForm .field {
  background: rgba(255, 255, 255, 0.06) !important;
  border: 1px solid rgba(255, 255, 255, 0.15) !important;
  color: #ffffff !important;
  -webkit-text-fill-color: #ffffff !important;
}

dialog#loginDialog #loginForm .field::placeholder {
  color: rgba(255, 255, 255, 0.55) !important;
  -webkit-text-fill-color: rgba(255, 255, 255, 0.55) !important;
}

dialog#loginDialog #loginForm #li_rem {
  accent-color: var(--accent);
}

dialog#loginDialog #loginForm .row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

dialog#loginDialog #loginForm #li_submit {
  background: rgba(var(--accent-rgb), 0.22) !important;
  border: 1px solid rgba(var(--accent-rgb), 0.45) !important;
  color: #ffffff !important;
  -webkit-text-fill-color: #ffffff !important;
}

dialog#loginDialog #loginForm #li_submit:hover {
  background: rgba(var(--accent-rgb), 0.32) !important;
  border-color: var(--accent) !important;
}

dialog#loginDialog #loginForm button[type="button"] {
  background: rgba(255, 255, 255, 0.08) !important;
  border: 1px solid rgba(255, 255, 255, 0.18) !important;
  color: #ffffff !important;
  -webkit-text-fill-color: #ffffff !important;
}

dialog#loginDialog #loginForm button[type="button"]:hover {
  background: rgba(255, 255, 255, 0.14) !important;
  border-color: rgba(255, 255, 255, 0.28) !important;
}

dialog#loginDialog #loginForm a[href="/register"] {
  color: var(--accent) !important;
}

/* ===========================================================================
   8. TOAST / NOTIFICATION POPUPS — CANONICAL RECIPE
   ===========================================================================
   The whole site is meant to use ONE notification style: a glassy pill
   anchored bottom-center, sliding up from below on .show, sliding back
   down on hide. Covers three legacy class names so existing JS keeps
   working without per-page changes:
     - `.toast` and `#toast`         (friends/settings/decks toasts)
     - `.notification`               (global-utils.js / deck-dashboard
                                      / arkham-components.css legacy)
     - `.popup`                      (utility popups used by older pages)

   Type variants (success/error/warning/info) only change the border
   colour so the recipe stays unmistakably "site notification" first.
   See AGENTS.md → "Toast / notification canonical recipe" for the
   contract every notification on the site must satisfy. */

.popup,
.toast,
#toast,
.notification {
  /* --- Positioning: bottom-center, viewport-fixed --- */
  position: fixed !important;
  bottom: 24px !important;
  left: 50% !important;
  top: auto !important;
  right: auto !important;
  transform: translate(-50%, 100px) !important;
  z-index: 9999 !important;

  /* --- Sizing: hug content, but cap so long messages still read --- */
  width: auto !important;
  max-width: min(90vw, 460px) !important;
  min-width: 0 !important;
  /* Belt-and-suspenders for pages that put `body { display: flex }` —
     prevents the toast from collapsing to a 0-width flex item. */
  flex: 0 0 auto !important;
  display: block;

  /* --- Glass surface --- */
  padding: 12px 20px !important;
  font-size: 14px !important;
  font-weight: 500 !important;
  line-height: 1.4 !important;
  color: #ffffff !important;
  background: rgba(30, 30, 32, 0.95) !important;
  backdrop-filter: blur(20px) saturate(180%) !important;
  -webkit-backdrop-filter: blur(20px) saturate(180%) !important;
  border: 1px solid rgba(255, 255, 255, 0.15) !important;
  border-radius: 12px !important;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4) !important;
  text-align: center !important;
  overflow-wrap: anywhere !important;
  word-break: normal !important;
  white-space: normal !important;

  /* --- Show/hide animation --- */
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s ease, transform 0.3s ease !important;
}

.popup.show,
.toast.show,
#toast.show,
.notification.show {
  opacity: 1 !important;
  pointer-events: auto !important;
  transform: translate(-50%, 0) !important;
}

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .popup,
  .toast,
  #toast,
  .notification {
    background: rgba(17, 26, 34, 0.95) !important;
  }
}

/* Type variants — only the border colour changes so the surface stays
   recognisably "site notification" first. JS callers may use any of
   the equivalent class names. */
.toast.toast-success,    .toast-success,
.popup.popup-success,    .popup-success,
.notification.notification-success { border-color: rgba(48, 209, 88, 0.55) !important; }

.toast.toast-error,      .toast-error,
.popup.popup-error,      .popup-error,
.notification.notification-error   { border-color: rgba(255, 69, 58, 0.60) !important; }

.toast.toast-warning,    .toast-warning,
.popup.popup-warning,    .popup-warning,
.notification.notification-warning { border-color: rgba(255, 159, 10, 0.55) !important; }

.toast.toast-info,       .toast-info,
.popup.popup-info,       .popup-info,
.notification.notification-info    { border-color: var(--accent-border, rgba(37, 128, 117, 0.55)) !important; }

/* Popup-internal text/close styling — preserved from the previous
   block so utility popups (which embed `.popup-message`/`.popup-close`)
   keep reading correctly. */
.popup .popup-message,
.popup .popup-content { color: #ffffff !important; }

.popup .popup-close {
  color: rgba(255, 255, 255, 0.75) !important;
  background: transparent !important;
}
.popup .popup-close:hover {
  color: #ffffff !important;
}

/* On desktop, anchor the notification to the main-content viewport
   (right of the sidebar) by nudging its centre with half the sidebar
   width. The phone breakpoint clears this — see the rule below. */
@media (min-width: 933px) {
  .toast,
  #toast,
  .notification,
  .popup {
    margin-left: calc(var(--modal-sidebar-offset, 240px) / 2) !important;
  }
}
@media (max-width: 932px) {
  .toast,
  #toast,
  .notification,
  .popup {
    margin-left: 0 !important;
    max-width: calc(100vw - 24px) !important;
  }
}

/* ===========================================================================
   9. CAMPAIGN OPTION ROWS INSIDE FRIENDS INVITE MODAL
   =========================================================================== */
.modal-content .campaign-option,
.modal-panel .campaign-option {
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.10);
  color: #ffffff;
}
.modal-content .campaign-option:hover,
.modal-panel .campaign-option:hover {
  background: rgba(var(--accent-rgb), 0.12);
  border-color: rgba(var(--accent-rgb), 0.35);
}
.modal-content .campaign-option.selected,
.modal-panel .campaign-option.selected {
  background: rgba(var(--accent-rgb), 0.22);
  border-color: var(--accent);
}

/* ===========================================================================
   10. WINDOWS / OLDER-BROWSER FALLBACK
   ===========================================================================
   The previous version of this block forced every popup panel to a
   solid `rgba(17,26,34,0.62)` fill whenever `html.windows-compatibility`
   was present. That made Mac and Windows render the same popup
   dramatically differently — Mac kept the glassy 0.18 + 20px blur
   recipe from section 3, Windows got a flat dark slab.

   AGENTS.md "Mac / Windows parity is a hard rule" applies here. Modern
   Windows Chromium (which is what `windows-compat.js` tags) supports
   `backdrop-filter` natively, so the canonical glassy recipe works on
   Windows too. The fallback path is now:
     • backdrop-filter SUPPORTED  → canonical 0.18 + 20px blur recipe
       (section 3, applies to Mac AND Windows identically)
     • backdrop-filter UNSUPPORTED → 0.62 solid fallback via the
       `@supports not (...)` block in section 3 (Windows IE-mode,
       very old browsers, headless / SSR contexts)

   Do NOT re-introduce a `html.windows-compatibility` override for
   popup backgrounds — it permanently broke Mac/Windows parity. If a
   specific weak GPU truly can't paint the blur, gate it on
   `@media (prefers-reduced-transparency: reduce)` instead so the
   degradation is opt-in by the OS, not platform-wide. */

/* ===========================================================================
   11. CANONICAL "DELETE" ICON
   ===========================================================================
   Every delete button on the site should use this class instead of the
   `🗑️` emoji (which renders inconsistently across OSes, can show as
   coloured Apple/Win/Android art, and never inherits text colour).

   Usage:
     <button class="..." aria-label="Delete">
       <span class="icon-trash" aria-hidden="true"></span>
     </button>

   Or, alongside a label (parent button should use display:inline-flex
   with align-items:center and a small gap so the icon sits on the
   text baseline):
     <button style="...; display:inline-flex; align-items:center; gap:6px;">
       <span class="icon-trash" aria-hidden="true"></span>Delete
     </button>

   The icon ships as a fixed-white SVG (fill="#ffffff" baked into
   assets/icons/trash.svg) painted via background-image. This is the
   simplest, most reliable cross-browser approach — we previously tried
   `mask-image` + `currentColor`, but external SVGs loaded as a CSS mask
   have no DOM color context, so `fill="currentColor"` resolved to
   transparent and the icon rendered invisibly. White was always the
   product requirement, so hard-coding it is the right answer.

   Default size is `1em` so the icon scales with the surrounding
   font-size. To render it larger or smaller, set `font-size` on the
   parent or override `width` / `height` directly on the span. */

.icon-trash {
  display: inline-block;
  width: 1em;
  height: 1em;
  flex-shrink: 0;
  vertical-align: -2px;
  background-image: url('/assets/icons/trash.svg?v=2026-05-15-white');
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
  /* Defensive: some pages wrap the icon inside a button that sets a
     text/background `color` we don't want to leak through. The SVG is
     opaque white so the element itself needs no background colour. */
  background-color: transparent;
}

/* Common pairing classes so a delete glyph sits next to its label
   without callers having to ship inline-flex on every button. */
.icon-trash + span,
span + .icon-trash {
  margin-left: 0.35em;
}
