/* Software detail page v2 -- ported from goodfirms-software-details_Final-9-9-2.html
 * (design 2026-09-09). Plan: docs -> repos/goodfirms-public-fe/
 * 2026-09-16-software-detail-redesign-plan.md
 *
 * 🔴 EVERY selector is `.sp2-*` or scoped under `.sp2`. Two reasons, both learned
 * the hard way on this codebase:
 *
 *  1. React 19 `precedence` HOISTS this sheet into <head> and KEEPS it across
 *     client-side navigation, so an unscoped rule styles every route the user
 *     visits next -- not just this page. (Wave 33: unscoped `#id:before` rules in
 *     home.css painted phantom category labels all over /directories.)
 *
 *  2. The design file's <style> carried a PAGE-LEVEL RESET:
 *       body   { margin; font-family; color; background; font-size; line-height }
 *       a      { color: inherit; text-decoration: none }
 *       button { border: none; background: none; color: inherit }
 *       img    { max-width: 100%; display: block }
 *       *, *::before, *::after { box-sizing: border-box }
 *     Shipped as-is those would have flattened every link and button SITE-WIDE.
 *     They are scoped under `.sp2` here. Bare `html{scroll-behavior}` is dropped --
 *     the site already sets it.
 *
 * Sections deliberately absent (owner decision, 2026-09-16): Software downtime
 * (`uptime-*`), AI adoption insights (`adopt-*`), AI capabilities (`ai-*`).
 *
 * ⚠️ BUMP ?v ON EVERY EDIT -- /static/css/* is edge-cached under a stable URL.
 */

:root {
  /* color */
  --navy:#171923;
  --gold:#c5a063;
  --gold-soft:#fdf6e9;
  --green:#3ebe69;
  --green-soft:#e1fbea;
  --surface:#ececec;
  --surface-2:#f6f6f7;
  --border:#dbdbdb;
  --muted:#444b55;
  --white:#ffffff;

  /* radius */
  --r-sm:6px;
  --r-md:8px;
  --r-lg:10px;
  --pill:100px;

  /* type */
  --font-head:'Manrope', system-ui, sans-serif;
  --font-body:'Roboto', system-ui, sans-serif;

  /* layout */
  --container:1340px;
  --rail:400px;
  --gap:40px;
  --gutter:clamp(16px, 4vw, 40px);
  --nav-h:52px;

  --ease:400ms ease;
  --shadow-sm:0 1px 2px rgba(23,25,35,.05);
  --shadow-md:0 8px 30px rgba(23,25,35,.08);}
.sp2 *, .sp2 *::before, .sp2 *::after {box-sizing:border-box;}
.sp2 {
  margin:0;
  font-family:var(--font-body);
  color:var(--navy);
  background:var(--white);
  font-size:16px;
  line-height:1.6;
  -webkit-font-smoothing:antialiased;}
/* The element resets are wrapped in :where() DELIBERATELY -- do not "simplify"
   this to a plain `.sp2 button {...}`.

   In the design these are BARE element selectors, specificity (0,0,1), so every
   single-class rule below (0,1,0) overrides them -- that is what makes
   `.btn-outline{background:#fff;border:1px solid}` and `.thumb{border:2px solid}`
   work at all. Scoping them as `.sp2 button` raises them to (0,1,1), which INVERTS
   that relationship and silently beats those component rules:

     .sp2-thumb        lost its border + gradient  -> the gold selected ring on
                       `.sp2-thumb.sp2-active` set a border-color on `border:none`
     .sp2-feature-tab  lost `color:var(--muted)` at rest
     .sp2-btn-outline  lost its white background + navy border  -> Read more
                       rendered as a bare text label

   `:where()` contributes ZERO specificity, so `.sp2 :where(button)` scopes the
   reset to this page while keeping the design's original (0,0,1). */
.sp2 :where(img) {max-width:100%;display:block;}
.sp2 :where(a) {color:inherit;text-decoration:none;}
.sp2 :where(button) {font-family:inherit;cursor:pointer;border:none;background:none;color:inherit;}
.sp2-container {
  width:100%;
  max-width:var(--container);
  margin-inline:auto;
  padding-inline:var(--gutter);}
.sp2-eyebrow {
  font-family:var(--font-body);
  font-weight:500;
  font-size:14px;
  letter-spacing:2px;
  text-transform:uppercase;
  color:var(--gold);
  margin:0;}
.sp2-eyebrow--muted {color:var(--muted);}
.sp2-h2 {
  font-family:var(--font-head);
  font-weight:700;
  font-size:clamp(24px,3vw,32px);
  color:var(--navy);
  margin:0;
  line-height:1.2;}
.sp2-sub {color:var(--muted);font-size:16px;margin:0;}
.sp2-btn {
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  font-family:var(--font-body);font-weight:600;font-size:14px;
  padding:10px 23px;border-radius:var(--r-sm);
  transition:var(--ease);white-space:nowrap;line-height:1;}
.sp2-btn svg {width:12px;height:12px;flex:none;}
.sp2-btn-gold {background:var(--gold);color:var(--navy);}
.sp2-btn-gold:hover {background:#b58f52;}
.sp2-btn-outline {background:var(--white);color:var(--navy);border:1px solid var(--navy);}
.sp2-btn-outline:hover {background:var(--navy);color:var(--white);}
.sp2-btn-soft {background:var(--surface);color:var(--navy);border:1px solid var(--border);}
.sp2-btn-soft:hover {background:#e2e2e4;}
/* 60px/18px in the design; reduced to 48px/16px (owner, 2026-09-16) so the
   rail CTAs stop dominating the card. BOTH rail buttons now carry this class —
   "Try software demo" previously hardcoded `height:48;fontSize:15` inline, so
   the two were sized in two different places and drifted apart the moment one
   changed. One rule governs the pair; resize here and they stay matched. */
.sp2-btn-lg {padding:0 23px;height:48px;font-size:16px;width:100%;}
.sp2-chip {
  display:inline-flex;align-items:center;gap:6px;
  background:var(--surface);border:1px solid var(--border);
  border-radius:var(--pill);padding:9px 15px;font-size:14px;color:var(--muted);}
.sp2-chip strong {color:var(--navy);font-weight:600;font-size:16px;}
.sp2-tag {
  display:inline-flex;align-items:center;
  background:var(--surface);border:1px solid var(--border);
  border-radius:var(--pill);padding:4px 12px;font-size:14px;color:var(--navy);
  transition:var(--ease);}
.sp2 a.sp2-tag:hover {background:var(--navy);color:var(--white);border-color:var(--navy);}
.sp2-pill-verified {
  display:inline-flex;align-items:center;gap:4px;
  background:var(--green-soft);border:.72px solid var(--green);
  color:var(--green);border-radius:var(--pill);
  padding:4px 8px;font-size:11px;font-weight:500;line-height:1;}
.sp2-pill-verified svg {width:10px;height:10px;}
.sp2-stars {display:inline-flex;gap:2px;}
.sp2-stars svg {width:15px;height:15px;}
.sp2-star-full {fill:var(--gold);}
.sp2-star-empty {fill:#d8d8d8;}
.sp2-site-header {
  background:var(--white);
  border-bottom:1px solid var(--border);}
.sp2-site-header .sp2-container {
  display:flex;align-items:center;justify-content:space-between;
  height:64px;gap:24px;}
.sp2-brand {display:flex;align-items:center;gap:10px;font-family:var(--font-head);font-weight:800;font-size:22px;color:var(--navy);}
.sp2-brand .sp2-shield {width:24px;height:28px;flex:none;}
.sp2-brand span b {color:var(--gold);font-weight:800;}
/* The design file's OWN site header (.sp2-main-nav / .sp2-header-* /
   .sp2-icon-btn / .sp2-burger, 12 rules) was removed 2026-09-16: this page
   renders the real GoodFirms header (`src/components/site/v2/HeaderV2.tsx`),
   so none of those classes existed in any markup. They were also the only
   reason the design's 820px breakpoint existed — it did nothing but hide a nav
   that was never there. Dead rules matter more in this sheet than most: React
   19 `precedence` hoists it into <head> and keeps it across client-side
   navigation. */
.sp2-subnav {
  position:sticky;top:0;z-index:40;
  background:var(--white);
  border-bottom:1px solid var(--border);
  box-shadow:var(--shadow-sm);}
.sp2-subnav .sp2-container {display:flex;align-items:center;gap:4px;overflow-x:auto;scrollbar-width:none;}
.sp2-subnav .sp2-container::-webkit-scrollbar {display:none;}
.sp2-subnav a {
  position:relative;padding:15px 16px;font-weight:600;font-size:16px;color:var(--muted);
  white-space:nowrap;transition:var(--ease);}
.sp2-subnav a:hover {color:var(--navy);}
.sp2-subnav a.sp2-active {color:var(--navy);}
.sp2-subnav a.sp2-active::after {
  content:"";position:absolute;left:16px;right:16px;bottom:-1px;height:3px;
  background:var(--gold);border-radius:3px 3px 0 0;}
.sp2-detail {position:relative;}
.sp2-detail__band {
  position:absolute;top:0;left:50%;transform:translateX(-50%);
  width:100vw;background:var(--navy);z-index:0;}
/* 🔴 EXPLICIT ROW PLACEMENT, copied from `.cp2-page` on the company profile.
   The three children are placed by name rather than by source order:

     masthead  col 1, row 1
     rail      col 2, row 1 / span 2   (sits beside the masthead AND runs down)
     main      col 1, row 2

   This is the whole reason the masthead is a direct grid child instead of the
   first element inside `.sp2-detail-main`. Collapsing to one column then gives
   masthead → rail → main, so the Visit Website card lands immediately after the
   hero. While the masthead was nested there was no `order` value that could put
   the rail between it and the content — the rail could only go before both or
   after both, which is how it first ended up above the product name and then
   below every section. */
.sp2-detail__grid {
  position:relative;z-index:1;
  display:grid;grid-template-columns:minmax(0,1fr) var(--rail);
  gap:var(--gap);
  align-items:start;
  padding-bottom:64px;}
.sp2-detail__grid > .sp2-masthead {grid-column:1;grid-row:1;}
.sp2-detail__grid > .sp2-detail-rail {grid-column:2;grid-row:1 / span 2;}
.sp2-detail__grid > .sp2-detail-main {grid-column:1;grid-row:2;}
.sp2-masthead {padding:48px 0 40px;}
.sp2-masthead__top {display:flex;gap:20px;align-items:center;}
.sp2-masthead__logo {
  width:75px;height:75px;border-radius:var(--r-sm);border:.5px solid var(--border);
  object-fit:cover;flex:none;background:var(--white);}

/* Initials fallback shown when a product has no logo. The design hard-coded
   this as a style="" attribute on the logo box; it is a rule here so the
   component stays markup-only. */
.sp2-masthead__initials {
  display: flex; align-items: center; justify-content: center;
  width: 100%; height: 100%;
  font-family: var(--font-head); font-weight: 800; font-size: 22px;
  color: var(--navy);
}
.sp2-masthead__title {display:flex;align-items:center;gap:10px;flex-wrap:wrap;}
.sp2-masthead__title h1 {
  font-family:var(--font-head);font-weight:800;color:var(--white);
  font-size:clamp(28px,4vw,44px);line-height:1.1;margin:0;}
.sp2-masthead__meta-top {display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-top:6px;}
.sp2-masthead__cat {color:#c9cdd6;font-size:14px;}
.sp2-masthead__cat b {color:var(--gold);font-weight:600;}
.sp2-masthead__tagline {color:var(--white);font-size:16px;line-height:1.8;margin:22px 0 12px;max-width:760px;}
.sp2-rating-row {display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-top:18px;}
.sp2-rating-row .sp2-score {color:var(--white);font-weight:600;font-size:18px;}
.sp2-rating-row .sp2-divider {color:#5a616c;}
.sp2-rating-row .sp2-write {display:inline-flex;align-items:center;gap:5px;color:var(--gold);font-weight:600;font-size:16px;}
.sp2-rating-row .sp2-write svg {width:18px;height:18px;}
.sp2-rating-row .sp2-claimed {display:inline-flex;align-items:center;gap:5px;color:#c9cdd6;font-size:14px;}
.sp2-rating-row .sp2-claimed svg {width:15px;height:15px;}
.sp2-rating-row .sp2-claimed.sp2-unclaimed {color:var(--gold);font-weight:600;}
.sp2-rating-row a.sp2-claimed:hover {text-decoration:underline;}
.sp2-rating-row .sp2-write:hover {text-decoration:underline;}
.sp2-claim {scroll-margin-top:84px;}
.sp2-chips-row {display:flex;flex-wrap:wrap;gap:14px;margin-top:20px;}
.sp2-chips-row .sp2-chip {background:var(--surface);}
.sp2-masthead__badges {display:flex;gap:26px 30px;flex-wrap:wrap;margin-top:24px;}
.sp2-badge-group {display:flex;flex-direction:column;gap:12px;}
.sp2-badge-group + .sp2-badge-group {border-left:1px solid #2b2f3a;padding-left:30px;}
.sp2-badge-tiles {display:flex;gap:10px;flex-wrap:wrap;}
.sp2-badge-kw {
  display:inline-flex;align-items:center;line-height:1;
  padding:8px 15px;border-radius:var(--pill);
  border:1px solid #3a3f4b;background:rgba(255,255,255,.04);
  color:#e6e8ec;font-size:14px;font-weight:500;white-space:nowrap;}
/* Self-contained on purpose. The design marks this group with an ID
   (`#certGroup`, (1,0,0)) so it can out-rank `.badge-group + .badge-group`,
   which paints a left divider between groups. Our port is all classes, so
   `.sp2-cert-group` at (0,1,0) would LOSE to that (0,2,0) sibling rule and the
   divider would come back - and again under the 767px block, which re-points it
   at border-top. So the element simply does not carry `sp2-badge-group`, the
   sibling rule cannot match it, and these two lines replace what it inherited. */
.sp2-cert-group {display:flex;flex-direction:column;gap:12px;flex-basis:100%;margin-top:8px;}
.sp2-cert-tiles {display:flex;gap:10px;flex-wrap:wrap;}
.sp2-cert-tile {
  width:62px;min-height:62px;background:var(--white);border-radius:10px;
  box-shadow:0 2px 10px rgba(0,0,0,.28);
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:4px;padding:7px 5px;text-align:center;}
.sp2-cert-tile svg {width:20px;height:20px;flex:none;}
.sp2-cert-tile .sp2-cert-name {
  font-family:var(--font-head);font-weight:700;font-size:9px;line-height:1.15;
  letter-spacing:.2px;color:var(--navy);}
.sp2-detail-main {min-width:0;}
.sp2-sect {padding:44px 0;border-bottom:1px solid var(--border);scroll-margin-top:70px;}
.sp2-sect:first-of-type {padding-top:40px;}
/* The LAST section on the page draws a border-bottom straight above the site
   footer — a rule with nothing under it to separate. Removed for whichever
   section ends the page: the claim block is last on an unclaimed profile, but
   `ClaimV2` returns null when `is_claimed === 1`, so on a claimed product
   Interview or Media ends it instead and would inherit the same stray line. */
.sp2-detail-main > .sp2-sect:last-child {border-bottom:0;}
/* `.sp2-claim` already carries its own `margin-top:32px`, so the section's 44px
   top padding stacked with it into ~76px of empty band under Media. The box
   keeps its own margin; the section stops adding a second gap. */
#claim-section {padding-top:0;}
.sp2-sect__head {margin-bottom:24px;}
.sp2-sect__head .sp2-eyebrow {margin-bottom:10px;}
.sp2-sect__head .sp2-sub {margin-top:12px;max-width:760px;}
.sp2-sentiment-top {display:flex;justify-content:space-between;font-size:12px;color:var(--muted);margin-bottom:6px;}
.sp2-sentiment-bar {display:flex;height:10px;border-radius:var(--pill);overflow:hidden;}
.sp2-sentiment-bar span {display:block;height:100%;}
.sp2-sentiment-legend {display:flex;gap:14px;flex-wrap:wrap;margin-top:8px;font-size:12px;color:var(--muted);}
.sp2-sentiment-legend i {width:10px;height:10px;border-radius:3px;display:inline-block;margin-right:5px;vertical-align:-1px;}
.sp2-insight-sources {display:flex;gap:7px;flex-wrap:wrap;margin-top:14px;}
.sp2-source-chip {display:inline-flex;align-items:center;gap:6px;background:var(--surface-2);border:1px solid var(--border);border-radius:var(--pill);padding:5px 11px;font-size:12.5px;color:var(--navy);}
.sp2-source-chip b {font-family:var(--font-head);font-weight:600;}
.sp2-source-chip .sp2-sc-count {color:var(--muted);}
.sp2-prose {color:var(--navy);font-size:16px;line-height:1.7;}
.sp2-prose p {margin:0 0 18px;}
.sp2-prose strong {font-weight:600;}
/* Read-more clamp — the SAME MECHANISM as the company profile
   (`.cp2-about-text` / `.cp2-collapsed` in company-profile-v2.css), not the
   design file's max-height animation.

   OverviewV2 marks the overflow paragraphs `.sp2-hide` on the server; the
   client toggles `.sp2-collapsed` on the container, so nothing is measured and
   nothing animates a height. That is deliberate: `max-height` cannot transition
   to `auto`, so the design's version has to write a pixel height read from
   `scrollHeight`, which goes stale whenever the text reflows (font swap,
   breakpoint change) and clips the tail.

   ⚠️ The marker class is `.sp2-hide`, NOT the company sheet's bare `.hide`.
   common.css ships a global `.hide {display:none !important}`, which is why the
   company rules need `!important` + `revert` to out-weigh it on expand. A
   prefixed class has no such competitor, so plain rules are enough here — and
   an unprefixed `.hide` in THIS sheet would leak site-wide, since React 19
   `precedence` keeps it in <head> across client-side navigation (Wave 33). */
.sp2-prose .sp2-hide {display:none;}
.sp2-prose:not(.sp2-collapsed) .sp2-hide {display:revert;}
/* Collapsed, the real last child is a hidden block, so the last VISIBLE
   paragraph keeps its 18px bottom margin and opens a gap above the toggle. */
.sp2-prose.sp2-collapsed > *:has(+ .sp2-hide) {margin-bottom:0;}
.sp2-read-more {margin-top:6px;}
.sp2-card {background:var(--white);border:1px solid var(--border);border-radius:var(--r-lg);}
.sp2-card--pad {padding:24px;}
.sp2-spec-card {padding:26px;}
.sp2-spec-grid {
  display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));
  gap:28px 24px;}
.sp2-spec-col h4 {
  font-family:var(--font-body);font-weight:500;font-size:12px;letter-spacing:1.5px;
  text-transform:uppercase;color:var(--gold);margin:0 0 14px;}
.sp2-spec-list {list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:10px;}
.sp2-spec-list li {display:flex;align-items:flex-start;gap:8px;font-size:15px;color:var(--navy);}
.sp2-spec-list li svg {width:16px;height:16px;flex:none;margin-top:2px;}
.sp2-spec-more {color:var(--gold);font-weight:600;font-size:14px;text-align:left;padding:0;font-family:inherit;}
.sp2-spec-more:hover {text-decoration:underline;}
/* Knowledge Base entries that carry a URL render as outbound links. Colour is
   pinned across states for the same reason as the block at the end of this
   sheet: common.css `a:focus, a:hover {color:var(--secondary)}` is (0,1,1) and
   would otherwise leave a clicked entry stuck gold. */
.sp2-spec-list .sp2-spec-link {display:inline-flex;align-items:flex-start;gap:6px;}
.sp2-spec-list .sp2-spec-link .sp2-ext-i {width:13px;height:13px;flex:none;margin-top:3px;}
.sp2-spec-list a.sp2-spec-link:focus, .sp2-spec-list a.sp2-spec-link:focus-visible,
.sp2-spec-list a.sp2-spec-link:active, .sp2-spec-list a.sp2-spec-link:visited {color:var(--navy);}
.sp2-spec-list a.sp2-spec-link:hover {color:var(--gold);text-decoration:underline;}
.sp2-spec-facts {
  display:flex;flex-wrap:wrap;gap:24px 40px;justify-content:space-between;margin-top:26px;padding-top:22px;border-top:1px solid var(--border);}
.sp2-spec-facts .sp2-fact {flex:1 1 auto;min-width:120px;}
.sp2-fact {display:flex;flex-direction:column;gap:2px;}
.sp2-fact .sp2-k {font-size:12px;letter-spacing:1px;text-transform:uppercase;color:var(--muted);}
.sp2-fact .sp2-v {font-family:var(--font-head);font-weight:700;font-size:18px;color:var(--navy);}
.sp2-fact--pop {position:relative;cursor:help;}
.sp2-fact--pop .sp2-v {display:inline-flex;align-items:center;gap:6px;}
.sp2-fact--pop .sp2-info-i {width:14px;height:14px;flex:none;}
.sp2-lang-pop {
  position:absolute;bottom:calc(100% + 12px);right:0;
  width:max-content;max-width:min(320px,84vw);
  background:var(--white);border:1px solid var(--border);border-radius:var(--r-lg);
  box-shadow:var(--shadow-md);padding:14px 16px;
  font-family:var(--font-body);font-weight:400;font-size:14px;line-height:2;color:var(--navy);
  opacity:0;visibility:hidden;transform:translateY(4px);
  transition:opacity var(--ease),transform var(--ease),visibility var(--ease);
  z-index:30;}
.sp2-fact--pop:hover .sp2-lang-pop, .sp2-fact--pop:focus-within .sp2-lang-pop {opacity:1;visibility:visible;transform:none;}
.sp2-lang-pop .sp2-lang {white-space:nowrap;}
.sp2-lang-pop .sp2-sep {color:var(--gold);margin:0 8px;}
.sp2-fact--langs {width:100%;}
.sp2-lang-all {display:flex;flex-wrap:wrap;gap:8px;margin-top:12px;}
.sp2-lang-all .sp2-lang {font-size:13px;color:var(--navy);background:var(--surface-2);border:1px solid var(--border);border-radius:var(--pill);padding:5px 12px;white-space:nowrap;}
.sp2-gallery {display:flex;flex-direction:column;gap:16px;}
.sp2-gallery__stage {
  position:relative;border:1px solid var(--border);border-radius:var(--r-lg);overflow:hidden;
  aspect-ratio:16/9;background:linear-gradient(135deg,#eef1f6,#dfe4ec);}
.sp2-shot {position:absolute;inset:0;display:flex;align-items:center;justify-content:center;}
.sp2-shot svg {width:100%;height:100%;}
.sp2-shot--video::after {
  content:"";position:absolute;inset:0;background:rgba(23,25,35,.35);}
.sp2-play {
  position:absolute;z-index:2;width:64px;height:64px;border-radius:50%;
  background:var(--gold);display:flex;align-items:center;justify-content:center;
  box-shadow:0 6px 20px rgba(0,0,0,.25);}
.sp2-play svg {width:22px;height:22px;fill:var(--navy);}
.sp2-gallery__thumbs {display:flex;gap:12px;overflow-x:auto;padding-bottom:4px;scrollbar-width:thin;}
.sp2-thumb {
  flex:none;width:150px;aspect-ratio:16/9;border-radius:var(--r-sm);overflow:hidden;
  border:2px solid transparent;cursor:pointer;background:linear-gradient(135deg,#eef1f6,#dfe4ec);
  position:relative;transition:var(--ease);}
.sp2-thumb.sp2-active {border-color:var(--gold);}
.sp2-thumb svg {width:100%;height:100%;}
.sp2-thumb .sp2-mini-play {position:absolute;inset:0;display:flex;align-items:center;justify-content:center;}
.sp2-thumb .sp2-mini-play span {width:28px;height:28px;border-radius:50%;background:var(--gold);display:flex;align-items:center;justify-content:center;}
.sp2-thumb .sp2-mini-play svg {width:11px;height:11px;fill:var(--navy);}
.sp2-features {display:grid;grid-template-columns:280px minmax(0,1fr);gap:0;border:1px solid var(--border);border-radius:var(--r-lg);overflow:hidden;}
.sp2-feature-tabs {background:var(--surface-2);border-right:1px solid var(--border);padding:8px;display:flex;flex-direction:column;gap:2px;}
.sp2-feature-tab {
  text-align:left;padding:14px 16px;border-radius:var(--r-sm);font-weight:600;font-size:15px;
  color:var(--muted);transition:var(--ease);display:flex;align-items:center;justify-content:space-between;gap:8px;}
.sp2-feature-tab:hover {background:#eceef1;color:var(--navy);}
.sp2-feature-tab.sp2-active {background:var(--white);color:var(--navy);box-shadow:var(--shadow-sm);}
.sp2-feature-tab.sp2-active .sp2-caret {opacity:1;}
.sp2-feature-tab .sp2-caret {opacity:0;color:var(--gold);}
.sp2-feature-panelwrap {padding:28px;}
.sp2-feature-panel {display:none;}
.sp2-feature-panel.sp2-active {display:block;animation:fade .35s ease;}
.sp2-feature-panel h4 {font-family:var(--font-head);font-weight:700;font-size:18px;margin:0 0 4px;}
/* The design's 4px assumes a `.sp2-focus-line` sits between the heading and the
   list and supplies the real gap with its own 18px bottom margin. `focus` is
   optional in the data, so on a product without one the heading landed directly
   on the first bullet. When no focus line follows, the h4 supplies that gap
   itself — matching the spacing the design shows above the list either way. */
.sp2-feature-panel h4:not(:has(+ .sp2-focus-line)) {margin-bottom:18px;}
.sp2-feature-panel .sp2-focus-line {color:var(--gold);font-weight:600;font-size:13px;letter-spacing:1px;text-transform:uppercase;margin:0 0 18px;}
.sp2-feature-panel .sp2-focus-link {display:inline-flex;align-items:center;gap:6px;transition:var(--ease);}
.sp2-feature-panel .sp2-focus-link:hover {color:#b58f52;text-decoration:underline;}
.sp2-feature-panel .sp2-focus-link .sp2-ext-i {width:13px;height:13px;flex:none;}
.sp2-feature-list {list-style:none;margin:0;padding:0;columns:2;column-gap:24px;}
.sp2-feature-list li {display:flex;align-items:flex-start;gap:8px;font-size:15px;color:var(--navy);break-inside:avoid;margin-bottom:12px;}
.sp2-feature-list li svg {width:16px;height:16px;flex:none;margin-top:2px;}
.sp2-feature-list li .sp2-li-text {flex:1;}
@keyframes fade {
  from {opacity:0;transform:translateY(4px);}
  to {opacity:1;transform:none;}
}
.sp2-sub-label {
  font-family:var(--font-head);font-weight:700;font-size:15px;
  color:var(--navy);margin:28px 0 16px;}
.sp2-price-summary {
  display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
  gap:1px;background:var(--border);border:1px solid var(--border);border-radius:var(--r-lg);overflow:hidden;margin-bottom:24px;}
.sp2-price-cell {background:var(--white);padding:18px 20px;}
.sp2-price-cell .sp2-k {font-size:12px;letter-spacing:1px;text-transform:uppercase;color:var(--muted);margin-bottom:6px;}
.sp2-price-cell .sp2-v {font-family:var(--font-head);font-weight:700;font-size:17px;color:var(--navy);display:flex;align-items:center;gap:6px;}
.sp2-price-cell .sp2-v svg {width:15px;height:15px;}
.sp2-price-desc {background:var(--gold-soft);border:1px solid #f0e3c8;border-radius:var(--r-lg);padding:18px 20px;font-size:15px;color:var(--navy);margin-bottom:20px;}
.sp2-price-actions {display:flex;flex-wrap:wrap;gap:12px;margin-bottom:32px;}
.sp2-packages {display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:16px;}
.sp2-pkg {border:1px solid var(--border);border-radius:var(--r-lg);padding:22px;display:flex;flex-direction:column;gap:14px;transition:var(--ease);background:var(--white);}
.sp2-pkg:hover {border-color:var(--gold);box-shadow:var(--shadow-md);}
.sp2-pkg--featured {border-color:var(--gold);position:relative;}
.sp2-pkg__ribbon {position:absolute;top:-10px;right:16px;background:var(--gold);color:var(--navy);font-size:11px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;padding:3px 10px;border-radius:var(--pill);}
.sp2-pkg__name {font-weight:600;font-size:14px;letter-spacing:1px;text-transform:uppercase;color:var(--muted);}
.sp2-pkg__price {font-family:var(--font-head);font-weight:800;font-size:30px;color:var(--navy);}
.sp2-pkg__price span {font-size:14px;font-weight:500;color:var(--muted);}
.sp2-pkg__feats {list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:10px;}
.sp2-pkg__feats li {display:flex;gap:8px;font-size:14px;color:var(--navy);}
.sp2-pkg__feats svg {width:15px;height:15px;flex:none;margin-top:2px;}
.sp2-interview__person {display:flex;align-items:center;gap:12px;margin-bottom:22px;}
.sp2-interview__person .sp2-avatar {width:44px;height:44px;border-radius:50%;background:linear-gradient(135deg,var(--gold),#e0c48c);display:flex;align-items:center;justify-content:center;color:var(--white);font-family:var(--font-head);font-weight:700;font-size:16px;flex:none;}
.sp2-interview__person .sp2-who {line-height:1.3;}
.sp2-interview__person .sp2-who .sp2-n {font-weight:600;font-size:16px;}
.sp2-interview__person .sp2-who .sp2-r {font-size:13px;color:var(--muted);}
.sp2-qa {background:var(--white);border:1px solid var(--border);border-radius:var(--r-lg);padding:26px;}
.sp2-qa .sp2-q {font-weight:600;font-size:16px;color:var(--navy);margin:0 0 10px;}
.sp2-qa .sp2-a {color:var(--muted);font-size:15px;line-height:1.7;margin:0 0 24px;}
.sp2-qa .sp2-a:last-of-type {margin-bottom:22px;}
/* Q&A clamp — mirrors the company profile's `.cp2-interview-body.is-clamped`.
   The height is measured on the client (a variable number of pairs has no
   predictable rendered height), so `.sp2-clamped` is only applied when the body
   actually overflows. The fade resolves to `--white` because `.sp2-qa` is a
   white card; on a different background the gradient would show a hard edge. */
.sp2-qa__body {position:relative;}
.sp2-qa__body.sp2-clamped {max-height:480px;overflow:hidden;}
.sp2-qa__body.sp2-clamped::after {
  content:"";position:absolute;left:0;right:0;bottom:0;height:84px;
  background:linear-gradient(to top,var(--white),rgba(255,255,255,0));
  pointer-events:none;}
.sp2-qa__toggle {margin-top:4px;}
.sp2-analytics {display:grid;grid-template-columns:315px minmax(0,1fr);gap:0;border:1px solid var(--border);border-radius:var(--r-lg);overflow:hidden;margin-bottom:28px;}
.sp2-analytics__score {padding:32px 25px;border-right:1px solid var(--border);display:flex;flex-direction:column;align-items:center;text-align:center;gap:8px;}
.sp2-analytics__score .sp2-big {font-family:var(--font-head);font-weight:800;font-size:46px;color:var(--navy);line-height:1;}
.sp2-analytics__score .sp2-rev {font-size:14px;color:var(--muted);}
.sp2-bars {padding:25px;display:flex;flex-direction:column;gap:14px;justify-content:center;}
.sp2-bar-row .sp2-bar-top {display:flex;justify-content:space-between;font-size:14px;color:var(--navy);margin-bottom:6px;}
.sp2-bar-track {height:8px;border-radius:var(--pill);background:var(--surface);overflow:hidden;}
.sp2-bar-fill {height:100%;border-radius:var(--pill);background:var(--gold);}
.sp2-voice {display:grid;grid-template-columns:1fr 1fr;gap:24px;}
.sp2-voice__col h4 {font-family:var(--font-head);font-weight:700;font-size:16px;margin:0 0 14px;}
.sp2-voice__list {list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:12px;}
.sp2-voice__list li {display:flex;gap:10px;font-size:15px;color:var(--muted);line-height:1.5;}
.sp2-voice__list li svg {width:16px;height:16px;flex:none;margin-top:2px;}
.sp2-voice__list.sp2-neg li svg path {stroke:#c98a2e;}
.sp2-reviews-head {display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:14px;margin-bottom:20px;}
.sp2-reviews-head .sp2-score-inline {display:flex;align-items:center;gap:10px;font-weight:600;font-size:18px;}
.sp2-reviews-tools {display:flex;align-items:center;gap:12px;}
.sp2-select {position:relative;}
.sp2-select__btn {display:inline-flex;align-items:center;gap:8px;border:1px solid var(--border);border-radius:var(--r-sm);padding:9px 14px;font-size:14px;font-weight:600;background:var(--white);}
.sp2-select__btn svg {width:12px;height:12px;}
.sp2-select__menu {position:absolute;right:0;top:calc(100% + 6px);background:var(--white);border:1px solid var(--border);border-radius:var(--r-md);box-shadow:var(--shadow-md);min-width:170px;padding:6px;display:none;z-index:20;}
.sp2-select.sp2-open .sp2-select__menu {display:block;}
.sp2-select__menu button {display:block;width:100%;text-align:left;padding:9px 12px;border-radius:var(--r-sm);font-size:14px;}
.sp2-select__menu button:hover {background:var(--surface-2);}
/* 🔴 `scroll-margin-top` is what makes a SHARED REVIEW LINK land correctly.
   `ReviewShareButton` builds `/software/{slug}?page=N#review-{id}` and this rule's element
   carries that `id`, so without the offset the review lands UNDER the sticky `.sp2-subnav`
   and the reader sees the wrong review. Matches `.sp2-sect` above (`--nav-h` is 52px), which
   is why the pager's `#reviews` links already land correctly.
   The v1 page solved this with a client component (`ReviewHashScroller`) that measured
   `.profile-navigation-section` — a class the v2 page does not render at all, so porting
   that component forward would have measured 0 and fixed nothing. CSS needs no JS and
   cannot drift from the markup. */
.sp2-review {margin-bottom:16px;border:1px solid var(--border);border-radius:var(--r-lg);overflow:hidden;background:var(--white);scroll-margin-top:70px;}
.sp2-review__top {padding:20px;display:flex;flex-direction:column;gap:16px;}
.sp2-review__id {display:flex;gap:16px;align-items:flex-start;}
.sp2-review__id .sp2-avatar {width:42px;height:42px;border-radius:50%;flex:none;background:linear-gradient(135deg,#c8cdd6,#a9b0bb);display:flex;align-items:center;justify-content:center;color:var(--white);font-weight:700;}
.sp2-review__who {flex:1;min-width:0;}
.sp2-review__who .sp2-line1 {display:flex;align-items:center;gap:10px;flex-wrap:wrap;}
.sp2-review__who .sp2-name {font-weight:600;font-size:14px;color:var(--navy);}
.sp2-review__who .sp2-date {color:var(--muted);font-size:14px;margin-top:4px;}
.sp2-share-btn {width:40px;height:40px;border:1px solid var(--border);border-radius:var(--r-sm);display:flex;align-items:center;justify-content:center;flex:none;transition:var(--ease);}
.sp2-share-btn:hover {border-color:var(--navy);}
.sp2-share-btn svg {width:18px;height:18px;}
.sp2-review__quote {font-weight:600;font-size:20px;line-height:1.6;color:var(--navy);margin:0;}
.sp2-review__ratings {padding:0 20px 16px;border-top:1px solid var(--border);padding-top:16px;display:flex;gap:40px;align-items:stretch;flex-wrap:wrap;}
/* `align-items:stretch` (was `center`) is what makes the gold overall-rating
   box match the height of the per-dimension list beside it: in a flex row,
   stretch sizes every item to the row's cross size, which is the tallest item.
   The box is then a flex COLUMN with `justify-content:flex-start` so its label
   and score stay pinned to the top of that taller box instead of centring in
   the new empty space. */
.sp2-overall-box {
  background:var(--gold-soft);border-radius:var(--r-lg);padding:10px 15px;min-width:210px;
  display:flex;flex-direction:column;justify-content:flex-start;}
.sp2-overall-box .sp2-lbl {font-weight:500;font-size:16px;margin-bottom:6px;}
.sp2-overall-box .sp2-val {display:flex;align-items:center;gap:8px;font-weight:600;}
.sp2-rating-cols {flex:1;min-width:220px;display:flex;flex-direction:column;gap:10px;}
.sp2-rating-cols .sp2-rc {display:flex;justify-content:space-between;align-items:center;font-size:16px;gap:8px;}
.sp2-rating-cols .sp2-rc .sp2-rv {display:flex;align-items:center;gap:6px;}
.sp2-review__body {padding:20px;border-top:1px solid var(--border);}
.sp2-review__tags {display:flex;gap:10px;flex-wrap:wrap;margin-bottom:16px;}
.sp2-review__text {color:var(--muted);font-size:16px;line-height:1.6;margin:0;}
/* Review bodies are vendor/reviewer HTML: ~9% carry real <p>/<ul>/<li> markup
   (a Pros/Cons list is the common shape). The design only ever drew a plain
   paragraph, so without these the list falls back to UA margins and renders
   with a blank line between every bullet. */
.sp2-review__text p {margin:0 0 12px;}
.sp2-review__text p:last-child {margin-bottom:0;}
.sp2-review__text ul, .sp2-review__text ol {margin:0 0 12px;padding-left:22px;}
.sp2-review__text ul {list-style:disc;}
.sp2-review__text ol {list-style:decimal;}
.sp2-review__text li {margin:0 0 4px;}
.sp2-review__text li p {margin:0;}
.sp2-review__text li:last-child {margin-bottom:0;}
.sp2-review__text strong, .sp2-review__text b {font-weight:600;color:var(--navy);}
.sp2-review__text .sp2-full {display:none;}
.sp2-review.sp2-expanded .sp2-review__text .sp2-full {display:inline;}
.sp2-review.sp2-expanded .sp2-review__text .sp2-ellipsis {display:none;}
.sp2-review__toggle {display:inline-flex;align-items:center;gap:8px;color:var(--gold);font-weight:600;font-size:16px;margin-top:16px;}
.sp2-review__toggle svg {width:12px;height:12px;transition:var(--ease);}
.sp2-review.sp2-expanded .sp2-review__toggle svg {transform:rotate(180deg);}
.sp2-verified-tag {display:inline-flex;align-items:center;gap:5px;color:var(--green);font-size:13px;font-weight:600;}
.sp2-verified-tag svg {width:14px;height:14px;}
.sp2-pager {display:flex;align-items:center;justify-content:center;gap:8px;margin-top:24px;flex-wrap:wrap;}
/* The design drew the pager with <button>s. The real pager uses <a> so each
   page stays crawlable, shareable and works without JS, so both are matched. */
.sp2-pager button, .sp2-pager a, .sp2-pager > span {
  display:inline-flex;align-items:center;justify-content:center;
  width:38px;height:38px;border-radius:var(--r-sm);border:1px solid var(--border);
  font-weight:600;font-size:14px;transition:var(--ease);}
.sp2-pager .sp2-pager__gap {border:0;width:auto;min-width:20px;color:var(--muted);}
.sp2-pager button:hover, .sp2-pager a:hover {border-color:var(--navy);}
.sp2-pager button.sp2-active, .sp2-pager > span.sp2-active {background:var(--gold);border-color:var(--gold);color:var(--navy);}
.sp2-pager .sp2-np {width:auto;padding:0 14px;}
/* ---- AI-generated adoption insights (#insights, sponsors only) -------------
   Ported from the design § `.adopt-card`. Sits between Pricing and Integrations.
   The section renders on roughly half the sponsor roster by design — most of
   these rules are unused on any given page. */
.sp2-adopt {border:1px solid var(--border);border-radius:var(--r-md);padding:18px 20px;max-width:760px;}
.sp2-adopt__top {display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:12px;}
.sp2-adopt__meta {font-size:13px;color:var(--muted);}
.sp2-ai-badge {
  display:inline-flex;align-items:center;gap:6px;
  background:var(--gold-soft);border:1px solid var(--gold);color:#8a6d2f;
  font-family:var(--font-head);font-weight:700;font-size:11px;
  letter-spacing:.6px;text-transform:uppercase;
  border-radius:var(--pill);padding:5px 11px;line-height:1;}
.sp2-ai-badge svg {width:12px;height:12px;flex:none;color:var(--gold);}

.sp2-adopt__points {list-style:none;margin:0 0 16px;padding:0;display:flex;flex-direction:column;gap:9px;}
.sp2-adopt__points li {display:flex;gap:9px;font-size:14.5px;line-height:1.5;color:var(--navy);}
.sp2-adopt__points li::before {content:"";width:6px;height:6px;border-radius:50%;background:var(--gold);flex:none;margin-top:7px;}

.sp2-sentiment__top {display:flex;justify-content:space-between;font-size:12px;color:var(--muted);margin-bottom:6px;}
.sp2-sentiment__bar {display:flex;height:10px;border-radius:var(--pill);overflow:hidden;}
.sp2-sentiment__bar span {display:block;height:100%;}
.sp2-sentiment__legend {display:flex;gap:14px;flex-wrap:wrap;margin-top:8px;font-size:12px;color:var(--muted);}
.sp2-sentiment__legend i {width:10px;height:10px;border-radius:3px;display:inline-block;margin-right:5px;vertical-align:-1px;}
/* Segment colours are shared by the bar and its legend swatches, so they are
   defined once on the modifier rather than twice per element.
   ⚠️ Negative is the design's AMBER (#e0a13c), not a red — deliberate: this is
   an unverified machine reading of strangers' comments on a paying sponsor's
   page, and alarm-red overstates how much it should be trusted. */
.sp2-sent--pos {background:var(--green);}
.sp2-sent--neu {background:#c9cdd6;}
.sp2-sent--neg {background:#e0a13c;}

.sp2-adopt__sources {display:flex;gap:7px;flex-wrap:wrap;margin-top:14px;}
.sp2-source-chip {
  display:inline-flex;align-items:center;gap:6px;
  background:var(--surface-2);border:1px solid var(--border);
  border-radius:var(--pill);padding:5px 11px;font-size:12.5px;color:var(--navy);}
.sp2-source-chip b {font-family:var(--font-head);font-weight:600;}

.sp2-ai-disclaimer {margin:12px 0 0;font-size:12px;line-height:1.5;color:var(--muted);max-width:760px;}

.sp2-integrations {display:flex;flex-wrap:wrap;gap:12px;}
.sp2-claim {
  margin:32px 0 0;background:var(--navy);border-radius:var(--r-lg);
  padding:26px 28px;display:flex;align-items:center;justify-content:space-between;gap:20px;flex-wrap:wrap;}
.sp2-claim h3 {font-family:var(--font-head);font-weight:700;color:var(--white);font-size:20px;margin:0 0 4px;}
.sp2-claim p {color:#c9cdd6;font-size:14px;margin:0;}
/* ✅ RESTORED 2026-09-18 — the sticky sub-nav this was waiting on now exists
   (`SubNavV2`), so the `var(--nav-h)` allowance is back. It clears `.sp2-subnav`,
   which is `position:sticky;top:0`; without it the stuck rail card slides under
   the bar. The site header itself is `position:relative`
   (src/styles/header-v2.css) so it scrolls away and needs no clearance.
   ⚠️ If the sub-nav is ever removed again, drop this term back to plain 20px or
   the card parks 52px low with an empty band above it. */
.sp2-detail-rail {position:sticky;top:calc(var(--nav-h) + 20px);align-self:start;margin-top:28px;}
.sp2-rail-card {background:var(--surface);border:1px solid var(--border);border-radius:var(--r-md);padding:20px;display:flex;flex-direction:column;gap:20px;}
.sp2-rail-card .sp2-stack {display:flex;flex-direction:column;gap:10px;}
/* Rail brand block — revealed once the masthead scrolls away (RailBrandV2),
   mirroring the company profile's `.cp2-side-brand`.
   ⚠️ It collapses via max-height + opacity rather than `display:none` so the
   reveal can animate; the negative margin cancels the parent card's 20px gap
   while hidden, so a collapsed block leaves NO space above the CTA. */
.sp2-rail-brand {
  display:flex;flex-direction:column;align-items:flex-start;gap:10px;
  max-height:0;margin-bottom:-20px;opacity:0;overflow:hidden;
  pointer-events:none;
  transition:max-height .3s ease,margin-bottom .3s ease,opacity .22s ease;}
.sp2-rail-brand.sp2-shown {max-height:200px;margin-bottom:0;opacity:1;pointer-events:auto;}
.sp2-rail-brand__top {display:flex;align-items:center;gap:12px;width:100%;}
/* `contain`, not `cover` — product logos are rarely square, and cover crops
   and upscales them. Matches the masthead logo's treatment. */
.sp2-rail-brand__logo {
  width:44px;height:44px;flex:0 0 auto;border-radius:8px;object-fit:contain;
  padding:3px;background:var(--white);border:1px solid var(--border);}
.sp2-rail-brand__initials {
  display:flex;align-items:center;justify-content:center;
  font-family:var(--font-head);font-weight:700;font-size:15px;color:var(--navy);}
.sp2-rail-brand__name {
  flex:1 1 auto;min-width:0;font-family:var(--font-head);font-weight:700;
  font-size:17px;line-height:1.25;color:var(--navy);}
.sp2-rail-brand__rating {display:inline-flex;align-items:center;gap:8px;}
.sp2-rail-brand__rating-text {
  font-family:var(--font-head);font-weight:700;font-size:14px;line-height:1;
  color:var(--navy);white-space:nowrap;}
.sp2-promo-banner {
  position:relative;overflow:hidden;margin-top:16px;
  background:linear-gradient(150deg,#eef1ff 0%,#ffffff 55%);
  border:1px solid #e2e6f5;
  border-radius:var(--r-md);padding:22px 20px 20px;color:var(--navy);}
.sp2-promo-banner__foot {display:flex;align-items:center;gap:8px;margin-top:16px;padding-top:14px;border-top:1px solid #e4e8f4;}
.sp2-promo-banner__foot-lbl {font-family:var(--font-head);font-weight:600;font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:#9aa2b1;}
.sp2-promo-banner__logo {display:block;height:16px;width:auto;}
.sp2-promo-banner__title {
  font-family:var(--font-head);font-weight:800;font-size:18px;
  line-height:1.3;margin:0 0 14px;color:var(--navy);}
.sp2-promo-banner__meta {font-size:13px;line-height:1.55;color:var(--muted);margin:0 0 16px;}
.sp2-promo-banner__cta {
  display:inline-flex;align-items:center;justify-content:center;gap:7px;
  height:40px;padding:0 20px;border-radius:var(--pill);
  background:#2340e8;color:var(--white);
  font-family:var(--font-body);font-weight:600;font-size:14px;
  transition:var(--ease);}
.sp2-promo-banner__cta:hover {background:#1a33c4;}
.sp2-promo-banner__cta svg {width:14px;height:14px;flex:none;}
.sp2-rail-facts {display:flex;flex-direction:column;gap:0;background:var(--white);border:1px solid var(--border);border-radius:var(--r-md);overflow:hidden;}
.sp2-rail-fact {display:flex;justify-content:space-between;align-items:center;gap:8px;padding:11px 14px;font-size:14px;}
.sp2-rail-fact + .sp2-rail-fact {border-top:1px solid var(--border);}
.sp2-rail-fact .sp2-k {color:var(--muted);}
.sp2-rail-fact .sp2-v {font-weight:600;color:var(--navy);text-align:right;}
.sp2-rail-why {display:flex;flex-direction:column;gap:14px;}
.sp2-rail-why .sp2-eyebrow {margin-bottom:0;}
.sp2-rail-why ul {list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:12px;}
.sp2-rail-why li {display:flex;gap:8px;font-size:15px;line-height:1.5;color:var(--navy);}
.sp2-rail-why li svg {width:18px;height:18px;flex:none;margin-top:1px;}
.sp2-rail-verified {display:flex;align-items:center;justify-content:center;gap:6px;font-size:13px;color:var(--muted);}
.sp2-rail-verified svg {width:15px;height:15px;}
.sp2-rail-verified a {color:var(--gold);font-weight:600;}
.sp2-site-footer {background:var(--navy);color:#c9cdd6;margin-top:0;padding:56px 0 28px;}
.sp2-footer-grid {display:grid;grid-template-columns:1.6fr 1fr 1fr 1fr;gap:40px;}
.sp2-footer-brand .sp2-brand {color:var(--white);margin-bottom:14px;}
.sp2-footer-brand address {font-style:normal;font-size:14px;line-height:1.7;}
.sp2-footer-brand .sp2-fnav {display:flex;gap:16px;margin-top:16px;font-size:13px;}
.sp2-footer-brand .sp2-fnav a:hover {color:var(--gold);}
.sp2-footer-col h5 {font-family:var(--font-head);color:var(--white);font-size:13px;letter-spacing:1.5px;text-transform:uppercase;margin:0 0 16px;}
.sp2-footer-col ul {list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:11px;}
.sp2-footer-col a {font-size:14px;transition:var(--ease);}
.sp2-footer-col a:hover {color:var(--gold);}
.sp2-footer-bottom {border-top:1px solid #2b2f3a;margin-top:40px;padding-top:22px;text-align:center;font-size:13px;color:#8a909b;}
/* ══ Responsive ═══════════════════════════════════════════════════════════
   🔴 BREAKPOINTS MATCH THE COMPANY PROFILE (owner, 2026-09-16), NOT the design
   file. The design shipped 1120 / 980 / 820 / 560 — values that exist nowhere
   else on this site, so a browser at 900px collapsed the software profile while
   leaving the company profile in its desktop layout, and the two pages changed
   shape at four widths that had nothing in common.

   The ladder is now the one `company-profile-v2.css` uses:

     1199   narrow the rail on a small desktop
     1024   STRUCTURAL — rail stops being sticky and moves ABOVE the content,
            every two-column grid collapses (company: `.cp2-aside` goes
            `position:static` into its own grid row at exactly this width)
     767    mobile — stacking that only makes sense on a phone
      640   small phone — the claim callout, mirroring `.cp2-notclaimed`

   Two things deliberately NOT copied from the company sheet, because this sheet
   already solves them better: its `.cp2-wrap {padding:0 16px}` at 767 (here
   `--gutter` is `clamp(16px,4vw,40px)`, which already bottoms out at 16px) and
   its fixed `.cp2-h2 {font-size:36px}` step-down (here `.sp2-h2` is
   `clamp(24px,3vw,32px)`, already fluid). Adding either would replace a fluid
   value with a stepped one — a regression, not parity. */
@media (max-width:1199px) {
  :root {--rail:340px;}
}
@media (max-width:1024px) {
  .sp2-detail__grid {grid-template-columns:1fr;}
  /* One column, three stacked rows — the same shape `.cp2-page` takes at this
     width, and the reason the rail sits right under the hero rather than at the
     bottom of the page. */
  .sp2-detail__grid > .sp2-masthead {grid-column:1;grid-row:1;}
  .sp2-detail__grid > .sp2-detail-rail {grid-column:1;grid-row:2;}
  .sp2-detail__grid > .sp2-detail-main {grid-column:1;grid-row:3;}
  /* The 40px `--gap` is a COLUMN gutter on desktop; once stacked it becomes a
     ROW gap and shows up twice — once under the hero band and again under the
     promo banner — so it is tightened here. */
  .sp2-detail__grid {gap:24px;}
  /* The 28px offset exists only to drop the STICKY rail below the desktop
     masthead's top edge. Stacked, it is pure dead space above the card. */
  .sp2-detail-rail {margin-top:0;}
  /* Overview is now the first `<section>` inside `.sp2-detail-main` (the
     masthead moved out of it), so it picks up the 40px first-section lead-in
     directly under the promo banner. */
  .sp2-sect:first-of-type {padding-top:24px;}
  /* 🔴 NO `order:-1` HERE — that is the company profile's mechanism and this
     DOM cannot take it. On `/company/*` the hero is a SIBLING of `.cp2-main`,
     so pulling the aside up lands it between hero and content. Here the
     MASTHEAD LIVES INSIDE `.sp2-detail-main`, so ordering the rail first put
     the Visit Website card above the product's own name and logo. The rail now
     simply falls after the content, which is what a single-column stack means
     for a grid child that is second in source order. */
  .sp2-detail-rail {position:static;}
  /* Rail is no longer sticky here, so the masthead is never off-screen while
     the card is visible — the brand block would just duplicate it. Same
     reasoning, and the same breakpoint, as `.cp2-side-brand`. */
  .sp2-rail-brand {display:none;}
  /* 🔴 The design's `height:auto` is REMOVED, not ported. `.sp2-detail__band`
     is `position:absolute; top:0` with no bottom anchor and no content, so
     `height:auto` computes to ZERO — the navy backdrop disappeared and
     `.sp2-masthead__title h1` (color:var(--white)) rendered white-on-white,
     along with the badge tiles. The band is JS-sized from `#identity` at every
     width instead; see BandV2. */
  .sp2-masthead {padding-top:32px;}
  .sp2-features {grid-template-columns:1fr;}
  .sp2-feature-tabs {flex-direction:row;overflow-x:auto;border-right:none;border-bottom:1px solid var(--border);}
  .sp2-feature-tab {white-space:nowrap;}
  .sp2-analytics {grid-template-columns:1fr;}
  .sp2-analytics__score {border-right:none;border-bottom:1px solid var(--border);}
  .sp2-voice {grid-template-columns:1fr;}
}
@media (max-width:767px) {
  .sp2-masthead__badges {flex-direction:column;gap:22px;}
  .sp2-badge-group + .sp2-badge-group {border-left:none;padding-left:0;border-top:1px solid #2b2f3a;padding-top:22px;}
  .sp2-feature-list {columns:1;}
  /* Overall-rating box above the per-dimension rows. Above 768px they stay
     side by side, matching the company's review card at the same width. */
  .sp2-review__ratings {flex-direction:column;align-items:stretch;gap:16px;}
  .sp2-overall-box {min-width:0;}
  .sp2-masthead__logo {width:60px;height:60px;}
  .sp2-spec-grid {gap:24px 20px;}
}
@media (max-width:640px) {
  /* Mirrors `.cp2-notclaimed` on the company profile: the callout stacks and
     its button goes full width rather than sitting at its text width. */
  .sp2-claim {flex-direction:column;align-items:flex-start;}
  .sp2-claim .sp2-btn {width:100%;justify-content:center;}
}
/* ── Link-state colour pinning ─────────────────────────────────────────────
   common.css ships `a:focus, a:hover {color: var(--secondary)}` — GOLD, at
   specificity (0,1,1). Every `.sp2-*` component colour is a single class,
   (0,1,0), so the GLOBAL WINS. Two visible defects came from exactly this:

     • an <a> KEEPS :focus after being clicked, so integration chips and outline
       buttons turned gold and STAYED gold after a click;
     • on `.sp2-btn-gold` that gold text landed on the gold button background,
       so "Get Free Trial" / "Visit Website" became unreadable on hover.

   Re-asserting each colour at `.sp2 a.<class>` (0,2,1) out-ranks the global.
   This is the same failure — and the same fix — as the company profile's
   Schedule a Call button.

   🔴 ORDER IS LOAD-BEARING, and not only against common.css. Every rule below
   is (0,2,1), so within this block SOURCE ORDER decides. `:hover` is therefore
   listed LAST for each class. Put the focus rules after it and hovering an
   ALREADY-FOCUSED element (i.e. hovering the button you just clicked) resolves
   to the focus colour — navy text on the navy hover background, invisible. The
   hover re-assert is required for the same reason even where an existing
   `.sp2-btn-outline:hover` (0,2,0) already beat the global: these (0,2,1)
   focus rules would otherwise out-rank it. */
.sp2 a.sp2-btn-gold:focus, .sp2 a.sp2-btn-gold:focus-visible,
.sp2 a.sp2-btn-gold:active, .sp2 a.sp2-btn-gold:visited,
.sp2 a.sp2-btn-gold:hover {color:var(--navy);}

.sp2 a.sp2-btn-soft:focus, .sp2 a.sp2-btn-soft:focus-visible,
.sp2 a.sp2-btn-soft:active, .sp2 a.sp2-btn-soft:visited,
.sp2 a.sp2-btn-soft:hover {color:var(--navy);}

.sp2 a.sp2-btn-outline:focus, .sp2 a.sp2-btn-outline:focus-visible,
.sp2 a.sp2-btn-outline:active, .sp2 a.sp2-btn-outline:visited {color:var(--navy);}
.sp2 a.sp2-btn-outline:hover {color:var(--white);}

.sp2 a.sp2-tag:focus, .sp2 a.sp2-tag:focus-visible,
.sp2 a.sp2-tag:active, .sp2 a.sp2-tag:visited {color:var(--navy);}
.sp2 a.sp2-tag:hover {background:var(--navy);color:var(--white);border-color:var(--navy);}

.sp2 a.sp2-promo-banner__cta:focus, .sp2 a.sp2-promo-banner__cta:focus-visible,
.sp2 a.sp2-promo-banner__cta:active, .sp2 a.sp2-promo-banner__cta:visited,
.sp2 a.sp2-promo-banner__cta:hover {color:var(--white);}

.sp2 a.sp2-focus-link:focus, .sp2 a.sp2-focus-link:focus-visible,
.sp2 a.sp2-focus-link:active, .sp2 a.sp2-focus-link:visited {color:var(--navy);}
.sp2 a.sp2-focus-link:hover {color:#b58f52;}

/* The masthead row sits on the dark band — these two are MEANT to be gold and
   light grey, so pinning keeps them from drifting to the global gold/each
   other's colour on focus. */
.sp2-rating-row a.sp2-write:focus, .sp2-rating-row a.sp2-write:focus-visible,
.sp2-rating-row a.sp2-write:active, .sp2-rating-row a.sp2-write:visited,
.sp2-rating-row a.sp2-write:hover {color:var(--gold);}

.sp2-rating-row a.sp2-claimed:focus, .sp2-rating-row a.sp2-claimed:focus-visible,
.sp2-rating-row a.sp2-claimed:active, .sp2-rating-row a.sp2-claimed:visited,
.sp2-rating-row a.sp2-claimed:hover {color:#c9cdd6;}
.sp2-rating-row a.sp2-claimed.sp2-unclaimed:focus,
.sp2-rating-row a.sp2-claimed.sp2-unclaimed:focus-visible,
.sp2-rating-row a.sp2-claimed.sp2-unclaimed:active,
.sp2-rating-row a.sp2-claimed.sp2-unclaimed:visited,
.sp2-rating-row a.sp2-claimed.sp2-unclaimed:hover {color:var(--gold);}

@media (prefers-reduced-motion:reduce) {
  .sp2 * {scroll-behavior:auto !important;transition:none !important;animation:none !important;}
}
