/* --------------------------------------------------------------------------
   TIER 1 TOKENS -- ground and scale, shared by every product.
   Declared on .hs-root (not :root) so they cannot leak into the rest of your
   WordPress site, and your theme cannot accidentally win a specificity fight.
   Signature colours (tier 2) live in each product's theme.css.
   -------------------------------------------------------------------------- */
.hs-root {
  /* Shell -- Theme.h Scheme::Blue */
  --rp-bg:        #0a0b11;
  --rp-panel:     #13141d;
  --rp-card:      #191a24;
  --rp-card2:     #20212d;
  --rp-border:    #292b39;
  --rp-border2:   #393c4e;
  --rp-text:      #eceef6;
  --rp-text2:     #969ab0;
  --rp-text3:     #5e617a;

  /* Type scale -- fluid, clamp() so it never needs a media query */
  --rp-f-display: clamp(2.6rem, 6.2vw, 5.1rem);
  --rp-f-h2:      clamp(1.95rem, 3.7vw, 3.05rem);
  --rp-f-h3:      clamp(1.15rem, 1.6vw, 1.4rem);
  --rp-f-lede:    clamp(1.05rem, 1.35vw, 1.24rem);
  --rp-f-body:    clamp(1rem, 1.05vw, 1.09rem);
  --rp-f-small:   0.875rem;
  --rp-f-micro:   0.845rem;   /* eyebrows / labels: was 0.72rem (+2pt) */

  /* Type families -- tier 1 so a product can restyle its whole page from
     its own theme.css by overriding two properties, instead of the ~20
     places base.css used to name a family literally. Whatever a product
     substitutes must also be added to the FONTS <link> in build.py, or the
     browser falls through to the next family in the stack. */
  --rp-font-display: "Space Grotesk", "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --rp-font-mono:    "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;

  /* Typographic feel -- line-height and tracking, tunable like the sizes */
  --rp-lh-head:   1.06;
  --rp-lh-body:   1.62;
  --rp-ls-head:   -0.028em;

  /* Rhythm */
  --rp-max:       1180px;
  --rp-gutter:    clamp(1.15rem, 4vw, 2.5rem);
  --rp-section:   clamp(4.5rem, 9vw, 8.5rem);
  --rp-r-sm:      10px;
  --rp-r:         16px;
  --rp-r-lg:      22px;

  /* Motion -- fast easings so hovers feel snappy, not floaty */
  --rp-fast:   140ms cubic-bezier(.22,.61,.36,1);
  --rp-med:    240ms cubic-bezier(.22,.61,.36,1);
  --rp-slow:   620ms cubic-bezier(.16,.84,.44,1);
  --rp-spring: 420ms cubic-bezier(.34,1.42,.64,1);
}

/* HardStop - tier-2 signature tokens. VALUES ONLY: one selector block, no
   extra rules. Declared on .hs-root, matching tier 1 in shared/css/tokens.css
   -- not :root, which would leak into the rest of the WordPress page and,
   worse, sit farther from the content than tier 1's own .hs-root default,
   so the nearer ancestor (tier 1) would silently win over this override.
   Waveform-widget colours are tier 3 and live in section.css. */
.hs-root {
  --rp-brand:          #ff5765;  /* clip red - also the logo bar */
  --rp-accent:         #3aa6ff;  /* Drive blue */
  --rp-accent-soft:    #7cc6ff;
  --rp-accent-2:       #ff5a8c;  /* Ceiling pink */
  --rp-accent-2-soft:  #ff92b5;
  --rp-good:           #34d399;  /* TP safety green */
  --rp-warn:           #ff9e3d;
  --rp-on-accent:      #edeae4;
}

/* HardStop tier-3: colours belonging to the waveform widget alone.
   Product-local by design - these are not part of the shared contract.
   Declared on .hs-root, matching tier 1 and tier 2, so the same
   nearest-ancestor override rules apply consistently to every tier. */
.hs-root {
  --rp-brass:     #c9a86a;  /* ceiling line on the waveform */
  --rp-wave-hi:   #bcd7e6;
  --rp-wave-lo:   #45626e;
  --rp-sig-red:   #e5484d;  /* clipper gain reduction */
  --rp-sig-green: #5bc88e;  /* TP limiter gain reduction */
}

/* Per-card accent for the one card that keys off the waveform's ceiling
   line colour -- mirrors the .hs-g-* rules in base.css but stays here
   because --rp-brass is product-local. */
.hs-g-brass { --rp-glow: var(--rp-brass); }

/* ==========================================================================
   HARDSTOP SALES PAGE -- structural stylesheet (tier 4 of the cascade)
   Tokens now live in three tiers, assembled ahead of this file by
   stylesheet() in build.py:
     tier 1  shared/css/tokens.css        ground + scale, every product
     tier 2  products/<slug>/theme.css    eight signature values
     tier 3  products/<slug>/section.css  product-local extras (optional)
   This file consumes those custom properties; it declares none of its own.
   ========================================================================== */

/* @property lets the browser interpolate a custom property instead of
   snapping between values. Without this the knob arc jumps; with it, it
   sweeps. Unsupported browsers ignore the block and just snap -- no harm. */
@property --arc { syntax: '<angle>'; inherits: true; initial-value: 0turn; }

/* --------------------------------------------------------------------------
   2. RESET -- scoped. Divi injects a lot of global CSS; this neutralises it
   inside our block only, without touching the rest of the site.
   -------------------------------------------------------------------------- */
.hs-root,
.hs-root *,
.hs-root *::before,
.hs-root *::after { box-sizing: border-box; }

.hs-root {
  margin: 0;
  padding: 0;
  background: var(--rp-bg);
  color: var(--rp-text);
  font-family: var(--rp-font-display);
  font-size: var(--rp-f-body);
  line-height: var(--rp-lh-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow-x: clip;
  position: relative;
  isolation: isolate;           /* keeps our z-indexes out of Divi's stack */
}

/* :where() contributes ZERO specificity, so every one of these rules weighs
   exactly as much as ".hs-root" alone (0,1,0) instead of (0,1,1).
   That matters: written the naive way, ".hs-root p { margin: 0 }" would beat
   ".hs-price__sub { margin-bottom: 1.5rem }" -- same class count, but the
   element selector tips it -- and component spacing would silently vanish.
   With :where() the reset still overpowers Divi's global styles but always
   loses to our own component classes. This is the single most useful
   specificity trick in modern CSS. */
.hs-root :where(h1, h2, h3, h4, p, ul, ol, li, figure, dl, dd, dt) {
  margin: 0; padding: 0; border: 0;
}
.hs-root :where(ul, ol) { list-style: none; }

/* Tables are the one place :where() is the WRONG tool. Divi ships global table
   chrome -- `table { border: 1px solid #eee; margin: 0 0 15px }` plus th/td
   borders and padding -- and some of those rules are class-scoped (0,1,1), so a
   zero-specificity :where() reset (0,1,0) would lose to them. These are written
   with a real element selector (0,1,1) instead: they tie with Divi and win on
   source order, because this <style> block is injected after the theme's.
   Left unreset, Divi's #eee border painted a bright rectangle around .hs-table
   and its 15px bottom margin dropped .hs-tablewrap's rounded border a row's
   worth below the table's actual edge -- the two outlines visibly came apart.
   Everything here is re-set properly by section 14; this only clears the theme.
   Section 14 sits later in the file, so it wins the same source-order tie. */
.hs-root table { border: 0; border-collapse: collapse; border-spacing: 0; margin: 0; background: none; }
.hs-root caption,
.hs-root thead, .hs-root tbody, .hs-root tfoot,
.hs-root tr, .hs-root th, .hs-root td {
  margin: 0; padding: 0; border: 0; background: none;
  font: inherit; color: inherit; text-align: inherit; vertical-align: inherit;
}

.hs-root :where(h1, h2, h3, h4) {
  font-weight: 700;
  line-height: var(--rp-lh-head);
  letter-spacing: var(--rp-ls-head);
  color: var(--rp-text);
}

.hs-root :where(img, svg, canvas, video, iframe) {
  display: block; max-width: 100%; height: auto;
}

/* :where() drops this to zero-for-the-selector specificity, so a component that
   sets its own colour (.hs-btn, below) wins even though it is also 1 class deep.
   Without it, .hs-root a (0,1,1) beat .hs-btn (0,1,0) and every filled button
   inherited body-text white instead of its dark --btn-fg. */
.hs-root :where(a) { color: inherit; text-decoration: none; }
.hs-root button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }

.hs-root ::selection { background: var(--rp-accent); color: #04060c; }

.hs-root :focus-visible {
  outline: 2px solid var(--rp-accent);
  outline-offset: 3px;
  border-radius: 6px;
}

/* --------------------------------------------------------------------------
   3. LAYOUT PRIMITIVES
   -------------------------------------------------------------------------- */
.hs-wrap {
  width: 100%;
  max-width: var(--rp-max);
  margin-inline: auto;
  padding-inline: var(--rp-gutter);
}
.hs-wrap--wide { max-width: 1400px; }

.hs-section { padding-block: var(--rp-section); position: relative; }
.hs-section--tight { padding-block: clamp(3rem, 5vw, 4.5rem); }

/* Hairline separators that fade at the edges -- subtler than a full border */
.hs-rule {
  height: 1px; border: 0; margin: 0;
  background: linear-gradient(90deg,
    transparent, var(--rp-border) 18%, var(--rp-border) 82%, transparent);
}

.hs-grid { display: grid; gap: clamp(1rem, 2vw, 1.6rem); }
.hs-grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr)); }
.hs-grid--3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 290px), 1fr)); }

.hs-center { text-align: center; }
/* Third-party storefront scripts (Audioloom's embedded storefront among them)
   show and hide their own elements by toggling the `hidden` attribute, and
   rely on the page having a rule that honours it. The UA default is weak
   enough that any display value overrides it, so this needs the !important
   the vendor asks for. No markup this repo generates carries the attribute -
   it exists for injected elements only. */
[hidden] { display: none !important; }
/* Visually hidden, still announced. For text that qualifies a visible label
   (e.g. spelling out what an "Official video" badge means) without repeating
   it on screen. */
.hs-vh {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  clip-path: inset(50%); overflow: hidden; white-space: nowrap;
}
.hs-measure { max-width: 62ch; }
.hs-measure-tight { max-width: 48ch; }
.hs-center .hs-measure,
.hs-center .hs-measure-tight { margin-inline: auto; }

/* --------------------------------------------------------------------------
   4. TYPOGRAPHY HELPERS
   -------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------
   SALE - banner, struck price, countdown

   SHARED, not per-product. These were written in clarity-delay/section.css
   because Clarity Delay was the only product with a sale block; the markup
   that uses them is emitted by the shared pricing.j2, so ANY product running
   a sale rendered this banner and only one product had the CSS to paint it.
   Every colour here comes from --rp-accent, which each theme declares, so the
   banner takes on whichever product it appears in.
   -------------------------------------------------------------------------- */
.hs-sale {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: .75rem 1.1rem;
  margin: 0 auto clamp(1.5rem, 3vw, 2.2rem);
  padding: .7rem 1.15rem;
  width: fit-content; max-width: 100%;
  /* No longer a pill: the countdown sits on its own line below the price, so
     a 999px radius would bow the sides of a two-line box. */
  border-radius: var(--rp-r-lg);
  border: 1px solid color-mix(in srgb, var(--rp-accent) 45%, transparent);
  background: color-mix(in srgb, var(--rp-accent) 9%, transparent);
}
.hs-sale__tag {
  font-family: var(--rp-font-mono);
  font-size: .62rem; font-weight: 700; letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--rp-on-accent); background: var(--rp-accent);
  border-radius: 999px; padding: .34em .8em;
}
.hs-sale__price { font-size: 1.05rem; color: var(--rp-text); }
.hs-sale__price s {
  color: var(--rp-text2); margin-right: .15em; text-decoration-thickness: .08em;
}
.hs-sale__price b { color: var(--rp-accent); font-weight: 700; }
/* OWN LINE. flex-basis:100% breaks the row inside the wrapping flex parent,
   and the hairline above separates the deadline from the price rather than
   letting the two read as one run-on strip. */
.hs-sale__clock {
  flex-basis: 100%; justify-content: center;
  padding-top: .62rem;
  border-top: 1px solid color-mix(in srgb, var(--rp-accent) 24%, transparent);
  display: inline-flex; align-items: baseline; gap: .5em;
  font-family: var(--rp-font-mono);
}
.hs-sale__clock-label {
  font-size: .6rem; letter-spacing: .14em; text-transform: uppercase;
  color: var(--rp-text3);
}
/* Tabular figures so the seconds ticking over does not shift the layout. */
.hs-sale__clock-val {
  font-size: .95rem; font-weight: 700; color: var(--rp-text);
  font-variant-numeric: tabular-nums;
}
/* The price it WAS. Sized absolutely, not in em: em here resolves against
   .hs-price__amt, whose font-size is the card's - the 2.6-3.5rem figure lives
   on the sibling <b> - so .55em rendered this at about 9px with a strike too
   thin to read. Set to sit clearly below the new price but well above the
   "one-time" note, and lifted from --rp-text3 to --rp-text2: struck text is
   already visually demoted, and dimming it as well made it unreadable. */
.hs-price__was {
  color: var(--rp-text2); font-size: clamp(1.15rem, 1.7vw, 1.45rem);
  font-weight: 500; margin-right: .18em; text-decoration-thickness: .07em;
}

/* THE SAVING, next to a struck-through price. Shared rather than per-product:
   the hub and every product page all render it, and a second copy in a
   product's section.css is a second place for the two to drift apart.

   Deliberately quieter than the sale price it follows. The new price is the
   number that closes the sale; this only tells a shopper how to feel about it,
   and two loud figures side by side make neither read. */
.hs-save {
  /* --rp-accent is declared by a PRODUCT's theme, so it is undefined on the
     hub's deal banner, which sits outside any card. An undefined var inside
     color-mix() invalidates the whole declaration - border, background and
     colour all silently drop and the chip renders as plain white text. The
     fallback chain keeps it painted everywhere: the product's accent inside a
     themed card, the house accent on the hub, a literal as the last resort. */
  --save-ink: var(--rp-accent, var(--hub-accent, #7c5cff));
  display: inline-block; white-space: nowrap; vertical-align: baseline;
  margin-left: .45em;
  padding: .18em .5em; border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--save-ink) 40%, transparent);
  background: color-mix(in srgb, var(--save-ink) 12%, transparent);
  color: var(--save-ink);
  font-family: var(--rp-font-mono); font-size: .64rem; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase; line-height: 1.3;
}
/* On the price card it is a flex item beside a 3rem figure - `display:block`
   would do nothing there, so it is aligned and spaced instead. margin-left
   separates it from the price note it follows ("one-time"). */
.hs-save--card { align-self: center; margin-left: .55rem; }
/* The featured card is themed in --rp-brand throughout - its rule, glow, flag,
   ticks and button all use it - so a pill in --rp-accent reads as a stray
   element from another palette. HardStop is the case that shows it: accent is
   Drive blue, brand is clip red, and the blue pill sat alone on a red card. */
.hs-price--feature .hs-save { --save-ink: var(--rp-brand); }
/* .hs-price__amt span paints EVERY span in the price row --rp-text3 at .9rem,
   and (0,1,1) outranks .hs-save's own (0,1,0) - so inside a price card the
   pill lost both its colour and its size and came out grey and oversized.
   Re-asserted here at (0,2,0) rather than by reordering the file, which would
   only hide the collision until the next rule lands between them. */
.hs-price__amt .hs-save { color: var(--save-ink); font-size: .64rem; }

/* Struck price inside a button, for a CTA that quotes a price. */
.hs-btn__was {
  opacity: .62; font-weight: 500; margin-right: .12em;
  text-decoration-thickness: .07em;
}

.hs-eyebrow {
  font-family: var(--rp-font-mono);
  font-size: var(--rp-f-micro);
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--rp-accent);
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
}
.hs-eyebrow::before {
  content: "";
  width: 22px; height: 2px;
  background: currentColor;
  border-radius: 2px;
  opacity: 0.85;
}
.hs-center .hs-eyebrow::before { display: none; }
/* One step up from the standard eyebrow, with the tracking eased off so the
   extra size does not turn into extra sprawl. */
.hs-eyebrow--lg {
  font-size: calc(var(--rp-f-micro) * 1.22);
  letter-spacing: 0.16em;
  color: var(--rp-accent-soft);
}

/* text-wrap:balance lets the browser even out the lines of a heading instead of
   filling greedily and leaving one orphaned word on the last line -- the job a
   hand-placed <br> used to do, except it re-solves itself at every window
   width. Browsers that don't support it simply wrap the old way, and it is
   capped at a few lines by spec so it never costs layout time on body copy.
   `pretty` is the cheaper cousin for paragraphs: it only fixes the last line. */
.hs-display { font-size: var(--rp-f-display); letter-spacing: -0.04em; text-wrap: balance; }
.hs-h2      { font-size: var(--rp-f-h2); text-wrap: balance; }
.hs-h3      { font-size: var(--rp-f-h3); letter-spacing: -0.018em; text-wrap: balance; }

.hs-lede { font-size: var(--rp-f-lede); color: var(--rp-text2); line-height: calc(var(--rp-lh-body) + .04); text-wrap: pretty; }
.hs-body { color: var(--rp-text2); }
.hs-mono {
  font-family: var(--rp-font-mono);
  font-size: var(--rp-f-small);
  letter-spacing: 0.01em;
}
.hs-dim  { color: var(--rp-text3); }
.hs-white{ color: var(--rp-text); }

/* Gradient wordmark treatment matching the plugin logo's white->red split */
.hs-grad {
  background: linear-gradient(96deg, var(--rp-text) 0%, var(--rp-text) 42%, var(--rp-brand) 78%);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
}
.hs-accent-txt  { color: var(--rp-accent); }
.hs-clip-txt    { color: var(--rp-brand); }
.hs-safety-txt  { color: var(--rp-good); }
.hs-ceiling-txt { color: var(--rp-accent-2); }

/* --------------------------------------------------------------------------
   5. AMBIENT BACKGROUND -- the studio-glow feel, done in CSS so it costs
   nothing to download. Two blurred radial "lamps" plus a fine grid.
   -------------------------------------------------------------------------- */
.hs-atmos { position: absolute; inset: 0; overflow: hidden; pointer-events: none; z-index: 0; }
.hs-atmos { opacity: var(--rp-atmos-strength, 1); }
.hs-atmos::before,
.hs-atmos::after {
  content: "";
  position: absolute;
  width: 62vw; aspect-ratio: 1;
  border-radius: 50%;
  filter: blur(110px);
  opacity: 0.4;
}
.hs-atmos::before { top: -22%; left: -14%; background: radial-gradient(circle, var(--rp-accent), transparent 66%); }
.hs-atmos::after  { top: 6%;  right: -18%; background: radial-gradient(circle, var(--rp-brand),   transparent 66%); opacity: .3; }

.hs-mesh {
  position: absolute; inset: 0; pointer-events: none; z-index: 0;
  background-image:
    linear-gradient(var(--rp-border2) 1px, transparent 1px),
    linear-gradient(90deg, var(--rp-border2) 1px, transparent 1px);
  background-size: 62px 62px;
  opacity: var(--rp-mesh-strength, 0.13);
  mask-image: radial-gradient(ellipse 80% 62% at 50% 34%, #000 12%, transparent 76%);
  -webkit-mask-image: radial-gradient(ellipse 80% 62% at 50% 34%, #000 12%, transparent 76%);
}

.hs-noise {
  position: absolute; inset: 0; pointer-events: none; z-index: 1; opacity: var(--rp-noise-strength, .16);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  mix-blend-mode: overlay;
}

/* --------------------------------------------------------------------------
   6. NAV -- hidden at top, slides down once you scroll past the hero
   -------------------------------------------------------------------------- */
.hs-nav {
  position: fixed; top: 0; left: 0; right: 0; z-index: 90;
  background: color-mix(in srgb, var(--rp-bg) 80%, transparent);
  backdrop-filter: blur(16px) saturate(140%);
  -webkit-backdrop-filter: blur(16px) saturate(140%);
  border-bottom: 1px solid transparent;
  transform: translateY(-104%);
  transition: transform var(--rp-med), border-color var(--rp-med);
  will-change: transform;
}
.hs-nav.is-visible { transform: translateY(0); border-bottom-color: var(--rp-border); }
.hs-nav__inner {
  max-width: var(--rp-max); margin-inline: auto;
  padding: 0.7rem var(--rp-gutter);
  display: flex; align-items: center; gap: 1.5rem;
}
.hs-nav__logo { width: 108px; flex: none; }
.hs-nav__logo svg { width: 100%; height: auto; }
.hs-nav__links { display: flex; gap: 1.65rem; margin-left: auto; }
.hs-nav__links a {
  font-size: var(--rp-f-small); color: var(--rp-text2);
  position: relative; padding-block: 3px;
  transition: color var(--rp-fast);
}
.hs-nav__links a::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 1.5px;
  background: var(--rp-accent); border-radius: 2px;
  transform: scaleX(0); transform-origin: left;
  transition: transform var(--rp-med);
}
.hs-nav__links a:hover { color: var(--rp-text); }
.hs-nav__links a:hover::after { transform: scaleX(1); }
@media (max-width: 880px) { .hs-nav__links { display: none; } .hs-nav__inner > .hs-btn { margin-left: auto; } }

/* --------------------------------------------------------------------------
   7. BUTTONS -- the single most-touched interactive element, so the states
   get the most care. Sheen sweep on hover, 1px press travel on :active.
   -------------------------------------------------------------------------- */
.hs-btn {
  --btn-bg: var(--rp-accent);
  --btn-fg: #04060c;
  position: relative;
  display: inline-flex; align-items: center; justify-content: center; gap: .6em;
  padding: 0.92em 1.75em;
  border-radius: 999px;
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-weight: 700;
  font-size: 0.97rem;
  letter-spacing: -0.004em;
  white-space: nowrap;
  /* .hs-root sets antialiased, which thins strokes. That helps light text on a
     dark page but hurts DARK text on a bright fill -- exactly what a filled
     button is. Back to the platform default here so the label stays solid. */
  -webkit-font-smoothing: auto;
  -moz-osx-font-smoothing: auto;
  overflow: hidden;
  isolation: isolate;
  transition: transform var(--rp-fast), box-shadow var(--rp-med), background var(--rp-fast);
  /* The glow is derived from --btn-bg rather than hardcoded, so retinting
     the brand colour retints the shadow with it. color-mix() is what makes
     this possible without a preprocessor. */
  box-shadow: 0 1px 0 rgba(255,255,255,.22) inset,
              0 6px 22px -8px color-mix(in srgb, var(--btn-bg) 62%, transparent);
}
.hs-btn::after {                       /* the sheen */
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(105deg, transparent 32%, rgba(255,255,255,.42) 50%, transparent 68%);
  transform: translateX(-120%);
  transition: transform 620ms cubic-bezier(.22,.61,.36,1);
}
.hs-btn:hover  { transform: translateY(-2px); box-shadow: 0 1px 0 rgba(255,255,255,.28) inset, 0 14px 34px -10px color-mix(in srgb, var(--btn-bg) 78%, transparent); }
.hs-btn:hover::after { transform: translateX(120%); }
.hs-btn:active { transform: translateY(0); transition-duration: 60ms; }

.hs-btn--pro    { --btn-bg: var(--rp-brand); }

.hs-btn--ghost {
  --btn-fg: var(--rp-text);
  /* light-on-dark again, so the thinning is wanted back */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  background: rgba(255,255,255,.035);
  border: 1px solid var(--rp-border2);
  box-shadow: none;
  backdrop-filter: blur(6px);
}
.hs-btn--ghost:hover { background: rgba(255,255,255,.075); border-color: var(--rp-text3); box-shadow: none; }

.hs-btn--sm  { padding: 0.66em 1.25em; font-size: .875rem; }
.hs-btn--lg  { padding: 1.05em 2.1em; font-size: 1.03rem; }
.hs-btn--full{ width: 100%; }

.hs-btn__ico { width: 1.05em; height: 1.05em; flex: none; transition: transform var(--rp-spring); }
.hs-btn:hover .hs-btn__ico--down  { transform: translateY(2px); }
.hs-btn:hover .hs-btn__ico--right { transform: translateX(3px); }

.hs-cta-row { display: flex; flex-wrap: wrap; gap: .85rem; }
.hs-center .hs-cta-row { justify-content: center; }

/* --------------------------------------------------------------------------
   8. CARD -- cursor-tracked glow. JS writes --mx/--my as percentages; the
   ::before layer is a radial gradient anchored to those, faded in on hover.
   This is why the glow follows the pointer instead of just switching on.
   -------------------------------------------------------------------------- */
.hs-card {
  position: relative;
  background: linear-gradient(168deg, var(--rp-card) 0%, var(--rp-panel) 100%);
  border: 1px solid var(--rp-border);
  border-radius: var(--rp-r);
  padding: clamp(1.4rem, 2.4vw, 1.95rem);
  overflow: hidden;
  isolation: isolate;
  transition: transform var(--rp-med), border-color var(--rp-med), box-shadow var(--rp-med);
}
.hs-card::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: radial-gradient(340px circle at var(--mx, 50%) var(--my, 0%),
              color-mix(in srgb, var(--rp-glow, var(--rp-accent)) var(--rp-cardglow, 17%), transparent), transparent 62%);
  opacity: 0; transition: opacity var(--rp-med);
}
.hs-card:hover {
  transform: translateY(-4px);
  border-color: var(--rp-border2);
  box-shadow: 0 22px 48px -26px rgba(0,0,0,.9);
}
.hs-card:hover::before { opacity: 1; }

.hs-card__ico {
  width: 46px; height: 46px;
  display: grid; place-items: center;
  border-radius: 13px;
  background: color-mix(in srgb, var(--rp-glow, var(--rp-accent)) 13%, transparent);
  border: 1px solid color-mix(in srgb, var(--rp-glow, var(--rp-accent)) 30%, transparent);
  color: var(--rp-glow, var(--rp-accent));
  margin-bottom: 1.1rem;
  transition: transform var(--rp-spring), background var(--rp-med);
}
.hs-card:hover .hs-card__ico { transform: translateY(-2px) scale(1.06) rotate(-4deg); }
.hs-card__ico svg { width: 23px; height: 23px; }
.hs-card h3 { margin-bottom: .5rem; font-size: 1.11rem; }
.hs-card p  { color: var(--rp-text2); font-size: .955rem; line-height: 1.62; }

/* Per-card accent -- mirrors how the plugin colour-codes its own controls */
.hs-g-accent  { --rp-glow: var(--rp-accent); }
.hs-g-safety  { --rp-glow: var(--rp-good); }
.hs-g-clip    { --rp-glow: var(--rp-brand); }
.hs-g-ceiling { --rp-glow: var(--rp-accent-2); }
.hs-g-danger  { --rp-glow: var(--rp-warn); }
/* .hs-g-brass -- HardStop's own tier-3 waveform accent; declared in
   section.css so it travels with --rp-brass instead of forcing every
   product to declare a colour it has no use for. */

/* --------------------------------------------------------------------------
   9. HERO
   -------------------------------------------------------------------------- */
.hs-hero {
  position: relative;
  padding-top: clamp(3.5rem, 8vw, 6.5rem);
  padding-bottom: clamp(3rem, 6vw, 5rem);
  text-align: center;
  overflow: hidden;
}
.hs-hero__inner { position: relative; z-index: 2; }

.hs-hero__logo { width: min(430px, 74vw); margin: 0 auto clamp(1.4rem, 3vw, 2.1rem); }
.hs-hero__logo svg { width: 100%; height: auto; filter: drop-shadow(0 6px 26px color-mix(in srgb, var(--rp-brand) 32%, transparent)); }

.hs-hero h1 { margin-bottom: 1.1rem; }
.hs-hero .hs-lede { margin: 0 auto 1.9rem; max-width: 54ch; }

.hs-badge-row { display: flex; flex-wrap: wrap; justify-content: center; gap: .5rem; margin-bottom: 1.5rem; }
.hs-badge {
  display: inline-flex; align-items: center; gap: .45em;
  padding: .38em .85em;
  border-radius: 999px;
  border: 1px solid var(--rp-border2);
  background: rgba(255,255,255,.03);
  font-family: var(--rp-font-mono);
  font-size: var(--rp-f-micro);
  letter-spacing: .11em; text-transform: uppercase;
  color: var(--rp-text2);
  transition: border-color var(--rp-fast), color var(--rp-fast), background var(--rp-fast);
}
.hs-badge:hover { border-color: var(--rp-accent); color: var(--rp-text); background: color-mix(in srgb, var(--rp-accent) 11%, transparent); }
.hs-badge__dot { width: 6px; height: 6px; border-radius: 50%; background: var(--rp-good); flex: none; }
.hs-badge--free { border-color: color-mix(in srgb, var(--rp-good) 45%, transparent); color: var(--rp-good); background: color-mix(in srgb, var(--rp-good) 10%, transparent); }

.hs-trust { display: flex; flex-wrap: wrap; justify-content: center; gap: .55rem 1.6rem; margin-top: 2.15rem; }
.hs-trust li {
  display: inline-flex; align-items: center; gap: .45em;
  font-size: var(--rp-f-small); color: var(--rp-text3);
}
.hs-trust svg { width: 15px; height: 15px; color: var(--rp-good); flex: none; }

/* Hero shot: perspective tilt that eases flat as it scrolls into view */
.hs-shot {
  position: relative;
  margin-top: clamp(2.5rem, 5vw, 4rem);
  perspective: 1800px;
}
.hs-shot__frame {
  position: relative;
  border-radius: var(--rp-r-lg);
  overflow: hidden;
  border: 1px solid var(--rp-border2);
  background: var(--rp-panel);
  box-shadow:
    0 0 0 1px rgba(255,255,255,.03) inset,
    0 40px 90px -40px rgba(0,0,0,.95),
    0 0 90px -30px color-mix(in srgb, var(--rp-accent) 40%, transparent);
  transform: rotateX(9deg) scale(.965);
  transform-origin: 50% 100%;
  transition: transform 1.1s cubic-bezier(.16,.84,.44,1), box-shadow var(--rp-slow);
}
.hs-shot.is-in .hs-shot__frame { transform: rotateX(0deg) scale(1); }
.hs-shot__frame img { width: 100%; }

/* The blue/red rim light around the hero shot, matching the plugin's own glow */
.hs-shot__glow {
  /* inset was -14% -6%: the -6% pushed this 3px past the viewport edge on a phone,
     which is exactly the kind of overflow you should fix at the source rather than
     paper over with a page-level clip. */
  position: absolute; inset: -14% 0;
  z-index: -1; pointer-events: none;
  background:
    radial-gradient(50% 60% at 12% 50%, color-mix(in srgb, var(--rp-accent) 46%, transparent), transparent 68%),
    radial-gradient(50% 60% at 88% 50%, color-mix(in srgb, var(--rp-brand) 42%, transparent), transparent 68%);
  filter: blur(52px);
  opacity: 0; transition: opacity 1.2s ease;
}
.hs-shot.is-in .hs-shot__glow { opacity: 1; animation: hs-breathe 7s ease-in-out infinite 1.2s; }
@keyframes hs-breathe { 0%,100% { opacity: .82; } 50% { opacity: 1; } }

/* Live canvas waveform strip under the hero shot */
.hs-wavebar {
  margin-top: 1.15rem;
  border: 1px solid var(--rp-border);
  border-radius: var(--rp-r-sm);
  background: linear-gradient(180deg, color-mix(in srgb, var(--rp-panel) 70%, #000), color-mix(in srgb, var(--rp-bg) 88%, #000));
  padding: .55rem .7rem .4rem;
  position: relative;
  overflow: hidden;
}
.hs-wavebar canvas { width: 100%; height: 110px; display: block; }
.hs-wavebar__legend {
  display: flex; flex-wrap: wrap; gap: .35rem 1.15rem;
  padding-top: .45rem;
  font-family: var(--rp-font-mono);
  font-size: 0.66rem; letter-spacing: .1em; text-transform: uppercase; color: var(--rp-text3);
}
.hs-wavebar__legend span { display: inline-flex; align-items: center; gap: .4em; }
.hs-wavebar__legend i { width: 9px; height: 9px; border-radius: 2px; display: block; }

/* --------------------------------------------------------------------------
   10. SPEC / STAT STRIPS
   -------------------------------------------------------------------------- */
.hs-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr));
  border: 1px solid var(--rp-border);
  border-radius: var(--rp-r);
  overflow: hidden;
  background: var(--rp-panel);
}
.hs-stat {
  padding: clamp(1.3rem, 2.4vw, 1.9rem) 1.35rem;
  border-right: 1px solid var(--rp-border);
  position: relative;
  transition: background var(--rp-med);
}
.hs-stat:last-child { border-right: 0; }
.hs-stat:hover { background: var(--rp-card); }
.hs-stat::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 2px;
  background: var(--rp-glow, var(--rp-accent));
  transform: scaleX(0); transform-origin: left;
  transition: transform var(--rp-med);
}
.hs-stat:hover::after { transform: scaleX(1); }
.hs-stat__n {
  font-family: var(--rp-font-mono);
  font-size: clamp(1.75rem, 3.1vw, 2.4rem);
  font-weight: 700; line-height: 1;
  color: var(--rp-glow, var(--rp-accent));
  letter-spacing: -.03em;
  display: block; margin-bottom: .3rem;
  font-variant-numeric: tabular-nums;
}
/* The number is the proof; the title is the claim it proves. Splitting them
   lets the card name a feature without giving up the numeral that makes the
   row scan as a row. */
.hs-stat__t {
  display: block;
  font-size: var(--rp-f-small);
  font-weight: 700;
  color: var(--rp-text);
  letter-spacing: -.012em;
  margin-bottom: .32rem;
}
.hs-stat__l { font-size: .845rem; color: var(--rp-text2); line-height: 1.45; }
@media (max-width: 640px) { .hs-stat { border-right: 0; border-bottom: 1px solid var(--rp-border); } }

/* --------------------------------------------------------------------------
   11. SPLIT (image + copy)
   -------------------------------------------------------------------------- */
.hs-split {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 400px), 1fr));
  gap: clamp(2rem, 5vw, 4.2rem);
  align-items: center;
}
.hs-split--flip > :first-child { order: 2; }
@media (max-width: 860px) { .hs-split--flip > :first-child { order: 0; } }

.hs-figure {
  position: relative;
  border-radius: var(--rp-r);
  overflow: hidden;
  border: 1px solid var(--rp-border2);
  box-shadow: 0 30px 60px -34px rgba(0,0,0,.92);
  transition: transform var(--rp-slow), box-shadow var(--rp-slow);
}
.hs-figure img { width: 100%; transition: transform 900ms cubic-bezier(.16,.84,.44,1); }
.hs-figure:hover { box-shadow: 0 36px 76px -34px rgba(0,0,0,1), 0 0 60px -26px color-mix(in srgb, var(--rp-glow, var(--rp-accent)) 55%, transparent); }
.hs-figure:hover img { transform: scale(1.035); }
.hs-figure figcaption {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 2.4rem 1.15rem .8rem;
  background: linear-gradient(transparent, rgba(6,8,13,.94));
  font-family: var(--rp-font-mono);
  font-size: .68rem; letter-spacing: .13em; text-transform: uppercase; color: var(--rp-text2);
}

/* Two-voice explainer, straight from the manual's "plain / precise" device */
.hs-voice { border-left: 2px solid var(--rp-border2); padding-left: 1.15rem; margin-bottom: 1.35rem; transition: border-color var(--rp-med); }
.hs-voice:hover { border-left-color: var(--rp-glow, var(--rp-accent)); }
.hs-voice__tag {
  display: block;
  font-family: var(--rp-font-mono);
  font-size: var(--rp-f-micro); font-weight: 700;
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--rp-glow, var(--rp-accent));
  margin-bottom: .45rem;
}
.hs-voice p { color: var(--rp-text2); }

/* Checklist */
.hs-checks { display: grid; gap: .8rem; margin-top: 1.5rem; }
.hs-checks li { display: flex; gap: .75rem; align-items: flex-start; color: var(--rp-text2); font-size: .97rem; }
.hs-checks svg { width: 19px; height: 19px; flex: none; color: var(--rp-good); margin-top: .18em; }
.hs-checks b { color: var(--rp-text); font-weight: 600; }

/* --------------------------------------------------------------------------
   12. CHARACTER KNOB ROW (Pro) -- the four colour-coded controls
   -------------------------------------------------------------------------- */
.hs-knobs { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 235px), 1fr)); gap: 1rem; }
.hs-knob {
  text-align: center;
  padding: 1.75rem 1.25rem 1.5rem;
  border: 1px solid var(--rp-border);
  border-radius: var(--rp-r);
  background: linear-gradient(168deg, var(--rp-card), var(--rp-panel));
  transition: transform var(--rp-med), border-color var(--rp-med), box-shadow var(--rp-med);
}
.hs-knob:hover {
  transform: translateY(-5px);
  border-color: color-mix(in srgb, var(--rp-glow) 55%, transparent);
  box-shadow: 0 20px 44px -26px rgba(0,0,0,.95), 0 0 44px -22px var(--rp-glow);
}
.hs-knob__dial {
  width: 78px; height: 78px; margin: 0 auto 1.05rem;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 32%, #23252f, #0f1017 72%);
  border: 1px solid var(--rp-border2);
  position: relative;
  box-shadow: 0 5px 16px rgba(0,0,0,.55), 0 1px 0 rgba(255,255,255,.06) inset;
  transition: box-shadow var(--rp-med);
}
.hs-knob:hover .hs-knob__dial { box-shadow: 0 5px 16px rgba(0,0,0,.55), 0 0 0 3px color-mix(in srgb, var(--rp-glow) 18%, transparent); }
.hs-knob__dial::before {            /* the arc */
  content: ""; position: absolute; inset: -5px;
  border-radius: 50%;
  background: conic-gradient(from 215deg, var(--rp-glow) 0turn var(--arc, .38turn), transparent var(--arc, .38turn) 1turn);
  mask: radial-gradient(circle, transparent 61%, #000 63%, #000 72%, transparent 74%);
  -webkit-mask: radial-gradient(circle, transparent 61%, #000 63%, #000 72%, transparent 74%);
  transition: --arc var(--rp-spring);
}
.hs-knob__dial::after {             /* the pointer */
  content: ""; position: absolute;
  left: 50%; top: 15%;
  width: 2.5px; height: 24%;
  border-radius: 2px;
  background: var(--rp-glow);
  transform-origin: 50% 165%;
  transform: translateX(-50%) rotate(var(--rot, -38deg));
  box-shadow: 0 0 9px var(--rp-glow);
  transition: transform var(--rp-spring);
}
.hs-knob:hover .hs-knob__dial::after { transform: translateX(-50%) rotate(calc(var(--rot, -38deg) + 46deg)); }
.hs-knob h3 {
  font-family: var(--rp-font-mono);
  font-size: .78rem; font-weight: 700; letter-spacing: .19em; text-transform: uppercase;
  color: var(--rp-glow); margin-bottom: .3rem;
}
.hs-knob__range {
  font-family: var(--rp-font-mono);
  font-size: .66rem; letter-spacing: .1em; color: var(--rp-text3); margin-bottom: .75rem;
}
.hs-knob p { font-size: .9rem; color: var(--rp-text2); line-height: 1.58; }

/* --------------------------------------------------------------------------
   13. VIDEO
   -------------------------------------------------------------------------- */
.hs-video {
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: var(--rp-r-lg);
  overflow: hidden;
  border: 1px solid var(--rp-border2);
  background: #06080d center/cover no-repeat;
  box-shadow: 0 44px 90px -44px rgba(0,0,0,.95), 0 0 90px -34px color-mix(in srgb, var(--rp-accent) 34%, transparent);
  cursor: pointer;
}
.hs-video iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.hs-video__poster { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: .5; transition: opacity var(--rp-med), transform 900ms cubic-bezier(.16,.84,.44,1); }
.hs-video:hover .hs-video__poster { opacity: .62; transform: scale(1.02); }
.hs-video__play {
  position: absolute; inset: 0; display: grid; place-items: center; gap: .9rem;
  align-content: center;
}
.hs-video__disc {
  width: 84px; height: 84px; border-radius: 50%;
  display: grid; place-items: center;
  background: rgba(255,255,255,.1);
  border: 1px solid rgba(255,255,255,.28);
  backdrop-filter: blur(9px);
  transition: transform var(--rp-spring), background var(--rp-med), box-shadow var(--rp-med);
}
.hs-video__disc svg { width: 30px; height: 30px; color: #fff; margin-left: 4px; }
.hs-video:hover .hs-video__disc {
  transform: scale(1.09);
  background: var(--rp-accent);
  box-shadow: 0 0 0 12px color-mix(in srgb, var(--rp-accent) 16%, transparent), 0 14px 40px -12px color-mix(in srgb, var(--rp-accent) 76%, transparent);
}
.hs-video__disc::before {
  content: ""; position: absolute; width: 84px; height: 84px; border-radius: 50%;
  border: 1px solid rgba(255,255,255,.34);
  animation: hs-ping 2.8s cubic-bezier(0,0,.2,1) infinite;
}
@keyframes hs-ping { 0% { transform: scale(1); opacity: .7; } 80%,100% { transform: scale(1.65); opacity: 0; } }
.hs-video__label {
  font-family: var(--rp-font-mono);
  font-size: var(--rp-f-micro); letter-spacing: .2em; text-transform: uppercase; color: rgba(255,255,255,.82);
}

/* COMING SOON -------------------------------------------------------------
   This is the DEFAULT state in the markup. The script swaps to the play button
   only once a real video ID is present, so the page tells the truth both before
   the video exists and with JavaScript turned off. */
.hs-video__soon { position: absolute; inset: 0; display: none; place-content: center; justify-items: center; gap: .85rem; }
.hs-video--soon .hs-video__soon { display: grid; }
.hs-video--soon .hs-video__play { display: none; }
.hs-video--soon { cursor: default; }
.hs-video--soon:hover .hs-video__poster { transform: none; opacity: .5; }

.hs-video__soon-badge {
  font-family: var(--rp-font-mono);
  font-size: clamp(.85rem, 2.1vw, 1.25rem);
  font-weight: 700; letter-spacing: .3em; text-transform: uppercase;
  color: var(--rp-text);
  padding: .75em 1.5em .75em 1.8em;      /* extra left pad balances the tracking */
  border: 1px solid var(--rp-border2);
  border-radius: 999px;
  background: color-mix(in srgb, var(--rp-bg) 72%, transparent);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  box-shadow: 0 0 0 6px color-mix(in srgb, var(--rp-accent) 7%, transparent),
              0 18px 44px -20px rgba(0,0,0,.9);
  position: relative;
}
.hs-video__soon-badge::before {
  content: ""; position: absolute; inset: -1px; border-radius: inherit; padding: 1px;
  background: linear-gradient(120deg, var(--rp-accent), transparent 42%, transparent 58%, var(--rp-brand));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude;
  opacity: .85;
}
.hs-video__soon-note {
  font-size: var(--rp-f-small); color: var(--rp-text2); text-align: center;
  padding-inline: 1rem;
}

/* --------------------------------------------------------------------------
   14. COMPARISON TABLE
   -------------------------------------------------------------------------- */
.hs-tablewrap {
  border: 1px solid var(--rp-border);
  border-radius: var(--rp-r);
  overflow: hidden;
  background: var(--rp-panel);
}
.hs-table { width: 100%; border-collapse: collapse; font-size: .945rem; }
.hs-table thead th {
  background: #05070c;
  padding: 1.05rem 1.15rem;
  text-align: left;
  font-family: var(--rp-font-mono);
  font-size: var(--rp-f-micro); font-weight: 700; letter-spacing: .16em; text-transform: uppercase;
  color: var(--rp-text2);
  border-bottom: 1px solid var(--rp-border);
}
.hs-table thead th:nth-child(2),
.hs-table thead th:nth-child(3) { text-align: center; width: 20%; }
.hs-table thead th:nth-child(3) { color: var(--rp-brand); }
.hs-table td { padding: .92rem 1.15rem; border-bottom: 1px solid var(--rp-border); color: var(--rp-text2); vertical-align: middle; }
.hs-table td:first-child { color: var(--rp-text); font-weight: 500; }
.hs-table td:nth-child(2),
.hs-table td:nth-child(3) { text-align: center; font-family: var(--rp-font-mono); font-size: .78rem; color: var(--rp-text3); }
.hs-table tbody tr { transition: background var(--rp-fast); }
.hs-table tbody tr:hover { background: color-mix(in srgb, var(--rp-accent) 6%, transparent); }
.hs-table tbody tr:last-child td { border-bottom: 0; }
.hs-table tbody tr td:nth-child(3) { background: color-mix(in srgb, var(--rp-brand) 5%, transparent); }
.hs-yes { color: var(--rp-good); font-size: 1.15rem; line-height: 1; }
.hs-no  { color: var(--rp-text3); opacity: .55; }
@media (max-width: 720px) {
  .hs-tablewrap {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    /* Without this, dragging the wide comparison table sideways on a phone can
       chain into the document and fight the vertical scroll. */
    overscroll-behavior-x: contain;
  }
  .hs-table { min-width: 560px; }
}

/* --------------------------------------------------------------------------
   15. PRICING
   -------------------------------------------------------------------------- */
/* Two-value gap: <row> <column>. The row gap only ever materialises once
   auto-fit wraps the cards into a stack, so this costs nothing in the
   side-by-side layout -- there is only one row there. It has to be bigger than
   the column gap, not equal to it: stacked, the cards are full-bleed and the
   only thing separating two tiers is that gap, and at 1.25rem it was *smaller*
   than the card's own 1.7rem padding, so the boundary between two cards read as
   tighter than the whitespace inside one and the tiers looked fused. It also
   gives the Pro card's red glow somewhere to fall off before it hits Basic. */
.hs-prices {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 330px), 1fr));
  gap: clamp(2.25rem, 5vw, 3rem) 1.25rem;
  align-items: stretch;
}
.hs-price {
  position: relative;
  display: flex; flex-direction: column;
  padding: clamp(1.7rem, 3vw, 2.4rem);
  border: 1px solid var(--rp-border);
  border-radius: var(--rp-r-lg);
  background: linear-gradient(168deg, var(--rp-card), var(--rp-panel));
  transition: transform var(--rp-med), border-color var(--rp-med), box-shadow var(--rp-med);
  overflow: hidden;
}
.hs-price:hover { transform: translateY(-5px); border-color: var(--rp-border2); box-shadow: 0 30px 60px -32px rgba(0,0,0,.95); }
.hs-price--feature {
  border-color: color-mix(in srgb, var(--rp-brand) 50%, transparent);
  box-shadow: 0 0 62px -28px color-mix(in srgb, var(--rp-brand) 70%, transparent);
}
.hs-price--feature:hover { border-color: var(--rp-brand); box-shadow: 0 30px 66px -30px rgba(0,0,0,.95), 0 0 70px -24px color-mix(in srgb, var(--rp-brand) 80%, transparent); }
.hs-price--feature::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 2px;
  background: linear-gradient(90deg, transparent, var(--rp-brand), transparent);
}
.hs-price__flag {
  position: absolute; top: 1.15rem; right: 1.15rem;
  padding: .3em .75em; border-radius: 999px;
  background: var(--rp-brand); color: #fff;
  font-family: var(--rp-font-mono);
  font-size: .62rem; font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
}
.hs-price__tier {
  font-family: var(--rp-font-mono);
  font-size: .74rem; font-weight: 700; letter-spacing: .2em; text-transform: uppercase;
  color: var(--rp-text3); margin-bottom: .85rem;
}
.hs-price__amt { display: flex; align-items: baseline; gap: .4rem; margin-bottom: .35rem; }
.hs-price__amt b {
  font-size: clamp(2.6rem, 5vw, 3.5rem); font-weight: 700; line-height: 1; letter-spacing: -.04em;
  font-family: var(--rp-font-display);
}
.hs-price__amt span { font-size: .9rem; color: var(--rp-text3); }
.hs-price__sub { color: var(--rp-text2); font-size: .93rem; margin-bottom: 1.5rem; min-height: 2.6em; }
.hs-price__list { display: grid; gap: .68rem; margin-bottom: 1.85rem; flex: 1; }
.hs-price__list li { display: flex; gap: .68rem; align-items: flex-start; font-size: .92rem; color: var(--rp-text2); }
.hs-price__list svg { width: 17px; height: 17px; flex: none; margin-top: .2em; }
.hs-price__list li b { color: var(--rp-text); font-weight: 600; }
.hs-price__note { margin-top: .95rem; text-align: center; font-size: .78rem; color: var(--rp-text3); }
/* One tier must not stretch the full grid - constrain and centre it so a
   single card reads as deliberate rather than as a layout that lost its
   sibling. Must stay AFTER .hs-prices above: same specificity, later wins. */
.hs-prices--single { grid-template-columns: minmax(0, 420px); justify-content: center; }
/* A tier with no ls_product_id yet - not-yet-purchasable, not a dead link. */
.hs-btn--disabled { opacity: .55; cursor: default; pointer-events: none; }
.hs-btn--disabled::after { display: none; }
/* A trial that shares its tier's checkout sits under the buy button as the
   quieter of the two routes into the same product. */
.hs-btn--trial { margin-top: .6rem; }
.hs-price__note--trial { margin-top: .5rem; }

/* --------------------------------------------------------------------------
   16. TESTIMONIALS
   -------------------------------------------------------------------------- */
.hs-quotes { columns: 3 300px; column-gap: 1.15rem; }
.hs-quote {
  break-inside: avoid; margin-bottom: 1.15rem;
  padding: 1.55rem;
  border: 1px solid var(--rp-border);
  border-radius: var(--rp-r);
  background: linear-gradient(168deg, var(--rp-card), var(--rp-panel));
  transition: transform var(--rp-med), border-color var(--rp-med), box-shadow var(--rp-med);
}
.hs-quote:hover { transform: translateY(-3px); border-color: var(--rp-border2); box-shadow: 0 20px 44px -26px rgba(0,0,0,.9); }
.hs-quote__stars { display: flex; gap: 2px; margin-bottom: .9rem; color: var(--rp-warn); }
.hs-quote__stars svg { width: 15px; height: 15px; }
.hs-quote p { color: var(--rp-text); font-size: .975rem; line-height: 1.65; margin-bottom: 1.1rem; }
.hs-quote footer { display: flex; align-items: center; gap: .7rem; }
.hs-quote__av {
  width: 38px; height: 38px; border-radius: 50%; flex: none;
  display: grid; place-items: center;
  background: linear-gradient(150deg, var(--rp-accent), var(--rp-brand));
  color: #04060c; font-weight: 700; font-size: .84rem;
}
.hs-quote__who b { display: block; font-size: .89rem; font-weight: 600; }
.hs-quote__who span { display: block; font-size: .77rem; color: var(--rp-text3); }
/* Optional per-entry portrait. A testimonial without an image renders exactly
   as it always did; only an entry carrying image: gets these. */
.hs-quote--portrait { padding: 0; overflow: hidden; }
.hs-quote--portrait > :not(.hs-quote__img) { padding-inline: 1.55rem; }
.hs-quote--portrait > :first-child + * { padding-top: 1.4rem; }
.hs-quote--portrait footer { padding-bottom: 1.55rem; }
.hs-quote__img {
  display: block; width: 100%; height: auto;
  aspect-ratio: 16 / 9; object-fit: cover;
  border-bottom: 1px solid var(--rp-border);
}

/* --------------------------------------------------------------------------
   16b. REVIEWS -- a wall of video cards. Each is a plain link over a locally
   served thumbnail, so a page carrying this section still makes no request to
   any video host until a visitor clicks through.
   -------------------------------------------------------------------------- */
.hs-reviews { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.25rem; }
@media (max-width: 720px) { .hs-reviews { grid-template-columns: minmax(0, 1fr); } }
.hs-review {
  display: block; text-decoration: none; color: inherit;
  border: 1px solid var(--rp-border);
  border-radius: var(--rp-r);
  background: linear-gradient(168deg, var(--rp-card), var(--rp-panel));
  overflow: hidden;
  transition: transform var(--rp-med), border-color var(--rp-med), box-shadow var(--rp-med);
}
.hs-review:hover { transform: translateY(-3px); border-color: var(--rp-border2); box-shadow: 0 20px 44px -26px rgba(0,0,0,.9); }
.hs-review__thumb { display: block; position: relative; aspect-ratio: 16 / 9; background: #000; }
.hs-review__thumb img { display: block; width: 100%; height: 100%; object-fit: cover; }
.hs-review__play {
  position: absolute; inset: 0; margin: auto;
  width: 62px; height: 62px; border-radius: 50%;
  display: grid; place-items: center;
  background: rgba(8,10,16,.72); border: 1px solid rgba(255,255,255,.22);
  color: #fff; backdrop-filter: blur(2px);
  transition: transform var(--rp-med), background var(--rp-med);
}
.hs-review__play svg { width: 26px; height: 26px; margin-left: 3px; }
.hs-review:hover .hs-review__play { transform: scale(1.08); background: var(--rp-brand); color: var(--rp-on-accent); }
.hs-review__flag {
  position: absolute; top: .7rem; left: .7rem;
  font-family: var(--rp-font-mono);
  font-size: .6rem; letter-spacing: .12em; text-transform: uppercase;
  color: var(--rp-text2); background: rgba(8,10,16,.82);
  border: 1px solid var(--rp-border2); border-radius: 999px;
  padding: .3em .7em;
}
.hs-review__meta { display: block; padding: 1.05rem 1.2rem 1.2rem; }
.hs-review__title { display: block; font-size: .95rem; font-weight: 600; line-height: 1.4; color: var(--rp-text); }
.hs-review__channel { display: block; margin-top: .35rem; font-size: .8rem; color: var(--rp-text3); }

/* --------------------------------------------------------------------------
   17. COMPATIBILITY
   -------------------------------------------------------------------------- */
.hs-os {
  padding: clamp(1.5rem, 2.6vw, 2rem);
  border: 1px solid var(--rp-border);
  border-radius: var(--rp-r);
  background: var(--rp-panel);
  transition: border-color var(--rp-med);
}
.hs-os:hover { border-color: var(--rp-border2); }
.hs-os__head { display: flex; align-items: center; gap: .75rem; margin-bottom: 1.25rem; padding-bottom: 1.1rem; border-bottom: 1px solid var(--rp-border); }
.hs-os__head svg { width: 26px; height: 26px; color: var(--rp-text2); }
.hs-os__head h3 { font-size: 1.06rem; }
.hs-os dl { display: grid; grid-template-columns: auto 1fr; gap: .7rem 1.15rem; font-size: .9rem; }
.hs-os dt { font-family: var(--rp-font-mono); font-size: .68rem; letter-spacing: .13em; text-transform: uppercase; color: var(--rp-text3); padding-top: .2em; }
.hs-os dd { color: var(--rp-text2); margin: 0; }

.hs-formats { display: flex; flex-wrap: wrap; gap: .45rem; }
.hs-format {
  padding: .34em .8em; border-radius: 7px;
  border: 1px solid var(--rp-border2);
  background: rgba(255,255,255,.028);
  font-family: var(--rp-font-mono);
  font-size: .7rem; font-weight: 700; letter-spacing: .1em; color: var(--rp-text2);
  transition: all var(--rp-fast);
}
.hs-format:hover { border-color: var(--rp-accent); color: var(--rp-accent); background: color-mix(in srgb, var(--rp-accent) 10%, transparent); transform: translateY(-1px); }

/* --------------------------------------------------------------------------
   18. FAQ -- the accordion animates grid-template-rows 0fr->1fr, which is the
   only pure-CSS way to transition to "auto" height. No JS height math.
   -------------------------------------------------------------------------- */
.hs-faq { display: grid; gap: .7rem; }
.hs-faq__item {
  border: 1px solid var(--rp-border);
  border-radius: var(--rp-r-sm);
  background: var(--rp-panel);
  overflow: hidden;
  transition: border-color var(--rp-med), background var(--rp-med);
}
.hs-faq__item:hover { border-color: var(--rp-border2); }
.hs-faq__item.is-open { border-color: color-mix(in srgb, var(--rp-accent) 42%, transparent); background: var(--rp-card); }
.hs-faq__q {
  width: 100%; display: flex; align-items: center; gap: 1rem;
  padding: 1.15rem 1.35rem;
  text-align: left; font-size: 1.005rem; font-weight: 600; line-height: 1.4;
  transition: color var(--rp-fast);
}
.hs-faq__item.is-open .hs-faq__q { color: var(--rp-accent); }
.hs-faq__sign { margin-left: auto; flex: none; width: 17px; height: 17px; position: relative; }
.hs-faq__sign::before,
.hs-faq__sign::after {
  content: ""; position: absolute; left: 50%; top: 50%;
  background: currentColor; border-radius: 2px;
  transform: translate(-50%, -50%);
  transition: transform var(--rp-spring), opacity var(--rp-fast);
}
.hs-faq__sign::before { width: 15px; height: 2px; }
.hs-faq__sign::after  { width: 2px; height: 15px; }
.hs-faq__item.is-open .hs-faq__sign::after { transform: translate(-50%,-50%) rotate(90deg); opacity: 0; }
.hs-faq__panel { display: grid; grid-template-rows: 0fr; transition: grid-template-rows var(--rp-med); }
.hs-faq__item.is-open .hs-faq__panel { grid-template-rows: 1fr; }
.hs-faq__panel > div { overflow: hidden; }
.hs-faq__panel p { padding: 0 1.35rem 1.3rem; color: var(--rp-text2); font-size: .955rem; }
.hs-faq__panel p + p { padding-top: 0; }

/* --------------------------------------------------------------------------
   19. CONTACT
   -------------------------------------------------------------------------- */
.hs-contact { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr)); gap: 1.15rem; }
.hs-contact__card {
  display: flex; flex-direction: column; align-items: flex-start; gap: .55rem;
  padding: 1.65rem;
  border: 1px solid var(--rp-border);
  border-radius: var(--rp-r);
  background: linear-gradient(168deg, var(--rp-card), var(--rp-panel));
  transition: transform var(--rp-med), border-color var(--rp-med), box-shadow var(--rp-med);
}
.hs-contact__card:hover {
  transform: translateY(-4px);
  border-color: color-mix(in srgb, var(--rp-glow, var(--rp-accent)) 50%, transparent);
  box-shadow: 0 22px 46px -28px rgba(0,0,0,.92), 0 0 44px -26px var(--rp-glow, var(--rp-accent));
}
.hs-contact__ico {
  width: 42px; height: 42px; border-radius: 12px; display: grid; place-items: center;
  background: color-mix(in srgb, var(--rp-glow, var(--rp-accent)) 13%, transparent);
  border: 1px solid color-mix(in srgb, var(--rp-glow, var(--rp-accent)) 30%, transparent);
  color: var(--rp-glow, var(--rp-accent));
  margin-bottom: .5rem;
  transition: transform var(--rp-spring);
}
.hs-contact__card:hover .hs-contact__ico { transform: scale(1.07) rotate(-5deg); }
.hs-contact__ico svg { width: 21px; height: 21px; }
.hs-contact__card h3 { font-size: 1.03rem; }
.hs-contact__card p { font-size: .91rem; color: var(--rp-text2); }
.hs-contact__link {
  margin-top: auto; padding-top: .55rem;
  font-family: var(--rp-font-mono);
  font-size: .8rem; color: var(--rp-glow, var(--rp-accent));
  display: inline-flex; align-items: center; gap: .4em;
  transition: gap var(--rp-fast);
}
.hs-contact__card:hover .hs-contact__link { gap: .7em; }

/* --------------------------------------------------------------------------
   20. FINAL CTA + FOOTER
   -------------------------------------------------------------------------- */
.hs-final {
  position: relative; overflow: hidden;
  border-radius: var(--rp-r-lg);
  border: 1px solid var(--rp-border2);
  background: linear-gradient(150deg, #12131c, #0a0b11 55%, #150d12);
  padding: clamp(2.8rem, 6vw, 5rem) clamp(1.5rem, 4vw, 3.5rem);
  /* NB: centring comes from the .hs-center class on the element, not from a
     text-align here. Setting it locally is what caused the button row to stay
     left-aligned: text-align centres inline content, but .hs-cta-row is a flex
     container and needs justify-content -- which only .hs-center supplies. One
     mechanism, one place. */
}
.hs-final::before {
  content: ""; position: absolute; inset: -50% -10%;
  background:
    radial-gradient(38% 55% at 18% 50%, color-mix(in srgb, var(--rp-accent) 32%, transparent), transparent 70%),
    radial-gradient(38% 55% at 82% 50%, color-mix(in srgb, var(--rp-brand) 30%, transparent), transparent 70%);
  filter: blur(48px); pointer-events: none;
  animation: hs-drift 18s ease-in-out infinite alternate;
}
@keyframes hs-drift { from { transform: translateX(-3%); } to { transform: translateX(3%); } }
.hs-final > * { position: relative; z-index: 1; }

.hs-foot { border-top: 1px solid var(--rp-border); padding-block: 2.6rem 3rem; }
.hs-foot__inner { display: flex; flex-wrap: wrap; gap: 1.5rem 2.5rem; align-items: center; }
.hs-foot__logo { width: 132px; }
.hs-foot__logo svg { width: 100%; height: auto; opacity: .85; }
.hs-foot__links { display: flex; flex-wrap: wrap; gap: 1.35rem; margin-left: auto; }
.hs-foot__links a { font-size: .855rem; color: var(--rp-text3); transition: color var(--rp-fast); }
.hs-foot__links a:hover { color: var(--rp-accent); }
.hs-foot__legal { width: 100%; font-size: .78rem; color: var(--rp-text3); padding-top: 1.4rem; border-top: 1px solid var(--rp-border); }

/* --------------------------------------------------------------------------
   21. SCROLL REVEAL -- the class is added by IntersectionObserver.
   Everything starts hidden ONLY if JS is running (html.hs-js), so the page
   is still fully readable with JS blocked. That's the progressive-enhancement
   rule: never hide content you can't guarantee you'll show again.
   -------------------------------------------------------------------------- */
.hs-js .hs-reveal {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity var(--rp-slow), transform var(--rp-slow);
  transition-delay: var(--d, 0ms);
  will-change: opacity, transform;
}
.hs-js .hs-reveal.is-in { opacity: 1; transform: none; }

/* ------------------------------------------------- customer reviews --- */
/* Score beside the breakdown rather than above it: same information, about
   half the height, and the bars get the width to actually be read. */
.hs-rsummary__eyebrow { display: block; text-align: center; margin-bottom: 1.1rem; }
.hs-rsummary {
  display: grid; grid-template-columns: minmax(0, 210px) minmax(0, 1fr);
  gap: clamp(1.4rem, 3.5vw, 3rem); align-items: center;
  margin-bottom: clamp(1.8rem, 3.5vw, 2.6rem);
}
.hs-rsummary__score { text-align: center; }
.hs-rsummary__num {
  font-size: clamp(2.4rem, 5vw, 3.4rem); font-weight: 700;
  line-height: 1; letter-spacing: -.03em; margin: .7rem 0 .5rem;
}
.hs-rsummary__count {
  margin: .55rem 0 0; font-family: var(--rp-font-mono); font-size: .66rem;
  letter-spacing: .12em; text-transform: uppercase; color: var(--rp-text3);
}
@media (max-width: 760px) {
  .hs-rsummary { grid-template-columns: minmax(0, 1fr); }
  .hs-rbars { max-width: 320px; margin-inline: auto; }
}

/* The breakdown. Every row is counted from the ratings, never written by hand. */
.hs-rbars { display: grid; gap: .3rem; }
.hs-rbar {
  display: grid; grid-template-columns: 2.4ch minmax(0, 1fr) 2.5ch;
  gap: .6rem; align-items: center;
  font-family: var(--rp-font-mono); font-size: .64rem; color: var(--rp-text3);
}
.hs-rbar__track {
  height: 7px; border-radius: 999px; overflow: hidden;
  background: rgba(255, 255, 255, .09);
}
.hs-rbar__fill {
  display: block; height: 100%; border-radius: 999px;
  background: var(--rp-accent);
}
.hs-rbar__c { text-align: right; }

/* Cards. Taller than a clamped teaser so a short review is whole on the card,
   and long ones fade rather than cut mid-word. */
.hs-creviews {
  display: grid; gap: clamp(.7rem, 1.6vw, 1rem);
  /* Four, explicitly. auto-fit picked three at this measure and stranded the
     fourth card alone on a second row. */
  grid-template-columns: repeat(4, minmax(0, 1fr));
}
@media (max-width: 940px) { .hs-creviews { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* Still two across on a phone - the pager drops to 2 per page to match, so a
   card keeps a readable width instead of being squeezed to a column of four.
   Everything shrinks a step rather than the layout collapsing. */
@media (max-width: 520px) {
  .hs-creviews { gap: .55rem; }
  .hs-creview { min-height: 210px; padding: .8rem .85rem; gap: .4rem; }
  .hs-creview__title { font-size: .82rem; }
  .hs-creview__body { font-size: .78rem; -webkit-line-clamp: 5; }
  .hs-creview__by { font-size: .54rem; gap: .3rem; flex-wrap: wrap; }
  .hs-creview__more { display: none; }
}
.hs-creview {
  position: relative; overflow: hidden;
  min-height: 250px; padding: 1rem 1.1rem;
  display: flex; flex-direction: column; gap: .5rem; text-align: left;
  border: 1px solid var(--rp-border); border-radius: var(--rp-r-lg);
  background: linear-gradient(168deg, var(--rp-card, #12131c), var(--rp-panel, #0d0e15));
  color: inherit; font: inherit; cursor: pointer;
  transition: border-color var(--rp-med), transform var(--rp-med), box-shadow var(--rp-med);
}
.hs-root .hs-creview:hover, .hs-root .hs-creview:focus-visible {
  transform: translateY(-2px);
  border-color: color-mix(in srgb, var(--rp-accent) 55%, transparent);
  box-shadow: 0 24px 46px -30px rgba(0,0,0,.95);
}
.hs-creview.is-hidden { display: none; }
.hs-creview__title { font-size: .92rem; color: var(--rp-text); }
.hs-creview__body {
  font-size: .85rem; line-height: 1.55; color: var(--rp-text2);
  display: -webkit-box; -webkit-line-clamp: 6; -webkit-box-orient: vertical;
  overflow: hidden;
}
.hs-creview__by {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: .6rem; margin-top: auto; padding-top: .5rem;
  font-family: var(--rp-font-mono); font-size: .6rem;
  letter-spacing: .1em; text-transform: uppercase; color: var(--rp-text3);
}
.hs-creview__name { color: var(--rp-text2); font-weight: 700; }
/* Quiet on purpose. The badge is a fact, not a sales device - it sits beside
   the name at the same weight as the date, and never competes with the review
   itself. Green rather than the product accent, so it reads as a status and
   not as decoration. */
/* Rating and badge on one line: both answer "how much does this count", so
   they are read together, above the words rather than buried under them. Wraps
   rather than squeezing - on the narrowest cards the badge drops to its own
   line instead of crushing the stars. */
.hs-creview__top {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: .4rem .5rem;
}
.hs-vbadge {
  display: inline-flex; align-items: center; gap: .25em;
  padding: .15em .5em;
  font-family: var(--rp-font-mono); font-size: .54rem; text-transform: uppercase;
  border-radius: 999px;
  border: 1px solid color-mix(in srgb, #35d07f 45%, transparent);
  background: color-mix(in srgb, #35d07f 12%, transparent);
  color: #7ce0ab;
  font-weight: 700; letter-spacing: .08em;
  white-space: nowrap;
}
.hs-rmodal__verified {
  display: inline-flex; align-items: center; gap: .3em;
  margin: .8rem 0 0; padding: .25em .7em;
  border-radius: 999px;
  border: 1px solid color-mix(in srgb, #35d07f 45%, transparent);
  background: color-mix(in srgb, #35d07f 12%, transparent);
  color: #7ce0ab;
  font-family: var(--rp-font-mono); font-size: .62rem;
  letter-spacing: .12em; text-transform: uppercase;
}
.hs-rmodal__verified[hidden] { display: none; }
/* Present for a mouse only on hover, but always in the accessibility tree via
   the button role - a keyboard user gets it from focus styling instead. */
.hs-creview__more {
  font-family: var(--rp-font-mono); font-size: .56rem; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase; color: var(--rp-accent);
  opacity: 0; transition: opacity var(--rp-med);
}
.hs-creview:hover .hs-creview__more,
.hs-creview:focus-visible .hs-creview__more { opacity: 1; }

/* Paging controls. Same shape as the hero slider's arrows so the two read as
   the same control, with a count between them - without it there is no way to
   tell how much is left, and an arrow that silently wraps feels broken. */
.hs-pager {
  display: flex; align-items: center; justify-content: center; gap: .9rem;
  margin-top: clamp(1.1rem, 2.4vw, 1.6rem);
}
.hs-pager__arrow {
  display: grid; place-items: center;
  width: 38px; height: 38px; padding: 0; border-radius: 50%; cursor: pointer;
  border: 1px solid rgba(255, 255, 255, .22);
  background: rgba(255, 255, 255, .06);
  color: var(--rp-text);
  transition: background var(--rp-med), border-color var(--rp-med), transform var(--rp-med);
}
.hs-root .hs-pager__arrow:hover {
  background: rgba(255, 255, 255, .14);
  border-color: color-mix(in srgb, var(--rp-accent) 70%, transparent);
  transform: scale(1.06);
}
.hs-pager__arrow:focus-visible { outline: 2px solid var(--rp-accent); outline-offset: 3px; }
.hs-pager__arrow svg { width: 16px; height: 16px; }
.hs-pager__count {
  min-width: 5ch; text-align: center;
  font-family: var(--rp-font-mono); font-size: .72rem; font-weight: 700;
  letter-spacing: .12em; color: var(--rp-text3);
}
@media (prefers-reduced-motion: reduce) {
  .hs-pager__arrow { transition: none; }
  .hs-root .hs-pager__arrow:hover { transform: none; }
}

/* The full review. <dialog> supplies the backdrop and Escape; this only has to
   look like the rest of the site. */
.hs-rmodal {
  width: min(92vw, 640px); padding: clamp(1.5rem, 3vw, 2.2rem);
  border: 1px solid var(--rp-border2); border-radius: var(--rp-r-lg);
  background: var(--rp-panel, #0d0e15); color: var(--rp-text);
  box-shadow: 0 40px 90px -40px rgba(0,0,0,1);
}
.hs-rmodal::backdrop { background: rgba(0, 0, 0, .72); backdrop-filter: blur(3px); }
.hs-rmodal__close {
  position: absolute; top: .7rem; right: .8rem;
  width: 32px; height: 32px; border-radius: 50%; cursor: pointer;
  border: 1px solid var(--rp-border); background: none;
  color: var(--rp-text3); font-size: 1.2rem; line-height: 1;
}
.hs-root .hs-rmodal__close:hover { color: var(--rp-text); }
.hs-rmodal__title { display: block; margin: .8rem 0 .6rem; font-size: 1.15rem; }
.hs-rmodal__body { margin: 0; color: var(--rp-text2); line-height: 1.7; }
.hs-rmodal__by {
  margin: 1.1rem 0 0; font-family: var(--rp-font-mono); font-size: .66rem;
  letter-spacing: .12em; text-transform: uppercase; color: var(--rp-text3);
}

/* Stars. An outline for the unearned ones rather than a missing shape, so a
   5-star review can never be mistaken for a 1-star one. */
.hs-stars { display: inline-flex; gap: .12rem; color: var(--rp-brand); }
.hs-stars svg { width: 15px; height: 15px; }
.hs-stars--lg { justify-content: center; }
.hs-stars--lg svg { width: 22px; height: 22px; }

@media (prefers-reduced-motion: reduce) {
  .hs-creview, .hs-creviews__all, .hs-creview__more { transition: none; }
  .hs-root .hs-creview:hover { transform: none; }
}

/* --------------------------------------------------------------------------
   22. REDUCED MOTION -- respect the OS setting. Non-negotiable for a11y.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .hs-root *,
  .hs-root *::before,
  .hs-root *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  .hs-js .hs-reveal { opacity: 1 !important; transform: none !important; }
  .hs-shot__frame { transform: none !important; }
}

/* ----------------------------------------------------------- hero slider --- */
/* Only present when a product declares hero.images. Every slide is stacked in
   the same box and cross-faded, so the frame never changes size between shots
   - the images are all the same aspect, and this keeps the page from jumping
   even if one day they are not.

   The first slide keeps its place in flow and sets the height; the rest are
   absolutely positioned over it. Without JavaScript they simply stack and the
   first one is on top, so the hero still shows the plugin. */
/* pan-y: vertical scrolling stays with the browser, horizontal gestures
   come to the slider. Without it a sideways drag scrolls the page and the
   swipe never lands. */
.hs-shot--slider .hs-shot__frame { position: relative; touch-action: pan-y; }
.hs-shot__slide { display: block; width: 100%; }
.hs-shot--slider .hs-shot__slide + .hs-shot__slide {
  position: absolute; inset: 0; height: 100%;
}
/* .hs-js is set by the page script, so these opacity rules only take effect
   once something can change them back. */
.hs-js .hs-shot--slider .hs-shot__slide {
  opacity: 0; transition: opacity 620ms ease;
}
.hs-js .hs-shot--slider .hs-shot__slide.is-current { opacity: 1; }

.hs-shot__dots {
  display: flex; justify-content: center; align-items: center; gap: .5rem;
  margin-top: 1rem;
}
/* NOT --rp-text3 for the inactive state. A product theme may repaint that
   token - Clarity Delay sets it to the guide's teal - which made the inactive
   dot the SAME colour as the active one, so nothing indicated which slide you
   were on. A fixed white at low alpha reads on any product's ground. */
.hs-root .hs-shot__dot {
  width: 30px; height: 6px; padding: 0; border: 0; border-radius: 999px;
  background: rgba(255, 255, 255, .26);
  cursor: pointer;
  transition: background var(--rp-med), width var(--rp-med), box-shadow var(--rp-med);
}
.hs-root .hs-root .hs-shot__dot:hover { background: rgba(255, 255, 255, .55); }
/* The current slide is wider AND brighter: two signals, so it still reads for
   anyone who cannot separate the accent from white. */
.hs-root .hs-shot__dot[aria-current="true"] {
  width: 46px;
  background: var(--rp-accent);
  box-shadow: 0 0 14px -2px color-mix(in srgb, var(--rp-accent) 70%, transparent);
}
.hs-root .hs-root .hs-shot__dot:focus-visible { outline: 2px solid var(--rp-accent); outline-offset: 3px; }

/* Prev/next. Swipe already works on touch; these are the same control for a
   mouse, which has nothing to swipe with. */
.hs-root .hs-shot__arrow {
  display: grid; place-items: center;
  width: 34px; height: 34px; padding: 0;
  border-radius: 50%; cursor: pointer;
  border: 1px solid rgba(255, 255, 255, .22);
  background: rgba(255, 255, 255, .06);
  color: var(--rp-text);
  transition: background var(--rp-med), border-color var(--rp-med), transform var(--rp-med);
}
.hs-root .hs-shot__arrow:hover {
  background: rgba(255, 255, 255, .14);
  border-color: color-mix(in srgb, var(--rp-accent) 70%, transparent);
  transform: scale(1.06);
}
.hs-root .hs-shot__arrow:focus-visible { outline: 2px solid var(--rp-accent); outline-offset: 3px; }
.hs-shot__arrow svg { width: 15px; height: 15px; }
@media (prefers-reduced-motion: reduce) {
  .hs-shot__dot, .hs-shot__arrow { transition: none; }
  .hs-shot__arrow:hover { transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .hs-js .hs-shot--slider .hs-shot__slide { transition: none; }
}

/* --------------------------------------------------- review submission --- */
.hs-reviewform {
  display: grid; gap: .7rem; max-width: 620px; margin: 0 auto;
  grid-template-columns: 1fr 1fr;
}
.hs-reviewform__body, .hs-reviewform__go,
.hs-reviewform__note { grid-column: 1 / -1; }
.hs-reviewform__field {
  padding: .85rem 1.1rem; border-radius: var(--rp-r);
  border: 1px solid var(--rp-border2); background: rgba(255,255,255,.03);
  color: var(--rp-text); font: inherit;
}
/* Dark the whole control, popup list included. Without color-scheme the
   option list is drawn by the UA in its light palette, which put near-white
   text on a white background - legible only by luck. */
.hs-reviewform__field { color-scheme: dark; }
.hs-reviewform__field option {
  background: var(--rp-panel, #0d0e15);
  color: var(--rp-text, #eceef6);
}
.hs-reviewform__field:focus {
  outline: 2px solid var(--rp-accent); outline-offset: 2px; border-color: transparent;
}
.hs-reviewform__note {
  margin: .2rem 0 0; min-height: 1.4em; font-size: .9rem; color: var(--rp-text2);
}
/* The success line, and the code inside it. Monospace and boxed because it is
   a thing to be copied by hand - the shape says "select me" without a button
   that would need clipboard permissions to mean anything. */
.hs-reviewform__note.is-thanks { color: var(--rp-text); }
.hs-reviewform__code {
  display: inline-block; margin-left: .1em; padding: .12em .5em;
  border-radius: 6px; border: 1px dashed var(--rp-accent);
  background: color-mix(in srgb, var(--rp-accent) 12%, transparent);
  font-family: var(--rp-font-mono); font-size: .95em; letter-spacing: .08em;
  user-select: all;
}
/* Offsets the anchor from under the sticky header, so #reviews lands on the
   heading rather than scrolling it out of sight. */
.hs-anchor { display: block; height: 0; scroll-margin-top: 90px; }

@media (max-width: 560px) { .hs-reviewform { grid-template-columns: 1fr; } }


/* visually-hidden but still read by screen readers */
.hs-root .hs-sr {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}
