/* =========================================================================
   MarvySocials — Design System
   -------------------------------------------------------------------------
   Self-contained stylesheet: brand tokens, base reset, typography, and
   reusable component classes. It is loaded AFTER tailwind.css in the layouts
   and renders the app correctly even when the Tailwind build has not run
   (tailwind.css is git-ignored). Component classes (.btn, .card, .input, ...)
   are the stable API for PHP views; the inline utility classes used across
   the codebase are covered by the compiled Tailwind build in production.
   ========================================================================= */

:root {
  /* Space scale */
  --ws-announce-h: 2.75rem;
  --ws-announce-duration: 72s;
  --space-1:4px; --space-2:8px; --space-3:12px; --space-4:16px;
  --space-5:24px; --space-6:32px; --space-7:48px; --space-8:64px;
  /* Radius scale */
  --radius-sm:8px; --radius-md:12px; --radius-lg:18px; --radius-xl:24px;
  /* Container */
  --container:1200px;
  --container-max:var(--container);
  /* Brand — indigo (mirrors tailwind.config.js -> colors.brand) */
  --brand-50:#eef2ff; --brand-100:#e0e7ff; --brand-200:#c7d2fe; --brand-300:#a5b4fc;
  --brand-400:#818cf8; --brand-500:#6366f1; --brand-600:#4f46e5; --brand-700:#4338ca;
  --brand-800:#3730a3; --brand-900:#312e81; --brand-950:#1e1b4b;
  /* Accent — fuchsia */
  --accent-50:#fdf4ff; --accent-100:#fae8ff; --accent-200:#f5d0fe; --accent-300:#f0abfc;
  --accent-400:#e879f9; --accent-500:#d946ef; --accent-600:#c026d3; --accent-700:#a21caf;
  /* Semantic */
  --success-50:#ecfdf5; --success-500:#10b981; --success-600:#059669; --success-700:#047857;
  --warning-50:#fffbeb; --warning-500:#f59e0b; --warning-600:#d97706; --warning-700:#b45309;
  --danger-50:#fef2f2;  --danger-500:#ef4444;  --danger-600:#dc2626;  --danger-700:#b91c1c;
  --info-50:#eff6ff;    --info-500:#3b82f6;    --info-600:#2563eb;
  /* Neutrals (slate) — fixed light scale used directly by components */
  --slate-50:#f8fafc; --slate-100:#f1f5f9; --slate-200:#e2e8f0; --slate-300:#cbd5e1;
  --slate-400:#94a3b8; --slate-500:#64748b; --slate-600:#475569; --slate-700:#334155;
  --slate-800:#1e293b; --slate-900:#0f172a; --slate-950:#020617;
  /* Themeable slate RGB triplets + surface, consumed by the Tailwind build
     (tailwind.config.js maps slate/surface to these). Flipped by `.dark`. */
  --ws-slate-50:248 250 252; --ws-slate-100:241 245 249; --ws-slate-200:226 232 240;
  --ws-slate-300:203 213 225; --ws-slate-400:148 163 184; --ws-slate-500:100 116 139;
  --ws-slate-600:71 85 105; --ws-slate-700:51 65 85; --ws-slate-800:30 41 59;
  --ws-slate-900:15 23 42; --ws-slate-950:2 6 23;
  --ws-surface:255 255 255;
  --surface-glass:rgba(255,255,255,.92);
  /* Surface & text */
  --color-bg:#ffffff; --color-surface:#ffffff; --color-surface-2:var(--slate-50);
  --color-text:var(--slate-900); --color-text-muted:var(--slate-500);
  --color-border:var(--slate-200);
  --text-primary:var(--slate-900); --text-secondary:var(--slate-600); --text-muted:var(--slate-500);
  --surface:#ffffff; --surface-muted:var(--slate-50);
  --border:var(--slate-200);
  --primary:var(--brand-600); --primary-hover:var(--brand-700);
  /* Typography */
  --font-sans:Inter,ui-sans-serif,system-ui,-apple-system,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;
  --font-display:Fraunces,Georgia,Cambria,'Times New Roman',serif;
  --font-mono:'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  /* Radius / shadow */
  --radius:0.75rem; --radius-lg:1rem; --radius-xl:1.5rem;
  --shadow-card:0 1px 2px rgba(16,24,40,.05),0 1px 3px rgba(16,24,40,.08);
  --shadow-card-hover:0 10px 30px -10px rgba(79,70,229,.35);
  --shadow-glow:0 0 0 4px rgba(99,102,241,.15);
}

.theme-dark {
  --color-bg:var(--slate-950); --color-surface:#0f172a; --color-surface-2:#1e293b;
  --color-text:#e2e8f0; --color-text-muted:#94a3b8; --color-border:#1e293b;
}

/* Dark theme — the single class that re-themes every component (via the
   semantic variables above) and every Tailwind slate/surface utility (via the
   --ws-* triplets). Applied to <html> by the theme init script. */
.dark,
.theme-dark {
  /* Semantic surfaces/text (design-system components) */
  --color-bg:#0b1020; --color-surface:#0f172a; --color-surface-2:#1e293b;
  --color-text:#e2e8f0; --color-text-muted:#94a3b8; --color-border:#1e293b;
  --text-primary:#f8fafc; --text-secondary:#cbd5e1; --text-muted:#94a3b8;
  --surface:#0f172a; --surface-muted:#1e293b; --border:#1e293b;
  --primary:var(--brand-500); --primary-hover:var(--brand-600);

  /* Themeable slate scale (Tailwind utilities): light -> dark surfaces,
     dark -> light text */
  --ws-slate-50:11 18 32; --ws-slate-100:16 24 39; --ws-slate-200:30 41 59;
  --ws-slate-300:51 65 85; --ws-slate-400:100 116 139; --ws-slate-500:148 163 184;
  --ws-slate-600:203 213 225; --ws-slate-700:226 232 240; --ws-slate-800:241 245 249;
  --ws-slate-900:248 250 252; --ws-slate-950:255 255 255;
  --ws-surface:15 23 42;
  --surface-glass:rgba(15,23,42,.92);
}

/* ------------------------------- Reset/base ------------------------------ */
*, *::before, *::after { box-sizing:border-box; }
html { -webkit-text-size-adjust:100%; scroll-behavior:smooth; }
body {
  margin:0; font-family:var(--font-sans); color:var(--color-text);
  background:var(--color-bg); line-height:1.6; -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}
h1,h2,h3,h4,h5,h6 { font-family:var(--font-display); font-weight:600; line-height:1.15; margin:0 0 .5em; letter-spacing:-.01em; }
h1 { font-size:clamp(2rem,5vw,3.25rem); }
h2 { font-size:clamp(1.5rem,3.5vw,2.25rem); }
h3 { font-size:1.25rem; }
h4 { font-size:1.05rem; }
p { margin:0 0 1rem; }
body { font-size:1rem; line-height:1.6; }
.small, .text-small, .muted-text { font-size:.875rem; }
.caption { font-size:.75rem; letter-spacing:.04em; text-transform:uppercase; color:var(--text-muted); font-weight:600; }
.lede { font-size:1.125rem; color:var(--text-secondary); max-width:46rem; }
a { color:var(--brand-600); text-decoration:none; }
a:hover { text-decoration:underline; }
img, svg { max-width:100%; display:block; }
button { font-family:inherit; cursor:pointer; }
:focus-visible { outline:2px solid var(--brand-500); outline-offset:2px; border-radius:4px; }
::selection { background:var(--brand-200); color:var(--brand-900); }

/* ------------------------------- Layout ---------------------------------- */
.container {
  width:min(100% - 2rem, var(--container-max));
  margin-inline:auto;
  padding-inline:0;
}
.container-pad { padding-inline:1rem; }
.stack > * + * { margin-top:1rem; }
.row { display:flex; gap:.75rem; align-items:center; flex-wrap:wrap; }
.grid { display:grid; gap:1rem; }
.grid-2 { grid-template-columns:repeat(auto-fit,minmax(280px,1fr)); }
.grid-3 { grid-template-columns:repeat(auto-fit,minmax(260px,1fr)); }
.grid-4 { grid-template-columns:repeat(auto-fit,minmax(220px,1fr)); }
.ws-main { min-height:60vh; }
/* Keep the top of <main> clear of the sticky nav when the skip link (or a
   #main URL) scrolls to it. */
.ws-main:focus-visible{outline:none}
#main{scroll-margin-top:6rem}

/* Reusable section patterns */
.ws-hero{background:radial-gradient(900px 280px at 12% -10%,var(--brand-100),transparent 60%),radial-gradient(700px 240px at 92% 0,var(--accent-100,#fae8ff),transparent 55%)}
.ws-feature-section,.ws-testimonial-section,.ws-stats-section,.ws-contact-section{padding:var(--space-7) 0}
.ws-feature-grid,.ws-testimonial-grid,.ws-stats-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:var(--space-4)}
.ws-service-grid,.ws-pricing-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:var(--space-4);align-items:stretch}
.ws-service-card,.ws-pricing-card,.ws-testimonial-card,.ws-stats-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-lg);box-shadow:var(--shadow-card);padding:var(--space-5);height:100%}
.ws-faq-section{padding:var(--space-7) 0}
.ws-cta{padding:var(--space-7) 0}
.ws-section-title{font-family:var(--font-display);font-size:clamp(1.4rem,3vw,2rem)}
.ws-section-lead{color:var(--text-muted);max-width:46rem}

/* ------------------------------- Buttons --------------------------------- */
.btn {
  display:inline-flex; align-items:center; justify-content:center; gap:.5rem;
  padding:.625rem 1.1rem; font-size:.925rem; font-weight:600; line-height:1;
  border-radius:var(--radius); border:1px solid transparent;
  transition:background-color .15s,border-color .15s,box-shadow .15s,transform .05s;
  text-decoration:none; white-space:nowrap;
}
.btn:active { transform:translateY(1px); }
.btn-primary { background:var(--brand-600); color:#fff; }
.btn-primary:hover { background:var(--brand-700); text-decoration:none; }
.btn-secondary { background:var(--color-surface); color:var(--color-text); border-color:var(--color-border); }
.btn-secondary:hover { background:var(--surface-muted); text-decoration:none; }
/* Ghost label is the semantic text token, not a fixed slate: on a dark
   surface --slate-700 rendered the (inactive) shop filter tabs and other
   ghost buttons dark-on-dark. --text-secondary flips with the theme. */
.btn-ghost { background:transparent; color:var(--text-secondary); }
.btn-ghost:hover { background:var(--surface-muted); text-decoration:none; }
.btn-danger { background:var(--danger-600); color:#fff; }
.btn-danger:hover { background:var(--danger-700); text-decoration:none; }
.btn-success { background:var(--success-600); color:#fff; }
.btn-success:hover { background:var(--success-700); text-decoration:none; }
.btn-lg { padding:.85rem 1.5rem; font-size:1rem; border-radius:var(--radius-lg); }
.btn-sm { padding:.4rem .75rem; font-size:.8125rem; }
.btn-block { width:100%; }
.btn[disabled], .btn.is-disabled { opacity:.55; pointer-events:none; }

/* ------------------------------- Cards ----------------------------------- */
.card {
  background:var(--color-surface); border:1px solid var(--color-border);
  border-radius:var(--radius-lg); box-shadow:var(--shadow-card);
  padding:1.5rem; transition:box-shadow .2s, transform .2s;
}
.card-hover:hover { box-shadow:var(--shadow-card-hover); transform:translateY(-2px); }
.card-title { font-family:var(--font-display); font-size:1.15rem; margin:0 0 .5rem; }
.card-meta { font-size:.85rem; color:var(--color-text-muted); }

/* ------------------------------- Search --------------------------------- */
.ws-searchwrap{position:relative;flex:1;display:flex;align-items:center}
.ws-searchwrap svg{position:absolute;left:.75rem;color:var(--slate-400)}
.ws-searchwrap .input{padding-left:2.5rem}
@media(max-width:560px){.ws-searchwrap{width:100%}}

/* ------------------------------- Forms ----------------------------------- */
.label { display:block; font-size:.875rem; font-weight:500; color:var(--text-secondary); margin-bottom:.375rem; }
.input, .select, .textarea {
  width:100%; padding:.6rem .8rem; font-size:.95rem; color:var(--color-text);
  background:var(--color-surface); border:1px solid var(--color-border); border-radius:.625rem;
  transition:border-color .15s,box-shadow .15s; font-family:inherit;
}
.input:focus, .select:focus, .textarea:focus {
  outline:none; border-color:var(--brand-500); box-shadow:var(--shadow-glow);
}
.input::placeholder { color:var(--slate-400); }
.textarea { min-height:120px; resize:vertical; }
.field { margin-bottom:1rem; }
.hint { font-size:.8rem; color:var(--color-text-muted); margin-top:.25rem; }
.form-error { color:var(--danger-600); font-size:.85rem; margin-top:.25rem; }

.checkbox { display:inline-flex; gap:.5rem; align-items:flex-start; font-size:.9rem; }
.checkbox input { margin-top:.2rem; }

/* ------------------------------- Badges ---------------------------------- */
.badge {
  display:inline-flex; align-items:center; gap:.35rem; padding:.2rem .6rem;
  font-size:.72rem; font-weight:600; letter-spacing:.02em; text-transform:uppercase;
  border-radius:9999px; border:1px solid transparent; line-height:1.4;
}
.badge-default { background:var(--surface-muted); color:var(--text-secondary); }
.badge-brand   { background:var(--brand-50);  color:var(--brand-700);  border-color:var(--brand-100); }
.badge-success { background:var(--success-50); color:var(--success-700); }
.badge-warning { background:var(--warning-50); color:var(--warning-700); }
.badge-danger  { background:var(--danger-50);  color:var(--danger-700); }
.badge-info    { background:var(--info-50);    color:var(--info-600); }
.badge-dot::before { content:""; width:.5rem; height:.5rem; border-radius:50%; background:currentColor; }

/* ------------------------------- Alerts ---------------------------------- */
.alert { padding:.85rem 1rem; border-radius:var(--radius); border:1px solid; font-size:.9rem; margin-bottom:1rem; }
.alert-success { background:var(--success-50); border-color:#a7f3d0; color:var(--success-700); }
.alert-warning { background:var(--warning-50); border-color:#fde68a; color:var(--warning-700); }
.alert-danger  { background:var(--danger-50);  border-color:#fecaca; color:var(--danger-700); }
.alert-info    { background:var(--info-50);    border-color:#bfdbfe; color:#1e40af; }

/* ------------------------------- Tables ---------------------------------- */
.table { width:100%; border-collapse:collapse; font-size:.9rem; }
.table th, .table td { padding:.75rem 1rem; text-align:left; border-bottom:1px solid var(--color-border); }
.table th { font-weight:600; color:var(--text-secondary); background:var(--surface-muted); }
.table tbody tr:hover { background:var(--surface-muted); }

/* ------------------------------- Navigation ------------------------------ */
.nav { display:flex; gap:.25rem; align-items:center; }
.nav-link { padding:.5rem .85rem; border-radius:.6rem; color:var(--text-secondary); font-size:.9rem; font-weight:500; }
.nav-link:hover { background:var(--surface-muted); color:var(--color-text); text-decoration:none; }
.nav-link.is-active { background:var(--brand-50); color:var(--brand-700); }

.sidebar {
  width:16rem; flex-shrink:0; border-right:1px solid var(--color-border);
  background:var(--color-surface); padding:1rem .75rem;
}
.sidebar .nav { flex-direction:column; align-items:stretch; }
.sidebar .nav-link { width:100%; }
.ws-nav-group{margin:0 0 .85rem}
.ws-nav-group-label{display:block;padding:.4rem .75rem .15rem;font-size:.68rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--slate-400)}
.ws-service-table{min-width:640px}
@media(max-width:700px){
  .ws-service-table th:nth-child(6),.ws-service-table td:nth-child(6){display:none}
}

/* ------------------------------- Utility --------------------------------- */
.muted { color:var(--color-text-muted); }
.text-center { text-align:center; }
.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}
.mb-0{margin-bottom:0}
.flex{display:flex}.items-center{align-items:center}.justify-between{justify-content:space-between}
.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}
.rounded{border-radius:var(--radius)}
.hidden{display:none}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}

.gradient-text {
  background:linear-gradient(90deg,var(--brand-600),var(--accent-600));
  -webkit-background-clip:text; background-clip:text; color:transparent;
}
.animate-fade-in { animation:ws-fade .25s ease-out; }
.animate-slide-up { animation:ws-slide-up .3s ease-out; }
@keyframes ws-fade { from{opacity:0} to{opacity:1} }
@keyframes ws-slide-up { from{opacity:0;transform:translateY(8px)} to{opacity:1;transform:translateY(0)} }

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

/* Announcements — static strip, black text on white, every page.
   The marquee was removed at the operator's request ("stop moving"):
   messages render in place, stacked when there is more than one, and
   the strip's real height is published to :root (--ws-announce-h) by a
   tiny inline script so the sticky offsets below it stay correct. */
.ws-announce{
  background:#fff;color:#000;border-bottom:1px solid #e5e7eb;
  min-height:var(--ws-announce-h);
  position:sticky;top:0;z-index:80;
  display:flex;align-items:center;overflow:hidden;
  padding:.4rem 1rem;
}
.dark .ws-announce,.theme-dark .ws-announce{background:#fff;color:#000;border-bottom-color:#e5e7eb}
.ws-announce-viewport{flex:1;height:100%;overflow:hidden;min-width:0;
  display:flex;align-items:center;justify-content:center}
.ws-announce-stack{display:flex;flex-direction:column;align-items:center;gap:.15rem;min-width:0}
/* Scrolling mode (speed > 0, more than one message): the items are laid out
   in a track that is duplicated once and marched left by 50% — one exact
   loop, no jump at the seam. The duration is the operator's
   announcement_speed_seconds, published as --ws-announce-speed on the
   container. Hover and keyboard focus pause it so a moving link can be
   clicked and read; reduced-motion users keep the static, centred layout. */
.ws-announce-track{display:flex;align-items:center;width:max-content;
  animation:ws-announce-marquee var(--ws-announce-speed,40s) linear infinite}
.ws-announce-track .ws-announce-item{margin-right:3rem}
/* A single scrolling message: each copy takes the full viewport width so the
   50% march is seamless even when the text is shorter than the strip. Long
   text is unaffected — the item simply grows past the minimum. */
.ws-announce.is-single .ws-announce-track .ws-announce-item{min-width:100vw}
.ws-announce-viewport:hover .ws-announce-track,
.ws-announce-viewport:focus-within .ws-announce-track{animation-play-state:paused}
@keyframes ws-announce-marquee{from{transform:translateX(0)}to{transform:translateX(-50%)}}
/* `color:inherit`, not a fixed colour: the strip's text colour is an operator
   setting applied inline on .ws-announce, and a hard-coded #000 here meant a
   white-on-navy banner rendered its messages in black — the setting appeared
   to do nothing. Each message keeps its own line; a single message centres
   exactly as the old static mode did. */
.ws-announce-item{
  display:flex;align-items:center;justify-content:center;
  max-width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  font-size:.85rem;font-weight:500;color:inherit;line-height:1.4;
}
.ws-announce-item::after{content:none}
.ws-sticky-below-announce{top:var(--ws-announce-h)}
@media (prefers-reduced-motion: reduce){
  .ws-announce-track{animation:none !important}
}
.ws-sev-warning,.ws-sev-critical,.ws-sev-success,.ws-sev-info{background:transparent;color:#000}

/* ------------------------------- Spacing scale -------------------------- */
.ws-space-1{margin:.25rem}.ws-space-2{margin:.5rem}.ws-space-3{margin:.75rem}
.ws-space-4{margin:1rem}.ws-space-6{margin:1.5rem}.ws-space-8{margin:2rem}
.ws-section{padding:4.5rem 0}
.ws-section-sm{padding:3rem 0}
.ws-page-hero{padding:3.5rem 0 2.5rem;background:
  radial-gradient(900px 280px at 12% -10%,var(--brand-100),transparent 60%),
  radial-gradient(700px 240px at 92% 0,var(--accent-100,#fae8ff),transparent 55%)}
.ws-page-hero h1{margin-bottom:.4rem}
/* FAQ intro: kicker, heading, lede and the search box are one centred column.
   It used to sit in a `.ws-hero-split` grid with nothing in the second cell,
   so the whole block hugged the left edge with half the page empty beside it
   (and the grid's wrappers were never closed). */
.ws-faq-hero{max-width:46rem;margin-inline:auto;text-align:center}
.ws-faq-hero .ws-lede{margin-inline:auto}
.ws-faq-hero .ws-searchwrap{position:relative;max-width:28rem;margin-inline:auto}
/* Text colour is the semantic token, not a fixed slate: the fixed light scale
   does not flip in dark mode, so --slate-600 here rendered dark-on-dark on the
   contact / services / shop write-ups. --text-secondary flips with the theme. */
.ws-lede{font-size:1.125rem;color:var(--text-secondary);max-width:40rem}
/* Kicker uses the themeable --primary, not the fixed --brand-700: the hero
   eyebrows ("Support", "Services", "Shop") sat dark-indigo on a dark hero in
   dark mode. --primary flips (brand-600 light, brand-500 dark). */
.ws-kicker{display:inline-block;font-size:.75rem;font-weight:700;letter-spacing:.12em;
  text-transform:uppercase;color:var(--primary);margin-bottom:.75rem}

/* ------------------------------- Public nav ----------------------------- */
/* Skip link: visually hidden until keyboard focus, but always present in the
   DOM as the first focusable element. It must never hide or clip the main
   content — only itself. Fixed positioning keeps it in the viewport when the
   user tabs while scrolled down; transform (not top/left) avoids layout shifts
   and stays off the screen-reader/gfx fast path. */
.ws-skip{position:fixed;top:1rem;left:1rem;z-index:9999;background:var(--brand-700);color:#fff;
  padding:.5rem .9rem;border-radius:.5rem;text-decoration:none;
  transform:translateY(-200%);transition:transform .2s ease}
.ws-skip:focus,.ws-skip:focus-visible{transform:translateY(0);outline:2px solid #fff;outline-offset:2px}
.ws-public-nav{border-bottom:1px solid var(--color-border);background:var(--surface-glass);
  backdrop-filter:saturate(140%) blur(10px);position:sticky;z-index:50}
.ws-public-nav-inner{display:flex;align-items:center;justify-content:space-between;gap:1rem;
  min-height:4rem;width:min(100% - 2rem,var(--container-max));margin:0 auto;padding:.65rem 0}
.ws-brand{display:inline-flex;align-items:center;gap:.65rem;color:var(--slate-900);font-weight:700;
  letter-spacing:-.02em;text-decoration:none}
.ws-brand:hover{text-decoration:none;color:var(--brand-700)}
/* One sizing contract for every brand mark. `partials/brand_logo` passes the
   height it wants as `--ws-logo-h` (inline), so the rendered height always
   equals the requested height — a `max-height` cap used to shrink the footer
   mark from 40px to 36px, and an operator-uploaded wordmark with small
   intrinsic pixels rendered smaller still. `width:auto` keeps the ratio. */
.ws-logo,.ws-logo-lg,.ws-logo-sm{display:block;width:auto;max-height:none;
  height:var(--ws-logo-h,2.25rem)}
.ws-logo-lg{--ws-logo-h:2.75rem}
.ws-logo-sm{--ws-logo-h:1.75rem}
/* The footer wordmark is the sign-off and is the same size on every page. */
.ws-footer-logo{--ws-logo-h:44px}
@media(max-width:520px){.ws-footer-logo{height:38px}}
.ws-brand-mark{width:2rem;height:2rem;border-radius:.7rem;overflow:hidden;flex-shrink:0}
.ws-brand-mark img{width:100%;height:100%;object-fit:cover}
.ws-visual{display:block;width:100%;height:auto;border-radius:var(--radius-xl);object-fit:cover;
  background:var(--slate-100)}
.ws-visual-card{width:100%;height:160px;object-fit:cover;border-radius:var(--radius) var(--radius) 0 0;
  margin:-1.5rem -1.5rem 1rem;max-width:none}
.ws-hero-split{display:grid;grid-template-columns:1fr 1.05fr;gap:3rem;align-items:center}
.ws-hero-media{position:relative}
.ws-hero-media img{width:100%;height:clamp(240px,38vw,460px);object-fit:cover;border-radius:1.5rem;
  box-shadow:0 24px 60px -28px rgba(49,46,129,.55)}
.ws-hero-media::after{content:"";position:absolute;inset:auto -12% -12% auto;width:42%;height:42%;
  background:radial-gradient(circle,rgba(192,38,211,.28),transparent 70%);pointer-events:none}
.ws-page-hero.has-media{padding-bottom:0}
.ws-auth-shell{display:grid;grid-template-columns:1.05fr .95fr;min-height:calc(100vh - 3rem)}
.ws-auth-visual{position:relative;overflow:hidden;background:#0b1020;color:#e2e8f0;padding:2.5rem}
.ws-auth-visual img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:.72}
.ws-auth-visual-inner{position:relative;z-index:1;max-width:28rem}
.ws-auth-visual h2{color:#fff}
.ws-plan-icon{width:48px;height:48px;border-radius:14px;object-fit:cover}
.ws-avatar{width:40px;height:40px;border-radius:50%;object-fit:cover;background:var(--brand-100)}
.ws-avatar-lg{width:64px;height:64px}
@media(max-width:880px){
  .ws-hero-split,.ws-auth-shell{grid-template-columns:1fr}
  .ws-auth-visual{min-height:220px}
}
.ws-nav-links{display:flex;align-items:center;gap:.15rem}
.ws-nav-links a{padding:.45rem .75rem;border-radius:.6rem;color:var(--text-secondary);font-size:.9rem;font-weight:500}
.ws-nav-links a:hover,.ws-nav-links a.is-active{background:var(--surface-muted);color:var(--color-text);text-decoration:none}
.ws-nav-actions{display:flex;align-items:center;gap:.5rem}
.ws-nav-toggle{display:none;background:var(--color-surface);border:1px solid var(--color-border);border-radius:.7rem;
  padding:.45rem .7rem;font-weight:600;min-height:40px}
.ws-nav-panel{display:none}
@media(max-width:860px){
  .ws-nav-links,.ws-nav-actions .ws-nav-desktop{display:none}
  .ws-nav-toggle{display:inline-flex;align-items:center}
  .ws-nav-panel{display:none;position:absolute;left:0;right:0;top:100%;background:var(--color-surface);
    border-bottom:1px solid var(--color-border);padding:1rem;box-shadow:var(--shadow-card)}
  .ws-nav-panel.is-open{display:block}
  .ws-nav-panel a,.ws-nav-panel button{display:block;width:100%;text-align:left;padding:.75rem .5rem;
    border-radius:.5rem;min-height:44px}
}

/* ------------------------------- Footer --------------------------------- */
.ws-footer{border-top:1px solid var(--color-border);background:var(--surface-muted);padding:3.5rem 0 2rem;margin-top:2rem}
.ws-footer-grid{display:grid;grid-template-columns:1.6fr repeat(4,1fr);gap:2rem}
.ws-footer h2{font-family:var(--font-sans);font-size:.8rem;letter-spacing:.08em;text-transform:uppercase;
  color:var(--text-muted);margin:0 0 .85rem}
.ws-footer ul{list-style:none;margin:0;padding:0}
.ws-footer li{margin:.4rem 0}
.ws-footer a{color:var(--text-secondary)}
.ws-footer-meta{margin-top:2.5rem;padding-top:1.25rem;border-top:1px solid var(--slate-200);
  display:flex;justify-content:space-between;gap:1rem;flex-wrap:wrap;color:var(--text-muted);font-size:.85rem}
.ws-footer-links{display:flex;gap:1rem;flex-wrap:wrap}
@media(max-width:1000px){.ws-footer-grid{grid-template-columns:1fr 1fr}.ws-footer{padding:2.5rem 0 5.5rem}}
@media(max-width:520px){.ws-footer-grid{grid-template-columns:1fr}}

/* ------------------------------- Legal / prose -------------------------- */
.ws-prose{max-width:46rem;line-height:1.75;color:var(--slate-700)}
.ws-prose h2{font-size:1.45rem;margin:2.25rem 0 .75rem;scroll-margin-top:6rem}
.ws-prose h3{font-size:1.1rem;margin:1.5rem 0 .5rem;scroll-margin-top:6rem}
.ws-prose ul,.ws-prose ol{padding-left:1.25rem;margin:.75rem 0}
.ws-prose li{margin:.35rem 0}
.ws-prose p{margin:.75rem 0}
.ws-prose code{background:var(--slate-100);padding:.1rem .35rem;border-radius:.3rem;font-size:.9em}
.ws-prose pre{background:var(--slate-900);color:#e2e8f0;padding:1rem;border-radius:var(--radius-md);overflow:auto}
.ws-prose pre code{background:transparent;padding:0}
.ws-prose img{border-radius:var(--radius-lg);margin:1.5rem 0}
.ws-prose a{text-decoration:underline;text-underline-offset:2px}
.ws-toc{position:sticky;top:6rem}
.ws-toc ol{list-style:none;padding:0;margin:0}
.ws-toc a{display:block;padding:.35rem 0;color:var(--text-secondary);font-size:.9rem}
.ws-legal-grid{display:grid;grid-template-columns:220px 1fr;gap:2.5rem;align-items:start}
@media(max-width:800px){.ws-legal-grid{grid-template-columns:1fr}.ws-toc{position:static}}
/* The callout panel keeps its fixed pale-indigo background in BOTH themes —
   the dark theme re-themes the text variables, not --brand-50 — so the text
   must be pinned black for both: left to inherit, it tracked the theme and
   turned near-white on the pale panel in dark mode (the security-practices
   write-up on /services became unreadable). Black is readable on the pale
   panel in light and dark alike, which is exactly how the section is meant
   to read. */
.ws-callout{border-left:3px solid var(--brand-500);background:var(--brand-50);color:#000;padding:1rem 1.15rem;border-radius:0 var(--radius) var(--radius) 0}

/* ------------------------------- Extra form controls -------------------- */
.switch{position:relative;display:inline-flex;align-items:center;gap:.65rem;cursor:pointer}
.switch input{position:absolute;opacity:0;width:1px;height:1px}
.switch-ui{width:2.5rem;height:1.4rem;background:var(--slate-300);border-radius:999px;position:relative;transition:.15s}
.switch-ui::after{content:"";position:absolute;top:2px;left:2px;width:1.05rem;height:1.05rem;border-radius:50%;
  background:#fff;transition:.15s}
.switch input:checked + .switch-ui{background:var(--brand-600)}
.switch input:checked + .switch-ui::after{transform:translateX(1.05rem)}
.switch input:focus-visible + .switch-ui{box-shadow:var(--shadow-glow)}
.radio{display:inline-flex;align-items:center;gap:.5rem;font-size:.9rem}
.ws-password{position:relative}
.ws-password .input{padding-right:4.5rem}
.ws-password-toggle{position:absolute;right:.4rem;top:50%;transform:translateY(-50%);border:0;background:transparent;
  color:var(--brand-700);font-size:.8rem;font-weight:600;padding:.35rem .5rem;min-height:36px}

/* ------------------------------- Tabs / accordion / modal --------------- */
.tabs{display:flex;gap:.25rem;border-bottom:1px solid var(--slate-200)}
.tab{padding:.7rem 1rem;border:0;background:transparent;font-weight:600;color:var(--slate-500);border-bottom:2px solid transparent}
.tab[aria-selected="true"]{color:var(--brand-700);border-bottom-color:var(--brand-600)}
.tab-panel[hidden]{display:none}
.accordion-item{border:1px solid var(--color-border);border-radius:var(--radius);padding:0;background:var(--color-surface)}
.accordion-item + .accordion-item{margin-top:.5rem}
.accordion-item summary{cursor:pointer;font-weight:600;list-style:none;padding:1rem 1.25rem}
.accordion-item summary::-webkit-details-marker{display:none}
.accordion-item summary::after{content:"+";float:right;color:var(--brand-600)}
.accordion-item[open] summary::after{content:"−"}
.accordion-item .accordion-body{padding:0 1.25rem 1rem;color:var(--text-secondary)}
.modal-backdrop{position:fixed;inset:0;background:rgba(15,23,42,.45);display:grid;place-items:center;padding:1rem;z-index:80}
.modal{background:var(--color-surface);border-radius:var(--radius-xl);max-width:28rem;width:100%;padding:1.5rem;box-shadow:var(--shadow-card-hover)}

/* ------------------------------- Loading / empty / toast ---------------- */
.spinner{width:1.25rem;height:1.25rem;border:2px solid var(--slate-200);border-top-color:var(--brand-600);
  border-radius:50%;animation:ws-spin .7s linear infinite}
.btn .spinner{width:1rem;height:1rem;border-color:rgba(255,255,255,.4);border-top-color:#fff}
.btn-secondary .spinner,.btn-ghost .spinner{border-color:var(--slate-300);border-top-color:var(--brand-600)}
.btn.ws-submitting{opacity:.8;cursor:progress}
@keyframes ws-spin{to{transform:rotate(360deg)}}
.skeleton{background:linear-gradient(90deg,var(--slate-100),var(--slate-50),var(--slate-100));
  background-size:200% 100%;animation:ws-shimmer 1.2s ease-in-out infinite;border-radius:.5rem;min-height:1rem}
@keyframes ws-shimmer{0%{background-position:100% 0}100%{background-position:-100% 0}}
.empty-state{text-align:center;padding:3rem 1.5rem;color:var(--text-muted)}
.empty-state h2,.empty-state h3{color:var(--color-text)}
.ws-empty-icon{display:inline-flex;align-items:center;justify-content:center;width:4rem;height:4rem;
  border-radius:999px;background:var(--brand-50);color:var(--brand-600)}
.toast{position:fixed;right:1rem;bottom:1rem;background:var(--slate-900);color:#fff;padding:.85rem 1rem;
  border-radius:var(--radius);box-shadow:var(--shadow-card);z-index:90;max-width:22rem}
#ws-toast-host{position:fixed;right:1rem;bottom:1rem;z-index:300;display:flex;flex-direction:column;gap:.6rem;
  max-width:min(22rem,calc(100vw - 2rem))}
#ws-toast-host .toast{margin:0;position:static;max-width:100%;display:flex;align-items:flex-start;gap:.5rem;
  box-shadow:var(--shadow-card-hover);animation:ws-slide-up .2s ease-out;transition:opacity .2s ease}
#ws-toast-host .toast.is-leaving{opacity:0}
.toast-close{margin-left:auto;background:transparent;border:0;color:inherit;opacity:.7;font-size:1.1rem;
  line-height:1;padding:0 .1rem;cursor:pointer}
.toast-close:hover{opacity:1}

/* ------------------------------- Site operator -------------------------- */
.ws-assistant-launch{position:fixed;right:1.1rem;bottom:1.1rem;z-index:200;border:0;border-radius:999px;
  background:var(--brand-600);color:#fff;padding:.85rem 1.05rem;font-weight:700;box-shadow:var(--shadow-card-hover);
  display:inline-flex;align-items:center;gap:.45rem;min-height:48px;pointer-events:auto;cursor:pointer}
.ws-assistant-launch:hover{background:var(--brand-700);text-decoration:none}
.ws-assistant-launch:focus-visible{outline:2px solid #fff;outline-offset:2px}
.ws-assistant{position:fixed;right:1.1rem;bottom:4.6rem;z-index:210;width:min(24rem,calc(100vw - 1.5rem));
  height:min(34rem,calc(100vh - 7rem));background:var(--color-surface);border:1px solid var(--color-border);border-radius:1.1rem;
  box-shadow:0 20px 50px -20px rgba(15,23,42,.35);display:flex;flex-direction:column;overflow:hidden;
  opacity:1;visibility:visible;transform:none;pointer-events:auto}
.ws-assistant[hidden]{display:none !important;opacity:0;visibility:hidden;pointer-events:none}
.ws-assistant-head{padding:1rem 1rem .75rem;border-bottom:1px solid var(--color-border);display:flex;justify-content:space-between;gap:.75rem}
.ws-assistant-head h2{font-size:1rem;margin:0}
.ws-assistant-log{flex:1;overflow:auto;padding:1rem;display:flex;flex-direction:column;gap:.75rem}
.ws-bubble{max-width:92%;padding:.75rem .9rem;border-radius:1rem;font-size:.925rem;line-height:1.5;white-space:pre-wrap}
.ws-bubble-assistant{background:var(--surface-muted);border:1px solid var(--color-border);border-bottom-left-radius:.3rem}
.ws-bubble-user{background:var(--brand-600);color:#fff;align-self:flex-end;border-bottom-right-radius:.3rem}
.ws-assistant-links{display:flex;flex-wrap:wrap;gap:.35rem;margin-top:.5rem}
.ws-assistant-links a{font-size:.8rem}
.ws-suggest{display:flex;flex-wrap:wrap;gap:.4rem;padding:0 1rem .5rem}
.ws-suggest button{border:1px solid var(--color-border);background:var(--color-surface);border-radius:999px;padding:.35rem .7rem;font-size:.8rem}
.ws-assistant-form{display:flex;gap:.4rem;padding:.75rem;border-top:1px solid var(--color-border)}
.ws-assistant-form .input{flex:1}
.ws-assistant-status{font-size:.8rem;color:var(--text-muted);padding:0 1rem .5rem}
@media(max-width:560px){
  .ws-assistant{right:0;left:0;bottom:0;width:100%;height:min(85vh,40rem);border-radius:1rem 1rem 0 0}
  .ws-assistant-launch{right:1rem;bottom:1rem}
}

/* Dashboard mobile nav sits at the bottom; keep the launcher above it there. */
@media(max-width:768px){
  body:has(.md\\:hidden.fixed.bottom-0) .ws-assistant-launch{bottom:4.6rem}
  body:has(.md\\:hidden.fixed.bottom-0) .ws-assistant{bottom:8.2rem}
}

/* ------------------------------- Pricing / cards ------------------------ */
.ws-plan{display:flex;flex-direction:column;height:100%}
.ws-plan ul{margin:.75rem 0 1.25rem;padding-left:1.1rem}
.ws-plan .btn{margin-top:auto}
.ws-compare{overflow-x:auto}
.ws-compare table{min-width:640px}

/* ------------------------------- Auth polish ---------------------------- */
.ws-auth-aside{font-size:.85rem;color:var(--slate-500);margin-top:1rem}

@media (prefers-reduced-motion: reduce) {
  .spinner,.skeleton{animation:none !important}
  .ws-announce-slide{transition:none !important}
}

/* ===================== Authenticated app shell ===================== */
:root {
  --ws-sidebar-w: 16.5rem;
  --ws-topbar-h: 4rem;
  --ws-page-pad: 1.5rem;
}
@media (min-width:1024px){ :root { --ws-page-pad: 2rem; } }
@media (max-width:767px){ :root { --ws-page-pad: 1rem; } }

.ws-app-shell { background: var(--surface-muted); }
.ws-app-frame { display:flex; min-height:100vh; }
.ws-sidebar {
  width: var(--ws-sidebar-w);
  flex-shrink:0;
  border-right:1px solid var(--color-border);
  background: var(--color-surface);
  display:flex; flex-direction:column;
  /* Offset below the sticky announcement bar exactly like .ws-topbar does
     (top:var(--ws-announce-h,0)). Without this offset, the sidebar's own
     sticky top edge — which holds the logo in .ws-sidebar-brand — lands at
     the same y=0 as the announcement ticker (z-index:80) once the page is
     scrolled, so the scrolling announcement text painted on top of the
     logo/brand mark. Same fix keeps the sidebar's height from running under
     the announcement bar it no longer overlaps. */
  position:sticky; top:var(--ws-announce-h,0);
  height:calc(100vh - var(--ws-announce-h,0px)); max-height:calc(100vh - var(--ws-announce-h,0px));
  z-index:30;
}
.ws-sidebar-brand {
  height: var(--ws-topbar-h);
  display:flex; align-items:center;
  padding:0 1.25rem;
  border-bottom:1px solid var(--color-border);
}
.ws-sidebar-nav { flex:1; overflow-y:auto; padding:.75rem .65rem 1rem; }
.ws-nav-group { margin:0 0 .35rem; border:0; }
.ws-nav-group > summary {
  list-style:none; cursor:pointer;
  display:block; padding:.45rem .75rem .2rem;
  font-size:.68rem; font-weight:700; letter-spacing:.08em;
  text-transform:uppercase; color:var(--slate-400);
}
.ws-nav-group > summary::-webkit-details-marker { display:none; }
.ws-nav-group-items { display:flex; flex-direction:column; gap:2px; }
.ws-nav-link {
  display:flex; align-items:center; gap:.75rem;
  border-radius:.7rem; padding:.5rem .75rem;
  font-size:.875rem; color:var(--slate-600); text-decoration:none;
}
.ws-nav-link:hover { background:var(--surface-muted); color:var(--color-text); text-decoration:none; }
.ws-nav-link.is-active { background:var(--brand-50); color:var(--brand-700); font-weight:600; }
.ws-sidebar-user {
  border-top:1px solid var(--color-border);
  padding:1rem;
  display:flex; align-items:center; gap:.75rem;
}
.ws-avatar-initial {
  width:2.25rem; height:2.25rem; border-radius:999px;
  background:var(--brand-100); color:var(--brand-700);
  display:grid; place-items:center; font-weight:700; font-size:.875rem; flex-shrink:0;
}
.btn-icon {
  background:transparent; border:0; padding:.35rem; color:var(--slate-400); cursor:pointer; border-radius:.5rem;
}
.btn-icon:hover { color:var(--slate-700); background:var(--surface-muted); }

.ws-app-main { flex:1; min-width:0; display:flex; flex-direction:column; }
.ws-topbar {
  height: var(--ws-topbar-h);
  border-bottom:1px solid var(--color-border);
  background: var(--color-surface);
  display:flex; align-items:center; justify-content:space-between;
  padding:0 1rem 0 var(--ws-page-pad);
  position:sticky; top:var(--ws-announce-h,0); z-index:40;
}
.ws-topbar-left, .ws-topbar-right { display:flex; align-items:center; gap:.5rem; min-width:0; }
.ws-topbar-title { font-weight:600; font-size:.95rem; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.ws-sidebar-toggle { display:none; }
.ws-unread {
  position:absolute; top:.25rem; right:.25rem; min-width:18px; height:18px; padding:0 4px;
  border-radius:999px; background:var(--danger-600); color:#fff; font-size:10px; font-weight:700;
  display:grid; place-items:center;
}
.ws-app-content {
  flex:1;
  padding: var(--ws-page-pad);
  padding-bottom: 5.5rem;
}
@media (min-width:768px) {
  .ws-app-content { padding-bottom: var(--ws-page-pad); }
}
.ws-page-wide { max-width: 88rem; }
.ws-page-medium { max-width: 48rem; margin-inline:auto; width:100%; }
.ws-page-narrow { max-width: 28rem; margin-inline:auto; width:100%; }

.ws-page-head { margin-bottom: 1.25rem; }
.ws-breadcrumb { display:flex; flex-wrap:wrap; gap:.35rem; align-items:center; font-size:.8rem; color:var(--text-muted); margin-bottom:.35rem; }
.ws-breadcrumb a { color:var(--text-secondary); }
.ws-breadcrumb-sep { opacity:.5; }
.ws-page-head-row { display:flex; justify-content:space-between; gap:1rem; align-items:flex-start; flex-wrap:wrap; }
.ws-page-title {
  font-family: var(--font-display);
  font-size: clamp(1.35rem, 2.2vw, 1.85rem);
  margin:0 0 .25rem;
  letter-spacing:-.02em;
}
.ws-page-desc { margin:0; color:var(--text-muted); max-width:40rem; font-size:.95rem; }
.ws-page-actions { display:flex; flex-wrap:wrap; gap:.5rem; }
.ws-page-body { display:flex; flex-direction:column; gap:1.25rem; }

.ws-stat-grid { display:grid; gap:1rem; grid-template-columns:repeat(auto-fit,minmax(180px,1fr)); }
.ws-stat-card .card-meta { font-size:.75rem; font-weight:600; letter-spacing:.04em; text-transform:uppercase; color:var(--text-muted); }
.ws-stat-value { font-family:var(--font-display); font-size:1.75rem; font-weight:700; letter-spacing:-.02em; margin-top:.25rem; }
.ws-action-grid { display:grid; gap:1rem; grid-template-columns:repeat(auto-fit,minmax(200px,1fr)); }
.ws-action-card { text-decoration:none; color:inherit; }
.ws-action-card:hover { text-decoration:none; }

.table-wrap, .card { overflow-x:auto; -webkit-overflow-scrolling:touch; }
.table-toolbar { display:flex; flex-wrap:wrap; gap:.75rem; align-items:center; margin-bottom:1rem; }
.table-toolbar .input, .table-toolbar .select { max-width:16rem; }
.form-layout { display:flex; flex-direction:column; gap:1rem; }
.form-section { padding-bottom:1rem; border-bottom:1px solid var(--color-border); }
.form-section:last-child { border-bottom:0; }
.form-actions { display:flex; flex-wrap:wrap; gap:.5rem; padding-top:.5rem; }

.ws-impersonation-banner {
  position:sticky; top:var(--ws-announce-h); z-index:1000;
  background:#7f1d1d; color:#fff; border-bottom:4px solid #fbbf24;
  padding:.75rem 1rem;
}

.ws-mobile-tabbar {
  display:none;
}
.ws-sidebar-backdrop { display:none; }

@media (max-width:767px) {
  .ws-sidebar {
    position:fixed; left:0; top:0; bottom:0; z-index:60;
    transform:translateX(-100%);
    transition:transform .2s ease;
    box-shadow: none;
  }
  .ws-app-shell.sidebar-open .ws-sidebar { transform:none; box-shadow: var(--shadow-card-hover); }
  .ws-sidebar-backdrop {
    display:block; position:fixed; inset:0; background:rgba(15,23,42,.45); z-index:55;
  }
  .ws-app-shell.sidebar-open .ws-sidebar-backdrop { display:block; }
  .ws-app-shell:not(.sidebar-open) .ws-sidebar-backdrop { display:none; }
  .ws-sidebar-toggle { display:inline-flex; }
  .ws-mobile-tabbar {
    display:grid; grid-template-columns:repeat(5,1fr);
    position:fixed; bottom:0; inset-inline:0; z-index:50;
    border-top:1px solid var(--color-border); background:var(--color-surface);
  }
  .ws-mobile-tabbar a {
    display:flex; flex-direction:column; align-items:center; justify-content:center;
    gap:.15rem; padding:.55rem .15rem; font-size:11px; color:var(--slate-500); text-decoration:none;
  }
  .ws-mobile-tabbar a.is-active { color:var(--brand-600); font-weight:600; }
  .ws-page-head-row { flex-direction:column; }
  .ws-page-actions { width:100%; }
  .ws-page-actions .btn { flex:1; min-height:44px; }
  .form-layout .row { flex-direction:column; align-items:stretch; }
}

@media (min-width:768px) {
  .ws-sidebar-backdrop { display:none !important; }
}

/* Dark mode nav/active */
.dark .ws-nav-link.is-active { background: rgba(99,102,241,.18); color: var(--brand-300); }
.dark .ws-topbar, .dark .ws-sidebar { background: var(--color-surface); }

/* ===================== Public landing (Aurora) ===================== */
.ws-landing-hero {
  padding: 4.5rem 0 3rem;
  background:
    radial-gradient(900px 320px at 8% -20%, var(--brand-100), transparent 55%),
    radial-gradient(700px 260px at 92% 0, var(--accent-100), transparent 50%);
}
.ws-landing-hero-inner {
  display:grid; grid-template-columns: 1.05fr 1fr; gap: 3rem; align-items:center;
}
.ws-landing-hero h1 { font-size: clamp(2rem, 4.2vw, 3.1rem); margin: .6rem 0 1rem; }
.ws-landing-hero-visual img {
  width:100%; height:auto; border-radius: 1.25rem;
  box-shadow: 0 28px 60px -28px rgba(49,46,129,.45); border:1px solid var(--color-border);
}
.ws-landing-stats { padding: 0 0 2.5rem; margin-top: -1rem; }
.ws-landing-stats-grid {
  display:grid; grid-template-columns: repeat(4,1fr); gap: 1rem;
}
.ws-landing-stat {
  background: var(--color-surface); border:1px solid var(--color-border);
  border-radius: var(--radius-lg); padding: 1.1rem 1.25rem; text-align:center;
  box-shadow: var(--shadow-card);
}
.ws-landing-stat strong { display:block; font-family:var(--font-display); font-size:1.5rem; color:var(--brand-700); }
.ws-landing-stat span { font-size:.85rem; color:var(--text-muted); }
.ws-landing-muted { background: var(--surface-muted); }
.ws-landing-cards {
  display:grid; grid-template-columns: repeat(auto-fit, minmax(230px,1fr)); gap:1rem;
}
.ws-landing-service { text-decoration:none; color:inherit; display:block; }
.ws-landing-service:hover { text-decoration:none; }
.ws-landing-icon {
  width:2.75rem; height:2.75rem; border-radius:.85rem;
  background:var(--brand-50); color:var(--brand-700);
  display:grid; place-items:center; margin-bottom:.75rem;
}
.ws-landing-link { display:inline-block; margin-top:.75rem; font-weight:600; font-size:.875rem; color:var(--brand-700); }
.ws-landing-rate { font-family:var(--font-display); font-size:1.35rem; color:var(--brand-700); }
.ws-landing-steps {
  list-style:none; margin:0; padding:0;
  display:grid; grid-template-columns: repeat(4,1fr); gap:1rem;
}
.ws-landing-step-num {
  display:inline-grid; place-items:center; width:2.4rem; height:2.4rem; border-radius:999px;
  background:var(--brand-50); color:var(--brand-700); font-weight:700; margin-bottom:.6rem;
}
.ws-landing-showcase {
  display:grid; grid-template-columns: .9fr 1.1fr; gap:2.5rem; align-items:center;
}
.ws-landing-showcase img {
  width:100%; border-radius:1.1rem; border:1px solid var(--color-border); box-shadow:var(--shadow-card);
}
.ws-landing-api {
  display:grid; grid-template-columns: 1fr 1fr; gap:2rem; align-items:center;
}
.ws-landing-code {
  margin:0; background:#0b1020; color:#e2e8f0; border-radius:1rem; padding:1.25rem 1.4rem;
  overflow:auto; font-size:.85rem; line-height:1.55;
}
.ws-landing-cta {
  text-align:center; background:linear-gradient(135deg,var(--brand-600),var(--accent-600));
  color:#fff; border-radius: var(--radius-xl); padding: 3rem 1.5rem;
}
.ws-landing-cta h2, .ws-landing-cta p { color:#fff; }
.ws-landing-cta p { opacity:.9; max-width:32rem; margin:0 auto 1.25rem; }
.ws-landing-cta .btn { background:#fff; color:var(--brand-700); }

@media (max-width: 900px) {
  .ws-landing-hero-inner, .ws-landing-showcase, .ws-landing-api { grid-template-columns:1fr; }
  .ws-landing-stats-grid, .ws-landing-steps { grid-template-columns:1fr 1fr; }
  .ws-landing-hero { padding: 2.5rem 0 2rem; }
}
@media (max-width: 560px) {
  .ws-landing-stats-grid, .ws-landing-steps { grid-template-columns:1fr; }
  .ws-landing-hero .btn-lg, .ws-landing-cta .btn { width:100%; }
}

/* Authenticated shell footer — same links as the public footer, less furniture */
.ws-app-footer{
  border-top:1px solid var(--slate-200,#e2e8f0);
  padding:1rem 1.5rem 1.5rem;
  margin-top:auto;
}
.ws-app-footer a{color:inherit;text-decoration:none;opacity:.75}
.ws-app-footer a:hover{opacity:1;text-decoration:underline}
.dark .ws-app-footer{border-top-color:rgba(148,163,184,.25)}

/* ===================== Navy chrome: menu + footer ========================
 *
 * One navy treatment, written once, applied to every navigation surface and
 * to the footer. Before this the public site had two different headers (the
 * shared navbar on some pages, a hand-written one in the themed shell on the
 * rest) and the footer inherited the page background, so "the menu" looked
 * different depending on which page you were on.
 *
 * The palette is fixed rather than derived from --brand: an operator changing
 * their accent colour should not be able to make the navigation illegible.
 * Accent hovers still use the brand colour where it stays readable on navy.
 */
:root{
  --ws-navy-900:#0b1b3a;
  --ws-navy-800:#102449;
  --ws-navy-700:#16305c;
  --ws-navy-600:#1d3c73;
  --ws-navy-line:rgba(255,255,255,.14);
  --ws-navy-ink:#ffffff;
  --ws-navy-ink-dim:rgba(255,255,255,.76);
}

/* ---- public + auth menus ---- */
.ws-public-nav,
.ws-auth-header{
  background:var(--ws-navy-900);
  border-bottom:1px solid var(--ws-navy-line);
  backdrop-filter:none;
  color:var(--ws-navy-ink);
}
.ws-public-nav .ws-brand,
.ws-auth-header .ws-brand,
.ws-public-nav .ws-brand-word,
.ws-public-nav .ws-nav-links a,
.ws-auth-header .ws-auth-nav a{ color:var(--ws-navy-ink); }
.ws-public-nav .ws-brand:hover,
.ws-auth-header .ws-brand:hover{ color:var(--ws-navy-ink); }
.ws-public-nav .ws-nav-links a:hover,
.ws-public-nav .ws-nav-links a.is-active,
.ws-auth-header .ws-auth-nav a:hover{
  background:var(--ws-navy-700);
  color:var(--ws-navy-ink);
}
.ws-public-nav .ws-nav-toggle,
.ws-auth-header .ws-nav-toggle{
  background:var(--ws-navy-700);
  border-color:var(--ws-navy-line);
  color:var(--ws-navy-ink);
}
.ws-public-nav .ws-nav-panel{
  background:var(--ws-navy-800);
  border-bottom-color:var(--ws-navy-line);
}
.ws-public-nav .ws-nav-panel a,
.ws-public-nav .ws-nav-panel button{ color:var(--ws-navy-ink); }
.ws-public-nav .ws-nav-panel a:hover{ background:var(--ws-navy-700); }
/* Ghost buttons sit on navy in the nav, so they need light ink. */
.ws-public-nav .btn-ghost,
.ws-auth-header .btn-ghost{
  color:var(--ws-navy-ink);
  border-color:var(--ws-navy-line);
  background:transparent;
}
.ws-public-nav .btn-ghost:hover,
.ws-auth-header .btn-ghost:hover{ background:var(--ws-navy-700); }

/* ---- the signed-in sidebar (the app's menu) ---- */
.ws-sidebar{
  background:var(--ws-navy-900);
  border-right:1px solid var(--ws-navy-line);
  color:var(--ws-navy-ink);
}
.ws-sidebar-brand{ border-bottom:1px solid var(--ws-navy-line); }
.ws-sidebar .ws-brand,
.ws-sidebar .ws-brand-word{ color:var(--ws-navy-ink); }
.ws-sidebar .ws-nav-group > summary{ color:rgba(255,255,255,.55); }
.ws-sidebar .ws-nav-link{ color:var(--ws-navy-ink-dim); }
.ws-sidebar .ws-nav-link:hover{ background:var(--ws-navy-700); color:var(--ws-navy-ink); }
.ws-sidebar .ws-nav-link.is-active{
  background:var(--ws-navy-600);
  color:var(--ws-navy-ink);
  font-weight:600;
}
.ws-sidebar-user{ border-top:1px solid var(--ws-navy-line); color:var(--ws-navy-ink); }
.ws-sidebar-user .muted,
.ws-sidebar-user .text-xs{ color:var(--ws-navy-ink-dim); }
.ws-sidebar .btn-icon{ color:var(--ws-navy-ink-dim); }
.ws-sidebar .btn-icon:hover{ color:var(--ws-navy-ink); background:var(--ws-navy-700); }

/* ---- footer ---- */
.ws-footer,
.ws-app-footer{
  background:var(--ws-navy-900);
  border-top:1px solid var(--ws-navy-line);
  color:var(--ws-navy-ink);
}
.ws-footer h2{ color:rgba(255,255,255,.62); }
.ws-footer a,
.ws-app-footer a{ color:var(--ws-navy-ink-dim); }
.ws-footer a:hover,
.ws-app-footer a:hover{ color:var(--ws-navy-ink); text-decoration:underline; }
.ws-footer p,
.ws-footer .muted,
.ws-app-footer .muted{ color:var(--ws-navy-ink-dim); }
.ws-footer-meta{ border-top-color:var(--ws-navy-line); color:var(--ws-navy-ink-dim); }
/* The footer renders the light wordmark directly (partials/footer asks for the
   'dark' variant), so no filter trickery is needed — a filtered logo loses the
   gradient in the mark. */

/* ===================== Sign-in / register split panel ====================
 *
 * The copy in the photo panel used to be top-aligned inside a very tall
 * column, with a brand mark pressed against the heading; the three elements
 * drifted apart and, below 880px, overlapped the photograph. The panel is now
 * a flex column that centres the write-up — vertically in the panel and
 * horizontally on the page — over a gradient that guarantees contrast, and on
 * small screens the photo is dropped altogether in favour of a compact banner
 * above the form. The logo no longer lives in the panel at all: the navy
 * header above already carries the mark, so the photograph belongs to the
 * words alone.
 */
.ws-auth-visual{
  display:flex;
  flex-direction:column;
  justify-content:center;
  align-items:center;
  text-align:center;
  min-height:32rem;
}
.ws-auth-visual::after{
  content:"";
  position:absolute; inset:0;
  background:linear-gradient(180deg,rgba(11,27,58,.35) 0%,rgba(11,27,58,.82) 62%,rgba(11,27,58,.95) 100%);
  z-index:0;
}
.ws-auth-visual-inner{
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:1.1rem;
  max-width:32rem;
}
.ws-auth-visual-copy{
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:.7rem;
}
.ws-auth-visual h2{
  margin:0;
  font-size:clamp(1.35rem,2.2vw,1.9rem);
  line-height:1.25;
  text-wrap:balance;
}
.ws-auth-visual p{ margin:0 auto; max-width:40ch; line-height:1.6; }
/* The longer write-up: three short promises under the pitch, separated by
   hairline rules so the centred paragraphs stay distinct blocks for the eye
   as they already are for a screen reader. */
.ws-auth-visual-points{
  list-style:none;
  margin:.35rem auto 0;
  padding:0;
  max-width:36ch;
  display:flex;
  flex-direction:column;
}
.ws-auth-visual-points li{
  padding:.75rem 0;
  font-size:.92rem;
  line-height:1.55;
  color:rgba(255,255,255,.88);
}
.ws-auth-visual-points li + li{ border-top:1px solid rgba(226,232,240,.22); }
@media(max-width:880px){
  /* Squeezing a photo and four paragraphs into a 220px strip is what made
     this read as one run-on sentence. Show the words, drop the picture. */
  .ws-auth-visual{
    min-height:0;
    padding:1.5rem 1.25rem 1.6rem;
    justify-content:center;
  }
  .ws-auth-visual img{ display:none; }
  .ws-auth-visual::after{ background:none; }
  .ws-auth-visual-inner{ gap:.85rem; max-width:none; }
  .ws-auth-visual-copy{ gap:.35rem; }
  .ws-auth-visual h2{ font-size:1.15rem; }
  .ws-auth-visual p{ font-size:.9rem; max-width:none; }
  .ws-auth-visual-points{ margin-top:.25rem; max-width:none; }
  .ws-auth-visual-points li{ font-size:.85rem; padding:.55rem 0; }
}

/* The announcement strip takes its colours from Admin → Settings (inline
   style), so the stylesheet only owns layout. A single message is centred
   rather than marched across the screen. */
.ws-announce.is-static .ws-announce-viewport{ display:flex; align-items:center; justify-content:center; }
.ws-announce-static{
  padding:0 1rem; font-size:.85rem; font-weight:500;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; max-width:100%;
}
/* A link inside the banner inherits the operator's chosen text colour — the
   background is theirs too, so a fixed link colour could land unreadable. It
   is underlined instead, which reads as a link on any background, and the
   marquee pauses on hover/focus so a moving link can actually be clicked. */
.ws-announce-link{
  color:inherit; text-decoration:underline; text-underline-offset:2px;
  font-weight:600;
}
.ws-announce-link:hover,.ws-announce-link:focus-visible{ text-decoration-thickness:2px; }
.ws-announce-link:focus-visible{ outline:2px solid currentColor; outline-offset:2px; border-radius:2px; }

/* Contact-page map. FIRST-PARTY: a 3×3 grid of OSM tiles served from this
   origin at /contact/map/tile/… (ContactMapService), with the pin placed by
   the server. No iframe, no third-party request from the visitor's browser.
   Fixed square aspect so the grid never distorts and the card does not jump
   while tiles load; the placeholder tint shows through any tile that has not
   been cached yet. */
.ws-map{
  position:relative; width:100%; aspect-ratio:1/1; min-height:240px;
  border-radius:var(--radius-lg); overflow:hidden;
  background:var(--slate-100); border:1px solid var(--color-border);
}
.ws-map-grid{ display:grid; grid-template-columns:repeat(3,1fr); grid-template-rows:repeat(3,1fr); }
.ws-map-tile{ display:block; width:100%; height:100%; object-fit:fill; }
/* A teardrop pin whose tip sits on the requested point (top:0 + the
   translate below put the bottom tip there). */
.ws-map-pin{ position:absolute; width:20px; height:20px; transform:translate(-50%,-100%); }
.ws-map-pin::before{
  content:""; position:absolute; inset:0;
  border-radius:50% 50% 50% 0; transform:rotate(-45deg);
  background:var(--brand-600); border:2px solid #fff;
  box-shadow:0 1px 4px rgba(15,23,42,.45);
}
