/*
 * ABN App Shell — shared styles
 * -----------------------------------------------------------
 * Canonical styles for chrome elements that should be identical
 * across all web apps: back button, feature request button + dialog,
 * wordmark logo, app title, common animations, common dialog modal.
 *
 * Load AFTER any app-specific :root variable block.
 * Expected CSS variables (both shotlist and calendar define these):
 *   --bg, --surface, --border, --border-strong
 *   --text, --text-secondary, --text-muted
 * -----------------------------------------------------------
 */

/* Common animations — shared so every app gets the same motion */
@keyframes abn-shell-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes abn-shell-modal-rise {
  from { opacity: 0; transform: translateY(24px); }
  to   { opacity: 1; transform: translateY(0); }
}
/* Exit counterparts. DISTINCT names (not fade-in `reverse`) are essential: a
   reversed same-named animation won't restart once the enter one has finished,
   so the popup would snap shut with no fade. */
@keyframes abn-shell-fade-out {
  from { opacity: 1; }
  to   { opacity: 0; }
}
@keyframes abn-shell-modal-fall {
  from { opacity: 1; transform: translateY(0); }
  to   { opacity: 0; transform: translateY(12px); }
}
/* Entrance animations used across apps: headers fade+slide in on mount,
   and the body gets a .first-render class for the first second after data
   arrives so rows can stagger in (see per-app CSS). */
@keyframes abn-header-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes abn-row-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ——— SITEWIDE POPUP / MODAL ANIMATION (safety net) ———————————————
   Every popup should ease in AND out, not snap on/off. This is the top-level
   guarantee so a hand-rolled dialog never ships without motion again:

   • ENTER (automatic): any full-screen overlay — by the naming convention used
     across the apps (…-overlay / …-lightbox) or the canonical .abn-pop — fades
     its backdrop and rises its dialog child. Low specificity, and declared
     BEFORE the per-app rules further down, so an app that defines its own
     overlay/dialog animation still wins.
   • EXIT (opt-in, one line): route your close through ABN_SHELL.dismiss(el, cb).
     It adds .abn-pop-out (which plays the reverse — marked !important so it wins
     over any per-app enter animation), then hides/removes on animation end. */
[class*="overlay"], [class*="lightbox"], .abn-pop {
  animation: abn-shell-fade-in 0.18s ease-out both;
}
[class*="overlay"] > *, [class*="lightbox"] > *, .abn-pop > *, .abn-pop-card {
  animation: abn-shell-modal-rise 0.4s cubic-bezier(0.22, 0.61, 0.36, 1) both;
}
.abn-pop-out { animation: abn-shell-fade-out 0.16s ease-in both !important; }
.abn-pop-out > *, .abn-pop-out .abn-pop-card {
  animation: abn-shell-modal-fall 0.16s ease-in both !important;
}
@media (prefers-reduced-motion: reduce) {
  [class*="overlay"], [class*="lightbox"], .abn-pop,
  [class*="overlay"] > *, [class*="lightbox"] > *, .abn-pop > *, .abn-pop-card,
  .abn-pop-out, .abn-pop-out > *, .abn-pop-out .abn-pop-card { animation: none !important; }
}
/* Scoped to body.first-render so the header only animates on the very
   first paint after data arrives. Apps that rebuild the header on every
   render (shotlist) would otherwise replay the fade on lock toggle, undo,
   etc. The first-render class is added by each app's first-load logic and
   stripped before any subsequent render. */
body.first-render .app-header {
  animation: abn-header-in 0.45s cubic-bezier(0.22, 0.61, 0.36, 1) both;
}
@media (prefers-reduced-motion: reduce) {
  body.first-render .app-header { animation: none; }
}

/* ——— HEADER STRIP (canonical chrome container) ———
   Single source of truth for the shared toolbar's height, padding and
   cluster gap so every embedded app's header lines up EXACTLY. The tallest
   chrome element (the wordmark + the undo/redo pills) is 30px, so 12px
   symmetric vertical padding + a 54px min-height yield a consistent 54px
   strip regardless of which buttons an app carries. 20px horizontal padding
   + `justify-content: space-between` put the title/back cluster hard left
   and the action cluster hard right.

   Apps keep their own header CONTENT (their buttons + title text) and any
   app-specific chrome layering (z-index) or horizontal scroll (overflow-x),
   but must NOT re-declare padding / min-height / gap locally: this file
   loads BEFORE each app's <style>, so a local copy silently overrides this
   rule. Delete the local override rather than fight it with !important. */
.app-header {
  box-sizing: border-box;
  min-height: 54px;
  padding: 12px 20px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* 8px so that when the header is content-full and zones pack together (e.g.
     calendar), the between-zone gap matches the 8px button gaps rather than
     showing a wider 16px. On non-full headers space-between still spreads the
     zones apart, so this is only the minimum. */
  gap: 8px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
/* Action-button cluster — right-aligned, vertically centred, one gap. */
.app-header .header-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

/* ——— INNER CLUSTER SPACING (canonical) ———
   Single source of truth for the header's inner group gaps so every embedded
   app lines up IDENTICALLY: back↔title↔undo on the left (12px), and
   button↔button + last-item↔comms + comms↔wordmark on the right (8px). Scoped
   to `.app-header` so these out-specify bare per-app `.left`/`.right`/
   `.header-*` rules. Apps must NOT re-declare these gaps locally — an
   equal-specificity `.app-header .right` in an app would win by source order,
   so delete the local copy rather than fight it. The wordmark's own
   `margin-left` (below) adds the extra step out to the brand mark, so the
   comms→wordmark gap is a consistent 8 + 16px across every app. */
.app-header .left,
.app-header .header-left { gap: 12px; }
.app-header .right,
.app-header .header-right,
.app-header .header-right-group { gap: 8px; }
/* The shared `.back-btn` carries its own `margin-right: 12px` so the nested
   apps whose left cluster has NO flex gap (a classless inline `gap:0` div)
   still space the back button off the title. In the class-based clusters the
   12px flex gap already owns that spacing, so the margin would double it to
   24px — zero it there. Net: back↔title is a consistent 12px in every app. */
.app-header .left .back-btn,
.app-header .header-left .back-btn { margin-right: 0; }

/* ——— APP TITLE ——— */
.app-header h1 {
  margin: 0;
  font-family: 'helvetica-neue-lt-pro', 'Helvetica Neue', Helvetica, sans-serif;
  font-size: 14px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 1.5px;
  white-space: nowrap;
}
.app-header h1 span {
  color: var(--text-muted);
  font-weight: 400;
}

/* ——— BACK BUTTON (pill, compact for in-app chrome) ———
   Apps just declare `<button class="back-btn">← BACK</button>`; the shared
   ABN_SHELL.wireBackButtons() runs on DOMContentLoaded, swaps the leading
   arrow for the canonical chevron icon, and wraps the remaining label so
   the icon's leading whitespace stays consistent. */
.back-btn {
  font-family: 'helvetica-neue-lt-pro', 'Helvetica Neue', Helvetica, sans-serif;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 4px 10px 4px 8px;
  background: rgba(255, 255, 255, 0.8);
  color: var(--text-muted);
  border: 1px solid var(--border);
  border-radius: 999px;
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s, background 0.15s, opacity 0.15s;
  margin-right: 12px;
  white-space: nowrap;
  opacity: 0.8;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  line-height: 1;
}
.back-btn:hover {
  color: var(--text);
  border-color: var(--text);
  opacity: 1;
}
.back-btn .back-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 11px;
  height: 11px;
  flex-shrink: 0;
}
.back-btn .back-icon svg {
  width: 100%;
  height: 100%;
  display: block;
}
.back-btn .back-label {
  display: inline-flex;
  align-items: center;
  line-height: 1;
}

/* ——— WORDMARK LOGO ———
   The SVG's natural viewBox is 4054×2673.6 (~1.516:1). Declaring
   aspect-ratio lets the browser reserve the exact rendered width before
   the image decodes, so adjacent header buttons don't shift on load.
   Without this, width=auto is 0 until decode, then snaps and bumps
   everything sideways. */
.app-wordmark {
  height: 30px;
  aspect-ratio: 4054 / 2674;
  width: auto;
  opacity: 0.5;
  margin-left: 16px;
  flex-shrink: 0;
  transition: opacity 0.15s ease;
}
.app-wordmark-link {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  line-height: 0;
}
.app-wordmark-link:hover .app-wordmark,
.app-wordmark-link:focus-visible .app-wordmark {
  opacity: 1;
}
.app-wordmark-link:focus-visible {
  outline: 2px solid rgba(0, 0, 0, 0.4);
  outline-offset: 4px;
}

/* ——— UNDO / REDO BUTTONS ———
   Canonical pill pair used by every app's header for undo/redo.
   Markup:
     <div class="undo-redo">
       <button id="undoBtn" title="Undo"></button>
       <button id="redoBtn" title="Redo"></button>
     </div>
   Populate via ABN_SHELL.renderUndoRedo(container, { onUndo, onRedo,
   canUndo, canRedo }). Hidden automatically when body.locked. */
.undo-redo { display: flex; gap: 8px; }
/* Undo / redo are icon-only → perfectly CIRCULAR (equal box, 50% radius). */
.undo-redo button {
  background: rgba(255, 255, 255, 0.8);
  border: 1px solid var(--border);
  border-radius: 50%;
  color: var(--text-muted);
  width: 30px;
  height: 30px;
  padding: 0;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: color 0.15s, border-color 0.15s, opacity 0.15s, background 0.15s;
}
.undo-redo button:hover { color: var(--text); border-color: var(--text); }
.undo-redo button:disabled { opacity: 0.3; cursor: default; }
.undo-redo button:disabled:hover { color: var(--text-muted); border-color: var(--border); }
.undo-redo button svg { width: 14px; height: 14px; flex-shrink: 0; display: block; }
/* Optically centre the side-weighted arrows (undo leans left, redo right). */
#undoBtn svg { transform: translateX(1px); }
#redoBtn svg { transform: translateX(-1px); }
body.locked .undo-redo { visibility: hidden; }

/* ——— LOCK / UNLOCK BUTTON ———
   Canonical pill used by every app's header for the view-only toggle.
   Amber when LOCKED (draws the eye — something is protecting edits);
   subtle when UNLOCKED (blends into the chrome).
   Markup:
     <button class="lock-btn" id="lockBtn"></button>
   Populate innerHTML via ABN_SHELL.renderLockButton(btn, isLocked). */
.lock-btn {
  font-family: 'helvetica-neue-lt-pro', 'Helvetica Neue', Helvetica, sans-serif;
  font-size: 10px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  background: #fef3c7;
  border: 1px solid #fcd34d;
  color: #b45309;
  border-radius: 999px;
  padding: 4px 12px;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  /* Fixed width so toggling between LOCKED (6 chars) and UNLOCKED (8 chars)
     never shifts the surrounding header chrome. */
  width: 120px;
  box-sizing: border-box;
  justify-content: center;
  white-space: nowrap;
}
.lock-btn:hover { background: #fde68a; border-color: #f59e0b; }
.lock-btn.unlocked {
  background: rgba(255, 255, 255, 0.8);
  border-color: var(--border);
  color: var(--text-muted);
}
.lock-btn.unlocked:hover { border-color: var(--text); color: var(--text); }
.lock-btn svg { width: 11px; height: 11px; flex-shrink: 0; }

/* ——— FEATURE REQUEST BUTTON (pill, compact) ——— */
/* ——— CANONICAL HEADER PILL ———————————————————————————————————————
   DESIGN PRINCIPLE: every pill-shaped header button looks IDENTICAL — same
   height, padding, font, radius, border + glass treatment. Only the horizontal
   width varies to fit the label. A new header pill must JOIN these selectors
   (this base rule + :hover + the glass-pill sweep + the mobile min-height
   below) instead of rolling its own shape, so header pills can never drift
   apart again. Anything app-specific (e.g. an icon+label layout) is added
   separately without redefining the shape. */
.feature-btn,
.replace-btn {
  font-family: 'helvetica-neue-lt-pro', 'Helvetica Neue', Helvetica, sans-serif;
  font-size: 10px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text);
  background: rgba(255, 255, 255, 0.8);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 4px 10px;
  cursor: pointer;
  opacity: 0.8;
  transition: opacity 0.15s, border-color 0.15s, background 0.15s;
  white-space: nowrap;
}
.feature-btn:hover,
.replace-btn:hover {
  opacity: 1;
  border-color: var(--text);
}

/* ——— FEATURE REQUEST DIALOG ——— */
.fr-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.4);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 10000;
  animation: abn-shell-fade-in 0.18s ease-out;
}
.fr-dialog {
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 16px;
  width: 480px;
  max-width: 90vw;
  padding: 28px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  box-shadow:
    0 1px 2px rgba(0, 0, 0, 0.04),
    0 8px 24px rgba(0, 0, 0, 0.08),
    0 24px 64px rgba(0, 0, 0, 0.10);
  /* Enter animation comes from the sitewide safety net (fade 0.18s + rise 0.4s)
     so this popup eases in exactly like every other one — no longer its own
     slower 0.55s rise, which read as an over-animated bounce. */
}
.fr-dialog h2 {
  font-family: 'helvetica-neue-lt-pro', 'Helvetica Neue', Helvetica, sans-serif;
  font-size: 14px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 1.5px;
  color: var(--text);
  margin: 0;
}
.fr-dialog textarea {
  font-family: inherit;
  font-size: 13px;
  line-height: 1.5;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--bg);
  color: var(--text);
  outline: none;
  resize: vertical;
  min-height: 120px;
}
.fr-dialog textarea:focus { border-color: var(--text); }
.fr-actions {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
}
.fr-actions button {
  font-family: inherit;
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  padding: 6px 14px;
  cursor: pointer;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.8);
  color: var(--text-muted);
  transition: color 0.15s, border-color 0.15s, background 0.15s, opacity 0.15s;
}
.fr-actions button:hover {
  color: var(--text);
  border-color: var(--text);
}
.fr-actions button.primary {
  background: var(--text);
  border-color: var(--text);
  color: #fff;
}
.fr-actions button.primary:hover {
  background: #000;
  border-color: #000;
  color: #fff;
}
.fr-actions button.primary:disabled {
  opacity: 0.4;
  cursor: default;
}

/* Generic dialog body helpers — reused by abnAlert / abnConfirm / abnPrompt
   wrappers so every confirmation, prompt, and notice on the site lands in
   the same on-brand modal (with the existing fr-overlay fade-in + fr-dialog
   modal-rise + drop shadow) instead of a browser-native popup. */
.fr-dialog .abn-dialog-msg {
  font-family: inherit;
  font-size: 13px;
  line-height: 1.5;
  letter-spacing: 0.01em;
  color: var(--text-secondary);
  white-space: pre-wrap;
}
.fr-dialog .abn-dialog-input {
  font-family: inherit;
  font-size: 14px;
  line-height: 1.4;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--bg);
  color: var(--text);
  outline: none;
  transition: border-color 0.15s;
}
.fr-dialog .abn-dialog-input:focus {
  border-color: var(--text);
}

/* ——— DROPDOWN / PICKER POPUPS ———————————————————————————————————————
   Single source of truth for every floating menu: cell pickers, insert
   menus, slash menus, date pickers, swatches. Apps just declare the
   markup (`<div class="picker-popup">…<button class="picker-opt">…`)
   and inherit the rounded corners, drop shadow, rise animation, and
   row hover behaviour from here. App-specific extensions (date-picker,
   colour-grid, picker-add-row, picker-divider, etc.) layer on top via
   their own selectors. */
@keyframes abn-shell-picker-rise {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: translateY(0); }
}
.picker-backdrop {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: transparent;
  animation: abn-shell-fade-in 0.16s ease-out;
}
.picker-popup {
  position: absolute;
  z-index: 201;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 6px;
  min-width: 180px;
  display: flex;
  flex-direction: column;
  gap: 1px;
  box-shadow:
    0 1px 2px rgba(0, 0, 0, 0.05),
    0 8px 24px rgba(0, 0, 0, 0.08),
    0 24px 64px rgba(0, 0, 0, 0.12);
  animation: abn-shell-picker-rise 0.18s cubic-bezier(0.22, 0.61, 0.36, 1);
  transform-origin: top left;
}
/* Centred-modal variant (used for things like the New Column dialog).
   Drives the rise from the centre instead of the anchor. */
.picker-popup.centered {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  transform-origin: center;
  animation: abn-shell-modal-rise 0.55s cubic-bezier(0.22, 0.61, 0.36, 1);
}
.picker-popup .picker-opt {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border: none;
  background: transparent;
  border-radius: 4px;
  cursor: pointer;
  font-family: 'helvetica-neue-lt-pro', 'Helvetica Neue', Helvetica, sans-serif;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text);
  transition: background 0.12s, transform 0.12s;
  text-align: left;
  width: 100%;
}
.picker-popup .picker-opt:hover { background: var(--bg); }
.picker-popup .picker-opt.active { background: var(--accent-dim, #eef); }
.picker-popup .picker-opt:active { transform: scale(0.985); }

/* ============================================================
   GLASS CHROME — system-wide application of the glass material
   (tokens in design-tokens.css; portal mirror in globals.css).

   Every iframe app loads this AFTER design-tokens.css and BEFORE its
   own <style>, so material properties carry !important on purpose:
   the design system owns surface treatment; apps own layout. Any app
   using the standard chrome class names inherits the material with
   zero per-app work — including future apps.

   Scope discipline (keep it this way):
     · GLASS PILLS  — header/toolbar buttons + chips. No backdrop
       blur on buttons (they can appear 100+ per page); translucent
       fill + rim + radius reads as the same family at zero cost.
     · GLASS PANES  — dialogs, popovers, menus, tooltips. These get
       real backdrop blur; there are never more than a few at once.
     · INK          — primary action pills + toasts. Solid, top-lit.
     · CONTENT      — table rows, event pills, cards, data: never
       touched here. Glass is chrome, not data.
   ============================================================ */

/* — Utility classes for NEW components — */
.abn-glass {
  background: var(--glass-bg-elevated);
  -webkit-backdrop-filter: var(--glass-blur-soft);
  backdrop-filter: var(--glass-blur-soft);
  border: var(--glass-border);
  border-radius: var(--glass-radius);
  box-shadow: var(--glass-rim), var(--glass-shadow);
}
.abn-glass-pop {
  background: var(--glass-bg-elevated);
  -webkit-backdrop-filter: var(--glass-blur-soft);
  backdrop-filter: var(--glass-blur-soft);
  border: var(--glass-border);
  border-radius: var(--glass-radius-pop);
  box-shadow: var(--glass-rim), var(--glass-shadow-pop);
}
.abn-glass-pill {
  background: var(--glass-pill-bg);
  border: 1px solid var(--glass-pill-border);
  border-radius: 999px;
  box-shadow: var(--glass-pill-rim), var(--glass-pill-shadow);
}
.abn-ink-pill {
  background: var(--ink-bg);
  color: #fff;
  border: none;
  border-radius: 999px;
  box-shadow: var(--ink-rim), var(--ink-shadow);
}

/* — GLASS PILLS: shared header/toolbar buttons & chips — */
.export-btn, .nav-btn, .view-btn, .action-btn, .filter-btn, .gear-btn,
.feature-btn, .replace-btn, .back-btn, .undo-redo button,
.filter-chip, .type-chip {
  background: var(--glass-pill-bg) !important;
  border: 1px solid var(--glass-pill-border) !important;
  border-radius: 999px !important;
  box-shadow: var(--glass-pill-rim), var(--glass-pill-shadow) !important;
}
.export-btn:hover, .nav-btn:hover, .view-btn:hover, .action-btn:hover,
.filter-btn:hover, .gear-btn:hover, .feature-btn:hover, .replace-btn:hover, .back-btn:hover,
.undo-redo button:hover:not(:disabled),
.filter-chip:hover, .type-chip:hover {
  background: var(--glass-pill-bg-hover) !important;
  border-color: rgba(17, 17, 17, 0.45) !important;
}
.view-btn.active, .filter-btn.active, .export-btn.active {
  background: var(--glass-pill-bg-hover) !important;
  border-color: rgba(17, 17, 17, 0.65) !important;
}
.filter-chip.active, .type-chip.active {
  background: var(--glass-pill-bg-hover) !important;
  border-color: currentColor !important;
}
.lock-btn {
  border-radius: 999px !important;
  box-shadow: var(--glass-pill-rim), var(--glass-pill-shadow) !important;
}
.ev-close-btn, .qc-close { border-radius: 999px !important; }

/* — INK: primary actions + toasts — */
.today-btn, .add-event-btn, .upload-btn, .add-cat-btn:not(.ghost),
.ev-dialog-footer button.primary, .scope-actions button.primary,
.fr-actions button.primary, .qc-actions button.primary {
  background: var(--ink-bg) !important;
  border: none !important;
  border-radius: 999px !important;
  color: #fff !important;
  box-shadow: var(--ink-rim), var(--ink-shadow) !important;
}
.today-btn:hover, .add-event-btn:hover, .upload-btn:hover,
.add-cat-btn:not(.ghost):hover,
.ev-dialog-footer button.primary:hover, .scope-actions button.primary:hover,
.fr-actions button.primary:hover, .qc-actions button.primary:hover {
  filter: brightness(1.18);
  opacity: 1 !important;
}
.today-btn:disabled { filter: none; opacity: 0.35 !important; }
.toast {
  background: var(--ink-bg) !important;
  border-radius: var(--glass-radius-field) !important;
  box-shadow: var(--ink-rim), 0 4px 14px rgba(0, 0, 0, 0.18) !important;
}
.upload-item {
  background: var(--ink-bg) !important;
  border-radius: var(--glass-radius-field) !important;
  box-shadow: var(--ink-rim), 0 4px 14px rgba(0, 0, 0, 0.18) !important;
}

/* — GLASS PANES: dialogs — the ONE popup recipe, white copy (see --pop-* in
   design-tokens; the account editor is the reference). Fields inside stay
   light with dark text. — */
.ev-dialog, .detail-panel, .scope-panel, .kbd-panel, .fr-dialog,
.dm-modal-dialog, .scout-form-panel, .abn-pop {
  background: var(--pop-bg) !important;
  -webkit-backdrop-filter: var(--pop-blur);
  backdrop-filter: var(--pop-blur);
  border: none !important;
  border-radius: var(--pop-radius) !important;
  box-shadow: var(--pop-rim), var(--pop-shadow) !important;
  color: var(--pop-fg-dim) !important;
}
/* Headings / labels read full white; secondary copy is the dimmed white. */
.ev-dialog h1, .ev-dialog h2, .ev-dialog h3, .ev-dialog h4, .ev-dialog label,
.detail-panel h1, .detail-panel h2, .detail-panel h3, .detail-panel h4,
.scope-panel h1, .scope-panel h2, .scope-panel h3, .scope-panel label,
.kbd-panel h1, .kbd-panel h2, .kbd-panel h3,
.fr-dialog h1, .fr-dialog h2, .fr-dialog h3,
.dm-modal-dialog h1, .dm-modal-dialog h2, .dm-modal-dialog h3, .dm-modal-dialog label,
.scout-form-panel h1, .scout-form-panel h2, .scout-form-panel h3, .scout-form-panel label,
.abn-pop h1, .abn-pop h2, .abn-pop h3, .abn-pop label {
  color: var(--pop-fg) !important;
}
.fr-dialog .abn-dialog-msg, .abn-pop .abn-dialog-msg { color: var(--pop-fg-dim) !important; }

/* — GLASS PANES: popovers, menus, tooltips — */
.picker-popup, .qc-pop, .more-pop, .mm-pop, .gear-pop,
.linked-menu, .time-picker-dropdown, .chips-suggest {
  background: var(--glass-bg-elevated) !important;
  -webkit-backdrop-filter: var(--glass-blur-soft);
  backdrop-filter: var(--glass-blur-soft);
  border: var(--glass-border) !important;
  border-radius: var(--glass-radius-pop) !important;
  box-shadow: var(--glass-rim), var(--glass-shadow-pop) !important;
}
.ev-tip {
  /* keeps its per-event colour bar on border-top — no border override */
  background: var(--glass-bg-elevated) !important;
  -webkit-backdrop-filter: var(--glass-blur-soft);
  backdrop-filter: var(--glass-blur-soft);
  border-radius: 0 0 var(--glass-radius-pop) var(--glass-radius-pop) !important;
  box-shadow: var(--glass-rim), var(--glass-shadow-pop) !important;
}

/* — Overlays behind panes: lighter dim + real blur — */
.ev-overlay, .detail-overlay, .scope-overlay, .kbd-overlay, .fr-overlay,
.dm-modal-overlay, .scout-form-overlay, .doc-req-overlay, .abn-pop-overlay {
  background: var(--overlay-dim) !important;
  -webkit-backdrop-filter: var(--overlay-blur);
  backdrop-filter: var(--overlay-blur);
}

/* — Fields inside glass panes — stay LIGHT with DARK text for legibility,
   the one exception to the white popup copy (matches the account editor). — */
.ev-dialog input, .ev-dialog select, .ev-dialog textarea,
.fr-dialog textarea, .fr-dialog input, .fr-dialog select, .fr-dialog .abn-dialog-input,
.dm-modal-dialog input, .dm-modal-dialog select, .dm-modal-dialog textarea,
.scout-form-panel input, .scout-form-panel select, .scout-form-panel textarea,
.abn-pop input, .abn-pop select, .abn-pop textarea,
.picker-popup input, .picker-popup select,
.qc-pop select {
  background: var(--pop-field-bg) !important;
  border: 1px solid rgba(17, 17, 17, 0.13) !important;
  border-radius: var(--glass-radius-field) !important;
  box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.55) !important;
  color: var(--text) !important;
}
.ev-dialog input::placeholder, .fr-dialog textarea::placeholder, .fr-dialog input::placeholder,
.dm-modal-dialog input::placeholder, .scout-form-panel input::placeholder,
.scout-form-panel textarea::placeholder, .abn-pop input::placeholder, .abn-pop textarea::placeholder {
  color: var(--text-muted) !important;
}
.ev-dialog input:focus, .ev-dialog select:focus, .ev-dialog textarea:focus,
.fr-dialog textarea:focus, .fr-dialog input:focus, .fr-dialog .abn-dialog-input:focus,
.dm-modal-dialog input:focus, .dm-modal-dialog select:focus, .dm-modal-dialog textarea:focus,
.scout-form-panel input:focus, .scout-form-panel select:focus, .scout-form-panel textarea:focus,
.abn-pop input:focus, .abn-pop select:focus, .abn-pop textarea:focus,
.picker-popup input:focus, .picker-popup select:focus {
  background: var(--pop-field-bg-focus) !important;
  border-color: rgba(17, 17, 17, 0.45) !important;
  box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.7), 0 0 0 3.5px rgba(17, 17, 17, 0.06) !important;
}
.ev-dialog-footer button, .detail-footer button, .scope-actions button,
.fr-actions button, .qc-actions button {
  border-radius: 999px !important;
}

/* — Search / toolbar text fields — */
.search-input, .lib-search, .filter-search {
  background: var(--glass-pill-bg) !important;
  border: 1px solid var(--glass-pill-border) !important;
  border-radius: 999px !important;
  box-shadow: var(--glass-pill-rim) !important;
}
.search-input:focus, .lib-search:focus, .filter-search:focus {
  background: rgba(255, 255, 255, 0.94) !important;
  border-color: rgba(17, 17, 17, 0.45) !important;
}

@supports not (backdrop-filter: blur(1px)) {
  /* Popups carry white copy, so without blur they need a dark solid. */
  .ev-dialog, .detail-panel, .scope-panel, .kbd-panel, .fr-dialog,
  .dm-modal-dialog, .scout-form-panel, .abn-pop {
    background: rgba(26, 26, 30, 0.97) !important;
  }
  /* Menus/popovers keep dark text → light solid. */
  .picker-popup, .qc-pop, .more-pop, .mm-pop, .gear-pop,
  .linked-menu, .time-picker-dropdown, .chips-suggest, .ev-tip {
    background: rgba(255, 255, 255, 0.97) !important;
  }
}

/* — GLASS PILLS: remaining header/toolbar buttons across apps —
   (decks/docs status pills keep their state border colours: fill,
   radius and rim only on those.) */
.menu-btn, .new-btn, .panel-toggle, .rb-tool-btn,
.grid-size-toggle button, .lib-sort, .map-nav-btn {
  background: var(--glass-pill-bg) !important;
  border: 1px solid var(--glass-pill-border) !important;
  border-radius: 999px !important;
  box-shadow: var(--glass-pill-rim), var(--glass-pill-shadow) !important;
}
.menu-btn:hover, .new-btn:hover, .panel-toggle:hover, .rb-tool-btn:hover,
.grid-size-toggle button:hover, .map-nav-btn:hover {
  background: var(--glass-pill-bg-hover) !important;
  border-color: rgba(17, 17, 17, 0.45) !important;
}
.grid-size-toggle button.active, .rb-tool-btn.active {
  background: var(--glass-pill-bg-hover) !important;
  border-color: rgba(17, 17, 17, 0.65) !important;
}
.count-pill, .save-pill {
  background: var(--glass-pill-bg) !important;
  border-radius: 999px !important;
  box-shadow: var(--glass-pill-rim) !important;
}
.add-loc-btn {
  background: var(--ink-bg) !important;
  border: none !important;
  border-radius: 999px !important;
  color: #fff !important;
  box-shadow: var(--ink-rim), var(--ink-shadow) !important;
}
.add-loc-btn:hover { filter: brightness(1.18); opacity: 1 !important; }

/* ============================================================
   BESPOKE CHROME → GLASS (site-wide sweep). Neutral action / nav / icon
   pills across the apps inherit the glass pill material so every standalone
   chrome control reads the same. Text/icon colour is left untouched (these
   carry dark glyphs → readable on the light pill). Colour-CODED data tags
   (cast pills, in/out tags, doc/variance chips, category badges, status
   dots) are intentionally NOT included — their colour is information, so per
   the design system they stay opaque.
   ============================================================ */
.action-btn, .nav-btn, .add-col-btn, .day-action-btn, .doc-add-btn,
.fmt-btn, .link-edit-btn, .linked-pick-btn, .picker-add-btn,
.cast-row-icon-btn, .eyedropper-btn, .geocode-btn, .col-del-btn,
.conn-chip {
  background: var(--glass-pill-bg) !important;
  border: 1px solid var(--glass-pill-border) !important;
  border-radius: 999px !important;
  box-shadow: var(--glass-pill-rim), var(--glass-pill-shadow) !important;
}
.action-btn:hover, .nav-btn:hover, .add-col-btn:hover, .day-action-btn:hover,
.doc-add-btn:hover, .fmt-btn:hover, .link-edit-btn:hover, .linked-pick-btn:hover,
.picker-add-btn:hover, .cast-row-icon-btn:hover, .eyedropper-btn:hover,
.geocode-btn:hover, .col-del-btn:hover {
  background: var(--glass-pill-bg-hover) !important;
  border-color: rgba(17, 17, 17, 0.45) !important;
}

/* ============================================================
   POPUP MOTION — site-wide. Promotes the account-editor feel to every
   modal: the overlay fades, the card rises in, its contents spring and
   stagger into place, and any textarea marked [data-autogrow] grows the
   popup vertically as you type. Single source of truth for how popups
   move across the whole site (the account editor keeps its own bespoke
   two-mode morph; everything else shares this).
   ============================================================ */
:root { --abn-pop-bounce: cubic-bezier(0.34, 1.56, 0.64, 1); }

@keyframes abn-pop-card-in {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes abn-pop-item-in {
  from { opacity: 0; transform: translateY(12px) scale(0.96); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

/* Overlays — gentle fade. */
.fr-overlay, .doc-req-overlay, .dm-modal-overlay, .scout-form-overlay,
.ev-overlay, .detail-overlay, .scope-overlay, .kbd-overlay, .abn-pop-overlay {
  animation: abn-shell-fade-in 0.18s ease-out;
}

/* Cards — rise + fade. Overrides each modal's prior bespoke rise so the
   whole site shares one entrance. */
.fr-dialog, .doc-req-dialog, .dm-modal-dialog, .scout-form-panel,
.ev-dialog, .detail-panel, .scope-panel, .kbd-panel, .abn-pop {
  animation: abn-pop-card-in 0.42s cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* Contents — spring in, staggered, for the request-style popups whose layout
   is a short vertical stack. Complex app panels keep the card entrance
   without per-item stagger. */
.fr-dialog > *, .doc-req-dialog > *, .dm-modal-dialog > *, .abn-pop > * {
  animation: abn-pop-item-in 0.5s var(--abn-pop-bounce) backwards;
}
.fr-dialog > *:nth-child(1), .doc-req-dialog > *:nth-child(1), .dm-modal-dialog > *:nth-child(1), .abn-pop > *:nth-child(1) { animation-delay: 0.08s; }
.fr-dialog > *:nth-child(2), .doc-req-dialog > *:nth-child(2), .dm-modal-dialog > *:nth-child(2), .abn-pop > *:nth-child(2) { animation-delay: 0.14s; }
.fr-dialog > *:nth-child(3), .doc-req-dialog > *:nth-child(3), .dm-modal-dialog > *:nth-child(3), .abn-pop > *:nth-child(3) { animation-delay: 0.20s; }
.fr-dialog > *:nth-child(4), .doc-req-dialog > *:nth-child(4), .dm-modal-dialog > *:nth-child(4), .abn-pop > *:nth-child(4) { animation-delay: 0.26s; }
.fr-dialog > *:nth-child(5), .doc-req-dialog > *:nth-child(5), .dm-modal-dialog > *:nth-child(5), .abn-pop > *:nth-child(5) { animation-delay: 0.32s; }
.fr-dialog > *:nth-child(6), .doc-req-dialog > *:nth-child(6), .dm-modal-dialog > *:nth-child(6), .abn-pop > *:nth-child(6) { animation-delay: 0.38s; }

/* Vertical auto-expand — a [data-autogrow] textarea is sized to its content
   (by app-shell.js for vanilla apps, by useAutoGrow() in the React portal);
   the height transition grows the popup smoothly, like the account editor. */
textarea[data-autogrow] {
  overflow: hidden;
  resize: none;
  transition: height 0.18s ease;
}

@media (prefers-reduced-motion: reduce) {
  .fr-overlay, .doc-req-overlay, .dm-modal-overlay, .scout-form-overlay,
  .ev-overlay, .detail-overlay, .scope-overlay, .kbd-overlay, .abn-pop-overlay,
  .fr-dialog, .doc-req-dialog, .dm-modal-dialog, .scout-form-panel,
  .ev-dialog, .detail-panel, .scope-panel, .kbd-panel, .abn-pop,
  .fr-dialog > *, .doc-req-dialog > *, .dm-modal-dialog > *, .abn-pop > * {
    animation: none !important;
  }
  textarea[data-autogrow] { transition: none; }
}

/* Phone: finger-sized header chrome + 16px dialog fields (no iOS focus-zoom).
   Shared across every embedded app. */
@media (max-width: 767.98px) {
  /* Drop the fixed 54px desktop floor so each app's compact/stacked mobile
     header (its own @media padding) drives the height. */
  .app-header { min-height: 0; }
  .back-btn { min-height: 40px; padding-top: 9px; padding-bottom: 9px; }
  .feature-btn, .replace-btn, .lock-btn, .view-toggle { min-height: 40px; }
  .undo-redo button { min-width: 40px; min-height: 40px; }
  .fr-dialog input, .fr-dialog textarea, .abn-dialog-input { font-size: 16px; }
}
