/* Stem cells vs knee replacement (/stem-cells-vs-knee-replacement), the page
   the "knee replacement alternative" ads land on. Rebuilt 2026-10-10.

   Layered over site.css and celva-home.css, the way home-page.css sits over
   index.html: this page keeps the shared engine (the hero, the film tile and
   its player, the reveals) because tests/e2e/vs-knee-replacement.spec.ts pins
   them, and everything here is scoped to .lp-vs-knee so nothing reaches the
   home page or the eight sibling landing pages. Never move a rule from here
   into celva-home.css.

   What the spec pins, and so what must not be renamed or reshaped here: the
   render-to-film pairs (.vsfig, .surgfig, their --a and --b halves, the
   vsSwap and vsSwapOut dwell), the film tile beside the four tiers riding at
   96px (.sec-split, .sec-still--pt), the first button inside the first phone
   screen, and no sideways scroll.

   The comparison is drawn level on purpose: two white cards of the same
   weight, the same eight rows in the same order, each row's rule running
   across both. Neither column is the highlighted one. */

/* Top: the fixed header. Bottom: the bar that follows the reader (48px, 18px
   off the foot), so a control reached with Tab is never parked under it. On
   the root, not :root: this sheet loads on this page alone,
   and a browser without :has() would drop the rule. */
:root { scroll-padding-top: 100px; scroll-padding-bottom: 84px; }
.lp-vs-knee main { overflow-x: clip; }
.lp-vs-knee .nb { white-space: nowrap; }

/* ---------- type and rhythm ---------- */
/* A heading breaks where its style changes, never mid-phrase. */
.lp-vs-knee main :is(h1, h2) > :is(.h-lead, em) { display: inline-block; }
.lp-vs-knee .sec { padding: clamp(60px, 7vw, 100px) 0; }
.lp-vs-knee :is(.sec-h2, .sec-h2--xl) { font-size: clamp(2rem, 3.5vw, 3.1rem); line-height: 1.08; margin: 0; }
.lp-vs-knee .sec-h2 em { color: var(--accent); }
.lp-vs-knee .lede { font-size: 1.125rem; line-height: 1.62; margin: 18px 0 0; font-weight: 400; }
.lp-vs-knee h2[tabindex="-1"]:focus { outline: none; }

/* ---------- buttons: focus and press ---------- */
.lp-vs-knee main .btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.lp-vs-knee :is(.hero, .ctaband) .btn:focus-visible { outline-color: #fff; }
.lp-vs-knee main .btn:active { transform: scale(.98); box-shadow: var(--shadow-sm); transition-duration: .08s; }

/* ---------- hero ---------- */
/* The first screen paints finished. celva-home.css hides every [data-r] and
   clips the picture until its script has run; a paid click should not wait
   on a script to read the headline or see the button. The picture settles
   in with a CSS animation that needs no script and hides nothing. */
.lp-vs-knee .hero { padding-bottom: clamp(44px, 6vw, 88px); }
.lp-vs-knee .hero__h1 { font-size: clamp(2.3rem, 4.6vw, 4.1rem); }
.lp-vs-knee .hero__sub { max-width: none; }
.js-anim .lp-vs-knee .hero [data-r] { opacity: 1; transform: none; transition: none; }
.js-anim .lp-vs-knee .hero__img { clip-path: none; }
/* site.js moves this film a few pixels as the page scrolls; the frame is the
   render's own black, so the strip it uncovers cannot be seen. */
.lp-vs-knee .hero__img { background: #05080F; }
.lp-vs-knee .hero__img video { animation: vkSettle 1.8s var(--ease) backwards; }
@keyframes vkSettle { from { transform: scale(1.17); } }

/* ---------- the comparison ---------- */
.lp-vs-knee .vialsec { background: #fff; }
.lp-vs-knee .vial { gap: 0 24px; margin-top: 44px; }
.lp-vs-knee .vial__col,
.lp-vs-knee .vial__col--celva { background: #fff; color: var(--ink); border: 1px solid var(--border); box-shadow: none; }
.lp-vs-knee .vial__col:hover { transform: none; box-shadow: none; }
.lp-vs-knee .vial__col--celva::before { content: none; }
.lp-vs-knee :is(.vial__tag, .vial__col--celva .vial__tag) { display: block; font-family: var(--font-body); font-size: .9375rem; font-weight: 500; letter-spacing: 0; text-transform: none; color: var(--accent); border: 0; border-radius: 0; padding: 0; }
.lp-vs-knee .vial__col h3 { margin: 8px 0 0; }
.lp-vs-knee .vial__col ul { gap: 0; margin-top: 18px; }
.lp-vs-knee :is(.vial__col, .vial__col--celva) li { font-size: 1rem; line-height: 1.6; color: var(--ink-muted); padding: 16px 0; }
/* Each row starts with its label, so the two columns read across as well as
   down. The words are the page's; only the dress changed (it was 9.6px mono
   capitals). */
.lp-vs-knee :is(.vial__col, .vial__col--celva) li b { display: block; font-family: var(--font-body); font-size: .875rem; font-weight: 600; letter-spacing: 0; text-transform: none; color: var(--ink); margin-bottom: 4px; }
/* The rule above each row. celva-home.css uses li::before for a dash; here it
   is the row's rule, so it can be drawn. */
.lp-vs-knee :is(.vial__col, .vial__col--celva) li::before { display: block; left: 0; right: 0; top: 0; width: auto; height: 1px; background: var(--border); transform-origin: left; }
.lp-vs-knee .vial__col li:first-child::before { display: none; }
.lp-vs-knee .vial__col li:first-child { padding-top: 0; }
.lp-vs-knee .vial__col li:last-child { padding-bottom: 0; }
/* Drawn left to right, a row at a time, the same row in both cards at the
   same moment: what the motion says is that the rows pair up. Only where a
   script has said it will finish the job (.js-anim), so nothing is ever left
   without its rule. */
.js-anim .lp-vs-knee .vial__col li::before { transform: scaleX(0); transition: transform .9s var(--ease); transition-delay: calc(var(--row, 0) * 70ms + 120ms); }
.js-anim .lp-vs-knee .vial__col.is-in li::before { transform: none; }
.lp-vs-knee .vial__col li:nth-child(2) { --row: 1; }
.lp-vs-knee .vial__col li:nth-child(3) { --row: 2; }
.lp-vs-knee .vial__col li:nth-child(4) { --row: 3; }
.lp-vs-knee .vial__col li:nth-child(5) { --row: 4; }
.lp-vs-knee .vial__col li:nth-child(6) { --row: 5; }
.lp-vs-knee .vial__col li:nth-child(7) { --row: 6; }
.lp-vs-knee .vial__col li:nth-child(8) { --row: 7; }
/* Side by side, the two cards share one set of rows, so "Recovery" on the
   left sits level with "Recovery" on the right however the text wraps. */
@supports (grid-template-rows: subgrid) {
  @media (min-width: 1081px) {
    .lp-vs-knee .vial__col { display: grid; grid-template-rows: subgrid; grid-row: span 11; align-content: start; }
    .lp-vs-knee .vial__col > ul { display: grid; grid-template-rows: subgrid; grid-row: span 8; }
  }
}
.lp-vs-knee .vial__closing { margin: 36px 0 0; text-align: left; font-family: var(--font-body); font-size: 1.0625rem; line-height: 1.7; font-weight: 400; color: var(--ink-muted); }
.lp-vs-knee .cta { margin-top: 36px; }

/* The figures: a 3D render at rest, the matching film on hover. The two
   comparison figures (.vsfig) and the surgery one (.surgfig) share every rule
   but the frame and the element whose hover they answer to. All six images
   are illustrations, not a patient's imaging. The three renders say so in
   their alt text; the three films do not (Jon, 2026-10-03), and the chips
   stay short (Jarred, 2026-09-23). */
.lp-vs-knee .vsfig { margin: -32px -32px 24px; }
.lp-vs-knee .vsfig__frame { position: relative; aspect-ratio: 4/3; overflow: hidden; background: #05080F; }
.lp-vs-knee .surgfig { margin: 0; }
.lp-vs-knee .surgfig__frame { position: relative; aspect-ratio: 1/1; border-radius: 14px; overflow: hidden; background: #05080F; box-shadow: var(--shadow-md); }
.lp-vs-knee :is(.vsfig__img, .surgfig__img) { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transform: scale(1.04); transition: transform 1.4s var(--ease), opacity .6s var(--ease); }
.lp-vs-knee :is(.vsfig__img--b, .surgfig__img--b) { opacity: 0; }
.lp-vs-knee :is(.vsfig__cap, .surgfig__cap) { position: absolute; left: 16px; top: 16px; }
.lp-vs-knee :is(.vsfig__cap, .surgfig__cap) b { display: block; background: #fff; border-radius: 6px; padding: 7px 11px; font-family: var(--font-body); font-size: .8125rem; font-weight: 500; line-height: 1.3; color: var(--ink); box-shadow: var(--shadow-sm); transition: transform .5s var(--ease), opacity .6s var(--ease); }
.lp-vs-knee :is(.vsfig__cap--b, .surgfig__cap--b) { position: absolute; left: 0; top: 0; white-space: nowrap; opacity: 0; }
.lp-vs-knee :is(.vial__col, .surgfig):hover :is(.vsfig__img, .surgfig__img) { transform: scale(1.09); }
.lp-vs-knee :is(.vial__col, .surgfig):hover :is(.vsfig__img--b, .surgfig__img--b) { opacity: 1; }
.lp-vs-knee :is(.vial__col, .surgfig):hover :is(.vsfig__cap, .surgfig__cap) b { transform: translateY(-3px); }
.lp-vs-knee :is(.vial__col, .surgfig):hover :is(.vsfig__cap--b, .surgfig__cap--b) { opacity: 1; }
/* The chips are stacked, so the first has to leave as the second arrives or
   the two sets of text read through each other mid-fade. */
.lp-vs-knee :is(.vial__col, .surgfig):hover :is(.vsfig__cap--a, .surgfig__cap--a) { opacity: 0; }
/* A phone has no hover, and most of this page's readers are on one, so the
   pair crossfades on a long dwell instead of never showing the second image.
   It loops for as long as the page is open: the clock starts at load, so a
   counted run would be over before a reader scrolled this far. */
@media (hover: none) {
  .lp-vs-knee :is(.vsfig__img--b, .vsfig__cap--b, .surgfig__img--b, .surgfig__cap--b) { animation: vsSwap 9s ease-in-out infinite; }
  .lp-vs-knee :is(.vsfig__cap--a, .surgfig__cap--a) { animation: vsSwapOut 9s ease-in-out infinite; }
  /* The dwell runs only while its figure is on screen. The page script marks
     the root once it is watching (.vk-live) and each frame as it comes and
     goes (.is-live); with no script the loop simply runs, as it always did. */
  .vk-live .lp-vs-knee :is(.vsfig__frame, .surgfig__frame):not(.is-live) :is(.vsfig__img--b, .vsfig__cap--b, .vsfig__cap--a, .surgfig__img--b, .surgfig__cap--b, .surgfig__cap--a) { animation-play-state: paused; }
}
@keyframes vsSwap { 0%, 42% { opacity: 0 } 52%, 92% { opacity: 1 } 100% { opacity: 0 } }
@keyframes vsSwapOut { 0%, 42% { opacity: 1 } 52%, 92% { opacity: 0 } 100% { opacity: 1 } }

/* ---------- when surgery is the right tool ---------- */
/* One short block on purpose: the text and the render sit side by side. */
.lp-vs-knee .surg { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, .8fr); gap: clamp(32px, 5vw, 72px); align-items: center; margin-top: 8px; }
.lp-vs-knee .plain p { font-size: 1.0625rem; line-height: 1.7; color: var(--ink-muted); font-weight: 400; margin: 22px 0 0; }
.lp-vs-knee .plain p.plain__last { color: var(--ink); font-family: var(--font-display); font-size: clamp(1.4rem, 2vw, 1.75rem); line-height: 1.3; font-weight: 300; }

/* ---------- Dr. Lewis ---------- */
/* The page's one tinted band. A native player with captions, and his
   credentials as he states them on camera. */
.lp-vs-knee .band { background: var(--accent-wash); padding: clamp(60px, 7vw, 100px) 0; }
.lp-vs-knee .band__in { text-align: left; align-items: stretch; }
.lp-vs-knee .band__lede { margin-left: 0; margin-right: 0; color: var(--ink-soft); }
.lp-vs-knee .kvid { width: 100%; max-width: none; margin: 40px 0 0; border-radius: 14px; overflow: hidden; box-shadow: var(--shadow-md); background: #07162c; }
.lp-vs-knee .kvid video { display: block; width: 100%; aspect-ratio: 1600/670; }
.lp-vs-knee .kvid video:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.lp-vs-knee .kcap { margin: 14px 0 0; font-size: .875rem; line-height: 1.5; color: var(--ink-soft); }
.lp-vs-knee .kcreds { list-style: none; margin: 36px 0 0; padding: 0; width: 100%; display: grid; grid-template-columns: repeat(3, 1fr); gap: 22px 32px; text-align: left; }
.lp-vs-knee .kcreds li { position: relative; padding: 14px 0 0; font-size: .9375rem; line-height: 1.5; color: var(--ink-soft); }
.lp-vs-knee .kcreds li::before { content: ""; position: absolute; left: 0; right: 0; top: 0; height: 1px; background: var(--border-strong); transform-origin: left; }
.lp-vs-knee .kcreds strong { display: block; color: var(--ink); font-weight: 600; margin-bottom: 2px; }
/* The six credentials fade the way everything else does (celva-home.js
   staggers them); their rules are ruled in after, one beat behind the text. */
.js-anim .lp-vs-knee .kcreds li::before { transform: scaleX(0); transition: transform .8s var(--ease) .25s; transition-delay: inherit; }
.js-anim .lp-vs-knee .kcreds li.is-in::before { transform: none; }
.lp-vs-knee .kfine { margin: 28px 0 0; font-size: .875rem; line-height: 1.6; color: var(--ink-soft); }

/* ---------- who qualifies ---------- */
/* Four candidacy tiers, two by two. They are not links, so they do not lift
   under a pointer. */
.lp-vs-knee .cells--four { grid-template-columns: repeat(2, 1fr); gap: 20px; }
.lp-vs-knee .cell { box-shadow: none; padding: 26px; }
.lp-vs-knee .cell:hover { transform: none; box-shadow: none; }
.lp-vs-knee .cell__code { display: block; font-family: var(--font-body); font-size: .875rem; font-weight: 600; letter-spacing: 0; text-transform: none; color: var(--accent); }
.lp-vs-knee .cell h3 { font-size: 1.5rem; line-height: 1.2; margin: 8px 0 10px; align-self: start; }
.lp-vs-knee .cell p { font-size: 1rem; }
@supports (grid-template-rows: subgrid) {
  @media (min-width: 1081px) {
    /* Verdict, heading and text line up across each pair of cards. */
    .lp-vs-knee .cells--four .cell { display: grid; grid-template-rows: subgrid; grid-row: span 3; row-gap: 0; align-content: start; }
  }
}
/* Kathie beside the tiers. Ported from the spine page's own block
   (branch claude/spine-lp-rewrite, PR #354, its degenerative-disc section);
   a fix to one copy belongs in the other. The tile rides sticky down the
   cards column and stops with its bottom on the last card's bottom: the
   sticky element is a full-height wrapper and the tile sits at its top,
   with the caption hanging below it so it adds no height to the sticky box. */
.lp-vs-knee .sec-split { display: grid; grid-template-columns: minmax(0,.8fr) minmax(0,1.2fr); gap: clamp(28px,3.6vw,56px); align-items: start; margin-top: 44px; }
.lp-vs-knee .sec-split .cells { margin-top: 0; }
.lp-vs-knee .sec-still--pt { margin: 0; align-self: stretch; display: flex; flex-direction: column; }
.lp-vs-knee .sec-still--pt > .sec-still__sticky { position: sticky; top: 96px; }
.lp-vs-knee .sec-still--pt .pt-fig__cap { position: absolute; left: 0; right: 0; top: 100%; margin: 12px 0 0; }
.lp-vs-knee .sec-still--pt .pt-tile { aspect-ratio: 3/4; }
.lp-vs-knee .pt-fig__cap { font-family: var(--font-body); font-size: .875rem; letter-spacing: 0; text-transform: none; color: var(--ink-muted); }
.lp-vs-knee .pt-tile:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }
.lp-vs-knee .pt-tile:active { transform: scale(.985); transition-duration: .08s; }
.lp-vs-knee .pt-modal__close:focus-visible { outline: 2px solid #fff; outline-offset: 2px; border-radius: 6px; }
/* Not in the spine page's copy: on a short laptop screen the riding tile was
   taller than the room under the header, so its foot and caption were cut.
   The room is what the header's offset (96px), the bar's zone at the foot
   (66px) and the caption (46px) leave. */
@media (min-width:1081px) { .lp-vs-knee .sec-still--pt .pt-tile { max-height: calc(100vh - 96px - 66px - 46px); } }

/* ---------- questions ---------- */
/* The heading runs the full width above; the line under it and the button
   ride beside the answers. */
.lp-vs-knee .faq { margin-top: 36px; }
.lp-vs-knee .faq__head .lede { margin-top: 0; }
.lp-vs-knee .faq__head .cta { margin-top: 28px; }
.lp-vs-knee .faq__list summary { align-items: center; gap: 16px; padding: 20px 0; min-height: 44px; }
.lp-vs-knee .faq__list summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; border-radius: 4px; }
.lp-vs-knee .faq__list summary:active { color: var(--accent-hover); }
/* The sign comes first in the markup (the question has to stay the summary's
   second child) and last on screen. */
.lp-vs-knee .faq__ic { order: 2; margin-left: auto; width: 28px; height: 28px; display: grid; place-items: center; }
.lp-vs-knee .faq__a { padding: 0 44px 24px 0; max-width: none; font-size: 1rem; line-height: 1.7; }

/* ---------- the closing call ---------- */
.lp-vs-knee .ctaband { padding: clamp(80px, 10vw, 136px) 0; }
.lp-vs-knee .ctaband__disclaimer { font-family: var(--font-body); font-size: .8125rem; letter-spacing: 0; line-height: 1.6; text-transform: none; color: rgba(255,255,255,.74); }

/* ---------- the bar that follows the reader ---------- */
/* At the foot of the window, not under the header: the film tile rides 96px
   from the top (the spec holds it there) and a bar under the header would
   sit on it. On a phone it is a strip under the thumb. */
.lp-vs-knee .hc-bar { position: fixed; left: 50%; bottom: 18px; z-index: 60; height: 48px; max-width: calc(100vw - 32px); background: rgba(255,255,255,.97); -webkit-backdrop-filter: saturate(180%) blur(12px); backdrop-filter: saturate(180%) blur(12px); border: 1px solid var(--border); border-radius: 10px; box-shadow: var(--shadow-md); overflow: hidden; transform: translate(-50%, 14px); opacity: 0; pointer-events: none; transition: opacity .2s, transform .3s var(--ease); }
/* Off, it is only unseen and untouchable, never out of the tab order: the
   bar comes before the page's parts in the markup, so Tab from the header
   lands in it, and holding the keyboard shows it. */
.lp-vs-knee .hc-bar:is(.is-on, :focus-within) { transform: translate(-50%, 0); opacity: 1; pointer-events: auto; transition: opacity .26s, transform .36s var(--ease); }
body.lp-vs-knee.nav-open .hc-bar { opacity: 0; visibility: hidden; pointer-events: none; }
.lp-vs-knee .hc-bar__track { display: flex; align-items: stretch; gap: 26px; height: 100%; padding: 0 22px; overflow-x: auto; scrollbar-width: none; overscroll-behavior-x: contain; scroll-padding-inline: 28px; }
.lp-vs-knee .hc-bar__track::-webkit-scrollbar { display: none; }
.lp-vs-knee .hc-bar__track a { position: relative; flex: none; display: inline-flex; align-items: center; min-width: 44px; color: var(--ink-muted); font-size: .875rem; font-weight: 500; white-space: nowrap; text-decoration: none; border-bottom: 0; transition: color .25s; }
.lp-vs-knee .hc-bar__track a::after { content: ""; position: absolute; left: 0; right: 0; bottom: 8px; height: 2px; background: var(--ink); transform: scaleX(0); transform-origin: left; transition: transform .4s var(--ease); }
.lp-vs-knee .hc-bar__track a:hover, .lp-vs-knee .hc-bar__track a[aria-current] { color: var(--ink); }
.lp-vs-knee .hc-bar__track a:hover::after { transform: scaleX(.35); }
.lp-vs-knee .hc-bar__track a[aria-current]::after { transform: scaleX(1); }
.lp-vs-knee .hc-bar__track a:active { color: var(--accent); }
.lp-vs-knee .hc-bar__track a:focus-visible { outline: 2px solid var(--accent); outline-offset: -6px; border-radius: 6px; }
/* How far through the page's five parts the reader is. */
.lp-vs-knee .hc-bar__progress { position: absolute; left: 0; right: 0; top: 0; height: 2px; background: var(--accent); transform-origin: left; transform: scaleX(var(--hc-p, 0)); }

/* ---------- narrower ---------- */
@media (max-width:1080px) {
  .lp-vs-knee .cells--four { grid-template-columns: 1fr; }
  .lp-vs-knee .sec-split { grid-template-columns: minmax(0,1fr); gap: 36px; }
  /* WebKit shrinks a flex-column figure to its aspect-ratio child and lets the
     caption spill under the next card; a plain block sized by the column, with
     the tile's height stated, lays out the same in every engine (spine page). */
  .lp-vs-knee .sec-still--pt { display: block; width: 100%; max-width: min(420px,100%); align-self: auto; }
  .lp-vs-knee .sec-still--pt > .sec-still__sticky { position: static; display: block; width: 100%; }
  .lp-vs-knee .sec-still--pt .pt-tile { width: 100%; height: auto; aspect-ratio: 3/4; }
  .lp-vs-knee .sec-still--pt .pt-fig__cap { position: static; margin: 12px 0 0; }
  .lp-vs-knee .surg { grid-template-columns: 1fr; }
  .lp-vs-knee .vial { gap: 20px; }
  /* One column from here down to 620px, where a 4:3 figure the width of the
     card is a whole screen of picture before each list. */
  .lp-vs-knee .vsfig__frame { aspect-ratio: 16/9; }
  .lp-vs-knee .surgfig { max-width: 520px; margin-top: 8px; }
  .lp-vs-knee .kcreds { grid-template-columns: 1fr 1fr; }
  .lp-vs-knee .faq { gap: 28px; }
}
@media (max-width:760px) {
  .lp-vs-knee .hc-bar { left: 0; right: 0; bottom: 0; max-width: none; height: calc(48px + env(safe-area-inset-bottom, 0px)); padding-bottom: env(safe-area-inset-bottom, 0px); border-width: 1px 0 0; border-radius: 0; box-shadow: 0 -6px 24px rgba(11,29,58,.08); transform: translateY(12px); }
  .lp-vs-knee .hc-bar:is(.is-on, :focus-within) { transform: none; }
  :root { scroll-padding-bottom: 64px; }
  .lp-vs-knee .hc-bar__track { gap: 22px; padding: 0 20px; -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 16px, #000 calc(100% - 28px), transparent); mask-image: linear-gradient(90deg, transparent 0, #000 16px, #000 calc(100% - 28px), transparent); }
}
@media (max-width:620px) {
  .lp-vs-knee .kcreds { grid-template-columns: 1fr; gap: 16px; }
  /* .vial__col padding drops to 24px here, so the full-bleed figure follows. */
  .lp-vs-knee .vsfig { margin: -24px -24px 20px; }
  .lp-vs-knee .vsfig__frame { aspect-ratio: 4/3; }
  .lp-vs-knee .faq__a { padding-right: 0; }
  .lp-vs-knee .lede { font-size: 1.0625rem; }
}

/* ---------- reduced motion ---------- */
/* Nothing scales, nothing lifts, and the dwell is off, so a phone holds the
   render and the film is left to its alt text. A hover still swaps render
   for film; it just does not move. The hover selectors are named because
   they outrank the plain ones. */
@media (prefers-reduced-motion: reduce) {
  .lp-vs-knee :is(.vsfig__img, .surgfig__img),
  .lp-vs-knee :is(.vial__col, .surgfig):hover :is(.vsfig__img, .surgfig__img),
  .lp-vs-knee :is(.vial__col, .surgfig):hover :is(.vsfig__cap, .surgfig__cap) b { transform: none; }
  .lp-vs-knee :is(.vsfig__img--b, .vsfig__cap--b, .vsfig__cap--a, .surgfig__img--b, .surgfig__cap--b, .surgfig__cap--a) { animation: none; }
  .lp-vs-knee .hero__img video { animation: none; }
  .lp-vs-knee .hero__lattice { animation: none; }
  .js-anim .lp-vs-knee :is(.vial__col li, .kcreds li)::before { transform: none; transition: none; }
  .lp-vs-knee .hc-bar, .lp-vs-knee .hc-bar__track a::after { transition: none !important; }
  .lp-vs-knee main .btn:active, .lp-vs-knee .pt-tile:active, .lp-vs-knee .pt-tile:hover { transform: none; }
}

/* ---------- print ---------- */
/* The finished page, dark on white: every reveal in place, every answer
   open (the script opens the folds and puts them back), no bar, and no
   films: neither has loaded a frame to print unless it was played. */
@media print {
  .lp-vs-knee .hc-bar, .lp-vs-knee .pt-modal, .lp-vs-knee :is(.hero__vid, .hero__scrim, .hero__lattice, .hero__grain, .ctaband__pattern, .faq__ic, .kvid, .sec-still--pt) { display: none !important; }
  /* The site header is fixed, and a fixed box prints on every sheet. */
  body.lp-vs-knee > .nav { position: static; }
  .lp-vs-knee .sec-split { display: block; }
  .lp-vs-knee main *, .lp-vs-knee main *::before, .lp-vs-knee main *::after { animation: none !important; transition: none !important; }
  .lp-vs-knee [data-r], .lp-vs-knee :is(.vial__col li, .kcreds li)::before { opacity: 1 !important; transform: none !important; }
  .lp-vs-knee .hero { min-height: 0; padding: 0 0 24px; background: #fff; color: var(--ink); }
  .lp-vs-knee main .hero__h1, .lp-vs-knee .hero__sub { color: var(--ink); }
  .lp-vs-knee .hero__h1 em { color: var(--accent); }
  .lp-vs-knee :is(.sec, .band, .ctaband) { padding: 28px 0; background: #fff; color: var(--ink); }
  .lp-vs-knee .ctaband :is(h2, p, .ctaband__disclaimer) { color: var(--ink); }
  .lp-vs-knee .ctaband h2 em { color: var(--accent); }
  .lp-vs-knee .faq__head { position: static; }
  .lp-vs-knee :is(.vial__col li, .cell, .surgfig, .faq__list details, .kcreds li) { break-inside: avoid; }
  .lp-vs-knee :is(h2, h3, .vial__tag) { break-after: avoid; }
}
