/* ============================================================================
   Wonderboy Creative — service page template.

   The long-form hub/spoke page type: hero, silo bar, two-column layout with a
   sticky section rail, 40+ article sections, and the module library that goes
   between them. First used by /winery-seo/; built to carry every service hub
   and spoke that follows it.

   Prefix: .wsp-  (Wonderboy Service Page)

   Declares NO design tokens and NO shared chrome. Colors, type, spacing,
   radius, shadow and motion all come from tokens.css; buttons, eyebrows, the
   container, nav and footer all come from wonderboy.css. This file is only the
   vocabulary that does not already exist.

   Ported from the approved design bundle at
   content/design/ui_kits/website/winery-seo.css. The two unscoped `a` rules in
   that file are deliberately omitted — they were written for a standalone
   prototype and would have restyled every link on the site. In-copy links are
   handled by the scoped .wsp-sec / .wsp-lede rules.
   ============================================================================ */

/* ---------- page container: wider than the marketing 1200 to seat the rail -- */
/* Stands alone, as the design has it. It was briefly written as a modifier on
   .wb-container to avoid repeating three properties; that broke every region
   that uses it, because .wsp-wrap then carried no width or padding of its own.
   The 80px of extra width over .wb-container is what seats the rail beside a
   740px reading measure. */
.wsp-wrap{width:100%;max-width:1280px;margin:0 auto;padding:0 28px}

/* ---------- reading-progress bar ---------- */
.wsp-progress{position:fixed;top:var(--wb-admin-bar);left:0;right:0;height:3px;z-index:150;background:transparent;pointer-events:none}
.wsp-progress span{display:block;height:100%;width:0;background:linear-gradient(90deg,var(--hero-500),var(--electric-500));box-shadow:0 0 12px rgba(56,189,248,.5);transition:width .08s linear}

/* ============================================================================
   HERO — one full-bleed image band, headline set ON it. No stacked text band.
   ============================================================================ */
.wsp-hero{position:relative;overflow:hidden;min-height:min(88vh,780px);display:flex;flex-direction:column;justify-content:flex-end;background:var(--midnight-950)}
.wsp-hero-media{position:absolute;inset:0;z-index:0}
.wsp-hero-media image-slot,.wsp-hero-media img{width:100%;height:100%;display:block;object-fit:cover;object-position:62% 45%}
.wsp-hero-media image-slot[data-filled],.wsp-hero-media img{opacity:1;filter:saturate(.9) contrast(1.04) brightness(.7)}
.wsp-hero-veil{position:absolute;inset:0;z-index:1;pointer-events:none;background:linear-gradient(90deg,rgba(18,26,43,.94) 0%,rgba(18,26,43,.72) 32%,rgba(20,28,46,.34) 70%,rgba(20,28,46,.12) 100%),linear-gradient(0deg,var(--midnight-950) 1%,rgba(18,26,43,.16) 46%),radial-gradient(58% 48% at 70% 26%,rgba(99,117,255,.2),transparent 72%)}
.wsp-hero-veil::after{content:'';position:absolute;inset:0;box-shadow:inset 0 -130px 170px -70px rgba(9,14,26,.92),inset 0 70px 130px -50px rgba(9,14,26,.45)}
.wsp-hero-rule{position:absolute;left:0;right:0;top:0;height:1px;z-index:2;background:linear-gradient(90deg,var(--hero-500),transparent 60%)}
/* margin-bottom:auto, deliberately.

   .wsp-hero is a bottom-aligned flex column with a min-height, and the silo
   bar is its last in-flow child. That made the bar the only thing holding the
   copy off the floor of the band. When the pills moved into inc/silos.php and
   a page had no published sibling left to name, the bar stopped rendering and
   the breadcrumb, headline and deck dropped by the bar's full height: 121px,
   measured on the dental and winery pages at 1440x779.

   The auto margin takes the free space below the copy rather than above it, so
   the copy is placed by its own padding and sits in the same place on a page
   with pills and a page without. The bar, when there is one, is still pinned to
   the bottom edge with its 54px gap. The split hero is unaffected: its content
   already exceeds the min-height, so there is no free space to move. */
.wsp-hero-inner{position:relative;z-index:3;padding:150px 0 0;margin-bottom:auto}

/* breadcrumb — the "above me" relationship */
.wsp-crumbs{display:flex;flex-wrap:wrap;align-items:center;gap:8px;font-family:var(--font-mono);font-size:11.5px;letter-spacing:.1em;text-transform:uppercase;color:#8794ad;margin:0;padding:0 0 22px;list-style:none}
/* Crumbs carry each page's full title, so they run longer than a shortened
   stand-in would. Smaller and tighter here to keep the trail one quiet line
   above the headline rather than a second thing competing with it. */
.wsp-hero.is-split .wsp-crumbs{font-size:10px;letter-spacing:.11em;gap:7px;padding-bottom:18px}
.wsp-crumbs li{display:flex;align-items:center;gap:8px}
.wsp-crumbs li+li::before{content:'/';color:#4d5a75}
.wsp-crumbs a{color:#a9b5cc;transition:color var(--dur-fast)}
.wsp-crumbs a:hover{color:var(--electric-400)}
.wsp-crumbs [aria-current]{color:#fff}

.wsp-hero h1{font-family:var(--font-display);font-weight:800;font-size:clamp(27px,3.6vw,48px);line-height:1.08;letter-spacing:-.022em;color:#fff;margin:0;max-width:27ch;text-wrap:pretty}
.wsp-h1-term{display:block;color:var(--hero-400)}
.wsp-hero-sub{font-family:var(--font-body);font-size:var(--text-lg);line-height:1.6;color:#c2cbe0;max-width:56ch;margin:22px 0 0}
.wsp-hero-cta{display:flex;flex-wrap:wrap;gap:14px;margin:32px 0 0}

/* meta strip — declares scale of the page (the "below me" hint) */
.wsp-hero-meta{display:flex;flex-wrap:wrap;gap:10px 26px;margin:34px 0 0;padding:0;list-style:none}
.wsp-hero-meta li{display:flex;align-items:center;gap:9px;font-family:var(--font-mono);font-size:11.5px;letter-spacing:.09em;text-transform:uppercase;color:#9aa7c0}
.wsp-hero-meta svg{color:var(--hero-400)}

/* silo bar along the hero floor — the "beside me" relationship */
.wsp-silo{position:relative;z-index:3;margin-top:54px;border-top:1px solid rgba(255,255,255,.12);background:rgba(12,19,33,.55);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px)}
.wsp-silo-inner{display:flex;flex-wrap:wrap;align-items:center;gap:14px 28px;padding:18px 0}
.wsp-silo-label{display:flex;align-items:center;gap:10px;white-space:nowrap;font-family:var(--font-mono);font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:#7f8ca6}
.wsp-silo-label img{height:13px}
.wsp-silo-links{display:flex;flex-wrap:wrap;gap:10px;margin-left:auto}
.wsp-silo-links a{display:inline-flex;align-items:center;gap:8px;white-space:nowrap;font-family:var(--font-display);font-weight:700;font-size:12.5px;letter-spacing:.03em;text-transform:uppercase;color:#c8d1e4;border:1px solid rgba(255,255,255,.16);border-radius:var(--radius-pill);padding:8px 15px;transition:border-color var(--dur-base),color var(--dur-base),background var(--dur-base)}
.wsp-silo-links a:hover{color:#fff;border-color:var(--hero-400);background:rgba(99,117,255,.16)}
.wsp-silo-links a[aria-current]{color:#fff;background:var(--hero-600);border-color:var(--hero-600)}

/* ============================================================================
   RESUME BAR — the page is read in pieces, over more than one sitting
   ============================================================================ */
.wsp-resume{position:sticky;top:calc(72px + var(--wb-admin-bar));z-index:90;background:var(--midnight-900);border-bottom:1px solid rgba(255,255,255,.1)}
.wsp-resume-inner{display:flex;flex-wrap:wrap;align-items:center;gap:12px 18px;padding:11px 0}
.wsp-resume-txt{font-family:var(--font-body);font-size:14px;color:#c2cbe0;display:flex;align-items:center;gap:10px}
.wsp-resume-txt svg{color:var(--electric-400);flex:0 0 auto}
.wsp-resume-txt strong{color:#fff;font-weight:600}
.wsp-resume-acts{display:flex;align-items:center;gap:8px;margin-left:auto}
.wsp-resume-acts button{font-family:var(--font-display);font-weight:700;font-size:12px;text-transform:uppercase;letter-spacing:.05em;border-radius:var(--radius-pill);border:1px solid rgba(255,255,255,.2);background:transparent;color:#c8d1e4;padding:8px 14px;cursor:pointer;transition:background var(--dur-base),color var(--dur-base),border-color var(--dur-base)}
.wsp-resume-acts button.is-go{background:var(--hero-500);border-color:var(--hero-500);color:#fff}
.wsp-resume-acts button.is-go:hover{background:var(--hero-600)}
.wsp-resume-acts button:hover{color:#fff;border-color:rgba(255,255,255,.4)}

/* ============================================================================
   LAYOUT — sticky left rail (map of the section) + reading column
   ============================================================================ */
.wsp-layout{display:grid;grid-template-columns:minmax(0,1fr) 300px;gap:76px;align-items:start;padding:56px 0 96px}
.wsp-rail{position:sticky;top:calc(88px + var(--wb-admin-bar));display:flex;flex-direction:column;gap:16px;max-height:calc(100vh - 112px - var(--wb-admin-bar))}
.wsp-main{min-width:0;max-width:740px}

/* ---------- TABLE OF CONTENTS — 43 sections, grouped into 7 parts ---------- */
.wsp-toc{background:#fff;border:1px solid var(--border-subtle);border-radius:var(--radius-lg);box-shadow:var(--shadow-sm);display:flex;flex-direction:column;flex:1 1 auto;min-height:120px;overflow:hidden}
.wsp-toc-head{display:flex;align-items:center;gap:9px;padding:15px 16px 13px;border-bottom:1px solid var(--border-subtle);font-family:var(--font-mono);font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--fg-muted)}
.wsp-toc-head svg{color:var(--hero-500)}
.wsp-toc-head .ct{margin-left:auto;color:var(--gray-400)}
.wsp-toc-scroll{overflow-y:auto;overscroll-behavior:contain;padding:6px}
.wsp-toc-scroll::-webkit-scrollbar{width:8px}
.wsp-toc-scroll::-webkit-scrollbar-thumb{background:var(--gray-200);border-radius:99px}
.wsp-toc-list{list-style:none;margin:0;padding:0}
.wsp-toc-list li+li{border-top:1px solid var(--gray-100)}
.wsp-toc-list a{display:flex;gap:10px;align-items:baseline;font-family:var(--font-body);font-size:13px;line-height:1.4;color:var(--fg-secondary);padding:9px 10px;border-radius:var(--radius-sm);transition:color var(--dur-fast),background var(--dur-fast)}
.wsp-toc-list a:hover{color:var(--midnight-900);background:var(--gray-50)}
.wsp-toc-list li.is-active a{color:var(--hero-700);background:var(--hero-50);font-weight:600}
.wsp-toc-list .n{flex:0 0 auto;font-family:var(--font-mono);font-size:10px;color:var(--gray-400)}
.wsp-toc-list li.is-active .n{color:var(--hero-600)}
/* ---------- contents: show the same hierarchy the page has ----------------
   Level 2 is the default and takes no indent; it is declared so the vocabulary
   is complete and every level the renderer can emit is accounted for. */
.wsp-toc-list li.wsp-toc-l2 > a{padding-left:10px}
.wsp-toc-list li.wsp-toc-l3 > a{padding-left:16px}
.wsp-toc-list li.wsp-toc-l4 > a{padding-left:30px}
.wsp-toc-list li.wsp-toc-l3 .t,.wsp-toc-list li.wsp-toc-l4 .t{color:var(--gray-500)}
.wsp-toc-list li.wsp-toc-l4 .t{font-size:12px}

/* spoke links live inside the TOC — the map shows what sits below this page */
.wsp-toc-spokes{border-top:1px solid var(--border-subtle);padding:12px 15px 14px;background:var(--gray-50)}
.wsp-toc-spokes.is-card{flex:0 0 auto;border:1px solid var(--border-subtle);border-radius:var(--radius-lg);padding:14px 16px 15px;box-shadow:var(--shadow-sm)}
.wsp-toc-spokes .lbl{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--fg-muted);display:flex;align-items:center;gap:7px;margin-bottom:9px;white-space:nowrap}
.wsp-toc-spokes .lbl svg{color:var(--hero-500)}
.wsp-toc-spokes ul{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:1px}
.wsp-toc-spokes a{display:flex;align-items:center;gap:8px;font-family:var(--font-body);font-weight:600;font-size:12.5px;color:var(--hero-700);padding:5px 0;transition:color var(--dur-fast),gap var(--dur-fast)}
.wsp-toc-spokes a:hover{color:var(--hero-600);gap:11px}
.wsp-toc-spokes a svg{flex:0 0 auto;color:var(--hero-400)}

/* ---------- rail audit card (persistent conversion) ---------- */
.wsp-audit{position:relative;overflow:hidden;border-radius:var(--radius-lg);padding:20px 19px 22px;flex:0 0 auto;background:radial-gradient(120% 90% at 92% -12%,rgba(99,117,255,.42),transparent 58%),linear-gradient(180deg,var(--midnight-900),var(--midnight-950));box-shadow:var(--shadow-md)}
.wsp-audit-bolt{position:absolute;right:-14px;bottom:-20px;width:108px;opacity:.09;pointer-events:none}
.wsp-audit .ttl{position:relative;font-family:var(--font-display);font-weight:800;font-size:18px;line-height:1.12;letter-spacing:-.01em;color:#fff;margin:0 0 7px}
.wsp-audit p{position:relative;font-size:12.5px;line-height:1.5;color:#a9b5cc;margin:0 0 14px}
.wsp-audit-form{position:relative;display:flex;flex-direction:column;gap:9px}
.wsp-field{display:flex;align-items:center;gap:8px;background:rgba(255,255,255,.07);border:1.5px solid rgba(255,255,255,.16);border-radius:var(--radius-md);padding:0 12px;transition:border-color var(--dur-base),box-shadow var(--dur-base)}
.wsp-field:focus-within{border-color:var(--electric-500);box-shadow:var(--shadow-glow)}
.wsp-field svg{color:var(--electric-400);flex:0 0 auto}
.wsp-field input{flex:1 1 auto;min-width:0;background:none;border:none;outline:none;font-family:var(--font-body);font-size:14px;color:#fff;padding:11px 0}
.wsp-field input::placeholder{color:#6f7c97}
.wsp-audit .wb-btn{width:100%}
/* The success state every offer form on this template shows. The retired
   contact rail card used it too, so it stayed when that card went. */
.wsp-sent{position:relative;display:flex;align-items:flex-start;gap:11px;font-size:13px;line-height:1.5;color:#d7deef}
.wsp-sent .ico{flex:0 0 auto;width:28px;height:28px;border-radius:50%;background:rgba(31,180,122,.18);color:var(--success);display:flex;align-items:center;justify-content:center}
.wsp-sent strong{display:block;font-family:var(--font-display);color:#fff;font-size:14px;margin-bottom:3px}
.wsp-audit-note{position:relative;display:flex;align-items:flex-start;gap:6px;font-family:var(--font-mono);font-size:10px;line-height:1.5;letter-spacing:.03em;color:#6f7c97;margin:12px 0 0}
.wsp-audit-note svg{flex:0 0 auto;margin-top:1px}
.wsp-audit-note svg{color:var(--success)}

/* ============================================================================
   PROSE — set for sustained reading
   ============================================================================ */
.wsp-lede{margin:0 0 22px}
.wsp-lede p{font-family:var(--font-body);font-size:20px;line-height:1.68;color:var(--midnight-900);margin:0 0 18px;text-wrap:pretty}
.wsp-lede p:last-child{margin-bottom:0}
.wsp-byline{display:flex;flex-wrap:wrap;align-items:center;gap:10px 18px;margin:0 0 30px;font-family:var(--font-mono);font-size:11px;letter-spacing:.09em;text-transform:uppercase;color:var(--fg-muted)}
.wsp-byline .who{color:var(--midnight-900);font-weight:500}
.wsp-byline .dot{width:4px;height:4px;border-radius:50%;background:var(--gray-300)}

.wsp-sec{padding:46px 0;border-bottom:1px solid var(--border-subtle);scroll-margin-top:104px}
/* The section heading. Its element is h2-h4 depending on where the section
   sits in the argument (see 'levels' in the page config), so the shared
   treatment hangs off .wsp-sec-h and only the scale steps down by level.
   A sub-section indents and loses the full-width rule, so the hierarchy is
   legible at a glance and not only in the outline. The indent alone carries
   it: see the note on the removed rails below. */
.wsp-sec>.wsp-sec-h{font-family:var(--font-display);font-weight:800;font-size:clamp(25px,3vw,34px);line-height:1.12;letter-spacing:-.02em;color:var(--midnight-900);margin:0 0 20px;text-wrap:pretty}
.wsp-sec--h3>.wsp-sec-h{font-size:clamp(20px,2.2vw,25px);font-weight:700;letter-spacing:-.015em}
.wsp-sec--h4>.wsp-sec-h{font-size:clamp(17px,1.7vw,19.5px);font-weight:700;letter-spacing:-.01em;color:var(--gray-700)}
.wsp-sec--h3,.wsp-sec--h4{border-bottom:0;padding:30px 0 0}
/* Indent only. These used to carry a border-left as well - 2px at h3, 1px at
   h4 - and the last sub-section of a run restored a border-bottom. With the
   full-width rule that .wsp-sec already draws above the run, those three
   hairlines are the same colour and meet at the corners, so a run of
   sub-sections read as a three-sided box drawn around the body copy. Nobody
   designed that box; it was the sum of three separate rules.

   It was also inconsistent, which is how it got noticed. The bottom edge came
   from :has(+ .wsp-sec--h2), which only matches when the next element really
   is the next topic. Where a module sits between the run and the next topic -
   the video on /winery-seo/, the guide on the dental page - the selector does
   not match and the box stays open. Winery drew 9 runs and closed 7; dental
   drew 12 and closed 11.

   Removing the two rails and the terminator removes the box on both pages and
   the inconsistency with it. The 38px of air before the next topic stays, and
   so does the full-width rule between topics, so the page still reads as
   separate bands. */
.wsp-sec--h3{padding-left:20px}
.wsp-sec--h4{padding-left:20px;margin-left:20px}
.wsp-sec--h3:has(+ .wsp-sec--h2),.wsp-sec--h4:has(+ .wsp-sec--h2){padding-bottom:38px}
.wsp-sec h3{font-family:var(--font-display);font-weight:700;font-size:20px;line-height:1.2;letter-spacing:-.01em;color:var(--midnight-900);margin:32px 0 10px}
.wsp-sec p{font-family:var(--font-body);font-size:18px;line-height:1.75;color:var(--fg-primary);margin:0 0 18px;text-wrap:pretty}
.wsp-sec p:last-child{margin-bottom:0}
.wsp-sec p strong{font-weight:700;color:var(--midnight-900)}
.wsp-sec em{font-style:italic;color:var(--gray-700)}

/* tiered / stepped lists that the copy already implies */
.wsp-list{list-style:none;margin:8px 0 22px;padding:0;display:flex;flex-direction:column;gap:16px;counter-reset:wsp}
.wsp-list>li{position:relative;padding-left:38px;font-family:var(--font-body);font-size:18px;line-height:1.7;color:var(--fg-primary)}
.wsp-list>li::before{counter-increment:wsp;content:counter(wsp,decimal-leading-zero);position:absolute;left:0;top:4px;font-family:var(--font-mono);font-size:11px;font-weight:600;letter-spacing:.04em;color:var(--hero-600)}
.wsp-list>li strong{display:block;font-family:var(--font-display);font-weight:700;font-size:18px;letter-spacing:-.01em;color:var(--midnight-900);margin-bottom:8px}
.wsp-list>li p{margin:0 0 12px}
.wsp-list>li p:last-child{margin-bottom:0}
.wsp-dl{margin:8px 0 22px;padding:0;display:flex;flex-direction:column}
.wsp-dl>div{padding:16px 0;border-top:1px solid var(--border-subtle);display:grid;grid-template-columns:minmax(0,190px) minmax(0,1fr);gap:6px 24px}
.wsp-dl>div:last-child{border-bottom:1px solid var(--border-subtle)}
.wsp-dl dt{font-family:var(--font-display);font-weight:700;font-size:16px;line-height:1.25;letter-spacing:-.005em;color:var(--midnight-900)}
.wsp-dl dd{margin:0;font-family:var(--font-body);font-size:16.5px;line-height:1.6;color:var(--fg-secondary)}

/* ---------- inline internal links — obviously clickable, not shouting ------ */
.wsp-sec a:not(.wb-btn):not(.wsp-spoke),.wsp-lede a{color:var(--hero-700);font-weight:600;background-image:linear-gradient(var(--hero-200),var(--hero-200));background-position:0 100%;background-repeat:no-repeat;background-size:100% 2px;padding-bottom:1px;transition:background-size var(--dur-base) var(--ease-out),color var(--dur-base)}
.wsp-sec a:not(.wb-btn):not(.wsp-spoke):hover,.wsp-lede a:hover{color:var(--hero-800);background-size:100% 100%;background-image:linear-gradient(var(--hero-50),var(--hero-50))}

/* ---------- PULL QUOTES — break the column into the left gutter ---------- */
.wsp-pull{margin:34px 0;padding:2px 0 2px 24px;border-left:2px solid var(--hero-500)}
.wsp-pull p{font-family:var(--font-display);font-weight:600;font-size:clamp(21px,2.3vw,27px);line-height:1.28;letter-spacing:-.015em;color:var(--midnight-900);margin:0;text-wrap:pretty}
.wsp-pull cite{display:block;margin-top:12px;font-family:var(--font-mono);font-size:10.5px;letter-spacing:.12em;text-transform:uppercase;color:var(--gray-400);font-style:normal}

/* a heavier statement block for the two or three hardest lines */
.wsp-say{position:relative;overflow:hidden;margin:38px 0;padding:34px 32px;border-radius:var(--radius-lg);background:radial-gradient(130% 120% at 88% -10%,var(--midnight-700),var(--midnight-950))}
.wsp-say img{position:absolute;right:-18px;top:-24px;width:130px;opacity:.09;pointer-events:none}
.wsp-say p{position:relative;font-family:var(--font-display);font-weight:800;font-size:clamp(22px,2.6vw,30px);line-height:1.18;letter-spacing:-.02em;color:#fff;margin:0;max-width:30ch}
.wsp-say .accent{color:var(--hero-400)}

/* ---------- stat call-out ---------- */
.wsp-stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:1px;margin:32px 0;background:var(--border-subtle);border:1px solid var(--border-subtle);border-radius:var(--radius-lg);overflow:hidden}
.wsp-stat{background:#fff;padding:20px 18px}
.wsp-stat .v{font-family:var(--font-display);font-weight:900;font-size:clamp(26px,3.2vw,36px);line-height:1;letter-spacing:-.03em;color:var(--hero-600);font-variant-numeric:tabular-nums}
.wsp-stat .k{margin-top:9px;font-family:var(--font-body);font-size:13px;line-height:1.45;color:var(--fg-secondary)}
.wsp-stat .src{margin-top:8px;font-family:var(--font-mono);font-size:9.5px;letter-spacing:.06em;text-transform:uppercase;color:var(--gray-400)}

/* ============================================================================
   FIGURES / MEDIA — bleed past the measure on wide screens
   ============================================================================ */
@media (min-width:1180px){
  .wsp-wide{width:calc(100% + 84px);margin-right:-84px}
  .wsp-pull{width:calc(100% + 84px);margin-right:-84px}
}

/* ---------- DATA TABLE: 16 rows, 3 columns, no horizontal scroll ---------- */
.wsp-table{margin:34px 0}
.wsp-table-head{display:flex;flex-wrap:wrap;align-items:baseline;gap:8px 14px;margin-bottom:14px}
.wsp-table-head .k{font-family:var(--font-mono);font-size:10.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--hero-600)}
.wsp-table-head h3{font-family:var(--font-display);font-weight:800;font-size:19px;line-height:1.2;color:var(--midnight-900);margin:0}
.wsp-kw{width:100%;table-layout:fixed;border-collapse:collapse;font-variant-numeric:tabular-nums;background:#fff;border:1px solid var(--border-subtle);border-radius:var(--radius-lg);overflow:hidden}
.wsp-kw thead th:nth-child(1){width:42%}
.wsp-kw thead th:nth-child(2){width:46%}
.wsp-kw thead th:nth-child(3){width:12%}
.wsp-kw caption{caption-side:bottom;text-align:left;font-family:var(--font-mono);font-size:10.5px;line-height:1.6;letter-spacing:.04em;color:var(--gray-400);padding-top:12px}
.wsp-kw thead th{font-family:var(--font-mono);font-size:9.5px;font-weight:600;letter-spacing:.11em;text-transform:uppercase;color:var(--gray-500);text-align:left;padding:11px 14px;background:var(--gray-50);border-bottom:1px solid var(--border-subtle);white-space:nowrap}
.wsp-kw thead th.r{text-align:right}
.wsp-kw thead th.c{text-align:center}
.wsp-kw tbody th{text-align:left;font-family:var(--font-body);font-weight:600;font-size:15px;color:var(--midnight-900);padding:0 10px 0 14px;line-height:1.25}
.wsp-kw tbody tr{border-bottom:1px solid var(--gray-100)}
.wsp-kw tbody tr:last-child{border-bottom:none}
.wsp-kw tbody tr:hover{background:var(--gray-50)}
.wsp-kw td{padding:9px 10px;vertical-align:middle}
.wsp-kw td.vol{padding-right:14px;display:grid;grid-template-columns:minmax(0,1fr) 56px;align-items:center;gap:10px}
.wsp-kw td.vol .bar{height:22px;border-radius:3px;background:var(--hero-100);min-width:2px}
.wsp-kw tbody tr.is-open td.vol .bar{background:var(--hero-200)}
.wsp-kw td.vol .num{text-align:right;font-family:var(--font-mono);font-size:13px;font-weight:500;color:var(--midnight-900)}
.wsp-kw td.kd{padding-right:14px;text-align:right}
.wsp-chip{display:inline-flex;align-items:center;justify-content:center;min-width:32px;font-family:var(--font-mono);font-size:12px;font-weight:600;padding:4px 7px;border-radius:var(--radius-sm);border:1px solid transparent}
.wsp-chip.t-open{background:var(--hero-50);color:var(--hero-700);border-color:var(--hero-100)}
.wsp-chip.t-mid{background:var(--gray-100);color:var(--gray-700);border-color:var(--gray-200)}
.wsp-chip.t-wall{background:#F8F1E4;color:#8A6522;border-color:#EADCC2}
.wsp-kw tfoot td{padding:13px 14px;background:var(--midnight-900);color:#fff;font-family:var(--font-body);font-size:14px;line-height:1.45}
.wsp-kw tfoot .big{font-family:var(--font-mono);font-weight:600;color:var(--electric-400)}
.wsp-legend{display:flex;flex-wrap:wrap;gap:8px 16px;margin-top:12px}
.wsp-legend span{display:inline-flex;align-items:center;gap:7px;font-family:var(--font-mono);font-size:10px;letter-spacing:.07em;text-transform:uppercase;color:var(--gray-500)}
.wsp-legend i{width:10px;height:10px;border-radius:3px;display:block}

/* ---------- COMPARISON TABLE: 3 rows, labelled-card collapse on phones ---- */
.wsp-cmp{width:100%;table-layout:fixed;border-collapse:collapse;background:#fff;border:1px solid var(--border-subtle);border-radius:var(--radius-lg);overflow:hidden;font-variant-numeric:tabular-nums}
.wsp-cmp thead th:nth-child(1){width:16%}
.wsp-cmp thead th:nth-child(2){width:23%}
.wsp-cmp thead th:nth-child(3){width:20%}
.wsp-cmp thead th:nth-child(4){width:21%}
.wsp-cmp thead th:nth-child(5){width:20%}
.wsp-cmp caption{caption-side:bottom;text-align:left;font-family:var(--font-mono);font-size:10.5px;line-height:1.6;color:var(--gray-400);padding-top:12px}
.wsp-cmp thead th{font-family:var(--font-mono);font-size:9.5px;font-weight:600;letter-spacing:.11em;text-transform:uppercase;color:var(--gray-500);text-align:left;padding:11px 14px;background:var(--gray-50);border-bottom:1px solid var(--border-subtle)}
.wsp-cmp tbody tr+tr{border-top:1px solid var(--gray-100)}
.wsp-cmp tbody th{text-align:left;padding:14px;vertical-align:top}
.wsp-cmp tbody th .nm{display:block;font-family:var(--font-display);font-weight:800;font-size:16px;color:var(--midnight-900);line-height:1.2}
.wsp-cmp tbody th .dr{display:block;margin-top:4px;font-family:var(--font-mono);font-size:10px;letter-spacing:.06em;text-transform:uppercase;color:var(--gray-400)}
.wsp-cmp td{padding:14px;vertical-align:top;font-family:var(--font-body);font-size:14.5px;line-height:1.45;color:var(--fg-secondary)}
.wsp-cmp td .pg{color:var(--midnight-900);font-weight:600}
.wsp-cmp td .zero{display:inline-flex;align-items:flex-start;gap:6px;font-family:var(--font-mono);font-size:11.5px;line-height:1.45;font-weight:600;color:var(--hero-700);background:var(--hero-50);border:1px solid var(--hero-100);border-radius:var(--radius-sm);padding:5px 8px}
.wsp-cmp td .zero svg{flex:0 0 auto;margin-top:1px}

/* ---------- link-wall bars (Zinfandel) ---------- */
.wsp-wall{margin:30px 0;border:1px solid var(--border-subtle);border-radius:var(--radius-lg);background:#fff;padding:20px 20px 16px;overflow:hidden}
.wsp-wall .hd{font-family:var(--font-mono);font-size:10.5px;letter-spacing:.12em;text-transform:uppercase;color:var(--gray-500);margin-bottom:16px}
.wsp-wall ul{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:11px}
.wsp-wall li{display:grid;grid-template-columns:minmax(0,1fr) 62px;align-items:center;gap:12px}
.wsp-wall .nm{font-family:var(--font-body);font-size:14px;color:var(--midnight-900);display:flex;align-items:baseline;gap:8px;min-width:0}
.wsp-wall .nm .dr{font-family:var(--font-mono);font-size:10px;letter-spacing:.05em;text-transform:uppercase;color:var(--gray-400);flex:0 0 auto}
.wsp-wall .track{grid-column:1/-1;height:8px;border-radius:99px;background:var(--gray-100);overflow:hidden}
.wsp-wall .track span{display:block;height:100%;border-radius:99px;background:var(--gray-400)}
.wsp-wall li.is-zero .track span{background:var(--hero-500)}
.wsp-wall .ct{font-family:var(--font-mono);font-size:12px;font-weight:600;text-align:right;color:var(--gray-600)}
.wsp-wall li.is-zero .ct{color:var(--hero-700)}
.wsp-wall .ft{margin:16px 0 0;font-family:var(--font-body);font-size:13.5px;line-height:1.55;color:var(--fg-secondary);display:flex;gap:9px}
.wsp-wall .ft svg{color:var(--hero-500);flex:0 0 auto;margin-top:2px}

/* ============================================================================
   VIDEO BLOCK — first-class element, own framing + caption + empty state
   ============================================================================ */
.wsp-video{margin:56px 0;scroll-margin-top:104px}
.wsp-video-top{display:flex;flex-wrap:wrap;align-items:baseline;gap:8px 14px;margin-bottom:16px}
.wsp-video-top .k{display:inline-flex;align-items:center;gap:8px;white-space:nowrap;font-family:var(--font-mono);font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--hero-600)}
.wsp-video-top .k img{height:12px}
.wsp-video h2{font-family:var(--font-display);font-weight:800;font-size:clamp(21px,2.4vw,27px);line-height:1.15;letter-spacing:-.02em;color:var(--midnight-900);margin:0;flex:1 1 100%}
.wsp-frame{position:relative;aspect-ratio:16/9;border-radius:var(--radius-lg);overflow:hidden;background:radial-gradient(130% 130% at 74% 0%,var(--midnight-700),var(--midnight-950));box-shadow:var(--shadow-lg)}
/* The video and podcast empty states were styled here: a dashed ring, a striped
   dead track and the words "Slot reserved". Both slots now render nothing at all
   until an asset is attached, so these rules had no markup left to match. */
.wsp-frame::after{content:'';position:absolute;inset:0;border-radius:var(--radius-lg);border:1px solid rgba(255,255,255,.1);pointer-events:none}
.wsp-frame img.poster{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:.45}
.wsp-frame-bolt{position:absolute;right:5%;top:11%;width:110px;opacity:.1;pointer-events:none}
.wsp-play{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);z-index:2;width:74px;height:74px;border-radius:50%;border:none;cursor:pointer;background:var(--hero-500);color:#fff;display:flex;align-items:center;justify-content:center;box-shadow:var(--shadow-brand);transition:transform var(--dur-base) var(--ease-out),background var(--dur-base)}
.wsp-play::after{content:'';position:absolute;inset:-10px;border-radius:50%;border:2px solid rgba(255,255,255,.22)}
.wsp-play:hover{transform:translate(-50%,-50%) scale(1.07);background:var(--hero-600)}
.wsp-frame-meta{position:absolute;left:24px;right:24px;bottom:20px;z-index:2}
.wsp-frame-meta .len{display:inline-flex;align-items:center;gap:7px;font-family:var(--font-mono);font-size:11.5px;color:#c2cbe0}

/* reserved / empty state — designed, not a gray box */
.wsp-cap{margin:14px 0 0;display:grid;grid-template-columns:minmax(0,1fr);gap:6px}
.wsp-cap .kicker{font-family:var(--font-mono);font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--hero-600)}
.wsp-cap p{font-family:var(--font-body);font-size:14px;line-height:1.6;color:var(--fg-muted);margin:0}
.wsp-cap a{color:var(--hero-700);font-weight:600}

/* lightbox */
.wsp-lb{position:fixed;inset:0;z-index:200;background:rgba(14,22,38,.76);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);display:flex;align-items:center;justify-content:center;padding:28px}
.wsp-lb-inner{width:100%;max-width:940px;position:relative}
.wsp-lb-close{position:absolute;top:-46px;right:0;width:38px;height:38px;border-radius:50%;border:none;cursor:pointer;background:rgba(255,255,255,.12);color:#fff;display:flex;align-items:center;justify-content:center}
.wsp-lb-close:hover{background:rgba(255,255,255,.24)}
/* The mount the script builds the iframe into. The iframe carries width/height
   attributes so it has an intrinsic ratio before any CSS applies; these rules
   make it fill the box rather than sitting at 560px inside a 940px panel. */
.wsp-lb-mount{display:block;width:100%;aspect-ratio:16/9;background:#000;border-radius:var(--radius-lg);overflow:hidden}
.wsp-lb-mount iframe{display:block;width:100%;height:100%;border:0}

/* ============================================================================
   PODCAST MODULE
   ============================================================================ */
.wsp-pod{position:relative;overflow:hidden;border-radius:var(--radius-lg);background:linear-gradient(180deg,var(--midnight-900),var(--midnight-950));box-shadow:var(--shadow-md);padding:18px 20px;margin:0 0 44px}
.wsp-pod::before{content:'';position:absolute;right:-60px;top:-90px;width:260px;height:260px;background:radial-gradient(circle,rgba(99,117,255,.22),transparent 62%);pointer-events:none}
/* The real <audio> element behind the custom bar. It has no controls attribute,
   so nothing paints it today — declared anyway so it can never take layout. */
.wsp-pod-audio{display:none}
.wsp-pod-top{position:relative;display:flex;align-items:center;gap:14px}
.wsp-pod-btn{flex:0 0 auto;width:48px;height:48px;border-radius:50%;border:none;cursor:pointer;background:var(--hero-500);color:#fff;display:flex;align-items:center;justify-content:center;box-shadow:var(--shadow-brand);transition:transform var(--dur-base) var(--ease-out),background var(--dur-base)}
.wsp-pod-btn:hover{background:var(--hero-600);transform:scale(1.05)}
.wsp-pod-btn:active{transform:scale(.94)}
.wsp-pod-btn:disabled{background:rgba(255,255,255,.08);box-shadow:none;color:#5d6a85;cursor:not-allowed;border:1.5px dashed rgba(255,255,255,.2)}
.wsp-pod-id{flex:1 1 auto;min-width:0}
.wsp-pod-show{display:flex;align-items:center;gap:8px;font-family:var(--font-mono);font-size:10px;letter-spacing:.15em;text-transform:uppercase;color:var(--electric-400);margin-bottom:6px}
.wsp-pod-show .ep{color:#6f7c97}
.wsp-pod-id h2{font-family:var(--font-display);font-weight:700;font-size:16px;line-height:1.22;color:#fff;margin:0}
.wsp-pod-home{flex:0 0 auto;display:inline-flex;align-items:center;gap:7px;white-space:nowrap;font-family:var(--font-display);font-weight:700;font-size:11.5px;letter-spacing:.04em;text-transform:uppercase;color:#c8d1e4;border:1px solid rgba(255,255,255,.18);border-radius:var(--radius-pill);padding:8px 13px;transition:color var(--dur-base),border-color var(--dur-base),background var(--dur-base)}
.wsp-pod-home:hover{color:#fff;border-color:var(--hero-400);background:rgba(99,117,255,.16)}
.wsp-pod-bar{position:relative;display:flex;align-items:center;gap:12px;margin-top:15px}
.wsp-pod-track{flex:1 1 auto;height:5px;border-radius:99px;background:rgba(255,255,255,.13);overflow:hidden;cursor:pointer}
.wsp-pod-track span{display:block;height:100%;width:0;border-radius:99px;background:var(--electric-500)}
.wsp-pod-time{flex:0 0 auto;font-family:var(--font-mono);font-size:11.5px;color:#8a96b0;font-variant-numeric:tabular-nums}
.wsp-pod-note{position:relative;margin:14px 0 0;font-family:var(--font-mono);font-size:10.5px;line-height:1.6;letter-spacing:.03em;color:#7f8ca6;display:flex;gap:8px}
.wsp-pod-note svg{color:var(--hero-400);flex:0 0 auto;margin-top:1px}

/* ============================================================================
   GUIDE DOWNLOAD — same component, two placements
   ============================================================================ */
.wsp-guide{display:grid;grid-template-columns:216px minmax(0,1fr);margin:48px 0;border:1px solid var(--border-subtle);border-radius:var(--radius-lg);overflow:hidden;background:#fff;box-shadow:var(--shadow-md);scroll-margin-top:104px}
.wsp-guide-cover{position:relative;display:flex;align-items:center;justify-content:center;padding:30px 24px;background:radial-gradient(130% 95% at 26% 0%,var(--hero-600),var(--midnight-900))}
.wsp-guide-doc{width:100%;aspect-ratio:3/4;border-radius:6px;background:linear-gradient(162deg,#fff,#EDF0F7);box-shadow:0 18px 40px rgba(8,12,24,.42);transform:rotate(-3deg);padding:18px 16px;display:flex;flex-direction:column;border:1px solid rgba(255,255,255,.6)}
.wsp-guide-doc img{height:22px;margin-bottom:14px}
.wsp-guide-doc .t{font-family:var(--font-display);font-weight:900;font-size:16px;line-height:1.02;text-transform:uppercase;letter-spacing:-.01em;color:var(--midnight-900)}
.wsp-guide-doc .r{margin-top:10px;width:38px;height:2px;background:var(--hero-500)}
.wsp-guide-doc .s{margin-top:auto;font-family:var(--font-mono);font-size:8.5px;letter-spacing:.1em;text-transform:uppercase;color:var(--hero-600)}
.wsp-guide-body{padding:26px 28px}
.wsp-guide-k{display:inline-flex;align-items:center;gap:8px;white-space:nowrap;font-family:var(--font-mono);font-size:10.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--hero-600);margin-bottom:10px}
.wsp-guide-body h2{font-family:var(--font-display);font-weight:800;font-size:23px;line-height:1.12;letter-spacing:-.015em;color:var(--midnight-900);margin:0 0 8px}
.wsp-guide-body>p{font-family:var(--font-body);font-size:15px;line-height:1.6;color:var(--fg-secondary);margin:0 0 16px}
.wsp-guide-list{list-style:none;margin:0 0 18px;padding:0;display:grid;grid-template-columns:1fr 1fr;gap:8px 18px}
.wsp-guide-list li{display:flex;align-items:flex-start;gap:8px;font-family:var(--font-body);font-size:13.5px;line-height:1.4;color:var(--fg-secondary)}
.wsp-guide-list svg{color:var(--hero-500);flex:0 0 auto;margin-top:2px}
.wsp-guide-form{display:flex;gap:10px;flex-wrap:wrap}
.wsp-lfield{flex:1 1 220px;display:flex;align-items:center;gap:9px;border:1.5px solid var(--gray-200);border-radius:var(--radius-md);padding:0 13px;transition:border-color var(--dur-base),box-shadow var(--dur-base)}
.wsp-lfield:focus-within{border-color:var(--hero-500);box-shadow:var(--shadow-glow)}
.wsp-lfield svg{color:var(--gray-400);flex:0 0 auto}
.wsp-lfield input{flex:1 1 auto;min-width:0;border:none;outline:none;font-family:var(--font-body);font-size:14.5px;padding:12px 0;color:var(--midnight-900);background:none}
.wsp-guide-fine{margin:12px 0 0;font-family:var(--font-mono);font-size:10px;letter-spacing:.04em;color:var(--gray-400);display:flex;align-items:center;gap:7px}
.wsp-guide-ok{display:flex;align-items:flex-start;gap:12px;padding:15px 16px;background:var(--success-bg);border-radius:var(--radius-md);font-family:var(--font-body);font-size:14px;line-height:1.55;color:var(--gray-700)}
.wsp-guide-ok svg{color:var(--success);flex:0 0 auto;margin-top:2px}
.wsp-guide-ok strong{font-family:var(--font-display);color:var(--midnight-900)}

/* ============================================================================
   SPOKE CARD — hands off down the silo, inline in the reading column
   ============================================================================ */
.wsp-spoke{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:18px;margin:36px 0;padding:20px 22px;border:1px solid var(--border-subtle);border-left:3px solid var(--hero-500);border-radius:var(--radius-lg);background:var(--gray-50);transition:transform var(--dur-base) var(--ease-out),box-shadow var(--dur-base) var(--ease-out),background var(--dur-base)}
.wsp-spoke:hover{transform:translateY(-2px);box-shadow:var(--shadow-md);background:#fff}
.wsp-spoke-ico{width:42px;height:42px;border-radius:var(--radius-md);background:#fff;border:1px solid var(--border-subtle);display:flex;align-items:center;justify-content:center;color:var(--hero-600)}
.wsp-spoke .lbl{font-family:var(--font-mono);font-size:9.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--gray-400);display:block;margin-bottom:5px}
.wsp-spoke .ttl{font-family:var(--font-display);font-weight:800;font-size:17px;line-height:1.2;letter-spacing:-.01em;color:var(--midnight-900);display:block}
.wsp-spoke .dsc{font-family:var(--font-body);font-size:13.5px;line-height:1.45;color:var(--fg-secondary);display:block;margin-top:4px}
.wsp-spoke .go{color:var(--hero-600);display:flex;align-items:center;transition:transform var(--dur-base)}
.wsp-spoke:hover .go{transform:translateX(4px)}

/* ---------- slim mid-page audit strip (repeating conversion) ---------- */
.wsp-strip{position:relative;overflow:hidden;display:flex;flex-wrap:wrap;align-items:center;gap:16px 22px;margin:44px 0;padding:20px 24px;border-radius:var(--radius-lg);background:linear-gradient(100deg,var(--midnight-900),var(--midnight-800))}
.wsp-strip img.bolt{position:absolute;right:12px;top:-16px;width:92px;opacity:.1;pointer-events:none}
.wsp-strip .txt{position:relative;flex:1 1 260px;min-width:0}
.wsp-strip .k{font-family:var(--font-mono);font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--electric-400);margin-bottom:6px}
.wsp-strip p{font-family:var(--font-display);font-weight:700;font-size:17px;line-height:1.25;color:#fff;margin:0}
.wsp-strip .wb-btn{position:relative;flex:0 0 auto}

/* ============================================================================
   CLOSING CTA — full-width audit card
   ============================================================================ */
.wsp-final{position:relative;overflow:hidden;background:var(--midnight-950);padding:88px 0;scroll-margin-top:80px}
.wsp-final-art{position:absolute;inset:0;z-index:0;opacity:.22;filter:grayscale(.4)}
.wsp-final-art image-slot,.wsp-final-art img{width:100%;height:100%;display:block;object-fit:cover}
.wsp-final-veil{position:absolute;inset:0;z-index:1;background:linear-gradient(90deg,var(--midnight-950) 30%,rgba(18,26,43,.7))}
.wsp-final-glow{position:absolute;left:22%;top:-38%;width:760px;height:760px;z-index:1;transform:translateX(-50%);background:radial-gradient(circle,rgba(99,117,255,.3),transparent 60%);pointer-events:none}
.wsp-final-inner{position:relative;z-index:2;max-width:720px}
.wsp-final-k{display:inline-flex;align-items:center;gap:10px;white-space:nowrap;font-family:var(--font-mono);font-weight:600;font-size:12px;letter-spacing:.17em;text-transform:uppercase;color:var(--hero-400);margin-bottom:16px}
.wsp-final-k img{height:15px}
.wsp-final h2{font-family:var(--font-display);font-weight:900;text-transform:uppercase;font-size:clamp(30px,4.4vw,52px);line-height:.99;letter-spacing:-.025em;color:#fff;margin:0 0 18px}
.wsp-final h2 .accent{color:var(--hero-400)}
.wsp-final p{font-size:var(--text-lg);line-height:1.6;color:#aeb9cf;max-width:56ch;margin:0 0 8px}
.wsp-final-form{display:flex;gap:12px;flex-wrap:wrap;align-items:center;margin:28px 0 16px;max-width:560px}
.wsp-final-form .wsp-field{flex:1 1 250px;border-width:1.5px}
.wsp-final-form .wsp-field input{padding:14px 0;font-size:15px}
.wsp-final-foot{display:flex;flex-wrap:wrap;align-items:center;gap:10px 22px;font-family:var(--font-body);font-size:14px;color:#8a96b0}
.wsp-final-foot svg{color:var(--hero-400)}
.wsp-final-ok{display:inline-flex;align-items:center;gap:14px;background:rgba(31,180,122,.12);border:1px solid rgba(31,180,122,.3);border-radius:var(--radius-lg);padding:20px 24px;margin:26px 0 16px}
.wsp-final-ok .ico{flex:0 0 auto;width:44px;height:44px;border-radius:50%;background:rgba(31,180,122,.2);color:var(--success);display:flex;align-items:center;justify-content:center}
.wsp-final-ok strong{display:block;font-family:var(--font-display);font-size:18px;color:#fff;margin-bottom:3px}
.wsp-final-ok span{font-size:14px;color:#aeb9cf}

/* ============================================================================
   FOOTER TRANSITION — hand off to the rest of the site, don't dead-end
   ============================================================================ */
.wsp-next{background:var(--gray-50);border-top:1px solid var(--border-subtle);padding:72px 0}
.wsp-next-head{max-width:620px;margin-bottom:38px}
.wsp-next-head .k{font-family:var(--font-mono);font-size:11px;letter-spacing:.15em;text-transform:uppercase;color:var(--hero-600);margin-bottom:12px}
.wsp-next-head h2{font-family:var(--font-display);font-weight:800;font-size:clamp(24px,3vw,34px);line-height:1.12;letter-spacing:-.02em;color:var(--midnight-900);margin:0 0 10px}
.wsp-next-head p{font-family:var(--font-body);font-size:16.5px;line-height:1.6;color:var(--fg-secondary);margin:0}
.wsp-next-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:32px}
.wsp-next-col h3{font-family:var(--font-mono);font-size:10.5px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;color:var(--gray-500);margin:0 0 4px;padding-bottom:12px;border-bottom:1px solid var(--border-subtle)}
.wsp-next-col p.sub{font-family:var(--font-body);font-size:13px;line-height:1.5;color:var(--fg-muted);margin:12px 0 4px}
.wsp-next-col ul{list-style:none;margin:0;padding:0}
.wsp-next-col li{border-bottom:1px solid var(--border-subtle)}
.wsp-next-col a{display:flex;align-items:center;gap:10px;padding:13px 2px;font-family:var(--font-body);font-weight:600;font-size:15px;color:var(--midnight-900);transition:color var(--dur-fast),padding-left var(--dur-base)}
.wsp-next-col a:hover{color:var(--hero-600);padding-left:6px}
.wsp-next-col a .sm{font-family:var(--font-body);font-weight:400;font-size:13px;color:var(--fg-muted);margin-left:auto;text-align:right;flex:0 0 auto}
.wsp-next-col a svg{color:var(--hero-400);flex:0 0 auto}

/* ============================================================================
   MOBILE — primary case. Action bar + contents sheet.
   ============================================================================ */
.wsp-bar{display:none;position:fixed;left:0;right:0;bottom:0;z-index:120;background:rgba(18,26,43,.94);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);border-top:1px solid rgba(255,255,255,.12);padding:9px 12px calc(9px + env(safe-area-inset-bottom));gap:9px}
.wsp-bar button,.wsp-bar a{flex:1 1 0;display:flex;align-items:center;justify-content:center;gap:8px;min-height:46px;border-radius:var(--radius-md);border:1px solid rgba(255,255,255,.18);background:rgba(255,255,255,.06);color:#fff;font-family:var(--font-display);font-weight:700;font-size:13px;letter-spacing:.03em;text-transform:uppercase;cursor:pointer}
.wsp-bar .is-primary{background:var(--hero-500);border-color:var(--hero-500);box-shadow:var(--shadow-brand)}
.wsp-bar .where{display:block;font-family:var(--font-mono);font-size:9px;letter-spacing:.1em;color:#9aa7c0;text-transform:uppercase;font-weight:400;margin-top:2px}
.wsp-bar .lbl-wrap{display:flex;flex-direction:column;align-items:flex-start;line-height:1.15}

.wsp-sheet{display:none;position:fixed;inset:0;z-index:140}
.wsp-sheet.is-open{display:block}
.wsp-sheet-scrim{position:absolute;inset:0;background:rgba(14,22,38,.6);backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px)}
.wsp-sheet-panel{position:absolute;left:0;right:0;bottom:0;max-height:88vh;display:flex;flex-direction:column;background:#fff;border-radius:var(--radius-xl) var(--radius-xl) 0 0;box-shadow:0 -18px 48px rgba(8,12,24,.4);animation:wsp-up .24s var(--ease-out)}
@keyframes wsp-up{from{transform:translateY(18px);opacity:.6}to{transform:translateY(0);opacity:1}}
.wsp-sheet-head{display:flex;align-items:center;gap:12px;padding:16px 18px 14px;border-bottom:1px solid var(--border-subtle)}
.wsp-sheet-head .t{font-family:var(--font-display);font-weight:800;font-size:16px;color:var(--midnight-900)}
.wsp-sheet-head .c{font-family:var(--font-mono);font-size:10.5px;letter-spacing:.1em;text-transform:uppercase;color:var(--gray-400)}
.wsp-sheet-head button{margin-left:auto;width:34px;height:34px;border-radius:50%;border:1px solid var(--border-subtle);background:#fff;color:var(--gray-600);display:flex;align-items:center;justify-content:center;cursor:pointer}
.wsp-sheet-body{overflow-y:auto;padding:8px;-webkit-overflow-scrolling:touch}
@media (prefers-reduced-motion:reduce){.wsp-sheet-panel{animation:none}}

@media (max-width:1080px){
  .wsp-layout{grid-template-columns:1fr;gap:0;padding:36px 0 72px}
  .wsp-rail{display:none}
  .wsp-main{max-width:720px;margin:0 auto}
  .wsp-bar{display:flex}
  /* Room for the bar, on the pages that have one. Only the hub renders it -
     a column page's rail moves under its article instead - so an unqualified
     rule leaves 72px of blank page below the footer on the other 23. */
  body:has(.wsp-bar){padding-bottom:72px}
  .wsp-resume{top:60px}
  /* The bar and its sheet only exist below this width, which means they only
     ever meet a thumb. The sheet's close button was drawn at 34px. */
  .wsp-sheet-head button{width:44px;height:44px}
}
@media (max-width:900px){
  /* comparison table: 3 rows become 3 labelled cards.

     This was written at 680px, which left the 681-900 band showing the full
     five-column table: table-layout is fixed, so at 768px that is five 149px
     cells and sentences setting nine characters to a line. The cards are what
     that band wants too. */
  .wsp-cmp,.wsp-cmp tbody,.wsp-cmp tr,.wsp-cmp th,.wsp-cmp td{display:block;width:auto}
  .wsp-cmp thead{display:none}
  .wsp-cmp{border:none;background:none;overflow:visible}
  .wsp-cmp tbody tr{border:1px solid var(--border-subtle);border-radius:var(--radius-lg);background:#fff;padding:4px 0;margin-bottom:12px}
  .wsp-cmp tbody tr+tr{border-top:1px solid var(--border-subtle)}
  .wsp-cmp tbody th{padding:14px 16px 10px;border-bottom:1px solid var(--gray-100)}
  .wsp-cmp td{padding:9px 16px;display:grid;grid-template-columns:104px minmax(0,1fr);gap:14px;align-items:baseline}
  .wsp-cmp td::before{content:attr(data-l);font-family:var(--font-mono);font-size:9.5px;letter-spacing:.1em;text-transform:uppercase;color:var(--gray-400)}
  /* Every part of the table is display:block above, but the caption was left a
     table-caption belonging to a table that no longer exists. Chromium wraps it
     in an anonymous table and shrink-wraps that: the footnote under this table
     was rendering 66px wide and 189px tall, one word to a line, down the left
     edge of the page. */
  .wsp-cmp caption{display:block;padding:4px 2px 0}

  .wsp-hero{min-height:auto}
  .wsp-hero-inner{padding:124px 0 0}
  .wsp-hero-media{opacity:.28}
  .wsp-silo-links{margin-left:0}
  .wsp-guide{grid-template-columns:1fr}
  .wsp-guide-cover{padding:26px 26px 0}
  .wsp-guide-doc{max-width:190px;margin:0 auto;transform:none}
  .wsp-guide-list{grid-template-columns:1fr}
  .wsp-dl>div{grid-template-columns:1fr}
}
@media (max-width:680px){
  .wsp-wrap{padding:0 18px}
  .wsp-hero h1{font-size:clamp(25px,6.8vw,34px);max-width:none}
  .wsp-hero-sub{font-size:16.5px}
  .wsp-hero-cta .wb-btn{width:100%}
  .wsp-lede p{font-size:18px}
  .wsp-sec{padding:38px 0}
  .wsp-sec p,.wsp-list>li{font-size:17px;line-height:1.72}
  .wsp-say{padding:26px 22px}
  .wsp-spoke{grid-template-columns:auto minmax(0,1fr);gap:14px}
  .wsp-spoke .go{display:none}
  .wsp-strip{padding:20px}
  .wsp-strip .wb-btn{width:100%}
  .wsp-pod-top{flex-wrap:wrap}
  .wsp-pod-home{order:3;width:100%;justify-content:center}
  .wsp-final{padding:64px 0}
  .wsp-next{padding:56px 0}

  /* keyword table: keeps three real columns, just tighter */
  .wsp-kw tbody th{font-size:14px;padding-left:12px;line-height:1.2}
  .wsp-kw td{padding:8px 6px}
  .wsp-kw td.vol{padding-right:6px;grid-template-columns:minmax(0,1fr) 46px;gap:6px}
  .wsp-kw td.vol .bar{height:20px}
  .wsp-kw td.vol .num{font-size:11.5px}
  .wsp-kw td.kd{padding-right:8px}
  .wsp-kw thead th{padding:10px 6px;font-size:8.5px;letter-spacing:.05em;white-space:normal;line-height:1.3}
  .wsp-kw thead th:first-child{padding-left:12px}
  .wsp-kw thead th:nth-child(1){width:42%}
  .wsp-kw thead th:nth-child(2){width:40%}
  .wsp-kw thead th:nth-child(3){width:18%}
  .wsp-chip{min-width:26px;font-size:11px;padding:3px 4px}

  .wsp-wall li{grid-template-columns:minmax(0,1fr) 54px}
}

/* ---------- base line-height ---------------------------------------------
   theme.json sets a body line-height of 1.65, which every WordPress page
   inherits. The design bundle this stylesheet was ported from leaves the base
   at `normal` and sets an explicit line-height on anything that needs one, so
   inheriting 1.65 here made every implicit-leading element in the page taller
   than designed — a few pixels each, compounding down a 43-section page.

   Restoring `normal` at the page-type roots makes the components resolve
   exactly as authored. Every rule above that sets its own line-height still
   wins, so prose, headings and the tables are untouched. */
.wsp-progress,.wsp-hero,.wsp-resume,.wsp-wrap,.wsp-final,.wsp-next,.wsp-bar,.wsp-sheet,
.wsp-runner,.wsp-quotes,.wsp-work,.wsp-cta,.wsp-carousel,.wsp-faq{line-height:normal}

/* ============================================================================
   COLUMN LAYOUT — prose left, a short stack of cards right
   ============================================================================
   The second of the template's two layouts. The hub's rail is a viewport-tall
   box holding a map of 43 sections. This one is a couple of small cards — the
   contents and the offer — that stick beside the reader as one unit and release
   at the end of the article.
   ============================================================================ */
.wsp-layout.is-column{grid-template-columns:minmax(0,1fr) 344px;gap:60px;padding:52px 0 64px}
.wsp-layout.is-column .wsp-main{max-width:none}
/* .wsp-wide leans a block 84px into the hub's 76px gutter. This layout's gutter
   is 60px and the rail beside it is real content, so a wide block would sit on
   top of it. Wide blocks stay in the column here. */
.wsp-layout.is-column .wsp-wide{width:100%;margin-right:0}

/* No rules between sections, and none down the side of a sub-section. On the
   hub they are a wayfinding aid through 43 sections read in sittings. Here they
   stacked up into boxes that looked like a component and meant nothing —
   heading size and space already say what belongs to what. */
.wsp-layout.is-column .wsp-sec{border-bottom:0;padding:34px 0 0}
/* The rails and the run terminator are gone from the shared rules above, so
   this only has to undo the indent and reset the spacing. */
.wsp-layout.is-column .wsp-sec--h3,
.wsp-layout.is-column .wsp-sec--h4{padding-left:0;margin-left:0;padding-top:28px}
.wsp-layout.is-column .wsp-sec--h3:has(+ .wsp-sec--h2),
.wsp-layout.is-column .wsp-sec--h4:has(+ .wsp-sec--h2){padding-bottom:0}
.wsp-layout.is-column .wsp-sec--h2{padding-top:52px}
.wsp-layout.is-column .wsp-main>.wsp-sec:first-child{padding-top:0}

/* The whole stack sticks as one unit — cards must not slide underneath each
   other. The hub caps its rail at the viewport height because its contents
   scrolls inside itself; this one has no internal scroller, so the cap is
   dropped. */
.wsp-rail.is-stack{max-height:none;gap:18px}
.wsp-rail.is-stack .wsp-toc{flex:0 0 auto;min-height:0}
/* Nothing here clips or scrolls: six landmarks are short enough to just be. */
.wsp-rail.is-stack .wsp-toc-scroll{overflow:visible;max-height:none}
.wsp-rail.is-stack .wsp-toc-head{padding:14px 16px 12px}
.wsp-rail.is-stack .wsp-toc-list a{padding:9px 10px;font-size:13px;gap:9px}
.wsp-rail.is-stack .wsp-toc-list .n{font-size:9.5px}

/* ---------- DATELINE — who wrote it, where, when, how long ---------------- */
.wsp-dateline{display:flex;align-items:center;gap:14px;padding:0 0 30px;margin-bottom:6px;border-bottom:1px solid var(--border-subtle)}
.wsp-dateline-mark{flex:0 0 auto;width:34px;height:34px}
.wsp-dateline-txt{display:flex;flex-direction:column;gap:5px;min-width:0}
.wsp-dateline-txt .who{font-family:var(--font-display);font-weight:700;font-size:15px;letter-spacing:-.005em;color:var(--midnight-900)}
.wsp-dateline-txt .meta{display:flex;flex-wrap:wrap;gap:6px 18px}
.wsp-dateline-txt .meta span{display:inline-flex;align-items:center;gap:7px;font-family:var(--font-mono);font-size:10.5px;letter-spacing:.08em;text-transform:uppercase;color:var(--fg-muted)}
.wsp-dateline-txt .meta svg{color:var(--hero-500)}

/* ---------- SPLIT HERO — art beside the copy, not under it ---------------- */
/* The photographic hero sets its headline on the image under a heavy veil. A
   mark or a mascot cannot take that treatment — the veil would erase it — so
   this variant gives the art its own column and lights it from behind. */
.wsp-hero.is-split{min-height:0;padding:0 0 8px;justify-content:flex-start}
.wsp-hero.is-split .wsp-hero-inner{padding:132px 0 66px}
.wsp-hero-split{display:grid;grid-template-columns:1.18fr .82fr;gap:48px;align-items:center}
/* min-width:0 or a long unbroken word in the headline blows the column out
   past the grid track instead of wrapping. */
.wsp-hero-copy{min-width:0}
.wsp-hero-art{position:relative;display:flex;align-items:center;justify-content:center;min-width:0}
.wsp-hero-art::before{
  content:'';position:absolute;width:min(78%,340px);aspect-ratio:1;border-radius:50%;
  background:radial-gradient(circle,rgba(79,107,246,.42),transparent 66%);
}
.wsp-hero-art img{
  position:relative;z-index:1;width:auto;height:clamp(280px,32vw,400px);max-width:100%;
  filter:drop-shadow(0 30px 50px rgba(0,0,0,.45));
}

/* ============================================================================
   RUNNER — the client logo marquee under the hero
   ============================================================================
   The whole differentiator against a programmatic city page, so it lands before
   a paragraph of copy. Greyscale at rest, colour on hover, and the animation
   pauses on hover so a logo can actually be read and clicked.
   ============================================================================ */
.wsp-runner{
  background:#fff;border-bottom:1px solid var(--border-subtle);
  padding:44px 0 48px;overflow:hidden;
  display:flex;flex-direction:column;align-items:center;gap:30px;
}
.wsp-runner-label{
  display:flex;align-items:center;gap:9px;
  font-family:var(--font-mono);font-size:11px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--fg-muted);
}
.wsp-runner-label img{height:13px}
/* Fades at both ends so logos enter and leave rather than being cut off. */
.wsp-runner-track-wrap{
  width:100%;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);
}
.wsp-runner-track{display:flex;align-items:center;gap:96px;width:max-content;animation:wsp-marq 90s linear infinite}
.wsp-runner-track-wrap:hover .wsp-runner-track,.wsp-runner-track:focus-within{animation-play-state:paused}
@keyframes wsp-marq{from{transform:translate3d(0,0,0)}to{transform:translate3d(-50%,0,0)}}
.wsp-runner-logo{flex:0 0 auto;height:88px;display:flex;align-items:center;justify-content:center}
.wsp-runner-logo img{
  height:84px;width:auto;max-width:280px;object-fit:contain;display:block;
  filter:grayscale(1);opacity:.5;
  transition:filter var(--dur-base),opacity var(--dur-base);
}
.wsp-runner-logo a{display:block;border-radius:var(--radius-sm)}
.wsp-runner-logo a:hover img,.wsp-runner-logo a:focus-visible img{filter:none;opacity:1}
/* Reduced motion: no marquee at all. The logos wrap into a static block, which
   is the same information without anything moving. */
@media (prefers-reduced-motion:reduce){
  .wsp-runner-track-wrap{-webkit-mask-image:none;mask-image:none}
  .wsp-runner-track{animation:none;flex-wrap:wrap;justify-content:center;width:100%;gap:34px 56px}
  .wsp-runner-logo[aria-hidden="true"]{display:none}
}

/* ============================================================================
   CAROUSEL — one component, used by the quotes and the work strip
   ============================================================================
   A scroll-snap row. Without JavaScript it is already a working scroller; the
   script only reveals the arrows and dots, which is why they ship hidden.
   ============================================================================ */
.wsp-carousel{position:relative}
/* contain:inline-size says the track's width does not depend on what is inside
   it, which for a horizontal scroller is simply true. Without it the columns
   are grid-auto-columns:100%, a percentage against a width that is not yet
   known, so the browser falls back to the widest card and hands that width
   back up the tree - the quote rail was making the whole article 364px wide in
   a 244px column, and on the Walla Walla page that set the narrowest the site
   could be drawn at 386px. Above 480px nothing moves: measured identical at
   680, 900 and 1280. */
.wsp-carousel-track{
  display:grid;grid-auto-flow:column;contain:inline-size;
  overflow-x:auto;overscroll-behavior-x:contain;
  scroll-snap-type:x mandatory;scroll-behavior:smooth;
  scrollbar-width:none;
}
.wsp-carousel-track::-webkit-scrollbar{display:none}
.wsp-carousel-track>*{scroll-snap-align:start}
.wsp-carousel-track:focus-visible{outline:2px solid var(--border-focus);outline-offset:4px;border-radius:var(--radius-lg)}
@media (prefers-reduced-motion:reduce){.wsp-carousel-track{scroll-behavior:auto}}

.wsp-carousel-ui{display:flex;align-items:center;gap:10px;margin-top:18px}
.wsp-carousel-arrow{
  width:38px;height:38px;flex:0 0 auto;display:flex;align-items:center;justify-content:center;
  border:1px solid var(--border-subtle);border-radius:50%;background:#fff;color:var(--midnight-900);
  cursor:pointer;transition:border-color var(--dur-base),color var(--dur-base),background var(--dur-base);
}
.wsp-carousel-arrow:hover:not(:disabled){border-color:var(--hero-400);color:var(--hero-700)}
.wsp-carousel-arrow:disabled{opacity:.32;cursor:default}
.wsp-carousel-dots{display:flex;align-items:center;gap:7px;margin-right:auto;order:-1}
.wsp-carousel-dots button{
  width:8px;height:8px;padding:0;border:0;border-radius:50%;
  background:var(--gray-300);cursor:pointer;transition:background var(--dur-base),width var(--dur-base);
}
.wsp-carousel-dots button.is-on{width:22px;border-radius:99px;background:var(--hero-500)}

/* ============================================================================
   QUOTES — one panel at a time, at a size worth reading
   ============================================================================ */
.wsp-quotes{display:block;margin:44px 0}
.wsp-quotes-k{
  display:block;margin-bottom:14px;
  font-family:var(--font-mono);font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--fg-muted);
}
.wsp-carousel.is-quotes .wsp-carousel-track{grid-auto-columns:100%}
.wsp-quote{
  position:relative;margin:0;padding:44px 44px 36px;min-width:0;
  border-radius:var(--radius-xl);overflow:hidden;
  background:
    radial-gradient(120% 140% at 88% -20%,rgba(99,117,255,.22),transparent 60%),
    linear-gradient(160deg,var(--midnight-800) 0%,var(--midnight-950) 62%);
}
/* A brushed sheen across the panel — the metallic read, done with light rather
   than a texture file, so it costs nothing and scales to any width. */
.wsp-quote::after{
  content:'';position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(104deg,transparent 34%,rgba(255,255,255,.07) 46%,rgba(255,255,255,.02) 52%,transparent 62%);
}
.wsp-quote-mark{
  position:absolute;right:22px;top:-14px;
  font-family:var(--font-display);font-weight:900;font-size:150px;line-height:1;
  color:rgba(255,255,255,.07);pointer-events:none;
}
.wsp-quote-text{
  position:relative;z-index:1;margin:0 0 28px;
  font-family:var(--font-display);font-weight:600;
  font-size:clamp(19px,2.2vw,25px);line-height:1.4;letter-spacing:-.015em;
  color:#fff;text-wrap:pretty;
  /* Steel, not flat white: the words read as spoken, and lifted off the panel. */
  background:linear-gradient(180deg,#ffffff 0%,#dfe6f5 58%,#aebada 100%);
  -webkit-background-clip:text;background-clip:text;
  -webkit-text-fill-color:transparent;color:transparent;
}
@supports not ((-webkit-background-clip:text) or (background-clip:text)){
  .wsp-quote-text{background:none;-webkit-text-fill-color:#fff;color:#fff}
}
.wsp-quote-by{
  position:relative;z-index:1;display:flex;align-items:center;gap:16px;font-style:normal;
  padding-top:22px;border-top:1px solid rgba(255,255,255,.14);
}
.wsp-quote-logo{flex:0 0 auto;height:40px;width:auto;max-width:120px;object-fit:contain;filter:grayscale(1) brightness(2.6);opacity:.75}
.wsp-quote-who{display:flex;flex-direction:column;gap:4px;min-width:0}
.wsp-quote-who strong{font-family:var(--font-display);font-weight:700;font-size:15.5px;letter-spacing:-.005em;color:#fff}
.wsp-quote-who span{font-family:var(--font-mono);font-size:10.5px;letter-spacing:.1em;text-transform:uppercase;color:#94a1bb}
.wsp-quote-who a{color:inherit;text-decoration:underline;text-underline-offset:3px;text-decoration-color:var(--hero-400)}

/* ============================================================================
   WORK — a glance at the work, mid-argument. Not the portfolio.
   ============================================================================ */
.wsp-work{display:block;margin:44px 0;scroll-margin-top:104px}
.wsp-work-head{display:flex;align-items:baseline;gap:16px;margin-bottom:16px}
.wsp-work-h{
  font-family:var(--font-mono);font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--fg-muted);
}
.wsp-work-all{
  margin-left:auto;display:inline-flex;align-items:center;gap:7px;white-space:nowrap;
  font-family:var(--font-display);font-weight:700;font-size:12.5px;color:var(--hero-700);
}
.wsp-work-all:hover{color:var(--hero-800)}
.wsp-carousel.is-work .wsp-carousel-track{grid-auto-columns:calc((100% - 32px) / 3);gap:16px}
.wsp-work-card{
  display:flex;flex-direction:column;overflow:hidden;min-width:0;
  border:1px solid var(--border-subtle);border-radius:var(--radius-lg);background:#fff;
  transition:border-color var(--dur-base),box-shadow var(--dur-base),transform var(--dur-base) var(--ease-out);
}
.wsp-work-card:hover{border-color:var(--hero-300);box-shadow:var(--shadow-md);transform:translateY(-2px)}
.wsp-work-shot{display:block;overflow:hidden;aspect-ratio:16/10;background:var(--gray-100)}
.wsp-work-shot img{display:block;width:100%;height:100%;object-fit:cover;object-position:top center}
.wsp-work-body{display:flex;flex-direction:column;gap:5px;padding:13px 14px 15px}
.wsp-work-name{font-family:var(--font-display);font-weight:700;font-size:14px;letter-spacing:-.01em;color:var(--midnight-900)}
.wsp-work-line{font-family:var(--font-body);font-size:12.5px;line-height:1.5;color:var(--fg-muted)}
@media (prefers-reduced-motion:reduce){
  .wsp-work-card,.wsp-work-card:hover{transition:none;transform:none}
}

/* ============================================================================
   FIGURES — real client photography in the flow of the prose
   ============================================================================ */
.wsp-fig{margin:38px 0}
/* Cropped to a consistent ratio rather than run at native height: a 4:3 frame
   at column width is most of a screen for one picture, and photographs from
   different shoots would otherwise each set their own rhythm down the page. */
/* No aspect-ratio and no object-fit. Both were here, and between them they
   cropped every figure to 3:2 from the centre. The photographs are shot 3:2
   and lost nothing, which is why this survived review; every diagram and
   screenshot was cut. Measured on the dental page: the map pack lost 121px a
   side, the procedure-page diagram 102px, the link-score chart 37px, which is
   exactly the three the owner reported and none of the three he did not.

   wbc_sp_figure() writes real width and height attributes on every img, so the
   intrinsic ratio reserves the same layout space before the file arrives and
   nothing shifts. */
.wsp-fig img{display:block;width:100%;height:auto;border-radius:var(--radius-lg)}
.wsp-fig figcaption{
  margin-top:11px;font-family:var(--font-mono);font-size:10.5px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--fg-muted);
}

/* ============================================================================
   PROOF CARDS — named clients the site has no case study for
   ============================================================================
   The work carousel above reads the portfolio and links into it. This is the
   plainer sibling: a logo, a town and one line of result, for the pages that
   want to name a practice whose case study is not written. A card with a built
   destination is an <a> and lifts on hover; one without is a <div> and sits
   still, so the difference is visible before you click rather than after.
   ============================================================================ */
.wsp-proof{
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px;margin:34px 0;
}
.wsp-proof-card{
  display:flex;flex-direction:column;gap:7px;min-width:0;padding:20px 18px 18px;
  border:1px solid var(--border-subtle);border-radius:var(--radius-lg);background:#fff;
}
a.wsp-proof-card{
  transition:border-color var(--dur-base),box-shadow var(--dur-base),transform var(--dur-base) var(--ease-out);
}
a.wsp-proof-card:hover{border-color:var(--hero-300);box-shadow:var(--shadow-md);transform:translateY(-2px)}
.wsp-proof-logo{display:flex;align-items:center;height:44px;margin-bottom:4px}
.wsp-proof-logo img{display:block;max-width:130px;width:auto;height:auto;max-height:38px;object-fit:contain}
.wsp-proof-name{font-family:var(--font-display);font-weight:700;font-size:15px;letter-spacing:-.01em;color:var(--midnight-900)}
.wsp-proof-loc{font-family:var(--font-mono);font-size:10.5px;letter-spacing:.1em;text-transform:uppercase;color:var(--fg-muted)}
.wsp-proof-line{font-family:var(--font-body);font-size:13px;line-height:1.55;color:var(--fg-body)}
@media (max-width:860px){
  .wsp-proof{grid-template-columns:1fr}
}
@media (prefers-reduced-motion:reduce){
  a.wsp-proof-card,a.wsp-proof-card:hover{transition:none;transform:none}
}

/* ============================================================================
   OPTIONAL HERO COMPONENTS — off unless a page config asks for them
   ============================================================================
   Both came off the dental SEO page when it moved onto this template. No page
   currently switches them on; they are here so the next one that wants them
   places data rather than rebuilding the markup in its own stylesheet.
   ============================================================================ */
.wsp-statcards{display:flex;flex-wrap:wrap;gap:14px;margin-top:30px}
.wsp-statcard{
  display:flex;flex-direction:column;gap:3px;min-width:140px;padding:14px 16px;
  border:1px solid rgba(255,255,255,.16);border-radius:var(--radius-lg);
  background:rgba(255,255,255,.07);backdrop-filter:blur(6px);
}
.wsp-statcard-label{font-family:var(--font-mono);font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:rgba(255,255,255,.62)}
.wsp-statcard-value{font-family:var(--font-display);font-weight:700;font-size:30px;line-height:1;letter-spacing:-.02em;color:#fff}
.wsp-statcard-foot{font-family:var(--font-body);font-size:11.5px;color:rgba(255,255,255,.66)}
.wsp-statcard-delta{color:var(--hero-300);font-weight:700}

.wsp-benefits{
  display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:18px;
  margin:30px 0 0;padding:22px 0 0;list-style:none;border-top:1px solid rgba(255,255,255,.14);
}
.wsp-benefits li{
  font-family:var(--font-body);font-size:13.5px;line-height:1.5;color:rgba(255,255,255,.8);
}
@media (max-width:860px){
  .wsp-benefits{grid-template-columns:repeat(2,minmax(0,1fr))}
}

/* ============================================================================
   CONTACT FORM — a rail card, so it sits beside the phone number
   ============================================================================
   In the rail rather than under the prose: at desktop width that puts the form
   level with the contact details instead of a screen below them, and on a
   phone the rail stacks under the copy, which is the order you want there
   anyway. One component, two behaviours, no second layout.
   ============================================================================ */

/* ============================================================================
   MAP — a picture and an address, never an embed
   ============================================================================
   A Google Maps iframe costs several hundred kilobytes of third-party script
   and a connection to Google on every page load, to answer a question a
   picture and a street name already answer. The image is optional: until one
   exists the block is the address and the number, which is the part that
   actually matters.
   ============================================================================ */
.wsp-map{background:var(--gray-50);border-top:1px solid var(--border-subtle);padding:52px 0}
.wsp-map-inner{display:grid;grid-template-columns:minmax(0,1fr);gap:26px;align-items:center}
.wsp-map-inner:has(.wsp-map-img){grid-template-columns:minmax(0,1.1fr) minmax(0,.9fr)}
.wsp-map-img{
  display:block;width:100%;height:auto;border-radius:var(--radius-lg);
  border:1px solid var(--border-subtle);
}
.wsp-map-txt{display:flex;flex-direction:column;gap:10px;min-width:0}
.wsp-map-txt .k{
  margin:0;font-family:var(--font-mono);font-size:10.5px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--fg-muted);
}
.wsp-map-addr{
  margin:0;font-family:var(--font-display);font-weight:700;
  font-size:clamp(20px,2.4vw,27px);letter-spacing:-.02em;color:var(--midnight-900);
}
.wsp-map-acts{display:flex;flex-wrap:wrap;align-items:center;gap:14px 20px;margin:4px 0 0}
.wsp-map-gbp{
  display:inline-flex;align-items:center;gap:7px;font-family:var(--font-display);
  font-weight:700;font-size:13px;color:var(--hero-700);
}
.wsp-map-gbp:hover{color:var(--hero-800)}
@media (max-width:860px){
  .wsp-map-inner,.wsp-map-inner:has(.wsp-map-img){grid-template-columns:1fr}
}

/* ============================================================================
   CTA — one component, two treatments
   ============================================================================
   'card' is the mid-page offer, inside the reading column. 'wide' is the one
   that closes the page, below the two columns, and it is the only thing on this
   page that runs full width.
   ============================================================================ */
.wsp-cta{position:relative;overflow:hidden}
.wsp-cta-inner{position:relative;z-index:2;display:flex;flex-wrap:wrap;align-items:center;gap:18px 32px}
.wsp-cta-bolt{position:absolute;right:-10px;top:50%;translate:0 -50%;width:120px;opacity:.07;pointer-events:none}
.wsp-cta-txt{flex:1 1 320px;min-width:0}
.wsp-cta-h{font-family:var(--font-display);font-weight:800;font-size:20px;line-height:1.2;letter-spacing:-.015em;margin:0 0 8px;color:#fff;text-wrap:pretty}
.wsp-cta-body{font-family:var(--font-body);font-size:15px;line-height:1.62;margin:0;color:#b6c1d8}
.wsp-cta-acts{display:flex;flex-wrap:wrap;align-items:center;gap:14px 20px}
.wsp-cta-alt{font-family:var(--font-display);font-weight:700;font-size:14px;color:#c8d1e4}
.wsp-cta-alt:hover{color:#fff;text-decoration:underline;text-underline-offset:3px}

/* card: sits in the reading column and does not interrupt the read. The only
   mid-page treatment — a full-bleed band every few screens reads as a page that
   keeps stopping to sell rather than one making an argument. */
.wsp-cta.is-card{
  margin:40px 0;padding:28px 30px;border-radius:var(--radius-lg);
  background:radial-gradient(130% 130% at 92% -20%,var(--midnight-700),var(--midnight-950));
}
.wsp-cta.is-card .wsp-cta-inner{max-width:none;padding:0}
/* The card lives inside .wsp-sec, and .wsp-sec p sets the reading column's dark
   ink with one class more of specificity than .wsp-cta-h and .wsp-cta-body have.
   So the section won, and on 21 service pages the card rendered #1C2539 text on
   its own #2B3550-to-#121A2B gradient - 1.19:1, an empty dark box where the
   offer should be. The markup was right and each rule was right on its own; the
   cascade was the bug, which is why nothing that reads HTML ever caught it.
   tests/contrast.mjs measures the rendered pixels and does. */
.wsp-sec .wsp-cta-h{color:#fff}
.wsp-sec .wsp-cta-body{color:#b6c1d8}
.wsp-sec .wsp-cta-alt{color:#c8d1e4}
.wsp-sec .wsp-cta-alt:hover{color:#fff}

/* wide: full width, and only below the two columns — the offer that closes the
   page, in the same place the hub puts its closing form. */
.wsp-cta.is-wide{background:var(--midnight-950);padding:104px 0}
.wsp-cta.is-wide .wsp-cta-inner{flex-direction:column;text-align:center;gap:22px}
.wsp-cta.is-wide .wsp-cta-bolt{right:auto;left:50%;top:-24px;translate:-50% 0;width:190px;opacity:.06}
.wsp-cta.is-wide .wsp-cta-txt{flex:0 1 auto;max-width:660px}
.wsp-cta.is-wide .wsp-cta-h{font-size:clamp(26px,3.4vw,38px)}
.wsp-cta.is-wide .wsp-cta-body{font-size:17px}
.wsp-cta.is-wide .wsp-cta-acts{justify-content:center}
/* The photograph behind it: a place, not content, so it sits under a veil heavy
   enough that the copy keeps its contrast at any crop. */
/* The band is a wide strip, so the crop has to be aimed. At 42% this landed on
   the hazy water and read as flat navy under the veil; the foreground is where
   the picture has contrast to spare. */
.wsp-cta-art{position:absolute;inset:0;z-index:0;width:100%;height:100%;object-fit:cover;object-position:50% 78%}
.wsp-cta-veil{
  position:absolute;inset:0;z-index:1;pointer-events:none;
  /* One layer, not three. Stacked translucent gradients multiply — the first
     pass came out near-opaque and the photograph may as well not have been
     there. Heavy through the middle where the copy sits, light at the edges so
     the picture reads. */
  background:radial-gradient(58% 116% at 50% 50%,
    rgba(15,22,38,.93) 0%,rgba(15,22,38,.87) 44%,rgba(15,22,38,.34) 100%);
}
.wsp-cta-art{filter:saturate(.85) contrast(1.04)}

/* ============================================================================
   FAQ — a real accordion, opening on click, with no script behind it
   ============================================================================ */
.wsp-faq{margin:8px 0 0;border-top:1px solid var(--border-subtle)}
.wsp-faq-item{border-bottom:1px solid var(--border-subtle);scroll-margin-top:104px}
.wsp-faq-q{
  display:flex;align-items:center;gap:18px;cursor:pointer;list-style:none;
  padding:20px 2px;
  font-family:var(--font-display);font-weight:700;font-size:18px;line-height:1.3;
  letter-spacing:-.01em;color:var(--midnight-900);
  transition:color var(--dur-fast);
}
.wsp-faq-q::-webkit-details-marker{display:none}
.wsp-faq-q>span:first-child{flex:1 1 auto}
.wsp-faq-q:hover{color:var(--hero-700)}
.wsp-faq-q:focus-visible{outline:2px solid var(--border-focus);outline-offset:2px;border-radius:var(--radius-sm)}
.wsp-faq-ico{
  flex:0 0 auto;width:30px;height:30px;display:flex;align-items:center;justify-content:center;
  border:1px solid var(--border-subtle);border-radius:50%;color:var(--hero-600);
  transition:transform var(--dur-base) var(--ease-out),background var(--dur-base),border-color var(--dur-base);
}
.wsp-faq-item[open] .wsp-faq-ico{transform:rotate(45deg);background:var(--hero-500);border-color:var(--hero-500);color:#fff}
.wsp-faq-a{padding:0 66px 24px 2px}
.wsp-faq-a p{font-family:var(--font-body);font-size:16.5px;line-height:1.72;color:var(--fg-secondary);margin:0 0 14px}
.wsp-faq-a p:last-child{margin-bottom:0}
@media (prefers-reduced-motion:reduce){.wsp-faq-ico{transition:none}}

/* ---------- column layout: responsive --------------------------------------- */
@media (max-width:1080px){
  /* The hub hides its rail here — its contents lives on in the mobile sheet.
     The column layout's rail is not navigation, it is an offer and two quotes,
     so it moves under the article instead of being thrown away.

     It only ever moved on paper. The single-column reset above this block is
     written .wsp-layout, and .wsp-layout.is-column re-declares the two-column
     track outside any media query, so the more specific rule kept winning all
     the way down to a phone: at 390px the grid resolved to "10px 344px", the
     article was assigned a 10px column it spilled out of, and the rail kept
     the position:sticky it was given for the desktop gutter - so the contents
     card sat on top of the article and followed the reader down all 30,000
     pixels of it. Both halves are undone here: one track, and the rail lets go
     of the gutter it no longer has. */
  .wsp-layout.is-column{grid-template-columns:minmax(0,1fr);gap:0}
  .wsp-rail.is-stack{position:static;max-height:none;display:block;max-width:560px;margin:8px auto 0}
  .wsp-rail.is-stack .wsp-toc{position:static}
}
@media (max-width:960px){
  .wsp-hero-split{grid-template-columns:1fr;gap:30px}
  .wsp-hero.is-split .wsp-hero-inner{padding:118px 0 48px}
  .wsp-hero-art{order:-1}
  .wsp-hero-art img{height:clamp(200px,42vw,280px)}
  .wsp-carousel.is-work .wsp-carousel-track{grid-auto-columns:calc((100% - 16px) / 2)}
}
@media (max-width:680px){
  .wsp-runner{padding:34px 0 36px;gap:22px}
  .wsp-runner-track{gap:56px}
  .wsp-runner-logo,.wsp-runner-logo img{height:64px}
  .wsp-quotes-grid{grid-template-columns:1fr}
  .wsp-work{padding:56px 0}
  .wsp-carousel.is-work .wsp-carousel-track{grid-auto-columns:86%}
  .wsp-quote{padding:30px 26px 26px;border-radius:var(--radius-lg)}
  .wsp-quote-mark{font-size:104px;right:14px}
  .wsp-faq-a{padding-right:8px}
  .wsp-cta.is-wide{padding:56px 0}
  .wsp-cta-acts,.wsp-cta-acts .wb-btn{width:100%}
  .wsp-cta-acts .wb-btn{justify-content:center}
  /* One declaration each. These were written twice inside this same block -
     .wsp-faq-q at 16.5px eleven lines above and again at 17.5px here, and
     .wsp-faq-a likewise - so the first of each pair had never had any effect
     while reading as though it did. */
  .wsp-faq-q{font-size:17.5px;gap:12px}
  .wsp-faq-a p{font-size:16px}
}

/* ---------------------------------------------------------------------------
   THUMB TARGETS - see the same block in wonderboy.css for the reasoning.

   The service page is where most of the reading happens and where the smallest
   controls are: contents rows at 36px, carousel arrows at 38px, and the
   carousel's page dots at 8px square, which is a target roughly the size of
   the full stop at the end of this sentence.
   -------------------------------------------------------------------------- */
@media (max-width:860px){
  .wsp-toc-list a{min-height:44px;align-items:center}
  /* The spoke list under the contents, which is also what the mobile sheet
     hands you when you press "On this page". Its rows were 27px. */
  .wsp-toc-spokes a{min-height:44px}
  .wsp-silo-links a{min-height:44px}
  .wsp-carousel-arrow{width:44px;height:44px}
  .wsp-work-all{min-height:44px}
  .wsp-cta-alt{display:inline-flex;align-items:center;min-height:44px}
  /* The dot keeps its 8px and its 22px active pill; what changes is that the
     button around it stops being the dot and becomes a box a thumb can find. */
  .wsp-carousel-dots{gap:0}
  .wsp-carousel-dots button{
    width:20px;height:44px;background:none;border-radius:0;
    display:flex;align-items:center;justify-content:center;
  }
  .wsp-carousel-dots button::before{
    content:'';width:8px;height:8px;border-radius:50%;background:var(--gray-300);
    transition:background var(--dur-base),width var(--dur-base);
  }
  .wsp-carousel-dots button.is-on{width:34px;background:none}
  .wsp-carousel-dots button.is-on::before{width:22px;border-radius:99px;background:var(--hero-500)}
  /* The crumbs are a 11.5px mono row, which is right for the look and wrong
     for a thumb. The row keeps its type; the links get a box around it. */
  .wsp-crumbs li{min-height:44px}
  .wsp-crumbs a,.wsp-crumbs [aria-current]{display:inline-flex;align-items:center;min-height:44px}

  /* And 16px on every field, or iOS zooms the page on focus and stays there.
     Same block, same breakpoint, same reason as wonderboy.css. */
  .wsp-field input,
  .wsp-lfield input,
  .wsp-final-form .wsp-field input{font-size:16px}
}

/* The template's eyebrows - the little mono kickers over a card, a video, the
   guide offer, the silo strip - are all white-space:nowrap so their icon stays
   on the line with the words. At 10.5px with .13em of tracking one of them is
   315px wide and unbreakable, so it set the minimum width of the whole page: a
   phone narrower than that got shrink-to-fit and read the site at 88%. They
   wrap below 480px. See the same fix for .wb-btn in wonderboy.css. */
@media (max-width:480px){
  .wsp-toc-spokes .lbl,
  .wsp-video-top .k,
  .wsp-pod-home,
  .wsp-guide-k,
  .wsp-final-k,
  .wsp-silo-label{white-space:normal}
  /* Last one in the same family. An <input> with no size attribute has an
     intrinsic width of about twenty characters, and that is what a grid track
     sized `1fr` takes as its automatic minimum - so the guide card could not
     be drawn narrower than 195px of empty text field plus its chrome. Giving
     the input a percentage width makes its contribution nothing while it still
     fills the row it is on. */
  .wsp-lfield{flex-basis:100%;min-width:0}
  .wsp-lfield input{width:100%}
}

/* ---------------------------------------------------------------------------
   TWO-COLUMN ROWS THAT RUN OUT OF ROOM ON A PHONE

   Both of these are label-and-value rows sized for a tablet: a fixed label
   column and whatever is left. At 320px what is left is about 130px, which put
   the comparison card's page titles at thirteen characters to a line, and the
   backlink wall's DR badge - which is flex:0 0 auto and so does not shrink at
   all - ran under the count in the column beside it. The label goes above the
   value instead.
   -------------------------------------------------------------------------- */
@media (max-width:400px){
  .wsp-cmp td{grid-template-columns:minmax(0,1fr);gap:3px}
  .wsp-wall li{grid-template-columns:minmax(0,1fr) auto}
  .wsp-wall .nm{flex-wrap:wrap;gap:2px 8px}
}
