/*
 * PayMeMate brand theme — Round 5
 *
 * What changed from Round 4:
 *   - Brand palette modernized: Material '14 purple (#5e35b7) → Radix-style
 *     violet (#7c3aed → #a78bfa). Surfaces de-tinted (truer neutrals).
 *   - Comprehensive chrome animations: page mount fade-slide, side-nav active
 *     accent bar, hover icon color shift, button micro-lift, card lift-on-hover,
 *     grid row hover, top-bar backdrop blur.
 *   - Login hero gets an animated mesh gradient (3 drifting blobs) instead of
 *     a flat brand gradient.
 *   - Refined input focus rings across the chrome (was only on .pmm-pay-card).
 *   - KPI cards: subtle gradient sheen + number tabular-nums.
 *
 * Layered as before:
 *   1. Token system (brand, surface, border, text, status, focus, elevation,
 *      motion, shape) — :root + dark mode override.
 *   2. Lumo bridge — pipes our tokens into Vaadin's --lumo-* variables.
 *   3. Chrome components (admin / merchant portal): nav, top bar, page mount,
 *      cards, KPI, badges, buttons, inputs, grid.
 *   4. Login screen — hero mesh + refined panel.
 *   5. Public payment-page primitives (.pmm-pay-*) — kept stable from Round 4
 *      so existing markup keeps working.
 *
 * Motion strategy:
 *   - All durations bound to tokens; @media prefers-reduced-motion zeros them.
 *   - Easing curves: standard (entrance) + spring (interaction feedback).
 *
 * Dark mode strategy:
 *   - Default = system; manual override via [data-theme=light|dark] on <html>.
 *   - AppShell init script sets the attribute synchronously to prevent FOUC.
 */

/* ============================================================
 * 1. TOKEN SYSTEM
 * ============================================================ */

:root {
  /* --- Brand (refined violet — Stripe/Linear feel, not Material '14) --- */
  --pmm-brand:           #7c3aed;   /* Violet 600 */
  --pmm-brand-2:         #a78bfa;   /* Violet 400 — gradient end */
  --pmm-brand-strong:    #6d28d9;   /* Violet 700 — pressed states */
  --pmm-brand-text:      #5b21b6;   /* Violet 800 — body text on light */
  --pmm-brand-gradient:  linear-gradient(135deg, #6d28d9 0%, #8b5cf6 60%, #a78bfa 100%);
  --pmm-brand-glow:      linear-gradient(135deg, rgba(109, 40, 217, 0.45) 0%, rgba(167, 139, 250, 0.45) 100%);
  --pmm-brand-soft:      rgba(124, 58, 237, 0.10);
  --pmm-brand-softer:    rgba(124, 58, 237, 0.04);

  /* --- Accent (cyan — for data-viz pops + hover icons) --- */
  --pmm-accent:          #06b6d4;   /* Cyan 500 */
  --pmm-accent-soft:     rgba(6, 182, 212, 0.10);

  /* --- Surfaces (cooler / truer neutrals than Round 4) --- */
  --pmm-surface-0:       #f7f7fb;   /* page bg — barely tinted */
  --pmm-surface-1:       #ffffff;   /* card */
  --pmm-surface-2:       #f4f4f8;   /* nested / line items */
  --pmm-surface-3:       #ecebf2;   /* sunken sections */
  --pmm-surface-overlay: rgba(255, 255, 255, 0.85);

  /* --- Borders (cooler, lower-saturation) --- */
  --pmm-border-subtle:   rgba(17, 18, 38, 0.06);
  --pmm-border-default:  rgba(17, 18, 38, 0.10);
  --pmm-border-strong:   rgba(17, 18, 38, 0.20);

  /* --- Text (warmer charcoal, less purple) --- */
  --pmm-text-primary:    #111226;
  --pmm-text-secondary:  #4b4d6b;
  --pmm-text-tertiary:   #797b95;
  --pmm-text-on-brand:   #ffffff;

  /* --- Status (slightly punchier) --- */
  --pmm-success:         #10b981;
  --pmm-success-bg:      rgba(16, 185, 129, 0.10);
  --pmm-success-text:    #047857;
  --pmm-warn:            #f59e0b;
  --pmm-warn-bg:         rgba(245, 158, 11, 0.12);
  --pmm-warn-text:       #b45309;
  --pmm-error:           #ef4444;
  --pmm-error-bg:        rgba(239, 68, 68, 0.10);
  --pmm-error-text:      #b91c1c;
  /* Info uses the accent (cyan) — gives the secondary color real surface
   * area on info badges, links, and data-viz instead of letting it sit
   * defined-but-unused. */
  --pmm-info:            var(--pmm-accent);
  --pmm-info-bg:         var(--pmm-accent-soft);
  --pmm-info-text:       #0e7490;

  /* --- Backwards-compat aliases ---
   * Several CSS rules + components were authored against earlier token names
   * (pmm-bg-elev0/1, pmm-border without a suffix). Aliasing here keeps every
   * reference resolving correctly without a wide find/replace that risks
   * touching unrelated rules. */
  --pmm-bg-elev0:        var(--pmm-surface-0);
  --pmm-bg-elev1:        var(--pmm-surface-1);
  --pmm-border:          var(--pmm-border-default);

  /* Status icon tokens — used by Java code that needs a tokenised colour for
   * inline SVG / fill attributes (success ✓ ticks, error ✗ crosses, etc.).
   * Distinct from --pmm-success/--pmm-error which carry a saturation suited
   * to badge backgrounds; the *-icon variants are tuned for foreground glyphs
   * against the card background. */
  --pmm-success-icon:    #10b981;
  --pmm-error-icon:      #ef4444;
  --pmm-warn-icon:       #f59e0b;

  /* --- Focus & elevation (longer, softer shadows for depth) --- */
  --pmm-focus-ring:      0 0 0 3px rgba(124, 58, 237, 0.28);
  --pmm-elev-0:          none;
  --pmm-elev-1:          0 1px 2px rgba(17, 18, 38, 0.05),
                         0 1px 3px rgba(17, 18, 38, 0.04);
  --pmm-elev-2:          0 4px 8px rgba(17, 18, 38, 0.06),
                         0 8px 24px rgba(17, 18, 38, 0.06);
  --pmm-elev-3:          0 12px 24px rgba(17, 18, 38, 0.10),
                         0 24px 64px rgba(17, 18, 38, 0.10);
  --pmm-elev-brand:      0 8px 20px rgba(124, 58, 237, 0.28);
  /* Neumorphism-light: subtle 1px highlight on top + soft 1-2px outer shadow.
   * Use on surfaces sitting flat on the page (form fields, list rows) where
   * elev-1's hard-edged shadow is too prominent. */
  --pmm-elev-soft:       0 1px 0 rgba(255, 255, 255, 0.6) inset,
                         0 1px 2px rgba(17, 18, 38, 0.06),
                         0 1px 3px rgba(17, 18, 38, 0.03);

  /* --- Shape --- */
  --pmm-shape-xs:        4px;
  --pmm-shape-sm:        8px;
  --pmm-shape-md:        12px;
  --pmm-shape-lg:        18px;
  --pmm-shape-xl:        24px;
  --pmm-shape-pill:      999px;

  /* --- Type scale (Inter via AppShell) --- */
  --pmm-font:            'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;
  --pmm-font-tabular:    var(--pmm-font);
  --pmm-type-display:    700 44px/52px var(--pmm-font);
  --pmm-type-headline:   700 24px/32px var(--pmm-font);
  --pmm-type-title:      600 18px/26px var(--pmm-font);
  --pmm-type-body:       400 14px/20px var(--pmm-font);
  --pmm-type-body-strong:600 14px/20px var(--pmm-font);
  --pmm-type-label:      600 11px/14px var(--pmm-font);

  /* --- Motion --- */
  --pmm-ease-standard:   cubic-bezier(0.20, 0.00, 0.00, 1.00);
  --pmm-ease-emphasized: cubic-bezier(0.30, 0.00, 0.80, 0.15);
  --pmm-ease-spring:     cubic-bezier(0.34, 1.56, 0.64, 1.00);
  --pmm-dur-instant:     90ms;
  --pmm-dur-short:       160ms;
  --pmm-dur-medium:      280ms;
  --pmm-dur-long:        480ms;

  color-scheme: light;
}

/* Dark mode — system preference, unless user opted into light explicitly */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --pmm-surface-0:       #0e0f1a;
    --pmm-surface-1:       #16182a;
    --pmm-surface-2:       #1c1f33;
    --pmm-surface-3:       #232743;
    --pmm-surface-overlay: rgba(22, 24, 42, 0.88);

    --pmm-border-subtle:   rgba(255, 255, 255, 0.06);
    --pmm-border-default:  rgba(255, 255, 255, 0.10);
    --pmm-border-strong:   rgba(255, 255, 255, 0.22);

    --pmm-text-primary:    #f1f0fa;
    --pmm-text-secondary:  #b4b5cc;
    /* Bumped from #797b95 (4:1, borderline AA) to #9395b4 (~6:1) so caption /
     * helper text passes WCAG AA on the dark surfaces. */
    --pmm-text-tertiary:   #9395b4;

    --pmm-brand-soft:      rgba(167, 139, 250, 0.16);
    --pmm-brand-softer:    rgba(167, 139, 250, 0.08);
    --pmm-brand-text:      #c4b5fd;

    --pmm-success-bg:      rgba(16, 185, 129, 0.18);
    --pmm-success-text:    #6ee7b7;
    --pmm-success-icon:    #6ee7b7;
    --pmm-warn-bg:         rgba(245, 158, 11, 0.20);
    --pmm-warn-text:       #fcd34d;
    --pmm-warn-icon:       #fcd34d;
    --pmm-error-bg:        rgba(239, 68, 68, 0.20);
    --pmm-error-text:      #fca5a5;
    --pmm-error-icon:      #fca5a5;
    /* Info badges/links use the accent (cyan) — secondary accent gets real
     * surface area instead of being a defined-but-unused token. */
    --pmm-info-bg:         rgba(34, 211, 238, 0.18);
    --pmm-info-text:       #67e8f9;

    --pmm-focus-ring:      0 0 0 3px rgba(167, 139, 250, 0.40);
    --pmm-elev-1:          0 1px 2px rgba(0, 0, 0, 0.50);
    --pmm-elev-2:          0 4px 16px rgba(0, 0, 0, 0.50), 0 1px 2px rgba(0, 0, 0, 0.30);
    --pmm-elev-3:          0 16px 48px rgba(0, 0, 0, 0.60), 0 2px 6px rgba(0, 0, 0, 0.35);
    --pmm-elev-brand:      0 8px 24px rgba(124, 58, 237, 0.50);
    --pmm-elev-soft:       0 1px 0 rgba(255, 255, 255, 0.04) inset,
                           0 1px 2px rgba(0, 0, 0, 0.40);

    color-scheme: dark;
  }
}

/* Manual override — wins over system */
:root[data-theme="dark"] {
  --pmm-surface-0:       #0e0f1a;
  --pmm-surface-1:       #16182a;
  --pmm-surface-2:       #1c1f33;
  --pmm-surface-3:       #232743;
  --pmm-surface-overlay: rgba(22, 24, 42, 0.88);
  --pmm-border-subtle:   rgba(255, 255, 255, 0.06);
  --pmm-border-default:  rgba(255, 255, 255, 0.10);
  --pmm-border-strong:   rgba(255, 255, 255, 0.22);
  --pmm-text-primary:    #f1f0fa;
  --pmm-text-secondary:  #b4b5cc;
  --pmm-text-tertiary:   #9395b4;
  --pmm-brand-soft:      rgba(167, 139, 250, 0.16);
  --pmm-brand-softer:    rgba(167, 139, 250, 0.08);
  --pmm-brand-text:      #c4b5fd;
  --pmm-success-bg:      rgba(16, 185, 129, 0.18);
  --pmm-success-text:    #6ee7b7;
  --pmm-success-icon:    #6ee7b7;
  --pmm-warn-bg:         rgba(245, 158, 11, 0.20);
  --pmm-warn-text:       #fcd34d;
  --pmm-warn-icon:       #fcd34d;
  --pmm-error-bg:        rgba(239, 68, 68, 0.20);
  --pmm-error-text:      #fca5a5;
  --pmm-error-icon:      #fca5a5;
  --pmm-info-bg:         rgba(34, 211, 238, 0.18);
  --pmm-info-text:       #67e8f9;
  --pmm-focus-ring:      0 0 0 3px rgba(167, 139, 250, 0.40);
  --pmm-elev-1:          0 1px 2px rgba(0, 0, 0, 0.50);
  --pmm-elev-2:          0 4px 16px rgba(0, 0, 0, 0.50), 0 1px 2px rgba(0, 0, 0, 0.30);
  --pmm-elev-3:          0 16px 48px rgba(0, 0, 0, 0.60), 0 2px 6px rgba(0, 0, 0, 0.35);
  --pmm-elev-brand:      0 8px 24px rgba(124, 58, 237, 0.50);
  --pmm-elev-soft:       0 1px 0 rgba(255, 255, 255, 0.04) inset,
                         0 1px 2px rgba(0, 0, 0, 0.40);
  color-scheme: dark;
}

/* Reduced motion — zero everything (system-respecting) */
@media (prefers-reduced-motion: reduce) {
  :root {
    --pmm-dur-instant: 0ms;
    --pmm-dur-short:   0ms;
    --pmm-dur-medium:  0ms;
    --pmm-dur-long:    0ms;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0ms !important;
    scroll-behavior: auto !important;
  }
}

/* ============================================================
 * 2. LUMO BRIDGE
 * ============================================================ */

html {
  --lumo-primary-color:           var(--pmm-brand);
  --lumo-primary-color-50pct:     rgba(124, 58, 237, 0.5);
  --lumo-primary-color-10pct:     var(--pmm-brand-soft);
  --lumo-primary-text-color:      var(--pmm-brand-text);
  --lumo-primary-contrast-color:  var(--pmm-text-on-brand);

  --lumo-error-color:        var(--pmm-error);
  --lumo-error-color-50pct:  rgba(239, 68, 68, 0.5);
  --lumo-error-color-10pct:  var(--pmm-error-bg);
  --lumo-error-text-color:   var(--pmm-error-text);

  --lumo-success-color:        var(--pmm-success);
  --lumo-success-color-50pct:  rgba(16, 185, 129, 0.5);
  --lumo-success-color-10pct:  var(--pmm-success-bg);
  --lumo-success-text-color:   var(--pmm-success-text);

  --lumo-border-radius-s: var(--pmm-shape-xs);
  --lumo-border-radius-m: var(--pmm-shape-sm);
  --lumo-border-radius-l: var(--pmm-shape-md);

  --lumo-font-family: var(--pmm-font);
  --lumo-font-size-xs: 11px;
  --lumo-font-size-s:  13px;
  --lumo-font-size-m:  14px;
  --lumo-font-size-l:  16px;
  --lumo-font-size-xl: 20px;
  --lumo-font-size-xxl: 28px;
  --lumo-font-size-xxxl: 40px;

  --lumo-line-height-s: 1.4;
  --lumo-line-height-m: 1.55;

  --lumo-base-color:     var(--pmm-surface-1);
  --lumo-tint-5pct:      var(--pmm-surface-2);
  --lumo-contrast-5pct:  var(--pmm-surface-2);
  --lumo-contrast-10pct: var(--pmm-surface-3);

  /* Text-color bridges — without these, every chrome `Span` styled
   * with `var(--lumo-secondary-text-color)` (the Vaadin idiom) falls
   * through to Lumo's default rgba-on-current-bg, which goes invisible
   * once we override --lumo-base-color in dark mode. The login form
   * subtitle was the most visible casualty. */
  --lumo-body-text-color:      var(--pmm-text-primary);
  --lumo-secondary-text-color: var(--pmm-text-secondary);
  --lumo-tertiary-text-color:  var(--pmm-text-tertiary);
  --lumo-disabled-text-color:  var(--pmm-text-tertiary);
  --lumo-header-text-color:    var(--pmm-text-primary);
}

/* Light-mode-only shade overrides — see Round 4 note. */
html:not([theme="dark"]) {
  --lumo-shade-5pct:  rgba(17, 18, 38, 0.04);
  --lumo-shade-10pct: rgba(17, 18, 38, 0.06);
}

html, body {
  background: var(--pmm-surface-0);
  color: var(--pmm-text-primary);
  font-family: var(--pmm-font);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

/* ============================================================
 * 3. CHROME COMPONENTS — admin / merchant portal
 * ============================================================ */

/* --- Top bar with backdrop blur --- */
vaadin-app-layout::part(navbar) {
  background: var(--pmm-surface-overlay);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  backdrop-filter: saturate(180%) blur(14px);
  border-bottom: 1px solid var(--pmm-border-subtle);
  box-shadow: 0 1px 0 rgba(17, 18, 38, 0.02);
}

/* --- Drawer / sidebar --- */
vaadin-app-layout::part(drawer) {
  background: var(--pmm-surface-1);
  border-right: 1px solid var(--pmm-border-subtle);
  width: 256px;
}

/* Side-nav items: smooth color/transform on hover, left accent on active */
vaadin-side-nav-item::part(item) {
  border-radius: var(--pmm-shape-sm);
  margin: 1px 6px;
  padding: 6px 10px;
  position: relative;
  color: var(--pmm-text-secondary);
  transition:
    background var(--pmm-dur-short) var(--pmm-ease-standard),
    color      var(--pmm-dur-short) var(--pmm-ease-standard),
    transform  var(--pmm-dur-short) var(--pmm-ease-standard);
}
vaadin-side-nav-item::part(item):hover {
  background: var(--pmm-surface-2);
  color: var(--pmm-text-primary);
}
vaadin-side-nav-item[active]::part(item) {
  background: var(--pmm-brand-soft);
  color: var(--pmm-brand-text);
  font-weight: 600;
}
vaadin-side-nav-item[active]::part(item)::before {
  content: "";
  position: absolute;
  left: -6px;
  top: 8px;
  bottom: 8px;
  width: 3px;
  border-radius: 0 3px 3px 0;
  background: var(--pmm-brand);
  animation: pmm-nav-accent-in var(--pmm-dur-medium) var(--pmm-ease-spring) both;
}
@keyframes pmm-nav-accent-in {
  from { transform: scaleY(0.2); opacity: 0; }
  to   { transform: scaleY(1);   opacity: 1; }
}
vaadin-side-nav-item vaadin-icon {
  transition: color var(--pmm-dur-short) var(--pmm-ease-standard),
              transform var(--pmm-dur-medium) var(--pmm-ease-spring);
}
vaadin-side-nav-item:hover vaadin-icon { color: var(--pmm-brand); transform: scale(1.08); }

/* Keep items within the drawer: a long label was pushing the expand chevron
   off the right edge (clipped by the 256px drawer), so parent groups looked
   like they had no children. Constrain the nav, let the label shrink and
   ellipsize, pin the toggle, and make the chevron clearly visible. */
vaadin-side-nav { width: 100%; box-sizing: border-box; }
vaadin-side-nav-item::part(content) { overflow: hidden; }
vaadin-side-nav-item::part(link) {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
vaadin-side-nav-item::part(toggle-button) {
  flex: 0 0 auto;
  color: var(--pmm-text-secondary);
  opacity: 1;
}
vaadin-side-nav-item:hover::part(toggle-button) { color: var(--pmm-brand); }

/* --- Page mount: every route fades + slides in --- */
vaadin-app-layout > [slot="main"] > * {
  animation: pmm-page-mount var(--pmm-dur-medium) var(--pmm-ease-standard) both;
}
@keyframes pmm-page-mount {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* --- Headings --- */
h1, h2, h3 { margin-top: 0; color: var(--pmm-text-primary); }
h2 {
  font: 600 22px/30px var(--pmm-font);
  letter-spacing: -0.2px;
  margin-bottom: 4px;
}

/* --- Buttons (all variants get a polish) --- */
vaadin-button {
  border-radius: var(--pmm-shape-sm);
  font-weight: 500;
  letter-spacing: 0.1px;
  transition:
    background var(--pmm-dur-short) var(--pmm-ease-standard),
    color      var(--pmm-dur-short) var(--pmm-ease-standard),
    box-shadow var(--pmm-dur-short) var(--pmm-ease-standard),
    transform  var(--pmm-dur-instant) var(--pmm-ease-standard);
}
vaadin-button:not([disabled]):active { transform: scale(0.97); }

vaadin-button[theme~="primary"] {
  background: var(--pmm-brand-gradient);
  color: var(--pmm-text-on-brand);
  box-shadow: var(--pmm-elev-brand);
}
vaadin-button[theme~="primary"]:hover {
  filter: brightness(1.06);
  box-shadow: 0 12px 28px rgba(124, 58, 237, 0.36);
  transform: translateY(-1px);
}
vaadin-button[theme~="primary"]:focus-visible {
  outline: 0;
  box-shadow: var(--pmm-elev-brand), var(--pmm-focus-ring);
}
/* The gradient above also painted disabled primary buttons, so "Approve" looked
   clickable while it was waiting for a required tick. Disabled must look disabled. */
vaadin-button[theme~="primary"][disabled] {
  background: var(--pmm-surface-3);
  color: var(--pmm-text-tertiary);
  box-shadow: none;
  filter: none;
  transform: none;
  cursor: not-allowed;
}

vaadin-button[theme~="tertiary"] {
  color: var(--pmm-text-secondary);
}
vaadin-button[theme~="tertiary"]:hover {
  background: var(--pmm-surface-2);
  color: var(--pmm-text-primary);
}

vaadin-button[theme~="error"][theme~="primary"] {
  background: linear-gradient(135deg, #dc2626 0%, #ef4444 100%);
  box-shadow: 0 8px 20px rgba(239, 68, 68, 0.28);
}

/* Icon-only buttons (drawer toggle, theme toggle in chrome) */
vaadin-button[theme~="icon"] {
  min-width: 36px;
  min-height: 36px;
  border-radius: var(--pmm-shape-sm);
}

/* --- Inputs (chrome-wide focus ring) --- */
vaadin-text-field::part(input-field),
vaadin-email-field::part(input-field),
vaadin-password-field::part(input-field),
vaadin-number-field::part(input-field),
vaadin-integer-field::part(input-field),
vaadin-text-area::part(input-field),
vaadin-date-picker::part(input-field),
vaadin-time-picker::part(input-field),
vaadin-date-time-picker::part(input-field),
vaadin-combo-box::part(input-field),
vaadin-select::part(input-field) {
  border-radius: var(--pmm-shape-sm);
  background: var(--pmm-surface-1);
  border: 1px solid var(--pmm-border-default);
  box-shadow: none;
  transition:
    border-color var(--pmm-dur-short) var(--pmm-ease-standard),
    box-shadow   var(--pmm-dur-short) var(--pmm-ease-standard);
}
vaadin-text-field[focused]::part(input-field),
vaadin-email-field[focused]::part(input-field),
vaadin-password-field[focused]::part(input-field),
vaadin-number-field[focused]::part(input-field),
vaadin-integer-field[focused]::part(input-field),
vaadin-text-area[focused]::part(input-field),
vaadin-date-picker[focused]::part(input-field),
vaadin-time-picker[focused]::part(input-field),
vaadin-date-time-picker[focused]::part(input-field),
vaadin-combo-box[focused]::part(input-field),
vaadin-select[focused]::part(input-field) {
  border-color: var(--pmm-brand);
  box-shadow: var(--pmm-focus-ring);
}

/* --- Grid (rows lift on hover; subtle row stripes) --- */
vaadin-grid {
  border-radius: var(--pmm-shape-md);
  border: 1px solid var(--pmm-border-subtle);
  overflow: hidden;
  background: var(--pmm-surface-1);
  box-shadow: var(--pmm-elev-1);
}
vaadin-grid::part(header-cell) {
  background: var(--pmm-surface-2);
  font-weight: 600;
  font-size: 12px;
  letter-spacing: 0.3px;
  color: var(--pmm-text-secondary);
  text-transform: uppercase;
}
vaadin-grid::part(row):hover {
  background: var(--pmm-brand-softer);
}
vaadin-grid::part(cell) {
  transition: background var(--pmm-dur-short) var(--pmm-ease-standard);
}

/* --- Dialog / confirm dialog --- */
vaadin-dialog-overlay::part(overlay),
vaadin-confirm-dialog-overlay::part(overlay) {
  border-radius: var(--pmm-shape-lg);
  box-shadow: var(--pmm-elev-3);
  background: var(--pmm-surface-1);
  animation: pmm-dialog-mount var(--pmm-dur-medium) var(--pmm-ease-spring) both;
}
@keyframes pmm-dialog-mount {
  from { opacity: 0; transform: translateY(-8px) scale(0.96); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

/* --- Notification --- */
vaadin-notification-card {
  border-radius: var(--pmm-shape-md);
  box-shadow: var(--pmm-elev-2);
  border: 1px solid var(--pmm-border-subtle);
  font-weight: 500;
  /* Keep toasts readable: cap the width and wrap long messages instead of
     stretching across the viewport and clipping the text. */
  max-width: min(460px, calc(100vw - 32px));
  white-space: normal;
  overflow-wrap: anywhere;
}
vaadin-notification-card [part="content"] { white-space: normal; }

/* --- Tabs --- */
vaadin-tab[selected]::part(focus-ring) { display: none; }
vaadin-tab {
  font-weight: 500;
  color: var(--pmm-text-secondary);
  transition: color var(--pmm-dur-short) var(--pmm-ease-standard);
}
vaadin-tab[selected] { color: var(--pmm-brand-text); font-weight: 600; }
vaadin-tabs {
  box-shadow: inset 0 -1px 0 var(--pmm-border-subtle);
}

/* --- Status badges (existing markup keeps working) --- */
.pmm-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 10px;
  border-radius: var(--pmm-shape-pill);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.2px;
  line-height: 1.4;
}
.pmm-badge--success { background: var(--pmm-success-bg); color: var(--pmm-success-text); }
.pmm-badge--error   { background: var(--pmm-error-bg);   color: var(--pmm-error-text); }
.pmm-badge--warn    { background: var(--pmm-warn-bg);    color: var(--pmm-warn-text); }
.pmm-badge--info    { background: var(--pmm-info-bg);    color: var(--pmm-info-text); }
.pmm-badge--neutral { background: var(--pmm-border-subtle); color: var(--pmm-text-secondary); }
.pmm-badge::before {
  content: "";
  width: 6px; height: 6px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.85;
}

/* --- Empty-state block --- */
.pmm-empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: var(--lumo-space-xl);
  text-align: center;
  color: var(--pmm-text-secondary);
}
.pmm-empty-state__icon {
  width: 56px; height: 56px;
  border-radius: 50%;
  background: var(--pmm-brand-soft);
  color: var(--pmm-brand);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: var(--lumo-space-m);
  animation: pmm-pulse-soft 2.4s ease-in-out infinite;
}
@keyframes pmm-pulse-soft {
  0%, 100% { box-shadow: 0 0 0 0 rgba(124, 58, 237, 0.16); }
  50%      { box-shadow: 0 0 0 14px rgba(124, 58, 237, 0); }
}
.pmm-empty-state h3 {
  margin: 0 0 var(--lumo-space-xs) 0;
  color: var(--pmm-text-primary);
}
.pmm-empty-state p {
  margin: 0 0 var(--lumo-space-m) 0;
  max-width: 380px;
}

/* --- KPI card (lift + sheen on hover, tabular numbers) --- */
.pmm-kpi {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  background: var(--pmm-surface-1);
  border: 1px solid var(--pmm-border-subtle);
  border-radius: var(--pmm-shape-md);
  padding: 20px 22px;
  box-shadow: var(--pmm-elev-1);
  position: relative;
  overflow: hidden;
  transition:
    transform   var(--pmm-dur-short) var(--pmm-ease-standard),
    box-shadow  var(--pmm-dur-short) var(--pmm-ease-standard),
    border-color var(--pmm-dur-short) var(--pmm-ease-standard);
}
.pmm-kpi::after {
  /* subtle brand gradient sheen on hover */
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 100% 0%, var(--pmm-brand-soft), transparent 60%);
  opacity: 0;
  transition: opacity var(--pmm-dur-medium) var(--pmm-ease-standard);
  pointer-events: none;
}
.pmm-kpi:hover {
  transform: translateY(-2px);
  box-shadow: var(--pmm-elev-2);
  border-color: var(--pmm-border-default);
}
.pmm-kpi:hover::after { opacity: 1; }
.pmm-kpi__label {
  color: var(--pmm-text-secondary);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.3px;
  text-transform: uppercase;
}
.pmm-kpi__value {
  font-size: 28px;
  font-weight: 600;
  margin-top: 4px;
  color: var(--pmm-text-primary);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.4px;
}
.pmm-kpi__hint {
  font-size: 12px;
  color: var(--pmm-text-tertiary);
  margin-top: 6px;
}

/* Hide Vaadin's dev-mode banner */
vaadin-dev-tools { display: none !important; }

/* ============================================================
 * 4. LOGIN — animated mesh hero
 * ============================================================ */

/* ===========================================================================
 * Login screen — HTML+Vaadin hybrid, lifted to high fidelity vs Stitch v1.
 *
 * Layout: .pmm-login (root Div, fills viewport)
 *   └── .pmm-login__main (flex row split 55/45)
 *         ├── .pmm-login__hero (Html block — left dark hero)
 *         └── .pmm-login__form (Java Div — right form panel)
 *   └── .pmm-login__global-foot (Html block — sticky pill footer)
 * =========================================================================== */
.pmm-login {
  position: relative;
  min-height: 100vh;
  display: block;
  background: var(--pmm-surface-1);
}
.pmm-login__main {
  display: flex;
  min-height: 100vh;
  width: 100%;
  overflow: hidden;
}

/* --- Hero (left 55%) — dark mesh, decorative orbs + noise overlay. --- */
.pmm-login__hero {
  flex: 1 1 55%;
  min-width: 0;
  position: relative;
  overflow: hidden;
  padding: 48px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  background-color: #0F1117;
  background-image:
    radial-gradient(at 0% 0%,    hsla(263, 85%, 33%, 0.40) 0, transparent 50%),
    radial-gradient(at 100% 0%,  hsla(188, 94%, 43%, 0.25) 0, transparent 50%),
    radial-gradient(at 100% 100%, hsla(263, 85%, 33%, 0.30) 0, transparent 50%),
    radial-gradient(at 0% 100%,  hsla(188, 94%, 43%, 0.20) 0, transparent 50%);
  color: #fff;
}
/* Subtle noise/grain overlay so the hero doesn't look like a flat
 * gradient — replaces Stitch's external mix-blend-overlay PNG with an
 * inline SVG fractal noise filter. Pure CSS, no network request. */
.pmm-login__hero-noise {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0.35;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0.55 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
  z-index: 0;
}
/* Drifting glow orbs — bigger, softer, slower than v1. */
.pmm-login__hero-orb {
  position: absolute;
  border-radius: 50%;
  filter: blur(110px);
  pointer-events: none;
  z-index: 0;
}
.pmm-login__hero-orb--violet {
  width: 520px; height: 520px;
  background: rgba(124, 58, 237, 0.40);
  top: -140px; left: -120px;
  animation: pmm-blob-drift-a 22s var(--pmm-ease-standard) infinite alternate;
}
.pmm-login__hero-orb--cyan {
  width: 420px; height: 420px;
  background: rgba(6, 182, 212, 0.28);
  bottom: -140px; right: -100px;
  animation: pmm-blob-drift-b 26s var(--pmm-ease-standard) infinite alternate;
}
@keyframes pmm-blob-drift-a {
  from { transform: translate(0, 0) scale(1); }
  to   { transform: translate(50px, 70px) scale(1.12); }
}
@keyframes pmm-blob-drift-b {
  from { transform: translate(0, 0) scale(1); }
  to   { transform: translate(-60px, -50px) scale(1.18); }
}
/* Stack content above the decorative orbs/noise. We DON'T use a
 * `.pmm-login__hero > *` selector here because that has higher
 * specificity than `.pmm-login__hero-noise` / `.pmm-login__hero-orb`
 * (class + universal beats single class), and would force their
 * position:absolute back to relative — collapsing them into the flex
 * flow and pushing the content to the bottom of the hero. Apply
 * z-index/position only on the content containers instead. */
.pmm-login__hero-top,
.pmm-login__hero-middle,
.pmm-login__hero-foot-wrap {
  position: relative;
  z-index: 1;
}

/* Hero — top wordmark. */
.pmm-login__hero-top { z-index: 1; }
.pmm-login__hero-brand {
  font-size: 18px;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: #fff;
}

/* Hero — middle stack (display headline + body + bullets). */
.pmm-login__hero-middle {
  max-width: 540px;
  z-index: 1;
  animation: pmm-page-mount 0.6s var(--pmm-ease-standard) both;
}
.pmm-login__hero-headline {
  font-size: 44px;
  font-weight: 700;
  line-height: 52px;
  letter-spacing: -0.02em;
  color: #fff;
  margin: 0 0 16px 0;
}
.pmm-login__hero-body {
  font-size: 16px;
  line-height: 24px;
  color: rgba(255, 255, 255, 0.80);
  margin: 0 0 32px 0;
}
.pmm-login__hero-bullets {
  list-style: none;
  padding: 0;
  margin: 0;
}
.pmm-login__hero-bullets li {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  margin-top: 12px;
  font-size: 14px;
  line-height: 20px;
  color: rgba(255, 255, 255, 0.90);
}
/* Cyan glow bullet — replaces VaadinIcon dot for the feature list. */
.pmm-login__bullet-dot {
  width: 8px; height: 8px;
  border-radius: 9999px;
  background: #06B6D4;
  box-shadow: 0 0 8px rgba(6, 182, 212, 0.65);
  flex: 0 0 8px;
  margin-top: 6px;
}

/* Hero — bottom note. */
.pmm-login__hero-foot-wrap {
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 12px;
  align-items: flex-start;
}
.pmm-login__hero-foot {
  font-size: 12px;
  line-height: 16px;
  color: rgba(255, 255, 255, 0.60);
}

/* Developer-docs chip on the login hero. Pulls the integration
   audience without poaching the headline space — sits below the
   PCI-adjacent note as a subtle violet/cyan tinted pill. */
.pmm-login__hero-dev {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 9px 14px;
  background: rgba(109, 76, 255, 0.14);
  border: 1px solid rgba(109, 76, 255, 0.35);
  border-radius: 9999px;
  color: rgba(255, 255, 255, 0.92);
  font-size: 12.5px;
  line-height: 16px;
  text-decoration: none;
  transition: background-color 160ms ease, border-color 160ms ease, transform 120ms ease;
  max-width: 100%;
}
.pmm-login__hero-dev:hover {
  background: rgba(109, 76, 255, 0.22);
  border-color: rgba(109, 76, 255, 0.55);
  transform: translateY(-1px);
}
.pmm-login__hero-dev strong {
  font-weight: 600;
  color: white;
  margin-right: 4px;
}
.pmm-login__hero-dev-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 6px;
  background: rgba(0, 188, 212, 0.20);
  color: #67e8f9;
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 11px;
  font-weight: 600;
  flex-shrink: 0;
}

/* --- Form panel (right 45%). --- */
.pmm-login__form {
  flex: 1 1 45%;
  min-width: 400px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: var(--pmm-surface-1);
  position: relative;
}
.pmm-login__form-inner {
  width: 100%;
  max-width: 400px;
  animation: pmm-page-mount 0.6s var(--pmm-ease-standard) 0.1s both;
}
.pmm-login__theme-toggle {
  position: absolute;
  top: 16px;
  right: 16px;
}

/* Form panel — Vaadin LoginForm restyled to match Stitch. */
.pmm-login__form vaadin-text-field::part(input-field),
.pmm-login__form vaadin-password-field::part(input-field),
.pmm-login__form vaadin-email-field::part(input-field) {
  border-radius: 12px;
  border: 1.5px solid var(--pmm-border-default);
  background: var(--pmm-surface-0);
  height: 44px;
  transition: border-color 200ms ease, box-shadow 200ms ease;
}
.pmm-login__form vaadin-text-field[focused]::part(input-field),
.pmm-login__form vaadin-password-field[focused]::part(input-field),
.pmm-login__form vaadin-email-field[focused]::part(input-field) {
  border-color: #7C3AED;
  box-shadow: 0 0 0 3px rgba(124, 58, 237, 0.20);
}
.pmm-login__form vaadin-button[theme~="primary"] {
  width: 100%;
  height: 48px;
  font-size: 15px;
  font-weight: 600;
  border-radius: 14px;
  background: #7C3AED;
  box-shadow: 0 4px 12px rgba(124, 58, 237, 0.20);
  transition: background 200ms ease, transform 100ms ease, box-shadow 200ms ease;
}
.pmm-login__form vaadin-button[theme~="primary"]:hover {
  background: #6D28D9;
  box-shadow: 0 6px 16px rgba(124, 58, 237, 0.28);
}
.pmm-login__form vaadin-button[theme~="primary"]:active {
  transform: scale(0.98);
}

/* Form panel — brand block, headline, subtitle. */
.pmm-login__brand {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 24px;
}
.pmm-login__brand-dot {
  width: 10px; height: 10px;
  border-radius: 9999px;
  background: #7C3AED;
}
.pmm-login__brand-name {
  font-size: 18px;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--pmm-text-primary);
}
.pmm-login__welcome {
  margin: 0 0 4px 0;
  font-size: 24px;
  font-weight: 600;
  line-height: 32px;
  color: var(--pmm-text-primary);
}
.pmm-login__welcome-sub {
  color: var(--pmm-text-secondary);
  margin: 0 0 24px 0;
  font-size: 14px;
  line-height: 20px;
}

/* Footer rows under the login form: helper hint + trust strip. */
.pmm-login__footer-hint {
  margin-top: 24px;
  padding-top: 24px;
  border-top: 1px solid var(--pmm-border-subtle);
  text-align: center;
  font-size: 12px;
  color: var(--pmm-text-secondary);
}
.pmm-login__trust {
  margin-top: 48px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}
.pmm-login__trust-label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: rgba(91, 100, 120, 0.55);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.pmm-login__trust-label svg { width: 14px; height: 14px; }
.pmm-login__trust-marks {
  display: flex;
  gap: 12px;
  opacity: 0.40;
}
.pmm-login__trust-mark {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.05em;
  color: var(--pmm-text-secondary);
  padding: 3px 8px;
  border: 1px solid var(--pmm-border-subtle);
  border-radius: 4px;
}

/* --- Sticky global pill footer (Stitch parity). --- */
.pmm-login__global-foot {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 16px 24px;
  display: flex;
  justify-content: center;
  align-items: center;
  pointer-events: none;
  z-index: 5;
}
.pmm-login__global-pill {
  pointer-events: auto;
  display: inline-flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  padding: 10px 20px;
  border-radius: 9999px;
  /* Solid-ish backdrop with a touch of blur — keeps the readable
     contrast on top of the violet+cyan mesh hero (translucent backdrops
     wash the text out against a bright gradient). */
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: saturate(180%) blur(12px);
  -webkit-backdrop-filter: saturate(180%) blur(12px);
  border: 1px solid var(--pmm-border-subtle);
  box-shadow: 0 4px 18px rgba(15, 23, 42, 0.10);
  font-size: 13px;
  color: var(--pmm-text-primary);
}
.pmm-login__global-foot-copy {
  font-size: 13px;
  color: var(--pmm-text-secondary);
}
.pmm-login__global-foot-sep {
  color: var(--pmm-text-tertiary);
  opacity: 0.6;
  user-select: none;
}
.pmm-login__global-foot-link {
  font-size: 13px;
  font-weight: 500;
  color: var(--pmm-brand, #6f5cff);
  text-decoration: none;
  transition: color 150ms ease, text-decoration-color 150ms ease;
  text-decoration: underline;
  text-decoration-color: transparent;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}
.pmm-login__global-foot-link:hover {
  color: #5b21b6;
  text-decoration-color: currentColor;
}
.pmm-login__global-foot-link:focus-visible {
  outline: 2px solid var(--pmm-brand, #6f5cff);
  outline-offset: 3px;
  border-radius: 4px;
}

/* Kept for future use (e.g. if a legal page is temporarily unpublished
   and we want to render it as a visible-but-disabled chip). Today all
   four links point at real routes, so this class isn't applied. */
.pmm-login__global-foot-link--disabled,
.pmm-login__global-foot-link--disabled:hover {
  color: var(--pmm-text-tertiary);
  opacity: 0.55;
  cursor: not-allowed;
  text-decoration: underline dotted;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}

/* Dark mode — the pill needs a much stronger backdrop so links above
   the dark mesh hero stay legible. Previous 0.75 alpha was too dim. */
:root[data-theme="dark"] .pmm-login__global-pill {
  background: rgba(15, 16, 32, 0.88);
  border-color: rgba(255, 255, 255, 0.12);
  box-shadow: 0 4px 18px rgba(0, 0, 0, 0.35);
  color: rgba(255, 255, 255, 0.92);
}
:root[data-theme="dark"] .pmm-login__global-foot-copy {
  color: rgba(255, 255, 255, 0.78);
}
:root[data-theme="dark"] .pmm-login__global-foot-sep {
  color: rgba(255, 255, 255, 0.35);
}
:root[data-theme="dark"] .pmm-login__global-foot-link {
  /* Lavender keeps the brand identity but reads cleanly on the dark
     pill. Plain violet (#6f5cff) is too dark against the backdrop. */
  color: #c4b5fd;
}
:root[data-theme="dark"] .pmm-login__global-foot-link:hover {
  color: #ffffff;
}

/* Hide hero on small screens */
@media (max-width: 900px) {
  .pmm-login__hero { display: none !important; }
  .pmm-login__form { flex: 1 !important; }
}

/* ============================================================
 * 5. PUBLIC PAYMENT-PAGE PRIMITIVES (.pmm-pay-*) — kept stable
 *    from Round 4 so existing markup keeps working.
 * ============================================================ */

.pmm-pay-page {
  background:
    radial-gradient(circle at 20% -20%, rgba(124, 58, 237, 0.10), transparent 50%),
    radial-gradient(circle at 90% 110%, rgba(167, 139, 250, 0.10), transparent 50%),
    var(--pmm-surface-0);
  /* Override Vaadin's setSizeFull() inline height:100% — public pay surfaces
   * must grow with content so short browser windows can scroll, never clip
   * the bottom of the form / link / hosted card. */
  height: auto !important;
  min-height: 100vh;
}

/* Ensure the entire route chain above .pmm-pay-page allows the document
 * to grow + scroll. Vaadin's flow-container-root and <body> are pinned
 * to height:100% by default, which would otherwise trap an overflowing
 * .pmm-pay-page. We only enable this when a public-pay surface is on
 * the page, so chrome routes (admin / merchant) keep their app-shell
 * full-viewport behavior. */
html:has(.pmm-pay-page),
body:has(.pmm-pay-page) {
  height: auto !important;
  min-height: 100vh;
  overflow-y: auto !important;
}
/* Vaadin renders the route inside a custom element named
 * `flow-container-root-<random>` whose tag name changes between deploys.
 * It is always the first child of <body>, so :first-child is the safest
 * selector that doesn't accidentally hit overlay containers (notifications,
 * dialogs, dev-tools). */
body:has(.pmm-pay-page) > :first-child {
  height: auto !important;
  min-height: 100vh;
}

.pmm-pay-card {
  background: var(--pmm-surface-1);
  border-radius: 18px;
  border: 1px solid var(--pmm-border-subtle);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.6) inset,
    0 8px 28px rgba(15, 17, 23, 0.06),
    0 24px 64px rgba(15, 17, 23, 0.05);
  padding: 32px 36px 32px;
  width: 100%;
  max-width: 580px;
  position: relative;
  overflow: hidden;
  font-family: var(--pmm-font);
  color: var(--pmm-text-primary);
  animation: pmm-card-mount var(--pmm-dur-medium) var(--pmm-ease-standard) both;
}
/* Mesh-gradient sliver across the top edge — gives the card a branded
 * hero feel without taking over the layout. Mirrors Stitch's mesh strip
 * pattern but contained to a 4px accent. */
.pmm-pay-card::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 4px;
  background: linear-gradient(
    90deg,
    #7C3AED 0%,
    #A78BFA 35%,
    #06B6D4 75%,
    #67E8F9 100%
  );
  opacity: 0.85;
}
@keyframes pmm-card-mount {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Header row — merchant chip on the left, security chip + theme toggle
 * on the right. Slightly more breathing room after the gradient strip. */
.pmm-pay-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 22px;
  padding-top: 4px;
}

.pmm-pay-merchant {
  display: flex;
  align-items: center;
  gap: 12px;
  color: var(--pmm-text-primary);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.005em;
}
.pmm-pay-merchant__logo {
  width: 36px; height: 36px;
  border-radius: 50%;
  object-fit: contain;
  background: #fff;
  border: 2px solid #fff;
  padding: 0;
  box-shadow:
    0 0 0 2px rgba(124, 58, 237, 0.12),
    0 2px 6px rgba(15, 17, 23, 0.12);
}

.pmm-pay-header__chips {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.pmm-pay-secure-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 8px 3px 6px;
  background: var(--pmm-success-bg);
  color: var(--pmm-success-text);
  border-radius: var(--pmm-shape-pill);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.3px;
}
.pmm-pay-secure-chip::before {
  content: "\1F512";
  font-size: 10px;
}

.pmm-pay-theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px; height: 32px;
  border-radius: var(--pmm-shape-pill);
  background: transparent;
  border: 1px solid var(--pmm-border-subtle);
  color: var(--pmm-text-secondary);
  cursor: pointer;
  transition:
    background    var(--pmm-dur-short) var(--pmm-ease-standard),
    color         var(--pmm-dur-short) var(--pmm-ease-standard),
    border-color  var(--pmm-dur-short) var(--pmm-ease-standard);
}
.pmm-pay-theme-toggle:hover {
  background: var(--pmm-brand-soft);
  color: var(--pmm-brand-text);
  border-color: var(--pmm-brand-soft);
}
.pmm-pay-theme-toggle:focus-visible {
  outline: 2px solid var(--pmm-brand);
  outline-offset: 2px;
}
.pmm-pay-theme-toggle vaadin-icon {
  width: 16px; height: 16px;
  transition: transform var(--pmm-dur-medium) var(--pmm-ease-spring);
}

.pmm-pay-hero { margin: 0 0 22px 0; }
.pmm-pay-hero__eyebrow {
  text-transform: uppercase;
  letter-spacing: 0.9px;
  font-size: 11px;
  color: var(--pmm-text-tertiary);
  font-weight: 600;
  margin-bottom: 6px;
}
.pmm-pay-hero__title {
  font: var(--pmm-type-headline);
  color: var(--pmm-text-primary);
  margin: 0 0 4px 0;
  letter-spacing: -0.2px;
}
.pmm-pay-hero__description {
  color: var(--pmm-text-secondary);
  font-size: 14px;
  line-height: 1.5;
  margin: 0;
}
.pmm-pay-hero__amount {
  font: var(--pmm-type-display);
  color: var(--pmm-text-primary);
  margin: 10px 0 2px 0;
  letter-spacing: -0.5px;
  font-variant-numeric: tabular-nums;
}

/* Calm mesh-gradient hero — DESIGN.md pillar:
   "Public-pay surfaces also use a calmer version of the same mesh on hero cards."
   Three soft radial blooms in the brand palette (violet → cyan → soft purple)
   bleed into the card background; text stays on top with full readability. */
.pmm-pay-hero--mesh {
  position: relative;
  margin: -4px -4px 18px -4px;
  padding: 20px 22px 22px 22px;
  border-radius: 16px;
  background:
    radial-gradient(120% 90% at 8% 0%,  rgba(124, 58, 237, 0.18) 0%, transparent 55%),
    radial-gradient(110% 80% at 95% 10%, rgba(6,  182, 212, 0.16) 0%, transparent 60%),
    radial-gradient(100% 70% at 60% 100%, rgba(167, 139, 250, 0.14) 0%, transparent 65%),
    var(--pmm-surface-1);
  border: 1px solid var(--pmm-border-subtle);
  overflow: hidden;
}
.pmm-pay-hero--mesh::after {
  /* Faint top-edge highlight to give the band a luminous lift in both themes. */
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.35), transparent);
  pointer-events: none;
}
:root[data-theme="dark"] .pmm-pay-hero--mesh,
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .pmm-pay-hero--mesh {
    background:
      radial-gradient(120% 90% at 8% 0%,  rgba(124, 58, 237, 0.30) 0%, transparent 55%),
      radial-gradient(110% 80% at 95% 10%, rgba(6,  182, 212, 0.22) 0%, transparent 60%),
      radial-gradient(100% 70% at 60% 100%, rgba(167, 139, 250, 0.20) 0%, transparent 65%),
      var(--pmm-surface-1);
  }
}

.pmm-pay-divider {
  height: 1px;
  background: var(--pmm-border-subtle);
  margin: 22px 0;
  border: 0;
}

.pmm-pay-field-label {
  font-size: 11px;
  font-weight: 600;
  color: var(--pmm-text-tertiary);
  text-transform: uppercase;
  letter-spacing: 0.6px;
  margin-bottom: 4px;
  display: block;
}

.pmm-pay-card vaadin-text-field::part(input-field),
.pmm-pay-card vaadin-email-field::part(input-field),
.pmm-pay-card vaadin-number-field::part(input-field),
.pmm-pay-card vaadin-password-field::part(input-field),
.pmm-pay-card vaadin-text-area::part(input-field),
.pmm-pay-card vaadin-integer-field::part(input-field),
.pmm-pay-card vaadin-date-picker::part(input-field),
.pmm-pay-card vaadin-time-picker::part(input-field),
.pmm-pay-card vaadin-combo-box::part(input-field),
.pmm-pay-card vaadin-select::part(input-field) {
  background: var(--pmm-surface-1);
  border: 1.5px solid var(--pmm-border-default);
  border-radius: 10px;
  box-shadow: none;
  transition: border-color var(--pmm-dur-short) var(--pmm-ease-standard),
              box-shadow   var(--pmm-dur-short) var(--pmm-ease-standard);
}
.pmm-pay-card vaadin-text-field[focused]::part(input-field),
.pmm-pay-card vaadin-email-field[focused]::part(input-field),
.pmm-pay-card vaadin-number-field[focused]::part(input-field),
.pmm-pay-card vaadin-password-field[focused]::part(input-field),
.pmm-pay-card vaadin-text-area[focused]::part(input-field),
.pmm-pay-card vaadin-integer-field[focused]::part(input-field),
.pmm-pay-card vaadin-date-picker[focused]::part(input-field),
.pmm-pay-card vaadin-time-picker[focused]::part(input-field),
.pmm-pay-card vaadin-combo-box[focused]::part(input-field),
.pmm-pay-card vaadin-select[focused]::part(input-field) {
  border-color: var(--pmm-brand);
  box-shadow: var(--pmm-focus-ring);
}
.pmm-pay-card vaadin-text-field::part(label),
.pmm-pay-card vaadin-email-field::part(label),
.pmm-pay-card vaadin-number-field::part(label),
.pmm-pay-card vaadin-password-field::part(label),
.pmm-pay-card vaadin-text-area::part(label),
.pmm-pay-card vaadin-integer-field::part(label),
.pmm-pay-card vaadin-date-picker::part(label),
.pmm-pay-card vaadin-time-picker::part(label),
.pmm-pay-card vaadin-combo-box::part(label),
.pmm-pay-card vaadin-select::part(label) {
  font-size: 12px;
  font-weight: 600;
  color: var(--pmm-text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.pmm-pay-lineitem {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px 14px;
  background: var(--pmm-surface-2);
  border: 1px solid var(--pmm-border-subtle);
  border-radius: var(--pmm-shape-md);
  margin-bottom: 10px;
}
.pmm-pay-lineitem__name { flex-grow: 1; font-weight: 600; color: var(--pmm-text-primary); }
.pmm-pay-lineitem__price { color: var(--pmm-text-secondary); font-size: 13px; font-variant-numeric: tabular-nums; }
.pmm-pay-lineitem__sold {
  background: var(--pmm-error-bg);
  color: var(--pmm-error-text);
  font-size: 11px;
  font-weight: 700;
  padding: 3px 10px;
  border-radius: var(--pmm-shape-pill);
  letter-spacing: 0.4px;
}

/* ── Customer-facing pay surface: border-box, scoped ──────────────────────
 *
 * Reported symptom: the amount breakdown on the public payment form sat flush
 * against the right edge of its container.
 *
 * Cause: .pmm-pay-totals declares `padding: 18px 16px` plus a 1px border, and
 * PublicFormView gives it width:100% via setWidthFull(). With the default
 * content-box sizing that renders as 100% + 34px, so the element overflowed its
 * parent by 34px on the right. The left padding looked correct, which is what
 * made it read as "hugging the right" rather than as an overflow.
 *
 * There is no universal box-sizing reset in this stylesheet. The ones that exist
 * — .pmm-filter-card, .pmm-page > .pmm-list-header and a few others — were
 * clearly added one at a time as this same bug surfaced in each place. Fourteen
 * rules on this surface alone carry padding plus a border, so the next report was
 * only a matter of which element got a width next.
 *
 * Scoped to the pay prefix rather than declared globally: a `*` reset dropped
 * into a stylesheet this size would change many layouts at once, and this is the
 * surface where a layout bug is most expensive — it is what a paying customer
 * sees. Verified before applying that nothing here compensates with
 * width: calc(100% - Npx), which border-box would have broken.
 */
[class^="pmm-pay-"],
[class*=" pmm-pay-"] {
  box-sizing: border-box;
}

.pmm-pay-totals {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 18px 16px 12px 16px;
  background: var(--pmm-surface-2);
  border: 1px solid var(--pmm-border-subtle);
  border-radius: 14px;
  margin: 8px 0 4px 0;
}
.pmm-pay-totals__row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 14px;
  color: var(--pmm-text-secondary);
  font-variant-numeric: tabular-nums;
}
.pmm-pay-totals__row > :last-child {
  font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  color: var(--pmm-text-primary);
  font-weight: 500;
}
.pmm-pay-totals__row--total {
  padding-top: 12px;
  margin-top: 4px;
  border-top: 1px solid var(--pmm-border-default);
  font-size: 16px;
  font-weight: 600;
  color: var(--pmm-text-primary);
}
.pmm-pay-totals__row--total > :last-child {
  font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 22px;
  font-weight: 700;
  color: var(--pmm-brand);
  letter-spacing: -0.01em;
}

.pmm-pay-totals--collapsed .pmm-pay-totals__row:not(.pmm-pay-totals__row--total):not(.pmm-pay-totals__trigger-row) {
  display: none;
}

.pmm-pay-totals__trigger {
  background: none;
  border: 0;
  padding: 0;
  font: var(--pmm-type-body);
  color: var(--pmm-brand-text);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-weight: 600;
}
.pmm-pay-totals__trigger:hover { text-decoration: underline; }
.pmm-pay-totals__trigger:focus-visible {
  outline: 2px solid var(--pmm-brand);
  outline-offset: 2px;
  border-radius: 4px;
}
.pmm-pay-totals__trigger vaadin-icon {
  width: 14px; height: 14px;
  transition: transform var(--pmm-dur-short) var(--pmm-ease-standard);
}
.pmm-pay-totals--expanded .pmm-pay-totals__trigger vaadin-icon { transform: rotate(180deg); }
.pmm-pay-totals__trigger-row {
  display: flex;
  justify-content: flex-end;
  margin-top: 4px;
}

.pmm-pay-fee-info {
  display: inline-flex;
  align-items: center;
  margin-left: 6px;
  color: var(--pmm-text-tertiary);
  cursor: help;
}
.pmm-pay-fee-info vaadin-icon { width: 14px; height: 14px; }

.pmm-pay-disclose {
  display: flex;
  flex-direction: column;
  gap: 0;
}
.pmm-pay-disclose__trigger {
  background: none;
  border: 0;
  padding: 8px 0;
  font: var(--pmm-type-body-strong);
  color: var(--pmm-brand-text);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  text-align: left;
}
.pmm-pay-disclose__trigger:hover { text-decoration: underline; }
.pmm-pay-disclose__trigger:focus-visible {
  outline: 2px solid var(--pmm-brand);
  outline-offset: 2px;
  border-radius: 4px;
}
.pmm-pay-disclose__trigger vaadin-icon {
  width: 14px; height: 14px;
  transition: transform var(--pmm-dur-short) var(--pmm-ease-standard);
}
.pmm-pay-disclose--open .pmm-pay-disclose__trigger vaadin-icon { transform: rotate(180deg); }

.pmm-pay-disclose__panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--pmm-dur-medium) var(--pmm-ease-standard);
}
.pmm-pay-disclose__panel-inner {
  overflow: hidden;
  min-height: 0;
}
.pmm-pay-disclose--open .pmm-pay-disclose__panel { grid-template-rows: 1fr; }
.pmm-pay-disclose__panel-inner > * { margin-top: 8px; }

.pmm-pay-terms-body {
  font-size: 13px;
  color: var(--pmm-text-secondary);
  line-height: 1.55;
  background: var(--pmm-surface-2);
  padding: 12px 14px;
  border-radius: var(--pmm-shape-md);
  max-height: 220px;
  overflow-y: auto;
  border: 1px solid var(--pmm-border-subtle);
}

.pmm-pay-gateway-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 4px;
}
.pmm-pay-gateway {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  background: var(--pmm-surface-1);
  border: 1.5px solid var(--pmm-border-default);
  border-radius: var(--pmm-shape-md);
  cursor: pointer;
  transition:
    border-color var(--pmm-dur-short) var(--pmm-ease-standard),
    background   var(--pmm-dur-short) var(--pmm-ease-standard),
    transform    var(--pmm-dur-short) var(--pmm-ease-spring),
    box-shadow   var(--pmm-dur-short) var(--pmm-ease-standard);
  user-select: none;
}
.pmm-pay-gateway:hover {
  border-color: color-mix(in srgb, var(--pmm-brand) 40%, transparent);
  transform: translateY(-1px);
  box-shadow: var(--pmm-elev-1);
}
.pmm-pay-gateway--selected {
  border-color: var(--pmm-brand);
  background: var(--pmm-brand-softer);
  box-shadow: var(--pmm-focus-ring);
}
.pmm-pay-gateway__name {
  flex-grow: 1;
  font-weight: 600;
  color: var(--pmm-text-primary);
  font-size: 14px;
}
.pmm-pay-gateway__fee {
  color: var(--pmm-text-tertiary);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}
.pmm-pay-gateway__qr-badge {
  background: var(--pmm-surface-2);
  color: var(--pmm-text-secondary);
  font-size: 10px;
  font-weight: 700;
  padding: 3px 7px;
  border-radius: 4px;
  letter-spacing: 0.4px;
  border: 1px solid var(--pmm-border-subtle);
}
.pmm-pay-gateway__fee-line {
  /* The total-to-pay line on a scheme tile. Deliberately not the tiny QR
     pill — this is the figure the customer commits to, so it reads as plain,
     legible text with the amount emphasised. */
  display: block;
  width: 100%;
  margin-top: 4px;
  font-size: 13px;
  font-weight: 600;
  color: var(--pmm-text-primary);
}
.pmm-pay-gateway__radio {
  width: 20px; height: 20px;
  border: 2px solid var(--pmm-border-strong);
  border-radius: 50%;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: border-color var(--pmm-dur-short) var(--pmm-ease-standard);
}
.pmm-pay-gateway--selected .pmm-pay-gateway__radio { border-color: var(--pmm-brand); }
.pmm-pay-gateway--selected .pmm-pay-gateway__radio::after {
  content: "";
  width: 10px; height: 10px;
  border-radius: 50%;
  background: var(--pmm-brand);
  animation: pmm-radio-pop var(--pmm-dur-short) var(--pmm-ease-spring) both;
}
@keyframes pmm-radio-pop {
  from { transform: scale(0.4); opacity: 0; }
  to   { transform: scale(1);   opacity: 1; }
}

/* Gateway brand-marks (CSS-drawn) */
.pmm-brand-mark {
  width: 40px; height: 28px;
  border-radius: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 11px;
  color: #fff;
  letter-spacing: 0.3px;
  flex-shrink: 0;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.06);
}
.pmm-brand-mark--stripe     { background: linear-gradient(135deg, #635bff 0%, #8a83ff 100%); }
.pmm-brand-mark--paypal     { background: linear-gradient(135deg, #0070ba 0%, #009cde 100%); }
.pmm-brand-mark--worldpay   { background: linear-gradient(135deg, #e30613 0%, #ff4b5c 100%); }
.pmm-brand-mark--windcave   { background: linear-gradient(135deg, #005b99 0%, #0080c9 100%); }
.pmm-brand-mark--alipay     { background: linear-gradient(135deg, #1677ff 0%, #00a1e9 100%); }
.pmm-brand-mark--wechat     { background: linear-gradient(135deg, #09bb07 0%, #34d132 100%); }
.pmm-brand-mark--unionpay   { background: linear-gradient(135deg, #d9232d 0%, #002857 100%); }
.pmm-brand-mark--binance    { background: linear-gradient(135deg, #f0b90b 0%, #ffd23f 100%); color: #1a1325; }
.pmm-brand-mark--zip        { background: linear-gradient(135deg, #000 0%, #3a3a3a 100%); }
.pmm-brand-mark--poli       { background: linear-gradient(135deg, #00a6d7 0%, #33bfe3 100%); }
.pmm-brand-mark--centrapay  { background: linear-gradient(135deg, #00c9a7 0%, #4aefd4 100%); }
.pmm-brand-mark--payplus    { background: linear-gradient(135deg, #ff6f61 0%, #ffa29b 100%); }
.pmm-brand-mark--eway       { background: linear-gradient(135deg, #f7941d 0%, #ffb84d 100%); }
.pmm-brand-mark--upi        { background: linear-gradient(135deg, #008753 0%, #00b074 100%); }
.pmm-brand-mark--mypos      { background: linear-gradient(135deg, #0072c6 0%, #1e90e0 100%); }
.pmm-brand-mark--attractpay { background: linear-gradient(135deg, #ff9f1c 0%, #ffbf69 100%); }
.pmm-brand-mark--default    { background: var(--pmm-brand-gradient); }

/* Submit button on public pay-card — Stitch-parity 56px tall, 14px radius,
 * violet gradient with strong brand glow shadow, scale-down on click. */
.pmm-pay-submit {
  width: 100%;
  margin-top: 24px;
  min-height: 56px;
  font-size: 16px;
  font-weight: 600;
  letter-spacing: 0.2px;
  background: var(--pmm-brand-gradient);
  color: var(--pmm-text-on-brand);
  border-radius: 14px;
  box-shadow:
    0 8px 20px rgba(124, 58, 237, 0.30),
    0 2px 6px rgba(124, 58, 237, 0.20);
  transition: transform 100ms var(--pmm-ease-standard),
              box-shadow var(--pmm-dur-short) var(--pmm-ease-standard),
              filter     var(--pmm-dur-short) var(--pmm-ease-standard);
}
.pmm-pay-submit:hover {
  transform: translateY(-1px);
  box-shadow:
    0 12px 28px rgba(124, 58, 237, 0.40),
    0 4px 10px rgba(124, 58, 237, 0.25);
  filter: brightness(1.04);
}
.pmm-pay-submit:active { transform: scale(0.97); }
.pmm-pay-submit:focus-visible {
  outline: 2px solid var(--pmm-brand);
  outline-offset: 3px;
}

.pmm-pay-submit-sub {
  display: block;
  text-align: center;
  font-size: 12px;
  color: var(--pmm-text-tertiary);
  margin-top: 8px;
  min-height: 1.2em;
}

.pmm-pay-trust {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  margin-top: 18px;
  padding-top: 18px;
  border-top: 1px solid var(--pmm-border-subtle);
  color: var(--pmm-text-tertiary);
  font-size: 12px;
}
.pmm-pay-trust__item {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

/* ----------------------------------------------------------------
 * Stitch v1 polish — applied on top of the existing .pmm-pay-* base
 * to bring the public payment surfaces in line with the Stitch design
 * (Apple Pay sheet feel: filled inputs, calm trust footer, larger
 * violet total, slightly wider rounded primary). These rules override
 * specific properties; we keep the original structure so the
 * 1400-line PublicFormView wiring stays untouched.
 * --------------------------------------------------------------- */

/* Filled-style inputs — surface-container-low fill, no resting border,
 * 2px violet ring on focus. Matches Stitch's "calm form" styling. */
.pmm-pay-card vaadin-text-field::part(input-field),
.pmm-pay-card vaadin-email-field::part(input-field),
.pmm-pay-card vaadin-number-field::part(input-field),
.pmm-pay-card vaadin-password-field::part(input-field),
.pmm-pay-card vaadin-text-area::part(input-field),
.pmm-pay-card vaadin-integer-field::part(input-field) {
  background: var(--pmm-surface-2);
  border: 1px solid transparent;
  border-radius: var(--pmm-shape-md);
  transition: border-color var(--pmm-dur-short) var(--pmm-ease-standard),
              box-shadow   var(--pmm-dur-short) var(--pmm-ease-standard),
              background   var(--pmm-dur-short) var(--pmm-ease-standard);
}
.pmm-pay-card vaadin-text-field[focused]::part(input-field),
.pmm-pay-card vaadin-email-field[focused]::part(input-field),
.pmm-pay-card vaadin-number-field[focused]::part(input-field),
.pmm-pay-card vaadin-password-field[focused]::part(input-field),
.pmm-pay-card vaadin-text-area[focused]::part(input-field),
.pmm-pay-card vaadin-integer-field[focused]::part(input-field) {
  background: var(--pmm-surface-1);
  border-color: var(--pmm-brand);
  box-shadow: 0 0 0 4px rgba(124, 58, 237, 0.18);
}

/* Total row pops in violet headline-md mono — the customer's eye
 * should land here. Stripe Checkout treats the total this way too. */
.pmm-pay-totals__row--total {
  font-family: var(--pmm-font);
  font-size: 18px;
  font-weight: 700;
  line-height: 24px;
  letter-spacing: -0.01em;
  color: var(--pmm-text-primary);
  padding-top: 16px;
  margin-top: 8px;
  border-top: 1px solid var(--pmm-border-default);
}
.pmm-pay-totals__row--total > :last-child {
  font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 22px;
  font-weight: 700;
  color: var(--pmm-brand);
  letter-spacing: -0.01em;
}

/* Pay button — wider, taller, more rounded. Matches Stitch's
 * confidence-level CTA. The existing brand-gradient + lift on hover
 * already match the design. */
.pmm-pay-submit {
  min-height: 56px;
  border-radius: var(--pmm-shape-lg);
  font-size: 17px;
  margin-top: 28px;
}

/* Trust strip — calmer, single horizontal line, lock + copy + "by
 * PayMeMate". Removes the pill-style border in favour of a quiet
 * footnote that reads as legal/factual. */
.pmm-pay-trust {
  margin-top: 24px;
  padding-top: 20px;
  border-top: 1px solid var(--pmm-border-subtle);
  font-size: 12px;
  color: var(--pmm-text-secondary);
  letter-spacing: 0.01em;
}

/* Gateway chips — when laid out as a 2-column grid, the selected one
 * gets a quiet 2px violet ring + tinted bg (rather than the heavy
 * gradient). Matches Apple Pay's "tap a card" feel. */
.pmm-pay-gateway {
  border-radius: var(--pmm-shape-md);
  border: 1px solid var(--pmm-border-default);
  transition:
    border-color var(--pmm-dur-short) var(--pmm-ease-standard),
    box-shadow   var(--pmm-dur-short) var(--pmm-ease-standard),
    background   var(--pmm-dur-short) var(--pmm-ease-standard);
}
.pmm-pay-gateway--selected {
  border-color: var(--pmm-brand);
  background: rgba(124, 58, 237, 0.04);
  box-shadow: 0 0 0 3px rgba(124, 58, 237, 0.12);
}

/* Card padding tightens slightly on mobile to maximise content area;
 * the desktop padding stays generous. */
@media (max-width: 480px) {
  .pmm-pay-card { padding: 28px 22px; }
  .pmm-pay-submit { min-height: 52px; font-size: 16px; }
}

.pmm-pay-result--success {
  animation: pmm-success-mount var(--pmm-dur-long) var(--pmm-ease-spring) both;
}
@keyframes pmm-success-mount {
  from { opacity: 0; transform: scale(0.92); }
  to   { opacity: 1; transform: scale(1); }
}
.pmm-pay-result--failure {
  animation: pmm-card-mount var(--pmm-dur-medium) var(--pmm-ease-standard) both,
             pmm-shake 360ms var(--pmm-ease-standard) both;
}
@keyframes pmm-shake {
  0%, 100% { transform: translateX(0); }
  20%      { transform: translateX(-4px); }
  40%      { transform: translateX(4px); }
  60%      { transform: translateX(-3px); }
  80%      { transform: translateX(3px); }
}

/* ============================================================
 * 7. WAVE 1 UX MODERNIZATION — DetailDrawer + QuickFilterBar +
 *    SkeletonGrid + Paginator polish + KPI sparklines.
 *
 * What changed vs Round 6:
 *   - .pmm-detail-drawer: side-panel detail pattern (Stripe / Linear).
 *     Slides in from right, modal=false so the grid behind stays visible.
 *   - .pmm-quick-filter: chip-style time + status filter buttons.
 *   - .pmm-skeleton-row: shimmer rows for grids during initial fetch.
 *   - .pmm-paginator: polish on the Paginator component.
 *   - .pmm-kpi__sparkline: inline 7-day mini-chart in dashboard cards.
 *
 * The whole point: the chrome stops feeling like a 2014 admin panel and
 * starts feeling like Stripe / Linear / Mercury — fast, dense, smart.
 * ============================================================ */

/* ---- DetailDrawer (slide-from-right) ----------------------- */

vaadin-dialog-overlay.pmm-detail-drawer {
  /* Pin to right edge full-height instead of centered modal. */
  align-items: stretch !important;
  justify-content: flex-end !important;
}
vaadin-dialog-overlay.pmm-detail-drawer::part(overlay) {
  height: 100vh !important;
  max-height: 100vh !important;
  margin: 0 !important;
  border-radius: var(--pmm-shape-lg) 0 0 var(--pmm-shape-lg) !important;
  box-shadow: var(--pmm-elev-3) !important;
  /* Slide-in animation overrides the default fade. */
  animation: pmm-drawer-slide-in var(--pmm-dur-medium) var(--pmm-ease-standard) both !important;
}
@keyframes pmm-drawer-slide-in {
  from { transform: translateX(100%); opacity: 0.85; }
  to   { transform: translateX(0);    opacity: 1; }
}

.pmm-detail-drawer__header {
  padding: var(--pmm-space-6) var(--pmm-space-6) var(--pmm-space-3);
  border-bottom: 1px solid var(--pmm-border-subtle);
  background: var(--pmm-surface-1);
}
.pmm-detail-drawer__title {
  margin: 0;
  font: 600 18px/26px var(--pmm-font);
  color: var(--pmm-text-primary);
}
.pmm-detail-drawer__subtitle {
  font: 400 13px/18px var(--pmm-font);
  color: var(--pmm-text-secondary);
  margin-top: 2px;
}
.pmm-detail-drawer__content {
  padding: var(--pmm-space-6);
  overflow-y: auto;
  flex: 1;
  min-height: 0;
}
.pmm-detail-drawer__footer {
  padding: var(--pmm-space-3) var(--pmm-space-6);
  border-top: 1px solid var(--pmm-border-subtle);
  background: var(--pmm-surface-1);
}

/* Mobile: full-width drawer */
@media (max-width: 768px) {
  vaadin-dialog-overlay.pmm-detail-drawer::part(overlay) {
    width: 100% !important;
    border-radius: 0 !important;
  }
}

/* ---- Detail key-value layout (used inside drawer + cards) -- */

.pmm-kv {
  display: grid;
  grid-template-columns: 140px 1fr;
  gap: var(--pmm-space-2) var(--pmm-space-4);
  padding: var(--pmm-space-4) 0;
}
.pmm-kv__key {
  color: var(--pmm-text-tertiary);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  font-weight: 600;
  align-self: center;
}
.pmm-kv__value {
  color: var(--pmm-text-primary);
  font-size: 14px;
  font-variant-numeric: tabular-nums;
  word-break: break-word;
}

/* Reusable monospace utility for ID / code / hash cells per DESIGN.md
   ("Numbers monospace — every grid cell with an amount uses JetBrains Mono").
   Also applies to opaque identifier strings (agent code, owner ID, reference)
   so they stay column-aligned and tell the eye "this is a value, not prose". */
.pmm-mono {
  font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

/* Hover-reveal row actions — Stripe/Linear pattern where the action column
   stays muted until the user mouses over the row, then fades in. Reduces
   the visual noise of every row carrying a dense icon cluster. Applied via
   addClassName("pmm-row-actions--hover") on the actions Div inside an
   addComponentColumn. The row itself doesn't need a hover class — Vaadin
   surfaces hover state on vaadin-grid-cell-content automatically and the
   :hover selector targets the cell ancestor. */
.pmm-row-actions--hover {
  opacity: 0;
  transition: opacity 120ms ease-out;
}
vaadin-grid-cell-content:hover .pmm-row-actions--hover,
vaadin-grid::part(row):hover .pmm-row-actions--hover,
.pmm-row-actions--hover:focus-within {
  opacity: 1;
}

/* ---- DetailDrawer sections (Stripe-style stacked sections) ---- */

.pmm-drawer-section {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 16px 0;
  border-top: 1px solid var(--pmm-border-subtle);
}
.pmm-drawer-section:first-of-type { border-top: 0; padding-top: 8px; }
.pmm-drawer-section__title {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  color: var(--pmm-text-tertiary);
  margin: 0 0 6px 0;
}
.pmm-drawer-section .pmm-kv { padding: 0; }
.pmm-drawer-section--collapsible > summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  color: var(--pmm-text-tertiary);
  user-select: none;
}
.pmm-drawer-section--collapsible > summary::-webkit-details-marker { display: none; }
.pmm-drawer-section--collapsible > summary::before {
  content: "▸";
  font-size: 10px;
  transition: transform 120ms ease-out;
}
.pmm-drawer-section--collapsible[open] > summary::before { transform: rotate(90deg); }
.pmm-drawer-section--collapsible .pmm-kv { margin-top: 8px; }

/* Drawer hero — status pill + amount + reference, on a calm tonal strip
   matching the public-pay mesh family but flatter for chrome density. */
.pmm-drawer-hero {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 12px 14px 14px 14px;
  background: var(--pmm-surface-2);
  border: 1px solid var(--pmm-border-subtle);
  border-radius: 12px;
  margin: 0 0 6px 0;
}
.pmm-drawer-hero__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
.pmm-drawer-hero__amount {
  font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 22px;
  font-weight: 700;
  color: var(--pmm-text-primary);
  letter-spacing: -0.01em;
}
.pmm-drawer-hero__ref {
  font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
  color: var(--pmm-text-secondary);
  word-break: break-all;
}

/* Timeline rail — vertical dotted track with status nodes. */
.pmm-timeline { display: flex; flex-direction: column; gap: 0; }
.pmm-timeline__item {
  display: grid;
  grid-template-columns: 14px 1fr;
  gap: 10px;
  align-items: flex-start;
  padding: 4px 0;
  position: relative;
}
.pmm-timeline__dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--pmm-brand);
  margin-top: 6px;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--pmm-brand) 18%, transparent);
}
.pmm-timeline__item--muted .pmm-timeline__dot { background: var(--pmm-text-tertiary); box-shadow: none; }
.pmm-timeline__item + .pmm-timeline__item::before {
  content: "";
  position: absolute;
  left: 4px;
  top: -10px;
  width: 2px;
  height: 16px;
  background: var(--pmm-border-default);
  border-radius: 1px;
}
.pmm-timeline__label {
  font-size: 13px;
  color: var(--pmm-text-primary);
  font-weight: 500;
  line-height: 1.4;
}
.pmm-timeline__when {
  font-size: 11px;
  color: var(--pmm-text-tertiary);
  margin-top: 1px;
}

/* ---- QuickFilterBar (chips) -------------------------------- */

.pmm-quick-filter {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 4px 0;
  align-items: center;
}
.pmm-quick-filter__label {
  font: 600 11px/16px var(--pmm-font);
  color: var(--pmm-text-tertiary);
  text-transform: uppercase;
  letter-spacing: 0.6px;
  margin-right: 6px;
}
.pmm-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 12px;
  border-radius: var(--pmm-shape-pill);
  background: var(--pmm-surface-2);
  border: 1px solid var(--pmm-border-subtle);
  color: var(--pmm-text-secondary);
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
  user-select: none;
  transition:
    background var(--pmm-dur-short) var(--pmm-ease-standard),
    color      var(--pmm-dur-short) var(--pmm-ease-standard),
    border-color var(--pmm-dur-short) var(--pmm-ease-standard);
}
.pmm-chip:hover {
  background: var(--pmm-brand-soft);
  color: var(--pmm-brand-text);
  border-color: var(--pmm-brand-soft);
}
.pmm-chip--active {
  background: var(--pmm-brand);
  color: var(--pmm-text-on-brand);
  border-color: var(--pmm-brand);
}
.pmm-chip--active:hover {
  background: var(--pmm-brand-strong);
  color: var(--pmm-text-on-brand);
  border-color: var(--pmm-brand-strong);
}
.pmm-chip:focus-visible {
  outline: 2px solid var(--pmm-brand);
  outline-offset: 2px;
}
/* Inactive chip — shown in the form-builder gateway preview when a container
 * scheme exists but its underlying gateway isn't enabled for this merchant.
 * Greyed + strikethrough so the merchant immediately reads "this is hidden". */
.pmm-chip--inactive {
  background: transparent;
  color: var(--pmm-text-tertiary);
  border-color: var(--pmm-border-subtle);
  text-decoration: line-through;
  text-decoration-color: var(--pmm-border-strong);
  cursor: help;
  opacity: 0.65;
}
.pmm-chip--inactive:hover {
  background: transparent;
  color: var(--pmm-text-secondary);
  border-color: var(--pmm-border-default);
  opacity: 0.9;
}

/* ---- Capability strip (page-header feature signalling) ----------
 * Non-interactive sibling of .pmm-chip. Used on pages that want to
 * communicate "here are the capabilities this surface offers, with
 * NEW / BETA pills on the recent additions". Rendered as a flex-wrap
 * row directly under a .pmm-section-header so an opening user reads
 * (a) what the page is for and (b) what it can do, in one glance.
 * The strip itself is .pmm-cap-strip; each chip is .pmm-cap-chip.
 * Chips never select / never filter — purely communicative.
 * ----------------------------------------------------------------- */
.pmm-cap-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 4px 0 12px;
}

.pmm-cap-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 10px 5px 8px;
  border-radius: var(--pmm-shape-pill, 999px);
  background: var(--pmm-surface-2);
  border: 1px solid var(--pmm-border-subtle);
  color: var(--pmm-text-secondary);
  font-size: 12px;
  font-weight: 500;
  line-height: 1;
  cursor: default;
  user-select: none;
  transition: background var(--pmm-dur-short, 120ms) ease,
              border-color var(--pmm-dur-short, 120ms) ease;
}

.pmm-cap-chip:hover {
  background: var(--pmm-brand-soft, rgba(111, 92, 255, 0.08));
  border-color: var(--pmm-brand-soft, rgba(111, 92, 255, 0.2));
  color: var(--pmm-text-primary);
}

.pmm-cap-chip__icon {
  width: 14px;
  height: 14px;
  color: var(--pmm-text-tertiary);
  flex: 0 0 auto;
}

.pmm-cap-chip:hover .pmm-cap-chip__icon {
  color: var(--pmm-brand, #6f5cff);
}

.pmm-cap-chip__label {
  white-space: nowrap;
}

.pmm-cap-chip__pill {
  display: inline-flex;
  align-items: center;
  padding: 1px 6px;
  border-radius: 4px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  line-height: 1.2;
}

.pmm-cap-chip__pill--new {
  background: var(--pmm-brand, #6f5cff);
  color: var(--pmm-text-on-brand, #fff);
}

.pmm-cap-chip__pill--beta {
  background: var(--pmm-accent-soft, rgba(34, 197, 235, 0.18));
  color: var(--pmm-accent-text, #08a3c3);
  border: 1px solid var(--pmm-accent-soft, rgba(34, 197, 235, 0.35));
}

/* ---- Truncated text (.pmm-truncate) ----------------------------------
 * Single-line ellipsis-on-overflow. Backed by the TruncatedText Vaadin
 * component, which also attaches a smart resize-aware tooltip so the
 * full content reveals on hover only when it's actually clipped.
 *
 * Use anywhere a string can be longer than its container — grid cells,
 * list rows, dense card layouts. The {@code max-width:100%} lets the
 * span shrink-to-fit inside flex / grid parents without needing the
 * caller to pin a width.
 * --------------------------------------------------------------------- */
.pmm-truncate {
  display: inline-block;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  vertical-align: middle;
}

/* ---- Segmented date-range pill (filter-row preset) ------------ */

/* Brief: "date range first (pill), then categorical filters (selects),
   then search (right-aligned), then a tertiary Reset link." This pill
   replaces the bare From/To date-picker pair at the leading edge of
   the filter row. Active state uses a calm violet tonal background;
   inactive pills sit on the surface-2 layer so the row reads as a
   single connected control. */
.pmm-segmented {
  display: inline-flex;
  align-items: center;
  background: var(--pmm-surface-2);
  border: 1px solid var(--pmm-border-subtle);
  border-radius: var(--pmm-shape-pill, 9999px);
  padding: 3px;
  gap: 2px;
  user-select: none;
}
.pmm-segmented__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 5px 12px;
  font-size: 13px;
  font-weight: 500;
  color: var(--pmm-text-secondary);
  border-radius: var(--pmm-shape-pill, 9999px);
  cursor: pointer;
  line-height: 1;
  transition: background 120ms ease-out, color 120ms ease-out;
  min-width: 44px;
  text-align: center;
}
.pmm-segmented__btn:hover {
  color: var(--pmm-text-primary);
  background: color-mix(in srgb, var(--pmm-brand, #7c3aed) 8%, transparent);
}
.pmm-segmented__btn:focus-visible {
  outline: 2px solid var(--pmm-brand, #7c3aed);
  outline-offset: 2px;
}
.pmm-segmented__btn--active {
  background: color-mix(in srgb, var(--pmm-brand, #7c3aed) 16%, transparent);
  color: var(--pmm-brand, #7c3aed);
  font-weight: 600;
}

/* ---- Skeleton row shimmer (grid loading state) ------------- */

.pmm-skeleton-row {
  display: flex;
  gap: 12px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--pmm-border-subtle);
}
.pmm-skeleton-cell {
  height: 14px;
  background: linear-gradient(
    90deg,
    var(--pmm-surface-2) 0%,
    var(--pmm-surface-3) 50%,
    var(--pmm-surface-2) 100%
  );
  background-size: 200% 100%;
  border-radius: 4px;
  animation: pmm-skeleton-shimmer 1.4s ease-in-out infinite;
}
@keyframes pmm-skeleton-shimmer {
  from { background-position: 200% 0; }
  to   { background-position: -200% 0; }
}

/* ---- Paginator polish -------------------------------------- */

.pmm-paginator {
  flex: 0 0 auto;
}
.pmm-paginator vaadin-button[theme~="primary"] {
  font-weight: 600;
  pointer-events: none; /* current page is non-interactive */
}

/* ---- KPI sparkline ----------------------------------------- */

.pmm-kpi__delta {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  font-size: 12px;
  font-weight: 600;
  margin-left: 6px;
}
.pmm-kpi__delta--up   { color: var(--pmm-success-text); }
.pmm-kpi__delta--down { color: var(--pmm-error-text); }
.pmm-kpi__delta--flat { color: var(--pmm-text-tertiary); }

.pmm-kpi__sparkline {
  margin-top: 8px;
  height: 36px;
  display: block;
}
.pmm-kpi__sparkline polyline {
  fill: none;
  stroke: var(--pmm-brand);
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.pmm-kpi__sparkline path {
  fill: var(--pmm-brand);
  fill-opacity: 0.08;
}

/* ============================================================
 * 6. ROUND 6 — DESIGN-SYSTEM EXTENSION (additive, non-breaking)
 *
 * Materialises the explicit design-system spec on top of Rounds 4+5:
 *   6a. 8pt spacing scale (--pmm-space-1..12)
 *   6b. Element-level type hierarchy (h1–h4, p, small, code)
 *   6c. Reusable chrome components (.pmm-page, .pmm-card,
 *       .pmm-section-header, .pmm-toolbar, .pmm-eyebrow, .pmm-caption,
 *       .pmm-link, .pmm-divider, .pmm-grid-2/3/4)
 *   6d. Skeleton-loader shimmer for async lists / grids
 *   6e. Responsive breakpoints (mobile-first refinements)
 * ============================================================ */

/* ---- 6a. Explicit 8pt spacing scale -------------------------- */
/* Lumo's --lumo-space-* is roughly 8pt-aligned; this exposes the
 * scale as plain multiples so component CSS doesn't have to think
 * about unit conversion. Multiply 8px by 1..12 stepwise. */
:root {
  --pmm-space-1:  4px;   /* hairline / inline gap inside tight groups */
  --pmm-space-2:  8px;   /* default gap between adjacent siblings */
  --pmm-space-3:  12px;  /* component inner padding (compact) */
  --pmm-space-4:  16px;  /* component inner padding (default) */
  --pmm-space-5:  20px;
  --pmm-space-6:  24px;  /* card padding */
  --pmm-space-8:  32px;  /* section gap */
  --pmm-space-10: 40px;
  --pmm-space-12: 48px;  /* page-level vertical rhythm */
  --pmm-space-16: 64px;  /* hero-level break */
}

/* ---- 6b. Element-level type hierarchy ------------------------ */
/* Set defaults on plain h1–h4 / p / small so any view that uses raw
 * Vaadin H1/H2/H3/Span/Paragraph picks up the system without per-view
 * inline styles. Tokens still drive per-component overrides. */
h1 {
  font: 700 32px/40px var(--pmm-font);
  letter-spacing: -0.022em;
  color: var(--pmm-text-primary);
  margin: 0 0 var(--pmm-space-3) 0;
}
h2 {
  font: 600 24px/32px var(--pmm-font);
  letter-spacing: -0.018em;
  color: var(--pmm-text-primary);
  margin: 0 0 var(--pmm-space-3) 0;
}
h3 {
  font: 600 18px/26px var(--pmm-font);
  letter-spacing: -0.012em;
  color: var(--pmm-text-primary);
  margin: 0 0 var(--pmm-space-2) 0;
}
h4 {
  font: 600 16px/24px var(--pmm-font);
  color: var(--pmm-text-primary);
  margin: 0 0 var(--pmm-space-2) 0;
}
p {
  font: 400 14px/22px var(--pmm-font);
  color: var(--pmm-text-secondary);
  margin: 0 0 var(--pmm-space-3) 0;
}
small {
  font: 500 12px/16px var(--pmm-font);
  color: var(--pmm-text-tertiary);
}
code, kbd, samp {
  font-family: 'JetBrains Mono', 'SF Mono', Menlo, Consolas, monospace;
  font-size: 0.92em;
}

/* ---- 6c. Reusable chrome components -------------------------- */

/* Page wrapper — every chrome view should opt into this for
 * consistent vertical rhythm. NO max-width by default: grids and
 * dashboards need the full chrome width on large monitors, and a
 * 1280px cap visibly squeezes them into a horizontal-scroll trap
 * on the very common 1440 / 1920 monitors. Form-style views that
 * want a narrower readable column should opt in to {@code .pmm-page--narrow}.
 *
 * The {@code min-height: 0} is critical: it lets a flex child grid
 * shrink to fit available vertical space (and trigger lazy loading)
 * instead of expanding to the full content height (which would
 * render every row and defeat pagination). */
.pmm-page {
  padding: var(--pmm-space-8) var(--pmm-space-8) var(--pmm-space-12);
  margin: 0 auto;
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: var(--pmm-space-6);
  min-height: 0;
  flex: 1;
}

/* Optional narrow variant for centered forms / profile pages. */
.pmm-page--narrow {
  max-width: 720px;
}

/*
 * Vaadin Grid inside a .pmm-page: claim the remaining flex space and
 * give the lazy loader a determinate viewport.  Without these
 * declarations Vaadin falls back to "render every row" because the
 * flex container's content-derived height makes the grid look
 * infinitely tall to the row-buffer calculator.
 *
 * !important is required because Java code typically calls
 * {@code grid.setSizeFull()} which writes {@code height: 100%} as an
 * inline style — and inline beats class without !important. Setting
 * height to auto + flex: 1 lets the grid occupy the remaining flex
 * space below the page header, with a 400px floor so the lazy loader
 * always has *some* viewport to compute its buffer against.
 */
/* Direct-child grids only. Grids nested inside a .pmm-card (e.g. the
 * dashboard "Recent transactions" widget) keep their natural sizing. */
.pmm-page > vaadin-grid {
  flex: 1 !important;
  min-height: 400px !important;
  height: auto !important;
  width: 100% !important;
}

/* Section header (title + optional toolbar on the right) */
.pmm-section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--pmm-space-4);
  flex-wrap: wrap;
}
.pmm-section-header__lead { display: flex; flex-direction: column; gap: var(--pmm-space-1); }
/* Page titles ride `headline-lg` (32/40, weight 600, -0.01em) per DESIGN.md.
   The CSS lives on the class — the markup carries either H1 (canonical
   per-page) or, in legacy/dialog contexts, H2. */
.pmm-section-header__title    { margin: 0; font: 600 32px/40px var(--pmm-font); letter-spacing: -0.01em; }
.pmm-section-header__subtitle { margin: 0; color: var(--pmm-text-secondary); font-size: 14px; }

.pmm-toolbar {
  display: inline-flex;
  align-items: center;
  gap: var(--pmm-space-2);
}

/* General-purpose card. Use over plain Div for any
 * "panel of related content" — replaces ad-hoc inline styling. */
.pmm-card {
  background: var(--pmm-surface-1);
  border: 1px solid var(--pmm-border-subtle);
  border-radius: var(--pmm-shape-md);
  padding: var(--pmm-space-6);
  box-shadow: var(--pmm-elev-soft);
  transition:
    transform   var(--pmm-dur-short) var(--pmm-ease-standard),
    box-shadow  var(--pmm-dur-short) var(--pmm-ease-standard),
    border-color var(--pmm-dur-short) var(--pmm-ease-standard);
}
.pmm-card--interactive {
  cursor: pointer;
}
.pmm-card--interactive:hover {
  transform: translateY(-2px);
  box-shadow: var(--pmm-elev-2);
  border-color: var(--pmm-border-default);
}
.pmm-card--interactive:focus-visible {
  outline: 0;
  box-shadow: var(--pmm-elev-2), var(--pmm-focus-ring);
}
/* Inner section spacing inside a .pmm-card */
.pmm-card > * + * { margin-top: var(--pmm-space-3); }
.pmm-card__title { margin: 0; font: 600 16px/24px var(--pmm-font); }
.pmm-card__hint  { margin: 0; color: var(--pmm-text-secondary); font-size: 13px; }

/* ────────────────────────────────────────────────────────────────
   Pay-link metadata (PublicFormView).
   The merchant's per-link descriptions / invoice number / short
   code render INLINE inside the hero card — no boxed banner, no
   separate background, no border. Stripe-style: the title sits at
   the top of the card; a row of subtle chips + a caption-style
   description weave into the same surface so the reader sees one
   continuous payment card, not "title + sidebar".
   ──────────────────────────────────────────────────────────────── */
.pmm-pay-link-meta {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: -4px 0 14px;       /* tight to the title above, normal gap below */
}
.pmm-pay-link-meta__chip-row {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.pmm-pay-link-meta__chip {
  display: inline-flex;
  align-items: center;
  padding: 2px 10px;
  border-radius: 999px;
  background: transparent;
  border: 1px solid var(--pmm-border-default, var(--pmm-border-subtle));
  color: var(--pmm-text-secondary);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.pmm-pay-link-meta__description {
  color: var(--pmm-text-primary);
  font-size: 14px;
  line-height: 1.4;
  margin: 0;
}
.pmm-pay-link-meta__description-secondary {
  color: var(--pmm-text-secondary);
  font-size: 13px;
  line-height: 1.4;
  margin: 0;
}
.pmm-pay-link-meta__link {
  color: var(--pmm-brand);
  margin-left: 6px;
  font-size: 13px;
  text-decoration: none;
}
.pmm-pay-link-meta__link:hover { text-decoration: underline; }

/* Mini transactions grid — Stitch v1 dashboard widget. Tight rows in a
 * Linear-style density, monospace numbers, status pills inline. We
 * roll our own (rather than reuse vaadin-grid) so the rendering stays
 * lightweight inside a card. */
.pmm-mini-grid {
  display: flex;
  flex-direction: column;
  margin-top: 4px;
}
.pmm-mini-grid__row {
  display: grid;
  grid-template-columns: 56px minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, 1fr) auto;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  border-radius: var(--pmm-shape-md);
  transition: background var(--pmm-dur-short) var(--pmm-ease-standard);
}
.pmm-mini-grid__row + .pmm-mini-grid__row {
  border-top: 1px solid var(--pmm-border-subtle);
}
.pmm-mini-grid__row:hover {
  background: var(--pmm-surface-2);
}
.pmm-mini-grid__time {
  font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
  color: var(--pmm-text-secondary);
  letter-spacing: 0.02em;
}
.pmm-mini-grid__ref {
  font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
  color: var(--pmm-text-primary);
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.pmm-mini-grid__amount {
  font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13px;
  color: var(--pmm-text-primary);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  text-align: right;
}
.pmm-mini-grid__gateway {
  font-size: 12px;
  color: var(--pmm-text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Dashboard 2/3 + 1/3 row — proper grid, stacks under 768px. */
.pmm-dashboard-row {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
  gap: 24px;
  width: 100%;
}
@media (max-width: 1024px) {
  .pmm-dashboard-row {
    grid-template-columns: 1fr;
  }
}

.pmm-dash__right-stack {
  display: flex;
  flex-direction: column;
  gap: 24px;
}

/* ===========================================================================
 * Dashboard page header — breadcrumbs + title row + today-pill.
 * =========================================================================== */
.pmm-dash__header {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 16px;
}
.pmm-dash__crumbs {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--pmm-text-tertiary);
}
.pmm-dash__crumbs svg {
  width: 14px; height: 14px;
}
.pmm-dash__crumbs-active {
  color: var(--pmm-brand-text);
  font-weight: 500;
}
.pmm-dash__header-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}
.pmm-dash__title {
  font-size: 32px;
  font-weight: 600;
  line-height: 40px;
  letter-spacing: -0.01em;
  color: var(--pmm-text-primary);
  margin: 0;
}
.pmm-dash__date-pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 14px;
  border-radius: 9999px;
  background: var(--pmm-surface-2);
  font-size: 13px;
  color: var(--pmm-text-secondary);
}
.pmm-dash__date-dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--pmm-success);
}

/* ===========================================================================
 * KPI card — refinements for trend indicators and mono numbers.
 * =========================================================================== */
.pmm-kpi__value {
  font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 30px;
  line-height: 36px;
  font-weight: 700;
  letter-spacing: -0.01em;
}
.pmm-kpi__trend {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 8px;
  font-size: 13px;
  font-weight: 500;
}
.pmm-kpi__trend svg {
  width: 14px; height: 14px;
}
.pmm-kpi__trend--up   { color: var(--pmm-success-text); }
.pmm-kpi__trend--down { color: var(--pmm-error-text); }
.pmm-kpi__trend-suffix {
  color: var(--pmm-text-tertiary);
  font-weight: 400;
}

/* ===========================================================================
 * Card header bar with right-aligned link (e.g. "View all →").
 * =========================================================================== */
.pmm-card__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--pmm-border-subtle);
}
.pmm-card__link-a {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  font-weight: 500;
  color: var(--pmm-brand-text);
  text-decoration: none;
}
.pmm-card__link-a svg {
  width: 14px; height: 14px;
}
.pmm-card__link-a:hover {
  text-decoration: underline;
}

/* ===========================================================================
 * Mini-grid header row — column titles above the data rows.
 * =========================================================================== */
.pmm-mini-grid__header {
  display: grid;
  grid-template-columns: 56px minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, 1fr) auto;
  align-items: center;
  gap: 12px;
  padding: 8px 12px;
  background: var(--pmm-surface-2);
  border-radius: var(--pmm-shape-sm);
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--pmm-text-tertiary);
}

/* ===========================================================================
 * Action list — clickable rows for the Quick actions card.
 * Each row: icon left, label center, chevron right.
 * =========================================================================== */
.pmm-action-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.pmm-action-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 16px;
  border: 1px solid var(--pmm-border-subtle);
  border-radius: var(--pmm-shape-md);
  cursor: pointer;
  background: var(--pmm-surface-1);
  transition: background var(--pmm-dur-short) var(--pmm-ease-standard),
              border-color var(--pmm-dur-short) var(--pmm-ease-standard),
              transform var(--pmm-dur-short) var(--pmm-ease-standard);
}
.pmm-action-row:hover {
  background: var(--pmm-brand-softer);
  border-color: color-mix(in oklab, var(--pmm-brand) 25%, transparent);
  transform: translateY(-1px);
}
.pmm-action-row__left {
  display: inline-flex;
  align-items: center;
  gap: 12px;
}
.pmm-action-row__icon {
  color: var(--pmm-brand);
  width: 18px; height: 18px;
}
.pmm-action-row__label {
  font-size: 14px;
  font-weight: 500;
  color: var(--pmm-text-primary);
}
.pmm-action-row__chevron {
  color: var(--pmm-text-tertiary);
  width: 16px; height: 16px;
  transition: color var(--pmm-dur-short) var(--pmm-ease-standard),
              transform var(--pmm-dur-short) var(--pmm-ease-standard);
}
.pmm-action-row:hover .pmm-action-row__chevron {
  color: var(--pmm-brand);
  transform: translateX(2px);
}

/* ===========================================================================
 * Gateway list with 3-bar signal strength indicator.
 * =========================================================================== */
.pmm-gw-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.pmm-gw-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 4px 0;
}
.pmm-gw-row__name {
  font-size: 14px;
  color: var(--pmm-text-primary);
}
.pmm-signal {
  display: inline-flex;
  gap: 3px;
  align-items: flex-end;
}
.pmm-signal__bar {
  width: 5px;
  height: 18px;
  border-radius: 2px;
  background: var(--pmm-border-default);
  opacity: 0.6;
}
.pmm-signal--ok .pmm-signal__bar--lit {
  background: var(--pmm-success);
  opacity: 1;
}
.pmm-signal--warn .pmm-signal__bar--lit {
  background: var(--pmm-warn);
  opacity: 1;
}
.pmm-signal--err .pmm-signal__bar--lit {
  background: var(--pmm-error);
  opacity: 1;
}
/* Each lit bar after the first gets progressively brighter — Stitch's
 * signal-bar pattern of subdued → mid → full. */
.pmm-signal__bar--lit { opacity: 0.6; }
.pmm-signal__bar--lit + .pmm-signal__bar--lit { opacity: 0.85; }
.pmm-signal__bar--lit + .pmm-signal__bar--lit + .pmm-signal__bar--lit { opacity: 1; }

/* ===========================================================================
 * Recent activity timeline — circular icon bubbles connected by a dotted
 * vertical line.
 * =========================================================================== */
.pmm-timeline {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 20px;
  padding-top: 8px;
}
.pmm-timeline__line {
  position: absolute;
  left: 19px;
  top: 24px;
  bottom: 24px;
  width: 0;
  border-left: 2px dotted var(--pmm-border-default);
  z-index: 0;
}
.pmm-timeline__row {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: flex-start;
  gap: 16px;
}
.pmm-timeline__bubble {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--pmm-surface-1);
  border: 1px solid var(--pmm-border-subtle);
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.pmm-timeline__bubble vaadin-icon {
  width: 18px; height: 18px;
}
.pmm-timeline__icon--ok      { color: var(--pmm-success); }
.pmm-timeline__icon--pending { color: var(--pmm-warn); }
.pmm-timeline__icon--err     { color: var(--pmm-error); }
.pmm-timeline__icon--neutral { color: var(--pmm-text-tertiary); }
.pmm-timeline__content {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-top: 6px;
}
.pmm-timeline__headline {
  font-size: 14px;
  color: var(--pmm-text-primary);
}
.pmm-timeline__amount {
  font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  font-weight: 700;
  color: var(--pmm-text-primary);
}
.pmm-timeline__gateway {
  font-weight: 500;
}
.pmm-timeline__ago {
  font-size: 12px;
  color: var(--pmm-text-tertiary);
}

/* Eyebrow / caption text helpers */
.pmm-eyebrow {
  text-transform: uppercase;
  letter-spacing: 0.6px;
  font-size: 11px;
  font-weight: 600;
  color: var(--pmm-text-tertiary);
}
.pmm-caption {
  font-size: 12px;
  line-height: 16px;
  color: var(--pmm-text-tertiary);
}

/* Link — accent-colored hover with underline-thickness shift */
.pmm-link {
  color: var(--pmm-brand-text);
  text-decoration: none;
  font-weight: 500;
  border-bottom: 1px solid transparent;
  transition: color var(--pmm-dur-short) var(--pmm-ease-standard),
              border-color var(--pmm-dur-short) var(--pmm-ease-standard);
}
.pmm-link:hover { color: var(--pmm-info); border-bottom-color: currentColor; }
.pmm-link:focus-visible {
  outline: 2px solid var(--pmm-brand);
  outline-offset: 2px;
  border-radius: 2px;
}

/* Divider — same hairline used everywhere, not the ad-hoc <hr> */
.pmm-divider {
  height: 1px;
  background: var(--pmm-border-subtle);
  border: 0;
  margin: var(--pmm-space-6) 0;
}

/* Responsive grid presets — drop a list of cards inside, get a
 * nice 1/2/4-col layout that collapses on mobile. */
.pmm-grid-2,
.pmm-grid-3,
.pmm-grid-4,
.pmm-grid-5 {
  display: grid;
  gap: var(--pmm-space-4);
  width: 100%;
}
.pmm-grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.pmm-grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.pmm-grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.pmm-grid-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
@media (max-width: 1100px) {
  .pmm-grid-5 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Accent KPI variant — violet left rule + slightly stronger value colour.
   Used for "headline" cards (e.g. Settlement "Sent today $") that benefit
   from being visually elevated next to peer KPIs. */
.pmm-kpi--accent {
  border-left: 4px solid var(--pmm-brand, #7c3aed);
}
.pmm-kpi--accent .pmm-kpi__value {
  color: var(--pmm-brand, #7c3aed);
}

/* Page-level layout primitives need explicit width:100% so they span
 * the dashboard root regardless of Vaadin's vertical-layout item
 * sizing defaults (which sometimes shrink children to content). */
.pmm-page > .pmm-card,
.pmm-page > .pmm-dashboard-row,
.pmm-page > .pmm-grid-2,
.pmm-page > .pmm-grid-3,
.pmm-page > .pmm-grid-4,
.pmm-page > .pmm-grid-5,
.pmm-page > .pmm-section-header,
.pmm-page > .pmm-toolbar,
.pmm-page > .pmm-dash__header,
.pmm-page > .pmm-list-header {
  width: 100%;
  box-sizing: border-box;
}

/* ===========================================================================
 * List-view page header — title + breadcrumbs + action cluster on the right.
 * Used by Transactions, Merchants, Reports and other admin list views.
 * =========================================================================== */
.pmm-list-header {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 4px;
}
.pmm-list-header__actions {
  display: inline-flex;
  align-items: center;
  gap: 12px;
}

/* Filter row card chrome — wraps the date picker + status/gateway/merchant
 * selects + search + saved-filter dropdown. */
.pmm-filter-card {
  padding: 12px 16px !important;
  width: 100%;
  box-sizing: border-box;
}
.pmm-filter-card__row {
  margin: 0 !important;
  padding: 0 !important;
  align-items: end !important;
  gap: 12px !important;
  flex-wrap: wrap;
}

/* Subtle accent button (Java side: addClassName("pmm-btn-accent") on
 * any vaadin-button, no Lumo theme variant required). Cyan secondary
 * accent gets actual surface area here. */
.pmm-btn-accent {
  background: var(--pmm-accent) !important;
  color: #ffffff !important;
  box-shadow: 0 6px 16px rgba(6, 182, 212, 0.30) !important;
}
.pmm-btn-accent:hover {
  filter: brightness(1.05);
  box-shadow: 0 10px 22px rgba(6, 182, 212, 0.40) !important;
  transform: translateY(-1px);
}

/* ---- 6d. Skeleton-loader shimmer ---------------------------- */
/* Drop-in skeleton block for async loading. Width/height set via
 * inline style or modifier classes. */
.pmm-skeleton {
  position: relative;
  overflow: hidden;
  background: var(--pmm-surface-2);
  border-radius: var(--pmm-shape-xs);
  min-height: 14px;
}
.pmm-skeleton::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    90deg,
    transparent 0%,
    rgba(255, 255, 255, 0.25) 50%,
    transparent 100%
  );
  animation: pmm-shimmer 1.4s linear infinite;
}
:root[data-theme="dark"] .pmm-skeleton::after,
:root:not([data-theme="light"]) .pmm-skeleton::after {
  /* in dark mode the bright sweep would over-flash; soften it */
  background: linear-gradient(
    90deg,
    transparent 0%,
    rgba(255, 255, 255, 0.06) 50%,
    transparent 100%
  );
}
@keyframes pmm-shimmer {
  from { transform: translateX(-100%); }
  to   { transform: translateX(100%); }
}
.pmm-skeleton--text { height: 14px; border-radius: 4px; }
.pmm-skeleton--title { height: 22px; border-radius: 6px; max-width: 60%; }
.pmm-skeleton--block { height: 88px; border-radius: var(--pmm-shape-md); }

/* ---- 6e. Responsive breakpoints ----------------------------- */
/* md  ≤ 1024  — collapse 4-col grids to 2-col, narrow page padding
 * sm  ≤ 768   — single-column, drop hero, condense type
 * xs  ≤ 480   — tightest padding
 */
@media (max-width: 1024px) {
  .pmm-page { padding: var(--pmm-space-6) var(--pmm-space-6) var(--pmm-space-10); }
  .pmm-grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .pmm-grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 768px) {
  h1 { font-size: 28px; line-height: 36px; }
  h2 { font-size: 20px; line-height: 28px; }
  .pmm-page { padding: var(--pmm-space-4) var(--pmm-space-4) var(--pmm-space-8); }
  .pmm-grid-2,
  .pmm-grid-3,
  .pmm-grid-4 { grid-template-columns: 1fr; }
  .pmm-pay-card { padding: var(--pmm-space-6) var(--pmm-space-5); }
  vaadin-app-layout::part(drawer) { width: 240px; }
}
@media (max-width: 480px) {
  .pmm-pay-card { padding: var(--pmm-space-5) var(--pmm-space-4); border-radius: var(--pmm-shape-md); }
  .pmm-card { padding: var(--pmm-space-4); }
}

/* ---- 6f. Global focus-visible (keyboard-only) --------------- */
/* Anything missed by component-level focus rules still gets a
 * brand-colored ring when navigated by keyboard. Intentionally
 * scoped to :focus-visible (not :focus) so mouse clicks don't
 * trigger the ring. */
*:focus-visible {
  outline: 2px solid var(--pmm-brand);
  outline-offset: 2px;
  border-radius: var(--pmm-shape-xs);
}
/* Suppress on form-field internals where the component already
 * shows a focused border + glow — double-rendering reads as buggy. */
vaadin-text-field input:focus-visible,
vaadin-email-field input:focus-visible,
vaadin-password-field input:focus-visible,
vaadin-number-field input:focus-visible,
vaadin-integer-field input:focus-visible,
vaadin-text-area textarea:focus-visible,
vaadin-combo-box input:focus-visible,
vaadin-select::part(input-field):focus-visible,
vaadin-button:focus-visible {
  outline: 0;
}

/* ===========================================================================
 * Welcome onboarding checklist (first-login merchants)
 * Rendered above the dashboard KPIs to guide a fresh account through gateway
 * setup → first link → first payment. Hidden once any of those is satisfied.
 * =========================================================================== */
.pmm-welcome {
  background: linear-gradient(135deg,
      color-mix(in oklab, var(--pmm-brand) 6%, var(--pmm-bg-elev1)) 0%,
      var(--pmm-bg-elev1) 100%);
  border-left: 4px solid var(--pmm-brand);
}

.pmm-welcome__step {
  padding: var(--lumo-space-m);
  border-radius: var(--pmm-shape-md);
  background: var(--pmm-bg-elev0);
  border: 1px solid var(--pmm-border);
  transition: background 160ms ease, border-color 160ms ease;
}

.pmm-welcome__step:hover {
  border-color: color-mix(in oklab, var(--pmm-brand) 35%, var(--pmm-border));
}

.pmm-welcome__step--done {
  opacity: 0.7;
}

.pmm-welcome__step-number {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--pmm-text-tertiary);
}

.pmm-welcome__step-label {
  font-size: 15px;
  font-weight: 600;
  color: var(--pmm-text-primary);
}

.pmm-welcome__step-hint {
  font-size: 13px;
  color: var(--pmm-text-secondary);
  line-height: 1.45;
}

.pmm-welcome__step-icon {
  flex-shrink: 0;
  margin-top: 2px;
}

/* ===========================================================================
 * Bulk action bar — appears above the grid when ≥1 row is selected.
 * =========================================================================== */
.pmm-bulk-bar {
  background: color-mix(in oklab, var(--pmm-brand) 6%, var(--pmm-bg-elev1));
  border: 1px solid color-mix(in oklab, var(--pmm-brand) 25%, var(--pmm-border));
  border-radius: var(--pmm-shape-md);
  padding: var(--lumo-space-s) var(--lumo-space-m);
  margin: var(--lumo-space-xs) 0;
  animation: pmm-bulk-bar-slide-in 180ms ease-out;
}

@keyframes pmm-bulk-bar-slide-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}

.pmm-bulk-bar__count {
  font-weight: 600;
  font-size: 13px;
  color: var(--pmm-text-primary);
}

/* ===========================================================================
 * Gateway setup wizard (Phase D4) — pill-strip + step body for
 * GatewaySetupWizardView. Uses .pmm-wizard__pill (active / done states),
 * .pmm-wizard__strip (the row container) and .pmm-wizard__body.
 * =========================================================================== */
.pmm-wizard__strip {
  display: flex;
  align-items: center;
  gap: 8px;
}
.pmm-wizard__pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  border-radius: 999px;
  border: 1px solid var(--pmm-border-subtle);
  background: var(--pmm-surface-1);
  color: var(--pmm-text-tertiary);
  font-size: 13px;
  font-weight: 500;
}
.pmm-wizard__pill--active {
  background: var(--pmm-brand-soft);
  border-color: color-mix(in oklab, var(--pmm-brand) 25%, transparent);
  color: var(--pmm-brand-text);
}
.pmm-wizard__pill--done {
  background: var(--pmm-success-bg);
  color: var(--pmm-success-text);
  border-color: color-mix(in oklab, var(--pmm-success) 25%, transparent);
}
.pmm-wizard__pill-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--pmm-surface-2);
  font-size: 11px;
  font-weight: 700;
}
.pmm-wizard__pill--active .pmm-wizard__pill-num {
  background: var(--pmm-brand);
  color: var(--pmm-text-on-brand);
}
.pmm-wizard__pill--done .pmm-wizard__pill-num {
  background: var(--pmm-success);
  color: #fff;
}
.pmm-wizard__pill-sep {
  flex: 1;
  height: 1px;
  background: var(--pmm-border-subtle);
  max-width: 32px;
}
.pmm-wizard__body {
  flex: 1;
  overflow-y: auto;
}

/* ===========================================================================
 * Saved filter dropdown — Linear / Stripe-style "Saved views" picker that
 * sits in the filter bar of any paginated grid. Lets users park common
 * filter combinations and one-click restore them later.
 * =========================================================================== */
.pmm-saved-filter {
  display: inline-flex;
  align-items: center;
}
.pmm-saved-filter vaadin-menu-bar {
  --lumo-button-size: 32px;
}
.pmm-saved-filter__label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  font-weight: 500;
  color: var(--pmm-text-secondary);
  padding: 0 4px;
}
.pmm-saved-filter__label vaadin-icon {
  color: var(--pmm-text-tertiary);
}
.pmm-saved-filter__row {
  width: 100%;
  margin: 0 !important;
  padding: 0 !important;
}
.pmm-saved-filter__name {
  font-size: 13px;
  color: var(--pmm-text-primary);
  padding: 4px 0;
}
.pmm-saved-filter__action {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  font-weight: 500;
  color: var(--pmm-brand-text);
  padding: 4px 0;
}
.pmm-saved-filter__action vaadin-icon {
  color: var(--pmm-brand);
}

/* ===========================================================================
 * SkeletonGrid — placeholder rows shown during the initial paginated fetch.
 * =========================================================================== */
.pmm-skeleton-grid {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 12px 8px;
}

.pmm-skeleton-grid__row {
  display: flex;
  gap: 12px;
  height: 32px;
  align-items: center;
}

.pmm-skeleton-grid__cell {
  flex: 1;
  height: 14px;
  border-radius: 4px;
}

/* Vary the cell widths to read more like a real grid (not a uniform block). */
.pmm-skeleton-grid__cell:nth-child(1) { flex: 0.6; }
.pmm-skeleton-grid__cell:nth-child(2) { flex: 1.2; }
.pmm-skeleton-grid__cell:nth-child(3) { flex: 1.0; }
.pmm-skeleton-grid__cell:nth-child(4) { flex: 0.8; }
.pmm-skeleton-grid__cell:nth-child(5) { flex: 0.7; }
.pmm-skeleton-grid__cell:nth-child(6) { flex: 1.5; }

/* ===========================================================================
 * Wizard — multi-step Dialog with progress nodes at the top.
 * =========================================================================== */
.pmm-wizard-progress {
  width: 100%;
  padding: 4px 0 12px;
  border-bottom: 1px solid var(--pmm-border-subtle);
}

.pmm-wizard-progress__step {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  border-radius: var(--pmm-shape-md);
  background: var(--pmm-bg-elev0);
  border: 1px solid var(--pmm-border);
  transition: background 160ms ease, border-color 160ms ease, color 160ms ease;
}

.pmm-wizard-progress__step--active {
  background: color-mix(in oklab, var(--pmm-brand) 8%, var(--pmm-bg-elev1));
  border-color: var(--pmm-brand);
}

.pmm-wizard-progress__step--done {
  opacity: 0.7;
}

.pmm-wizard-progress__num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  font-size: 12px;
  font-weight: 700;
  background: color-mix(in oklab, var(--pmm-brand) 30%, var(--pmm-bg-elev0));
  color: var(--pmm-text-primary);
}

.pmm-wizard-progress__step--active .pmm-wizard-progress__num {
  background: var(--pmm-brand);
  color: white;
}

.pmm-wizard-progress__step--done .pmm-wizard-progress__num {
  background: var(--lumo-success-color);
  color: white;
}

.pmm-wizard-progress__label {
  font-size: 13px;
  font-weight: 600;
  color: var(--pmm-text-primary);
}

.pmm-wizard-body {
  padding: 8px 4px;
  min-height: 280px;
}

/* ===========================================================================
 * NotificationBell — top-bar bell with unread badge + popover list.
 * =========================================================================== */
.pmm-notification-bell__wrap {
  position: relative;
  display: inline-flex;
}

.pmm-notification-bell__badge {
  position: absolute;
  top: -2px;
  right: -2px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 8px;
  background: var(--lumo-error-color);
  color: white;
  font-size: 10px;
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}

.pmm-notification-popover__header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 12px;
  border-bottom: 1px solid var(--pmm-border-subtle);
}

.pmm-notification-popover__title {
  font-weight: 600;
  font-size: 13px;
  color: var(--pmm-text-primary);
}

.pmm-notification-popover__list {
  max-height: 380px;
  overflow-y: auto;
}

.pmm-notification-popover__empty {
  padding: 32px 16px;
  text-align: center;
  color: var(--pmm-text-tertiary);
  font-size: 13px;
}

.pmm-notification-row {
  display: flex;
  gap: 10px;
  padding: 10px 12px;
  border-bottom: 1px solid var(--pmm-border-subtle);
  cursor: pointer;
  transition: background 120ms ease;
}

.pmm-notification-row:hover {
  background: color-mix(in oklab, var(--pmm-brand) 4%, var(--pmm-bg-elev1));
}

.pmm-notification-row--unread {
  background: color-mix(in oklab, var(--pmm-brand) 6%, transparent);
}

.pmm-notification-row__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  margin-top: 6px;
  flex-shrink: 0;
}

.pmm-notification-row__dot--info     { background: var(--pmm-info); }
.pmm-notification-row__dot--success  { background: var(--pmm-success); }
.pmm-notification-row__dot--warning  { background: var(--pmm-warn); }
.pmm-notification-row__dot--error    { background: var(--pmm-error); }

.pmm-notification-row__text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1;
  min-width: 0;
}

.pmm-notification-row__title {
  font-weight: 600;
  font-size: 13px;
  color: var(--pmm-text-primary);
}

.pmm-notification-row__body {
  font-size: 12px;
  color: var(--pmm-text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.pmm-notification-row__time {
  font-size: 11px;
  color: var(--pmm-text-tertiary);
}

/* ===========================================================================
 * KeyboardShortcutsHelp — '?' overlay with grouped shortcut rows.
 * =========================================================================== */
.pmm-shortcuts-help__section {
  margin-bottom: var(--lumo-space-m);
}

.pmm-shortcuts-help__heading {
  font-size: 13px;
  font-weight: 700;
  margin: 0 0 8px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--pmm-text-tertiary);
}

.pmm-shortcuts-help__row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 6px 0;
  border-bottom: 1px solid var(--pmm-border-subtle);
}

.pmm-shortcuts-help__row:last-child {
  border-bottom: 0;
}

.pmm-shortcuts-help__key {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
  font-size: 12px;
  font-weight: 600;
  padding: 3px 8px;
  border-radius: 4px;
  background: var(--pmm-bg-elev0);
  border: 1px solid var(--pmm-border);
  color: var(--pmm-text-primary);
  min-width: 96px;
  text-align: center;
}

.pmm-shortcuts-help__desc {
  font-size: 13px;
  color: var(--pmm-text-secondary);
  flex: 1;
}

/* ===========================================================================
 * Top-bar global search trigger — Phase E1 (second discovery path).
 * Visible "input"-shaped affordance in the chrome navbar that opens the
 * existing CommandPalette dialog on click. Keyboard users still hit
 * Cmd/Ctrl+K; mouse users now have a discoverable surface. Pattern
 * lifted from Stripe / Linear / Vercel chrome.
 *
 * Structure (see GlobalSearchTrigger.java):
 *   .pmm-search-trigger              ← clickable Div (role="button")
 *     .pmm-search-trigger__icon      ← left search glyph
 *     .pmm-search-trigger__placeholder  ← "Search features and pages…"
 *     .pmm-search-trigger__hint      ← keyboard hint chip (⌘K / Ctrl+K)
 * =========================================================================== */
.pmm-search-trigger {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  max-width: 420px;
  padding: 7px 12px;
  border-radius: 10px;
  background: var(--pmm-surface-2);
  border: 1px solid var(--pmm-border-subtle);
  color: var(--pmm-text-tertiary);
  cursor: text;
  transition: background-color 120ms ease, border-color 120ms ease,
              box-shadow 120ms ease;
  user-select: none;
  /* Center horizontally inside the expanded slot so on wide screens the
   * trigger feels like a hero element rather than left-aligned right
   * after the brand. */
  margin: 0 auto;
}

.pmm-search-trigger:hover {
  background: var(--lumo-contrast-10pct, rgba(255, 255, 255, 0.04));
  border-color: var(--pmm-border, rgba(17, 18, 38, 0.12));
  color: var(--pmm-text-secondary);
}

.pmm-search-trigger:focus-visible {
  outline: none;
  border-color: var(--pmm-accent-primary, #6f5cff);
  box-shadow: 0 0 0 3px var(--pmm-accent-ring, rgba(111, 92, 255, 0.25));
}

.pmm-search-trigger__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  color: var(--pmm-text-tertiary);
}

.pmm-search-trigger__icon vaadin-icon,
.pmm-search-trigger__icon iron-icon {
  width: 16px;
  height: 16px;
}

.pmm-search-trigger__placeholder {
  flex: 1 1 auto;
  font-size: 14px;
  color: var(--pmm-text-tertiary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.pmm-search-trigger__hint {
  flex: 0 0 auto;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.02em;
  padding: 2px 8px;
  border-radius: 6px;
  background: var(--pmm-bg-elev1, rgba(0, 0, 0, 0.04));
  border: 1px solid var(--pmm-border-subtle);
  color: var(--pmm-text-secondary);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

/* ===========================================================================
 * Command palette dialog refinements — Phase E1.
 * The base dialog is Vaadin's; we just tighten the layout, add a clear
 * focus state for the highlighted result row, and provide a no-matches
 * empty state. Hovering or arrow-key-highlighting a row paints it with
 * the palette accent so the user always knows what Enter will activate.
 * =========================================================================== */
.pmm-command-palette::part(overlay) {
  border-radius: 14px;
}

.pmm-command-palette__search {
  margin: 12px 12px 4px;
}

.pmm-command-palette__results {
  max-height: 50vh;
  overflow-y: auto;
  padding: 4px 8px 12px;
}

/* The highlighted (selected) row — Vaadin renders it via aria-selected. */
.pmm-command-palette__results vaadin-item[selected],
.pmm-command-palette__results vaadin-item:hover {
  background: var(--pmm-surface-2);
  border-radius: 8px;
}

.pmm-command-palette__results vaadin-item[selected] .pmm-command-palette__row vaadin-icon,
.pmm-command-palette__results vaadin-item:hover .pmm-command-palette__row vaadin-icon {
  color: var(--pmm-accent-primary, #6f5cff) !important;
}

.pmm-command-palette__empty {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  padding: 18px 20px 22px;
  color: var(--pmm-text-secondary);
}

.pmm-command-palette__empty-line1 {
  font-size: 14px;
  font-weight: 600;
  color: var(--pmm-text-primary);
}

.pmm-command-palette__empty-line2 {
  font-size: 12px;
  color: var(--pmm-text-tertiary);
}

/* ===========================================================================
 * Mobile drawer adjustments — Phase F1.
 * Below 768px the brand greeting is noisy, the bell + theme toggle
 * fight the logout for tap area, and the side-nav drawer is too narrow
 * to comfortably tap submenus. Reflow the chrome accordingly.
 * =========================================================================== */
@media (max-width: 768px) {
  /* Drop the personal greeting on small screens — saves ~140px of header
   * real estate that gets eaten by the bell + theme toggle + logout. */
  vaadin-app-layout::part(navbar) .pmm-greeting,
  vaadin-app-layout vaadin-horizontal-layout > span.pmm-greeting {
    display: none;
  }

  /* Logout becomes an icon-only button below 768px; the "Log out" label
   * was the single biggest header element on mobile. */
  vaadin-app-layout vaadin-horizontal-layout > vaadin-button:last-child {
    --lumo-button-size: 36px;
    min-width: 36px;
  }

  /* Tighten side-nav padding so submenu items don't wrap. */
  vaadin-app-layout::part(drawer) vaadin-side-nav-item {
    padding-left: 8px;
    padding-right: 8px;
  }

  /* Search trigger collapses to icon-only on mobile — the placeholder
   * text and the Ctrl+K chip both consume real estate the bell + theme
   * toggle + logout need more. The icon alone is still a discoverable
   * tap target; users can also hit Cmd/Ctrl+K (irrelevant on mobile)
   * or just navigate via the drawer. */
  .pmm-search-trigger {
    max-width: 44px;
    padding: 7px;
    justify-content: center;
  }

  .pmm-search-trigger__placeholder,
  .pmm-search-trigger__hint {
    display: none;
  }
}

/* ===========================================================================
 * Dark mode for public payment surfaces — Phase F4.
 * Public pay views ({.pmm-pay-card}, etc.) already use the design-system
 * tokens, but the route doesn't include a theme toggle. The merchant chrome
 * does. This block lets a host page that prefers dark mode opt-in via
 * `<html data-theme="dark">`, which is what the existing ThemeToggle writes.
 * =========================================================================== */
:root[data-theme="dark"] .pmm-pay-card {
  background: var(--pmm-bg-elev1);
  color: var(--pmm-text-primary);
  border-color: var(--pmm-border);
}

:root[data-theme="dark"] .pmm-pay-card label,
:root[data-theme="dark"] .pmm-pay-card .pmm-eyebrow {
  color: var(--pmm-text-secondary);
}

/* ===========================================================================
 * Recently visited (Phase F5) — sticky section above the main side nav.
 * Implementation uses a {@code <vaadin-side-nav>} with class {@code .pmm-recent-nav};
 * the heading lives in the SideNav's label slot. Older legacy class names
 * (.pmm-recent-visited*) kept below so any third-party / archived markup
 * still renders correctly.
 * =========================================================================== */
.pmm-recent-section {
  margin: 0 0 8px;
  padding: 0;
  border-bottom: 1px solid var(--pmm-border-subtle);
}

.pmm-recent-nav::part(label) {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--pmm-text-tertiary);
  padding: 12px 16px 6px;
}

.pmm-recent-nav vaadin-side-nav-item::part(item) {
  font-size: 13px;
  color: var(--pmm-text-secondary);
}

.pmm-recent-nav vaadin-side-nav-item::part(item):hover {
  background: var(--pmm-surface-2);
  color: var(--pmm-text-primary);
}

/* --- Legacy class names retained for back-compat --- */
.pmm-recent-visited {
  margin-top: var(--lumo-space-m);
  padding: 8px 12px;
  border-top: 1px solid var(--pmm-border-subtle);
}

.pmm-recent-visited__heading {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--pmm-text-tertiary);
  margin: 0 0 6px;
}

.pmm-recent-visited__item {
  display: block;
  padding: 6px 8px;
  font-size: 13px;
  color: var(--pmm-text-secondary);
  border-radius: 6px;
  cursor: pointer;
  transition: background 100ms ease, color 100ms ease;
  text-decoration: none;
}

.pmm-recent-visited__item:hover {
  background: color-mix(in oklab, var(--pmm-brand) 8%, transparent);
  color: var(--pmm-text-primary);
}

/* ===========================================================================
 * Form builder — tighter, more modern density. Replaces the legacy 3-panel
 * layout's loose spacing + duplicated headings.
 * =========================================================================== */
.pmm-form-builder {
  padding: var(--lumo-space-m);
}

.pmm-form-builder__toolbar {
  position: sticky;
  top: 0;
  z-index: 5;
  padding: 8px 12px;
  background: var(--pmm-bg-elev1);
  border: 1px solid var(--pmm-border);
  border-radius: var(--pmm-shape-md);
  margin-bottom: var(--lumo-space-s);
  backdrop-filter: blur(8px);
}

/*
 * Form builder columns: palette (240px) | canvas (flex) | inspector (320px).
 *
 * These are laid out by a Vaadin HorizontalLayout, which does NOT wrap. With
 * two fixed-width panels totalling 560px plus gaps, anything under roughly
 * 900px squeezed the canvas to nothing and the panels ran into each other —
 * widgets overlapping, form unusable. There were no responsive rules for this
 * layout at all.
 *
 * Fix: allow wrapping, and below the breakpoint let every column go full
 * width and stack. min-width:0 on the canvas is the load-bearing bit — a flex
 * item defaults to min-width:auto, so the canvas refuses to shrink below its
 * content and pushes the inspector out of the viewport instead of the columns
 * reflowing.
 */
.pmm-form-builder__cols {
  align-items: stretch;
  /* Wrapping is for the stacked breakpoint only. Left on at all widths it
     let the three columns break onto separate rows on a full-size desktop,
     which is exactly the complaint this layout exists to answer. The
     stacked media query below turns it back on deliberately. */
  flex-wrap: nowrap;
}

.pmm-form-builder__palette,
.pmm-form-builder__inspector {
  background: var(--pmm-bg-elev1);
  border: 1px solid var(--pmm-border);
  border-radius: var(--pmm-shape-md);
  padding: 10px 12px;
  overflow-y: auto;
  max-height: 78vh;
  /* Fixed px width is set inline by the view; keep it from being flexed
     narrower than its content on mid-size screens. */
  flex-shrink: 0;
}

/* The canvas must be allowed to shrink, or it shoves the inspector off-screen. */
.pmm-form-builder__cols > *:not(.pmm-form-builder__palette):not(.pmm-form-builder__inspector) {
  min-width: 0;
}

/* The preview stays in normal flow, below the columns.
 *
 * It was briefly pinned to the bottom of the viewport, on the theory that
 * checking a change shouldn't mean scrolling away from it. Measured with a
 * real form on the canvas, that was clearly worse: at 34vh it covered the
 * bottom 40% of the canvas permanently, so you gained a preview and lost
 * the thing being previewed. Three sticky columns plus a pinned panel is
 * more furniture than a 900px viewport can hold.
 *
 * flex: 0 0 auto IS still needed. The page is a fixed-height flex column,
 * and the default 0 1 auto let the columns above claim every pixel and
 * squeezed the preview to a 2px sliver — present in the DOM, sized to
 * nothing, invisible. Refusing to shrink is what makes it a real panel. */
.pmm-form-builder__tabs {
  flex: 0 0 auto;
  min-height: 200px;
}

/* Wide screens: the side panels follow you.
   Each panel used to be its own 78vh scroll box, so a long form gave three
   independent scrollbars and the properties you were editing slid out of
   view as you moved down the canvas — the "everything is somewhere else"
   complaint. Sticky pins them beside the canvas instead. */
/* 1280, not 1024.
 *
 * Three columns need roughly 1150px of CONTENT width: palette 240 +
 * inspector 320 + gaps, and a canvas wide enough to render a form field.
 * The nav drawer eats ~256px of the viewport, so a 1100px window leaves
 * about 844 — and the canvas was being squeezed to 205px with its blocks
 * spilling out of it. A 1024 breakpoint claimed the three-column layout
 * worked on exactly the laptop widths where it was at its worst.
 *
 * Below 1280 the stacked layout takes over, which gives the canvas the
 * full width instead of a sliver. */
@media (min-width: 1281px) {
  .pmm-form-builder__palette,
  .pmm-form-builder__inspector {
    position: sticky;
    top: 8px;
    align-self: flex-start;
  }
}

@media (max-width: 1280px) {
  /* Stack: each panel takes the full row. The inline widths (240/320px) are
     overridden here — on a narrow screen a 240px palette beside a 320px
     inspector leaves the canvas unusable even when it fits.
     Raised from 1024 to 1280: measured at 1100px the canvas was 205px wide
     with 91 elements spilling out of it, because the drawer takes ~256px
     before the columns get a say. */
  .pmm-form-builder__cols {
    flex-direction: column;
    /* Stacking is intended here — this is the one place it helps. */
    flex-wrap: wrap;
  }
  /* Full width once stacked, and back to sizing from content.
     flex: 1 1 0 is right for a ROW — grow from nothing to fill the space
     the fixed side panels don't claim. In a COLUMN the same rule reads as
     "zero height basis", and inside a fixed-height page there is no free
     space to grow into, so the canvas collapsed to a 50px strip with the
     form scrolled away inside it. Content height with a floor is what a
     stacked canvas actually wants. */
  .pmm-form-builder__canvas-wrap {
    width: 100%;
    flex: 0 0 auto;
    min-height: 240px;
  }
  .pmm-form-builder__palette,
  .pmm-form-builder__inspector {
    width: 100% !important;
    max-width: 100%;
    /* Don't let a stacked panel eat the screen — the canvas is the point. */
    max-height: 40vh;
  }

  /* Order matters more than position once stacked. The canvas is what you
     look at, and the properties of the field you just tapped must be the
     next thing under it — not below a full-height canvas you have to scroll
     past. The palette becomes a compact strip pinned to the top, so adding
     a field never means scrolling back up. */
  .pmm-form-builder__palette {
    order: -1;
    position: sticky;
    top: 0;
    z-index: 3;
    max-height: 24vh;
  }
  .pmm-form-builder__cols > *:not(.pmm-form-builder__palette):not(.pmm-form-builder__inspector) {
    order: 0;
    /* Capped so a form with twenty fields doesn't bury the inspector under
       a screen and a half of canvas. Scrolls within itself instead. */
    max-height: 52vh;
    overflow-y: auto;
  }
  .pmm-form-builder__inspector {
    order: 1;
  }
  /* Horizontal drag from palette to canvas doesn't exist when stacked, so the
     palette reads as a compact row of choices rather than a tall column. */
  .pmm-form-builder__palette .pmm-form-builder__category {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
  }
  .pmm-form-builder__palette .pmm-form-builder__palette-card {
    flex: 0 0 auto;
  }
}

.pmm-form-builder__panel-title {
  margin: 0 0 4px;
  font-size: 13px;
  font-weight: 700;
  color: var(--pmm-text-primary);
}

.pmm-form-builder__panel-hint {
  display: block;
  font-size: 11px;
  color: var(--pmm-text-tertiary);
  margin-bottom: 8px;
}

.pmm-form-builder__category {
  margin-top: 12px;
}

.pmm-form-builder__palette-card {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  margin-bottom: 6px;
  background: var(--pmm-surface-1);
  border: 1px solid var(--pmm-border-subtle);
  border-radius: 8px;
  cursor: grab;
  user-select: none;
  font-size: 13px;
  transition: background 120ms ease, border-color 120ms ease,
              transform 120ms ease, box-shadow 120ms ease;
}

.pmm-form-builder__palette-card:hover {
  background: var(--pmm-brand-softer);
  border-color: var(--pmm-brand-soft);
  transform: translateX(2px);
  box-shadow: 0 1px 3px rgba(124, 58, 237, 0.08);
}
.pmm-form-builder__palette-card:hover .pmm-form-builder__palette-icon {
  color: var(--pmm-brand);
}
.pmm-form-builder__palette-card:hover .pmm-form-builder__palette-label {
  color: var(--pmm-brand-text);
}

.pmm-form-builder__palette-card:active {
  cursor: grabbing;
  transform: scale(0.98);
}

/* Group header in the palette — Stitch-style uppercase eyebrow with
 * collapse chevron on the right. */
.pmm-form-builder__category {
  margin-top: 16px;
}
.pmm-form-builder__category-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--pmm-text-tertiary);
}

/* Drop-zone glow indicator — appears between fields when a palette item
 * is dragged over the canvas. */
.pmm-form-builder__drop-zone {
  height: 36px;
  border: 2px dashed var(--pmm-brand-soft);
  background: var(--pmm-brand-softer);
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 500;
  color: var(--pmm-brand-text);
  margin: 8px 0;
  animation: pmm-drop-pulse 1.4s ease-in-out infinite;
}
@keyframes pmm-drop-pulse {
  0%, 100% { opacity: 0.7; }
  50%      { opacity: 1; box-shadow: 0 0 0 4px rgba(124, 58, 237, 0.06); }
}

/* ===========================================================================
 * Form Builder — live-preview canvas blocks (Stitch v1).
 *
 * Each block renders the field as customers will see it (read-only Vaadin
 * input). Hover-only handle bar floats top-right with drag/up/down/copy/
 * delete actions. Selected block gets a violet ring + soft brand tint.
 * =========================================================================== */
.pmm-builder-block {
  position: relative;
  /* NEVER shrink. This is the one that made the builder look broken.
   *
   * The blocks are flex children of a column inside a height-bounded
   * canvas, so with the default flex-shrink:1 they were squeezed to fit:
   * every block rendered 30px tall while its content needed 71-156px, and
   * because the block also sets overflow:hidden, each field's label and
   * input were sliced off mid-line. On screen that reads as the widgets
   * overlapping each other. Measuring the canvas panel showed nothing --
   * the panel was fine, its contents were being crushed inside it.
   *
   * Refusing to shrink lets each block take its natural height and the
   * canvas scroll, which is what overflow-y:auto on the wrapper is for. */
  flex: 0 0 auto;
  /* Extra left padding reserves space for the drag-handle gutter; the
     handle itself sits inside the block at position:absolute so the
     existing content alignment is preserved. */
  padding: 14px 16px 14px 36px;
  margin-bottom: 12px;
  background: var(--pmm-surface-1);
  border: 1px solid var(--pmm-border-subtle);
  border-radius: 12px;
  cursor: pointer;
  /* Hard-cap the block to its parent's width so widgets never spill out
   * horizontally — half-width cells (200px) used to overflow when an
   * input had a long placeholder + prefix icon. */
  width: 100%;
  max-width: 100%;
  min-width: 0;
  box-sizing: border-box;
  overflow: hidden;
  transition: box-shadow 150ms var(--pmm-ease-standard),
              border-color 150ms var(--pmm-ease-standard),
              background 150ms var(--pmm-ease-standard);
}
.pmm-builder-block:hover {
  border-color: var(--pmm-brand-soft);
  box-shadow: 0 1px 3px rgba(124, 58, 237, 0.08),
              0 4px 12px rgba(124, 58, 237, 0.04);
}
.pmm-builder-block--selected {
  border-color: var(--pmm-brand);
  background: color-mix(in oklab, var(--pmm-brand) 4%, var(--pmm-surface-1));
  box-shadow: 0 0 0 1px var(--pmm-brand),
              0 4px 16px rgba(124, 58, 237, 0.12);
}

/* Type pill — small uppercase eyebrow showing the field type. Hidden by
 * default, fades in on hover or when block is selected. */
/* What a form field is used for (payment amount, amount choices, receipt email) -
   always visible on the builder canvas, unlike the hover-only badges. */
.pmm-builder-block__role {
  display: inline-block;
  margin: 0 0 6px 0;
  font-size: 11px;
  font-weight: 600;
  color: var(--pmm-info-text);
  background: var(--pmm-info-bg);
  padding: 2px 8px;
  border-radius: 9999px;
}

.pmm-builder-block__type {
  position: absolute;
  top: 8px;
  /* Clear the left drag-handle gutter (28px wide). */
  left: 36px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--pmm-text-tertiary);
  background: var(--pmm-surface-2);
  padding: 2px 8px;
  border-radius: 9999px;
  opacity: 0;
  transition: opacity 150ms var(--pmm-ease-standard);
  pointer-events: none;
}
.pmm-builder-block:hover .pmm-builder-block__type,
.pmm-builder-block--selected .pmm-builder-block__type {
  opacity: 1;
}
.pmm-builder-block--selected .pmm-builder-block__type {
  background: var(--pmm-brand-soft);
  color: var(--pmm-brand-text);
}

/* "Required" mini-badge — tucked top-right, fades in alongside the type. */
.pmm-builder-block__required {
  position: absolute;
  top: 8px;
  right: 200px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--pmm-error-text);
  background: var(--pmm-error-bg);
  padding: 2px 8px;
  border-radius: 9999px;
  opacity: 0;
  transition: opacity 150ms var(--pmm-ease-standard);
  pointer-events: none;
}
.pmm-builder-block:hover .pmm-builder-block__required,
.pmm-builder-block--selected .pmm-builder-block__required {
  opacity: 1;
}

/* Preview wrapper — adds top-padding when type pill is visible so the
 * pill doesn't overlap the field's own label. */
.pmm-builder-block__preview {
  padding-top: 12px;
}
.pmm-builder-block__preview vaadin-text-field,
.pmm-builder-block__preview vaadin-text-area,
.pmm-builder-block__preview vaadin-email-field,
.pmm-builder-block__preview vaadin-number-field,
.pmm-builder-block__preview vaadin-password-field,
.pmm-builder-block__preview vaadin-date-picker,
.pmm-builder-block__preview vaadin-time-picker,
.pmm-builder-block__preview vaadin-combo-box,
.pmm-builder-block__preview vaadin-radio-group {
  pointer-events: none; /* Block isn't editable — selection happens by clicking */
  width: 100%;
}

/* Heading-like blocks — TEXT_LABEL renders as a heading inside a block. */
.pmm-builder-block__heading {
  display: block;
  font-size: 16px;
  font-weight: 600;
  color: var(--pmm-text-primary);
  padding: 4px 0;
}
.pmm-builder-block__heading--main {
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -0.01em;
}
.pmm-builder-block__divider {
  border: 0;
  height: 1px;
  background: var(--pmm-border-default);
  margin: 8px 0;
}

/* File-upload preview — dashed drop-zone box. */
.pmm-builder-block__upload {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.pmm-builder-block__upload-label {
  font-size: 12px;
  font-weight: 500;
  color: var(--pmm-text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.pmm-builder-block__upload-drop {
  border: 2px dashed var(--pmm-border-default);
  background: var(--pmm-surface-2);
  border-radius: 10px;
  padding: 24px;
  text-align: center;
  font-size: 13px;
  color: var(--pmm-text-tertiary);
}

/* Payment-method preview — block where the gateway picker would be. */
.pmm-builder-block__pay-preview {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 12px 14px;
  background: var(--pmm-brand-softer);
  border: 1px dashed var(--pmm-brand-soft);
  border-radius: 10px;
}
.pmm-builder-block__pay-eyebrow {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--pmm-brand-text);
}
.pmm-builder-block__pay-hint {
  font-size: 13px;
  color: var(--pmm-text-secondary);
}

/* Submit-button preview — actual button, disabled so it doesn't fire. */
.pmm-builder-block__submit-preview {
  width: 100%;
  height: 48px;
  border-radius: 12px;
  margin-top: 4px;
}

/* ===========================================================================
 * Hand-rolled field-preview primitives (.pmm-fp__*) — Stitch v1 fidelity.
 *
 * These replace the Vaadin web-component shadow-DOM previews so the
 * canvas matches Stitch's exact aesthetic. Each block renders pure HTML
 * with full CSS reach.
 * =========================================================================== */
.pmm-fp__group {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.pmm-fp__label {
  font-size: 11px;
  font-weight: 600;
  color: var(--pmm-text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.pmm-fp__req {
  color: var(--pmm-error);
  font-weight: 700;
  margin-left: 2px;
}

/* Outlined input — TEXT_FIELD / EMAIL / NUMBER / PASSWORD render as this
 * placeholder-only outlined box that mirrors the public form's actual
 * input styling. Hand-rolled so we control radius, border, focus ring. */
.pmm-fp__input {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 44px;
  padding: 0 14px;
  border-radius: 10px;
  border: 1.5px solid var(--pmm-border-default);
  background: var(--pmm-surface-1);
  font-size: 14px;
  color: var(--pmm-text-primary);
  transition: border-color var(--pmm-dur-short) var(--pmm-ease-standard);
  /* Always 100% of the parent block. Long placeholders inside half-width
   * cells used to overflow horizontally; ellipsis truncation keeps the
   * preview tight. */
  width: 100%;
  max-width: 100%;
  min-width: 0;
  box-sizing: border-box;
  overflow: hidden;
}
.pmm-fp__input .pmm-fp__placeholder {
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.pmm-builder-block:hover .pmm-fp__input {
  border-color: color-mix(in oklab, var(--pmm-brand) 35%, var(--pmm-border-default));
}
.pmm-builder-block--selected .pmm-fp__input {
  border-color: var(--pmm-brand);
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--pmm-brand) 15%, transparent);
}
.pmm-fp__input-prefix {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  font-weight: 600;
  color: var(--pmm-text-tertiary);
  min-width: 18px;
}
.pmm-fp__placeholder {
  color: var(--pmm-text-tertiary);
  font-size: 14px;
  font-weight: 400;
}

/* Select / dropdown chrome — chevron on the right. */
.pmm-fp__select {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  height: 44px;
  padding: 0 14px;
  border-radius: 10px;
  border: 1.5px solid var(--pmm-border-default);
  background: var(--pmm-surface-1);
  font-size: 14px;
  color: var(--pmm-text-tertiary);
  cursor: default;
  width: 100%;
  max-width: 100%;
  min-width: 0;
  box-sizing: border-box;
  overflow: hidden;
}
.pmm-fp__select > span:first-child {
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.pmm-fp__select svg {
  width: 16px;
  height: 16px;
  color: var(--pmm-text-tertiary);
  flex-shrink: 0;
}
.pmm-fp__select--icon svg {
  color: var(--pmm-brand);
}
.pmm-builder-block:hover .pmm-fp__select {
  border-color: color-mix(in oklab, var(--pmm-brand) 35%, var(--pmm-border-default));
}
.pmm-builder-block--selected .pmm-fp__select {
  border-color: var(--pmm-brand);
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--pmm-brand) 15%, transparent);
}

/* Multi-line text area preview — taller version of the input. */
.pmm-fp__textarea {
  min-height: 96px;
  padding: 12px 14px;
  border-radius: 10px;
  border: 1.5px solid var(--pmm-border-default);
  background: var(--pmm-surface-1);
  font-size: 14px;
  color: var(--pmm-text-tertiary);
  width: 100%;
  max-width: 100%;
  box-sizing: border-box;
  overflow: hidden;
}
.pmm-builder-block:hover .pmm-fp__textarea,
.pmm-builder-block--selected .pmm-fp__textarea {
  border-color: var(--pmm-brand);
}

/* Checkbox preview — tight horizontal row with the box on the left. */
.pmm-fp__check {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: 14px;
  color: var(--pmm-text-primary);
  cursor: default;
}
.pmm-fp__check-box {
  width: 18px;
  height: 18px;
  border-radius: 5px;
  border: 1.5px solid var(--pmm-border-strong);
  background: var(--pmm-surface-1);
  flex-shrink: 0;
}

/* Radio group preview — vertical list of options, first one selected. */
.pmm-fp__radio {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 0;
  font-size: 14px;
  color: var(--pmm-text-primary);
}
.pmm-fp__radio-dot {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 1.5px solid var(--pmm-border-strong);
  background: var(--pmm-surface-1);
  flex-shrink: 0;
  position: relative;
}
.pmm-fp__radio--checked .pmm-fp__radio-dot {
  border-color: var(--pmm-brand);
}
.pmm-fp__radio--checked .pmm-fp__radio-dot::after {
  content: "";
  position: absolute;
  inset: 3px;
  border-radius: 50%;
  background: var(--pmm-brand);
}

/* File-upload preview — dashed drop-zone with cloud-up icon. */
.pmm-fp__upload {
  border: 2px dashed var(--pmm-border-default);
  border-radius: 12px;
  background: var(--pmm-surface-2);
  padding: 24px;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  color: var(--pmm-text-secondary);
}
.pmm-fp__upload svg {
  width: 28px;
  height: 28px;
  color: var(--pmm-brand);
  margin-bottom: 4px;
}
.pmm-fp__upload strong {
  color: var(--pmm-brand-text);
  font-weight: 600;
}
.pmm-fp__upload small {
  font-size: 11px;
  color: var(--pmm-text-tertiary);
}
.pmm-builder-block:hover .pmm-fp__upload {
  border-color: var(--pmm-brand);
  background: var(--pmm-brand-softer);
}

/* Headings — TEXT_LABEL renders as a heading inside the block. */
.pmm-fp__heading {
  font-size: 16px;
  font-weight: 600;
  color: var(--pmm-text-primary);
}
.pmm-fp__heading--main {
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--pmm-text-primary);
}
.pmm-fp__divider {
  border: 0;
  height: 1px;
  background: var(--pmm-border-default);
  margin: 4px 0;
}

/* Hyperlink preview — violet-text link styling. */
.pmm-fp__link {
  color: var(--pmm-brand-text);
  font-weight: 500;
  text-decoration: underline;
  text-decoration-thickness: 1.5px;
  text-underline-offset: 3px;
}

/* Image placeholder — soft surface card with image-icon + label. */
.pmm-fp__image {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 120px;
  background: var(--pmm-surface-2);
  border: 1px dashed var(--pmm-border-default);
  border-radius: 10px;
  color: var(--pmm-text-tertiary);
  font-size: 13px;
}
.pmm-fp__image svg {
  width: 32px;
  height: 32px;
}

/* Popup preview — info pill with circle-info icon. */
.pmm-fp__popup {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  background: var(--pmm-info-bg);
  color: var(--pmm-info-text);
  border-radius: 10px;
  font-size: 13px;
  font-weight: 500;
}
.pmm-fp__popup svg {
  width: 16px;
  height: 16px;
}

/* Quantity / price stepper preview — for VALUE_TEXT (qty × price). */
.pmm-fp__qty {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 14px;
  background: var(--pmm-surface-2);
  border: 1px solid var(--pmm-border-subtle);
  border-radius: 10px;
}
.pmm-fp__qty-text {
  display: flex;
  flex-direction: column;
}
.pmm-fp__qty-name {
  font-size: 14px;
  font-weight: 500;
  color: var(--pmm-text-primary);
}
.pmm-fp__qty-price {
  font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13px;
  font-weight: 600;
  color: var(--pmm-brand-text);
}
.pmm-fp__qty-stepper {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: var(--pmm-surface-1);
  border: 1px solid var(--pmm-border-default);
  border-radius: 9999px;
  padding: 2px;
}
.pmm-fp__qty-stepper button {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 0;
  background: transparent;
  color: var(--pmm-text-secondary);
  font-size: 16px;
  font-weight: 600;
  cursor: default;
}
.pmm-fp__qty-stepper span {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 13px;
  font-weight: 600;
  color: var(--pmm-text-primary);
  min-width: 16px;
  text-align: center;
}

/* Payment-method preview — Stitch's gateway-chip row with eyebrow. */
.pmm-fp__pay {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px 16px;
  background: color-mix(in oklab, var(--pmm-brand) 4%, var(--pmm-surface-1));
  border: 1px solid color-mix(in oklab, var(--pmm-brand) 20%, var(--pmm-border-subtle));
  border-radius: 12px;
}
.pmm-fp__pay-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--pmm-brand-text);
}
.pmm-fp__pay-eyebrow svg {
  width: 14px;
  height: 14px;
}
.pmm-fp__pay-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.pmm-fp__pay-chip {
  padding: 5px 12px;
  border-radius: 9999px;
  background: var(--pmm-surface-1);
  border: 1px solid var(--pmm-border-default);
  font-size: 12px;
  font-weight: 500;
  color: var(--pmm-text-primary);
}
.pmm-fp__pay-chip--active {
  background: var(--pmm-brand);
  border-color: var(--pmm-brand);
  color: var(--pmm-text-on-brand);
}
.pmm-fp__pay-chip--more {
  background: transparent;
  border: 1px dashed var(--pmm-border-default);
  color: var(--pmm-text-tertiary);
}
.pmm-fp__pay-hint {
  font-size: 12px;
  color: var(--pmm-text-secondary);
}

/* Image-carousel preview (Vaadin v1 builder canvas) — first image with
 * a "1 / N" badge. Customer-facing carousel with arrows + dots lives in
 * pay-v2.html. */
.pmm-fp__carousel {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  border-radius: 12px;
  overflow: hidden;
  background: var(--pmm-surface-2);
  border: 1px solid var(--pmm-border-default);
}
.pmm-fp__carousel img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.pmm-fp__carousel-count {
  position: absolute;
  top: 8px;
  right: 8px;
  padding: 3px 10px;
  border-radius: 9999px;
  background: rgba(0, 0, 0, 0.6);
  color: #fff;
  font-size: 11px;
  font-weight: 600;
  backdrop-filter: blur(6px);
}
.pmm-fp__carousel--video::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, transparent 50%, rgba(0,0,0,0.4) 100%);
  pointer-events: none;
}
.pmm-fp__embed-play {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.9);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: #111226;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.30);
}
.pmm-fp__embed-play svg { width: 18px; height: 18px; margin-left: 2px; }

/* Submit-button preview — full-width violet pill, the actual CTA. */
.pmm-fp__submit {
  width: 100%;
  height: 52px;
  border-radius: 14px;
  border: 0;
  background: var(--pmm-brand-gradient);
  color: var(--pmm-text-on-brand);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 0.2px;
  cursor: default;
  box-shadow:
    0 6px 16px rgba(124, 58, 237, 0.22),
    0 2px 4px rgba(124, 58, 237, 0.18);
  opacity: 1;
}
.pmm-fp__submit[disabled] { opacity: 1; cursor: default; }

/* Quick-pick chip row — RADIO with preset=true renders as Stitch's
 * horizontal amount/option chips. First option highlighted active. */
.pmm-fp__chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 4px;
}
.pmm-fp__chip {
  padding: 8px 16px;
  border-radius: 9999px;
  background: var(--pmm-surface-1);
  border: 1.5px solid var(--pmm-border-default);
  font-size: 14px;
  font-weight: 500;
  color: var(--pmm-text-primary);
  font-variant-numeric: tabular-nums;
  cursor: default;
  transition: background var(--pmm-dur-short) var(--pmm-ease-standard),
              border-color var(--pmm-dur-short) var(--pmm-ease-standard);
}
.pmm-fp__chip--active {
  background: var(--pmm-brand);
  border-color: var(--pmm-brand);
  color: var(--pmm-text-on-brand);
  font-weight: 600;
  box-shadow: 0 4px 10px rgba(124, 58, 237, 0.20);
}
.pmm-builder-block:hover .pmm-fp__chip:not(.pmm-fp__chip--active) {
  border-color: color-mix(in oklab, var(--pmm-brand) 35%, var(--pmm-border-default));
}

/* 50/50 row — two adjacent half-width fields lay out side-by-side. The
 * row wraps to single column under 600px so mobile preview stays clean.
 * minmax(0, 1fr) prevents grid blow-out when child content is wider
 * than the cell (default min-width: auto would force the cell to grow). */
.pmm-builder-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 12px;
  margin-bottom: 12px;
  width: 100%;
}
.pmm-builder-row .pmm-builder-block {
  margin-bottom: 0;
  min-width: 0;
}
@media (max-width: 600px) {
  .pmm-builder-row {
    grid-template-columns: 1fr;
  }
}

/* When a TEXT_LABEL has fontSize 14 (description), render it more like
 * body copy rather than a heading — this matches the donation template's
 * description block sitting under the main title. */
.pmm-fp__heading {
  line-height: 1.4;
}

/* Undo / redo button cluster — top-bar ghost icons in a tight group. */
.pmm-form-builder__undo-group {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 2px;
  border-radius: 8px;
  background: var(--pmm-surface-2);
  margin-right: 4px;
}
.pmm-form-builder__undo-group vaadin-button {
  --lumo-button-size: 30px;
  min-width: 30px;
}

/* Publish primary CTA — slightly more emphasis than Save (which became
 * tertiary). When the form is already published the button shows
 * "Published" with a green ring. */
.pmm-form-builder__publish vaadin-icon {
  color: currentColor;
  width: 14px;
  height: 14px;
}

/* Drop-zone glow on the canvas — fires when a palette item is dragged
 * over. The class is toggled by the dragenter / dragleave handlers on
 * the canvas DropTarget element. */
.pmm-form-builder__canvas.pmm-drop-active {
  border-color: var(--pmm-brand);
  background: color-mix(in oklab, var(--pmm-brand) 6%, var(--pmm-surface-1));
  box-shadow:
    0 0 0 4px color-mix(in oklab, var(--pmm-brand) 12%, transparent),
    0 8px 32px rgba(124, 58, 237, 0.16);
}
.pmm-form-builder__canvas.pmm-drop-active::after {
  content: "Drop to add field";
  position: absolute;
  top: 12px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--pmm-brand);
  color: var(--pmm-text-on-brand);
  padding: 4px 12px;
  border-radius: 9999px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  pointer-events: none;
  z-index: 5;
  animation: pmm-drop-pulse 1.4s ease-in-out infinite;
}

/* Hover-only handle bar — top-right cluster with drag/up/down/copy/delete.
 * Hidden by default; fades in on block hover or when selected. */
.pmm-builder-block__handles {
  position: absolute;
  top: 6px;
  right: 8px;
  display: inline-flex;
  align-items: center;
  gap: 2px;
  background: var(--pmm-surface-1);
  border: 1px solid var(--pmm-border-subtle);
  border-radius: 8px;
  padding: 2px;
  box-shadow: 0 1px 4px rgba(15, 17, 23, 0.06);
  opacity: 0;
  transform: translateY(-2px);
  transition: opacity 150ms var(--pmm-ease-standard),
              transform 150ms var(--pmm-ease-standard);
}
.pmm-builder-block:hover .pmm-builder-block__handles,
.pmm-builder-block--selected .pmm-builder-block__handles {
  opacity: 1;
  transform: translateY(0);
}
.pmm-builder-block__handle {
  --lumo-button-size: 28px;
  min-width: 28px;
  width: 28px;
  height: 28px;
  padding: 0;
  margin: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--pmm-text-secondary);
}
.pmm-builder-block__handle:hover {
  background: var(--pmm-brand-softer);
  color: var(--pmm-brand);
}
.pmm-builder-block__handle--drag { cursor: grab; }

/* Left-side drag-handle gutter — Notion / Linear pattern. Sits at the
   leading edge of every canvas block as a six-dot icon; visible only on
   row hover or when the row is selected. Drag origin lives here so the
   click-anywhere-to-select behaviour on the block isn't hijacked by an
   accidental grab attempt. */
.pmm-builder-block__gutter {
  position: absolute;
  top: 0;
  left: 0;
  width: 28px;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: grab;
  user-select: none;
  color: var(--pmm-text-tertiary);
  opacity: 0;
  transition: opacity 150ms var(--pmm-ease-standard),
              background 150ms var(--pmm-ease-standard);
  border-top-left-radius: 12px;
  border-bottom-left-radius: 12px;
}
.pmm-builder-block:hover .pmm-builder-block__gutter,
.pmm-builder-block--selected .pmm-builder-block__gutter {
  opacity: 1;
}
.pmm-builder-block__gutter:hover {
  background: var(--pmm-brand-softer);
  color: var(--pmm-brand);
}
.pmm-builder-block__gutter:active { cursor: grabbing; }
/* The six-dot indicator — two columns of three dots, drawn with
   gradients to stay one Element (no children needed). */
.pmm-builder-block__gutter::before {
  content: "";
  width: 8px;
  height: 14px;
  background-image:
    radial-gradient(circle, currentColor 1px, transparent 1.5px),
    radial-gradient(circle, currentColor 1px, transparent 1.5px);
  background-size: 4px 4px;
  background-position: 0 0, 4px 0;
  background-repeat: repeat-y;
}
.pmm-builder-block__handle--danger:hover {
  background: var(--pmm-error-bg);
  color: var(--pmm-error);
}
.pmm-builder-block__handle vaadin-icon {
  width: 14px;
  height: 14px;
}

.pmm-form-builder__palette-icon {
  color: var(--pmm-brand);
  flex-shrink: 0;
}

.pmm-form-builder__palette-label {
  font-size: 12px;
  font-weight: 500;
  color: var(--pmm-text-primary);
}

.pmm-form-builder__canvas-wrap {
  background: var(--pmm-surface-0);
  border: 1px solid var(--pmm-border-subtle);
  border-radius: var(--pmm-shape-md);
  padding: 24px;
  overflow-y: auto;
  max-height: 78vh;
  /* Fill the available middle column so the inner canvas card has room
   * to expand to its 720px max-width instead of shrinking to content.
   *
   * Basis 0 rather than auto, and NO width: 100%. Those two together were
   * the whole "everything is somewhere else" bug: a 100%-wide flex item in
   * a wrapping row can never share that row, so the palette and inspector
   * were pushed onto lines of their own — stacked at 1440px just as badly
   * as on a phone. Growing from zero lets all three sit side by side and
   * still gives the canvas every pixel the other two don't claim. */
  flex: 1 1 0;
  min-width: 0;
  box-sizing: border-box;
  /* Stitch-faithful dotted grid background — 16px dots at 4% opacity so
   * empty canvas feels intentional rather than empty. Token-based so it
   * stays visible in light + dark mode. */
  background-image: radial-gradient(
    circle at 1px 1px,
    var(--pmm-border-default) 1px,
    transparent 0
  );
  background-size: 16px 16px;
  background-position: 0 0;
}

/* Form Builder top-bar polish — status pill + last-saved caption tucked
 * next to the form name field. Mirrors Stitch's "DRAFT · Last saved 2m ago". */
.pmm-form-builder__status-group {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-left: 4px;
}
.pmm-form-builder__status {
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  border-radius: 9999px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.pmm-form-builder__status--draft {
  background: var(--pmm-warn-bg);
  color: var(--pmm-warn-text);
  border: 1px solid color-mix(in oklab, var(--pmm-warn) 25%, transparent);
}
.pmm-form-builder__status--published {
  background: var(--pmm-success-bg);
  color: var(--pmm-success-text);
  border: 1px solid color-mix(in oklab, var(--pmm-success) 25%, transparent);
}
.pmm-form-builder__saved {
  font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px;
  color: var(--pmm-text-tertiary);
  font-weight: 500;
}

.pmm-form-builder__canvas {
  min-height: 360px;
  background: var(--pmm-surface-1);
  border: 1px solid var(--pmm-border-subtle);
  border-radius: var(--pmm-shape-md);
  padding: 32px;
  transition: border-color 120ms ease, box-shadow 120ms ease;
  box-shadow: 0 1px 2px rgba(15, 17, 23, 0.04),
              0 8px 24px rgba(15, 17, 23, 0.04);
  /* Width: fill the canvas wrap up to 720px, centered. Without an explicit
   * width: 100%, Vaadin's VerticalLayout shrinks to content (~400px) which
   * causes blocks to look cramped and forces 50/50 rows to overflow on
   * longer placeholders. */
  width: 100%;
  max-width: 720px;
  margin: 0 auto;
  box-sizing: border-box;
}

/* Drag-over state — canvas lights up with brand glow when a field is being
 * dragged from the palette. The host code adds .pmm-drop-active when a
 * DragEnter fires; CSS animates the pulse. */
.pmm-form-builder__canvas.pmm-drop-active {
  border-color: var(--pmm-brand);
  box-shadow: 0 0 0 3px var(--pmm-brand-soft),
              0 8px 24px rgba(124, 58, 237, 0.10);
}

/* Selected field block — violet ring + soft lift, mirrors Stitch. */
.pmm-form-builder__canvas .pmm-field-block--selected,
.pmm-form-builder__canvas [data-selected="true"] {
  outline: 2px solid var(--pmm-brand);
  outline-offset: 2px;
  background: var(--pmm-brand-softer);
  border-radius: var(--pmm-shape-sm);
}

.pmm-form-builder__tabs {
  border: 1px solid var(--pmm-border);
  border-radius: var(--pmm-shape-md);
  background: var(--pmm-bg-elev1);
}

/* Payment-source inspector card — shows the resolved gateway list for the
 * selected PAY_OPTION/PAY_CONTAINER field, driven by the form's container.
 * Stripe/Linear-grade affordance: instead of "configured at render time"
 * mystery copy, the merchant sees exactly what customers will see. */
.pmm-form-builder__pay-source {
  margin-top: var(--lumo-space-s);
  padding: 12px;
  background: linear-gradient(135deg,
      color-mix(in oklab, var(--pmm-brand) 6%, var(--pmm-bg-elev1)) 0%,
      var(--pmm-bg-elev1) 100%);
  border: 1px solid color-mix(in oklab, var(--pmm-brand) 25%, var(--pmm-border));
  border-radius: var(--pmm-shape-md);
}

.pmm-form-builder__pay-source-header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 6px;
}

.pmm-form-builder__pay-source-name {
  font-size: 14px;
  font-weight: 700;
  color: var(--pmm-text-primary);
}

.pmm-form-builder__pay-source-code {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
  font-size: 11px;
  color: var(--pmm-text-tertiary);
  padding: 2px 6px;
  border-radius: 4px;
  background: var(--pmm-bg-elev0);
  border: 1px solid var(--pmm-border);
}

.pmm-form-builder__pay-source-list {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 10px 0 6px;
}

.pmm-form-builder__pay-source-chip {
  font-size: 11px;
  padding: 3px 8px;
}

/* Mode badges in the inspector — Embed = brand-tinted, Redirect = warm
 * accent so the difference is recognisable without reading the label. */
.pmm-form-builder__pay-source-mode--embed {
  font-size: 10px;
  padding: 2px 7px;
  background: color-mix(in oklab, var(--pmm-brand) 15%, var(--pmm-bg-elev0));
  color: var(--pmm-brand);
  border: 1px solid color-mix(in oklab, var(--pmm-brand) 35%, var(--pmm-border));
}

.pmm-form-builder__pay-source-mode--redirect {
  font-size: 10px;
  padding: 2px 7px;
  background: color-mix(in oklab, var(--lumo-warning-color) 15%, var(--pmm-bg-elev0));
  color: var(--lumo-warning-text-color);
  border: 1px solid color-mix(in oklab, var(--lumo-warning-color) 35%, var(--pmm-border));
}

.pmm-form-builder__pay-fallback {
  display: block;
  font-size: 12px;
  color: var(--pmm-text-secondary);
  line-height: 1.4;
  margin: 4px 0 8px;
}

/* Public URL row in the inspector pay-source card. The container's standalone
 * shareable URL — copy/open buttons let the merchant grab the link without
 * leaving the builder. */
.pmm-form-builder__pay-link {
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px dashed var(--pmm-border-default);
}

.pmm-form-builder__pay-link-url {
  display: inline-block;
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
  font-size: 11px;
  padding: 4px 8px;
  margin-top: 4px;
  border-radius: 4px;
  background: var(--pmm-surface-2);
  color: var(--pmm-text-primary);
  border: 1px solid var(--pmm-border-subtle);
  word-break: break-all;
  max-width: 100%;
}

/* Public URL panel on the DirectConnect detail page — same intent as the
 * inspector card but with more breathing room since we're not crammed into a
 * 320px sidebar. */
.pmm-direct-connect-link {
  margin: var(--lumo-space-m) 0;
  padding: 16px 20px;
  border-radius: var(--pmm-shape-md);
  background: linear-gradient(135deg,
      color-mix(in oklab, var(--pmm-brand) 8%, var(--pmm-surface-1)) 0%,
      var(--pmm-surface-1) 100%);
  border: 1px solid color-mix(in oklab, var(--pmm-brand) 30%, var(--pmm-border-default));
}

.pmm-direct-connect-link__url {
  display: inline-block;
  margin-top: 6px;
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
  font-size: 13px;
  padding: 6px 10px;
  border-radius: 6px;
  background: var(--pmm-surface-0);
  color: var(--pmm-text-primary);
  border: 1px solid var(--pmm-border-default);
  word-break: break-all;
}

.pmm-direct-connect-link__hint {
  display: block;
  margin-top: 6px;
  font-size: 13px;
  color: var(--pmm-text-secondary);
  line-height: 1.45;
}

/* Loading-button spinner class (used by LoadingButton). */
.pmm-loading-spinner {
  animation: pmm-spin 0.8s linear infinite;
}

@keyframes pmm-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

/* AdminLogsView — tint rows by severity so WARN/ERROR jump out
   at a glance, and colour the Level column to match. */
vaadin-grid::part(row).log-row-warn {
  background: color-mix(in srgb, var(--pmm-warning, #f59e0b) 8%, transparent);
}
vaadin-grid::part(row).log-row-error {
  background: color-mix(in srgb, var(--pmm-error, #ef4444) 12%, transparent);
}
vaadin-grid::part(cell).log-level-error {
  color: var(--pmm-error, #ef4444);
  font-weight: 600;
}
vaadin-grid::part(cell).log-level-warn {
  color: var(--pmm-warning, #f59e0b);
  font-weight: 600;
}
vaadin-grid::part(cell).log-level-info {
  color: var(--pmm-text-secondary);
}
vaadin-grid::part(cell).log-level-debug,
vaadin-grid::part(cell).log-level-trace {
  color: var(--pmm-text-tertiary);
  font-size: var(--lumo-font-size-xs);
}

/* ============================================================
   FormBuilder — empty canvas state + decluttered canvas rows
   ============================================================ */

.pmm-form-builder__canvas-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 56px 24px;
  border: 2px dashed var(--pmm-border);
  border-radius: var(--lumo-border-radius-l);
  background: var(--pmm-surface);
  color: var(--pmm-text-secondary);
}
.pmm-form-builder__canvas-empty-icon {
  width: 40px;
  height: 40px;
  color: var(--pmm-accent, var(--lumo-primary-color));
  opacity: 0.7;
  margin-bottom: 12px;
}
.pmm-form-builder__canvas-empty-heading {
  margin: 0 0 4px;
  color: var(--pmm-text-primary);
}
.pmm-form-builder__canvas-empty-hint {
  font-size: 14px;
  color: var(--pmm-text-secondary);
  margin-bottom: 18px;
  max-width: 360px;
  line-height: 1.5;
}
/* Inline starter-template tiles shown in the empty-canvas state. */
.pmm-form-builder__template-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 10px;
  width: 100%;
  max-width: 560px;
  margin: 4px 0 8px;
}
.pmm-form-builder__template-tile {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  padding: 14px 14px 12px;
  background: var(--lumo-base-color);
  border: 1px solid var(--pmm-border);
  border-radius: var(--lumo-border-radius-m);
  cursor: pointer;
  text-align: left;
  transition: border-color .15s ease, transform .15s ease, box-shadow .15s ease;
}
.pmm-form-builder__template-tile:hover {
  border-color: var(--pmm-accent, var(--lumo-primary-color));
  transform: translateY(-1px);
  box-shadow: 0 4px 14px -10px color-mix(in srgb, var(--pmm-accent, var(--lumo-primary-color)) 60%, transparent);
}
.pmm-form-builder__template-tile-icon {
  width: 18px;
  height: 18px;
  color: var(--pmm-accent, var(--lumo-primary-color));
  margin-bottom: 2px;
}
.pmm-form-builder__template-tile-name {
  font-weight: 600;
  color: var(--pmm-text-primary);
  font-size: 14px;
}
.pmm-form-builder__template-tile-desc {
  font-size: 12px;
  color: var(--pmm-text-secondary);
  line-height: 1.4;
}
.pmm-form-builder__canvas-empty-drag-hint {
  font-size: 12px;
  color: var(--pmm-text-tertiary);
  margin-top: 18px;
  font-style: italic;
}

/* ============================================================
 * 12. STITCH v1 ALIGNMENT — polish layer for screens #5–#9
 *     (form builder, receipt, QR, gateway wizard, DART files).
 *     Adds the Stitch design's small differences on top of the
 *     existing class system without rewriting Java views.
 * ============================================================ */

/* --- #5 Form builder ----------------------------------------- */

/* Three-rail layout: tighten the rails' background tint and the
 * left/right borders so the canvas feels like a tray sitting
 * inside the chrome (Stitch v1 form builder hero look). */
.pmm-form-builder__palette,
.pmm-form-builder__inspector {
  background: var(--pmm-surface-2);
  border: 1px solid var(--pmm-border-subtle);
  border-radius: var(--pmm-shape-md);
}

/* Active/selected canvas row — quiet violet ring + tinted bg.
 * Reveals edit/delete on hover via existing visibility classes. */
.pmm-form-builder__canvas .pmm-card--selected,
.pmm-form-builder__canvas [data-selected="true"] {
  border-color: var(--pmm-brand) !important;
  box-shadow: 0 0 0 3px rgba(124, 58, 237, 0.12) !important;
}

/* Template tile — large clickable card on the empty canvas.
 * Stitch shows 4 of these; the existing ones get a subtle lift
 * + violet hover ring so they feel "pickable". */
.pmm-form-builder__template-tile {
  transition:
    transform   var(--pmm-dur-short) var(--pmm-ease-standard),
    border-color var(--pmm-dur-short) var(--pmm-ease-standard),
    box-shadow  var(--pmm-dur-short) var(--pmm-ease-standard);
}
.pmm-form-builder__template-tile:hover {
  transform: translateY(-2px);
  border-color: var(--pmm-brand);
  box-shadow: 0 8px 22px rgba(124, 58, 237, 0.15);
}

/* --- #6 Receipt page (PublicReceiptView) --------------------- */

/* Centred success card — taller, more breathing room, soft
 * ambient shadow per Stitch. Inherits .pmm-pay-card base. */
.pmm-pay-result {
  text-align: center;
  padding: 40px 32px 32px;
}
.pmm-pay-result--success .pmm-pay-result__icon {
  width: 72px; height: 72px;
  border-radius: 50%;
  background: rgba(16, 185, 129, 0.10);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto 16px;
}
.pmm-pay-result--success .pmm-pay-result__icon vaadin-icon {
  color: #10B981;
  width: 36px; height: 36px;
}
.pmm-pay-result__detail-row {
  display: flex;
  justify-content: space-between;
  padding: 10px 0;
  font-size: 13px;
}
.pmm-pay-result__detail-row > :first-child {
  color: var(--pmm-text-tertiary);
  text-transform: uppercase;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
}
.pmm-pay-result__detail-row > :last-child {
  font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  font-weight: 500;
  color: var(--pmm-text-primary);
}

/* --- #7 QR payment screen ------------------------------------ */

/* QR code container — square, centred, tinted backdrop so the
 * QR pattern reads cleanly. Countdown pill below sits in
 * surface-container-high. */
.pmm-pay-qr-card {
  text-align: center;
}
.pmm-pay-qr-frame {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 280px; height: 280px;
  margin: 16px auto;
  padding: 16px;
  background: #FFFFFF;
  border-radius: var(--pmm-shape-md);
  border: 1px solid var(--pmm-border-default);
  box-shadow: var(--pmm-elev-2);
}
.pmm-pay-qr-frame img,
.pmm-pay-qr-frame canvas,
.pmm-pay-qr-frame svg {
  width: 100%; height: 100%;
}
.pmm-pay-qr-countdown {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 14px;
  background: var(--pmm-surface-2);
  border-radius: 9999px;
  font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13px;
  color: var(--pmm-text-primary);
  font-weight: 500;
}
.pmm-pay-qr-countdown--urgent {
  background: rgba(245, 158, 11, 0.10);
  color: #B45309;
}

/* QR status ping — animated cyan dot + "Waiting for your payment" caption,
 * Stitch v1 spec (visible feedback that the polling is live). */
.pmm-pay-qr-status {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 16px;
  font-size: 13px;
  color: var(--pmm-text-secondary);
}
.pmm-pay-qr-status__dot {
  position: relative;
  display: inline-flex;
  width: 8px; height: 8px;
}
.pmm-pay-qr-status__dot::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: var(--pmm-accent);
  animation: pmm-ping 1.4s cubic-bezier(0, 0, 0.2, 1) infinite;
}
.pmm-pay-qr-status__dot::after {
  content: "";
  position: relative;
  width: 100%; height: 100%;
  border-radius: 50%;
  background: var(--pmm-accent);
}
@keyframes pmm-ping {
  0%   { opacity: 0.75; transform: scale(1); }
  75%, 100% { opacity: 0; transform: scale(2.2); }
}

/* QR provider chip — green tonal pill at the top of the QR card showing
 * which gateway the customer is paying with (WeChat / Alipay / UnionPay). */
.pmm-pay-qr-provider {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 4px 12px;
  border-radius: 9999px;
  background: var(--pmm-success-bg);
  color: var(--pmm-success-text);
  font-size: 12px;
  font-weight: 600;
  border: 1px solid color-mix(in oklab, var(--pmm-success) 25%, transparent);
}
.pmm-pay-qr-provider img {
  width: 16px; height: 16px;
}

/* Receipt — bold violet mono total row, Stitch v1 parity. */
.pmm-pay-result__total {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-top: 16px;
  margin-top: 8px;
  border-top: 1px solid var(--pmm-border-default);
}
.pmm-pay-result__total-label {
  font-size: 18px;
  font-weight: 600;
  color: var(--pmm-text-primary);
}
.pmm-pay-result__total-value {
  font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 24px;
  font-weight: 700;
  color: var(--pmm-brand);
  letter-spacing: -0.01em;
}

/* "Back to {merchantName}" CTA on the receipt — Stitch's outlined ghost
 * button style, full-width, 48px tall. */
.pmm-pay-result__back {
  width: 100%;
  height: 48px;
  margin-top: 16px;
  border-radius: 12px;
  background: var(--pmm-surface-1);
  border: 1px solid var(--pmm-border-default);
  color: var(--pmm-text-primary);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: background var(--pmm-dur-short) var(--pmm-ease-standard),
              transform 100ms var(--pmm-ease-standard);
}
.pmm-pay-result__back:hover {
  background: var(--pmm-surface-2);
}
.pmm-pay-result__back:active {
  transform: scale(0.98);
}

/* "Download PDF receipt" link below the back button — tertiary violet. */
.pmm-pay-result__download {
  margin-top: 8px;
  font-size: 14px;
  font-weight: 500;
  color: var(--pmm-brand-text);
  text-align: center;
  cursor: pointer;
}
.pmm-pay-result__download:hover { text-decoration: underline; }

/* --- #8 Gateway setup wizard (modal) ------------------------- */

/* 3-step indicator at top of the wizard modal. The existing
 * dialog uses .pmm-wizard__steps; this polishes the per-step
 * pill state. */
.pmm-wizard__step {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  border-radius: 9999px;
  font-size: 13px;
  font-weight: 500;
  color: var(--pmm-text-secondary);
  background: var(--pmm-surface-2);
  transition: all var(--pmm-dur-short) var(--pmm-ease-standard);
}
.pmm-wizard__step--complete {
  background: rgba(16, 185, 129, 0.10);
  color: #047857;
}
.pmm-wizard__step--active {
  background: rgba(124, 58, 237, 0.10);
  color: var(--pmm-brand);
  box-shadow: inset 0 0 0 2px var(--pmm-brand);
}
.pmm-wizard__step-num {
  display: inline-flex;
  width: 20px; height: 20px;
  align-items: center;
  justify-content: center;
  border-radius: 9999px;
  background: rgba(0, 0, 0, 0.06);
  font-size: 11px;
  font-weight: 700;
}
.pmm-wizard__step--complete .pmm-wizard__step-num,
.pmm-wizard__step--active .pmm-wizard__step-num {
  background: currentColor;
  color: #fff;
}

/* Progress bar under the steps — two-thirds violet on step 2. */
.pmm-wizard__progress {
  height: 3px;
  background: var(--pmm-border-default);
  border-radius: 9999px;
  margin: 16px 0 24px;
  overflow: hidden;
}
.pmm-wizard__progress-fill {
  height: 100%;
  background: var(--pmm-brand);
  border-radius: inherit;
  transition: width var(--pmm-dur-medium) var(--pmm-ease-standard);
}

/* Test-connection success/failure card */
.pmm-wizard__test-card {
  background: var(--pmm-surface-2);
  border-radius: var(--pmm-shape-md);
  padding: 32px 24px;
  text-align: center;
}
.pmm-wizard__test-icon {
  width: 64px; height: 64px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 12px;
}
.pmm-wizard__test-icon--success {
  background: rgba(16, 185, 129, 0.12);
  color: #10B981;
}
.pmm-wizard__test-icon--error {
  background: rgba(239, 68, 68, 0.12);
  color: #EF4444;
}

/* --- #9 DART files admin view -------------------------------- */

/* Hero KPI strip above the DART files grid — same KPI pattern as
 * the merchant dashboard but rendered tighter (admin density).
 * Inherits .pmm-kpi base. */
.pmm-dart-kpi-strip {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--lumo-space-m);
  margin-bottom: var(--lumo-space-l);
}
@media (max-width: 900px) {
  .pmm-dart-kpi-strip { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 480px) {
  .pmm-dart-kpi-strip { grid-template-columns: 1fr; }
}

/* DART filename column — render as monospace pill so admins can
 * scan filenames quickly. The full long filename overflows with
 * an ellipsis in the cell; full text on hover via title attr. */
.pmm-dart-filename {
  font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
  font-weight: 500;
  color: var(--pmm-text-primary);
  background: var(--pmm-surface-2);
  padding: 4px 8px;
  border-radius: 4px;
  display: inline-block;
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ===========================================================================
 * Worldpay DART Settlement view (WorldpayDartSettlementView).
 *
 * Settlement-focused redesign of the file-detail screen. Reads top→bottom:
 * hero ($ NET headline) → money-flow strip (Gross → Fees → Refunds →
 * Chargebacks → Net) → reconciliation health banner → per-tx table (with
 * sticky totals footer) → final summary paragraph. See the design critique
 * in the Java view's class Javadoc for the full rationale.
 * =========================================================================== */

/* — Hero — eyebrow / big amount / sub-line + Copy-summary action ----------- */
.pmm-dart-hero {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  width: 100%;
  box-sizing: border-box;
  padding: 28px 32px;
  margin-top: var(--lumo-space-m);
  border-radius: 16px;
  background:
    radial-gradient(120% 80% at 0% 0%, rgba(124, 58, 237, 0.18) 0%, transparent 55%),
    radial-gradient(120% 80% at 100% 100%, rgba(6, 182, 212, 0.16) 0%, transparent 55%),
    linear-gradient(180deg, var(--pmm-surface-1, #ffffff), var(--pmm-surface-1, #ffffff));
  border: 1px solid var(--pmm-border-default, rgba(124, 58, 237, 0.18));
}
.pmm-dart-hero__lead {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}
.pmm-dart-hero__eyebrow {
  color: var(--pmm-accent, #06b6d4);
  letter-spacing: 0.08em;
}
.pmm-dart-hero__amount {
  font-size: clamp(36px, 5vw, 56px);
  font-weight: 700;
  line-height: 1.05;
  margin: 4px 0;
  color: var(--pmm-text-primary);
  font-variant-numeric: tabular-nums;
}
.pmm-dart-hero__sub {
  color: var(--pmm-text-secondary);
  font-size: 14px;
}
.pmm-dart-hero__caveat {
  margin-top: 8px;
  font-size: 12px;
  color: var(--pmm-text-tertiary);
  font-style: italic;
}
.pmm-dart-hero__trail {
  display: flex;
  align-items: flex-start;
  flex-shrink: 0;
}
.pmm-dart-hero__copy {
  margin-top: 4px;
}

/* — Money-flow strip — 5 tiles + 4 chevrons -------------------------------- */
.pmm-dart-flow {
  display: grid;
  grid-template-columns: 1fr auto 1fr auto 1fr auto 1fr auto 1.15fr;
  align-items: stretch;
  gap: 8px;
  width: 100%;
  box-sizing: border-box;
  margin-top: var(--lumo-space-m);
}
.pmm-dart-flow__tile {
  /* Reuses .pmm-kpi for the tile shell; this override only nudges spacing. */
  padding: 16px 14px;
}
.pmm-dart-flow__chevron {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--pmm-text-tertiary);
}
.pmm-dart-flow__chevron > vaadin-icon {
  --vaadin-icon-size: 20px;
}
.pmm-dart-flow__negative {
  color: var(--pmm-error, #dc2626);
}
@media (max-width: 1100px) {
  /* On narrower screens the 9-column flow grid shrinks gracefully into
   * a single column. Chevrons rotate to point down to keep the flow
   * metaphor intact. */
  .pmm-dart-flow {
    grid-template-columns: 1fr;
  }
  .pmm-dart-flow__chevron > vaadin-icon {
    transform: rotate(90deg);
  }
}

/* — Reconciliation health banner -------------------------------------------- */
.pmm-dart-recon {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  box-sizing: border-box;
  padding: 10px 16px;
  margin-top: var(--lumo-space-m);
  border-radius: 10px;
  border: 1px solid transparent;
  font-size: 14px;
}
.pmm-dart-recon__icon {
  --vaadin-icon-size: 18px;
  flex-shrink: 0;
}
.pmm-dart-recon__msg {
  color: var(--pmm-text-primary);
  font-weight: 500;
}
.pmm-dart-recon--ok {
  background: rgba(34, 197, 94, 0.08);
  border-color: rgba(34, 197, 94, 0.25);
}
.pmm-dart-recon--ok .pmm-dart-recon__icon { color: rgb(22, 163, 74); }
.pmm-dart-recon--warn {
  background: rgba(245, 158, 11, 0.10);
  border-color: rgba(245, 158, 11, 0.30);
}
.pmm-dart-recon--warn .pmm-dart-recon__icon { color: rgb(217, 119, 6); }
.pmm-dart-recon--info {
  background: rgba(6, 182, 212, 0.08);
  border-color: rgba(6, 182, 212, 0.25);
}
.pmm-dart-recon--info .pmm-dart-recon__icon { color: rgb(8, 145, 178); }

/* — Per-transaction table card --------------------------------------------- */
.pmm-dart-table-card {
  padding: 0 !important;
  overflow: hidden;
  /* flex-shrink:0 is load-bearing, not tidying. This card is a flex item in a
   * viewport-height .pmm-page column, and `overflow: hidden` (needed to clip
   * the grid to the rounded corners) makes its automatic minimum size resolve
   * to 0 — per spec min-height:auto only protects items whose overflow is
   * visible. So when the page's content exceeds the viewport, the card is the
   * thing that gets squeezed, and it collapsed to 2px: its two borders, with
   * the whole grid clipped away. The data was in the DOM and correct, the
   * screen just showed a hairline. */
  flex-shrink: 0;
}
.pmm-dart-table-card__topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 18px;
  border-bottom: 1px solid var(--pmm-border-default);
}
.pmm-dart-table-card__raw {
  color: var(--pmm-link, var(--pmm-brand, #7c3aed));
  font-size: 13px;
  text-decoration: none;
}
.pmm-dart-table-card__raw:hover { text-decoration: underline; }
.pmm-dart-table-card__more {
  display: block;
  padding: 10px 18px;
  font-size: 12px;
  color: var(--pmm-text-tertiary);
  border-top: 1px solid var(--pmm-border-default);
  background: var(--pmm-surface-2);
}
.pmm-dart-table__net {
  font-weight: 600;
  color: var(--pmm-text-primary);
}
.pmm-dart-table__totals-label {
  font-weight: 600;
  color: var(--pmm-text-secondary);
}

/* The grid's sticky footer row gets a subtle tint so totals stand out. */
.pmm-dart-table::part(footer-row),
.pmm-dart-table vaadin-grid-cell-content[part~="footer"] {
  background: var(--pmm-surface-2);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* — Final summary card ----------------------------------------------------- */
.pmm-dart-summary {
  padding: 16px 20px !important;
}
.pmm-dart-summary__title {
  display: block;
  margin-bottom: 8px;
  color: var(--pmm-text-secondary);
}
.pmm-dart-summary__body {
  font-size: 14px;
  line-height: 1.6;
  color: var(--pmm-text-primary);
}
.pmm-dart-summary__net {
  color: var(--pmm-brand, #7c3aed);
}

/* — Status chips (settlement view's per-row status column) ----------------- */
/* Reuses the existing .pmm-chip primitive defined elsewhere in this file;
 * these variants add settlement-specific colour treatments. */
.pmm-chip--success {
  background: rgba(34, 197, 94, 0.10);
  border-color: rgba(34, 197, 94, 0.30);
  color: rgb(22, 163, 74);
}
.pmm-chip--warn {
  background: rgba(245, 158, 11, 0.12);
  border-color: rgba(245, 158, 11, 0.35);
  color: rgb(180, 83, 9);
}
.pmm-chip--muted {
  background: var(--pmm-surface-2);
  border-color: var(--pmm-border-default);
  color: var(--pmm-text-tertiary);
}

/* Width clamp on the settlement page's children — same pattern as
 * the rest of the admin views. Without this Vaadin's vertical layout
 * shrinks block-level children to content-width. */
.pmm-dart-settlement > .pmm-dart-hero,
.pmm-dart-settlement > .pmm-dart-flow,
.pmm-dart-settlement > .pmm-dart-recon,
.pmm-dart-settlement > .pmm-dart-table-card,
.pmm-dart-settlement > .pmm-dart-summary {
  width: 100%;
  box-sizing: border-box;
}

/* ===========================================================================
 * Daily settlement view (WorldpayDartDailySettlementView) — cross-file day
 * view. Adds three new section primitives on top of the per-file view's
 * vocabulary: a stacked warnings banner, the 4-up supporting-reports row,
 * and the contributing-files list.
 * =========================================================================== */

.pmm-dart-day > .pmm-dart-hero,
.pmm-dart-day > .pmm-dart-flow,
.pmm-dart-day > .pmm-dart-day__warnings,
.pmm-dart-day > .pmm-dart-day__supporting,
.pmm-dart-day > .pmm-dart-day__lines,
.pmm-dart-day > .pmm-dart-day__files {
  width: 100%;
  box-sizing: border-box;
}

/* Settlement-batch chips — clickable Bill ID anchors, each opens the
 * lifecycle trace for that batch. Wraps to multiple rows on narrow
 * viewports. */
.pmm-dart-day__batches {
  padding: 14px 18px !important;
  margin-top: var(--lumo-space-m);
}
.pmm-dart-day__batches-head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 10px;
}
.pmm-dart-day__batches-hint {
  font-size: 12px;
  color: var(--pmm-text-tertiary);
}
.pmm-dart-day__batches-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.pmm-dart-day__batches-chips .pmm-chip {
  cursor: pointer;
  padding: 6px 10px;
  font-size: 13px;
  transition: transform 0.05s ease;
}
.pmm-dart-day__batches-chips .pmm-chip:hover {
  transform: translateY(-1px);
}

/* Info chip variant — cyan accent so the Bill ID chips stand out
 * as actionable. */
.pmm-chip--info {
  background: rgba(6, 182, 212, 0.10);
  border-color: rgba(6, 182, 212, 0.35);
  color: rgb(8, 145, 178);
}

/* Per-transaction breakdown card — the joined 312 + 324 + PMM view. */
.pmm-dart-day__lines {
  padding: 0 !important;
  overflow: hidden;
  margin-top: var(--lumo-space-m);
  /* See .pmm-dart-table-card — same trap. Without this the card collapsed to
   * 2px on the day view and the entire per-transaction breakdown was
   * invisible, while page-text extraction still showed every row. */
  flex-shrink: 0;
}
.pmm-dart-day__lines-hint {
  display: block;
  font-size: 12px;
  color: var(--pmm-text-tertiary);
  margin-top: 4px;
}

/* ===========================================================================
 * Transaction lifecycle view (WorldpayDartLifecycleView) — traces one
 * Funding Bill ID across the T+1 hold/release flow.
 * =========================================================================== */

.pmm-dart-lifecycle > .pmm-dart-lifecycle__summary,
.pmm-dart-lifecycle > .pmm-dart-lifecycle__timeline-card,
.pmm-dart-lifecycle > .pmm-dart-day__files {
  width: 100%;
  box-sizing: border-box;
}

.pmm-dart-lifecycle__summary {
  padding: 18px 20px !important;
  margin-top: var(--lumo-space-m);
}
.pmm-dart-lifecycle__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 24px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--pmm-border-default);
  margin-bottom: 14px;
}
.pmm-dart-lifecycle__meta-tile {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.pmm-dart-lifecycle__meta-label {
  color: var(--pmm-text-tertiary);
}
.pmm-dart-lifecycle__meta-value {
  font-size: 14px;
  font-weight: 600;
  color: var(--pmm-text-primary);
}

/* Timeline — each row is a typed event with icon, date, narrative,
 * source report, and signed amount on the right. */
.pmm-dart-lifecycle__timeline-card {
  padding: 14px 18px !important;
}
.pmm-dart-lifecycle__timeline {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: 10px;
}
.pmm-dart-lifecycle__event {
  display: grid;
  grid-template-columns: 32px 1fr auto;
  gap: 12px;
  align-items: flex-start;
  padding: 10px 0;
  border-top: 1px solid var(--pmm-border-default);
}
.pmm-dart-lifecycle__event:first-of-type { border-top: 0; }
.pmm-dart-lifecycle__event-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--pmm-surface-2);
  color: var(--pmm-brand, #7c3aed);
}
.pmm-dart-lifecycle__event-icon vaadin-icon { --vaadin-icon-size: 16px; }
.pmm-dart-lifecycle__event-body {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}
.pmm-dart-lifecycle__event-head {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
.pmm-dart-lifecycle__event-date {
  font-size: 13px;
  font-weight: 600;
  color: var(--pmm-text-primary);
}
.pmm-dart-lifecycle__event-narrative {
  font-size: 13px;
  color: var(--pmm-text-secondary);
}
.pmm-dart-lifecycle__event-source {
  font-size: 11px;
  color: var(--pmm-text-tertiary);
}
.pmm-dart-lifecycle__event-amount {
  text-align: right;
  font-size: 14px;
  white-space: nowrap;
  align-self: center;
}
.pmm-dart-lifecycle__empty {
  display: block;
  padding: 14px 0;
  color: var(--pmm-text-tertiary);
  font-style: italic;
}
.pmm-dart-lifecycle__file-date {
  font-size: 12px;
  color: var(--pmm-text-secondary);
}

/* Warnings banner — vertical stack of banners (one per warning).
 * Severity-driven coloring reuses the .pmm-dart-recon classes from the
 * per-file view + adds an ERROR variant. */
.pmm-dart-day__warnings {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: var(--lumo-space-m);
}
.pmm-dart-recon--err {
  background: rgba(220, 38, 38, 0.10);
  border-color: rgba(220, 38, 38, 0.35);
}
.pmm-dart-recon--err .pmm-dart-recon__icon { color: rgb(220, 38, 38); }

/* Supporting reports row — 4 cards in a row showing 312/324/330/340
 * each with their cross-check status against the 313. Responsive
 * collapse to 2-up on tablet, single column on mobile. */
.pmm-dart-day__supporting {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
  margin-top: var(--lumo-space-m);
}
@media (max-width: 1100px) { .pmm-dart-day__supporting { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 700px)  { .pmm-dart-day__supporting { grid-template-columns: 1fr; } }

.pmm-dart-day__sub-card {
  padding: 14px 16px !important;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.pmm-dart-day__sub-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.pmm-dart-day__sub-card-link {
  font-size: 12px;
  color: var(--pmm-link, var(--pmm-brand, #7c3aed));
  text-decoration: none;
}
.pmm-dart-day__sub-card-link:hover { text-decoration: underline; }

.pmm-dart-day__kv {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 6px 0;
  border-top: 1px solid var(--pmm-border-default);
}
.pmm-dart-day__kv:first-of-type { border-top: 0; }
.pmm-dart-day__kv-label {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--pmm-text-tertiary);
}
.pmm-dart-day__kv-value {
  font-size: 18px;
  font-weight: 600;
  color: var(--pmm-text-primary);
  font-variant-numeric: tabular-nums;
}
.pmm-dart-day__kv-hint {
  font-size: 12px;
  color: var(--pmm-text-secondary);
}
.pmm-dart-day__missing-hint {
  font-size: 12px;
  color: var(--pmm-text-tertiary);
  font-style: italic;
}
.pmm-dart-day__crosscheck-ok {
  font-size: 11px;
  color: rgb(22, 163, 74);
  margin-top: 4px;
}
.pmm-dart-day__crosscheck-warn {
  font-size: 11px;
  color: rgb(217, 119, 6);
  font-weight: 500;
  margin-top: 4px;
}

/* Contributing files card — one row per DART file received for this
 * date, with filename, status pill and a drill-down link. Compact list
 * so it doesn't dominate the page. */
.pmm-dart-day__files {
  padding: 14px 18px !important;
  margin-top: var(--lumo-space-m);
}
.pmm-dart-day__file-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 6px 0;
  border-top: 1px solid var(--pmm-border-default);
}
.pmm-dart-day__file-row:first-of-type { border-top: 0; padding-top: 8px; }
.pmm-dart-day__file-link {
  margin-left: auto;
  font-size: 12px;
  color: var(--pmm-link, var(--pmm-brand, #7c3aed));
  text-decoration: none;
}
.pmm-dart-day__file-link:hover { text-decoration: underline; }

/* Chip variant for ERROR severity used in the contributing-files list */
.pmm-chip--err {
  background: rgba(220, 38, 38, 0.10);
  border-color: rgba(220, 38, 38, 0.35);
  color: rgb(220, 38, 38);
}

/* ────────────────────────────────────────────────────────────────
 * V49+ Disabled-merchant row dimming.
 *
 * Vaadin Grid's setPartNameGenerator stamps the part name onto each
 * cell of the row. We hit it via the part selector + the [part~=...]
 * attribute matcher so the dim travels across every cell (the badge
 * pill stays vibrant so the click target reads as primary).
 * ────────────────────────────────────────────────────────────────*/
vaadin-grid::part(cell)[part~="disabled-row"] {
  opacity: 0.6;
}
vaadin-grid::part(cell)[part~="disabled-row"] vaadin-grid-cell-content [theme*="badge"] {
  opacity: 1;
}

/* ────────────────────────────────────────────────────────────────
 * V49+ Merchant credit-usage card (top of dashboard).
 *
 * Single-glance read for "how much of today's cap is left". Three
 * number blocks (used / remaining / cap) above a horizontal progress
 * bar that's colour-keyed off the usage ratio.
 * ────────────────────────────────────────────────────────────────*/
.pmm-credit-card { margin-bottom: 16px; }
.pmm-credit-card__numbers {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 16px;
  margin: 12px 0 16px 0;
}
.pmm-credit-card__num {
  display: flex; flex-direction: column; gap: 4px;
  padding: 12px 14px;
  border-radius: 8px;
  background: var(--lumo-contrast-5pct);
  border: 1px solid var(--lumo-contrast-10pct);
}
.pmm-credit-card__num-label {
  font-size: 12px;
  color: var(--lumo-secondary-text-color);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.pmm-credit-card__num-value {
  font-size: 22px; font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.pmm-credit-card__num--ok .pmm-credit-card__num-value { color: rgb(16, 185, 129); }
.pmm-credit-card__num--warn .pmm-credit-card__num-value { color: rgb(245, 158, 11); }
.pmm-credit-card__num--danger .pmm-credit-card__num-value { color: rgb(220, 38, 38); }

.pmm-credit-card__bar {
  position: relative; width: 100%; height: 8px;
  border-radius: 999px;
  background: var(--lumo-contrast-10pct);
  overflow: hidden;
}
.pmm-credit-card__bar-fill {
  height: 100%; border-radius: 999px;
  transition: width 320ms ease-out, background-color 320ms ease-out;
}
.pmm-credit-card__bar-fill--ok     { background: rgb(16, 185, 129); }
.pmm-credit-card__bar-fill--warn   { background: rgb(245, 158, 11); }
.pmm-credit-card__bar-fill--danger { background: rgb(220, 38, 38); }

.pmm-credit-card__caption {
  display: block;
  margin-top: 8px;
  font-size: 12px;
  color: var(--lumo-secondary-text-color);
}
