/*
  Carwalo motion & depth system
  -----------------------------
  One easing/duration vocabulary for the whole site. Every animated surface
  (WebGL scene, scroll reveals, hovers, counters) reads from these tokens so
  timing feels coherent from page to page.

  JS marks <html> with .js-motion; all "hidden until revealed" states are
  scoped under it so the site stays fully visible without JavaScript.
*/

:root {
  --motion-ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --motion-ease-inout: cubic-bezier(0.65, 0.05, 0.36, 1);
  --motion-ease-spring: cubic-bezier(0.34, 1.4, 0.44, 1);
  --motion-dur-xs: 0.22s;
  --motion-dur-s: 0.45s;
  --motion-dur-m: 0.8s;
  --motion-dur-l: 1.25s;
  --motion-stagger: 90ms;
  --glow-teal: rgba(68, 161, 160, 0.55);
  --glow-teal-soft: rgba(68, 161, 160, 0.22);
  --glass-bg: rgba(17, 17, 17, 0.55);
  --glass-border: rgba(238, 238, 238, 0.08);
}

/* ---------------------------------------------------------------------------
   Scroll reveals
--------------------------------------------------------------------------- */

@media (prefers-reduced-motion: no-preference) {
  html.js-motion [data-reveal] {
    opacity: 0;
    transform: translate3d(0, 30px, 0);
    transition:
      opacity var(--motion-dur-m) var(--motion-ease-out),
      transform var(--motion-dur-m) var(--motion-ease-out);
    transition-delay: var(--reveal-delay, 0s);
  }

  html.js-motion [data-reveal="left"] {
    transform: translate3d(-40px, 0, 0);
  }

  html.js-motion [data-reveal="right"] {
    transform: translate3d(40px, 0, 0);
  }

  html.js-motion [data-reveal="scale"] {
    transform: scale3d(0.92, 0.92, 1);
  }

  html.js-motion [data-reveal="fade"] {
    transform: none;
  }

  html.js-motion [data-reveal].is-inview {
    opacity: 1;
    transform: none;
  }
}

/* ---------------------------------------------------------------------------
   WebGL wash scene (hero + ambient page headers)
--------------------------------------------------------------------------- */

.wash_canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  pointer-events: none;
  opacity: 0;
  transition: opacity 1.4s var(--motion-ease-out);
}

.scene-active .wash_canvas {
  opacity: 1;
}

/* Once the scene renders, simplify the static fallback beneath the canvas. */
.section-hero.scene-active {
  background-image:
    linear-gradient(
      180deg,
      var(--color-neutral--primary-background),
      var(--color-neutral--transparent) 40%
    );
}

.section-hero.scene-active .hero_blur_wrap {
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

.hero_scene_vignette {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(
      120% 90% at 50% 110%,
      rgba(9, 9, 9, 0.85),
      transparent 55%
    ),
    radial-gradient(
      130% 100% at 50% -20%,
      rgba(9, 9, 9, 0.9),
      transparent 60%
    );
}

/* Ambient header scene on subpages */
.page_scene {
  position: absolute;
  inset: 0 0 auto;
  height: min(72vh, 760px);
  overflow: clip;
  pointer-events: none;
  z-index: 0;
  -webkit-mask-image: linear-gradient(180deg, #000 55%, transparent);
  mask-image: linear-gradient(180deg, #000 55%, transparent);
}

/* ---------------------------------------------------------------------------
   Hero
--------------------------------------------------------------------------- */

.hero_enhanced {
  position: relative;
}

.hero_enhanced .hero_container {
  position: relative;
  z-index: 1;
}

.hero_enhanced .hero_heading.heading-h1 {
  font-size: clamp(2.9rem, 1.9rem + 3.4vw, 5.4rem);
  line-height: 1.08;
  letter-spacing: -0.03em;
  text-wrap: balance;
}


/* Kinetic type: words rise out of a clipping line */
.hero_heading .w,
.faq_heading .w {
  display: inline-block;
  overflow: clip;
  vertical-align: bottom;
  padding-bottom: 0.08em;
  margin-bottom: -0.08em;
}

@media (prefers-reduced-motion: no-preference) {
  html.js-motion .hero_heading.is-split .wi,
  html.js-motion .faq_heading.is-split .wi {
    display: inline-block;
    transform: translateY(112%);
    transition: transform 0.9s var(--motion-ease-out);
    transition-delay: calc(var(--w-i, 0) * 65ms + 0.15s);
  }

  html.js-motion .hero_heading.is-split.is-inview .wi,
  html.js-motion .faq_heading.is-split.is-inview .wi {
    transform: translateY(0);
  }
}

.hero_heading .w-accent .wi,
.hero_heading .w-accent,
.faq_heading .w-accent .wi,
.faq_heading .w-accent {
  background-image: linear-gradient(
    115deg,
    #aee2e2 10%,
    #44a1a0 45%,
    #aee2e2 90%
  );
  background-size: 220% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

@media (prefers-reduced-motion: no-preference) {
  .hero_heading .w-accent .wi,
  .faq_heading .w-accent .wi {
    animation: accent-drift 9s var(--motion-ease-inout) infinite alternate;
  }
}

@keyframes accent-drift {
  from {
    background-position: 0% 50%;
  }

  to {
    background-position: 100% 50%;
  }
}

/* Product mockup: floating, tilting, glowing */
.hero_enhanced .hero_image_container {
  perspective: 1200px;
  z-index: 1;
}

.hero_phone_tilt {
  position: relative;
  transform-style: preserve-3d;
  will-change: transform;
}

@media (prefers-reduced-motion: no-preference) {
  html.js-motion .hero_phone_tilt {
    animation: phone-float 7s ease-in-out infinite;
  }
}

@keyframes phone-float {
  0%,
  100% {
    translate: 0 0;
  }

  50% {
    translate: 0 -14px;
  }
}

.hero_phone_glow {
  position: absolute;
  inset: -12% -20%;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(
    52% 46% at 50% 52%,
    var(--glow-teal-soft),
    transparent 72%
  );
  filter: blur(6px);
}

@media (prefers-reduced-motion: no-preference) {
  .hero_phone_glow {
    animation: glow-breathe 7s ease-in-out infinite;
  }
}

@keyframes glow-breathe {
  0%,
  100% {
    opacity: 0.75;
    scale: 1;
  }

  50% {
    opacity: 1;
    scale: 1.06;
  }
}

/* Wide screens: keep the product mockup and copy as one centered composition. */
@media screen and (min-width: 992px) {
  .hero_enhanced .hero_content_container {
    flex-flow: row;
    justify-content: center;
    align-items: center;
    width: 100%;
    max-width: min(100%, 1300px);
    margin-inline: auto;
    grid-column-gap: clamp(3rem, 6vw, 7rem);
  }

  .hero_enhanced .hero_image_container {
    display: block;
    min-width: 320px;
    max-width: 430px;
  }

  .hero_enhanced .hero_text_container {
    align-items: flex-start;
    max-width: 640px;
  }

  .hero_enhanced .hero_heading.heading-h1,
  .hero_enhanced .hero_paragraph {
    text-align: left;
  }

  .hero_enhanced .hero_disclaimer {
    text-align: left;
  }
}

@media screen and (min-width: 1440px) {
  .hero_enhanced .hero_image_container {
    max-width: 470px;
  }
}

/*
 * Short landscape viewports (13"-16" laptops, windowed browsers).
 * The hero heading scales with viewport *width* and the phone mockup has a
 * fixed intrinsic aspect ratio, so on a wide-but-short screen the combined
 * content overflows the fold and pushes the download CTA out of view. These
 * height-based overrides compress the hero so it fits within one viewport.
 * Scoped to min-width: 992px, so the mobile layout is untouched. The compound
 * .section-hero.hero_enhanced selector matches the same element and keeps
 * these ahead of the width-based hero rules above regardless of source order.
 */
@media screen and (min-width: 992px) and (max-height: 1024px) {
  .section-hero.hero_enhanced .hero_heading.heading-h1 {
    font-size: min(clamp(2.9rem, 1.9rem + 3.4vw, 5.4rem), 9vh);
  }

  .section-hero.hero_enhanced .hero_content_container {
    padding-top: var(--_sizes---spacing--spacing-l);
    padding-bottom: var(--_sizes---spacing--spacing-l);
    grid-row-gap: var(--_sizes---spacing--spacing-m);
  }

  .section-hero.hero_enhanced .hero_text_container {
    padding-top: 0;
    padding-bottom: 0;
    grid-row-gap: var(--_sizes---spacing--spacing-xs);
  }

  .section-hero.hero_enhanced .hero_image_container {
    max-width: min(430px, 48vh);
    min-width: 0;
    padding-top: var(--_sizes---spacing--spacing-s);
  }
}

/* Wider desktops still render the larger mockup; keep it height-capped too. */
@media screen and (min-width: 1440px) and (max-height: 1024px) {
  .section-hero.hero_enhanced .hero_image_container {
    max-width: min(470px, 48vh);
  }
}

/* Very short screens (small 13" laptops): compress the hero further. */
@media screen and (min-width: 992px) and (max-height: 768px) {
  .section-hero.hero_enhanced .hero_heading.heading-h1 {
    font-size: min(clamp(2.6rem, 1.6rem + 3.4vw, 5.4rem), 8.2vh);
  }

  .section-hero.hero_enhanced .hero_content_container {
    padding-top: var(--_sizes---spacing--spacing-m);
    padding-bottom: var(--_sizes---spacing--spacing-m);
  }

  .section-hero.hero_enhanced .hero_image_container {
    max-width: min(430px, 44vh);
  }
}

/* Availability chip instead of plain small print */
.hero_enhanced .hero_disclaimer {
  padding: 0.45em 1em;
  border: 1px solid var(--glass-border);
  border-radius: 999px;
  background-color: rgba(17, 17, 17, 0.4);
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
}

.hero_enhanced .hero_disclaimer::before {
  content: "";
  width: 0.55em;
  height: 0.55em;
  border-radius: 50%;
  background-color: var(--color-brand--tertiary);
  box-shadow: 0 0 8px 1px var(--glow-teal);
}

@media (prefers-reduced-motion: no-preference) {
  .hero_enhanced .hero_disclaimer::before {
    animation: ping 2.6s var(--motion-ease-inout) infinite;
  }
}

@keyframes ping {
  0%,
  100% {
    box-shadow: 0 0 6px 0 var(--glow-teal);
  }

  50% {
    box-shadow: 0 0 12px 3px var(--glow-teal);
  }
}

/* Scroll cue fades away once the user commits to scrolling */
@media (prefers-reduced-motion: no-preference) {
  html.js-motion .lottie_scroll_container {
    transition: opacity var(--motion-dur-s) var(--motion-ease-out);
  }

  html.js-motion.has-scrolled .lottie_scroll_container {
    opacity: 0;
  }
}

/* ---------------------------------------------------------------------------
   Buttons: sheen sweep + lift, magnetic handled in JS via translate vars
--------------------------------------------------------------------------- */

.store_button_container {
  position: relative;
  overflow: clip;
  transition:
    transform var(--motion-dur-xs) var(--motion-ease-out),
    border-color var(--motion-dur-xs) var(--motion-ease-out),
    box-shadow var(--motion-dur-s) var(--motion-ease-out);
  transform: translate3d(var(--mx, 0), var(--my, 0), 0);
}

.store_button_container::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    115deg,
    transparent 30%,
    rgba(238, 238, 238, 0.14) 50%,
    transparent 70%
  );
  transform: translateX(-130%);
  pointer-events: none;
}

.store_button_container:hover {
  border-color: var(--color-brand--tertiary);
  box-shadow: 0 8px 32px -10px var(--glow-teal);
}

@media (prefers-reduced-motion: no-preference) {
  .store_button_container:hover::after {
    transition: transform 0.7s var(--motion-ease-out);
    transform: translateX(130%);
  }
}

/* ---------------------------------------------------------------------------
   Navbar: settles into glass once the page scrolls
--------------------------------------------------------------------------- */

.nav_bar_container {
  transition: box-shadow var(--motion-dur-s) var(--motion-ease-out);
}

html.has-scrolled .nav_bar_container {
  box-shadow: 0 14px 44px -18px rgba(0, 0, 0, 0.85);
}

/* ---------------------------------------------------------------------------
   Features: drawn timeline, numbered chapters, parallax mockups
--------------------------------------------------------------------------- */

.features_middle_line {
  position: relative;
}

.features_middle_line::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  /* Fill grows via a compositor-only scaleY instead of animating `height`
     every scroll frame (which relayouts). The gradient is proportional, so
     scaling looks identical to a growing height. */
  transform: scaleY(var(--line-progress, 0));
  transform-origin: top center;
  will-change: transform;
  border-radius: inherit;
  background: linear-gradient(
    180deg,
    transparent,
    var(--color-brand--tertiary) 12%,
    var(--color-brand--tertiary)
  );
  box-shadow: 0 0 14px 1px var(--glow-teal-soft);
}

.features_middle_square {
  transition: box-shadow var(--motion-dur-s) var(--motion-ease-out);
  box-shadow: 0 0 12px 2px rgba(225, 97, 58, 0.45);
}

/* ---------------------------------------------------------------------------
   Features timeline — compositor-driven progress (no main-thread JS)

   The diamond + fill used to be positioned by JS on every scroll event. JS
   runs on the main thread while scrolling runs on the compositor, so the two
   desync by a frame and the diamond visibly jitters against the scroll.

   Where supported, we hand the whole thing to the compositor via a
   scroll-driven view-timeline: the browser interpolates the fill's scaleY and
   the diamond's translateY directly from scroll position — locked to the page
   exactly like the old `position: sticky` was, with zero main-thread cost.

   Non-supporting browsers (Safari, Firefox) fall through to the JS-fed
   `--line-progress` / `--line-fill` transforms above — same look, minor jitter.

   Tuning: `animation-range` controls when the line draws relative to the
   section passing through the viewport. Widen/narrow the two `cover` %s to
   start the draw earlier/later.
--------------------------------------------------------------------------- */

@supports (animation-timeline: view()) {
  .features_grid_container {
    view-timeline-name: --features-line;
    view-timeline-axis: block;
  }

  /* Container-query context so the diamond travels the full track height with
     a compositor-only transform: 100cqh == the track's height. */
  .features_middle_line_container {
    container-type: size;
  }

  .features_middle_line::after {
    animation: features-line-grow linear both;
    animation-timeline: --features-line;
    animation-range: cover 15% cover 85%;
  }

  .features_middle_square {
    animation: features-diamond-ride linear both;
    animation-timeline: --features-line;
    animation-range: cover 15% cover 85%;
  }
}

@keyframes features-line-grow {
  from {
    transform: scaleY(0);
  }
  to {
    transform: scaleY(1);
  }
}

@keyframes features-diamond-ride {
  from {
    transform: translate(-50%, -50%) translateY(0) rotate(45deg);
  }
  to {
    transform: translate(-50%, -50%) translateY(100cqh) rotate(45deg);
  }
}

.feature_index {
  color: var(--color-brand--tertiary);
  font-family: Outfit, sans-serif;
  font-size: var(--_sizes---text-size--body-s);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  letter-spacing: 0.28em;
  opacity: 0.85;
  margin-bottom: var(--_sizes---spacing--spacing-xs);
  display: inline-flex;
  align-items: center;
  gap: 0.8em;
}

.feature_index::after {
  content: "";
  width: 2.4em;
  height: 1px;
  background: linear-gradient(90deg, var(--color-brand--tertiary), transparent);
}

/* The alignment class sits on the same element as .feature_index, so it must be
   matched with a compound selector (not a descendant one). .align-top-right also
   forces `display: flex; flex-flow: column`, which stacked the accent line under
   the number in the right-hand column while the left column kept it inline. Pin
   the number + line to a horizontal row in both columns, mirrored on the right. */
.feature_index.align-top-right {
  display: flex;
  flex-direction: row-reverse;
  align-items: center;
  justify-content: flex-start;
}

.feature_index.align-top-right::after {
  background: linear-gradient(270deg, var(--color-brand--tertiary), transparent);
}

/* Mobile collapses to one centered column, so both sides render identically:
   a centered row with the accent line to the right of the number. Lives here
   (not in style.css) because motion.css loads last and must win the cascade. */
@media screen and (max-width: 767px) {
  .feature_index,
  .feature_index.align-top-right {
    display: inline-flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
  }

  .feature_index.align-top-right::after {
    background: linear-gradient(90deg, var(--color-brand--tertiary), transparent);
  }
}

.features_grid_image_container {
  will-change: transform;
}

/* ---------------------------------------------------------------------------
   Database counters: glass cards with an ambient pulse
--------------------------------------------------------------------------- */

.db_number_card {
  padding: var(--_sizes---spacing--spacing-l) var(--_sizes---spacing--spacing-m);
  border: 1px solid var(--glass-border);
  border-radius: var(--_sizes---borders--border-main);
  background-color: var(--glass-bg);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  max-width: 760px;
  position: relative;
  overflow: clip;
  transition:
    border-color var(--motion-dur-s) var(--motion-ease-out),
    box-shadow var(--motion-dur-s) var(--motion-ease-out);
}

.db_number_card::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(
    60% 90% at 50% 0%,
    rgba(68, 161, 160, 0.12),
    transparent 70%
  );
}

.db_number_card:hover {
  border-color: rgba(68, 161, 160, 0.35);
  box-shadow: 0 24px 60px -30px var(--glow-teal);
}

/* ---------------------------------------------------------------------------
   CTA: living gradient
--------------------------------------------------------------------------- */

.cta_container {
  position: relative;
  overflow: clip;
}

@media (prefers-reduced-motion: no-preference) {
  .cta_container {
    background-size: 160% 160%;
    animation: cta-drift 16s var(--motion-ease-inout) infinite alternate;
  }
}

@keyframes cta-drift {
  from {
    background-position: 0% 0%;
  }

  to {
    background-position: 100% 100%;
  }
}

.qr_code_container {
  transform: translate3d(var(--mx, 0), var(--my, 0), 0);
}

/* ---------------------------------------------------------------------------
   Download page (in-house replacement for the old Linktree)
--------------------------------------------------------------------------- */

.download_hero .hero_container {
  justify-content: flex-start;
  padding-top: clamp(2.5rem, 6vw, 5.5rem);
  padding-bottom: clamp(4rem, 8vw, 8rem);
}

.download_hero + .section-footer {
  margin-top: 0;
}

.download_hero + .section-footer .footer_spacer {
  display: none;
}

.download_hero + .section-footer .footer_container_sticky {
  position: relative;
  bottom: auto;
}

.download_stack {
  display: grid;
  grid-template-areas:
    "heading"
    "copy"
    "qr"
    "stores"
    "availability"
    "more";
  grid-template-columns: minmax(0, 1fr);
  align-items: center;
  justify-items: center;
  gap: clamp(1.25rem, 3vw, 2rem);
  width: 100%;
  max-width: 1200px;
  text-align: center;
}

.download_heading {
  grid-area: heading;
  max-width: 11ch;
}

.download_hero .hero_heading.heading-h1,
.download_hero .hero_paragraph {
  text-align: center;
}

.download_subheading {
  grid-area: copy;
  max-width: 52ch;
  color: var(--color-neutral--secondary-text);
  text-wrap: balance;
}

.download_hero .store_buttons_container {
  grid-area: stores;
  /* Wrap instead of overflowing the (narrow) left column and sliding
     under the QR card in the two-column layout. */
  flex-wrap: wrap;
}

.download_hero .hero_disclaimer {
  grid-area: availability;
  margin-top: 0;
}

.download_qr_card {
  grid-area: qr;
  margin: 0;
  width: min(100%, 420px);
  box-sizing: border-box;
  padding: clamp(1rem, 2.4vw, 1.5rem);
  background: #0d1717;
  border: 1px solid rgba(174, 226, 226, 0.22);
  border-radius: clamp(1rem, 2vw, 1.5rem);
  box-shadow: 0 24px 64px -28px rgba(9, 9, 9, 0.92), 0 0 52px -30px rgba(174, 226, 226, 0.72);
  display: flex;
  flex-flow: column;
  align-items: center;
  gap: var(--_sizes---spacing--spacing-s);
  transition:
    transform var(--motion-dur-s) var(--motion-ease-out);
}

.download_qr_card:hover {
  transform: translateY(-4px);
  border-color: rgba(174, 226, 226, 0.4);
  box-shadow: 0 30px 72px -28px rgba(9, 9, 9, 0.96), 0 0 58px -28px rgba(174, 226, 226, 0.78);
}

.download_qr_hint {
  color: #aee2e2;
  font-size: var(--_sizes---text-size--body-xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-weight: 600;
}

.download_more {
  grid-area: more;
  width: 100%;
  margin-top: clamp(1rem, 3vw, 2rem);
  padding-top: clamp(2rem, 5vw, 3.5rem);
  border-top: 1px solid var(--glass-border);
  display: flex;
  flex-flow: column;
  align-items: center;
  gap: var(--_sizes---spacing--spacing-m);
  container-type: inline-size;
  container-name: download-more;
}

.download_more_heading {
  color: var(--color-neutral--tertiary-text);
  font-size: var(--_sizes---text-size--body-s);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  font-weight: 600;
}

.download_links {
  width: 100%;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--_sizes---spacing--spacing-s);
}

.download_link_card {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 2vw, 1.5rem);
  min-height: 5rem;
  box-sizing: border-box;
  padding: clamp(1rem, 2vw, 1.5rem);
  border: 1px solid var(--glass-border);
  border-radius: var(--_sizes---borders--border-main);
  background-color: var(--glass-bg);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  text-align: left;
  transition:
    transform var(--motion-dur-xs) var(--motion-ease-out),
    border-color var(--motion-dur-xs) var(--motion-ease-out),
    box-shadow var(--motion-dur-s) var(--motion-ease-out);
}

.download_link_card:focus-visible,
.download_hero .store_button_container:focus-visible {
  outline: 3px solid var(--color-brand--alternative);
  outline-offset: 4px;
}

.download_link_card:hover {
  transform: translateY(-3px);
  border-color: rgba(68, 161, 160, 0.4);
  box-shadow: 0 20px 50px -24px var(--glow-teal);
}

.download_link_icon {
  flex: none;
  width: 3rem;
  height: 3rem;
  display: flex;
  align-items: center;
  justify-content: center;
}

.download_link_icon img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.download_link_icon_pad img {
  width: 78%;
  height: 78%;
  /* envelope.svg is drawn for light backgrounds */
  filter: invert(0.88);
}

.download_link_text {
  display: flex;
  flex-flow: column;
  gap: 0.15em;
  min-width: 0;
}

.download_link_title {
  color: var(--color-neutral--primary-text);
  font-family: Poppins, sans-serif;
  font-size: var(--_sizes---text-size--body-m);
  font-weight: 600;
}

.download_link_sub {
  color: var(--color-neutral--tertiary-text);
  font-size: var(--_sizes---text-size--body-s);
  font-weight: 300;
  overflow-wrap: anywhere;
}

.download_link_arrow {
  margin-left: auto;
  color: var(--color-brand--tertiary);
  font-size: var(--_sizes---text-size--body-l);
  transition: transform var(--motion-dur-xs) var(--motion-ease-out);
}

.download_link_card:hover .download_link_arrow {
  transform: translateX(5px);
}

@container download-more (min-width: 1040px) {
  .download_links {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media screen and (min-width: 992px) {
  .download_stack {
    grid-template-areas:
      "heading qr"
      "copy qr"
      "stores qr"
      "availability qr"
      "more more";
    grid-template-columns: minmax(0, 1fr) minmax(320px, 380px);
    column-gap: clamp(1.75rem, 3.5vw, 5rem);
    row-gap: 1.5rem;
    justify-items: start;
    text-align: left;
  }

  .download_hero .hero_heading.heading-h1,
  .download_hero .hero_paragraph {
    text-align: left;
  }

  .download_qr_card {
    align-self: center;
    justify-self: end;
  }

  .download_more {
    align-items: stretch;
  }

  .download_more_heading {
    text-align: center;
  }
}

@media (hover: none) {
  .download_link_card:hover,
  .download_qr_card:hover {
    transform: none;
  }
}

/* ---------------------------------------------------------------------------
   Blog: listing cards + reading experience
--------------------------------------------------------------------------- */

.blog_cat_post_container {
  transition:
    transform var(--motion-dur-s) var(--motion-ease-out),
    box-shadow var(--motion-dur-s) var(--motion-ease-out);
}

.blog_cat_post_container:hover {
  transform: translateY(-6px);
  box-shadow: 0 30px 60px -34px rgba(0, 0, 0, 0.9),
    0 18px 48px -30px var(--glow-teal-soft);
}

.blog_cat_post_image_container {
  overflow: clip;
}

.blog_cat_post_image {
  transition: transform 1.1s var(--motion-ease-out);
}

.blog_cat_post_container:hover .blog_cat_post_image {
  transform: scale(1.05);
}

.reading_progress {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 50;
  width: 100%;
  height: 3px;
  pointer-events: none;
  background: transparent;
}

.reading_progress::before {
  content: "";
  display: block;
  height: 100%;
  width: 100%;
  transform-origin: 0 50%;
  transform: scaleX(var(--read-progress, 0));
  background: linear-gradient(
    90deg,
    var(--color-brand--secondary),
    var(--color-brand--tertiary)
  );
  box-shadow: 0 0 10px var(--glow-teal);
}

.blog_post_image_container {
  overflow: clip;
}

/* ---------------------------------------------------------------------------
   Contact: custom support illustration
--------------------------------------------------------------------------- */

.contact_illustration {
  position: absolute;
  top: 50%;
  right: 1%;
  transform: translateY(-50%);
  width: clamp(260px, 36vw, 480px);
  pointer-events: none;
}

.contact_illustration svg {
  display: block;
  width: 100%;
  height: auto;
}

@media screen and (max-width: 900px) {
  /* Like the download QR, the illustration flows in content instead of being
     pinned. It's the first DOM child, so order it below the heading + contact
     details (never above the page). Tighten the column gaps and let it scale
     with the viewport so it doesn't float in empty space at tablet widths. */
  .contact_container {
    gap: var(--_sizes---spacing--spacing-m);
    margin-bottom: var(--_sizes---spacing--spacing-m);
  }

  .contact_illustration {
    order: 1;
    position: static;
    transform: none;
    width: clamp(230px, 42vw, 340px);
    margin: 0 auto;
    align-self: center;
  }
}

.ci_float,
.ci_twinkle,
.ci_steam {
  transform-box: fill-box;
  transform-origin: center;
}

/* Match the download page: constrain the contact content to a centered
   1200px column (same as .download_stack) instead of letting it stretch the
   full 1600px content width. .content-size-padding is a centered flex column,
   so a max-width here centres each block. */
.section-contact > .content-size-padding > .contact_container,
.section-contact > .content-size-padding > .form_container {
  width: 100%;
  max-width: 1200px;
}

@media (prefers-reduced-motion: no-preference) {
  .ci_float {
    animation: ci-float 6s var(--motion-ease-inout) infinite;
    animation-delay: var(--d, 0s);
  }

  .ci_twinkle {
    animation: ci-twinkle 3.4s var(--motion-ease-inout) infinite;
    animation-delay: var(--d, 0s);
  }

  .ci_steam {
    animation: ci-steam 2.8s var(--motion-ease-inout) infinite;
    animation-delay: var(--d, 0s);
  }
}

@keyframes ci-float {
  0%,
  100% {
    transform: translateY(0);
  }

  50% {
    transform: translateY(-9px);
  }
}

@keyframes ci-twinkle {
  0%,
  100% {
    opacity: 0.35;
    transform: scale(0.8);
  }

  50% {
    opacity: 1;
    transform: scale(1.1);
  }
}

@keyframes ci-steam {
  0%,
  100% {
    opacity: 0.25;
    transform: translateY(0);
  }

  50% {
    opacity: 0.7;
    transform: translateY(-4px);
  }
}

/* ---------------------------------------------------------------------------
   Contact: form focus glow
--------------------------------------------------------------------------- */

.form_field {
  transition:
    border-color var(--motion-dur-xs) var(--motion-ease-out),
    box-shadow var(--motion-dur-s) var(--motion-ease-out);
}

.form_field:focus {
  border-color: var(--color-brand--tertiary);
  box-shadow: 0 0 0 3px rgba(68, 161, 160, 0.18);
}

/* ---------------------------------------------------------------------------
   Contact: interactive link buttons (mail / phone / socials)
--------------------------------------------------------------------------- */

@media (prefers-reduced-motion: no-preference) {
  .contact_link {
    transition:
      transform var(--motion-dur-xs) var(--motion-ease-spring),
      border-color var(--motion-dur-xs) var(--motion-ease-out),
      box-shadow var(--motion-dur-s) var(--motion-ease-out);
  }

  /* Diagonal light sweep that glides across the button on hover. */
  .contact_link::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(
      115deg,
      transparent 30%,
      rgba(174, 226, 226, 0.28) 50%,
      transparent 70%
    );
    background-size: 250% 100%;
    background-position: 150% 0;
    pointer-events: none;
    opacity: 0;
    transition: opacity var(--motion-dur-xs) var(--motion-ease-out);
  }

  .contact_link:hover {
    transform: translateY(-3px) scale(1.02);
    box-shadow:
      0 10px 26px -12px rgba(174, 226, 226, 0.55),
      0 0 0 1px rgba(174, 226, 226, 0.4);
  }

  .contact_link:hover::after {
    opacity: 1;
    animation: contact-sweep 0.7s var(--motion-ease-out);
  }

  .contact_link:active {
    transform: translateY(-1px) scale(0.99);
    transition-duration: 0.08s;
  }

  /* Icon tile springs and tilts. */
  .contact_link_icon {
    transition:
      transform var(--motion-dur-s) var(--motion-ease-spring),
      box-shadow var(--motion-dur-s) var(--motion-ease-out);
  }

  .contact_link:hover .contact_link_icon {
    transform: rotate(-6deg) scale(1.1);
    box-shadow: 0 6px 16px -6px rgba(174, 226, 226, 0.7);
  }

  /* Label nudges forward to follow the motion. */
  .contact_link_text {
    transition: transform var(--motion-dur-s) var(--motion-ease-spring);
  }

  .contact_link:hover .contact_link_text {
    transform: translateX(4px);
  }
}

@keyframes contact-sweep {
  from {
    background-position: 150% 0;
  }

  to {
    background-position: -50% 0;
  }
}

/* ---------------------------------------------------------------------------
   Ambient page headers (blog, contact, legal…) share the hero's water DNA
--------------------------------------------------------------------------- */

.section-blog,
.section-contact,
.section-blog-post,
.section-psw-reset,
.owners_hero_section,
.section-legal-info,
.section-legal {
  position: relative;
}

.section-blog > .content-size-padding,
.section-contact > .content-size-padding,
.section-blog-post > .content-size-padding,
.section-psw-reset > .content-size-padding,
.owners_hero_section > .owners_hero_container {
  position: relative;
  z-index: 1;
}

/* ---------------------------------------------------------------------------
   Reduced motion: everything lands instantly, nothing drifts
--------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .wash_canvas {
    opacity: 1;
    transition: none;
  }

  .store_button_container::after {
    display: none;
  }
}

/* ---------------------------------------------------------------------------
   Scroll performance
   -------------------
   Skip layout + paint for below-the-fold sections until they're near the
   viewport, and idle the hero's decorative loops once it scrolls away. No
   visual is removed — the work is just deferred until it can be seen. The
   `auto` intrinsic size lets the browser cache each section's real height
   after first view, so the scrollbar doesn't jump on the way back up.

   Deliberately excluded: .section-hero (always first paint + WebGL scene)
   and .section-footer (its sticky child dislikes size containment).
--------------------------------------------------------------------------- */

.section-features,
.section-db-number,
.section-cta,
.section-faq,
.section-contact,
.section-blog,
.section-blog-post,
.section-privacy-policy,
.section-tos {
  content-visibility: auto;
  contain-intrinsic-size: auto 900px;
}

.section-features,
.section-faq {
  contain-intrinsic-size: auto 1400px;
}

.section-blog-post,
.section-privacy-policy,
.section-tos {
  contain-intrinsic-size: auto 2200px;
}

/* Hero decorative loops stop ticking once the hero is fully scrolled past
   (motion.js toggles .anim-idle via an IntersectionObserver). */
html.js-motion .section-hero.anim-idle,
html.js-motion .section-hero.anim-idle * {
  animation-play-state: paused !important;
}
