/*
Theme Name: PPC Sherpa
Theme URI: https://ppcsherpa.com
Author: PPC Sherpa
Author URI: https://ppcsherpa.com
Description: Custom theme for PPC Sherpa - AI-powered Google Ads auditing SaaS.
Version: 1.0.0
License: Proprietary
Text Domain: ppcsherpa
*/

/* ============================================
   DESIGN TOKENS (CSS Custom Properties)
   ============================================ */

:root {
  /* Brand Colors */
  --color-primary: #1A6BFF;
  --color-primary-hover: #1558D9;
  --color-primary-light: #EBF2FF;
  --color-dark: #0A1F44;
  --color-bg: #FAFBFC;
  --color-surface: #FFFFFF;
  --color-text: #1A1A2E;
  --color-text-muted: #5A5A72;
  --color-border: #E2E4E9;

  /* Semantic Colors */
  --color-success: #16A34A;
  --color-warning: #F59E0B;
  --color-danger: #DC2626;

  /* Typography */
  --font-body: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-mono: 'SF Mono', 'Fira Code', 'Fira Mono', monospace;

  /* Type Scale (major third - 1.25) */
  --text-xs: 0.75rem;     /* 12px */
  --text-sm: 0.875rem;    /* 14px */
  --text-base: 1rem;      /* 16px */
  --text-lg: 1.125rem;    /* 18px */
  --text-xl: 1.25rem;     /* 20px */
  --text-2xl: 1.5rem;     /* 24px */
  --text-3xl: 1.875rem;   /* 30px */
  --text-4xl: 2.25rem;    /* 36px */
  --text-5xl: 3rem;       /* 48px */
  --text-6xl: 3.75rem;    /* 60px */

  /* Font Weights */
  --weight-regular: 400;
  --weight-medium: 500;
  --weight-semibold: 600;
  --weight-bold: 700;

  /* Spacing Scale */
  --space-1: 0.25rem;     /* 4px */
  --space-2: 0.5rem;      /* 8px */
  --space-3: 0.75rem;     /* 12px */
  --space-4: 1rem;        /* 16px */
  --space-5: 1.25rem;     /* 20px */
  --space-6: 1.5rem;      /* 24px */
  --space-8: 2rem;        /* 32px */
  --space-10: 2.5rem;     /* 40px */
  --space-12: 3rem;       /* 48px */
  --space-16: 4rem;       /* 64px */
  --space-20: 5rem;       /* 80px */
  --space-24: 6rem;       /* 96px */

  /* Layout */
  --container-max: 1200px;
  --container-narrow: 800px;
  --container-padding: var(--space-6);

  /* Borders */
  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 12px;
  --radius-xl: 16px;
  --radius-full: 9999px;

  /* Shadows */
  --shadow-sm: 0 1px 2px rgba(10, 31, 68, 0.06);
  --shadow-md: 0 4px 12px rgba(10, 31, 68, 0.08);
  --shadow-lg: 0 8px 24px rgba(10, 31, 68, 0.12);

  /* Transitions */
  --transition-fast: 150ms ease;
  --transition-base: 250ms ease;
}


/* ============================================
   RESET & BASE
   ============================================ */

*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  font-size: 16px;
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  overflow-x: hidden;
}

body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  font-family: var(--font-body);
  font-size: var(--text-base);
  font-weight: var(--weight-regular);
  line-height: 1.6;
  color: var(--color-text);
  background-color: var(--color-bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

#main-content {
  flex: 1 0 auto;
}

img,
picture,
video,
svg {
  display: block;
  max-width: 100%;
}

a {
  color: var(--color-primary);
  text-decoration: none;
  transition: color var(--transition-fast);
}

a:hover {
  color: var(--color-primary-hover);
}

ul, ol {
  list-style: none;
}

button {
  font-family: inherit;
  font-size: inherit;
  cursor: pointer;
  border: none;
  background: none;
}

input,
textarea,
select {
  font-family: inherit;
  font-size: inherit;
}


/* ============================================
   TYPOGRAPHY
   ============================================ */

h1, h2, h3, h4, h5, h6 {
  color: var(--color-dark);
  font-weight: var(--weight-bold);
  line-height: 1.2;
}

h1 { font-size: var(--text-5xl); }
h2 { font-size: var(--text-4xl); }
h3 { font-size: var(--text-3xl); }
h4 { font-size: var(--text-2xl); }
h5 { font-size: var(--text-xl); }
h6 { font-size: var(--text-lg); }

p {
  margin-bottom: var(--space-4);
}

p:last-child {
  margin-bottom: 0;
}

strong {
  font-weight: var(--weight-semibold);
}

small {
  font-size: var(--text-sm);
}


/* ============================================
   LAYOUT
   ============================================ */

.container {
  width: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--container-padding);
}

.container--narrow {
  max-width: var(--container-narrow);
}

.section {
  padding-block: var(--space-20);
}

@media (max-width: 768px) {
  .section {
    padding-block: var(--space-12);
  }
}


/* ============================================
   BUTTONS
   ============================================ */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-6);
  font-weight: var(--weight-semibold);
  font-size: var(--text-base);
  line-height: 1;
  border-radius: var(--radius-md);
  transition: all var(--transition-fast);
  white-space: nowrap;
}

.btn--primary {
  background-color: var(--color-primary);
  color: var(--color-surface);
}

.btn--primary:hover {
  background-color: var(--color-primary-hover);
  color: var(--color-surface);
}

.btn--secondary {
  background-color: transparent;
  color: var(--color-primary);
  border: 1.5px solid var(--color-primary);
}

.btn--secondary:hover {
  background-color: var(--color-primary-light);
}

.btn--lg {
  padding: var(--space-4) var(--space-8);
  font-size: var(--text-lg);
}


/* ============================================
   CARDS
   ============================================ */

.card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-8);
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--transition-base);
}

.card:hover {
  box-shadow: var(--shadow-md);
}


/* ============================================
   SITE HEADER
   ============================================ */

.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
}

.site-header__inner {
  display: flex;
  align-items: center;
  /* Was justify-content: space-between with exactly 2 children (logo,
     nav) -- pinned both to opposite edges. Now that the alert bell (see
     header.php, /app/ pages only) is a 3rd/4th flex child sitting between
     the toggle button and <nav>, space-between would spread it out with
     an even gap on each side instead of hugging whichever neighbor is
     actually visible at a given width. flex-start + margin-right: auto on
     .site-header__logo below reproduces the same "logo left, everything
     else flush right" result while letting the toggle/bell/nav cluster
     stay tight together via this gap, matching .site-header__nav's own
     internal gap value below so the bell-to-nav spacing on desktop looks
     identical to before the bell moved out of <nav>. */
  justify-content: flex-start;
  gap: var(--space-8);
  height: 72px;
}

.site-header__logo {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  /* Consumes all free space right after the logo, pushing every following
     flex child (toggle, bell, nav) to the right edge of the header --
     see .site-header__inner above. */
  margin-right: auto;
}

.site-header__logo img {
  height: 36px;
  width: auto;
}

.site-header__logo-text {
  font-size: var(--text-xl);
  font-weight: var(--weight-bold);
  color: var(--color-dark);
}

.site-header__nav {
  display: flex;
  align-items: center;
  gap: var(--space-8);
}

.site-header__menu {
  display: flex;
  align-items: center;
  gap: var(--space-6);
}

.site-header__menu a {
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--color-text);
  transition: color var(--transition-fast);
}

.site-header__menu a:hover {
  color: var(--color-primary);
}

/* Mobile hamburger */
.site-header__toggle {
  display: none;
  flex-direction: column;
  gap: 5px;
  padding: var(--space-2);
}

.site-header__toggle span {
  display: block;
  width: 24px;
  height: 2px;
  background: var(--color-dark);
  border-radius: 2px;
  transition: all var(--transition-fast);
}

@media (max-width: 768px) {
  .site-header__toggle {
    display: flex;
  }

  .site-header__nav {
    position: fixed;
    top: 72px;
    left: 0;
    right: 0;
    bottom: 0;
    flex-direction: column;
    align-items: stretch;
    background: var(--color-surface);
    padding: var(--space-6);
    transform: translateX(100%);
    transition: transform var(--transition-base);
  }

  .site-header__nav.is-open {
    transform: translateX(0);
  }

  .site-header__menu {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
  }

  .site-header__menu a {
    display: block;
    padding: var(--space-4) 0;
    font-size: var(--text-lg);
    border-bottom: 1px solid var(--color-border);
  }
}

/* /app/ pages (account list + all per-account audit pages) intentionally
   scroll the nav away instead of keeping it stuck -- these pages carry
   long data tables (negative keywords, Meta Spend Monitor) where a
   permanently-pinned nav eats vertical space without helping. Marketing
   pages keep the sticky behavior above untouched. Selector list mirrors
   every /app/ page template (see URL Structure / Live Pages in CLAUDE.md);
   `*=` match tolerates whatever suffix WordPress appends
   (page-template-page-app-php, etc). */
body[class*="page-template-page-app"] .site-header,
body[class*="page-template-page-google-ads"] .site-header,
body[class*="page-template-page-negative-keywords"] .site-header,
body[class*="page-template-page-meta-monitor"] .site-header,
body[class*="page-template-page-gads-setup"] .site-header {
  position: static;
}

/* These three /app/ templates wrap their main content in the global
   .section class, whose padding-block: var(--space-20) (80px) is sized for
   marketing-page hero/section rhythm -- way more than a page that's mostly
   a data table or a short form needs directly under the now-static nav
   above. page-app.php and page-meta-monitor.php don't use .section for
   their main content (their own page-specific containers already sit
   around 32px, matching the value below), so they're not listed here --
   there's nothing to override. Only padding-top changes; bottom keeps the
   full --space-20 on every page, including these three (nothing below the
   content needs tightening). */
body[class*="page-template-page-google-ads"] .section,
body[class*="page-template-page-negative-keywords"] .section,
body[class*="page-template-page-gads-setup"] .section {
  padding-top: var(--space-8);
}


/* ============================================
   SITE FOOTER
   ============================================ */

.site-footer {
  background: var(--color-dark);
  color: rgba(255, 255, 255, 0.7);
  padding-block: var(--space-12);
}

.site-footer a {
  color: rgba(255, 255, 255, 0.7);
}

.site-footer a:hover {
  color: var(--color-surface);
}

.site-footer__inner {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-6);
}

.site-footer__copy {
  font-size: var(--text-sm);
}

.site-footer__links {
  display: flex;
  gap: var(--space-6);
}

.site-footer__links a {
  font-size: var(--text-sm);
}

@media (max-width: 768px) {
  .site-footer__inner {
    flex-direction: column;
    text-align: center;
  }
}


/* ============================================
   FORMS
   ============================================ */

.form-group {
  margin-bottom: var(--space-6);
  position: relative;
}

.form-label {
  display: block;
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-text-muted);
  margin-bottom: var(--space-2);
}

/* Helper copy between a label and its input -- distinct from .form-hint,
   which sits below the input (character counts, inline validation hints). */
.form-help {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  margin-bottom: var(--space-2);
}

.form-input,
.form-select,
.form-textarea {
  display: block;
  width: 100%;
  padding: 14px var(--space-4);
  font-size: var(--text-base);
  font-family: var(--font-body);
  color: var(--color-text);
  background-color: var(--color-bg);
  border: 1.5px solid var(--color-border);
  border-radius: var(--radius-md);
  transition: all var(--transition-base);
}

.form-input:hover,
.form-select:hover,
.form-textarea:hover {
  border-color: #C0C4CC;
  background-color: var(--color-surface);
}

.form-input:focus,
.form-select:focus,
.form-textarea:focus {
  outline: none;
  border-color: var(--color-primary);
  background-color: var(--color-surface);
  box-shadow: 0 0 0 4px rgba(26, 107, 255, 0.12), 0 1px 3px rgba(10, 31, 68, 0.06);
}

.form-input::placeholder,
.form-textarea::placeholder {
  color: #A0A4B0;
}

.form-input--error {
  border-color: var(--color-danger);
  background-color: #FFF5F5;
}

.form-input--error:focus {
  box-shadow: 0 0 0 4px rgba(220, 38, 38, 0.1), 0 1px 3px rgba(10, 31, 68, 0.06);
  background-color: var(--color-surface);
}

.form-hint {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  margin-top: var(--space-2);
}

.form-error {
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  color: var(--color-danger);
  margin-top: var(--space-2);
  display: flex;
  align-items: center;
  gap: var(--space-1);
}

.form-error::before {
  content: "";
  display: inline-block;
  width: 14px;
  height: 14px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='%23DC2626'%3E%3Cpath fill-rule='evenodd' d='M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z'/%3E%3C/svg%3E") no-repeat center;
  background-size: contain;
  flex-shrink: 0;
}

.form-textarea {
  min-height: 120px;
  resize: vertical;
}

.form-select {
  appearance: none;
  cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%235A5A72' d='M1.41 0L6 4.58 10.59 0 12 1.41l-6 6-6-6z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--space-4) center;
  padding-right: var(--space-10);
}

/* Toggle switch instead of basic checkbox */
.form-toggle {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  cursor: pointer;
  user-select: none;
}

.form-toggle input[type="checkbox"] {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}

.form-toggle__track {
  position: relative;
  width: 44px;
  height: 24px;
  background: var(--color-border);
  border-radius: var(--radius-full);
  transition: background var(--transition-fast);
  flex-shrink: 0;
}

.form-toggle__track::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 20px;
  height: 20px;
  background: var(--color-surface);
  border-radius: 50%;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
  transition: transform var(--transition-fast);
}

.form-toggle input:checked + .form-toggle__track {
  background: var(--color-primary);
}

.form-toggle input:checked + .form-toggle__track::after {
  transform: translateX(20px);
}

.form-toggle input:focus-visible + .form-toggle__track {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

.form-toggle__label {
  font-size: var(--text-sm);
  color: var(--color-text);
}

/* Standard checkbox (for legal/consent) */
.form-checkbox {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  cursor: pointer;
}

.form-checkbox input[type="checkbox"] {
  appearance: none;
  width: 20px;
  height: 20px;
  border: 1.5px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-bg);
  cursor: pointer;
  flex-shrink: 0;
  margin-top: 1px;
  transition: all var(--transition-fast);
  position: relative;
}

.form-checkbox input[type="checkbox"]:checked {
  background: var(--color-primary);
  border-color: var(--color-primary);
}

.form-checkbox input[type="checkbox"]:checked::after {
  content: "";
  position: absolute;
  left: 6px;
  top: 2px;
  width: 5px;
  height: 10px;
  border: solid var(--color-surface);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

.form-checkbox input[type="checkbox"]:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

.form-checkbox span {
  font-size: var(--text-sm);
  color: var(--color-text);
  line-height: 1.5;
}


/* ============================================
   TABLES
   ============================================ */

.table-wrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
}

.table th,
.table td {
  padding: var(--space-3) var(--space-4);
  text-align: left;
  border-bottom: 1px solid var(--color-border);
}

.table th {
  font-weight: var(--weight-semibold);
  color: var(--color-dark);
  background: var(--color-bg);
  white-space: nowrap;
}

.table tbody tr:hover {
  background-color: var(--color-primary-light);
}


/* ============================================
   SHARED APP DATA TABLE (.sherpa-table)
   ============================================
   Standard look for in-app data tables (negative keywords, Meta Spend
   Monitor): dark navy static header, consistent row striping/hover.
   Deliberately covers only the table itself, not the page-specific card
   chrome (border/shadow/radius) around it. */

.sherpa-table-wrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.sherpa-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}

/* Plain static header by default -- renders in normal flow at the top of
   the table, above every row. No position: sticky here (it was removed on
   purpose): it needs an ancestor with no overflow to pin to the viewport,
   but this table lives inside a horizontally-scrollable wrapper, so sticky
   landed the header on top of row 1 instead. A static header sits where it
   should with zero fuss. /app/ pages re-enable sticky below now that both
   blockers (the fixed nav and the wrapper's overflow) are addressed there. */
.sherpa-table th {
  text-align: left;
  padding: 10px 14px;
  background-color: var(--color-dark);
  color: #FFFFFF;
  font-weight: 600;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  white-space: nowrap;
}

/* Rounds the header's top corners directly rather than relying on
   overflow: hidden on an ancestor card to clip them -- see note above. */
.sherpa-table thead tr:first-child th:first-child {
  border-top-left-radius: 12px;
}

.sherpa-table thead tr:first-child th:last-child {
  border-top-right-radius: 12px;
}

.sherpa-table td {
  padding: 12px 14px;
  vertical-align: middle;
}

/* Border lives on the row, not the cell: individual td heights can differ
   (a multiline term/reason cell vs. a short Status/Actions cell), and
   border-bottom on td renders at each cell's own bottom edge, which
   staggers into a broken line instead of one continuous rule across the
   row. tr border-bottom is unaffected by per-cell height differences.
   Requires border-collapse: collapse (set on .sherpa-table above) for tr
   borders to render at all. */
.sherpa-table tbody tr {
  border-bottom: 1px solid var(--color-border);
}

/* Both consumers of this component (negative keywords, Meta Spend
   Monitor) render a bordered pagination bar with its own border-top
   directly below the table -- omit the last row's border-bottom so it
   doesn't double up against that line. */
.sherpa-table tbody tr:last-child {
  border-bottom: none;
}

.sherpa-table tbody tr:nth-child(even) {
  background: var(--color-bg);
}

.sherpa-table tbody tr:hover {
  background: var(--color-primary-light);
}

/* ---- /app/ pages: sticky header ----
   Now that the nav is position: static on /app/ pages (see the
   body[class*="page-template-..."] .site-header override above), a sticky
   table header has somewhere real to pin. Getting there also requires
   removing the other blocker documented above: .sherpa-table-wrap's
   overflow-x: auto (needed for horizontal scroll on narrow widths) forces
   overflow-y to auto too per the CSS Overflow spec, which makes the wrapper
   -- not the viewport -- the sticky positioning context, so the header
   never actually pins while scrolling (it just sits on top of row 1). This
   override drops the wrapper back to overflow-x: visible on /app/ pages
   only, trading away that wrapper's horizontal-scroll fallback in exchange
   for a working sticky header. Acceptable here because the table view is
   desktop-only (768px+, see .negkw-table-wrap / min-width: 768px media
   query) -- narrower viewports get the stacked-card layout instead, which
   never used this wrapper's scroll behavior anyway. */
body[class*="page-template-page-app"] .sherpa-table-wrap,
body[class*="page-template-page-google-ads"] .sherpa-table-wrap,
body[class*="page-template-page-negative-keywords"] .sherpa-table-wrap,
body[class*="page-template-page-meta-monitor"] .sherpa-table-wrap,
body[class*="page-template-page-gads-setup"] .sherpa-table-wrap {
  overflow-x: visible;
}

body[class*="page-template-page-app"] .sherpa-table thead th,
body[class*="page-template-page-google-ads"] .sherpa-table thead th,
body[class*="page-template-page-negative-keywords"] .sherpa-table thead th,
body[class*="page-template-page-meta-monitor"] .sherpa-table thead th,
body[class*="page-template-page-gads-setup"] .sherpa-table thead th {
  position: sticky;
  top: 0;
  z-index: 10;
  /* Explicit (not just inherited from .sherpa-table th above) so rows
     scrolling underneath a pinned header never show through it. */
  background-color: var(--color-dark);
}

/* WordPress adds body.admin-bar and a 32px-tall #wpadminbar fixed to the
   viewport top whenever a WP admin is logged in. The sticky header needs
   to clear it by the same amount on these same /app/ pages, or the bar
   would cover the top row of the pinned header. */
body.admin-bar[class*="page-template-page-app"] .sherpa-table thead th,
body.admin-bar[class*="page-template-page-google-ads"] .sherpa-table thead th,
body.admin-bar[class*="page-template-page-negative-keywords"] .sherpa-table thead th,
body.admin-bar[class*="page-template-page-meta-monitor"] .sherpa-table thead th,
body.admin-bar[class*="page-template-page-gads-setup"] .sherpa-table thead th {
  top: 32px;
}

/* The rounded top corners set on the first/last th above (see "Rounds the
   header's top corners directly" note higher up) only make sense when the
   table's top edge sits in context with the card below it. Once the header
   is pinned to the viewport edge (sticky, above), those corners leave a
   visible white gap between the rounded navy corner and the page
   background behind it. Zeroed out on these same /app/ pages only --
   bottom radius (on .negkw-pagination, unaffected by sticky) stays as-is. */
body[class*="page-template-page-app"] .sherpa-table thead tr:first-child th:first-child,
body[class*="page-template-page-google-ads"] .sherpa-table thead tr:first-child th:first-child,
body[class*="page-template-page-negative-keywords"] .sherpa-table thead tr:first-child th:first-child,
body[class*="page-template-page-meta-monitor"] .sherpa-table thead tr:first-child th:first-child,
body[class*="page-template-page-gads-setup"] .sherpa-table thead tr:first-child th:first-child {
  border-top-left-radius: 0;
}

body[class*="page-template-page-app"] .sherpa-table thead tr:first-child th:last-child,
body[class*="page-template-page-google-ads"] .sherpa-table thead tr:first-child th:last-child,
body[class*="page-template-page-negative-keywords"] .sherpa-table thead tr:first-child th:last-child,
body[class*="page-template-page-meta-monitor"] .sherpa-table thead tr:first-child th:last-child,
body[class*="page-template-page-gads-setup"] .sherpa-table thead tr:first-child th:last-child {
  border-top-right-radius: 0;
}


/* ============================================
   BADGES
   ============================================ */

.badge {
  display: inline-flex;
  align-items: center;
  padding: var(--space-1) var(--space-3);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  border-radius: var(--radius-full);
  line-height: 1.4;
}

.badge--success {
  background: #DCFCE7;
  color: #166534;
}

.badge--warning {
  background: #FEF3C7;
  color: #92400E;
}

.badge--danger {
  background: #FEE2E2;
  color: #991B1B;
}

.badge--info {
  background: var(--color-primary-light);
  color: #1E40AF;
}

/* Solid primary fill (not the pale --color-primary-light tint --info uses)
   so this reads clearly even sitting on top of a --color-primary-light row
   highlight (e.g. the setup page's new-campaign highlight, see
   page-gads-setup.js) rather than blending into it. */
.badge--new {
  background: var(--color-primary);
  color: var(--color-surface);
}


/* ============================================
   ALERTS
   ============================================ */

.alert {
  padding: var(--space-4) var(--space-5);
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
  line-height: 1.5;
  border-left: 4px solid;
}

.alert--success {
  background: #DCFCE7;
  border-color: var(--color-success);
  color: #166534;
}

.alert--warning {
  background: #FEF3C7;
  border-color: var(--color-warning);
  color: #92400E;
}

.alert--danger {
  background: #FEE2E2;
  border-color: var(--color-danger);
  color: #991B1B;
}

.alert--info {
  background: var(--color-primary-light);
  border-color: var(--color-primary);
  color: #1E40AF;
}


/* ============================================
   HOVER POPOVER (shared: negative keywords detail page waste pill, Google
   Ads dashboard tile waste figure -- methodology explainers on
   estimated-waste dollar figures). Replaces an earlier separate-icon
   .info-tooltip approach: the trigger is the element itself (whole pill /
   whole metric), not an added icon. Hover reveals after a 500ms delay
   (transition-delay), dismisses instantly; .active is a JS-toggled
   fallback for touch devices, dismissing instantly too. Each consuming
   page adds a small delegated click handler (initPopovers()) for that,
   duplicated per page per this theme's convention.
   ============================================ */

.has-popover {
  position: relative;
  cursor: help;
  transition: background-color var(--transition-fast);
}

.has-popover:hover,
.has-popover.active {
  background-color: var(--color-primary-light);
}

.has-popover .popover-content {
  position: absolute;
  top: calc(100% + 8px);
  left: 50%;
  width: max-content;
  max-width: 320px;
  background: var(--color-dark);
  color: #FFFFFF;
  font-size: var(--text-xs);
  font-weight: 400;
  line-height: 1.5;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  opacity: 0;
  visibility: hidden;
  transform: translateX(-50%);
  transition: opacity var(--transition-fast), visibility var(--transition-fast);
  transition-delay: 0s;
  z-index: 60;
  pointer-events: none;
  /* white-space isn't set anywhere else on this element, so without an
     explicit value it inherits from whatever trigger it's nested in --
     .negkw-stat-pill and .sherpa-table th both set white-space: nowrap,
     which without this override would stop the text from wrapping at
     all inside the max-width box. */
  white-space: normal;
  word-wrap: break-word;
  overflow-wrap: break-word;
  /* Same inheritance issue as white-space above: .sherpa-table th sets
     text-transform: uppercase (an inherited property), which without this
     override would shout the Annual Waste column header's popover copy
     in all caps instead of the normal sentence casing it's written in. */
  text-transform: none;
}

.has-popover .popover-content::before {
  content: '';
  position: absolute;
  bottom: 100%;
  left: 50%;
  transform: translateX(-50%);
  border: 6px solid transparent;
  border-bottom-color: var(--color-dark);
}

.has-popover:hover .popover-content,
.has-popover:focus-within .popover-content {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transition-delay: 0.5s;
}

.has-popover.active .popover-content {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transition-delay: 0s;
}

/* Modifier: left-align instead of centering the popover on its trigger.
   Centered positioning (left: 50%; transform: translateX(-50%)) can push
   a 320px-wide popover past the viewport's right edge, where it gets
   silently clipped by html's global `overflow-x: hidden` (see the base
   html rule above) -- that rule is app-wide (keeps things like the
   off-screen slide-in auth drawer from creating a horizontal scrollbar)
   and isn't safe to remove just for this, so triggers near the left/
   center-left of their container use this modifier instead. */
.has-popover--align-left .popover-content {
  left: 0;
  transform: none;
}

.has-popover--align-left .popover-content::before {
  left: 16px;
  transform: none;
}

/* Modifier: flip the popover to appear above the trigger instead of below
   -- for triggers with content directly below them (e.g. a sortable table
   column header, where "below" would be the first data row). */
.has-popover .popover-content--above {
  top: auto;
  bottom: calc(100% + 8px);
}

.has-popover .popover-content--above::before {
  bottom: auto;
  top: 100%;
  border-bottom-color: transparent;
  border-top-color: var(--color-dark);
}

@media (max-width: 480px) {
  .has-popover .popover-content {
    left: auto;
    right: -8px;
    transform: none;
  }

  .has-popover .popover-content::before {
    left: auto;
    right: 12px;
    transform: none;
  }
}


/* ============================================
   SHARED LOADING ANIMATION (.sherpa-loader)
   ============================================ */

/* Sherpa walk-cycle sprite sheet: assets/img/sherpa-sprite-edge.png, 3
   frames of 724x571 each, 2172px total width. .sherpa-loader__sprite is
   sized to one natural frame with the keyframes shifting
   background-position-x from 0 to -2172px in 3 discrete steps() -- the raw
   pixel math stays the same regardless of display size. Size variants scale
   that natural-size sprite down with CSS transform inside a fixed-size,
   overflow-hidden wrapper (same technique proven in the style guide's
   Loading Animation demo, see page-styleguide.php), so a new size only
   means adding one wrapper-size rule + one scale rule, never touching the
   animation itself. Replaces the per-page .app-spinner--lg (page-app.css,
   page-meta-monitor.css), .negkw-spinner (page-negative-keywords.css), and
   .setup-loader-dots (page-gads-setup.css) loading states -- the small 14px
   .app-spinner stays as-is, the sherpa character isn't readable at that
   size. */
.sherpa-loader {
  display: inline-block;
  overflow: hidden;
  vertical-align: middle;
}

/* Every prior .sherpa-loader usage put the `hidden` attribute on an outer
   wrapper element (e.g. #app-state-loading), never on .sherpa-loader
   itself, so this override was never needed until the Refresh Accounts
   button (page-app.php) toggled `hidden` directly on the .sherpa-loader
   span inline inside the button. Without it, the author rule above
   (`display: inline-block`) beats the browser's built-in
   `[hidden] { display: none }` UA rule regardless of specificity -- same
   recurring gotcha documented elsewhere in this file (Key Learnings) for
   .app-spinner, .app-loading, etc. */
.sherpa-loader[hidden] {
  display: none;
}

.sherpa-loader__sprite {
  display: block;
  width: 724px;
  height: 571px;
  background-image: url('assets/img/sherpa-sprite-edge.png');
  background-repeat: no-repeat;
  background-position: 0 0;
  transform-origin: top left;
  animation: sherpa-loader-walk 0.9s steps(3) infinite;
}

@keyframes sherpa-loader-walk {
  from { background-position-x: 0; }
  to   { background-position-x: -2172px; }
}

/* Wrapper dimensions = 724px/571px scaled to each target height
   (height/571 factor), e.g. 48px tall -> 48 * 724/571 = 60.86px wide. */
.sherpa-loader--sm { width: 35.50px;  height: 28px; }
.sherpa-loader--md { width: 60.86px;  height: 48px; }
.sherpa-loader--lg { width: 101.44px; height: 80px; }

.sherpa-loader--sm .sherpa-loader__sprite { transform: scale(0.04904); }
.sherpa-loader--md .sherpa-loader__sprite { transform: scale(0.08406); }
.sherpa-loader--lg .sherpa-loader__sprite { transform: scale(0.14011); }


/* ============================================
   HEALTH GRADES
   ============================================ */

.grade {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  font-size: var(--text-2xl);
  font-weight: var(--weight-bold);
  border-radius: var(--radius-md);
  line-height: 1;
}

.grade--a { background: #DCFCE7; color: #166534; }
.grade--b { background: #D1FAE5; color: #065F46; }
.grade--c { background: #FEF3C7; color: #92400E; }
.grade--d { background: #FED7AA; color: #9A3412; }
.grade--f { background: #FEE2E2; color: #991B1B; }

.grade--lg {
  width: 72px;
  height: 72px;
  font-size: var(--text-4xl);
  border-radius: var(--radius-lg);
}


/* ============================================
   CODE / MONOSPACE
   ============================================ */

code {
  font-family: var(--font-mono);
  font-size: 0.875em;
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: 0.125em 0.375em;
}

pre {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  background: var(--color-dark);
  color: #E2E8F0;
  padding: var(--space-5);
  border-radius: var(--radius-md);
  overflow-x: auto;
  line-height: 1.6;
}

pre code {
  background: none;
  border: none;
  padding: 0;
  font-size: inherit;
  color: inherit;
}


/* ============================================
   UTILITIES
   ============================================ */

.text-center { text-align: center; }
.text-muted { color: var(--color-text-muted); }
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border-width: 0;
}


/* ============================================
   FOCUS STYLES (Accessibility)
   ============================================ */

:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}


/* ============================================
   SCROLL ANIMATIONS
   ============================================ */

.animate-on-scroll {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 0.6s ease, transform 0.6s ease;
}

.animate-on-scroll.is-visible {
  opacity: 1;
  transform: translateY(0);
}


/* ============================================
   MODAL / WAITLIST OVERLAY
   ============================================ */

.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(10, 31, 68, 0.6);
  z-index: 500;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-6);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--transition-base), visibility var(--transition-base);
}

.modal-overlay.is-open {
  opacity: 1;
  visibility: visible;
}

.modal {
  background: var(--color-surface);
  border-radius: var(--radius-xl);
  padding: var(--space-10);
  max-width: 480px;
  width: 100%;
  position: relative;
  box-shadow: var(--shadow-lg), 0 32px 64px rgba(10, 31, 68, 0.2);
  transform: translateY(16px);
  transition: transform var(--transition-base);
}

.modal-overlay.is-open .modal {
  transform: translateY(0);
}

.modal__close {
  position: absolute;
  top: var(--space-4);
  right: var(--space-4);
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  color: var(--color-text-muted);
  transition: background var(--transition-fast), color var(--transition-fast);
}

.modal__close:hover {
  background: var(--color-bg);
  color: var(--color-dark);
}

.modal__headline {
  font-size: var(--text-2xl);
  font-weight: var(--weight-bold);
  color: var(--color-dark);
  margin-bottom: var(--space-2);
  line-height: 1.2;
}

.modal__sub {
  font-size: var(--text-base);
  color: var(--color-text-muted);
  margin-bottom: var(--space-6);
  line-height: 1.5;
}

/* Formidable Forms overrides */
.modal .frm_forms .frm_form_field {
  margin-bottom: var(--space-5) !important;
}

.modal .frm_forms label.frm_primary_label {
  display: block !important;
  font-size: var(--text-xs) !important;
  font-weight: var(--weight-bold) !important;
  text-transform: uppercase !important;
  letter-spacing: 0.06em !important;
  color: var(--color-text-muted) !important;
  margin-bottom: var(--space-2) !important;
}

.modal .frm_forms input[type="text"],
.modal .frm_forms input[type="email"],
.modal .frm_forms input[type="tel"],
.modal .frm_forms select,
.modal .frm_forms textarea {
  display: block !important;
  width: 100% !important;
  padding: 14px var(--space-4) !important;
  font-size: var(--text-base) !important;
  font-family: var(--font-body) !important;
  color: var(--color-text) !important;
  background-color: var(--color-bg) !important;
  border: 1.5px solid var(--color-border) !important;
  border-radius: var(--radius-md) !important;
  box-shadow: none !important;
  transition: border-color var(--transition-base), box-shadow var(--transition-base) !important;
}

.modal .frm_forms input[type="text"]:focus,
.modal .frm_forms input[type="email"]:focus,
.modal .frm_forms input[type="tel"]:focus,
.modal .frm_forms textarea:focus {
  outline: none !important;
  border-color: var(--color-primary) !important;
  background-color: var(--color-surface) !important;
  box-shadow: 0 0 0 4px rgba(26, 107, 255, 0.12) !important;
}

.modal .frm_forms .frm_submit input[type="submit"],
.modal .frm_forms .frm_submit button[type="submit"] {
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
  width: 100% !important;
  padding: var(--space-4) var(--space-8) !important;
  font-family: var(--font-body) !important;
  font-size: var(--text-lg) !important;
  font-weight: var(--weight-semibold) !important;
  line-height: 1 !important;
  background-color: var(--color-primary) !important;
  color: var(--color-surface) !important;
  border: none !important;
  border-radius: var(--radius-md) !important;
  cursor: pointer !important;
  transition: background-color var(--transition-fast) !important;
  box-shadow: none !important;
}

.modal .frm_forms .frm_submit input[type="submit"]:hover,
.modal .frm_forms .frm_submit button[type="submit"]:hover {
  background-color: var(--color-primary-hover) !important;
}

/* Hide Formidable's default success message; we show our own */
.modal .frm_message,
.modal .frm_forms .frm_message {
  display: none !important;
}

/* Custom success state */
.modal__success {
  display: none;
  text-align: center;
  padding: var(--space-4) 0 var(--space-2);
}

.modal__success.is-visible {
  display: block;
}

.modal__success-icon {
  width: 88px;
  height: 88px;
  background: linear-gradient(145deg, #DCFCE7, #BBF7D0);
  color: var(--color-success);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto var(--space-6);
  box-shadow: 0 0 0 10px rgba(22, 163, 74, 0.08);
}

.modal__success-headline {
  font-size: var(--text-2xl);
  font-weight: var(--weight-bold);
  color: var(--color-dark);
  margin-bottom: var(--space-3);
  line-height: 1.2;
}

.modal__success-message {
  font-size: var(--text-base);
  color: var(--color-text-muted);
  line-height: 1.65;
  max-width: 320px;
  margin-inline: auto;
  margin-bottom: var(--space-8);
}

.modal__success-meta {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  align-items: center;
}

.modal__success-meta-item {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  padding: var(--space-2) var(--space-4);
}

@media (max-width: 480px) {
  .modal {
    padding: var(--space-8) var(--space-6);
  }
}


/* ============================================
   AUTH DRAWER
   ============================================ */

.auth-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  z-index: 9998;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s ease;
}

.auth-overlay.active {
  opacity: 1;
  pointer-events: auto;
}

.auth-drawer {
  position: fixed;
  top: 0;
  right: 0;
  height: 100vh;
  width: 448px;
  max-width: 100vw;
  background: var(--color-surface);
  z-index: 9999;
  transform: translateX(100%);
  transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  box-shadow: -4px 0 24px rgba(0, 0, 0, 0.15);
  display: flex;
  flex-direction: column;
  overflow-x: hidden;
}

.auth-drawer.active {
  transform: translateX(0);
}

.auth-drawer-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 24px;
  border-bottom: 1px solid var(--color-border);
  flex-shrink: 0;
}

.auth-drawer-header h2 {
  font-size: 1.25rem;
  font-weight: 600;
  color: var(--color-text);
  margin: 0;
}

.auth-drawer-close {
  background: none;
  border: none;
  cursor: pointer;
  padding: 8px;
  color: var(--color-text-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  transition: background var(--transition-fast), color var(--transition-fast);
}

.auth-drawer-close:hover {
  background: var(--color-bg);
  color: var(--color-dark);
}

.auth-drawer-body {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 24px;
  display: flex;
  justify-content: center;
}

#clerk-auth-mount {
  width: 100%;
}

.auth-drawer-footer {
  padding: 16px 24px;
  text-align: center;
  border-top: 1px solid var(--color-border);
  font-size: 0.875rem;
  color: var(--color-text-muted);
  flex-shrink: 0;
}

.auth-drawer-footer a {
  color: var(--color-primary);
  text-decoration: none;
  font-weight: 500;
  margin-left: 4px;
}

.auth-drawer-footer a:hover {
  text-decoration: underline;
}

body.drawer-open {
  overflow: hidden;
}

@media (max-width: 768px) {
  .auth-drawer {
    width: 100vw;
  }
}


/* ============================================
   AUTH NAV STATE
   ============================================ */

.auth-logged-out {
  display: flex;
  align-items: center;
  gap: 12px;
}

.auth-logged-out.hidden {
  display: none;
}

.auth-logged-in {
  display: none;
  align-items: center;
  gap: 16px;
}

.auth-logged-in.active {
  display: flex;
}

.nav-dashboard-link {
  color: var(--color-text);
  font-weight: var(--weight-medium);
  text-decoration: none;
  font-size: 0.9375rem;
}

.nav-dashboard-link:hover {
  color: var(--color-primary);
}

#clerk-user-button {
  display: flex;
  align-items: center;
}


/* ============================================
   ALERT BELL (nav notifications, /app/ pages only)
   ============================================
   Bell icon + unread badge + dropdown panel in the header bar, wired up by
   theme/assets/js/alerts.js against the backend's /alerts endpoints (see
   CLAUDE.md). Markup is only rendered in header.php on /app/ page
   templates (ppcsherpa_is_app_page() in functions.php), but the CSS lives
   globally here per this theme's convention of keeping design-token-based
   component styles centralized rather than duplicated per page. Overlay
   and dropdown open/close via a JS-toggled .active class, same pattern as
   the global auth drawer (.auth-overlay/.auth-drawer above), rather than
   the hidden-attribute toggle used for simple show/hide elements -- this
   one needs the opacity/transform transition on open/close.

   #alerts-bell is a direct sibling of <nav id="primary-nav"> inside
   .site-header__inner, not nested inside it -- <nav> collapses into an
   off-canvas drawer at 768px (see .site-header__nav's mobile rules
   above), and the bell needs to stay reachable without opening the
   hamburger. .alerts-dropdown's position: absolute is still relative to
   #alerts-bell (position: relative, right below) regardless of where
   that wrapper sits in the DOM, so moving it out of <nav> doesn't change
   how the dropdown positions itself -- only .site-header__inner's own
   flex layout (see the SITE HEADER section above) needed adjusting to
   fit the bell in as a new flex child. */

.alerts-bell {
  position: relative;
  display: flex;
  align-items: center;
}

.alerts-bell__btn {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  background: none;
  border: none;
  border-radius: var(--radius-md);
  color: var(--color-text);
  cursor: pointer;
  transition: background-color var(--transition-fast), color var(--transition-fast);
}

.alerts-bell__btn:hover,
.alerts-bell__btn.active {
  background-color: var(--color-primary-light);
  color: var(--color-primary);
}

.alerts-badge {
  position: absolute;
  top: -2px;
  right: -2px;
  min-width: 18px;
  height: 18px;
  padding: 0 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-danger);
  color: #FFFFFF;
  font-size: 11px;
  font-weight: var(--weight-bold);
  line-height: 1;
  border-radius: var(--radius-full);
  border: 2px solid var(--color-surface);
}

/* .alerts-badge sets its own display: flex above, which (per this file's
   existing [hidden] gotcha elsewhere) beats the browser's UA [hidden]
   rule and needs re-declaring here -- see Key Learnings in CLAUDE.md. */
.alerts-badge[hidden] {
  display: none;
}

.alerts-overlay {
  display: none;
}

.alerts-dropdown {
  position: absolute;
  top: calc(100% + 10px);
  right: 0;
  width: 360px;
  max-height: 420px;
  overflow-y: auto;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  z-index: 200;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transform: translateY(-6px);
  transition: opacity var(--transition-fast), visibility var(--transition-fast), transform var(--transition-fast);
}

.alerts-dropdown.active {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: translateY(0);
}

.alerts-dropdown__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-4);
  border-bottom: 1px solid var(--color-border);
}

.alerts-dropdown__title {
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--color-dark);
}

.alerts-dropdown__mark-all {
  background: none;
  border: none;
  padding: 0;
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  color: var(--color-primary);
  cursor: pointer;
}

.alerts-dropdown__mark-all:hover {
  text-decoration: underline;
}

.alerts-dropdown__list {
  display: flex;
  flex-direction: column;
}

.alerts-row {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: var(--space-3) var(--space-4);
  padding-right: var(--space-8);
  border-bottom: 1px solid var(--color-border);
  border-left: 4px solid transparent;
  background: var(--color-surface);
  cursor: pointer;
  transition: background-color var(--transition-fast);
}

.alerts-row:last-child {
  border-bottom: none;
}

.alerts-row:hover {
  background: var(--color-bg);
}

.alerts-row--unread {
  background: var(--color-primary-light);
  border-left-color: var(--color-primary);
}

.alerts-row--unread:hover {
  background: #E0EBFF;
}

.alerts-row__type {
  font-size: 10px;
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--color-text-muted);
}

.alerts-row__title {
  font-size: var(--text-sm);
  font-weight: var(--weight-regular);
  color: var(--color-text);
}

.alerts-row--unread .alerts-row__title {
  font-weight: var(--weight-bold);
}

.alerts-row__body {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  line-height: 1.4;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.alerts-row__time {
  font-size: 11px;
  color: var(--color-text-muted);
  margin-top: 2px;
}

.alerts-row__dismiss {
  position: absolute;
  top: var(--space-3);
  right: var(--space-3);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  padding: 0;
  background: none;
  border: none;
  border-radius: var(--radius-sm);
  color: var(--color-text-muted);
  opacity: 0;
  cursor: pointer;
  transition: opacity var(--transition-fast), background-color var(--transition-fast), color var(--transition-fast);
}

.alerts-row:hover .alerts-row__dismiss,
.alerts-row__dismiss:focus {
  opacity: 1;
}

.alerts-row__dismiss:hover {
  background: rgba(10, 31, 68, 0.08);
  color: var(--color-danger);
}

.alerts-dropdown__empty {
  padding: var(--space-8) var(--space-4);
  text-align: center;
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

/* Mobile: full-width dropdown anchored below the nav bar with a dimming
   overlay behind it, instead of a small right-aligned panel. 640px is a
   deliberately narrower breakpoint than the site nav's own 768px collapse
   (see SITE HEADER above) -- this only governs the dropdown's own layout,
   not whether the bell is reachable. */
@media (max-width: 640px) {
  .alerts-overlay {
    display: block;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.35);
    z-index: 199;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--transition-fast);
  }

  .alerts-overlay.active {
    opacity: 1;
    pointer-events: auto;
  }

  .alerts-dropdown {
    position: fixed;
    top: 72px;
    left: 0;
    right: 0;
    width: 100%;
    max-width: 100%;
    max-height: calc(100vh - 72px);
    border-radius: 0;
  }

  /* Clears the WP admin toolbar (32px, fixed to the viewport top) the same
     way the sticky table header does elsewhere in this file. */
  body.admin-bar .alerts-dropdown {
    top: 104px;
    max-height: calc(100vh - 104px);
  }
}


/* ============================================
   RECONNECT MODAL (global reauth prompt, theme/assets/js/reconnect-modal.js)
   ============================================
   Defined globally (not in a page-specific stylesheet) the same way the
   alert bell above is, even though the markup itself is injected by JS --
   not present in any page-*.php template at all -- and only ever actually
   shown on /app/ pages. Same visual shape as page-app.css's
   .app-modal-overlay/.app-modal (deactivate confirmation), rebuilt with
   design tokens here since this one isn't page-specific. See CLAUDE.md. */

.reconnect-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(10, 31, 68, 0.5);
  z-index: 1500;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-6);
}

.reconnect-modal-overlay[hidden] {
  display: none;
}

.reconnect-modal {
  background: var(--color-surface);
  width: 100%;
  max-width: 440px;
  padding: var(--space-8);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}

.reconnect-modal__title {
  color: var(--color-dark);
  margin-bottom: var(--space-4);
}

.reconnect-modal__body {
  color: var(--color-text-muted);
  line-height: 1.6;
  margin-bottom: var(--space-6);
}

.reconnect-modal__actions {
  display: flex;
  gap: var(--space-3);
  justify-content: flex-end;
}


/* ============================================
   BREADCRUMB (shared: /app/google-ads/{id}/, /app/meta-monitor/)
   ============================================
   Defined globally (not in a page-specific stylesheet) so both pages stay
   visually identical without duplicating the block in two self-contained
   page CSS files. */

.app-breadcrumb {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-8);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  flex-wrap: wrap;
}

.app-breadcrumb__link {
  color: var(--color-text-muted);
}

.app-breadcrumb__link:hover {
  color: var(--color-primary);
}

.app-breadcrumb__sep {
  color: var(--color-border);
}

.app-breadcrumb__item {
  color: var(--color-text-muted);
}

.app-breadcrumb__item--current {
  color: var(--color-dark);
}


/* ============================================
   ACCOUNT SWITCHER (shared component, theme/assets/js/account-switcher.js)
   ============================================
   The breadcrumb's account segment on the Google Ads Dashboard, Negative
   Keywords, and Setup pages -- a dropdown trigger (name + chevron) instead
   of a plain label/link, opening a scrollable list of the user's other
   active accounts. Defined globally (not per-page) since the three
   consuming pages need it to look and behave identically, same reasoning
   as the shared .app-breadcrumb block above. */

.app-breadcrumb__switcher {
  position: relative;
  display: inline-flex;
}

.app-breadcrumb__switcher-trigger {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  font-weight: inherit;
  color: var(--color-dark);
  cursor: pointer;
}

.app-breadcrumb__switcher-trigger:hover {
  color: var(--color-primary);
}

.app-breadcrumb__switcher-chevron {
  flex-shrink: 0;
  color: currentColor;
  transition: transform var(--transition-fast);
}

.app-breadcrumb__switcher-trigger[aria-expanded="true"] .app-breadcrumb__switcher-chevron {
  transform: rotate(180deg);
}

.app-breadcrumb__switcher-panel {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  z-index: 50;
  width: 260px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  overflow: hidden;
}

.app-breadcrumb__switcher-panel[hidden] {
  display: none;
}

.app-breadcrumb__switcher-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-5) 0;
}

.app-breadcrumb__switcher-list {
  /* ~4 items at a time (see .app-breadcrumb__switcher-item's own padding/
     line-height below) before scrolling kicks in. */
  max-height: 208px;
  overflow-y: auto;
}

.app-breadcrumb__switcher-item {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: var(--space-2) var(--space-4);
  text-decoration: none;
  transition: background-color var(--transition-fast);
}

.app-breadcrumb__switcher-item:hover {
  background: var(--color-bg);
}

.app-breadcrumb__switcher-item-name {
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--color-text);
}

.app-breadcrumb__switcher-item-id {
  font-size: 12px;
  font-weight: var(--weight-regular);
  color: var(--color-text-muted);
}

.app-breadcrumb__switcher-empty {
  padding: var(--space-4);
  font-size: var(--text-sm);
  font-weight: var(--weight-regular);
  color: var(--color-text-muted);
  text-align: center;
}

.app-breadcrumb__switcher-viewall {
  display: block;
  padding: var(--space-3) var(--space-4);
  border-top: 1px solid var(--color-border);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--color-primary);
  text-align: center;
  text-decoration: none;
}

.app-breadcrumb__switcher-viewall:hover {
  text-decoration: underline;
}


/* ============================================
   BULK ACTION BAR (shared: negative keywords + Meta Spend Monitor)
   ============================================
   Generic fixed-to-viewport-bottom layout, extracted out of
   page-negative-keywords.css's .negkw-bulkbar (2026-07 label system work)
   so Meta Spend Monitor's new bulk bar can reuse the exact same look
   instead of duplicating it -- same pattern as .sherpa-table above (shared
   base class + page-specific extras layered on top in each page's own
   CSS). Both pages' bar elements carry this class alongside their own
   page-prefixed one (e.g. class="negkw-bulkbar bulk-action-bar"); the
   page-prefixed class still owns anything genuinely page-specific
   (Approve/Dismiss/Undo/Apply button variants on negative keywords, for
   instance -- there's nothing to reuse there since Meta's bar only ever
   shows the Label button).

   justify-content is flex-start, not space-between (changed 2026-07-31):
   negative keywords used to rely on space-between across two direct flex
   children (an Apply Approved button plus a sibling actions div) to pin
   one left and one right, but that meant Apply Approved appearing/
   disappearing changed which child space-between treated as "the other
   one," visibly shifting every button's position. Each consuming page now
   puts every action inside a single full-width child div and right-aligns
   just its own Clear Selection element with margin-left: auto instead --
   see .negkw-bulkbar__actions/.negkw-bulkbar__clear in page-negative-
   keywords.css. flex-start vs. space-between is a no-op for Meta Spend
   Monitor's bar, which only ever has that one single child to begin with. */

.bulk-action-bar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 400;
  background: var(--color-surface);
  border-top: 1px solid var(--color-border);
  box-shadow: 0 -4px 16px rgba(10, 31, 68, 0.12);
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: var(--space-4);
  flex-wrap: wrap;
  width: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  padding: var(--space-4) var(--container-padding);
}

/* [hidden] has to be re-declared here: it and .bulk-action-bar are equal
   specificity, and this author rule would otherwise always beat the
   browser's built-in "[hidden] { display: none }" UA rule, permanently
   defeating bar.hidden = true/false in JS regardless of selection state
   -- same class of bug documented throughout this file (see the alert
   badge/dropdown entries above). */
.bulk-action-bar[hidden] {
  display: none;
}

@media (max-width: 600px) {
  .bulk-action-bar {
    flex-direction: column;
    align-items: stretch;
  }
}

/* Shared "Label" button -- identical on both pages (negative keywords'
   bulk bar and Meta Spend Monitor's new one), outline-primary to match
   the existing per-page action buttons' treatment (e.g. .negkw-bulkbar__
   approve) without introducing a third button look. */
.bulk-action-bar__label-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  background: transparent;
  border: 1.5px solid var(--color-primary);
  color: var(--color-primary);
  padding: 8px 18px;
  font-size: 14px;
  font-weight: 600;
  border-radius: 8px;
  cursor: pointer;
  transition: background-color var(--transition-fast);
}

.bulk-action-bar__label-btn:hover {
  background: var(--color-primary-light);
}


/* ============================================
   LABEL PILLS (shared: negative keywords table/cards, Meta Spend Monitor
   table, Advanced Filters label-value picker)
   ============================================
   Rendered via window.PPCSLabelDropdown.pillsHTML() in
   theme/assets/js/label-dropdown.js so every consumer gets byte-identical
   markup. Background is always an inline style (the label's own hex
   color, arbitrary/user-chosen -- there's no fixed set of classes to
   reuse the way .badge's success/warning/danger tokens work), with text
   color also inlined per-pill from a luminance check (see
   contrastTextColor() in label-dropdown.js) rather than living in CSS at
   all. This class only owns shape/spacing/typography. */

.label-pill-group {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  flex-wrap: wrap;
}

.label-pill {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  border-radius: var(--radius-full);
  font-size: 11px;
  font-weight: var(--weight-semibold);
  line-height: 1.4;
  white-space: nowrap;
}

/* Overflow "+N" badge -- deliberately neutral (not an arbitrary label
   color), since it doesn't represent one specific label. */
.label-pill--overflow {
  background: var(--color-bg);
  color: var(--color-text-muted);
  border: 1px solid var(--color-border);
}


/* ============================================
   LABEL DROPDOWN (shared component, theme/assets/js/label-dropdown.js)
   ============================================
   One floating panel (position: fixed, escaping any scrolling ancestor
   the same way the alert bell's dropdown and the negative keywords page's
   header popover both do -- see Key Learnings in CLAUDE.md on
   overflow-x: auto also clipping the vertical axis) reused across every
   open() call, anchored below (or, more often in practice, above -- see
   the position() comment in label-dropdown.js) whichever "Label" button
   triggered it. Two content states swap wholesale via innerHTML: the
   list view (search + checkbox list + Create/Apply) and the create/edit
   form view (color grid + name input + Cancel/Save, plus delete for
   edit). Compact control sizing here is deliberate, matching this
   theme's existing convention of not reusing the larger marketing-form
   .form-input/.form-select styles for compact in-app controls (see e.g.
   .negkw-filter-select/.negkw-filter-value in page-negative-
   keywords.css). */

.label-dropdown {
  position: fixed;
  z-index: 500;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  font-family: var(--font-body);
}

.label-dropdown[hidden] {
  display: none;
}

.label-dropdown__loading,
.label-dropdown__empty {
  padding: var(--space-6) var(--space-4);
  text-align: center;
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

.label-dropdown__search-wrap {
  padding: var(--space-3);
  border-bottom: 1px solid var(--color-border);
  flex-shrink: 0;
}

.label-dropdown__search {
  width: 100%;
  padding: 7px 10px;
  font-size: 13px;
  font-family: var(--font-body);
  border: 1px solid var(--color-border);
  border-radius: 6px;
  background: var(--color-bg);
  color: var(--color-text);
}

.label-dropdown__search:focus {
  outline: none;
  border-color: var(--color-primary);
  background: var(--color-surface);
  box-shadow: 0 0 0 3px rgba(26, 107, 255, 0.12);
}

.label-dropdown__list {
  overflow-y: auto;
  flex: 1;
  min-height: 0;
}

.label-dropdown__item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  cursor: pointer;
  transition: background-color var(--transition-fast);
}

.label-dropdown__item:hover {
  background: var(--color-bg);
}

.label-dropdown__item-checkbox {
  width: 15px;
  height: 15px;
  flex-shrink: 0;
  cursor: pointer;
  accent-color: var(--color-primary);
}

.label-dropdown__item-color {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
}

.label-dropdown__item-name {
  flex: 1;
  font-size: 13px;
  color: var(--color-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Pencil icon: only visible on hover/focus, same reveal-on-hover pattern
   as the alert dropdown's per-row dismiss button (.alerts-row__dismiss
   above), for the same reason -- a small secondary action that shouldn't
   compete visually with the row's primary click target. */
.label-dropdown__item-edit {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  padding: 0;
  background: none;
  border: none;
  border-radius: var(--radius-sm);
  color: var(--color-text-muted);
  opacity: 0;
  cursor: pointer;
  transition: opacity var(--transition-fast), background-color var(--transition-fast), color var(--transition-fast);
}

.label-dropdown__item:hover .label-dropdown__item-edit,
.label-dropdown__item-edit:focus {
  opacity: 1;
}

.label-dropdown__item-edit:hover {
  background: var(--color-primary-light);
  color: var(--color-primary);
}

.label-dropdown__footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-3);
  border-top: 1px solid var(--color-border);
  flex-shrink: 0;
}

.label-dropdown__create-link {
  font-size: 13px;
  font-weight: 600;
  color: var(--color-primary);
}

.label-dropdown__create-link:hover {
  text-decoration: underline;
}

.label-dropdown__apply-btn {
  background: var(--color-primary);
  color: #FFFFFF;
  border: none;
  padding: 7px 16px;
  font-size: 13px;
  font-weight: 600;
  border-radius: 7px;
  cursor: pointer;
  transition: background-color var(--transition-fast);
}

.label-dropdown__apply-btn:hover {
  background: var(--color-primary-hover);
}

/* ---- Create / edit form view ---- */

.label-dropdown__form {
  padding: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.label-dropdown__form-title {
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--color-dark);
}

.label-dropdown__color-grid {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: var(--space-2);
}

.label-dropdown__color-dot {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: none;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: transform var(--transition-fast);
}

.label-dropdown__color-dot:hover {
  transform: scale(1.1);
}

.label-dropdown__color-dot--selected {
  box-shadow: 0 0 0 2px var(--color-surface), 0 0 0 4px var(--color-dark);
}

.label-dropdown__name-input {
  width: 100%;
  padding: 8px 10px;
  font-size: 13px;
  font-family: var(--font-body);
  border: 1px solid var(--color-border);
  border-radius: 6px;
  background: var(--color-bg);
  color: var(--color-text);
}

.label-dropdown__name-input:focus {
  outline: none;
  border-color: var(--color-primary);
  background: var(--color-surface);
  box-shadow: 0 0 0 3px rgba(26, 107, 255, 0.12);
}

.label-dropdown__form-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}

.label-dropdown__form-footer[hidden] {
  display: none;
}

.label-dropdown__form-footer-right {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.label-dropdown__trash-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  padding: 0;
  background: none;
  border: 1.5px solid var(--color-border);
  border-radius: 7px;
  color: var(--color-text-muted);
  cursor: pointer;
  transition: border-color var(--transition-fast), color var(--transition-fast);
}

.label-dropdown__trash-btn:hover {
  border-color: var(--color-danger);
  color: var(--color-danger);
}

.label-dropdown__cancel-btn {
  background: transparent;
  border: 1.5px solid var(--color-border);
  color: var(--color-text-muted);
  padding: 7px 14px;
  font-size: 13px;
  font-weight: 600;
  border-radius: 7px;
  cursor: pointer;
}

.label-dropdown__cancel-btn:hover {
  border-color: #C0C4CC;
  color: var(--color-text);
}

.label-dropdown__save-btn {
  background: var(--color-primary);
  color: #FFFFFF;
  border: none;
  padding: 7px 16px;
  font-size: 13px;
  font-weight: 600;
  border-radius: 7px;
  cursor: pointer;
  transition: background-color var(--transition-fast);
}

.label-dropdown__save-btn:hover {
  background: var(--color-primary-hover);
}

.label-dropdown__delete-confirm {
  background: #FEF2F2;
  border: 1px solid #FECACA;
  border-radius: var(--radius-md);
  padding: var(--space-3);
}

.label-dropdown__delete-confirm p {
  font-size: 12px;
  color: var(--color-text);
  margin-bottom: var(--space-2);
}

.label-dropdown__delete-confirm-actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
}

.label-dropdown__delete-cancel-btn {
  background: transparent;
  border: 1.5px solid var(--color-border);
  color: var(--color-text-muted);
  padding: 6px 12px;
  font-size: 12px;
  font-weight: 600;
  border-radius: 6px;
  cursor: pointer;
}

.label-dropdown__delete-confirm-btn {
  background: var(--color-danger);
  color: #FFFFFF;
  border: none;
  padding: 6px 12px;
  font-size: 12px;
  font-weight: 600;
  border-radius: 6px;
  cursor: pointer;
}

.label-dropdown__delete-confirm-btn:hover {
  background: #B91C1C;
}

@media (max-width: 480px) {
  .label-dropdown {
    width: calc(100vw - 16px) !important;
    left: 8px !important;
  }
}
