/* Interactive product showcase */
.product-showcase-section {
  --product-ink: #15162d;
  --product-muted: #68708a;
  --product-panel: rgba(255, 255, 255, 0.82);
  /* Space held back at the top for the fixed navbar, and a little at the bottom
     for the card to sit clear of the edge. Every pixel here comes straight out
     of the height available to the card, so both are sized to what they
     actually are — a 71px navbar — rather than to a round number. Declared out
     here so the script can read them. */
  --product-pin-nav-offset: 4.75rem;
  --product-pin-bottom-gap: 1.5rem;

  /* How far the heading travels to reach the bar label, how small it has to get
     to match it, and how far along that journey the page is. The first two are
     measured from where the two elements actually are by `product-scroll.js`;
     the last is published by it on every scroll frame, and is what everything
     below is interpolated from. The defaults are what the section looks like
     before it has been measured, so nothing moves unless the numbers arrive. */
  --morph-drop: 0px;
  --morph-scale: 1;
  --morph-progress: 0;

  /* How much scrolling the whole run of products occupies, published by
     `product-scroll.js` once it has measured the window. The fallback matches
     the script's own default so the section is the right height even before it
     has run. */
  --product-pin-run: 4 * 50svh;
  display: block !important;
  position: relative;
  /* No `overflow: hidden` here. It would make this element a scroll container,
     and the sticky backdrop inside it would then pin to this box rather than
     to the viewport. Nothing inside the section overflows horizontally. */
  padding: 6.5rem 0 7rem !important;
  background:
    radial-gradient(circle at 8% 12%, rgba(28, 25, 23, 0.1), transparent 28rem),
    radial-gradient(circle at 92% 86%, rgba(236, 72, 153, 0.07), transparent 30rem),
    var(--bg-primary, #fdfbf7) !important;
}

/* The section is already visible by default; avoid a full-section transition
   being retriggered as it crosses the viewport. */
#products.product-showcase-section.scroll-animate {
  transition: none !important;
}

.product-showcase-section > .container {
  position: relative;
  z-index: 1;
  max-width: 1200px;
}

.product-showcase-heading {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 2rem;
  margin-bottom: 2.25rem;
}

.product-showcase-heading-copy {
  max-width: 680px;
}



.product-showcase-heading h2 {
  margin: 0 !important;
  color: var(--text-primary, #1c1917) !important;
  font-size: clamp(2.35rem, 5vw, 4.5rem) !important;
  font-weight: 800 !important;
  letter-spacing: -0.055em;
  line-height: 0.98;
}

.product-showcase-heading p {
  max-width: 590px;
  margin: 1rem 0 0;
  color: var(--text-secondary, #44403c);
  font-size: 1rem;
  line-height: 1.7;
}

.product-showcase-live {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  flex: 0 0 auto;
  padding: 0.7rem 0.9rem;
  color: var(--text-secondary, #44403c);
  background: rgba(255, 255, 255, 0.72);
  border: 1px solid var(--border-light, rgba(28, 25, 23, 0.1));
  border-radius: 999px;
  box-shadow: 0 8px 24px rgba(28, 25, 23, 0.05);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
}

.product-showcase-live::before {
  width: 0.5rem;
  height: 0.5rem;
  content: "";
  background: #22c55e;
  border-radius: 50%;
  box-shadow: 0 0 0 0.25rem rgba(34, 197, 94, 0.12);
  animation: product-live-pulse 2.2s ease-in-out infinite;
}

/* --------------------------------------------------------------------------
   Pinned product showcase

   The section is a tall scroll track: `.product-pin__viewport` sticks to the
   screen while the page scrolls through it, and `product-scroll.js` cross-fades
   between the cards so exactly one product shows at a time, then eases to the
   nearest card once scrolling settles. The decorative layers sit in a sticky
   backdrop of their own, and a sticky bar keeps the section name on screen.

   `is-pinned` is added by that script only when the window is big enough to
   hold a card and the visitor has not asked for reduced motion. Without it the
   cards simply stack, which is the no-JavaScript, small-screen and
   reduced-motion path.
   -------------------------------------------------------------------------- */
.product-pin__intro,
.product-pin__viewport,
.product-pin__stage {
  position: relative;
  z-index: 1;
}

.product-pin__viewport,
.product-pin__stage {
  width: 100%;
}

.product-pin__backdrop {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

.product-pin__track {
  display: grid;
  gap: 1.75rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.product-pin__step {
  min-width: 0;
}

/* Only reserves scroll length while the section is pinned. */
.product-pin__spacer {
  display: none;
}

/* The cards and the bar sit deeper than the section, so they need the same
   container width. Without this they fall back to Bootstrap's narrower
   breakpoint width and the cards drift out of line with the heading above
   them, and the layout collapses to a single column. */
.product-pin__stage {
  max-width: 1200px;
  margin-inline: auto;
}

.product-pin__card {
  /* The card's accent is used three ways: as a tint, as the fill under white
     text, and as the fill of small text. Only the last two need it darkened, and
     both are cleared by the same threshold, so one token covers them. */
  --product-accent-ink: color-mix(in srgb, var(--product-accent) 65%, #000);
  display: grid;
  grid-template-columns: minmax(0, 1.06fr) minmax(0, 1fr);
  overflow: hidden;
  overflow-anchor: none;
  background: var(--product-panel);
  border: 1px solid rgba(28, 25, 23, 0.1);
  border-radius: 28px;
  box-shadow: 0 28px 80px rgba(50, 43, 100, 0.12), 0 3px 10px rgba(28, 25, 23, 0.04);
  /* A large blur layer causes scroll-time repaints as the section enters view. */
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

/* The dark panel has no intrinsic height of its own, so it needs one in the
   stacked layout. Inside a full-screen slide it is sized from the viewport. */
.product-pin__card .product-preview-visual {
  min-height: clamp(300px, 34svh, 420px);
}

/* Sticky section header, shown only while the section is pinned. It carries
   the heading that otherwise scrolls away, so the section stays named for the
   whole run, plus the progress through the products. The label is a span, not
   a heading: the real `h2` is above this and stays in the document. */
.product-pin__bar {
  display: none;
  align-items: center;
  gap: 1.25rem;
  margin-bottom: 1.5rem;
}

/* `aria-hidden` because the section's real name is the heading above it, and two
   elements naming the same thing is noise rather than emphasis. */
.product-pin__bar-label {
  flex: 0 0 auto;
  color: var(--product-ink);
  font-size: 1.05rem;
  font-weight: 800;
  letter-spacing: -0.03em;
  white-space: nowrap;
}

.product-pin__bar-track {
  flex: 1 1 auto;
  height: 4px;
  overflow: hidden;
  background: rgba(28, 25, 23, 0.12);
  border-radius: 999px;
}

.product-pin__bar-track i {
  display: block;
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, var(--accent-color, #1c1917), #ec4899);
  border-radius: 999px;
  box-shadow: 0 0 12px rgba(28, 25, 23, 0.45);
  /* Driven by `--pin-step`, the value quantised to a product boundary, rather
  than the continuous `--pin-progress`. Filling from the continuous value
  made the bar crawl between products like liquid: it kept sliding while the
  card sat still, so the two disagreed and the section read as moving on its
  own. Snapped, the bar advances only when the product does. */
  transform: scaleX(var(--pin-step, 0));
  transform-origin: left center;
  /* Short and eased, so a step reads as one movement to the next boundary
  rather than a sweep through every fraction in between. */
  transition: transform 260ms cubic-bezier(0.33, 0, 0.2, 1);
}

.product-pin__bar-nav {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  gap: 0.4rem;
}

.product-pin__bar-btn {
  display: grid;
  width: 2rem;
  height: 2rem;
  place-items: center;
  color: var(--product-ink);
  background: rgba(255, 255, 255, 0.75);
  border: 1px solid rgba(28, 25, 23, 0.12);
  border-radius: 999px;
  cursor: pointer;
  font-size: 0.7rem;
  transition: color 200ms ease, background 200ms ease, border-color 200ms ease, transform 200ms ease;
}

.product-pin__bar-btn:hover:not(:disabled),
.product-pin__bar-btn:focus-visible {
  color: #ffffff;
  background: var(--accent-color, #1c1917);
  border-color: var(--accent-color, #1c1917);
  outline: none;
  transform: translateY(-1px);
}

.product-pin__bar-btn:disabled {
  cursor: not-allowed;
  opacity: 0.35;
}


/* A window this short cannot afford the card's full-size spacing. Everything
   here is trimmed rather than removed, and the script still measures the result
   before committing to the pinned layout, so this only decides how often that
   fallback is needed. */
@media (min-width: 992px) and (max-height: 780px) {
  .product-pin__card .product-preview-copy {
    padding: 1.6rem;
  }

  .product-pin__card .product-preview-copy h3 {
    font-size: clamp(1.6rem, 2.6vw, 2.15rem);
  }

  .product-pin__card .product-preview-copy > p {
    font-size: 0.9rem;
    line-height: 1.6;
  }

  .product-pin__card .product-preview-feature-list {
    gap: 0.5rem;
    margin-top: 1.1rem;
  }

  .product-pin__card .product-preview-actions {
    margin-top: 1.35rem;
  }
}

/* The pinned treatment.

   The gate is width only. A height requirement here is what stopped the whole
   section working on ordinary laptops: a 1366x768 screen has roughly 620px of
   viewport once the browser chrome is subtracted, so a fixed `min-height` cut
   the pin off exactly where most people are looking at it. Whether the cards
   actually fit is measured in `product-scroll.js` instead, which is the only
   thing that can answer it. */
@media (min-width: 992px) {
  .product-showcase-section.is-pinned {
    padding: 5.5rem 0 4rem !important;
  }

  .product-showcase-section.is-pinned .product-pin__backdrop {
    position: sticky;
    top: 0;
    height: 100vh;
    height: 100svh;
    /* Sits on top of the cards without adding a screen of scroll length. */
    margin-bottom: -100vh;
    margin-bottom: -100svh;
  }

  /* The card is centred in the window, so the space above it and the space below
     it are the same. Anything else reads as the card having slid down the screen.

     The cost is that half the window's spare height lands above the card, and the
     heading sits above the viewport in normal flow, so that much space also sits
     between the heading and the card before the section sticks. The two cannot
     both be tightened: the space above the card is the same space as the space
     below it, and moving it out of the gap puts all of it under the card, which
     reads as the card having slid down the screen. Top-aligning was tried and
     reverted for exactly that. */
  .product-showcase-section.is-pinned .product-pin__viewport {
    position: sticky;
    top: 0;
    display: flex;
    align-items: center;
    height: 100vh;
    height: 100svh;
    /* The navbar is fixed at the top, so the card gets whatever is left below
       it. */
    padding-top: var(--product-pin-nav-offset);
    padding-bottom: var(--product-pin-bottom-gap);
  }

  .product-showcase-section.is-pinned .product-pin__stage {
    display: flex;
    flex-direction: column;
    justify-content: center;
  }

  /* The bar rides in the slack the centred card leaves above itself rather than
     holding a strip of the layout open. That slack exists because the card is
     shorter than the window, so putting the label in it costs the card nothing:
     the label cannot move the card when the run begins, and before the run there
     is no longer an empty reserved strip under the heading. */
  .product-showcase-section.is-pinned .product-pin__track {
    position: relative;
  }

  .product-showcase-section.is-pinned .product-pin__bar {
    position: absolute;
    bottom: 100%;
    left: 0;
    right: 0;
    display: flex;
    margin-bottom: 0;
    /* The bar is positioned against the stage's padding box, while the cards sit
       inside its content box. Without this the label and the arrows would hang
       over the edges of the card by the container's gutter. Taken from the same
       variable Bootstrap sizes the container with, so the two cannot drift. */
    padding-inline: calc(var(--bs-gutter-x, 1.5rem) * 0.5);
    /* The bar fades itself in from `--morph-progress` a little further down, where
       the whole handoff lives together. Left at 0 here, this is simply what it is
       before the journey begins. */
    opacity: 0;
    /* Invisible before the run, so it must not be clickable either. */
    pointer-events: none;
  }

  /* The heading travelling into the label, driven entirely by `--morph-progress`.

     No transition, deliberately: the value is rewritten on every scroll frame, so
     anything that eased it would put the heading permanently behind the scroll it
     is supposed to be tracking. The script runs the journey over exactly
     `--morph-drop` of scrolling, so the page carries the heading up by as much as
     this pushes it down — the two cancel, the heading appears to hold its place
     on the screen, and the gap under it is spent on the journey rather than sat
     in front of it.

     Scaling from its top left keeps the two left edges lined up, which is what
     makes the smaller text arrive exactly where the label sits rather than
     merely near it. */
  .product-pin__intro h2 {
    transform-origin: left top;
    transform: translateY(calc(var(--morph-progress) * var(--morph-drop)))
      scale(calc(1 - (1 - var(--morph-scale)) * var(--morph-progress)));
  }

  /* The handoff, placed by the scroll rather than by a timer. The heading holds
     its full weight for the first half of the travel, so it is never two
     headings at once, and the label only arrives underneath it as the heading
     goes. Both are ramps over the one number, so they cannot drift out of step
     with each other however the window is resized. */
  .product-showcase-section.is-pinned .product-pin__intro {
    opacity: calc(1 - clamp(0, (var(--morph-progress) - 0.5) * 2, 1));
  }

  /* The label appears as the heading is still travelling, which is what makes
     the two read as one moving into the other. */
  .product-showcase-section.is-pinned .product-pin__bar {
    opacity: clamp(0, (var(--morph-progress) - 0.5) * 2.2, 1);
  }

  /* The bar is clickable from the moment it is properly visible, so the arrows
     are never on screen and dead. The class is the only discrete thing left in
     the morph; it animates nothing, so it cannot flicker. */
  .product-showcase-section.is-pinned.is-morphing .product-pin__bar {
    pointer-events: auto;
  }

  /* A slow drift on the pattern, against the direction of travel, so the
     pinned card sits in front of a background that is quietly moving. The
     layer is over-scanned by the same distance it travels, otherwise the top
     of the backdrop would be left bare. */
  .product-showcase-section.is-pinned .product-pin__backdrop .geometric-pattern-layer {
    top: -48px;
    bottom: -48px;
    transform: translate3d(0, calc(var(--pin-progress, 0) * 40px), 0);
    transition: transform 260ms linear;
  }

  /* Every card shares one grid cell, so the track is exactly as tall as the
     tallest card and moving between steps never changes the page height. */
  .product-showcase-section.is-pinned .product-pin__track {
    grid-template-areas: "card";
    grid-template-columns: minmax(0, 1fr);
    gap: 0;
  }

  /* The outgoing card fades down as the next one fades up, so only one product
     reads at a time. Opacity and nothing else: it applies to the whole subtree
     and cannot be undone by a descendant, and this page does force
     `visibility` back on headings. `visibility` is left alone on purpose —
     transitioning it is what used to strand the hidden cards part-faded behind
     the visible one. */
  .product-showcase-section.is-pinned .product-pin__step {
    grid-area: card;
    display: flex;
    opacity: 0;
    pointer-events: none;
    transition: opacity 380ms ease;
  }

  .product-showcase-section.is-pinned .product-pin__step.is-active {
    opacity: 1;
    pointer-events: auto;
  }

  .product-showcase-section.is-pinned .product-pin__card .product-preview-visual {
    min-height: clamp(300px, 34svh, 420px);
  }

  .product-showcase-section.is-pinned .product-pin__spacer {
    display: block;
    /* Exactly the run the products are spaced across, plus a tail so the last
       card comes to rest before the pin releases. Sized from the measured run
       rather than a screen per product, so there is no stretch of scrolling at
       the end where the card is pinned but nothing is changing. */
    height: calc(var(--product-pin-run) + 24svh);
  }
}

.product-preview-visual {
  --product-accent: var(--accent-color, #1c1917);
  position: relative;
  height: 100%;
  min-height: 0;
  max-height: 100%;
  overflow: hidden;
  isolation: isolate;
  background: #0b1024;
}

.product-preview-visual::before {
  position: absolute;
  inset: 0;
  z-index: -1;
  content: "";
  opacity: 0.28;
  background-image: linear-gradient(rgba(255, 255, 255, 0.08) 1px, transparent 1px), linear-gradient(90deg, rgba(255, 255, 255, 0.08) 1px, transparent 1px);
  background-size: 42px 42px;
  mask-image: linear-gradient(to bottom, black, transparent 85%);
}

.product-preview-visual::after {
  position: absolute;
  inset: 0;
  z-index: 1;
  content: "";
  pointer-events: none;
  background: linear-gradient(180deg, rgba(6, 9, 25, 0.08) 15%, rgba(6, 9, 25, 0.18) 48%, rgba(6, 9, 25, 0.94) 100%), radial-gradient(circle at 78% 18%, color-mix(in srgb, var(--product-accent) 38%, transparent), transparent 32%);
}

.product-preview-image {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 62%;
  opacity: 0.82;
  animation: product-image-in 500ms ease both;
}

.product-preview-badge,
.product-preview-metric,
.product-preview-visual-caption {
  position: absolute;
  z-index: 2;
}

.product-preview-badge {
  top: 1.35rem;
  left: 1.35rem;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0.7rem;
  color: #ffffff;
  background: rgba(10, 14, 36, 0.64);
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 999px;
  box-shadow: 0 10px 25px rgba(0, 0, 0, 0.18);
  backdrop-filter: blur(12px);
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.product-preview-badge::before {
  width: 0.45rem;
  height: 0.45rem;
  content: "";
  background: var(--product-accent);
  border-radius: 50%;
  box-shadow: 0 0 0 0.25rem color-mix(in srgb, var(--product-accent) 22%, transparent);
}

.product-preview-metric {
  right: 1.35rem;
  bottom: 1.35rem;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  color: #ffffff;
  text-align: right;
}

.product-preview-metric strong {
  color: #ffffff;
  font-size: clamp(2rem, 4vw, 3.2rem);
  font-weight: 800;
  letter-spacing: -0.07em;
  line-height: 0.95;
}

.product-preview-metric span {
  margin-top: 0.35rem;
  color: rgba(255, 255, 255, 0.68);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.product-preview-visual-caption {
  bottom: 1.4rem;
  left: 1.35rem;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  color: rgba(255, 255, 255, 0.72);
  font-size: 0.65rem;
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
}

.product-preview-visual-caption strong {
  color: #ffffff;
  font-size: 0.78rem;
  letter-spacing: 0.08em;
}

.product-preview-emr {
  position: absolute;
  inset: 13% 9% 12%;
  z-index: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: rgba(245, 251, 255, 0.94);
  border: 1px solid rgba(255, 255, 255, 0.7);
  border-radius: 22px;
  box-shadow: 0 28px 55px rgba(0, 0, 0, 0.32);
  transform: perspective(900px) rotateY(-8deg) rotateX(3deg) rotateZ(-2deg);
}

.product-preview-emr-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.8rem 1rem;
  color: #123d4a;
  background: #e0f5f5;
  border-bottom: 1px solid rgba(18, 61, 74, 0.1);
  font-size: 0.65rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.product-preview-emr-dots {
  display: flex;
  gap: 0.3rem;
}

.product-preview-emr-dots i {
  width: 0.45rem;
  height: 0.45rem;
  background: #14b8a6;
  border-radius: 50%;
}

.product-preview-emr-body {
  display: grid;
  grid-template-columns: 0.8fr 1.2fr;
  gap: 0.8rem;
  padding: 1rem;
}

.product-preview-emr-stat {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 0.9rem;
  background: #ffffff;
  border: 1px solid rgba(18, 61, 74, 0.08);
  border-radius: 14px;
}

.product-preview-emr-stat strong {
  color: #0f766e;
  font-size: 2rem;
  letter-spacing: -0.06em;
}

.product-preview-emr-stat span {
  /* 4.03:1 as it stood. */
  color: #557075;
  font-size: 0.62rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.product-preview-emr-queue {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
}

.product-preview-emr-queue div {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.65rem 0.7rem;
  color: #36535b;
  background: #ffffff;
  border: 1px solid rgba(18, 61, 74, 0.08);
  border-radius: 10px;
  font-size: 0.64rem;
  font-weight: 700;
}

.product-preview-emr-queue b {
  padding: 0.2rem 0.4rem;
  color: #0f766e;
  background: #ccfbf1;
  border-radius: 999px;
  font-size: 0.55rem;
  text-transform: uppercase;
}

.product-preview-copy {
  display: flex;
  flex-direction: column;
  justify-content: center;
  justify-content: safe center;
  height: 100%;
  min-width: 0;
  min-height: 0;
  max-height: 100%;
  overflow: hidden;
  padding: clamp(2rem, 4vw, 3.4rem);
}

.product-preview-eyebrow {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.55rem;
  color: var(--product-muted);
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.13em;
  text-transform: uppercase;
}

/* Replaces the old side-panel icon: a small accent chip in the card eyebrow so
   each product still reads as a distinct system without a selector list. */
.product-preview-icon {
  display: grid;
  flex: 0 0 auto;
  width: 1.6rem;
  height: 1.6rem;
  place-items: center;
  background: color-mix(in srgb, var(--product-accent) 12%, white);
  border-radius: 9px;
  font-size: 0.72rem;
}

.product-preview-eyebrow .product-preview-index {
  /* 3.26:1 on the card as an accent, 6.69:1 as an ink. */
  color: var(--product-accent-ink);
}

.product-preview-eyebrow .product-preview-dot {
  width: 0.3rem;
  height: 0.3rem;
  background: var(--product-accent);
  border-radius: 50%;
}

.product-preview-copy h3 {
  margin: 1rem 0 0;
  color: var(--product-ink);
  font-size: clamp(1.8rem, 3vw, 2.75rem);
  font-weight: 800;
  letter-spacing: -0.055em;
  line-height: 1.02;
}

.product-card-title-link {
  color: inherit;
  text-decoration: none;
  transition: opacity 0.2s ease;
}

.product-card-title-link:hover {
  opacity: 0.82;
  text-decoration: none;
}

.product-pin__card--clickable {
  cursor: pointer;
}

.product-preview-visual--link {
  display: block;
  text-decoration: none;
  cursor: pointer;
}

.product-preview-copy > p {
  margin: 1rem 0 0;
  color: var(--product-muted);
  font-size: 0.96rem;
  line-height: 1.7;
}

.product-preview-feature-list {
  display: grid;
  gap: 0.7rem;
  margin: 1.5rem 0 0;
  padding: 0;
  list-style: none;
}

.product-preview-feature-list li {
  display: flex;
  align-items: flex-start;
  gap: 0.65rem;
  color: var(--product-ink);
  font-size: 0.82rem;
  font-weight: 700;
  line-height: 1.4;
}

.product-preview-feature-list i {
  display: grid;
  flex: 0 0 auto;
  width: 1.15rem;
  height: 1.15rem;
  place-items: center;
  color: var(--product-accent);
  background: color-mix(in srgb, var(--product-accent) 12%, white);
  border-radius: 50%;
  font-size: 0.55rem;
}

.product-preview-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 1rem;
  margin-top: 2rem;
}

.product-preview-button,
.product-preview-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.65rem;
  min-height: 2.9rem;
  padding: 0.75rem 1rem;
  border-radius: 11px;
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  transition: transform 200ms ease, box-shadow 200ms ease, background 200ms ease;
}

.product-preview-button {
  /* This is the one place a card puts white text straight onto its accent, and
     three of the five accents were too light to carry it: teal 3.26:1, pink
     3.53:1 and amber only 2.15:1, all short of the 4.5:1 minimum. The accent is
     mixed towards black for this fill alone, which keeps the hue recognisable and
     lifts the worst case to 4.75:1. The badges, rules and progress line keep the
     vivid value, because none of them carry text.

     Mixed here rather than through a token on the section: `--product-accent` is
     set per card, and a `var()` that cannot be resolved is not a fallback — the
     declaration is dropped at computed-value time, which left the buttons with no
     background at all. */
  color: #ffffff;
  background: var(--product-accent-ink);
  border: 1px solid var(--product-accent-ink);
  box-shadow: 0 10px 22px color-mix(in srgb, var(--product-accent) 25%, transparent);
  cursor: pointer;
}

.product-preview-button:hover,
.product-preview-button:focus-visible {
  color: #ffffff;
  transform: translateY(-2px);
  box-shadow: 0 14px 28px color-mix(in srgb, var(--product-accent) 34%, transparent);
}

.product-preview-link {
  color: var(--product-ink);
  border: 1px solid rgba(28, 25, 23, 0.14);
}

.product-preview-link:hover,
.product-preview-link:focus-visible {
  color: var(--product-accent);
  border-color: color-mix(in srgb, var(--product-accent) 45%, white);
  transform: translateY(-2px);
}

@keyframes product-live-pulse {
  0%, 100% { box-shadow: 0 0 0 0.25rem rgba(34, 197, 94, 0.12); }
  50% { box-shadow: 0 0 0 0.45rem rgba(34, 197, 94, 0.03); }
}

@keyframes product-image-in {
  from { opacity: 0; transform: scale(1.04); }
  to { opacity: 0.82; transform: scale(1); }
}

@media (max-width: 1199px) {
  .product-pin__card {
    grid-template-columns: minmax(0, 1fr) minmax(300px, 0.9fr);
  }

  .product-pin__card .product-preview-copy {
    padding: clamp(1.75rem, 3vw, 2.4rem);
  }
}

@media (max-width: 991px) {
  .product-showcase-section {
    padding: 5rem 0 5.5rem !important;
  }

  .product-showcase-heading {
    align-items: flex-start;
    flex-direction: column;
    gap: 1rem;
  }

  .product-showcase-live {
    align-self: flex-start;
  }

  /* Stacked card. The copy panel grows with its content instead of being
     locked to a fixed height, so the demo and contact buttons are never cut
     off for the products with the longest descriptions. */
  .product-pin__card {
    grid-template-columns: minmax(0, 1fr);
  }

  .product-pin__card .product-preview-visual {
    height: 380px;
    min-height: 380px;
    max-height: 380px;
  }

  .product-pin__card .product-preview-copy {
    height: auto;
    min-height: 0;
    max-height: none;
    overflow: visible;
    justify-content: flex-start;
  }
}

@media (max-width: 576px) {
  .product-showcase-section {
    padding: 4rem 0 4.5rem !important;
  }

  .product-showcase-heading h2 {
    font-size: 2.65rem !important;
  }

  .product-showcase-heading p {
    font-size: 0.9rem;
  }

  .product-pin__track {
    gap: 1.25rem;
  }

  .product-pin__card {
    border-radius: 20px;
  }

  .product-pin__card .product-preview-visual {
    height: 300px;
    min-height: 300px;
    max-height: 300px;
  }

  /* Give the inset EMR mock enough room that its queue rows are not cut off. */
  .product-preview-emr {
    inset: 8% 7% 8%;
  }

  .product-preview-badge {
    top: 0.85rem;
    left: 0.85rem;
  }

  .product-preview-metric {
    right: 0.85rem;
    bottom: 0.85rem;
  }

  .product-preview-visual-caption {
    bottom: 0.9rem;
    left: 0.85rem;
  }

  .product-pin__card .product-preview-copy {
    padding: 1.25rem;
  }

  .product-preview-copy h3 {
    font-size: 1.65rem;
  }

  .product-preview-actions {
    align-items: stretch;
    flex-direction: column;
  }

  .product-preview-button,
  .product-preview-link {
    width: 100%;
  }
}

@media (prefers-reduced-motion: reduce) {
  .product-pin__step,
  .product-pin__bar-track i,
  .product-showcase-section.is-pinned .product-pin__backdrop .geometric-pattern-layer,
  .product-pin__bar-btn,
  .product-preview-button,
  .product-preview-link,
  .product-showcase-live::before,
  .product-preview-image {
    animation: none;
    transition: none;
  }

  /* The handoff from the big heading to the bar label is a swap, not a travel. */
  .product-showcase-section.is-pinned .product-pin__bar,
  .product-showcase-section.is-pinned .product-pin__intro,
  .product-pin__intro h2 {
    transition: none;
  }
}

/* Compact, responsive product demo dialog */
.product-demo-modal {
  position: fixed;
  inset: 0;
  z-index: 12000;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
}

.product-demo-modal.open {
  display: flex;
}

.product-demo-modal__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(15, 12, 35, 0.64);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}

.product-demo-modal__dialog {
  position: relative;
  z-index: 1;
  width: min(720px, 100%);
  max-height: min(760px, calc(100vh - 3rem));
  overflow: auto;
  background: #ffffff;
  border: 1px solid rgba(28, 25, 23, 0.12);
  border-radius: 24px;
  box-shadow: 0 30px 90px rgba(28, 25, 23, 0.28);
  animation: product-modal-in 220ms ease both;
}

.product-demo-modal__header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.5rem 1.75rem;
  border-bottom: 1px solid rgba(28, 25, 23, 0.08);
}

.product-demo-modal__category {
  display: block;
  color: var(--accent-color, #1c1917);
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.product-demo-modal__header h2 {
  margin: 0.4rem 0 0;
  color: var(--text-primary, #1c1917);
  font-size: clamp(1.55rem, 3vw, 2.2rem);
  font-weight: 800;
  letter-spacing: -0.045em;
  line-height: 1.05;
}

.product-demo-modal__close {
  display: grid;
  flex: 0 0 auto;
  width: 2.35rem;
  height: 2.35rem;
  place-items: center;
  color: var(--text-secondary, #44403c);
  background: var(--bg-secondary, #f7f4eb);
  border: 1px solid rgba(28, 25, 23, 0.1);
  border-radius: 50%;
  cursor: pointer;
  transition: color 180ms ease, background 180ms ease, transform 180ms ease;
}

.product-demo-modal__close:hover,
.product-demo-modal__close:focus-visible {
  color: #ffffff;
  background: var(--accent-color, #1c1917);
  outline: none;
  transform: rotate(8deg);
}

.product-demo-modal__body {
  padding: 2rem 1.75rem;
}

.product-workflow-demo {
  margin: -0.25rem 0 1.5rem;
}

.product-workflow-demo .modal-overlay {
  padding: 0;
}

.product-workflow-demo .modal {
  max-height: 430px !important;
  border-radius: 16px;
  box-shadow: none;
}

.product-workflow-demo .modal-content {
  min-height: 320px;
}

.product-terminal-demo,
.product-demo-modal__body .cmd-window {
  --cmd-text: #faf8f3;
  --cmd-yellow: #fde68a;
  --cmd-cyan: #a8a29e;
  --cmd-green: #86efac;
  color: #faf8f3;
}

.product-terminal-demo {
  margin: -0.25rem 0 1.5rem;
}

.product-terminal-demo .cmd-window {
  height: 420px !important;
  min-height: 360px;
  max-height: 420px;
  border-radius: 16px;
  box-shadow: none;
}

.product-terminal-demo .console-content,
.product-demo-modal__body .console-content {
  min-height: 300px;
  color: #faf8f3;
  background: #0b0b0b;
}

.product-terminal-demo .log-line,
.product-demo-modal__body .log-line,
.product-terminal-demo .log-message,
.product-demo-modal__body .log-message {
  color: #faf8f3;
}

.product-terminal-demo .log-timestamp,
.product-demo-modal__body .log-timestamp,
.product-terminal-demo .highlight-timestamp,
.product-demo-modal__body .highlight-timestamp {
  color: #c4bdd4;
}

.terminal-live-status {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  color: #22c55e;
  font-family: 'Montserrat', sans-serif;
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
}

.terminal-live-status i {
  font-size: 0.45rem;
}

.terminal-cursor {
  display: inline-block;
  color: #22c55e;
  animation: terminal-cursor-blink 900ms steps(2, start) infinite;
}

.product-terminal-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.65rem 0.85rem;
  color: rgba(255, 255, 255, 0.58);
  background: #111827;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  font-size: 0.68rem;
  font-weight: 700;
}

.product-terminal-footer span {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}

.product-terminal-footer button {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.4rem 0.6rem;
  color: #a8a29e;
  background: transparent;
  border: 1px solid rgba(168, 162, 158, 0.35);
  border-radius: 7px;
  cursor: pointer;
  font: inherit;
  font-size: 0.65rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.product-terminal-footer button:hover:not(:disabled),
.product-terminal-footer button:focus-visible:not(:disabled) {
  color: #ffffff;
  background: rgba(28, 25, 23, 0.25);
  outline: none;
}

.product-terminal-footer button:disabled {
  cursor: not-allowed;
  opacity: 0.45;
}

@keyframes terminal-cursor-blink {
  50% { opacity: 0; }
}

.product-demo-modal__body.product-demo-partial-body {
  padding: 0;
  background: #f8fafc;
}

.product-demo-modal__body h3 {
  margin: 0.65rem 0 0;
  color: var(--text-primary, #1c1917);
  font-size: clamp(1.35rem, 2.5vw, 1.9rem);
  font-weight: 800;
  letter-spacing: -0.04em;
}

.product-demo-modal__body p {
  max-width: 580px;
  margin: 0.85rem 0 0;
  color: var(--text-secondary, #44403c);
  font-size: 0.98rem;
  line-height: 1.7;
}

.product-demo-modal__stat {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  margin-top: 1.75rem;
  padding: 1rem 1.1rem;
  background: rgba(28, 25, 23, 0.08);
  border: 1px solid rgba(28, 25, 23, 0.16);
  border-radius: 14px;
}

.product-demo-modal__stat strong {
  color: var(--accent-color, #1c1917);
  font-size: 2rem;
  font-weight: 800;
  letter-spacing: -0.06em;
  line-height: 1;
}

.product-demo-modal__stat span {
  margin-top: 0.35rem;
  color: var(--text-muted, #78716c);
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.product-demo-modal__footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.1rem 1.75rem 1.35rem;
  border-top: 1px solid rgba(28, 25, 23, 0.08);
}

.product-demo-modal__cta,
.product-demo-modal__secondary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  min-height: 2.75rem;
  padding: 0.7rem 1rem;
  border-radius: 10px;
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.product-demo-modal__cta {
  color: #ffffff;
  background: var(--accent-color, #1c1917);
}

.product-demo-modal__cta:hover,
.product-demo-modal__cta:focus-visible {
  color: #ffffff;
  background: var(--accent-dark, #0c0a09);
  outline: none;
}

.product-demo-modal__secondary {
  color: var(--text-secondary, #44403c);
  background: transparent;
  border: 1px solid rgba(28, 25, 23, 0.14);
  cursor: pointer;
}

.product-demo-modal__secondary:hover,
.product-demo-modal__secondary:focus-visible {
  color: var(--accent-color, #1c1917);
  border-color: rgba(28, 25, 23, 0.4);
  outline: none;
}

@keyframes product-modal-in {
  from { opacity: 0; transform: translateY(12px) scale(0.98); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

@media (max-width: 576px) {
  .product-demo-modal {
    align-items: flex-end;
    padding: 0.75rem;
  }

  .product-demo-modal__dialog {
    max-height: calc(100vh - 1.5rem);
    border-radius: 20px;
  }

  .product-demo-modal__header,
  .product-demo-modal__body {
    padding-inline: 1.15rem;
  }

  .product-demo-modal__footer {
    align-items: stretch;
    flex-direction: column;
    padding-inline: 1.15rem;
  }

  .product-demo-modal__cta,
  .product-demo-modal__secondary {
    width: 100%;
  }
}
