/* =========================================================
   AnalyticsArena — project overrides
   ---------------------------------------------------------
   Loaded AFTER vendor/analytics-arena/styles.css.
   The vendored styles.css is kept verbatim and never edited;
   every Scoreboard-specific deviation lives here so the design
   system stays drop-in upgradeable.
   ========================================================= */

/* Hide elements until Alpine.js initialises (mirrors client.css). */
[x-cloak] { display: none !important; }

/* ---------------------------------------------------------
   Lucide icons — design-system icon conventions.
   Icons render as <i data-lucide="name">, replaced with <svg>
   by lucide.createIcons(). Default to a 16px affordance size.
   --------------------------------------------------------- */
.ti,
[data-lucide],
svg.lucide {
  width: 16px;
  height: 16px;
  flex: none;
}
.svg-lucide-lg,
.ti-lg { width: 20px; height: 20px; }

/* ---------------------------------------------------------
   App shell — full-width topbar above a sidebar + content
   grid. The vendored .layout is a docs-style 2-column; here
   it is the application frame.
   --------------------------------------------------------- */
.app-shell { min-height: 100vh; }

.app-layout {
  display: grid;
  grid-template-columns: 248px 1fr;
  gap: 0;
  align-items: start;
  /* Cap the shell so content does not stretch absurdly wide on large
     monitors (mirrors the design system's .layout max-width). */
  max-width: 1680px;
  margin-inline: auto;
}

/* Sidebar — sticky below the 60px topbar. */
.app-sidenav {
  position: sticky;
  top: 60px;
  align-self: start;
  height: calc(100vh - 60px);
  overflow-y: auto;
  border-right: 1px solid var(--border);
  background: var(--surface);
  padding: var(--space-6) var(--space-4);
  display: flex;
  flex-direction: column;
}

/* Main content column. Wider than the docs .content (1100px)
   because app pages carry dense tables and KPI grids. */
.app-content {
  min-width: 0;
  padding: var(--space-8) var(--space-10);
}

/* Account menu trigger / dropdown wrapper. */
.topbar-account { position: relative; }
.topbar-account .menu {
  position: absolute;
  right: 0;
  top: calc(100% + 8px);
  z-index: 60;
}

/* The hamburger is desktop-hidden; shown on narrow viewports. */
.nav-toggle { display: none; }

/* Topbar brand lockup — theme-swapped via .light-only / .dark-only. */
.topbar .brand-lockup { height: 26px; }

/* App footer — sits at the end of the content column. */
.app-footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-top: var(--space-12);
  padding-top: var(--space-5);
  border-top: 1px solid var(--border);
  font-size: 13px;
  color: var(--text-subtle);
}
.app-footer nav { display: flex; gap: var(--space-5); flex-wrap: wrap; }

/* Neutralise client.css's global button hover lift inside the
   shell so design-system buttons/toggles stay flush. */
.topbar button:hover:not(:disabled),
.app-sidenav button:hover:not(:disabled) {
  transform: none;
  box-shadow: none;
}

/* ---------------------------------------------------------
   Content building blocks shared by all migrated pages.
   --------------------------------------------------------- */

/* Page header — one H1 per page plus a supporting line. */
.page-head { margin-bottom: var(--space-8); }
.page-head h1 { font-size: 26px; margin-bottom: 4px; }
.page-head p { font-size: 14px; margin: 0; }

/* The bare .card/.card-body pair the product editor (and the budget page)
   were written against. Nothing ever defined it — every "card" on those
   pages rendered as invisible, borderless text floating on the page, which
   read as "this page never got the new UI". Styled to the same surface as
   .aa-card; a card title (h4 first-in-body, the editor's convention) gets
   the handoff's carded-section treatment. */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
}
.card .card-body { padding: 16px; }
.card .card-body > h4:first-child {
  margin: -16px -16px 14px;
  padding: 13px 16px;
  border-bottom: 1px solid var(--border);
  font-size: 14px;
  font-weight: 600;
}

/* Generic surface card — panels that are neither tables nor KPIs. */
.aa-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
}
.aa-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 16px;
  border-bottom: 1px solid var(--border);
}
.aa-card-head h5 { margin: 0; font-size: 14px; }
.aa-card-body { padding: 16px; }

/* A table that fills a .table-card edge to edge. */
.table-card .table th:first-child,
.table-card .table td:first-child { padding-left: 16px; }

/* Toast — fixed transient notification. */
.aa-toast {
  position: fixed;
  top: 16px;
  right: 16px;
  z-index: 100;
  max-width: 380px;
  display: flex;
  gap: 10px;
  align-items: flex-start;
  padding: 12px 14px;
  font-size: 13px;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--success);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-lg);
}
.aa-toast.is-error { border-left-color: var(--danger); }
.aa-toast.is-info { border-left-color: var(--info); }
.aa-toast.is-warning { border-left-color: var(--warning); }

/* Clickable table rows. */
.table tbody tr.row-link { cursor: pointer; }

/* Modal overlay — backdrop + centring for design-system .modal. */
.aa-modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 80;
  background: rgba(16, 24, 40, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
}

/* Selected/active surface card. */
.aa-card.is-selected {
  border-color: var(--primary);
  box-shadow: 0 0 0 1px var(--primary);
}

/* Generic icon close button (also used standalone, not just in .alert). */
.close-btn {
  background: none;
  border: 0;
  cursor: pointer;
  color: var(--text-subtle);
  padding: 4px;
  border-radius: var(--r-sm);
  display: grid;
  place-items: center;
}
.close-btn:hover { color: var(--text); background: var(--bg-muted); }

/* Spinning icon (reuses the styles.css spin keyframes). */
.spin { animation: spin 0.8s linear infinite; }

/* Multi-step wizard step indicator. */
.wiz-step {
  width: 28px; height: 28px;
  border-radius: 50%;
  display: grid; place-items: center;
  font-size: 12.5px; font-weight: 600;
  background: var(--bg-muted); color: var(--text-subtle);
  flex: none;
}
.wiz-step.is-current,
.wiz-step.is-done { background: var(--primary); color: var(--on-primary); }
.wiz-step-label { margin-left: 8px; font-size: 12px; color: var(--text-subtle); }
.wiz-step-label.is-active { color: var(--primary); font-weight: 500; }
.wiz-connector { width: 32px; height: 2px; margin: 0 8px; background: var(--border); flex: none; }
.wiz-connector.is-done { background: var(--primary); }

/* Label/value summary rows. */
.aa-summary-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}
.aa-summary-row > :last-child { font-weight: 500; }

/* Click-to-edit table cell (inline editing). */
.aa-cell-edit {
  cursor: pointer;
  padding: 2px 5px;
  border-radius: var(--r-sm);
  font-size: 12.5px;
  max-width: 140px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.aa-cell-edit:hover { background: var(--bg-muted); }

/* ---------------------------------------------------------
   Responsive — below 992px the sidebar becomes an off-canvas
   drawer toggled by dashboardApp()'s sidebarOpen.
   --------------------------------------------------------- */
@media (max-width: 991.98px) {
  .app-layout { grid-template-columns: 1fr; }
  .nav-toggle { display: grid; }

  .app-sidenav {
    position: fixed;
    top: 60px;
    left: 0;
    width: 264px;
    z-index: 55;
    transform: translateX(-100%);
    transition: transform var(--dur) var(--ease);
    box-shadow: var(--shadow-lg);
  }
  .app-sidenav.is-open { transform: translateX(0); }

  .app-scrim {
    position: fixed;
    inset: 60px 0 0 0;
    background: rgba(16, 24, 40, 0.45);
    z-index: 54;
  }
  .app-content { padding: var(--space-6) var(--space-5); }
}

/* ============================================================
   Buttons: keep icon + label on one line
   ============================================================
   Icon-plus-label buttons were breaking internally (icon on one line,
   text below) when a toolbar squeezed them on narrow screens. Buttons
   should wrap as whole units instead — their flex containers already do
   that. */
.btn {
  flex-wrap: nowrap;
  white-space: nowrap;
}
.btn > span {
  flex-shrink: 0;
  white-space: nowrap;
}
.btn > i,
.btn > svg,
.btn > span > i,
.btn > span > svg {
  flex-shrink: 0;
}

/* Toolbars: buttons keep their natural width at every breakpoint and wrap
   as whole units. Without flex: 0 0 auto they shrink below their content
   and the label collapses under the icon. */
.aa-toolbar-actions {
  flex-wrap: wrap;
}
.aa-toolbar-actions > .btn,
.aa-toolbar-actions > label.btn {
  flex: 0 0 auto;
}

/* Phone: stack toolbar buttons full width so long labels stay readable. */
@media (max-width: 767.98px) {
  .aa-toolbar-actions {
    width: 100%;
    flex-direction: column;
    align-items: stretch;
  }
  .aa-toolbar-actions > .btn,
  .aa-toolbar-actions > label.btn {
    width: 100%;
    flex: 0 0 auto;
  }
}

/* ============================================================
   Topbar: stop fixed-width header items forcing page overflow
   ============================================================
   The topbar's items (brand + 240px search + icon buttons + 24px gaps)
   summed wider than a phone viewport, which widened the whole document
   and clipped every page horizontally. The brand also got squashed
   because flex shrank the image's width while its height stayed fixed. */
.topbar-inner { min-width: 0; }
.brand { flex-shrink: 0; }
.brand-lockup { flex-shrink: 0; width: auto; }
/* The full dot-burst mark (aa_*_icon.png, 333x180). The vendor
   .brand-mark rule styles a DIV as a solid primary-blue rounded chip
   (28x28, background, radius, overflow:hidden) — on this <img> that
   paints a blue rectangle behind the transparent PNG, so every chip
   property must be zeroed here, not just the size. (The old "mush at
   24px" was that chip background, not the art.) */
.brand-mark {
  display: none;
  flex-shrink: 0;
  height: 22px;
  width: auto;
  background: none;
  border-radius: 0;
  overflow: visible;
}
.topbar-inner > .theme-toggle { flex-shrink: 0; }

/* Search: full field on desktop; on small screens an icon that expands to
   take over the topbar row (other controls hide) — never an overlay, which
   let the brand and buttons show through the field. */
.topbar-search-toggle,
.topbar-search-close { display: none; }
.topbar-search-field { position: relative; }

/* Results dropdown. Anchored to .topbar-search (not the field) so it stays
   put when the small-screen layout hides the field and shows the toggle. */
.topbar-search { position: relative; }
.topbar-search-menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  width: min(420px, calc(100vw - var(--space-4) * 2));
  /* The panel is a preview, not a results page: cap it and scroll rather
     than letting it grow past the viewport on a long match list. */
  max-height: min(60vh, 420px);
  overflow-y: auto;
  /* 60, matching .notif-menu — the topbar dropdown next door.
     Not a bigger number: `.topbar` is `position: sticky; z-index: 50`, so it
     opens a stacking context and everything inside it paints at the bar's
     level however high the child's z-index climbs. A 1050 here would read as
     "competes with .aa-modal-overlay (1060)" when it cannot; the value only
     orders this menu against its siblings. Verified with elementFromPoint
     that the panel is on top of page content at 60. */
  z-index: 60;
}
.topbar-search-result {
  /* .menu-item is a flex row sized to its content; these rows need the text
     column to be the part that gives way, so the badge and state stay
     readable and only the title truncates. */
  align-items: flex-start;
  text-decoration: none;
}
.topbar-search-result.is-active { background: var(--bg-muted); }
.topbar-search-badge {
  flex-shrink: 0;
  font-size: 10.5px;
  letter-spacing: .02em;
  text-transform: uppercase;
  color: var(--text-subtle);
  background: var(--bg-muted);
  border-radius: var(--r-sm);
  padding: 2px 6px;
  margin-top: 1px;
}
.topbar-search-text { min-width: 0; display: flex; flex-direction: column; }
.topbar-search-primary {
  font-weight: 600;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.topbar-search-secondary {
  font-size: 12px;
  color: var(--text-subtle);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.topbar-search-meta {
  flex-shrink: 0;
  margin-left: auto;
  font-size: 11.5px;
  color: var(--text-subtle);
}

@media (max-width: 767.98px) {
  .topbar-inner {
    gap: var(--space-3);
    padding: 0 var(--space-4);
  }
  .topbar .brand-lockup { height: 22px; }

  .topbar-search { width: auto; flex-shrink: 0; }
  .topbar-search-toggle { display: grid; }
  .topbar-search .topbar-search-field { display: none; }
  .topbar-search kbd { display: none; }

  /* Open: search fills the row, everything but the nav toggle steps aside. */
  .topbar-inner.search-open .brand,
  .topbar-inner.search-open .topbar-search-toggle,
  .topbar-inner.search-open > .theme-toggle:not(.nav-toggle):not(.topbar-search-close),
  .topbar-inner.search-open .topbar-account,
  /* The marketplace pill steps aside too. It is up to ~150px, and "search
     fills the row" is not true if the scope control keeps its place --
     on a small phone the input ends up too narrow to use. */
  .topbar-inner.search-open .mkscope { display: none; }

  .topbar-inner.search-open .topbar-search {
    flex: 1 1 auto;
    width: auto;
    min-width: 0;
  }
  .topbar-inner.search-open .topbar-search-field { display: block; }
  .topbar-inner.search-open .topbar-search-field input { width: 100%; }
  .topbar-inner.search-open .topbar-search-close { display: grid; }
}

/* Long URLs, keys, and identifiers wrap instead of widening their card. */
.aa-wrap-anywhere,
.aa-wrap-anywhere code {
  overflow-wrap: anywhere;
  word-break: break-word;
}

/* ============================================================
   x-show + inline display: the Alpine trap
   ============================================================
   Alpine's x-show REMOVES the inline display property when it shows an
   element, so `style="display: inline-flex"` is silently lost and the
   element falls back to display:inline — which pushed block-level SVG
   icons onto their own line inside buttons. Use this class instead: when
   shown, the class supplies inline-flex; when hidden, x-show's inline
   `display: none` still wins on specificity. Never mark it !important. */
.btn-label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
}

/* ============================================================
   Metric strip — responsive KPI cards
   ============================================================
   Drill/summary metrics read as compact cards that reflow into columns
   instead of one tall stacked list on phones. */
.aa-metric-strip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(118px, 1fr));
  gap: var(--space-3);
  padding: 12px 16px;
  background: var(--bg-subtle);
  border-bottom: 1px solid var(--border);
}
.aa-metric-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: 8px 10px;
  min-width: 0;
}
.aa-metric-value {
  font-size: 15px;
  font-weight: 600;
  line-height: 1.3;
}

/* ============================================================
   Alpine-safe display utilities
   ============================================================
   x-show removes an element's inline display property when it shows it,
   so `style="display: flex"` is silently lost. These classes carry the
   display instead — never with !important, so x-show's inline
   `display: none` still wins when hiding. */
.d-flex-safe { display: flex; }
.d-inline-flex-safe { display: inline-flex; }
.d-grid-safe { display: grid; }
.d-inline-grid-safe { display: inline-grid; }

/* ---------- Dense KPI grid (campaigns dashboard) ----------
   A dozen metric cards need to sit tighter than the 4-up `row g-4`
   layout allows: auto-fill keeps 2 per row on phones and up to 6 on
   wide screens without a per-breakpoint column class for each one. */
.aa-kpi-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(148px, 1fr));
  gap: 12px;
}
.aa-kpi-grid .kpi { padding: 14px 16px; }
.aa-kpi-grid .kpi-label { font-size: 11.5px; gap: 6px; }
.aa-kpi-grid .kpi-label > span { min-width: 0; }

/* `.kpi` clips its content, so a wide currency figure (six digits plus
   cents) silently truncated at the 28px base size. Shrink it and let it
   wrap rather than disappear. */
.aa-kpi-fit {
  font-size: 20px;
  line-height: 1.15;
  overflow-wrap: anywhere;
}
@media (min-width: 1400px) {
  .aa-kpi-fit { font-size: 22px; }
}

/* ---------- Auth pages (sign in, register, password reset) ----------
   Standalone shell for dashboards/auth_base.html: no topbar, no sidebar,
   a single centred column on a subtle ground. Everything is token-driven
   so both themes come for free. */
.aa-auth {
  min-height: 100vh;
  margin: 0;
  background: var(--bg-subtle);
  /* A single soft wash of brand colour behind the card — the only
     decorative element on the page. */
  background-image: radial-gradient(
    120% 55% at 50% -10%, var(--primary-subtle) 0%, transparent 60%
  );
  background-repeat: no-repeat;
}
.aa-auth-main {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-8) var(--space-4);
}
.aa-auth-col {
  width: 100%;
  max-width: 400px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-6);
}
.aa-auth-theme {
  position: absolute;
  top: var(--space-4);
  right: var(--space-4);
}
.aa-auth-logo { display: block; }
.aa-auth-logo .brand-lockup { height: 34px; }
.aa-auth-logo:hover { opacity: 0.85; }

.aa-auth-card {
  width: 100%;
  padding: var(--space-8);
  box-shadow: var(--shadow-sm);
}
.aa-auth-head { margin-bottom: var(--space-6); }
.aa-auth-head h1 {
  margin: 0 0 var(--space-2);
  font-family: var(--font-heading);
  font-size: 24px;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--text);
}
.aa-auth-head p { margin: 0; font-size: 13.5px; }

.aa-auth-form { display: flex; flex-direction: column; gap: var(--space-5); }
.aa-auth-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
}
.aa-auth-link {
  font-size: 13px;
  font-weight: 500;
  color: var(--primary);
}
.aa-auth-link:hover { color: var(--primary-hover); text-decoration: underline; }

.aa-auth-foot {
  margin-top: var(--space-6);
  padding-top: var(--space-5);
  border-top: 1px solid var(--border);
  text-align: center;
  font-size: 13px;
}
.aa-auth-footer {
  font-size: 12px;
  color: var(--text-subtle);
  text-align: center;
}

/* Dismiss control on the auth error alert. */
.aa-auth-alert-close {
  margin-left: auto;
  padding: 0;
  background: none;
  border: 0;
  color: var(--text-subtle);
  cursor: pointer;
  line-height: 1;
}
.aa-auth-alert-close:hover { color: var(--text); }
.aa-auth-alert-close .ti { width: 16px; height: 16px; }

/* A control parked inside the right edge of an .input — the mirror of the
   kit's .input-affix, which only handles a leading icon. */
.aa-input-suffix { position: relative; }
.aa-input-suffix .input { padding-right: 38px; }
.aa-input-suffix > button {
  position: absolute;
  top: 0;
  right: 0;
  height: 100%;
  width: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: 0;
  color: var(--text-subtle);
  cursor: pointer;
}
.aa-input-suffix > button:hover { color: var(--text); }
.aa-input-suffix > button .ti { width: 16px; height: 16px; }

/* Wider column for the registration wizard, whose forms are two-up. */
.aa-auth-col-wide { max-width: 620px; }

/* Helper text under a field — quieter than .label, tied to the input above. */
.aa-auth-hint {
  margin: 0;
  font-size: 12px;
  color: var(--text-subtle);
}

/* Two-up field grid; collapses to one column on phones. */
.aa-auth-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-5);
}
.aa-auth-grid > .span-2 { grid-column: 1 / -1; }
@media (max-width: 575.98px) {
  .aa-auth-grid { grid-template-columns: minmax(0, 1fr); }
}

/* Footer action row: a back link on the left, primary action on the right. */
.aa-auth-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
  padding-top: var(--space-2);
}
.aa-auth-actions-end {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-left: auto;
}

/* ---------- Registration progress ----------
   Three numbered steps with connectors. State is encoded in the marker itself
   (a check replaces the number once a step is done), not colour alone.

   Distinct from .wiz-step above: that one is a compact inline row for wizards
   inside a modal toolbar, where the label sits beside the marker. Here the
   indicator spans the card and labels sit under the markers, so the two are
   not interchangeable. */
.aa-steps {
  display: flex;
  align-items: flex-start;
  margin: 0 0 var(--space-6);
  padding: 0 0 var(--space-6);
  border-bottom: 1px solid var(--border);
  list-style: none;
}
.aa-step {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  position: relative;
  text-align: center;
  min-width: 0;
}
/* Connector drawn to the left of every step but the first, so it always sits
   between two markers. */
.aa-step + .aa-step::before {
  content: "";
  position: absolute;
  top: 13px;
  right: 50%;
  left: -50%;
  height: 2px;
  background: var(--border);
}
/* A connector belongs to the step on its right, so it only fills once that
   step has been reached — not merely because the one behind it was. */
.aa-step.is-reached::before { background: var(--primary); }
.aa-step-marker {
  position: relative;
  z-index: 1;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12.5px;
  font-weight: 600;
  border: 2px solid var(--border);
  background: var(--surface);
  color: var(--text-subtle);
}
.aa-step-marker .ti { width: 14px; height: 14px; }
.aa-step.is-current .aa-step-marker {
  border-color: var(--primary);
  background: var(--primary);
  color: var(--on-primary);
}
.aa-step.is-done .aa-step-marker {
  border-color: var(--primary);
  background: var(--primary-subtle);
  color: var(--primary);
}
.aa-step-label {
  font-size: 12px;
  color: var(--text-subtle);
  line-height: 1.3;
}
.aa-step.is-current .aa-step-label { color: var(--text); font-weight: 500; }
.aa-step.is-done .aa-step-label { color: var(--text-muted); }

/* ---------- Password strength + requirements ---------- */
.aa-pw-meter { display: flex; flex-direction: column; gap: 6px; }
.aa-pw-meter-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  font-size: 12px;
  color: var(--text-muted);
}
.aa-pw-meter-verdict { font-weight: 600; }
.aa-pw-meter-track {
  height: 4px;
  border-radius: 999px;
  background: var(--bg-muted);
  overflow: hidden;
}
.aa-pw-meter-fill {
  height: 100%;
  width: 0;
  border-radius: 999px;
  background: var(--danger);
  transition: width var(--dur) var(--ease), background var(--dur) var(--ease);
}
.aa-pw-weak   { color: var(--danger); }
.aa-pw-medium { color: var(--warning); }
.aa-pw-strong { color: var(--success); }
.aa-pw-meter-fill.aa-pw-weak   { background: var(--danger);  width: 33%; }
.aa-pw-meter-fill.aa-pw-medium { background: var(--warning); width: 66%; }
.aa-pw-meter-fill.aa-pw-strong { background: var(--success); width: 100%; }

.aa-req-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 4px var(--space-4);
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 12px;
  color: var(--text-subtle);
}
@media (max-width: 575.98px) {
  .aa-req-list { grid-template-columns: minmax(0, 1fr); }
}
.aa-req-list li { display: flex; align-items: center; gap: 6px; }
.aa-req-list li.is-met { color: var(--success); }
.aa-req-list .ti { width: 13px; height: 13px; flex-shrink: 0; }

/* Outcome pages (password reset complete) — a single centred statement. */
.aa-auth-outcome { text-align: center; }
.aa-auth-outcome-mark {
  width: 48px;
  height: 48px;
  margin: 0 auto var(--space-4);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--success-subtle);
  color: var(--success);
}
.aa-auth-outcome-mark .ti { width: 24px; height: 24px; }

/* Inline "fetching the previous step's data" state on the wizard. */
.aa-auth-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  padding: var(--space-8) 0;
  font-size: 13.5px;
}

/* The requirement list sits directly under the strength bar inside the same
   .field, whose 6px gap is too tight between two distinct readouts. */
.aa-pw-meter + .aa-req-list { margin-top: var(--space-2); }

/* ---------- Drill-down accordion row ----------
   The expanded panel under a search-term / keyword row. Injected as raw HTML
   by the page's Alpine component, so it needs real classes rather than the
   hardcoded Tailwind greys it used to carry — those rendered a white panel
   with near-invisible text once the dark theme landed. */
/* Qualified with .table because `.table th, .table td` sets padding and a
   --border bottom edge at higher specificity than a lone class could beat. */
.table td.aa-drill-cell,
.aa-drill-cell {
  padding: 0;
  /* Inset relative to the --surface rows above, plus an accent edge tying the
     panel to the row it belongs to. */
  background: var(--bg-subtle);
  border-bottom: 2px solid var(--primary);
}
.aa-drill-body { padding: var(--space-3) var(--space-4); }
.aa-drill-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-2);
}
.aa-drill-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  min-width: 0;
}
.aa-drill-term { color: var(--primary); }
.aa-drill-loading {
  padding: var(--space-4) 0;
  text-align: center;
  font-size: 13px;
  color: var(--text-muted);
}
/* Campaign names inherit from the table, which is --text; inside the inset
   panel they read better one step back. */
.aa-drill-cell .aa-drill-body { color: var(--text); }

/* ---------- Theme control inside the account menu ----------
   A .menu-item that toggles a setting instead of navigating. It is a <button>,
   so the element defaults have to be cleared to sit flush with the links
   around it. */
.aa-menu-switch {
  width: 100%;
  background: none;
  border: 0;
  text-align: left;
  font-family: var(--font-sans);
  font-size: 13px;
  color: var(--text);
}
.aa-menu-switch .switch { margin-left: auto; }
/* The kit's switch is driven by `input:checked + .track`, but an input cannot
   live inside a button — so the on state comes from a class instead. */
.aa-menu-switch .track.is-on { background: var(--primary); }
.aa-menu-switch .track.is-on::after { transform: translateX(14px); }

/* ============================================================
   Date range selector — one trigger, one option list, two shells
   Implements handoff/Date Selector.html. Replaces the segmented
   range control, which wrapped and orphaned "Custom" below 768px.

   Differences from the handoff mock, which framed both platforms
   side by side inside a phone graphic:
   - one instance per page, presentation switched by media query,
     rather than a separate .is-desktop / .is-mobile pair;
   - the sheet and scrim are position: fixed, since here they clip
     to the real viewport rather than a mock screen container.
   ============================================================ */
.dr { position: relative; display: inline-block; max-width: 100%; }

.dr-trigger {
  display: inline-flex; align-items: center; gap: 9px;
  height: 34px; padding: 0 11px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  color: var(--text);
  font-family: var(--font-sans); font-size: 12.5px; font-weight: 500;
  cursor: pointer;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
  white-space: nowrap; max-width: 100%;
}
.dr-trigger:hover { border-color: var(--border-strong); }
.dr-trigger[aria-expanded="true"] {
  border-color: var(--primary);
  box-shadow: var(--shadow-focus);
}
.dr-trigger .cal { width: 15px; height: 15px; color: var(--text-muted); flex-shrink: 0; }
.dr-trigger .lbl { font-weight: 600; }
/* The resolved dates live on the trigger, so the active period is
   readable without opening the control. */
.dr-trigger .res {
  font-family: var(--font-mono); font-size: 11.5px;
  color: var(--text-muted); font-variant-numeric: tabular-nums;
  overflow: hidden; text-overflow: ellipsis;
}
.dr-trigger .chev {
  width: 14px; height: 14px; color: var(--text-subtle);
  flex-shrink: 0; margin-left: 1px;
  transition: transform var(--dur) var(--ease);
}
.dr-trigger[aria-expanded="true"] .chev { transform: rotate(180deg); }

/* ---- shared option list ---- */
.dr-panel { background: var(--surface); }
.dr-opts { display: flex; flex-direction: column; padding: 6px; }
.dr-opt {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 8px 10px; border: none; background: none;
  border-radius: var(--r-md); cursor: pointer; text-align: left;
  font-family: var(--font-sans); color: var(--text);
  transition: background var(--dur) var(--ease);
}
.dr-opt:hover { background: var(--bg-subtle); }
.dr-opt .on { width: 15px; height: 15px; flex-shrink: 0; color: var(--primary); opacity: 0; }
.dr-opt[aria-selected="true"] { background: var(--primary-subtle); }
.dr-opt[aria-selected="true"] .on { opacity: 1; }
.dr-opt[aria-selected="true"] .nm { font-weight: 600; color: var(--text); }
.dr-opt .nm { font-size: 13px; }
.dr-opt .dt {
  margin-left: auto; font-family: var(--font-mono); font-size: 11.5px;
  color: var(--text-subtle); font-variant-numeric: tabular-nums;
}
.dr-sep { height: 1px; background: var(--border); margin: 6px 4px; }

/* ---- custom sub-panel ---- */
.dr-custom { padding: 4px 10px 10px; }
.dr-custom .two { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; }
.dr-custom .fld { display: flex; flex-direction: column; gap: 5px; }
.dr-custom .fld .lb {
  font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--text-subtle); font-weight: 700;
}
.dr-custom .input { height: 34px; font-size: 12.5px; width: 100%; }
.dr-custom .apply { margin-top: 10px; width: 100%; }
.dr-custom .err { font-size: 11.5px; color: var(--danger); margin-top: 7px; }

/* ---- desktop: popover anchored to the trigger's right edge ---- */
.dr-panel {
  position: absolute; top: calc(100% + 6px); right: 0; z-index: 60;
  width: 286px;
  border: 1px solid var(--border); border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
}
.dr-grab, .dr-title { display: none; }
.dr-scrim { display: none; }

/* ---- mobile: full-width trigger + bottom sheet ---- */
@media (max-width: 767.98px) {
  /* flex-grow as well as width: several toolbars place the trigger in a flex
     row beside a small action button, where width:100% alone leaves it short
     of the line. */
  .dr { display: block; width: 100%; flex: 1 1 auto; min-width: 0; }
  /* A toolbar hosting the trigger takes the full line on mobile, so the
     trigger itself can reach full width per the spec. */
  .aa-dr-bar { width: 100%; }
  .dr-trigger {
    display: flex; width: 100%; height: 46px;
    padding: 0 14px; font-size: 14px; border-radius: var(--r-lg);
  }
  .dr-trigger .cal { width: 17px; height: 17px; }
  .dr-trigger .res { font-size: 12.5px; }
  .dr-trigger .chev { margin-left: auto; width: 16px; height: 16px; }

  .dr-scrim {
    display: block; position: fixed; inset: 0; z-index: 70;
    background: rgba(8, 11, 16, 0.5);
  }
  .dr-panel {
    position: fixed; left: 0; right: 0; bottom: 0; top: auto;
    width: auto; z-index: 71;
    border: 0; border-top: 1px solid var(--border);
    border-radius: 20px 20px 0 0;
    padding-bottom: max(22px, env(safe-area-inset-bottom));
    box-shadow: 0 -14px 40px rgba(0, 0, 0, 0.28);
    max-height: 85vh; overflow-y: auto;
  }
  .dr-grab {
    display: block; width: 38px; height: 4px; border-radius: 2px;
    background: var(--border-strong); margin: 9px auto 3px;
  }
  .dr-title {
    display: flex; align-items: center; justify-content: space-between;
    padding: 6px 16px 10px; border-bottom: 1px solid var(--border);
  }
  .dr-title b { font-size: 14.5px; font-family: var(--font-heading); }
  .dr-title button {
    background: none; border: none; color: var(--text-muted); cursor: pointer;
    display: grid; place-items: center; width: 30px; height: 30px; border-radius: 8px;
  }
  .dr-title button .ti { width: 17px; height: 17px; }
  .dr-opts { padding: 8px 10px; }
  /* 48px targets, above the 44px minimum. */
  .dr-opt { padding: 12px; min-height: 48px; }
  .dr-opt .nm { font-size: 15px; }
  .dr-opt .dt { font-size: 12.5px; }
  .dr-opt .on { width: 18px; height: 18px; }
  .dr-custom { padding: 4px 18px 12px; }
  .dr-custom .input { height: 44px; font-size: 14px; }
  .dr-custom .apply { height: 46px; font-size: 14.5px; }
}

/* ==========================================================================
   Resizable table columns (static/js/aa-table.js)
   ========================================================================== */

/* The grab area straddles the column border rather than sitting inside one
   cell, so the cursor finds it where the eye expects the divider to be. */
.aa-col-resize {
  position: absolute;
  top: 0;
  right: -3px;
  height: 100%;
  cursor: col-resize;
  user-select: none;
  touch-action: none;
  z-index: 2;
}

/* Invisible until the header is hovered — a permanent divider on every column
   is visual noise on a table nobody is resizing. */
.aa-col-resize::after {
  content: "";
  position: absolute;
  top: 20%;
  left: 50%;
  width: 2px;
  height: 60%;
  border-radius: 1px;
  background: transparent;
  transition: background 120ms ease;
}

.table th:hover .aa-col-resize::after,
.aa-col-resize:hover::after {
  background: var(--border);
}

.aa-col-resize:hover::after,
.aa-resizing .aa-col-resize::after {
  background: var(--primary);
}

/* While dragging, the pointer owns the page: no text selection, and the
   col-resize cursor holds even as the pointer leaves the header. */
.aa-resizing {
  user-select: none;
  cursor: col-resize;
}

.aa-resizing * {
  cursor: col-resize !important;
}

/* Frozen columns clip rather than push the table wider, which is what makes a
   narrowed column narrow — and what the tooltip then compensates for. */
.table[style*="table-layout: fixed"] th,
.table[style*="table-layout: fixed"] td {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---- KPI card values that outgrow their card ----
   .kpi-value is mono at a fixed 28px. On a phone the card is roughly 145px of
   usable width, and a mono glyph is about 0.6em, so anything past eight
   characters runs off the edge: "$2,144,628" rendered as "$2,144,62" — digits
   silently dropped, which for a currency figure is worse than any layout
   problem it could have caused.

   Stepped by length rather than scaled uniformly: a short value like "$9.96"
   should keep the large type the design intends, and only the long ones give
   it up. Thresholds are derived from that 0.6em glyph width against ~145px.

   The last tier also allows a break, so a value longer than any tier
   anticipates wraps instead of being clipped. A wrapped number is ugly; a
   truncated one is wrong. */
   Sized against the card, not against an assumed card. The first version of
   this used fixed px tiers derived from a phone card (~145px inner), which is
   the widest case, not the narrowest: at >=1200px these cards are col-xl-2,
   six across, leaving roughly 83-123px inside after gutters and .kpi's 20px
   padding. A 10-character value at 23px is ~138px and still overflowed — and
   .kpi sets overflow:hidden, so it clipped rather than showing the problem.

   cqw makes the tier proportional to whatever the card actually is: 100cqw is
   the card's content box, and a mono glyph is ~0.6em, so N characters fit at
   (100 / 0.6N) cqw. Each tier caps at its character count, and min() keeps the
   28px ceiling so a short value on a wide card still gets the large type. */
.kpi { container-type: inline-size; }

.kpi-value               { font-size: min(28px, 20cqw); }
.kpi-value.kpi-value-sm  { font-size: min(28px, 16cqw); }
.kpi-value.kpi-value-xs  { font-size: min(28px, 13cqw); }
.kpi-value.kpi-value-xxs { font-size: min(28px, 10.5cqw); overflow-wrap: anywhere; }

/* Container queries are widely supported, but a browser without them would
   get no sizing at all rather than imperfect sizing. Fall back to the fixed
   tiers — wrong on a narrow desktop card, still better than 28px everywhere. */
@supports not (container-type: inline-size) {
  .kpi-value.kpi-value-sm  { font-size: 23px; }
  .kpi-value.kpi-value-xs  { font-size: 19px; }
  .kpi-value.kpi-value-xxs { font-size: 16px; }
}

/* Icon-only header button (the product-detail edit gear). btn-sm is sized for
   a label, so an icon alone sits in a wide pill with the glyph off-centre;
   this squares it to match the icon buttons elsewhere in a page header. */
.aa-gear-btn {
  padding: 0;
  width: 34px;
  height: 34px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

/* Inline icon+label inside an x-show element.
   MUST be a class, not style="display: inline-flex". Alpine's x-show hides by
   setting inline display:none and shows by CLEARING the inline display — which
   also wipes a static display declared there, so the element falls back to
   block and the icon stacks above its own label. Both catalog-management
   header buttons rendered that way.
   No !important: hiding relies on Alpine's inline display:none outranking this
   rule, which is exactly why d-flex (which is !important) must never be put on
   an x-show element — a CI guard enforces that separately. */
.aa-inline-icon {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}

/* Badges are one-line labels BY CONSTRUCTION: the vendor styles give them a
   fixed 20px height, so a badge that wraps overflows its own box with the
   text cramped against the edges — which is exactly how "DEFERRED · DD7"
   rendered on the ledger's mobile view when the status column tightened.
   nowrap system-wide rather than on that one pill: every badge that can
   wrap has the same fixed height and the same failure. The width this adds
   is absorbed by each table's own overflow-x container, never the page. */
.badge { white-space: nowrap; }
/* The opt-out, for the handful of AUTO-height badges that carry free text
   (the product-detail brand badge holds a tenant-configurable name up to
   255 chars). For those, wrapping is the correct behaviour and nowrap would
   push them past the viewport — the mirror image of the ledger bug. An
   explicit class rather than an attribute selector on style="height: auto":
   opting out is a decision the markup should state, not something inferred
   from an inline style string. */
.badge.badge-wrap { white-space: normal; height: auto; }


/* ==========================================================================
   Global marketplace selector
   --------------------------------------------------------------------------
   Taken from the design handoff prototype
   (design_handoff_global_marketplace_selector). Our vendored
   static/vendor/analytics-arena/styles.css is byte-identical to the one that
   prototype shipped with, so every token below already resolves and nothing
   here invents a primitive.

   Two deliberate changes from the prototype's CSS:

   1. Its page furniture (.wrap, .doc-head, .cols, .frame-label, .pghd, .kpi,
      .panel, .tbl, .m-top, .m-body) is documentation scaffolding around the
      component and is not carried over.

   2. Five class names are namespaced, because the prototype is a single page
      and this is a global stylesheet where a bare .pin would style anything:

         .glyph  -> .mkglyph      .pin    -> .mkpin
         .stale  -> .mkstale      .scrim  -> .mkscrim
         .sheet  -> .mksheet

      Nothing else is renamed, so the handoff's spec still reads across.
   ========================================================================== */
.mkscope { position: relative; flex-shrink: 0; }

/* Set the scope control clear of the brand lockup. At the topbar's own gap it
   sits close enough to the logo to read as part of the lockup rather than as a
   control of its own; this is the separation, measured from the logo.

   Only from 992px up. Between 768 and 991 the topbar is already near its width
   budget (brand + a ~250px pill + the 240px search field + two icon buttons +
   gaps), and this file exists partly because header items summing wider than
   the viewport once widened the document and clipped every page horizontally.
   One number to tune, in one place. */
@media (min-width: 992px) {
  .mkscope { margin-left: 100px; }
}

.mktrig { display: inline-flex; align-items: center; gap: 9px; height: 36px; padding: 0 8px 0 6px; border: 1px solid var(--border-strong); border-radius: var(--r-md); background: var(--surface); color: var(--text); font: 500 13px var(--font-sans); cursor: pointer; box-shadow: var(--shadow-xs); max-width: 270px; }
.mktrig:hover { background: var(--bg-subtle); }
.mktrig[aria-expanded="true"] { border-color: var(--primary); box-shadow: var(--shadow-focus); }
.mktrig .lbl { display: flex; flex-direction: column; align-items: flex-start; gap: 1px; min-width: 0; }
.mktrig .l1 { font-weight: 600; font-size: 12.5px; line-height: 1.1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 150px; }
.mktrig .l2 { font: 400 9.5px/1.1 var(--font-mono); color: var(--text-subtle); letter-spacing: .03em; text-transform: uppercase; }
.mktrig .cv { margin-left: 2px; color: var(--text-subtle); width: 14px; height: 14px; }

.mkglyph { width: 24px; height: 24px; border-radius: 6px; display: grid; place-items: center; font: 600 11px var(--font-sans); color: #fff; flex-shrink: 0; letter-spacing: -.01em; }
.mkglyph.lg { width: 30px; height: 30px; font-size: 13px; border-radius: 8px; }
/* Channel colours. An unknown channel falls through to the neutral base
   above rather than to a colour that means something else. */
.mkglyph.ch-amazon { background: #1f2937; }
.mkglyph.ch-walmart { background: #0071ce; }
.mkglyph.ch-shopify { background: #0e9f6e; }
.mkglyph.ch-ebay { background: #8b5cf6; }

.mkpanel { position: absolute; top: calc(100% + 8px); left: 0; width: 378px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-xl); box-shadow: var(--shadow-xl); z-index: 60; overflow: hidden; display: none; }
.mkpanel.open { display: block; }
.mksearch { padding: 10px 10px 8px; border-bottom: 1px solid var(--border); position: relative; }
.mksearch .input { height: 34px; padding-left: 31px; font-size: 13px; }
.mksearch svg { position: absolute; left: 20px; top: 50%; transform: translateY(-50%); width: 14px; height: 14px; color: var(--text-subtle); }
.mklist { max-height: 392px; overflow-y: auto; padding: 6px; }
.mkgrp { font: 700 10px var(--font-sans); letter-spacing: .1em; text-transform: uppercase; color: var(--text-subtle); padding: 11px 8px 5px; display: flex; align-items: center; gap: 7px; }
.mkgrp .n { margin-left: auto; font-family: var(--font-mono); font-weight: 400; letter-spacing: .02em; }

.mkrow { display: flex; align-items: center; gap: 10px; width: 100%; padding: 7px 8px; border: 0; background: transparent; border-radius: var(--r-md); cursor: pointer; text-align: left; color: var(--text); font-family: var(--font-sans); }
.mkrow:hover { background: var(--bg-subtle); }
.mkrow.sel { background: var(--primary-subtle); }
.mkrow .nm { font-size: 13px; font-weight: 500; line-height: 1.25; display: flex; align-items: center; gap: 6px; }
.mkrow .meta { font: 400 10.5px var(--font-mono); color: var(--text-subtle); letter-spacing: .02em; margin-top: 2px; }
.mkrow .col { min-width: 0; flex: 1; }
.mkrow .rt { margin-left: auto; display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.mkrow .num { font: 500 12px var(--font-mono); color: var(--text-muted); font-variant-numeric: tabular-nums; }
.mkrow.sel .num { color: var(--primary); }
/* Text glyph, not a lucide <i>: rows are rendered by x-for AFTER
   lucide.createIcons() has run, so a data-lucide element in here would never
   be converted and would render as an empty box. Same rule the notification
   list and the topbar search results already follow. */
.mkrow .tick { width: 15px; height: 15px; color: var(--primary); opacity: 0; flex-shrink: 0; display: grid; place-items: center; font-size: 13px; line-height: 1; }
.mkrow.sel .tick { opacity: 1; }
/* A marketplace with no connection is shown, greyed, with its own action --
   never hidden. Hiding it is the difference between "you don't sell there"
   and "we never told you that exists". */
.mkrow.off { cursor: default; }
.mkrow.off .mkglyph { filter: grayscale(1); opacity: .45; }
.mkrow.off .nm { color: var(--text-muted); }

.mkconn { border: 0; background: transparent; color: var(--primary); font: 600 11.5px var(--font-sans); cursor: pointer; padding: 4px 6px; border-radius: var(--r-sm); }
.mkconn:hover { background: var(--primary-subtle); }

.mkpin { border: 0; background: transparent; color: var(--text-subtle); padding: 3px; border-radius: var(--r-sm); cursor: pointer; display: grid; place-items: center; opacity: 0; }
.mkrow:hover .mkpin { opacity: 1; }
.mkpin.on { opacity: 1; color: var(--warning); }
.mkpin { font-size: 13px; line-height: 1; width: 20px; height: 20px; }
/* Keyboard users never hover, so the pin has to appear on focus too or it is
   unreachable without a mouse. */
.mkpin:focus-visible { opacity: 1; }

/* Sits beside the NAME, where the number is about to be judged -- not tucked
   away on a settings page nobody opens. */
.mkstale { width: 7px; height: 7px; border-radius: 50%; background: var(--warning); flex-shrink: 0; }

.mkfoot { border-top: 1px solid var(--border); padding: 8px 10px; display: flex; align-items: center; gap: 10px; background: var(--bg-subtle); }
.mkfoot .hint { font: 400 10.5px var(--font-mono); color: var(--text-subtle); margin-left: auto; }
.mkempty { padding: 26px 14px; text-align: center; font-size: 12.5px; color: var(--text-subtle); }

/* Fixed, not absolute: the prototype's scrim lived inside a mock viewport,
   ours has to cover the real one. Teleported to <body> by the template --
   inside .topbar its backdrop-filter would make the HEADER its containing
   block. z-index clears the topbar's own sticky z-50 stacking context. */
.mkscrim { position: fixed; inset: 0; z-index: 1000; display: none; }
.mkscrim.on { display: block; }
/* An unstyled wrapper at body level; its children position themselves. */
.mkportal { }

/* The scope chip for page headers -- "you are looking at Amazon.com" restated
   where the numbers are, so scope is not something you have to remember. */
.scopetag { display: inline-flex; align-items: center; gap: 7px; height: 26px; padding: 0 10px 0 5px; border-radius: var(--r-pill); background: var(--bg-muted); font: 500 12px var(--font-sans); color: var(--text-muted); }
.scopetag .mkglyph { width: 18px; height: 18px; border-radius: 5px; font-size: 9px; }

/* --------------------------------------------------------------------------
   Below 768px the dropdown becomes a bottom sheet. Both are in the DOM and
   CSS picks one, so there is no layout shift on first paint and no JS media
   query to get out of step with the breakpoint.
   -------------------------------------------------------------------------- */
.mksheet { position: fixed; left: 0; right: 0; bottom: 0; z-index: 1001; background: var(--surface); border-radius: 18px 18px 0 0; box-shadow: 0 -12px 40px rgba(16, 24, 40, .22); transform: translateY(102%); transition: transform var(--dur-slow) var(--ease); display: flex; flex-direction: column; max-height: 86%; }
.mksheet.open { transform: translateY(0); }
.mksheet .grab { width: 38px; height: 4px; border-radius: 2px; background: var(--border-strong); margin: 9px auto 4px; }
.mksheet .sh { padding: 4px 16px 10px; display: flex; align-items: center; gap: 10px; }
.mksheet .sh h3 { font-size: 15.5px; margin: 0; letter-spacing: -.01em; }
.mksheet .sh button { margin-left: auto; }
.mksheet .mksearch { padding: 0 16px 10px; border-bottom: 1px solid var(--border); }
.mksheet .mksearch svg { left: 26px; top: 17px; transform: none; }
.mksheet .mksearch .input { height: 40px; }
.mksheet .mklist { max-height: none; flex: 1; padding: 6px 10px; }
/* 48px rows: a thumb target, not a pointer target. */
.mksheet .mkrow { padding: 10px 8px; min-height: 48px; }
.mksheet .mkrow .nm { font-size: 14px; }
.mksheet .mkfoot { padding: 10px 14px calc(10px + env(safe-area-inset-bottom)); }

/* Compact name pill. The brand collapses to its icon mark on mobile, which
   buys the room for the marketplace NAME — clearer than a flag (several
   marketplaces can share a country's flag, and the name is the identity). */
.mktrig-m { display: none; align-items: center; gap: 4px; height: 36px; padding: 0 8px 0 11px; border: 1px solid var(--border-strong); border-radius: var(--r-pill); background: var(--surface); cursor: pointer; min-width: 0; font: 600 13px var(--font-sans); color: var(--text); }
.mktrig-m .t { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 128px; }
.mktrig-m .cv { width: 14px; height: 14px; color: var(--text-subtle); flex-shrink: 0; }

/* The swap. Above the breakpoint the sheet is not merely hidden but
   display:none, so its focusable controls are out of the tab order rather
   than sitting invisibly off-screen. */
@media (max-width: 767.98px) {
  .mktrig { display: none; }
  .mktrig-m { display: flex; }
  .mkpanel { display: none !important; }
  /* Icon-only brand: the wordmark plus a marketplace name cannot share a
     phone topbar. */
  .topbar .brand-lockup { display: none; }
  .brand-mark { display: block; }
  /* theme-aware pair: the display:block above must not resurrect the
     wrong-theme mark */
  [data-theme="dark"] .brand-mark.light-only,
  .brand-mark.dark-only { display: none; }
  [data-theme="dark"] .brand-mark.dark-only { display: block; }
}
@media (min-width: 768px) {
  .mksheet { display: none; }
  /* The scrim belongs to the sheet. On desktop it would blanket the page at
     z-1000 and swallow every click while the dropdown is open. */
  .mkscrim { display: none !important; }
}
/* Keyboard highlight. The prototype was mouse-driven and had no equivalent;
   without it, arrowing through the list moves aria-activedescendant with
   nothing visible following it. Distinct from .sel, which means "this is the
   current scope" rather than "this is where the keyboard is". */
.mkrow.is-focus { background: var(--bg-muted); box-shadow: inset 0 0 0 1px var(--border-strong); }

/* ==========================================================================
   Settings ▸ Marketplaces  (handoff_marketplaces, Surface 2)
   --------------------------------------------------------------------------
   Taken from the design handoff prototype. Its styles.css is byte-identical
   to our vendored copy, so every token resolves and .table/.alert/.badge/
   .btn/.menu/.radio/.kbd all come from there unchanged.

   Everything is scoped under .mkpage. The prototype is a single page and uses
   bare names -- .cc, .fact, .lead, .dot, .empty, .off -- that a global
   stylesheet cannot afford: `.empty` alone appears in 76 of our templates.
   Scoping keeps the handoff's names readable against the spec without any of
   them escaping this screen.

   The prototype's [data-vp="mobile"] switch becomes a real media query.
   ========================================================================== */
.mkpage .crumb { font-size: 11.5px; color: var(--text-subtle); font-family: var(--font-mono); margin: 0 0 10px; letter-spacing: .02em; }
.mkpage .pghd { display: flex; align-items: flex-start; gap: 22px; margin-bottom: 20px; }
.mkpage .pghd h1 { font-size: 23px; margin: 0 0 5px; letter-spacing: -.02em; }
.mkpage .pghd .sub { font-size: 13px; color: var(--text-muted); margin: 0; line-height: 1.5; max-width: 44ch; }
.mkpage .pghd-a { margin-left: auto; display: flex; flex-direction: column; align-items: flex-end; gap: 9px; flex-shrink: 0; }

.mkpage .tscroll { overflow-x: auto; }
.mkpage .mtable td { vertical-align: middle; }
.mkpage .mtable th, .mkpage .mtable td { padding: 10px 10px; }
.mkpage .mtable th:first-child, .mkpage .mtable td:first-child { padding-left: 12px; padding-right: 0; width: 30px; }
.mkpage .mtable th:last-child, .mkpage .mtable td:last-child { width: 52px; }
.mkpage .mtable td.tight { width: 34px; padding-right: 0; }

/* Country chip. 25x18 so a two-letter code and a channel glyph occupy the
   same box and the marketplace names stay on one optical line. */
.mkpage .cc { display: inline-grid; place-items: center; width: 25px; height: 18px; border-radius: 3px; border: 1px solid var(--border); background: var(--bg-muted); font-family: var(--font-mono); font-size: 9.5px; font-weight: 500; color: var(--text-muted); flex-shrink: 0; letter-spacing: .03em; }
.mkpage .cc svg { width: 12px; height: 12px; color: var(--text-subtle); }
.mkpage .mkname { display: flex; align-items: center; gap: 10px; min-width: 0; }
.mkpage .mkname b { font-size: 13.5px; font-weight: 500; letter-spacing: -.005em; white-space: nowrap; }

/* Region is a FACT, not a field: mono, muted, no border, no background, no
   hover. Beside it sit the two things that ARE editable -- a bordered 32px
   menu button and a radio -- so region looks like neither and nobody tries
   to "correct" Amazon's grouping. This is why it is not a .badge. */
.mkpage .fact { font-family: var(--font-mono); font-size: 11.5px; font-weight: 500; color: var(--text-muted); letter-spacing: .05em; }
/* NOT `.dash`, and not `.empty` on the button below. Both are live global
   classes in the vendored stylesheet -- `.dash` is a sample-dashboard grid
   container (display:grid, min-height, border) and `.empty` is the 36px
   dashed empty-state box. Scoping MY rules under .mkpage does nothing about
   that: a bare global rule applies to my element the moment I put its class
   name on it. The prototype could use these names because it is one page. */
.mkpage .fact.is-unset { color: var(--text-subtle); opacity: .7; }

.mkpage .cstack { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.mkpage .subnote { font-size: 11px; color: var(--text-subtle); line-height: 1.35; }
.mkpage .subnote.warn { color: var(--warning); }
.mkpage .credcell { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--text-muted); white-space: nowrap; }
.mkpage .credcell svg { width: 14px; height: 14px; color: var(--success); }
.mkpage .credcell.warnc, .mkpage .credcell.warnc svg { color: var(--warning); }
.mkpage .credcell.off, .mkpage .credcell.off svg { color: var(--text-subtle); }
.mkpage .credcell q { font-style: normal; }

/* The ads-account picker is a MENU BUTTON, never a <select>. An Alpine
   <select> whose options come from a nested x-for renders its placeholder
   instead of the stored value, which reads to users as "it doesn't save".
   Building this as a <select> re-introduces that bug. */
.mkpage .profwrap { position: relative; display: block; max-width: 198px; }
.mkpage .profbtn { display: inline-flex; align-items: center; gap: 8px; min-width: 0; width: 100%; max-width: 198px; height: 32px; padding: 0 9px; border: 1px solid var(--border-strong); border-radius: var(--r-md); background: var(--surface); cursor: pointer; color: var(--text); font-family: var(--font-sans); font-size: 12.5px; text-align: left; }
.mkpage .profbtn:hover { border-color: var(--text-subtle); }
.mkpage .profbtn[aria-expanded="true"] { border-color: var(--primary); box-shadow: var(--shadow-focus); }
.mkpage .profbtn .pid { font-family: var(--font-mono); font-size: 11px; color: var(--text-subtle); }
.mkpage .profbtn .chev { margin-left: auto; width: 14px; height: 14px; color: var(--text-subtle); }
.mkpage .profbtn.is-empty { color: var(--text-subtle); }
.mkpage .profmenu { position: absolute; z-index: 55; top: calc(100% + 5px); left: 0; width: 262px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg); box-shadow: var(--shadow-lg); padding: 5px; }

.mkpage .homecell { text-align: center; }
.mkpage .homecell .radio { display: inline-flex; align-items: center; justify-content: center; vertical-align: middle; }

.mkpage .expbtn { width: 26px; height: 26px; border-radius: var(--r-sm); border: 0; background: transparent; color: var(--text-subtle); display: grid; place-items: center; cursor: pointer; }
.mkpage .expbtn:hover { background: var(--bg-muted); color: var(--text); }
.mkpage .expbtn svg { width: 15px; height: 15px; transition: transform var(--dur) var(--ease); }
.mkpage .expbtn.open svg { transform: rotate(90deg); }

.mkpage .exprow > td { background: var(--bg-subtle); padding: 0; border-top: 0; }
/* 40px left indent aligns the panel past the chevron column. */
.mkpage .expwrap { padding: 4px 16px 18px 40px; }
.mkpage .expwrap .lead { font-size: 12.5px; color: var(--text-muted); margin: 0 0 10px; line-height: 1.5; }
.mkpage .expwrap .foot { font-size: 11.5px; color: var(--text-subtle); font-family: var(--font-mono); margin: 10px 0 0; }

.mkpage .cand { display: flex; align-items: center; gap: 12px; padding: 10px 12px; border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface); cursor: pointer; text-align: left; width: 100%; font-family: var(--font-sans); color: var(--text); }
.mkpage .cand + .cand { margin-top: 7px; }
.mkpage .cand:hover { border-color: var(--text-subtle); }
.mkpage .cand.is-on { border-color: var(--primary); box-shadow: 0 0 0 1px var(--primary) inset; background: var(--primary-subtle); }
.mkpage .cand .who { min-width: 0; flex: 1; }
.mkpage .cand .who b { display: block; font-size: 13px; font-weight: 600; }
.mkpage .cand .who span { display: block; font-size: 11.5px; color: var(--text-subtle); font-family: var(--font-mono); margin-top: 2px; }
.mkpage .cand .dot { width: 14px; height: 14px; border-radius: 50%; border: 1.5px solid var(--border-strong); flex-shrink: 0; display: grid; place-items: center; }
.mkpage .cand.is-on .dot { border-color: var(--primary); }
.mkpage .cand.is-on .dot::after { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--primary); }

.mkpage .tnote { font-size: 12px; color: var(--text-subtle); margin: 0; display: flex; align-items: center; gap: 7px; }
.mkpage .tnote svg { width: 13px; height: 13px; flex-shrink: 0; }

/* --------------------------------------------------------------------------
   Mobile: the table becomes a card list. Column names are injected from
   data-l via ::before, and the desktop fixed widths must be reset to auto or
   the stacked cells stay pinned narrow.
   -------------------------------------------------------------------------- */
@media (max-width: 767.98px) {
  .mkpage .pghd { flex-direction: column; gap: 14px; align-items: stretch; }
  .mkpage .pghd-a { margin-left: 0; align-items: stretch; width: 100%; }
  .mkpage .table-card { border: 0; background: transparent; }
  .mkpage .tscroll { overflow: visible; }
  .mkpage .mtable, .mkpage .mtable tbody, .mkpage .mtable tr, .mkpage .mtable td { display: block; width: auto; }
  .mkpage .mtable thead { display: none; }
  .mkpage .mtable tr.mrow { border: 1px solid var(--border); border-radius: var(--r-md); margin-bottom: 9px; padding: 9px 11px; background: var(--surface); }
  .mkpage .mtable td { border: 0; padding: 5px 0; display: flex; align-items: center; gap: 10px; min-height: 0; }
  .mkpage .mtable td::before { content: attr(data-l); flex: 0 0 88px; font-size: 9.5px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--text-subtle); }
  .mkpage .mtable td.tight { display: none; }
  .mkpage .mtable td.nolabel::before { content: none; }
  .mkpage .mtable th:first-child, .mkpage .mtable td:first-child,
  .mkpage .mtable th:nth-child(3), .mkpage .mtable td:nth-child(3),
  .mkpage .mtable th:last-child, .mkpage .mtable td:last-child { width: auto; }
  /* The expanded panel attaches to the bottom of its card -- negative top
     margin, no top border, bottom corners only -- so it reads as part of
     that card rather than as a floating panel. */
  .mkpage .mtable tr.exprow { margin: -9px 0 9px; border: 1px solid var(--border); border-top: 0; border-radius: 0 0 var(--r-md) var(--r-md); }
  .mkpage .mtable tr.exprow > td { padding: 0; }
  .mkpage .expwrap { padding: 12px; }
  .mkpage .profwrap, .mkpage .profbtn { max-width: none; }
  .mkpage .profbtn { min-width: 0; width: 100%; height: 38px; }
  .mkpage .profmenu { width: 100%; }
  .mkpage .table-card-foot { padding: 10px 0 0; border: 0; }
}

/* A marketplace sync discovered but the seller has not confirmed. Muted, so
   it cannot be mistaken for a storefront they told us about. `is-muted` was
   what the old markup bound and it is styled nowhere -- this is the rule that
   was missing, under a name that is actually ours. */
.mkpage .mtable tr.is-pending .mkname b,
.mkpage .mtable tr.is-pending .fact { color: var(--text-subtle); }
.mkpage .mtable tr.is-pending .cc { opacity: .6; }

/* ==========================================================================
   Settings ▸ Credentials ▸ Amazon Advertising  (handoff_marketplaces, S3)
   --------------------------------------------------------------------------
   Scoped under .mkpage, like Surface 2. Checked first that none of these
   names already carries a bare global rule — that check is what `.dash` and
   `.empty` taught, and it is the reverse of the one worth running: not "will
   my rule clobber theirs", but "will theirs clobber my element".
   ========================================================================== */
.mkpage .regs { display: flex; flex-direction: column; gap: 12px; }
.mkpage .regcard { border: 1px solid var(--border); border-radius: var(--r-lg); background: var(--surface); overflow: hidden; }
/* An unconnected region is quieter, never absent. There are exactly three and
   the list never grows, so collapsing the unconnected ones would hide the one
   thing the user needs to notice. */
.mkpage .regcard.off { background: var(--bg-subtle); border-style: dashed; }
.mkpage .reghd { display: flex; align-items: center; gap: 10px; padding: 12px 15px; }
.mkpage .regcard:not(.off) .reghd { border-bottom: 1px solid var(--border); }
.mkpage .reghd h5 { margin: 0; font-size: 13.5px; }
.mkpage .reghd .rc { font-family: var(--font-mono); font-size: 10.5px; color: var(--text-subtle); letter-spacing: .05em; }
.mkpage .reghd .sp, .mkpage .regfoot .sp, .mkpage .pcard-hd .sp { margin-left: auto; }
.mkpage .regbody { padding: 14px 15px; }
.mkpage .regmk { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 13px; }
.mkpage .regmk .names { font-size: 12.5px; color: var(--text-muted); }
.mkpage .regfoot { display: flex; gap: 8px; padding: 11px 15px; border-top: 1px solid var(--border); background: var(--bg-subtle); flex-wrap: wrap; }

.mkpage .pcard { border: 1px solid var(--border); border-radius: var(--r-lg); background: var(--surface); overflow: hidden; }
.mkpage .pcard-hd { display: flex; align-items: center; gap: 12px; padding: 14px 16px; border-bottom: 1px solid var(--border); }
.mkpage .pcard-hd h5 { margin: 0; font-size: 14px; }
.mkpage .pcard-hd.nb { border-bottom-width: 0; }
.mkpage .pcard-bd { padding: 16px; }

.mkpage .kv { display: grid; grid-template-columns: 132px minmax(0, 1fr); gap: 7px 16px; font-size: 12.5px; align-items: center; }
.mkpage .kv dt { color: var(--text-subtle); }
.mkpage .kv dd { margin: 0; font-family: var(--font-mono); font-size: 12px; display: flex; align-items: center; gap: 8px; min-width: 0; }
.mkpage .kv dd .tx { font-family: var(--font-sans); font-size: 12.5px; }

/* What keeps a healthy card short is not collapsing it — it is that the
   secrets live behind one disclosure. */
.mkpage .disclose { display: inline-flex; align-items: center; gap: 6px; border: 0; background: transparent; color: var(--primary); font: 500 12.5px/1 var(--font-sans); cursor: pointer; padding: 0; margin-top: 12px; }
.mkpage .disclose svg { width: 14px; height: 14px; transition: transform var(--dur) var(--ease); }
.mkpage .disclose.open svg { transform: rotate(180deg); }
.mkpage .credbox { margin-top: 12px; padding: 12px 13px; border: 1px solid var(--border); border-radius: var(--r-md); background: var(--bg-subtle); }
.mkpage .mask { font-family: var(--font-mono); letter-spacing: .06em; color: var(--text-muted); }
.mkpage .iconbtn { width: 26px; height: 26px; border-radius: var(--r-sm); border: 1px solid var(--border); background: var(--surface); color: var(--text-subtle); display: grid; place-items: center; cursor: pointer; flex-shrink: 0; }
.mkpage .iconbtn:hover { color: var(--text); border-color: var(--border-strong); }
.mkpage .iconbtn svg { width: 13px; height: 13px; }

@media (max-width: 767.98px) {
  .mkpage .kv { grid-template-columns: minmax(0, 1fr); gap: 2px 0; }
  .mkpage .kv dt { margin-top: 9px; font-size: 10px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; }
  .mkpage .regfoot .btn { flex: 1; }
}

/* ---------------------------------------------------------------------------
   Settings ▸ Marketplaces — phase 4 group cards (§6 of the hierarchy spec).
   One card per region; the seller account and its selling health live on the
   header, so region and connection stop being repeated on every row.
--------------------------------------------------------------------------- */
.mkpage .gcard { margin-bottom: 16px; }
.mkpage .ghead {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; padding: 12px 16px;
  border-bottom: 1px solid var(--border);
}
.mkpage .gtitle { display: flex; align-items: baseline; gap: 10px; min-width: 0; }
.mkpage .gtitle b { font-size: 14px; font-weight: 600; color: var(--text); }
/* The merchant id: a fact in mono, styled like the row-level .fact so it
   reads as data, never as a control. */
.mkpage .gid {
  font-family: var(--font-mono); font-size: 11.5px; color: var(--text-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mkpage .gstat {
  display: inline-flex; align-items: center; gap: 6px; flex: none;
  font-size: 12px; font-weight: 500; color: var(--success);
}
.mkpage .gstat svg { width: 13px; height: 13px; }
.mkpage .gstat.warnc { color: var(--warning); }
.mkpage .gstat.off { color: var(--text-subtle); font-weight: 400; }
/* The unconnected / not-yet-confirmed body: quiet copy plus one action. */
.mkpage .gnote {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; padding: 14px 16px; flex-wrap: wrap;
}
.mkpage .gnote p { margin: 0; font-size: 13px; color: var(--text-muted); }
@media (max-width: 767.98px) {
  .mkpage .ghead { flex-wrap: wrap; }
  .mkpage .gnote { flex-direction: column; align-items: stretch; }
  .mkpage .gnote .btn { justify-content: center; }
}
