/*
  ARCLO — PRODUCT DEMO ANIMATIONS
  Self-running phone-mockup animations used inside service visual
  containers (currently: the "5-Star Review System" homepage card).

  Kept in its own file, separate from the core design system
  (tokens/base/layout/components/sections), because it is a distinct,
  optional widget rather than a structural site component.

  ---------------------------------------------------------------
  REUSABLE PIECES vs. REVIEW-SPECIFIC PIECES
  ---------------------------------------------------------------
  .phone-shell / .phone-shell__notch / .phone-shell__screen
    Generic phone mockup chrome. Reuse this for future service demos
    (missed-call text back, appointment booking, lead follow-up,
    business phone) by building a new set of .xxx-demo__state screens
    inside the same .phone-shell__screen.

  .review-demo*
    Specific to the 5-Star Review System demo. Do not reuse these
    class names for a different service's screen content; give the
    next demo its own prefix (e.g. .missed-call-demo__state) inside
    the shared .phone-shell.
*/

/* ---------------------------------------------------------------
   Phone shell (reusable)
--------------------------------------------------------------- */

.phone-shell {
  /* Sized from height, not width: the surrounding .media-frame is a
     wide 4:3 box, so height is always the limiting dimension for a
     tall phone shape. Sizing from width instead made the phone
     overflow vertically and get clipped by the frame. */
  position: relative;
  height: min(300px, 82%);
  aspect-ratio: 9 / 19.5;
  background: var(--navy-950);
  border: 2px solid rgba(8, 31, 59, 0.4);
  border-radius: 32px;
  box-shadow: var(--shadow-lg);
  padding: 8px;
  margin-inline: auto;
}

.phone-shell__notch {
  position: absolute;
  top: 16px;
  left: 50%;
  transform: translateX(-50%);
  width: 32%;
  height: 16px;
  background: var(--navy-950);
  border-radius: 999px;
  z-index: 2;
}

.phone-shell__screen {
  position: relative;
  width: 100%;
  height: 100%;
  background: var(--canvas);
  border-radius: 24px;
  overflow: hidden;
}

/* Larger, unboxed placement (e.g. the homepage "5-Star Review
   System" card): the phone sits directly on the section background
   with no surrounding .media-frame, so it's sized from the viewport
   instead of a percentage of a parent that no longer has a fixed
   height. */
.phone-shell--lg {
  height: clamp(320px, 27vw, 460px);
}

/* ---------------------------------------------------------------
   Review demo — outer wrapper
   No .media-frame wrapper here on purpose: this is the larger,
   unboxed placement described above.
--------------------------------------------------------------- */

.review-demo {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  padding-block: var(--space-6);
}

/* ---------------------------------------------------------------
   Review demo — animated states
   Each .review-demo__state is absolutely stacked inside the phone
   screen. Only one is visible (.is-active) at a time. JS toggles
   .is-active on the four top-level states; everything else below
   (bubbles, stars, touch taps, checkmarks) is driven by plain CSS
   transition-delay / animation-delay relative to that same class,
   so there is exactly one moving part in JS: which state is active.
--------------------------------------------------------------- */

.review-demo__states {
  position: relative;
  width: 100%;
  height: 100%;
}

.review-demo__state {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 6px;
  padding: 16px 12px;
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 450ms ease, transform 450ms ease;
  pointer-events: none;
}

.review-demo__state.is-active {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

.review-demo__state.is-active.is-leaving {
  opacity: 0;
  transform: translateY(-6px);
}

/* Shared text styles inside the phone screen */

.review-demo__eyebrow {
  font-family: var(--font-body);
  font-size: 8px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-ink-muted);
}

.review-demo__headline {
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 600;
  line-height: 1.25;
  color: var(--color-ink);
  max-width: 22ch;
}

.review-demo__note {
  font-family: var(--font-body);
  font-size: 9px;
  color: var(--color-ink-muted);
}

.review-demo__business {
  font-family: var(--font-body);
  font-size: 9px;
  font-weight: 600;
  color: var(--color-ink-soft);
}

/* ---------------------------------------------------------------
   STATE 1 — Job complete
--------------------------------------------------------------- */

.review-demo__check {
  display: inline-flex;
  width: 26px;
  height: 26px;
  color: var(--navy-900);
  margin-block: 2px;
}

.review-demo__check--lg {
  width: 32px;
  height: 32px;
}

.review-demo__check svg {
  width: 100%;
  height: 100%;
}

.review-demo__check circle {
  stroke: var(--color-border-strong);
}

.review-demo__check path {
  stroke: currentColor;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  transition: stroke-dashoffset 500ms ease;
  transition-delay: 250ms;
}

.review-demo__state--job.is-active .review-demo__check path,
.review-demo__state--confirmation.is-active .review-demo__check path {
  stroke-dashoffset: 0;
}

.review-demo__state--job.is-active .review-demo__note {
  transition-delay: 350ms;
}

/* ---------------------------------------------------------------
   STATE 2 — Review request text (SMS thread)
--------------------------------------------------------------- */

.review-demo__chat-header {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  /* Extra top padding clears the phone-shell notch, which overlaps
     the first ~18px of the screen area. */
  padding: 22px 0 8px;
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 600;
  color: var(--color-ink);
  border-bottom: 1px solid var(--color-border);
  background: var(--canvas);
}

.review-demo__chat-body {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  width: 100%;
  margin-top: 14px;
}

.review-demo__bubble {
  position: relative;
  text-align: left;
  font-family: var(--font-body);
  font-size: 9.5px;
  line-height: 1.4;
  padding: 7px 10px;
  border-radius: 12px;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 400ms ease, transform 400ms ease;
}

.review-demo__bubble--message {
  background: var(--fog-100);
  color: var(--color-ink);
  border-bottom-left-radius: 4px;
  max-width: 92%;
  transition-delay: 150ms;
}

.review-demo__bubble--link {
  background: var(--navy-900);
  color: var(--canvas);
  font-weight: 600;
  border-bottom-left-radius: 4px;
  transition-delay: 750ms;
}

.review-demo__state--sms.is-active .review-demo__bubble {
  opacity: 1;
  transform: translateY(0);
}

/* ---------------------------------------------------------------
   STATE 3 — Review screen
--------------------------------------------------------------- */

.review-demo__prompt {
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 600;
  color: var(--color-ink);
}

.review-demo__stars {
  display: inline-flex;
  gap: 4px;
  margin-block: 4px;
}

.review-demo__star {
  display: inline-flex;
  width: 15px;
  height: 15px;
}

.review-demo__star svg {
  width: 100%;
  height: 100%;
}

.review-demo__star path {
  fill: transparent;
  stroke: var(--color-border-strong);
  stroke-width: 1.4;
}

.review-demo__stars--static .review-demo__star path {
  fill: var(--star-gold);
  stroke: var(--star-gold);
}

/* Each star's own animation-delay comes from an inline custom
   property (--star-delay) set in the HTML, so the stagger lives in
   one obvious place per star rather than five near-duplicate rules. */
@keyframes reviewStarFill {
  0% {
    transform: scale(1);
  }
  45% {
    transform: scale(1.25);
  }
  100% {
    transform: scale(1);
  }
}

.review-demo__state--review.is-active .review-demo__star {
  animation: reviewStarFill 380ms ease;
  animation-delay: var(--star-delay, 0ms);
}

.review-demo__state--review.is-active .review-demo__star path {
  fill: var(--star-gold);
  stroke: var(--star-gold);
  transition: fill 250ms ease, stroke 250ms ease;
  transition-delay: var(--star-delay, 0ms);
}

.review-demo__feedback {
  font-family: var(--font-body);
  font-style: italic;
  font-size: 9.5px;
  color: var(--color-ink-soft);
  max-width: 26ch;
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 400ms ease, transform 400ms ease;
  transition-delay: 1900ms;
}

.review-demo__state--review.is-active .review-demo__feedback {
  opacity: 1;
  transform: translateY(0);
}

.review-demo__submit {
  font-family: var(--font-body);
  font-size: 9.5px;
  font-weight: 600;
  color: var(--canvas);
  background: var(--navy-900);
  padding: 6px 16px;
  border-radius: var(--radius-md);
  margin-top: 4px;
  position: relative;
}

/* ---------------------------------------------------------------
   Touch indicator (used inside states 2 and 3)
   A quiet translucent circle, not a desktop cursor: fades in,
   scales down as if pressed, fades out.
--------------------------------------------------------------- */

.review-demo__touch {
  position: absolute;
  top: 50%;
  right: 6px;
  width: 26px;
  height: 26px;
  margin-top: -13px;
  border-radius: 50%;
  background: rgba(8, 31, 59, 0.16);
  opacity: 0;
  pointer-events: none;
}

@keyframes reviewTouchTap {
  0% {
    opacity: 0;
    transform: scale(1.3);
  }
  35% {
    opacity: 1;
    transform: scale(1);
  }
  70% {
    opacity: 1;
    transform: scale(0.78);
  }
  100% {
    opacity: 0;
    transform: scale(0.78);
  }
}

.review-demo__state--sms.is-active [data-touch="link"] {
  animation: reviewTouchTap 550ms ease;
  animation-delay: 1700ms;
}

.review-demo__state--review.is-active [data-touch="submit"] {
  animation: reviewTouchTap 550ms ease;
  animation-delay: 2600ms;
}

/* ---------------------------------------------------------------
   STATE 4 — Confirmation
--------------------------------------------------------------- */

.review-demo__state--confirmation .review-demo__stars {
  transition-delay: 250ms;
}

/* ---------------------------------------------------------------
   Reduced motion: static end state, no timers, no animation.
   Markup for this lives alongside .review-demo__states; JS never
   starts its timers when this media query matches.
--------------------------------------------------------------- */

.review-demo__static {
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  height: 100%;
  text-align: center;
  padding: 16px 12px;
}

@media (prefers-reduced-motion: reduce) {
  .review-demo__states {
    display: none;
  }

  .review-demo__static {
    display: flex;
  }
}

/* ---------------------------------------------------------------
   Small-width safety: at narrow mobile widths the service-visual
   container itself is narrower (still 4:3), so the phone derived
   from it is small enough that the SMS message bubble text was
   wrapping to more lines than the screen has height for and
   overflowing the phone. Two changes fix it together: let the phone
   claim more of the container height (there's no sibling text
   column competing for space once the layout stacks), and tighten
   bubble type/spacing so the message fits in fewer, still-legible
   lines.
--------------------------------------------------------------- */

@media (max-width: 420px) {
  /* Excludes .phone-shell--lg on purpose: that modifier's own
     unconditional clamp() (above) already resolves to a sensible,
     definite 320px floor at every mobile width, and this rule and
     that one have equal specificity, so without :not() here this
     rule would win by source order and clobber it. That's exactly
     what was happening: with height stuck at an unresolvable
     percentage (this rule's 92%, against an unboxed parent with no
     definite height of its own), the browser fell back to deriving
     height from width via aspect-ratio instead — ballooning to
     700px+ tall for the demos that are plain block children (missed-
     call, booking, business phone) and collapsing to ~40px tall for
     the one that's a flex child (5-Star Review), instead of the
     intended, consistent phone size all four should share. */
  .phone-shell:not(.phone-shell--lg) {
    height: min(268px, 92%);
  }

  .review-demo__bubble {
    font-size: 8.5px;
    line-height: 1.35;
    padding: 6px 8px;
  }

  .review-demo__chat-body {
    gap: 6px;
  }

  .review-demo__chat-header {
    padding: 20px 0 6px;
    font-size: 9px;
  }
}

/* =================================================================
   SHARED PRODUCT-DEMO PRIMITIVES
   Used by the five demos below (Functional Website, Missed-Call Text
   Back, Appointment Booking, Business Phone, Automated Lead
   Follow-Up). Deliberately a parallel ".demo__*" vocabulary rather
   than a rename of ".review-demo__*": the Review System animation
   above is the working reference implementation and is left
   completely untouched (markup, classes, and js/review-demo.js) to
   avoid any risk of regressing it. These primitives copy its type
   scale, spacing, and motion values so all six demos read as one
   family. The actual phone chrome (.phone-shell etc. above) IS
   shared directly, no parallel copy needed.

   Controller: js/product-demos.js drives all five via a single
   createDemoController() — one IntersectionObserver + timer-bag
   implementation, not five copies.
================================================================== */

.demo__states {
  position: relative;
  width: 100%;
  height: 100%;
}

.demo__state {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 6px;
  padding: 16px 12px;
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 450ms ease, transform 450ms ease;
  pointer-events: none;
}

.demo__state.is-active {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

.demo__state.is-active.is-leaving {
  opacity: 0;
  transform: translateY(-6px);
}

.demo__eyebrow {
  font-family: var(--font-body);
  font-size: 8.5px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-ink-muted);
}

.demo__headline {
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 600;
  line-height: 1.25;
  color: var(--color-ink);
  max-width: 24ch;
}

.demo__note {
  font-family: var(--font-body);
  font-size: 9.5px;
  color: var(--color-ink-muted);
}

.demo__business {
  font-family: var(--font-body);
  font-size: 9.5px;
  font-weight: 600;
  color: var(--color-ink-soft);
}

/* Checkmark — identical drawing technique to .review-demo__check
   (stroke-dasharray/offset), generic name for reuse across demos. */
.demo__check {
  display: inline-flex;
  width: 28px;
  height: 28px;
  color: var(--navy-900);
  margin-block: 2px;
}

.demo__check--lg {
  width: 34px;
  height: 34px;
}

.demo__check--success {
  color: var(--color-success);
}

.demo__check svg {
  width: 100%;
  height: 100%;
}

.demo__check circle {
  stroke: var(--color-border-strong);
}

.demo__check--success circle {
  stroke: rgba(47, 107, 79, 0.28);
}

.demo__check path {
  stroke: currentColor;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  transition: stroke-dashoffset 500ms ease;
  transition-delay: 250ms;
}

.demo__state.is-active .demo__check path,
.demo__static .demo__check path {
  stroke-dashoffset: 0;
}

/* Touch indicator (phone taps) — same quiet translucent-circle
   language as .review-demo__touch. Cursor (browser clicks) is a
   smaller solid dot so the two read as related but distinct. */
@keyframes demoTap {
  0% {
    opacity: 0;
    transform: scale(1.3);
  }
  35% {
    opacity: 1;
    transform: scale(1);
  }
  70% {
    opacity: 1;
    transform: scale(0.78);
  }
  100% {
    opacity: 0;
    transform: scale(0.78);
  }
}

/* Sizes itself to whatever position:relative element it sits inside
   via inset, so the same markup works over a calendar cell, a time
   pill, or a tab label without per-instance width/height math. */
.demo__touch {
  position: absolute;
  inset: -6px;
  border-radius: 50%;
  background: rgba(8, 31, 59, 0.16);
  opacity: 0;
  pointer-events: none;
}

.demo__cursor {
  position: absolute;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--navy-900);
  box-shadow: 0 0 0 4px rgba(8, 31, 59, 0.12);
  opacity: 0;
  pointer-events: none;
}

/* Generic trigger: any [data-touch]/[data-cursor] plays the tap the
   moment its state becomes active. Each instance sets its own
   `animation-delay` inline (mirrors the Review demo's per-star
   `--star-delay` technique) so timing lives next to the markup it
   belongs to instead of in a per-demo stylesheet rule. */
.demo__state.is-active [data-touch],
.demo__state.is-active [data-cursor] {
  animation: demoTap 550ms ease;
  animation-fill-mode: both;
}

/* Generic delayed-opacity hook for a small status line inside an
   otherwise-already-visible state (e.g. "Conversation started"
   appearing a moment after the bubbles it summarizes). Delay set
   inline per instance. */
.demo__state.is-active [data-fade] {
  opacity: 1;
}

/* Subtle incoming-call ring pulse — restrained scale/opacity only,
   same technique as the Review demo's star-fill keyframe. */
@keyframes demoRingPulse {
  0%, 100% {
    transform: scale(1);
    opacity: 0.5;
  }
  50% {
    transform: scale(1.12);
    opacity: 0.9;
  }
}

.demo__ring {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: 1.4px solid var(--color-border-strong);
  color: var(--color-ink-soft);
  margin-block: 2px;
}

.demo__ring::before {
  content: "";
  position: absolute;
  inset: -6px;
  border-radius: 50%;
  border: 1px solid var(--color-border);
  animation: demoRingPulse 1600ms ease-in-out infinite;
}

.demo__ring svg {
  width: 17px;
  height: 17px;
}

/* Generic pill button (CTA inside a demo screen) */
.demo__button {
  font-family: var(--font-body);
  font-size: 10.5px;
  font-weight: 600;
  color: var(--canvas);
  background: var(--navy-900);
  padding: 7px 18px;
  border-radius: var(--radius-md);
  margin-top: 4px;
  position: relative;
}

/* Notification / reminder card */
.demo__notification {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  text-align: left;
  width: 88%;
  padding: 8px 10px;
  background: var(--fog-100);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  opacity: 0;
  transform: translateY(-8px);
  transition: opacity 400ms ease, transform 400ms ease;
}

.demo__state.is-active .demo__notification {
  opacity: 1;
  transform: translateY(0);
}

.demo__notification__title {
  font-family: var(--font-body);
  font-size: 9.5px;
  font-weight: 600;
  color: var(--color-ink);
}

.demo__notification__body {
  font-family: var(--font-body);
  font-size: 9px;
  line-height: 1.4;
  color: var(--color-ink-soft);
}

/* ---------------------------------------------------------------
   Chat thread (Missed-Call, Lead Follow-Up)
   Directional bubbles: --out (business, navy, right) vs. --in
   (customer, fog, left) so a two-way conversation is legible at a
   glance without relying on avatars/labels.
--------------------------------------------------------------- */

.demo__chat-header {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  padding: 22px 0 8px;
  font-family: var(--font-body);
  font-size: 10.5px;
  font-weight: 600;
  color: var(--color-ink);
  border-bottom: 1px solid var(--color-border);
  background: var(--canvas);
}

.demo__chat-body {
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 100%;
  margin-top: 14px;
}

.demo__bubble {
  position: relative;
  text-align: left;
  font-family: var(--font-body);
  font-size: 10.5px;
  line-height: 1.4;
  padding: 7px 11px;
  border-radius: 12px;
  max-width: 88%;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 400ms ease, transform 400ms ease;
}

.demo__state.is-active .demo__bubble {
  opacity: 1;
  transform: translateY(0);
}

.demo__bubble--out {
  align-self: flex-end;
  background: var(--navy-900);
  color: var(--canvas);
  border-bottom-right-radius: 4px;
}

.demo__bubble--in {
  align-self: flex-start;
  background: var(--fog-100);
  color: var(--color-ink);
  border-bottom-left-radius: 4px;
}

.demo__bubble-tag {
  align-self: flex-end;
  font-family: var(--font-body);
  font-size: 8px;
  letter-spacing: 0.03em;
  color: var(--color-ink-muted);
  opacity: 0;
  transition: opacity 400ms ease;
}

.demo__state.is-active .demo__bubble-tag {
  opacity: 1;
}

/* ---------------------------------------------------------------
   Calendar UI (Appointment Booking)
--------------------------------------------------------------- */

.demo__calendar {
  width: 100%;
  padding-top: 14px;
}

.demo__calendar-head {
  font-family: var(--font-body);
  font-size: 10.5px;
  font-weight: 600;
  color: var(--color-ink);
  margin-bottom: 7px;
}

.demo__calendar-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 4px;
}

.demo__calendar-cell {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 19px;
  font-family: var(--font-body);
  font-size: 9px;
  color: var(--color-ink-soft);
  border-radius: 4px;
}

.demo__calendar-cell--label {
  color: var(--color-ink-muted);
  font-weight: 600;
  font-size: 8px;
}

.demo__calendar-cell--dim {
  color: var(--color-ink-faint);
}

.demo__calendar-cell--target {
  position: relative;
  background: var(--color-bg-alt);
  transition: background 250ms ease, color 250ms ease;
}

.demo__state.is-active .demo__calendar-cell--target.is-picked {
  background: var(--navy-900);
  color: var(--canvas);
}

/* ---------------------------------------------------------------
   Pill grid (time slots) + tabs (Business Phone)
--------------------------------------------------------------- */

.demo__pill-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  width: 100%;
  margin-top: 6px;
}

.demo__pill {
  position: relative;
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 500;
  color: var(--color-ink-soft);
  background: var(--color-bg-alt);
  padding: 8px 6px;
  border-radius: var(--radius-md);
  transition: background 250ms ease, color 250ms ease;
}

.demo__state.is-active .demo__pill.is-picked {
  background: var(--navy-900);
  color: var(--canvas);
}

.demo__tabs {
  display: flex;
  gap: 20px;
  margin-bottom: 10px;
  width: 100%;
  justify-content: center;
}

.demo__tab {
  position: relative;
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 500;
  color: var(--color-ink-muted);
  padding-bottom: 6px;
  transition: color 200ms ease;
}

.demo__tab.is-picked {
  color: var(--color-ink);
  font-weight: 600;
}

/* A short underline on the active tab makes the Calls/Messages
   switch visibly obvious, not just a color/weight change. */
.demo__tab::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  border-radius: 2px;
  background: var(--navy-900);
  opacity: 0;
  transform: scaleX(0.6);
  transition: opacity 200ms ease, transform 200ms ease;
}

.demo__tab.is-picked::after {
  opacity: 1;
  transform: scaleX(1);
}

/* ---------------------------------------------------------------
   List rows (Business Phone: recent calls / message inbox)
--------------------------------------------------------------- */

.demo__list {
  display: flex;
  flex-direction: column;
  width: 100%;
  gap: 0;
}

.demo__list-row {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  text-align: left;
  gap: 1px;
  padding: 7px 2px;
  border-top: 1px solid var(--color-border);
}

.demo__list-row:first-child {
  border-top: none;
}

.demo__list-row__name {
  font-family: var(--font-body);
  font-size: 10.5px;
  font-weight: 600;
  color: var(--color-ink);
}

.demo__list-row__meta {
  font-family: var(--font-body);
  font-size: 9px;
  color: var(--color-ink-muted);
}

.demo__list-row__preview {
  font-family: var(--font-body);
  font-size: 9px;
  color: var(--color-ink-soft);
  max-width: 28ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---------------------------------------------------------------
   Reduced-motion static wrapper (generic; content differs per demo)
--------------------------------------------------------------- */

.demo__static {
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  height: 100%;
  text-align: center;
  padding: 16px 12px;
}

@media (prefers-reduced-motion: reduce) {
  .demo__states {
    display: none;
  }

  .demo__static {
    display: flex;
  }
}

/* =================================================================
   BROWSER SHELL (reusable)
   Same design language as .phone-shell: navy-tinted border, layered
   shadow, restrained radius. Sized from width (browsers are wide),
   where .phone-shell is sized from height (phones are tall).
================================================================== */

.browser-shell {
  position: relative;
  width: 100%;
  aspect-ratio: 4 / 3;
  background: var(--white);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  margin-inline: auto;
}

.browser-shell--lg {
  /* ~13% larger than the original 440px so the browser carries
     comparable visual weight to the phones' .phone-shell--lg. */
  width: min(500px, 100%);
}

.browser-shell--sm {
  width: min(310px, 100%);
}

.browser-shell__bar {
  display: flex;
  align-items: center;
  gap: 10px;
  height: 22px;
  padding: 0 10px;
  background: var(--fog-100);
  border-bottom: 1px solid var(--color-border);
}

.browser-shell__dots {
  display: flex;
  gap: 4px;
}

.browser-shell__dot {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--color-border-strong);
}

.browser-shell__address {
  flex: 1;
  height: 13px;
  display: flex;
  align-items: center;
  padding: 0 8px;
  background: var(--white);
  border-radius: var(--radius-full);
  font-family: var(--font-body);
  font-size: 7px;
  color: var(--color-ink-muted);
}

.browser-shell__screen {
  position: relative;
  width: 100%;
  height: calc(100% - 22px);
  background: var(--canvas);
  overflow: hidden;
}

/* ---------------------------------------------------------------
   Website hero content (Functional Website demo)
--------------------------------------------------------------- */

.demo__viewport {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 6px;
  padding: 16px 14px;
  transition: transform 900ms ease;
  transition-delay: 300ms;
}

.demo__state.is-active .demo__viewport {
  transform: translateY(-22px);
}

.demo__site-brand {
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--color-ink);
  margin-top: 6px;
}

.demo__site-headline {
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 600;
  line-height: 1.2;
  color: var(--color-ink);
  max-width: 22ch;
  margin-top: 4px;
}

.demo__site-sub {
  font-family: var(--font-body);
  font-size: 10px;
  color: var(--color-ink-soft);
  max-width: 30ch;
}

.demo__site-stars {
  display: inline-flex;
  gap: 2px;
  margin-top: 10px;
}

.demo__site-stars svg {
  width: 11px;
  height: 11px;
}

.demo__site-stars path {
  fill: var(--star-gold);
  stroke: var(--star-gold);
}

.demo__site-trust {
  font-family: var(--font-body);
  font-size: 8px;
  color: var(--color-ink-muted);
}

/* ---------------------------------------------------------------
   Form UI (Functional Website + Lead Follow-Up)
--------------------------------------------------------------- */

.demo__form {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 6px;
  width: 100%;
  max-width: 84%;
}

.demo__field {
  text-align: left;
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 350ms ease, transform 350ms ease;
}

.demo__state.is-active .demo__field {
  opacity: 1;
  transform: translateY(0);
}

.demo__field__label {
  display: block;
  font-family: var(--font-body);
  font-size: 7.5px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-ink-muted);
}

.demo__field__value {
  display: block;
  font-family: var(--font-body);
  font-size: 10px;
  color: var(--color-ink);
  padding-top: 1px;
  border-bottom: 1px solid var(--color-border);
  padding-bottom: 3px;
}

/* ---------------------------------------------------------------
   Paired demo layout (Automated Lead Follow-Up): a smaller browser
   and phone side by side, scaled down so the pair carries about the
   same visual weight as a single standalone demo.
--------------------------------------------------------------- */

.pair-demo {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-6);
  width: 100%;
  padding-block: var(--space-6);
}

.pair-demo .phone-shell {
  /* ~10% larger than before; still a few px above the chat content's
     natural height at this scale, so wrapped message text never sits
     flush against the screen edge. */
  height: clamp(288px, 24vw, 363px);
  flex-shrink: 0;
}

/* The paired phone is narrower than the standalone .phone-shell--lg
   demos, so the same chat copy needs denser type than the base
   .demo__bubble to avoid wrapping past the screen height. */
.pair-demo .demo__chat-header {
  font-size: 8.5px;
  padding: 18px 0 6px;
}

.pair-demo .demo__chat-body {
  margin-top: 10px;
  gap: 5px;
}

.pair-demo .demo__bubble {
  font-size: 7.8px;
  line-height: 1.32;
  padding: 5px 7px;
  max-width: 96%;
}

.pair-demo .demo__bubble-tag {
  font-size: 7px;
}

.pair-demo .demo__note {
  font-size: 8.2px;
}

/* Kept side by side on mobile (not stacked) per the desktop
   composition — both shells scaled down together, plus denser
   type below, so the pair still fits one mobile-width row without
   either shell overflowing the other. */
@media (max-width: 560px) {
  .pair-demo {
    gap: var(--space-3);
    align-items: flex-start;
  }

  .browser-shell--sm {
    width: min(195px, 58%);
    flex-shrink: 0;
  }

  .pair-demo .phone-shell {
    height: clamp(190px, 52vw, 210px);
  }

  .pair-demo .demo__headline {
    font-size: 10px !important;
  }

  .pair-demo .demo__field__label {
    font-size: 7px;
  }

  .pair-demo .demo__field__value {
    font-size: 8.5px;
  }

  .pair-demo .demo__button {
    font-size: 8px !important;
    padding: 5px 10px !important;
  }

  .pair-demo .demo__chat-header {
    font-size: 7.5px;
    padding: 14px 0 4px;
  }

  .pair-demo .demo__bubble {
    font-size: 6.8px;
    line-height: 1.28;
    padding: 4px 6px;
  }

  .pair-demo .demo__bubble-tag {
    font-size: 6.2px;
  }

  .pair-demo .demo__note {
    font-size: 7px;
  }
}

@media (max-width: 420px) {
  .demo__headline {
    font-size: 13px;
  }

  .demo__bubble,
  .demo__list-row__name,
  .demo__list-row__preview {
    font-size: 9px;
  }

  .demo__list-row__meta {
    font-size: 8px;
  }

  .demo__list-row {
    padding-block: 6px;
  }

  .demo__tab {
    font-size: 10px;
  }

  .demo__site-headline {
    font-size: 14px;
  }
}
