/* Shared base styles for the ThingDeck site.
   Referenced by every page — edit once, applies everywhere. */

/* ---------------------------------------------------------------------
   Theme tokens — every color in tailwind-config.js points at one of these
   CSS variables instead of a hardcoded hex, so a single `.dark` class on
   <html> re-themes every existing utility class (bg-surface-*, text-on-*,
   etc.) with no per-element edits needed. Light values live on :root;
   dark overrides live under .dark. See assets/js/theme-toggle.js for how
   the class gets applied/persisted.
   --------------------------------------------------------------------- */
/* ---------------------------------------------------------------------
   Palette — "Control Panel": a cool graphite/steel neutral system (not
   warm paper, not near-black-with-neon) with one accent, Signal Amber,
   standing in for an indicator light. Circuit Green (tertiary/verified)
   is the other semantic light on the panel — kept distinct from the
   accent so "verified" never gets mistaken for "call to action".
   --------------------------------------------------------------------- */
:root {
  --on-tertiary-container: #0e5a38;
  --on-error: #ffffff;
  --on-primary-fixed: #10151c;
  --on-surface-variant: #525b66;
  --on-tertiary: #ffffff;
  --on-error-container: #93000a;
  --outline-variant: #cbd2d9;
  --on-secondary-fixed: #12283a;
  --secondary-container: #e4ecf3;
  --secondary-fixed: #d6e4ef;
  --tertiary-container: #e4f5ec;
  --background: #eef1f4;
  --on-tertiary-fixed-variant: #0e5a38;
  --on-tertiary-fixed: #06301d;
  --on-background: #10151c;
  --on-surface: #10151c;
  --surface-container-highest: #d1d8df;
  --error-container: #ffdad6;
  --surface-container: #e0e5ea;
  --inverse-on-surface: #eef1f4;
  --surface-container-high: #d9dfe5;
  --on-secondary-fixed-variant: #2a4f6e;
  --primary-container: #10151c;
  --error: #ba1a1a;
  --surface: #f5f7f9;
  --surface-tint: #525b66;
  --surface-bright: #ffffff;
  --surface-container-low: #e7ebef;
  --tertiary: #1fa971;
  --primary-fixed: #dde3e9;
  --secondary: #3d6b96;
  --inverse-surface: #232b34;
  --surface-variant: #dce1e6;
  --outline: #6b7480;
  --on-secondary-container: #1b3a54;
  --on-secondary: #ffffff;
  --surface-container-lowest: #ffffff;
  --secondary-fixed-dim: #a9c4d9;
  --tertiary-fixed: #c8ecda;
  --on-primary-fixed-variant: #3a4450;
  --on-primary: #ffffff;
  --tertiary-fixed-dim: #7fcba5;
  --surface-dim: #dce1e6;
  --primary: #10151c;
  --on-primary-container: #a9b2bd;
  --primary-fixed-dim: #c9d3dc;
  --inverse-primary: #c9d3dc;
  --accent: #e8952e;
  /* Amber is a light/mid tone in both themes, so its "on" color is always
     dark ink — unlike the other on-* tokens, this one does not flip
     between light and dark mode. */
  --on-accent: #10151c;
  --verified: #1fa971;

  --field-bg: #ffffff;
  --field-border: #cbd2d9;
}

:root.dark {
  --on-surface-variant: #9aa5b1;
  --outline-variant: #2e3844;
  --background: #10151c;
  --on-background: #edf1f4;
  --on-surface: #edf1f4;
  --surface-container-highest: #2a343f;
  --surface-container: #1a212a;
  --inverse-on-surface: #1a212a;
  --surface-container-high: #212a34;
  --surface: #10151c;
  --surface-tint: #9aa5b1;
  --surface-bright: #2e3844;
  --surface-container-low: #151b22;
  --tertiary: #3dc98d;
  --secondary: #7fa8c9;
  --inverse-surface: #edf1f4;
  --surface-variant: #2a343f;
  --outline: #7c8794;
  --on-secondary-container: #ffffff;
  --on-secondary: #0a1e2e;
  --surface-container-lowest: #0a0d12;
  --surface-dim: #0a0d12;
  --primary: #ffffff;
  --secondary-container: #2a4a63;
  --tertiary-container: #0e3a28;
  --on-tertiary-container: #7ee8b8;
  --on-tertiary: #06301d;
  --error: #ffb4ab;
  --on-error: #690005;
  --error-container: #93000a;
  --on-error-container: #ffdad6;
  --accent: #f5b24c;
  --verified: #3dc98d;

  --field-bg: #151b22;
  --field-border: #2e3844;

  /* primary-container / on-primary-container / *-fixed* tokens are
     intentionally left unchanged — primary-container is the footer's
     background and doubles as a fixed dark-navy band in both themes.
     on-primary-container follows for the same reason (footer body text).
     on-primary also stays fixed white: bg-primary is never actually used
     as an element background anywhere in the site, but text-on-primary IS
     used standalone (index.html's "Grow your business" card, set against
     the fixed-dark primary-container) — flipping on-primary dark here
     made that white text invisible against its own dark card. */
}

body { font-family: 'IBM Plex Sans', sans-serif; background-color: var(--background); color: var(--on-background); transition: background-color .2s, color .2s; }
.material-symbols-outlined { font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24; }
.icon-fill { font-variation-settings: 'FILL' 1, 'wght' 400, 'GRAD' 0, 'opsz' 24; }
.shadow-1 { box-shadow: 0px 4px 12px rgba(15, 23, 42, 0.03); }
.shadow-2 { box-shadow: 0px 8px 24px rgba(15, 23, 42, 0.08); }
:root.dark .shadow-1 { box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.24); }
:root.dark .shadow-2 { box-shadow: 0px 8px 24px rgba(0, 0, 0, 0.36); }

/* ---------------------------------------------------------------------
   Ambient background glow — a fixed, full-page decorative layer sitting
   behind all content (see the .bg-glow markup right after <body> on every
   page). Only `transform` and `opacity` are animated, so every frame is
   GPU-composited and never touches layout or paint on the main thread —
   it doesn't compete with page load, scrolling, or input. The blur filter
   itself is static (applied once, not re-rasterized per frame). Disabled
   entirely under prefers-reduced-motion, and pointer-events: none so it
   can never intercept clicks.
   --------------------------------------------------------------------- */
:root { --glow-opacity: 0.10; --dot-color: rgba(15, 23, 42, 0.14); }
:root.dark { --glow-opacity: 0.16; --dot-color: rgba(255, 255, 255, 0.12); }

/* Dot grid — a single repeating radial-gradient tile, not per-dot elements,
   so it's one cheap paint regardless of how many dots are on screen. Static
   (no animation) to keep this addition effectively free. */
.bg-glow {
  position: fixed; inset: 0; z-index: -1; overflow: hidden; pointer-events: none;
  background-image: radial-gradient(circle, var(--dot-color) 1px, transparent 1px);
  background-size: 24px 24px;
}
/* Quiet variant — flat solid background, no dot texture, softer glow.
   Opt-in per page (add "bg-glow--quiet" alongside "bg-glow") so this can
   be trialled on one page before rolling out everywhere. */
.bg-glow--quiet { background-image: none; }
.bg-glow--quiet span { opacity: calc(var(--glow-opacity) * 0.6); }
.bg-glow span {
  position: absolute;
  border-radius: 50%;
  filter: blur(80px);
  opacity: var(--glow-opacity);
  will-change: transform;
}
.bg-glow span:nth-child(1) {
  width: 440px; height: 440px;
  background: #e8952e;
  top: -120px; left: -100px;
  animation: glow-drift-1 34s ease-in-out infinite alternate;
}
.bg-glow span:nth-child(2) {
  width: 400px; height: 400px;
  background: #1fa971;
  bottom: -140px; right: -100px;
  animation: glow-drift-2 40s ease-in-out infinite alternate;
}
.bg-glow span:nth-child(3) {
  width: 340px; height: 340px;
  background: #3d6b96;
  top: 38%; right: 8%;
  animation: glow-drift-3 27s ease-in-out infinite alternate;
}
@keyframes glow-drift-1 { from { transform: translate3d(0, 0, 0) scale(1); } to { transform: translate3d(60px, 50px, 0) scale(1.15); } }
@keyframes glow-drift-2 { from { transform: translate3d(0, 0, 0) scale(1); } to { transform: translate3d(-50px, -40px, 0) scale(1.1); } }
@keyframes glow-drift-3 { from { transform: translate3d(0, 0, 0) scale(1); } to { transform: translate3d(-40px, 30px, 0) scale(0.92); } }

@media (prefers-reduced-motion: reduce) {
  .bg-glow span { animation: none !important; }
}

/* Provider directory filtering (providers.html) */
.provider-card[hidden] { display: none !important; }

/* Form fields (list-your-business.html)
   !important on background/color/border here because the Tailwind CDN
   "forms" plugin (?plugins=forms in the CDN script tag) injects its own
   input reset (background-color: #fff, etc.) into a dynamically-created
   stylesheet that loads after base.css, so it otherwise wins the cascade
   on <input> elements specifically — <select> isn't affected the same way,
   which is why only inputs showed a stuck white background pre-fix. */
.field-input { width: 100%; padding: 10px 12px; background: var(--field-bg) !important; border: 1px solid var(--field-border) !important; border-radius: 0.5rem; font-family: 'IBM Plex Sans', sans-serif; font-size: 14px; color: var(--on-background) !important; outline: none; transition: all .15s; }
.field-input:focus { border-color: var(--accent) !important; box-shadow: 0 0 0 4px rgba(232,149,46,0.15); }
.field-input::placeholder { color: var(--on-surface-variant); opacity: 0.7; }
.field-label { display: block; font-family: 'IBM Plex Sans', sans-serif; font-size: 13px; font-weight: 600; letter-spacing: 0.02em; color: var(--on-background); margin-bottom: 6px; }
.field-hint { font-size: 12px; color: var(--on-surface-variant); margin-top: 4px; }
.check-chip { display: flex; align-items: center; gap: 8px; padding: 10px 12px; border: 1px solid var(--field-border) !important; border-radius: 0.5rem; cursor: pointer; transition: all .15s; background: var(--field-bg) !important; }
.check-chip:hover { border-color: var(--accent); }
.check-chip input:checked ~ span { color: var(--accent); font-weight: 600; }

/* ---------------------------------------------------------------------
   Scroll reveal — a small opacity/translate transition toggled by
   assets/js/reveal.js via IntersectionObserver. Elements start hidden
   only once JS confirms it can reveal them (see reveal.js's no-JS/no-IO
   fallback), and reduced-motion users see content in place, no motion.
   --------------------------------------------------------------------- */
[data-reveal] { opacity: 0; transform: translateY(16px); transition: opacity .6s ease, transform .6s ease; }
[data-reveal].is-visible { opacity: 1; transform: translateY(0); }
@media (prefers-reduced-motion: reduce) {
  [data-reveal] { opacity: 1; transform: none; transition: none; }
}

/* Brand marquee (index.html "Works with the brands..." strip) — two
   copies of the same track sit side by side and scroll together as one
   continuous loop; pauses on hover/focus so it's readable on demand. */
.marquee-track { display: flex; width: max-content; animation: marquee-scroll 32s linear infinite; }
.marquee-viewport:hover .marquee-track,
.marquee-viewport:focus-within .marquee-track { animation-play-state: paused; }
@keyframes marquee-scroll { from { transform: translateX(0); } to { transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce) {
  .marquee-track { animation: none; }
}
