/* ============================================================================
   SnapToolSuite Design System — THE SINGLE SOURCE OF TRUTH for color/look.
   Linked LAST in each page's <head> so this :root overrides the page's inline
   tokens. Change a value here → every page that links this file updates.
   See SnapToolSuite-Design-System.md. Palette: charcoal / stone / tan-gold / white.
   ============================================================================ */
:root {
  /* core palette */
  --charcoal: #1a1a1a;
  --stone: #e5e5e5;
  --gold: #c6a878;
  --gold-d: #a98c57;
  --white: #ffffff;

  /* mapped onto the tokens the tool pages already use */
  --primary: #c6a878;        /* tan-gold — primary buttons / CTAs */
  --primary-dark: #a98c57;   /* gold hover */
  --on-primary: #1a1a1a;     /* charcoal text on a gold button (contrast) */
  --cta-text: #1a1a1a;
  --cta-btn-hover: #b89a68;
  --accent: #a98c57;         /* tan-gold-dark — highlights, result numbers */
  --danger: #b91c1c;
  --on-danger: #ffffff;

  /* Gold-as-TEXT/LINK token. Gold #c6a878 as a fill is fine, but as TEXT on a
     light bg it reads ~2:1 (fails). Links/credit use --link, which is a DEEPER
     gold on light (≈4.3:1 on white, ≥3:1 on the warm page bg) and the BRIGHT gold
     on dark (where bright gold is readable). Fills/buttons keep --gold/--primary. */
  --link: #8a6a35;           /* deep gold — readable gold text on light */

  --text: #1a1a1a;           /* charcoal */
  --text-h: #1a1a1a;
  --muted: #6e6a62;
  --bg: #f6f5f2;             /* warm off-white */
  --card: #ffffff;
  --border: #e5e5e5;         /* stone */

  --radius: 12px;
  --shadow: 0 2px 4px rgba(26, 26, 26, 0.06);   /* micro-shadow, never heavy */
  --font: 'Inter', 'Satoshi', 'Neue Haas Grotesk', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --mono: ui-monospace, 'JetBrains Mono', 'SF Mono', Menlo, Consolas, monospace;

  /* Pin light so an OS/browser in dark mode can't auto-darken native form fields
     (inputs/selects/scrollbars) → no dark-on-dark text. The [data-theme="dark"]
     block below flips this to dark when the user actually opts into dark. */
  color-scheme: light;
}

/* Gold primary buttons need CHARCOAL text — white on tan-gold fails contrast, and
   many pages hard-code color:#fff. This loads after each page's inline <style>, so
   it wins for the primary `.btn`; more-specific variants (.btn.ghost) keep their own
   text. Covers the factory's common filled-button classes. */
.btn,
.cap-btn,
.estep,
.dl-btn,
button.primary,
.cta-btn {
  color: var(--on-primary);
}
.btn.ghost,
.btn.sub,
.btn.outline {
  color: var(--text);
}

/* Links default to BRAND GOLD — kills the browser-default link blue (#0000EE) on any UNSTYLED
   <a>. The .guide / .related / "service a pool in order" chain links in tools have no class and
   no color rule, so they were rendering default-blue — a blue the de-blue normalizer can NEVER
   catch because it's the ABSENCE of a color, not a hex in any file. Bare `a` is lowest
   specificity (0,0,1), so every classed/scoped link (.backlink, .go, .mm-footer a, .cta a, the
   sidebar items, etc.) keeps its own color. Loaded last → applies site-wide, every page. */
a { color: var(--link); }

/* The shared "Request a tool" CTA banner hard-codes a blue gradient (not a token).
   Re-skin to the charcoal anchor + a gold button. (design.css loads after the page,
   so equal-specificity selectors win — no !important needed.) */
.cta { background: #1a1a1a; }
.cta p { color: #b8b3a8; }
.cta a { background: var(--gold); color: #1a1a1a; }
.cta a:hover { background: #d2b68a; }

/* embed-widget "Copy the code" button: charcoal text on gold (it hard-codes white) */
.embed-steps .estep-copy { color: var(--on-primary); }

/* Homepage sidebar: the active "All tools / Popular / New / category" item hard-codes a
   blue tint (#EEF3FF) background. Re-skin the selected state to a warm gold tint so it
   matches the tan-gold brand instead of blue (translucent → works in light and dark). */
.side-item.on, .side-cat.on { background: rgba(198, 168, 120, 0.18); }

/* Residual blue pills/nudges the page CSS hard-codes (#EFF6FF / #EEF3FF / #BFDBFE) —
   re-skin to the tan-gold palette so nothing reads blue:
   .pchem = pool chem chip, .pro-nudge = upgrade box, .ct = inline tag chip. */
.pchem    { background: rgba(198, 168, 120, 0.16); color: var(--gold-d); }
.ct       { background: rgba(198, 168, 120, 0.16); }
.pro-nudge { background: rgba(198, 168, 120, 0.12); border-color: rgba(169, 140, 87, 0.45); }
/* account "popular/Pro" pill + the Pro page's highlighted plan column (both hard-code blue) */
.tag.pill { background: rgba(198, 168, 120, 0.16); color: var(--gold-d); }
.col-hl,
.compare td.col-hl,
.compare tr:first-child td.col-hl { background: rgba(198, 168, 120, 0.16); }

/* Embedded tools (?embed=1) should show ONLY the tool — hide the full site footer nav
   (Home · All tools · About · …). The small "Powered by" credit stays (Pro strips it
   via _pro.js / the valid embed key). */
body.embed .mm-foot-nav { display: none; }

/* Hub / listing pages (pool-tools, seller-tools, /tools/, etc.) hard-code a blue
   note box (#EFF4FF / #C7D2FE) and a blue card-hover border. Re-skin to the
   tan-gold palette (translucent so it works in light AND dark). */
.note      { background: rgba(198, 168, 120, 0.14); border-color: rgba(169, 140, 87, 0.40); color: var(--text); }
.tool:hover { border-color: var(--gold); }

/* ── GOLD-AS-TEXT FIX (site-wide) ──────────────────────────────────────────
   Gold #c6a878 (--primary) as a FILL is on-brand, but as TEXT on a light bg it
   reads ~2:1 (fails WCAG). Several CLASSED content links/labels hard-code
   color:var(--primary) — most visibly `.backlink` (on EVERY tool page) and the
   `.doc` sheet headings. design.css loads LAST, so these equal/higher-specificity
   rules win without !important. Re-point them to --link, the theme-aware DEEP gold
   (#8a6a35 light ≈4.5:1 on white / #d2b68a bright on dark) so they read in BOTH
   themes. Bare <a> already uses --link (rule above); this catches the classed ones
   that override it. Gold FILLS/buttons (.btn, .preset, chips) are untouched. */
.backlink,
a.backlink,
.go, a.go,
.sts-pitch a,
.related a,
.rel a,
.guide a,
.embed-sec .note a {
  color: var(--link);
}

/* The `.doc` print/preview SHEET stays WHITE in BOTH themes (it's paper). Its
   headings hard-code color:var(--primary) → ~2:1 on white, AND the theme-aware
   --link would go bright on dark and ALSO fail on the white sheet. So pin the doc
   headings to a FIXED deep gold (#8a6a35 ≈4.6:1 on #fff) that is correct on the
   paper regardless of page theme. Covers both the bare and `.s-h`-classed forms. */
.doc h2, .doc h3,
.doc h2.s-h, .doc h3.s-h { color: #8a6a35; }

/* Bold gold inline text (b/strong colored gold on light) reads ~2:1 too. Where a
   tool colors emphasis with --primary, deepen it to --link (theme-aware). Scoped to
   b/strong so it never touches gold FILLS. */
b[style*="--primary"], strong[style*="--primary"] { color: var(--link); }

/* ============================================================================
   DARK MODE — the dark variant of the universal palette. Activated by
   <html data-theme="dark"> (set by _theme.js from ?theme=dark or saved pref).
   Charcoal bg · white text · tan-gold accents/CTAs (per the spec + the image).
   ============================================================================ */
[data-theme="dark"] {
  --primary: #c6a878;        /* tan-gold CTAs (gold pops on dark) */
  --primary-dark: #d2b68a;
  --on-primary: #1a1a1a;     /* charcoal text on the gold button */
  --cta-text: #1a1a1a;
  --cta-btn-hover: #d2b68a;
  --accent: #c6a878;
  --danger: #ef8a8a;
  --on-danger: #1a1a1a;
  --link: #d2b68a;           /* bright gold — readable as link text on dark */

  --text: #ecebe5;           /* near-white body */
  --text-h: #ffffff;         /* white headings */
  --muted: #95918a;
  --bg: #14171d;             /* charcoal (slightly cool) */
  --card: #1e222a;           /* panel a touch above the bg */
  --border: #2d323b;         /* subtle dark divider */
  --shadow: 0 2px 10px rgba(0, 0, 0, 0.45);
  color-scheme: dark;
}
/* the CTA banner reads as a raised panel on dark (it's #1a1a1a in light) */
[data-theme="dark"] .cta { background: #1e222a; }
/* common hard-coded white surfaces → dark card */
[data-theme="dark"] input,
[data-theme="dark"] textarea,
[data-theme="dark"] select { background: var(--card); color: var(--text); }

/* Pool Chemistry Mastery invite — product cross-sell on pool pages.
   Always charcoal + champagne (North Ranch handbook brand) in both themes,
   so it reads as "this is the paid thing" vs the free tool around it. */
.psm-invite { margin: 30px auto; max-width: 760px; border-radius: 14px; overflow: hidden;
  background: #1a1a1a; border: 1px solid var(--gold-d);
  box-shadow: 0 6px 22px rgba(0, 0, 0, 0.20); }
/* 50/50: text fills the left half, the image fills the right half. */
.psm-invite-in { display: flex; gap: 24px; align-items: center; padding: 24px 26px; }
.psm-invite-text { flex: 1 1 0; min-width: 0; }
/* media half = the animated handbook "look inside": 4 CSS pages crossfade on a slow ~18s
   loop — cover -> contents -> quick-dose cheat sheet -> green-water fix -> rests on the
   cover (so the buy button is the frame people land on). Cover serif = Playfair Display
   (injected into pool-page <head> by _pool_cta.py). */
.psm-invite-media { flex: 1 1 0; min-width: 0; max-width: 300px; align-self: center;
  display: flex; flex-direction: column; align-items: center; gap: 12px;
  container-type: inline-size; }
/* ENGINE STANDARD — fixed/narrow display type: the card lives inside .mm, which sets
   overflow-wrap:break-word (inherited). Reset it here so a long word (e.g. "CHEMISTRY")
   never splits mid-character, and size the big cover title in container-query units (cqw)
   so it always SCALES to fit the book width instead of overflowing/wrapping. */
.psm-book { position: relative; width: 100%; aspect-ratio: 1700 / 2200; overflow-wrap: normal; }
.psm-pg { position: absolute; inset: 0; border-radius: 8px; overflow: hidden; opacity: 0;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.35); animation: 18s ease-in-out infinite; }
.psm-c1 { animation-name: psmCover; } .psm-c2 { animation-name: psmCon; }
.psm-c3 { animation-name: psmQ; } .psm-c4 { animation-name: psmG; }
@keyframes psmCover { 0%{opacity:1} 26%{opacity:1} 30%{opacity:0} 84%{opacity:0} 88%{opacity:1} 100%{opacity:1} }
@keyframes psmCon { 0%,26%{opacity:0;transform:translateY(10px) scale(.986)} 30%{opacity:1;transform:none} 46%{opacity:1;transform:none} 50%{opacity:0;transform:translateY(-8px) scale(1.012)} 100%{opacity:0;transform:translateY(-8px) scale(1.012)} }
@keyframes psmQ { 0%,46%{opacity:0;transform:translateY(10px) scale(.986)} 50%{opacity:1;transform:none} 66%{opacity:1;transform:none} 70%{opacity:0;transform:translateY(-8px) scale(1.012)} 100%{opacity:0;transform:translateY(-8px) scale(1.012)} }
@keyframes psmG { 0%,66%{opacity:0;transform:translateY(10px) scale(.986)} 70%{opacity:1;transform:none} 84%{opacity:1;transform:none} 88%{opacity:0;transform:translateY(-8px) scale(1.012)} 100%{opacity:0;transform:translateY(-8px) scale(1.012)} }
.psm-cv { height: 100%; background: #17150f; display: flex; flex-direction: column;
  justify-content: space-between; padding: 7% 6%; text-align: center; border-radius: 8px;
  border: 1px solid rgba(198, 168, 120, 0.22); }
.psm-hr { height: 2px; background: var(--gold); width: 100%; }
.psm-kick { color: var(--gold); font-size: 9px; letter-spacing: 2.5px; font-weight: 700; margin-top: 10%; }
.psm-mid { flex: 1; display: flex; flex-direction: column; justify-content: center; gap: 9px; }
.psm-bt { font-family: 'Playfair Display', Georgia, serif; color: #f5f1e8; font-weight: 800;
  font-size: clamp(20px, 12.5cqw, 36px); line-height: .96; letter-spacing: .5px; word-break: keep-all; }
.psm-dv { width: 46px; height: 2px; background: var(--gold-d); margin: 3px auto; }
.psm-ed { color: #f0ebe0; font-size: 12px; letter-spacing: 5px; font-weight: 600; }
.psm-tg { color: #9c947f; font-size: 10px; letter-spacing: .5px; margin-bottom: 10%; }
.psm-paper { height: 100%; background: #f3ecdd; border-radius: 8px; padding: 8% 7%;
  display: flex; flex-direction: column; text-align: left; }
.psm-pk { color: var(--gold-d); font-size: 9px; letter-spacing: 1.6px; font-weight: 700;
  text-transform: uppercase; margin-bottom: 7px; }
.psm-pt { font-family: 'Playfair Display', Georgia, serif; color: #2b2620; font-weight: 700;
  font-size: clamp(17px, 8cqw, 24px); line-height: 1.08; margin: 0 0 3px; word-break: keep-all; }
.psm-ps { color: #6f6755; font-size: 10.5px; font-style: italic; margin: 0 0 11px; }
.psm-pr { height: 1px; background: rgba(120, 100, 60, 0.4); margin: 0 0 13px; }
.psm-toc, .psm-dose, .psm-steps { list-style: none; margin: 0; padding: 0; }
.psm-toc li { display: flex; align-items: baseline; font-size: 12px; color: #2b2620; margin: 0 0 10px; }
.psm-ld { flex: 1; border-bottom: 1px dotted rgba(120, 100, 60, 0.55); margin: 0 6px; transform: translateY(-3px); }
.psm-no { color: var(--gold-d); font-weight: 700; font-family: 'Playfair Display', Georgia, serif; }
.psm-dose li { display: flex; align-items: center; gap: 8px; font-size: 10.5px; color: #2b2620;
  padding: 6px 0; border-bottom: 1px solid rgba(120, 100, 60, 0.18); }
.psm-gl { flex: 0 0 58px; font-weight: 700; color: var(--gold-d); }
.psm-ch { flex: 1; color: #6f6755; }
.psm-am { font-weight: 700; white-space: nowrap; }
.psm-df { margin-top: auto; border-top: 1px dashed rgba(120, 100, 60, 0.55); padding-top: 8px;
  color: #9a9079; font-size: 9px; letter-spacing: .5px; }
.psm-steps li { display: flex; gap: 9px; align-items: flex-start; font-size: 11px; color: #2b2620;
  margin: 0 0 9px; line-height: 1.35; }
.psm-sn { flex: 0 0 18px; height: 18px; border-radius: 50%; background: var(--gold); color: #1a1a1a;
  font-weight: 700; font-size: 10px; display: flex; align-items: center; justify-content: center;
  font-family: 'Playfair Display', Georgia, serif; }
.psm-dots { display: flex; gap: 8px; align-items: center; }
.psm-dot { height: 6px; width: 6px; border-radius: 99px; background: rgba(198, 168, 120, 0.32);
  animation: 18s ease-in-out infinite; }
.psm-do1 { animation-name: psmDc1; } .psm-do2 { animation-name: psmDc2; }
.psm-do3 { animation-name: psmDc3; } .psm-do4 { animation-name: psmDc4; }
@keyframes psmDc1 { 0%,26%{background:var(--gold);width:20px} 30%,86%{background:rgba(198,168,120,.32);width:6px} 90%,100%{background:var(--gold);width:20px} }
@keyframes psmDc2 { 0%,30%{background:rgba(198,168,120,.32);width:6px} 34%,46%{background:var(--gold);width:20px} 50%,100%{background:rgba(198,168,120,.32);width:6px} }
@keyframes psmDc3 { 0%,50%{background:rgba(198,168,120,.32);width:6px} 54%,66%{background:var(--gold);width:20px} 70%,100%{background:rgba(198,168,120,.32);width:6px} }
@keyframes psmDc4 { 0%,70%{background:rgba(198,168,120,.32);width:6px} 74%,84%{background:var(--gold);width:20px} 88%,100%{background:rgba(198,168,120,.32);width:6px} }
@media (prefers-reduced-motion: reduce) {
  .psm-pg, .psm-dot, .psm-invite-btn { animation: none !important; }
  .psm-c1 { opacity: 1; } .psm-c2, .psm-c3, .psm-c4 { opacity: 0; }
  .psm-do1 { background: var(--gold); width: 20px; }
  .psm-invite-btn { box-shadow: 0 0 0 1.5px rgba(137,207,240,.5), 0 0 14px 2px rgba(137,207,240,.5); } }
@media (max-width: 560px) {
  .psm-invite-in { flex-direction: column; align-items: stretch; gap: 18px; }
  .psm-invite-text { flex: 0 0 auto; }
  .psm-invite-media { flex: 0 0 auto; width: 62%; max-width: 240px; align-self: center; } }
.psm-invite-attrib { display: block; margin: 12px 0 0; color: var(--gold);
  font-size: 0.85rem; font-style: italic; }
.psm-invite strong { display: block; color: #fff; font-size: 1.18rem;
  line-height: 1.25; margin: 0 0 6px; }
.psm-invite .sub { display: block; color: #cfc9bd; font-size: 0.95rem;
  max-width: 48ch; line-height: 1.5; }
.psm-invite-btn { display: inline-block; margin: 16px 0 0; background: var(--gold);
  color: #1a1a1a !important; font-weight: 700; text-decoration: none; font-size: 0.84rem;
  padding: 10px 15px; border-radius: 9px; white-space: nowrap; border: 1px solid var(--gold);
  transition: transform 0.08s ease, background 0.15s ease;
  animation: psmBtnGlow 18s ease-in-out infinite; }
.psm-invite-btn:hover { background: #d8bd8e; transform: translateY(-1px); }
/* The $24 button pulses a BABY-BLUE glow ONLY while the cover/thumbnail is showing — same
   18s timeline as the book (cover is visible 88%->26%) — and goes dark the instant a page
   turns. #89CFF0 (rgb 137,207,240) is a literal hex; it's the ONE intentional blue accent
   (overrides the no-blue brand rule, per Barry) and is safe here because _normalize_colors.py
   only globs *.html, never design.css. Glow stays <=20px so .psm-invite overflow:hidden
   doesn't clip it. */
@keyframes psmBtnGlow {
  0%   { box-shadow: 0 0 0 1.5px rgba(137,207,240,.55), 0 0 14px 2px rgba(137,207,240,.55); }
  9%   { box-shadow: 0 0 0 2px rgba(137,207,240,.9), 0 0 20px 3px rgba(137,207,240,.85); }
  18%  { box-shadow: 0 0 0 1.5px rgba(137,207,240,.55), 0 0 14px 2px rgba(137,207,240,.55); }
  26%  { box-shadow: 0 0 0 1.5px rgba(137,207,240,.55), 0 0 14px 2px rgba(137,207,240,.55); }
  31%  { box-shadow: 0 0 0 0 rgba(137,207,240,0), 0 0 0 0 rgba(137,207,240,0); }
  84%  { box-shadow: 0 0 0 0 rgba(137,207,240,0), 0 0 0 0 rgba(137,207,240,0); }
  88%  { box-shadow: 0 0 0 1.5px rgba(137,207,240,.55), 0 0 14px 2px rgba(137,207,240,.55); }
  95%  { box-shadow: 0 0 0 2px rgba(137,207,240,.9), 0 0 20px 3px rgba(137,207,240,.85); }
  100% { box-shadow: 0 0 0 1.5px rgba(137,207,240,.55), 0 0 14px 2px rgba(137,207,240,.55); }
}
@media (max-width: 560px) {
  .psm-invite-in { padding: 18px 18px; }
  .psm-invite-btn { width: 100%; text-align: center; } }

/* Contextual "get the supplies" affiliate link — sits right under the result card,
   a plain helpful utility link (NOT the gold handbook CTA, which stays the hero). */
.psm-supplies { margin: 14px 2px 4px; font-size: 14px; color: var(--muted); }
.psm-supplies a { color: var(--link); font-weight: 600; text-decoration: none; }
.psm-supplies a:hover { text-decoration: underline; }
.psm-supplies-ad { margin-left: 8px; font-size: 11px; color: var(--muted); opacity: 0.8; }

/* "Get the supplies" recommended-product card (replaces the old bare text link). Sits
   right under the calculator result. Self-removes on ?embed=1 (see _pool_supplies.py). */
.psm-product { position: relative; display: flex; align-items: center; gap: 16px;
  background: var(--card); border: 1px solid var(--gold); border-radius: 12px;
  padding: 16px 18px; margin: 16px 2px; }
/* Integrated header icon (.mm-ico) — category-tinted chip, matches the hub-card chip.
   GLOBAL (not scoped to .mm.premium) so non-premium tools size it too; _premium.css only
   sized the svg under .mm.premium, leaving plain-.mm tools with a full-width oversized SVG. */
.mm-header:has(.mm-ico) { display: flex; align-items: center; gap: 12px; }
.mm-header .mm-head-text { min-width: 0; flex: 1; }
.mm-ico { flex: 0 0 auto; width: 38px; height: 38px; border-radius: 10px; display: inline-flex;
  align-items: center; justify-content: center; color: var(--primary, #c6a878);
  background: color-mix(in srgb, var(--primary, #c6a878) 14%, transparent); }
.mm-ico svg { width: 22px; height: 22px; }

.psm-product-ico { flex: 0 0 auto; width: 52px; height: 52px; border-radius: 10px;
  background: rgba(198, 168, 120, 0.16); color: var(--gold-d);
  display: flex; align-items: center; justify-content: center; }
.psm-product-ico svg { width: 28px; height: 28px; }
.psm-product-body { flex: 1; min-width: 0; }
.psm-product-eyebrow { display: block; font-size: 11px; letter-spacing: 0.07em;
  text-transform: uppercase; color: var(--gold-d); font-weight: 700; }
.psm-product-name { display: block; font-size: 15px; font-weight: 700; color: var(--text); margin: 2px 0; }
.psm-product-note { display: block; font-size: 13px; color: var(--muted); }
.psm-product-btn { flex: 0 0 auto; background: var(--gold); color: #1a1a1a !important;
  font-weight: 700; font-size: 14px; text-decoration: none; padding: 11px 18px;
  border-radius: 9px; white-space: nowrap; }
.psm-product-btn:hover { background: #d8bd8e; }
.psm-product-ad { position: absolute; top: 7px; right: 11px; font-size: 10px;
  letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted); opacity: 0.7; }
@media (max-width: 520px) {
  .psm-product { flex-wrap: wrap; }
  .psm-product-btn { width: 100%; text-align: center; } }

/* "Rather have a pro handle it?" lead capture (rung 3 — hire-it-out). Light champagne-bordered
   card, pairs above the dark handbook card on pool pages. Stores to Supabase tool_lead
   (see _pool_cta.py). On-brand charcoal/champagne — no blue. */
.psm-lead { max-width: 760px; margin: 26px auto 14px; background: var(--card);
  border: 1px solid var(--gold); border-radius: 14px; padding: 20px 24px;
  display: flex; gap: 22px; align-items: center; flex-wrap: wrap; }
.psm-lead-text { flex: 1 1 240px; min-width: 0; }
.psm-lead-text strong { display: block; font-size: 1.06rem; color: var(--text); }
.psm-lead-text span { display: block; font-size: 0.9rem; color: var(--muted); margin-top: 4px; }
.psm-lead-form { flex: 1 1 320px; display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.psm-lead-form input { padding: 11px 12px; border: 1px solid var(--border); border-radius: 9px;
  font: inherit; font-size: 14px; color: var(--text); background: #fff; }
.psm-lead-form input[type="email"] { flex: 1 1 150px; min-width: 0; }
.psm-lead-form input[type="text"] { flex: 0 0 78px; width: 78px; }
.psm-lead-form input:focus { outline: none; border-color: var(--primary);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--primary) 30%, transparent); }
/* hire-a-pro CTA follows the page's category accent (pool = blue); the $24 handbook
   card (.psm-invite-btn) keeps its own North Ranch gold brand and is NOT changed here. */
.psm-lead-form button { flex: 0 0 auto; background: var(--primary); color: #fff; font-weight: 700;
  border: 0; border-radius: 9px; padding: 12px 18px; font: inherit; font-size: 14px;
  cursor: pointer; white-space: nowrap; }
.psm-lead-form button:hover { background: color-mix(in srgb, var(--primary) 88%, #000); }
.psm-lead-form button:disabled { opacity: 0.6; cursor: default; }
.psm-lead-status { flex-basis: 100%; font-size: 13px; color: var(--muted); min-height: 14px; }
.psm-lead-done { margin: 0; font-weight: 600; color: var(--gold-d); }
@media (max-width: 560px) {
  .psm-lead-form input[type="email"] { flex-basis: 100%; }
  .psm-lead-form input[type="text"] { flex: 1 1 100%; width: auto; }
  .psm-lead-form button { width: 100%; text-align: center; } }

/* A13 — "Find a pool pro" affiliate CTA (replaces .psm-lead email capture once the CJ
   offer URL is set in _pool_cta.py). Same charcoal/champagne card as .psm-lead, no blue. */
.psm-findpro { max-width: 760px; margin: 26px auto 14px; background: var(--card);
  border: 1px solid var(--gold); border-radius: 14px; padding: 20px 24px; }
.psm-findpro-in { display: flex; gap: 22px; align-items: center; flex-wrap: wrap; }
.psm-findpro-text { flex: 1 1 240px; min-width: 0; }
.psm-findpro-text strong { display: block; font-size: 1.06rem; color: var(--text); }
.psm-findpro-text span { display: block; font-size: 0.9rem; color: var(--muted); margin-top: 4px; }
.psm-findpro-form { flex: 1 1 280px; display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.psm-findpro-zip { padding: 11px 12px; border: 1px solid var(--border); border-radius: 9px;
  font: inherit; font-size: 14px; color: var(--text); background: #fff; flex: 0 0 90px; width: 90px; }
.psm-findpro-zip:focus { outline: none; border-color: var(--gold);
  box-shadow: 0 0 0 2px rgba(198, 168, 120, 0.3); }
.psm-findpro-form button, .psm-findpro-btn { flex: 0 0 auto; background: var(--gold); color: #1a1a1a;
  font-weight: 700; border: 0; border-radius: 9px; padding: 12px 18px; font: inherit; font-size: 14px;
  cursor: pointer; white-space: nowrap; text-decoration: none; display: inline-block; }
.psm-findpro-form button:hover, .psm-findpro-btn:hover { background: #d8bd8e; }
.psm-findpro-disc { margin: 12px 0 0; font-size: 12px; color: var(--muted); }
.psm-findpro-disc a { color: inherit; text-decoration: underline; }
@media (max-width: 560px) {
  .psm-findpro-zip { flex: 1 1 100%; width: auto; }
  .psm-findpro-form button, .psm-findpro-btn { width: 100%; text-align: center; } }


/* ============================================================================
   STS shared visual-component library (window.STS, _components.js) — ticket A19.
   Result-display primitives: scale/gauge, meter (floor fallback), donut, two-state.
   Token-only; zone colors carry MEANING inside data displays (green = ideal only,
   amber = close, red = off — founder rule). Light page = deeper zone variants;
   [data-theme=dark] = brighter variants. Honors prefers-reduced-motion.
   Components mount into a .sts-viz wrapper (the per-tool placeholder).
   ============================================================================ */
.sts-viz { --z-ideal:#15875f; --z-amber:#b07d1a; --z-red:#c0392b; --z-band:#1a1a1a;
  margin: 0 0 14px; }
[data-theme="dark"] .sts-viz { --z-ideal:#1d9e75; --z-amber:#d8a93f; --z-red:#d6504f; --z-band:#ecebe5; }
body.embed .sts-viz { margin-bottom: 12px; }

/* --- SCALE / GAUGE (generalized pH gauge) --- */
.sts-scale { padding: 4px 4px 0; }
.sts-scale .sts-g-top, .sts-scale .sts-g-bot { position: relative; height: 32px; }
.sts-scale .sts-gbar { position: relative; height: 13px; border-radius: 999px;
  background: var(--z-ideal); }
.sts-scale .sts-gband { position: absolute; top: -3px; bottom: -3px; border: 2px solid var(--z-band);
  border-radius: 5px; opacity: .8; box-sizing: border-box; pointer-events: none; }
.sts-scale .sts-gmark { position: absolute; transform: translateX(-50%); text-align: center; width: 0;
  transition: left .35s cubic-bezier(.4,0,.2,1); }
.sts-scale .sts-gv { font-size: 18px; font-weight: 800; font-variant-numeric: tabular-nums;
  white-space: nowrap; letter-spacing: -.3px; transition: color .2s; }
.sts-scale .sts-gl { font-size: 10px; font-weight: 700; letter-spacing: .5px; color: var(--muted);
  white-space: nowrap; }
.sts-scale .sts-g-top .sts-gmark { bottom: 2px; }
.sts-scale .sts-g-bot .sts-gmark { top: 2px; }
.sts-scale .sts-gcaret { position: absolute; left: 50%; transform: translateX(-50%);
  width: 0; height: 0; border-left: 6px solid transparent; border-right: 6px solid transparent;
  transition: border-color .2s; }
.sts-scale .sts-gcaret.sts-up { bottom: -6px; border-top: 7px solid var(--z-ideal); }
.sts-scale .sts-gcaret.sts-dn { top: -6px; border-bottom: 7px solid var(--z-ideal); }
.sts-scale .sts-gaxis { display: flex; justify-content: space-between; font-size: 10.5px;
  color: var(--muted); margin-top: 6px; }
.sts-scale .sts-gaxis span:nth-child(2) { text-align: center; }

/* --- METER (FLOOR fallback) --- */
.sts-meter .sts-mhead { display: flex; justify-content: space-between; align-items: baseline;
  gap: 8px; margin-bottom: 6px; }
.sts-meter .sts-mlabel { font-size: 12.5px; font-weight: 600; color: var(--muted);
  letter-spacing: .2px; }
.sts-meter .sts-mval { font-size: 18px; font-weight: 800; font-variant-numeric: tabular-nums;
  letter-spacing: -.3px; transition: color .2s; }
.sts-meter .sts-mtrack { position: relative; height: 12px; border-radius: 999px;
  background: var(--border); overflow: visible; }
.sts-meter .sts-mband { position: absolute; top: 0; bottom: 0; background: color-mix(in srgb,var(--z-ideal) 22%,transparent);
  border-radius: 999px; pointer-events: none; }
.sts-meter .sts-mfill { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 999px;
  background: var(--z-ideal); transition: width .4s cubic-bezier(.4,0,.2,1), background .2s; }
.sts-meter .sts-mdot { position: absolute; top: 50%; width: 16px; height: 16px; border-radius: 50%;
  background: var(--card); border: 3px solid var(--z-ideal); transform: translate(-50%,-50%);
  box-shadow: 0 1px 3px rgba(0,0,0,.25); transition: left .4s cubic-bezier(.4,0,.2,1), border-color .2s; }
.sts-meter .sts-maxis { display: flex; justify-content: space-between; font-size: 10.5px;
  color: var(--muted); margin-top: 7px; }

/* --- DONUT --- */
.sts-donut { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.sts-donut-svg { flex: none; }
.sts-donut .sts-donut-cap { font-size: 12px; color: var(--muted); }
.sts-donut .sts-legend { display: flex; flex-direction: column; gap: 5px; }
.sts-donut .sts-leg { display: flex; align-items: center; gap: 7px; font-size: 13px; color: var(--text); }
.sts-donut .sts-leg i { width: 11px; height: 11px; border-radius: 3px; flex: none; }
.sts-donut-seg { transition: stroke-dasharray .5s cubic-bezier(.4,0,.2,1); }

/* --- TWO-STATE --- */
.sts-two { display: flex; align-items: stretch; gap: 10px; }
.sts-two .sts-two-cell { flex: 1; background: var(--bg); border: 1px solid var(--border);
  border-radius: 10px; padding: 10px 12px; text-align: center; }
.sts-two .sts-two-l { font-size: 11px; font-weight: 700; letter-spacing: .4px; text-transform: uppercase;
  color: var(--muted); }
.sts-two .sts-two-v { font-size: 20px; font-weight: 800; font-variant-numeric: tabular-nums;
  margin-top: 2px; }
.sts-two .sts-two-v.good { color: var(--z-ideal); }
.sts-two .sts-two-arrow { display: flex; align-items: center; color: var(--muted); }
.sts-two .sts-two-arrow.good { color: var(--z-ideal); }
.sts-two .sts-two-arrow.bad { color: var(--z-red); }

@media (max-width: 360px) {
  .sts-scale .sts-gv { font-size: 16px; }
  .sts-meter .sts-mval { font-size: 16px; }
}
@media (prefers-reduced-motion: reduce) {
  .sts-scale .sts-gmark, .sts-scale .sts-gv, .sts-scale .sts-gcaret,
  .sts-meter .sts-mfill, .sts-meter .sts-mdot, .sts-meter .sts-mval,
  .sts-donut-seg { transition: none !important; }
}
