@font-face {
  font-family: "Archivo";
  src: url("../fonts/Archivo-latin.woff2") format("woff2");
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Archivo";
  src: url("../fonts/Archivo-latin-ext.woff2") format("woff2");
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "JetBrains Mono";
  src: url("../fonts/JetBrainsMono-latin.woff2") format("woff2");
  font-weight: 400 600;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "JetBrains Mono";
  src: url("../fonts/JetBrainsMono-latin-ext.woff2") format("woff2");
  font-weight: 400 600;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* dark glass: the one chosen look, not a light/dark toggle. every surface on top of the
   fixed lightfield background is a translucent, blurred panel (.glass). */
:root {
  --r-xl: 12px;
  --r-l: 10px;
  --r-m: 8px;
  --r-s: 6px;
  --r-xs: 4px;
  --r-xxs: 3px;
  --r-pill: 8px;
  --paper: #07080a;
  --paper-2: #0c0e12;
  --surface: #14151a;
  --ink: #f2f3f0;
  --ink-2: rgba(242, 243, 240, 0.78);
  --muted: rgba(242, 243, 240, 0.5);
  --line: rgba(255, 255, 255, 0.12);
  --line-strong: rgba(255, 255, 255, 0.22);
  --lime: #c8ff3d;
  --lime-ink: #06100a;
  --bad: #ff8f80;
  --bad-soft: rgba(255, 143, 128, 0.14);
  --cool: #6fa8ff;
  --dark: #040506;
  --dark-2: #0a0b0d;
  --dark-line: rgba(255, 255, 255, 0.1);
  --dark-text: var(--ink);
  --dark-muted: var(--muted);
  --error: #ff8f80;
  --glass: rgba(255, 255, 255, 0.045);
  --glass-border: rgba(255, 255, 255, 0.09);
  --glass-strong: rgba(255, 255, 255, 0.07);
  --blur-lg: 28px;
  --blur-md: 18px;
  --blur-sm: 10px;
  --sans: "Archivo", system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  --gutter: clamp(16px, 4vw, 48px);
  --ease: cubic-bezier(0.2, 0.7, 0.1, 1);
  --m-fast: 180ms;
  --m-base: 420ms;
  --m-slow: 760ms;
  color-scheme: dark;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 84px;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font: 400 1.0625rem/1.6 var(--sans);
  font-stretch: 100%;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

/* iOS Safari still pans sideways with overflow-x: hidden on body when decorative 3D pieces
   poke past the edge; clip on both roots stops that without breaking position: sticky. */
html,
body {
  overflow-x: clip;
}

/* ---------- light field background: fixed, follows scroll progress via body[data-glow] ---------- */
.lightfield {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
  background: var(--paper);
}

/* the 3D scene (css/scene.css, js/scene.js) sits between the opaque lightfield and the
   noise overlay, so it renders as a dim layer behind every section and glass panel */

.lightfield::before,
.lightfield::after {
  content: "";
  position: absolute;
  width: 70vmax;
  height: 70vmax;
  border-radius: 50%;
  filter: blur(80px);
  opacity: 0.5;
  transition: transform 1.2s var(--ease), opacity 1.2s var(--ease);
  will-change: transform;
}

.lightfield::before {
  background: radial-gradient(circle, var(--lime) 0%, transparent 70%);
  top: -20vmax;
  left: -10vmax;
}

.lightfield::after {
  background: radial-gradient(circle, var(--cool) 0%, transparent 70%);
  bottom: -25vmax;
  right: -15vmax;
}

[data-glow="work"] .lightfield::before { transform: translate(10vw, 20vh); opacity: 0.4; }
[data-glow="work"] .lightfield::after { transform: translate(-8vw, -10vh); opacity: 0.5; }
[data-glow="pricing"] .lightfield::before { transform: translate(-6vw, 30vh); opacity: 0.65; }
[data-glow="pricing"] .lightfield::after { transform: translate(10vw, -15vh); opacity: 0.35; }
[data-glow="process"] .lightfield::before { transform: translate(14vw, 10vh); opacity: 0.35; }
[data-glow="process"] .lightfield::after { transform: translate(-14vw, 10vh); opacity: 0.6; }
[data-glow="form"] .lightfield::before { transform: translate(-10vw, -10vh); opacity: 0.5; }
[data-glow="form"] .lightfield::after { transform: translate(12vw, 20vh); opacity: 0.55; }

.noise {
  position: fixed;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  opacity: 0.035;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
}

main,
header,
footer {
  position: relative;
  z-index: 3;
}

/* ---------- glass primitive: translucent, blurred panel used for every raised surface ---------- */
.glass {
  background: var(--glass);
  border: 1px solid var(--glass-border);
  border-radius: var(--r-xl);
  backdrop-filter: blur(var(--blur-md)) saturate(1.3);
  -webkit-backdrop-filter: blur(var(--blur-md)) saturate(1.3);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.07) inset,
    0 30px 60px -30px rgba(0, 0, 0, 0.6),
    0 10px 24px -12px rgba(0, 0, 0, 0.5);
  position: relative;
  isolation: isolate;
}

@media (max-width: 640px) {
  .glass {
    backdrop-filter: blur(var(--blur-sm)) saturate(1.2);
    -webkit-backdrop-filter: blur(var(--blur-sm)) saturate(1.2);
  }
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
}

img {
  display: block;
  max-width: 100%;
  height: auto;
}

a {
  color: inherit;
  text-underline-offset: 0.22em;
  text-decoration-thickness: 1px;
}

h1,
h2,
h3 {
  margin: 0;
  font-weight: 800;
  font-stretch: 72%;
  line-height: 0.95;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

h2 {
  font-size: clamp(2.6rem, 6.4vw, 5.6rem);
}

h3 {
  font-size: clamp(1.5rem, 2.4vw, 2rem);
  line-height: 1.05;
  letter-spacing: -0.01em;
}

p {
  margin: 0;
  text-wrap: pretty;
}

mark {
  background: linear-gradient(var(--lime), var(--lime)) no-repeat 0 88% / 100% 0.62em;
  color: inherit;
  padding: 0 0.04em;
}

:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
  border-radius: var(--r-xxs);
}

.wrap {
  width: 100%;
  max-width: 1320px;
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* above laptop width the 1320px cap left a fixed island with a growing dead zone beside it;
   let every section use the wider canvas instead. */
@media (min-width: 1680px) {
  .wrap {
    max-width: 1600px;
  }
}

@media (min-width: 2200px) {
  .wrap {
    max-width: 1900px;
  }
}

.skip {
  position: absolute;
  left: var(--gutter);
  top: -100px;
  z-index: 30;
  background: var(--lime);
  color: var(--lime-ink);
  padding: 10px 16px;
  border-radius: var(--r-s);
  font-weight: 700;
}

.skip:focus {
  top: 12px;
}

.label,
.status,
.footnote,
.hero-meta dt,
.tier-time span,
.currency a {
  font-family: var(--mono);
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.label {
  color: var(--muted);
  margin-bottom: 1rem;
}

.label::before {
  content: "§ ";
  color: var(--ink-2);
}

.lead {
  font-size: clamp(1.125rem, 1.5vw, 1.3rem);
  line-height: 1.5;
  color: var(--ink-2);
  max-width: 34em;
}

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6em;
  min-height: 52px;
  padding: 0 1.6rem;
  border: 1.5px solid var(--lime);
  border-radius: var(--r-m);
  background: var(--lime);
  color: var(--lime-ink);
  font: 700 1rem/1 var(--sans);
  font-stretch: 100%;
  text-decoration: none;
  cursor: pointer;
  transition: transform 0.2s var(--ease), background-color 0.2s, border-color 0.2s, color 0.2s;
}

.button:hover {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--paper);
}

.button:active {
  transform: scale(0.98);
}

/* an occasional ripple on the main "get a quote" buttons: two rings spread outward like water
   every few seconds, idle the rest of the cycle, so it catches the eye without nagging. The
   global reduced-motion rule switches it off. */
.button-pulse {
  position: relative;
}

.button-pulse::before,
.button-pulse::after {
  content: "";
  position: absolute;
  inset: -1.5px;
  border: 2px solid var(--lime);
  border-radius: var(--r-m);
  opacity: 0;
  pointer-events: none;
  animation: button-ripple 6s cubic-bezier(0.2, 0.7, 0.3, 1) 1.2s infinite;
}

.button-pulse::after {
  animation-delay: 1.55s;
}

.button-pulse--late::before {
  animation-delay: 4.2s;
}

.button-pulse--late::after {
  animation-delay: 4.55s;
}

.button-pulse:hover::before,
.button-pulse:hover::after,
.button-pulse:focus-visible::before,
.button-pulse:focus-visible::after {
  animation: none;
}

/* on phones the bottom bar carries its own rippling button: while that bar is showing, the
   hero button stays still so only one thing on screen pulses. */
@media (max-width: 899px) {
  body:has(.sticky-cta:not(.is-away):not([hidden])) .hero .button-pulse::before,
  body:has(.sticky-cta:not(.is-away):not([hidden])) .hero .button-pulse::after {
    animation: none;
  }
}

@keyframes button-ripple {
  0% {
    inset: -1.5px;
    border-radius: var(--r-m);
    opacity: 1;
  }
  10% {
    opacity: 0.55;
  }
  24% {
    inset: -16px;
    border-radius: calc(var(--r-m) + 12px);
    opacity: 0;
  }
  100% {
    inset: -16px;
    opacity: 0;
  }
}

.button-arrow {
  transition: transform 0.25s var(--ease);
}

.button:hover .button-arrow {
  transform: translateX(4px);
}

.button-outline {
  background: transparent;
  border-color: var(--ink);
  color: var(--ink);
}

.button-small {
  white-space: nowrap;
  min-height: 44px;
  padding: 0 1.15rem;
  font-size: 0.9375rem;
}

.button[disabled] {
  opacity: 0.6;
  cursor: progress;
}

.text-link {
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
  font-weight: 700;
  text-decoration: none;
  background: linear-gradient(var(--lime), var(--lime)) no-repeat 0 100% / 100% 2px;
  padding-bottom: 3px;
  transition: background-size 0.25s var(--ease), color 0.2s;
}

.text-link:hover {
  background-size: 100% 100%;
  color: var(--lime-ink);
}

/* shared by every text link that carries the chat icon (hero, contact section, footer):
   sized and vertically centred against the surrounding text, never via element.style. */
.icon-chat {
  width: 1.05em;
  height: 1.05em;
  flex-shrink: 0;
  vertical-align: -0.15em;
  color: #25d366;
}

.text-link .icon-chat {
  margin-right: 0.1em;
}

.site-header {
  position: sticky;
  top: 0;
  z-index: 40;
  padding: 14px 0;
}

.header-inner {
  display: flex;
  align-items: center;
  gap: 20px;
  min-height: 0;
  padding: 10px 20px;
  border-radius: var(--r-pill);
  background: rgba(10, 11, 14, 0.55);
  backdrop-filter: blur(var(--blur-lg)) saturate(1.4);
  -webkit-backdrop-filter: blur(var(--blur-lg)) saturate(1.4);
  box-shadow: 0 20px 40px -20px rgba(0, 0, 0, 0.6);
  border: 1px solid var(--glass-border);
}

@media (max-width: 640px) {
  .header-inner {
    backdrop-filter: blur(var(--blur-sm));
    -webkit-backdrop-filter: blur(var(--blur-sm));
    padding: 8px 14px;
  }

  /* flex children default to a content-based min-width, which is what let the
     header overflow the viewport instead of shrinking; this lets them shrink
     and the wordmark truncate instead */
  .header-inner > * {
    min-width: 0;
  }

  .wordmark-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  /* the rounded-rectangle CTA duplicates the hero's own button and the floating .sticky-cta
     that appears once the hero scrolls away, and doesn't fit next to the full wordmark and
     the menu toggle at phone widths; drop it here and keep the language switch only */
  .header-actions .button {
    display: none;
  }
}

.wordmark {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-right: auto;
  text-decoration: none;
}

.wordmark-mark {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: var(--r-m);
  background: #0f0f0d;
  color: var(--lime);
  box-shadow: 0 0 0 1px var(--line);
  font-weight: 800;
  font-stretch: 75%;
  font-size: 1rem;
  letter-spacing: -0.02em;
}

.wordmark-text {
  display: flex;
  flex-direction: column;
  line-height: 1.15;
}

.wordmark-name {
  white-space: nowrap;
  font-weight: 750;
  font-stretch: 90%;
  font-size: 1.05rem;
}

.wordmark-tag {
  font-family: var(--mono);
  font-size: 0.6875rem;
  color: var(--muted);
}

.nav ul {
  display: flex;
  gap: 2px;
  list-style: none;
  margin: 0;
  padding: 0;
}

.nav a {
  position: relative;
  display: block;
  padding: 8px 12px;
  font-family: var(--mono);
  font-size: 0.8125rem;
  font-weight: 500;
  text-decoration: none;
  color: var(--ink-2);
  transition: color 0.2s;
}

.nav a::after {
  content: "";
  position: absolute;
  left: 12px;
  right: 100%;
  bottom: 4px;
  height: 2px;
  background: var(--lime);
  transition: right var(--m-base) var(--ease);
}

.nav a:hover,
.nav a:focus-visible {
  color: var(--ink);
}

.nav a:hover::after,
.nav a:focus-visible::after {
  right: 12px;
}

.header-actions {
  display: flex;
  align-items: center;
  gap: 10px;
}

/* a WhatsApp entry the header keeps in view at every scroll position (it's sticky), for the
   widths where the bottom sticky-cta bar (mobile only, see its own min-width:900px rule) isn't
   there to carry that job. Qualified by .header-actions, not just .icon-button's own class, so
   it wins over that shared rule's display:inline-flex regardless of source order. */
.header-actions .header-whatsapp {
  display: none;
}

@media (min-width: 900px) {
  .header-actions .header-whatsapp {
    display: inline-flex;
  }
}

.lang {
  font-family: var(--mono);
  font-size: 0.75rem;
  font-weight: 600;
  text-decoration: none;
  padding: 8px;
  color: var(--muted);
}

.lang:hover {
  color: var(--ink);
}

/* .nav-disclosure wraps the nav in a <details>/<summary> so it degrades without JS: the
   toggle button only shows at mobile width, and native details[open] drives visibility,
   no script required. At desktop the summary is hidden and .nav is forced visible,
   overriding the UA default that hides non-summary children until the details is open. */
.nav-disclosure .nav {
  display: block;
}

.nav-toggle {
  display: none;
}

@media (max-width: 960px) {
  .header-inner {
    position: relative;
  }

  .nav-disclosure .nav {
    display: none;
    position: absolute;
    left: 0;
    right: 0;
    top: calc(100% + 10px);
    z-index: 10;
    background: var(--paper-2);
    border: 1px solid var(--glass-border);
    border-radius: var(--r-l);
    padding: 6px;
    box-shadow: 0 20px 40px -20px rgba(0, 0, 0, 0.6);
  }

  .nav-disclosure[open] .nav {
    display: block;
  }

  .nav-disclosure .nav ul {
    flex-direction: column;
    gap: 0;
  }

  .nav-disclosure .nav a {
    padding: 14px 12px;
  }

  .nav-disclosure .nav a::after {
    display: none;
  }

  .nav-toggle {
    display: grid;
    place-items: center;
    width: 38px;
    height: 38px;
    border-radius: var(--r-m);
    border: 1px solid var(--line);
    background: var(--glass);
    cursor: pointer;
    list-style: none;
  }

  .nav-toggle::-webkit-details-marker {
    display: none;
  }

  .nav-toggle-icon,
  .nav-toggle-icon::before,
  .nav-toggle-icon::after {
    display: block;
    width: 16px;
    height: 2px;
    background: var(--ink);
  }

  .nav-toggle-icon {
    position: relative;
  }

  .nav-toggle-icon::before,
  .nav-toggle-icon::after {
    content: "";
    position: absolute;
    left: 0;
  }

  .nav-toggle-icon::before {
    top: -5px;
  }

  .nav-toggle-icon::after {
    top: 5px;
  }

  .nav-disclosure[open] .nav-toggle-icon {
    background: transparent;
  }

  .nav-disclosure[open] .nav-toggle-icon::before {
    top: 0;
    transform: rotate(45deg);
  }

  .nav-disclosure[open] .nav-toggle-icon::after {
    top: 0;
    transform: rotate(-45deg);
  }

  @media (prefers-reduced-motion: no-preference) {
    .nav-toggle-icon::before,
    .nav-toggle-icon::after {
      transition: top 0.2s var(--ease), transform 0.2s var(--ease);
    }
  }
}

@media (max-width: 440px) {
  .wordmark-tag {
    display: none;
  }
}

.hero {
  position: relative;
  padding-block: clamp(96px, 9vw, 130px) clamp(56px, 8vw, 104px);
  overflow: hidden;
  display: flex;
  align-items: center;
}

/* the fixed header is sticky but not part of flex layout (it's a flow sibling before .hero),
   so .hero's own top padding is the only thing pushing the headline down below it; the clamp()
   above picks ~130px on a 1440px desktop, which is far more headroom than a ~390px phone needs
   once the sticky header (under 60px) is accounted for, so tighten it hard on narrow screens. */
@media (max-width: 640px) {
  .hero {
    padding-block: 28px clamp(48px, 8vw, 72px);
    min-height: 0;
  }

  .status {
    margin-bottom: 14px;
  }
}

/* a second light source for laptop width: the fixed lightfield sits behind the whole page and
   reads faint this far down the viewport, so the hero gets its own closer, warmer glow on top
   of it (still the lime + cool pair, no new colours) purely to lift "not cheerful" on a laptop,
   not a different palette. */
@media (min-width: 900px) {
  .hero::before {
    content: "";
    position: absolute;
    z-index: -1;
    top: -12vw;
    left: 38%;
    width: 60vw;
    height: 60vw;
    max-width: 820px;
    max-height: 820px;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(200, 255, 61, 0.22) 0%, rgba(111, 168, 255, 0.08) 55%, transparent 72%);
    filter: blur(40px);
    pointer-events: none;
  }
}

/* short laptop screens (the common 1280x720 / 1366x768 range): the hero's generous padding and
   vertical rhythm are tuned for a tall phone or a 900px+ desktop window, so on a wide but short
   window the primary CTA and price land well past the fold. Tighten the rhythm and the slogan
   clamp instead of hiding anything, so the hero still reads as the same hero, just denser. */
.hero .wrap {
  position: relative;
  width: 100%;
}

.status {
  position: relative;
  z-index: 1;
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 10px;
  width: fit-content;
  padding: 7px 14px 7px 12px;
  border: 1px solid rgba(200, 255, 61, 0.3);
  background: rgba(200, 255, 61, 0.06);
  border-radius: var(--r-pill);
  color: var(--lime);
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  margin-bottom: clamp(20px, 3vw, 32px);
}

.dot {
  display: inline-block;
  width: 6px;
  height: 6px;
  margin-right: 2px;
  border-radius: 50%;
  background: var(--lime);
  box-shadow: 0 0 0 0 rgba(200, 255, 61, 0.5);
}

.js .dot {
  animation: pulse 2.2s ease-in-out infinite;
}

.clock {
  color: var(--ink-2);
  font-weight: 600;
  text-transform: none;
}

@keyframes pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.4; transform: scale(0.7); }
}

/* mobile: default block flow stacks the sticker above the heading group in DOM order. Desktop:
   flipped to a row so the sticker reads as sitting next to the headline instead of above it. */
.hero-title-row {
  position: relative;
  z-index: 1;
}

/* fit-content so the sticker hangs off the slogan's own right edge, next to the short first
   line, instead of the far side of the hero column on wide screens. */
.hero-slogan-wrap {
  position: relative;
  width: fit-content;
  margin-top: clamp(10px, 1.6vw, 18px);
}

/* rotated lime roundel: the discount as a shape, not just a number in a sentence. */
.hero-sticker {
  position: absolute;
  z-index: 2;
  top: -0.35rem;
  right: -10px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  width: clamp(84px, 10vw, 148px);
  height: clamp(84px, 10vw, 148px);
  padding: 8px;
  border-radius: var(--r-l);
  background: var(--lime);
  color: var(--lime-ink);
  transform: rotate(-8deg);
  box-shadow: 0 20px 44px -16px rgba(200, 255, 61, 0.55);
}

.hero-sticker-percent {
  font-weight: 800;
  font-stretch: 66%;
  font-size: clamp(1.8rem, 3vw, 2.5rem);
  line-height: 1;
  letter-spacing: -0.02em;
}

.hero-sticker-label {
  font-family: var(--mono);
  font-size: 0.625rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  text-align: center;
}

.hero-heading {
  font-family: var(--mono);
  font-size: 0.8125rem;
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--ink-2);
  max-width: 28ch;
}

.hero-slogan {
  position: relative;
  z-index: 1;
  font-size: clamp(3.3rem, 7.6vw, 7.25rem);
  line-height: 0.92;
  font-stretch: 72%;
  letter-spacing: -0.01em;
  max-width: 12.5ch;
}

.hero-slogan .word {
  display: inline-block;
  overflow: hidden;
  vertical-align: top;
}

.hero-slogan .word > span {
  display: inline-block;
}

.js .hero-slogan .word > span {
  transform: translateY(100%);
  opacity: 0;
  animation: word-rise var(--m-slow) var(--ease) forwards;
}

@keyframes word-rise {
  to {
    transform: translateY(0);
    opacity: 1;
  }
}

/* stagger the word-rise without inline styles: each word is an element child, so nth-child works */
.js .hero-slogan .word:nth-child(2) > span {
  animation-delay: 60ms;
}
.js .hero-slogan .word:nth-child(3) > span {
  animation-delay: 120ms;
}
.js .hero-slogan .word:nth-child(4) > span {
  animation-delay: 180ms;
}
.js .hero-slogan .word:nth-child(5) > span {
  animation-delay: 240ms;
}
.js .hero-slogan .word:nth-child(6) > span {
  animation-delay: 300ms;
}
.js .hero-slogan .word:nth-child(7) > span {
  animation-delay: 360ms;
}
.js .hero-slogan .word:nth-child(8) > span {
  animation-delay: 420ms;
}
.js .hero-slogan .word:nth-child(9) > span {
  animation-delay: 480ms;
}
.js .hero-slogan .word:nth-child(10) > span {
  animation-delay: 540ms;
}

.hero-slogan mark {
  background: none;
  color: var(--lime);
  font-style: normal;
  position: relative;
  padding: 0 0.04em;
}

/* the big price line: struck regular price plus launch price, large enough that the discount
   is the first number read in the hero, not buried in the meta chips below. Sits right under
   the headline (before the lead paragraph, see hero() in home.ts) with a tight top margin so
   it lands inside the first viewport on short screens, not past the fold. */
.hero-price-line {
  position: relative;
  z-index: 1;
  margin: clamp(20px, 3vw, 28px) 0 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.hero-price-line-figures {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px clamp(12px, 1.6vw, 36px);
}

.hero-price-line-figures .price-strike {
  font-size: clamp(1.3rem, 2.4vw, 2rem);
  --strike-w: 4px;
}

.hero-price-line-figures .price-strike::after {
  top: 47%;
}

.hero-price-line-figures .price-strike .amount {
  color: var(--ink-2);
  font-weight: inherit;
  font-stretch: normal;
  letter-spacing: normal;
}

.hero-price-line-figures > .amount {
  font-size: clamp(3rem, 6vw, 4.6rem);
  color: var(--lime);
}

/* compact launch badge under the big price line: the one line a Facebook-ad click needs to see
   to know the price on screen is a time-limited launch price, not the permanent one. */
.hero-launch-badge {
  width: fit-content;
  margin: 0.1em 0 0;
  font-family: var(--mono);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  padding: 3px 9px;
  border-radius: var(--r-pill);
  background: rgba(200, 255, 61, 0.14);
  border: 1px solid rgba(200, 255, 61, 0.4);
  color: var(--lime);
  display: inline-block;
}

.hero .lead {
  margin-top: clamp(28px, 4vw, 44px);
  font-size: clamp(1.125rem, 1.6vw, 1.3rem);
  color: var(--ink-2);
  max-width: 34em;
}

.hero-note {
  margin: 10px 0 0;
  font-family: var(--mono);
  font-size: 0.8125rem;
  color: var(--muted);
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px 26px;
  margin-top: clamp(32px, 4vw, 44px);
}

.hero-whatsapp {
  font-size: 0.9375rem;
}

/* price / delivery / ownership as floating glass chips, not a measurement strip */
.hero-meta {
  position: relative;
  z-index: 1;
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin: clamp(40px, 5vw, 56px) 0 0;
  max-width: 820px;
}

.hero-meta > div {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 14px 20px;
  border-radius: var(--r-l);
  transition: transform 0.4s var(--ease), border-color 0.4s var(--ease);
}

@media (hover: hover) and (pointer: fine) {
  .hero-meta > div:hover {
    transform: translateY(-3px);
    border-color: rgba(200, 255, 61, 0.35);
  }
}

.hero-meta dt {
  font-family: var(--mono);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

.hero-meta dd {
  margin: 4px 0 0;
  font-weight: 600;
  font-size: 0.95rem;
  line-height: 1.15;
}

.hero-meta dd .amount {
  font: inherit;
  letter-spacing: 0;
  color: var(--lime);
  font-weight: 700;
}

.hero-meta dd .tier-discount-badge {
  margin-left: 0.5em;
  vertical-align: middle;
}

/* reassurance row: short fear-killers under the price chips */
.hero-reassure {
  display: grid;
  gap: 10px;
  margin: clamp(28px, 4vw, 40px) 0 0;
  max-width: 640px;
  list-style: none;
  padding: 0;
}

.hero-reassure li {
  position: relative;
  padding-left: 1.5em;
  font-size: 0.9375rem;
  color: var(--ink-2);
}

.hero-reassure li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.5em;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--lime);
  box-shadow: 0 0 10px 1px rgba(200, 255, 61, 0.4);
}


/* short laptop screens (the common 1280x720 / 1366x768 range): the hero's generous padding and
   vertical rhythm are tuned for a tall phone or a 900px+ desktop window, so on a wide but short
   window the primary CTA and price land well past the fold. Tighten the rhythm and the slogan
   clamp instead of hiding anything, so the hero still reads as the same hero, just denser. Comes
   after the base hero rules in source order so it wins the cascade at equal specificity. */
@media (min-width: 900px) and (max-height: 1100px) {
  .hero {
    padding-block: 20px 32px;
    min-height: 0;
    align-items: flex-start;
  }

  .status {
    margin-bottom: 10px;
  }

  .hero-slogan-wrap {
    margin-top: 6px;
  }

  /* wide enough for two lines: at 11.5ch the slogan broke into four short lines and left the
     whole right half of a laptop screen empty */
  .hero-heading {
    max-width: none;
  }

  .hero-slogan {
    font-size: clamp(2.4rem, 4.4vw, 3.9rem);
    line-height: 1.02;
    max-width: 21ch;
  }

  /* the sticker's own clamp is tuned for the full-size slogan; at this compact size it would
     dwarf and cover the two short lines, so it scales down and sits tighter to the corner. */
  .hero-sticker {
    top: 0.3rem;
    right: auto;
    left: calc(100% + 18px);
    width: clamp(56px, 7vw, 88px);
    height: clamp(56px, 7vw, 88px);
    padding: 5px;
  }

  .hero-sticker-percent {
    font-size: clamp(1.1rem, 1.8vw, 1.5rem);
  }

  .hero-sticker-label {
    font-size: 0.5rem;
  }

  .hero-price-line {
    margin-top: 10px;
    gap: 2px;
  }

  .hero-price-line-figures > .amount {
    font-size: clamp(1.9rem, 2.8vw, 2.4rem);
  }

  .hero-price-line-figures .price-strike {
    font-size: clamp(1rem, 1.4vw, 1.25rem);
  }

  /* the struck regular price must read smaller than the launch price beside it */
  .hero-price-line-figures .price-strike .amount {
    font-size: clamp(1.3rem, 1.9vw, 1.7rem);
  }

  .hero .lead {
    margin-top: 12px;
    font-size: 0.9375rem;
    max-width: 42em;
  }

  .hero-note {
    display: none;
  }

  .hero-actions {
    margin-top: 24px;
  }


  .hero-meta {
    margin-top: 18px;
  }

  .hero-reassure {
    margin-top: 12px;
  }

}

/* wide-and-tall viewports (2560x1440 and up): the compact-laptop query above only fires by
   height, so a wide window that is also tall falls through to the base rules, whose character
   caps were tuned for a narrow column and break the slogan into four lines. This one is keyed
   on width alone, comes after the compact query so it wins the cascade whatever the height is,
   and gives the same two-line slogan / one-line kicker structure, scaled up for the extra room.
   It also turns the hero into a real two-column composition: copy stays in its own measure on
   the left, #build-film shifts into a right-hand column at this same breakpoint
   (build-stage.css), so the sticker anchors to the headline instead of floating over the film. */
@media (min-width: 1680px) {
  .hero {
    padding-block: clamp(72px, 7vw, 140px) clamp(80px, 8vw, 150px);
    min-height: 0;
    align-items: center;
  }

  .hero-heading-group {
    max-width: 900px;
  }

  .hero-heading {
    max-width: none;
    font-size: clamp(0.8125rem, 0.6rem + 0.45vw, 1.0625rem);
  }

  .hero-slogan-wrap {
    margin-top: clamp(14px, 1.2vw, 22px);
  }

  .hero-slogan {
    max-width: 21ch;
    font-size: clamp(3.4rem, 3.4vw, 6.75rem);
    line-height: 1;
  }

  .hero-sticker {
    top: 0.2rem;
    right: auto;
    left: calc(100% + 22px);
    width: clamp(78px, 5vw, 120px);
    height: clamp(78px, 5vw, 120px);
  }

  .hero-sticker-percent {
    font-size: clamp(1.5rem, 1.6vw, 2.2rem);
  }

  .hero-price-line-figures > .amount {
    font-size: clamp(2.6rem, 2.6vw, 3.8rem);
  }

  .hero .lead {
    font-size: clamp(1.0625rem, 0.7rem + 0.5vw, 1.375rem);
    max-width: 36em;
  }

  .hero-meta {
    max-width: 920px;
  }
}

@media (min-width: 2200px) {
  .hero-slogan {
    font-size: clamp(5rem, 3vw, 7.5rem);
  }

  .hero-heading {
    font-size: clamp(0.95rem, 0.85rem + 0.25vw, 1.2rem);
  }

  /* fixed mono labels tuned for a 1440px window read as leftover debug text once the window is
     4K; floor them higher at this width without touching the vw-clamped headline sizes above. */
  .label,
  .status,
  .footnote,
  .hero-meta dt,
  .tier-time span,
  .currency a {
    font-size: 0.875rem;
  }

  .lead {
    font-size: clamp(1.25rem, 1vw, 1.5rem);
  }

  h2 {
    font-size: clamp(3.4rem, 5vw, 6.4rem);
  }
}

/* 3D scroll scene (css/scene.css, js/scene.js): styled there, not here. */

.section {
  padding-block: clamp(80px, 11vw, 152px);
}

/* translucent, not solid: the scroll scene sits fixed behind the whole page (scene.css),
   so a full-bleed section tint has to let it through, blurred, like every other glass
   surface. Plain rgba tint everywhere; backdrop-filter added only under @supports, same
   gate the .glass primitive uses. */
.section-tint {
  background: rgba(12, 14, 18, 0.42);
}

.section-ink {
  background: rgba(4, 5, 6, 0.5);
  color: var(--dark-text);
  --ink: var(--dark-text);
  --ink-2: rgba(242, 243, 240, 0.78);
  --muted: var(--dark-muted);
  --line: var(--dark-line);
  --paper: var(--dark);
  --paper-2: var(--dark-2);
}

@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .section-tint,
  .section-ink {
    -webkit-backdrop-filter: blur(var(--blur-sm)) saturate(1.2);
    backdrop-filter: blur(var(--blur-sm)) saturate(1.2);
  }
}

.head {
  max-width: 820px;
  margin-bottom: clamp(40px, 6vw, 72px);
}

@media (min-width: 1680px) {
  .head {
    max-width: 1020px;
  }
}

@media (min-width: 2200px) {
  .head {
    max-width: 1200px;
  }
}

/* only the hero headline sits straight on the background film; every other block of text gets
   a frosted panel so it never fights the moving layers behind it. */
.head,
.footnote,
.pricing-notes,
.care-intro,
.care-notes,
.switches .currency,
.switches .speed,
.footer-inner {
  background: linear-gradient(160deg, rgba(22, 24, 28, 0.62), rgba(10, 11, 13, 0.72));
  border: 1px solid var(--glass-border);
  backdrop-filter: blur(var(--blur-md)) saturate(1.1);
  -webkit-backdrop-filter: blur(var(--blur-md)) saturate(1.1);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.06) inset,
    0 24px 50px -28px rgba(0, 0, 0, 0.7);
}

.head,
.footnote,
.pricing-notes,
.care-intro,
.care-notes,
.footer-inner {
  width: fit-content;
  border-radius: var(--r-xl);
  padding: clamp(18px, 3vw, 30px) clamp(18px, 3.2vw, 34px);
}

@media (max-width: 640px) {
  .head,
  .footnote,
  .pricing-notes,
  .care-intro,
  .care-notes,
  .switches .currency,
  .switches .speed,
  .footer-inner {
    backdrop-filter: blur(var(--blur-sm)) saturate(1.1);
    -webkit-backdrop-filter: blur(var(--blur-sm)) saturate(1.1);
  }
}

.head .lead {
  margin-top: 1.25rem;
}

.head-row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px 48px;
  margin-bottom: clamp(40px, 6vw, 72px);
}

.head-row .head {
  margin-bottom: 0;
}

.footnote {
  margin-top: 28px;
  color: var(--muted);
  text-transform: none;
  letter-spacing: 0;
}

/* ---------- work strip: small glass-framed phone shots, not a portfolio wall ---------- */
.work-strip {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 16px;
  perspective: 1400px;
  padding: 6px 2px 4px;
}

@media (min-width: 761px) and (max-width: 1100px) {
  .work-strip {
    grid-template-columns: repeat(3, 1fr);
  }
}

.work-item {
  position: relative;
  aspect-ratio: 3 / 4;
  padding: 8px;
  border-radius: var(--r-l);
  background: var(--glass);
  border: 1px solid var(--glass-border);
  backdrop-filter: blur(var(--blur-sm)) saturate(1.2);
  -webkit-backdrop-filter: blur(var(--blur-sm)) saturate(1.2);
  box-shadow: 0 24px 50px -24px rgba(0, 0, 0, 0.65);
  text-decoration: none;
  transform: translateZ(0) rotateY(0deg);
  transition: transform 0.5s var(--ease), box-shadow 0.5s var(--ease), border-color 0.5s var(--ease);
}

.work-frame {
  display: block;
  position: relative;
  width: 100%;
  height: 100%;
  border-radius: var(--r-s);
  overflow: hidden;
}

.work-frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top;
  opacity: 0.88;
  transition: opacity 0.4s var(--ease), transform 0.6s var(--ease);
}

.work-caption {
  position: absolute;
  bottom: 10px;
  left: 10px;
  right: 10px;
  padding: 7px 8px;
  border-radius: var(--r-pill);
  background: rgba(10, 11, 14, 0.65);
  border: 1px solid var(--glass-border);
  backdrop-filter: blur(var(--blur-sm));
  -webkit-backdrop-filter: blur(var(--blur-sm));
  font-family: var(--mono);
  font-size: 10px;
  text-align: center;
  color: var(--ink);
  overflow-wrap: anywhere;
  line-height: 1.3;
}

.work-caption-note {
  display: block;
  color: var(--muted);
}

.care-plan-promo {
  margin: 4px 0 0;
  font-size: 0.875rem;
  color: var(--lime);
}

.care-plan-promo .amount {
  font: inherit;
  font-weight: 700;
  letter-spacing: normal;
}

@media (hover: hover) and (pointer: fine) {
  .work-item:hover {
    transform: translateZ(26px) rotateY(-4deg) translateY(-6px);
    border-color: rgba(200, 255, 61, 0.35);
    box-shadow: 0 36px 70px -28px rgba(0, 0, 0, 0.75), 0 0 40px -14px rgba(200, 255, 61, 0.3);
  }

  .work-item:nth-child(even):hover {
    transform: translateZ(26px) rotateY(4deg) translateY(-6px);
  }

  .work-item:hover .work-frame img {
    opacity: 1;
    transform: scale(1.06);
  }
}

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .work-item {
      animation: work-in linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 40%;
    }

    .work-item:nth-child(2) { animation-range: entry 4% cover 44%; }
    .work-item:nth-child(3) { animation-range: entry 8% cover 48%; }
    .work-item:nth-child(4) { animation-range: entry 12% cover 52%; }
    .work-item:nth-child(5) { animation-range: entry 16% cover 56%; }
    .work-item:nth-child(6) { animation-range: entry 20% cover 60%; }
  }
}

@keyframes work-in {
  from { opacity: 0; transform: translateY(24px) scale(0.94); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

@media (max-width: 760px) {
  .work-strip {
    grid-template-columns: repeat(2, 1fr);
    perspective: none;
  }

  .work-item,
  .work-item:hover {
    transform: none;
  }
}

/* ---------- why-me: two glass slabs at depth, "mine" pulled forward and lit ---------- */
/* why-me as paired rows: each topic sits above its own two-column strip, "usual" pushed back,
   "mine" lit lime and floated slightly forward, so the contrast the section exists to show
   never collapses into two separately-stacked lists on a narrow phone. */
.compare-rows {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 10px 0;
}

.compare-row {
  padding: 18px 20px;
  border-radius: var(--r-l);
  background: var(--surface);
  border: 1px solid var(--line);
}

.compare-row-topic {
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--muted);
  margin: 0 0 10px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.compare-row-cells {
  display: grid;
  grid-template-columns: 1fr 1.08fr;
  gap: 12px;
  align-items: stretch;
}

.compare-cell {
  padding: 14px 16px;
  border-radius: var(--r-m);
  background: linear-gradient(160deg, var(--bad-soft), rgba(255, 143, 128, 0.02));
  border: 1px solid rgba(255, 143, 128, 0.35);
}

.compare-cell--mine {
  background: linear-gradient(160deg, rgba(200, 255, 61, 0.14), rgba(200, 255, 61, 0.02));
  border-color: rgba(200, 255, 61, 0.4);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.07) inset, 0 20px 40px -20px rgba(200, 255, 61, 0.24);
}

.compare-cell-label {
  font-family: var(--mono);
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--bad);
  margin: 0 0 6px;
  display: flex;
  align-items: center;
  gap: 5px;
}

.compare-cell-label::before {
  content: "\2715";
  font-size: 0.8em;
}

.compare-cell--mine .compare-cell-label {
  color: var(--lime);
}

.compare-cell--mine .compare-cell-label::before {
  content: "\2713";
}

.compare-text {
  margin: 0;
  font-size: 0.9375rem;
  color: var(--ink-2);
  line-height: 1.45;
}

.compare-cell--mine .compare-text {
  color: var(--ink);
}

@media (max-width: 520px) {
  .compare-row-cells {
    grid-template-columns: 1fr 1fr;
    gap: 8px;
  }

  .compare-cell {
    padding: 10px 12px;
  }

  .compare-text {
    font-size: 0.875rem;
  }
}

.currency {
  display: inline-flex;
  gap: 2px;
  padding: 4px;
  border: 1px solid var(--line);
  border-radius: var(--r-m);
}

.currency a {
  min-width: 56px;
  padding: 9px 12px;
  border-radius: var(--r-s);
  text-align: center;
  text-decoration: none;
  color: var(--ink-2);
  transition: background-color 0.2s, color 0.2s;
}

.currency a:hover {
  background: var(--paper-2);
}

.currency a[aria-current="true"] {
  background: var(--ink);
  color: var(--paper);
}

.switches {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

/* promo strip: a lit glass band above the tiers, the first thing read in the section. The
   percent is the one number a skimming reader takes in, so it leads as a large numeral, with
   the deadline as a strong line beside it and the mechanics as smaller supporting text. */
.promo-strip {
  margin-bottom: 1.75rem;
  padding: 20px 26px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px 26px;
  background: linear-gradient(120deg, rgba(200, 255, 61, 0.14), rgba(200, 255, 61, 0.03));
  border-color: rgba(200, 255, 61, 0.45);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.07) inset,
    0 0 60px -8px rgba(200, 255, 61, 0.45);
}

.promo-strip-figure {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  margin: 0;
  flex-shrink: 0;
}

.promo-strip-kicker {
  font-family: var(--mono);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-2);
}

.promo-strip-percent {
  font-size: clamp(3rem, 7vw, 5.25rem);
  font-weight: 800;
  line-height: 0.95;
  font-stretch: 66%;
  letter-spacing: -0.02em;
  color: var(--lime);
}

.promo-strip-copy {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

.promo-strip-date {
  margin: 0;
  font-weight: 700;
  font-size: clamp(1.1rem, 1.6vw, 1.375rem);
  max-width: 56em;
}

.promo-strip-note {
  margin: 0;
  font-weight: 500;
  font-size: 0.8125rem;
  color: var(--ink-2);
  max-width: 56em;
}

/* ---------- pricing: floating glass slabs at depth, the featured tier closest and lit ---------- */
.pricing-stage {
  display: grid;
  gap: 20px;
  perspective: 1800px;
}

@media (min-width: 1000px) {
  .pricing-stage {
    grid-template-columns: repeat(3, 1fr);
    align-items: end;
    gap: 28px;
    padding-top: 10px;
  }
}

.tier {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: clamp(26px, 3vw, 34px);
  transform: translateZ(0);
  transition: transform 0.6s var(--ease), box-shadow 0.6s var(--ease);
}

@media (min-width: 1000px) {
  .tier[data-depth="back"] { transform: translateZ(-60px) translateY(18px) scale(0.96); opacity: 0.85; }
  .tier[data-depth="mid"] { transform: translateZ(0); }
  .tier[data-depth="front"].tier-featured {
    transform: translateZ(40px) translateY(-18px) scale(1.04);
    background: linear-gradient(165deg, rgba(200, 255, 61, 0.14), rgba(200, 255, 61, 0.03));
    border-color: rgba(200, 255, 61, 0.4);
    box-shadow: 0 1px 0 rgba(255, 255, 255, 0.07) inset, 0 40px 80px -28px rgba(200, 255, 61, 0.3), 0 0 60px -10px rgba(200, 255, 61, 0.18);
  }

  @supports (animation-timeline: view()) {
    @media (prefers-reduced-motion: no-preference) {
      .tier[data-depth="back"] { animation: tier-rock-back linear both; animation-timeline: view(); animation-range: entry 10% cover 90%; }
      .tier[data-depth="mid"] { animation: tier-rock-mid linear both; animation-timeline: view(); animation-range: entry 10% cover 90%; }
    }
  }

  @keyframes tier-rock-back {
    0% { transform: translateZ(-60px) translateY(18px) scale(0.96) rotateY(7deg); }
    50% { transform: translateZ(-60px) translateY(18px) scale(0.96) rotateY(-4deg); }
    100% { transform: translateZ(-60px) translateY(18px) scale(0.96) rotateY(4deg); }
  }

  @keyframes tier-rock-mid {
    0% { transform: translateZ(0) rotateY(-5deg); }
    50% { transform: translateZ(0) rotateY(3deg); }
    100% { transform: translateZ(0) rotateY(-3deg); }
  }

  .tier:hover { transform: translateZ(10px) translateY(-6px); }
  .tier[data-depth="front"].tier-featured:hover { transform: translateZ(50px) translateY(-26px) scale(1.05); }
  .tier[data-depth="back"]:hover { transform: translateZ(-50px) translateY(10px) scale(0.98); opacity: 0.95; }
}

.tier-badge {
  position: absolute;
  top: -13px;
  left: 26px;
  font-family: var(--mono);
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  background: var(--lime);
  color: var(--lime-ink);
  padding: 5px 12px;
  border-radius: var(--r-pill);
  font-weight: 700;
}

/* corner ribbon: a lime diagonal band every card carries, so the discount reads before anyone
   gets to the price row. Positioned top-right, rotated into the corner it clips with the card's
   own border-radius. */
.tier-ribbon {
  position: absolute;
  top: 16px;
  right: -34px;
  z-index: 1;
  width: 140px;
  padding: 5px 0;
  background: var(--lime);
  color: var(--lime-ink);
  font-family: var(--mono);
  font-weight: 800;
  font-size: 0.8125rem;
  letter-spacing: 0.02em;
  text-align: center;
  transform: rotate(32deg);
  box-shadow: 0 10px 22px -10px rgba(200, 255, 61, 0.5);
}

.tier-featured .tier-ribbon {
  font-size: 0.875rem;
  padding: 6px 0;
}

.tier-pitch {
  margin-top: 0.9rem;
  color: var(--ink-2);
  min-height: 3.2em;
}

.price {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 10px;
  margin: 1.6rem 0 0.4rem;
}

.amount {
  font-weight: 800;
  font-stretch: 66%;
  font-size: clamp(3rem, 5vw, 4.2rem);
  line-height: 0.9;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums lining-nums;
}

.price-small {
  font-family: var(--mono);
  font-size: 0.75rem;
  color: var(--muted);
}

/* "od"/"from" sits before the big number on the baseline-aligned .price row, which leaves it
   floating low against the number's cap-height. Nudging it up reads it as one phrase. */
.price > .price-small:first-child {
  align-self: flex-start;
  margin-top: 0.3em;
}

.tier-time {
  display: flex;
  gap: 8px;
  align-items: baseline;
  padding-bottom: 1.4rem;
  margin-bottom: 1.4rem;
  border-bottom: 1px dashed var(--line-strong);
  font-weight: 650;
}

.tier-time span {
  color: var(--muted);
}

.tier-price-row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px 12px;
}

/* the regular price, struck through in lime so it reads as superseded, not current, with the
   label right beside it so nobody mistakes it for a past price. <s> hides its own number from
   assistive tech (see regularStrike in home.ts) so the label is the only thing announced. */
.tier-price-regular {
  margin: 0 0 0.5rem;
  font-size: 0.95rem;
  color: var(--ink-2);
}

.tier-price-regular-label {
  display: block;
  font-family: var(--mono);
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-2);
  margin-bottom: 0.2rem;
}

/* a drawn line instead of text-decoration: line-through sits at the <s> element's own font
   metrics, so it rode far above the middle of the much larger .amount inside it. */
.price-strike {
  position: relative;
  display: inline-block;
  text-decoration: none;
  font-weight: 650;
}

.price-strike::after {
  content: "";
  position: absolute;
  left: -0.08em;
  right: -0.08em;
  top: 54%;
  height: var(--strike-w, 2px);
  border-radius: 2px;
  background: var(--lime);
  transform: translateY(-50%) rotate(-2deg);
  pointer-events: none;
}

@media (forced-colors: active) {
  .price-strike {
    text-decoration: line-through;
  }

  .price-strike::after {
    display: none;
  }
}

/* roughly 60% of the launch price's clamp() below: big enough to read as a real price, still
   clearly secondary to the number that matters. */
.tier-price-regular .price-strike {
  font-size: clamp(1.8rem, 2.6vw, 2.6rem);
  --strike-w: 3px;
}

.tier-price-regular .price-strike .price-small {
  margin-right: 0.3em;
}

.tier-price-regular .amount {
  font-size: inherit;
  font-weight: inherit;
  font-stretch: normal;
  letter-spacing: normal;
  color: var(--ink-2);
}

.tier-discount-badge {
  font-family: var(--mono);
  font-size: 0.8125rem;
  font-weight: 800;
  letter-spacing: 0.02em;
  padding: 5px 12px;
  border-radius: var(--r-pill);
  background: var(--lime);
  color: var(--lime-ink);
  align-self: center;
}

.tier-featured .tier-discount-badge {
  font-size: 0.9375rem;
  padding: 6px 14px;
}

/* the saving as a solid pill, not plain coloured text: a second lime shape in the card besides
   the ribbon, so the amount saved reads as a fact, not a footnote. */
.tier-savings {
  display: inline-block;
  margin: 0.3rem 0 1rem;
  padding: 5px 12px;
  border-radius: var(--r-pill);
  background: var(--lime);
  color: var(--lime-ink);
  font-size: 0.875rem;
  font-weight: 800;
}

/* bumped up from the shared .amount size: the standard price is the number this section exists
   to show, so it reads larger than the plain price everywhere else on the page. */
.tier-price-slot--standard .tier-price-row .price .amount {
  font-size: clamp(3.4rem, 5.8vw, 4.8rem);
}

/* express is a secondary line by default, standard owns the big number. no-JS keeps this
   state forever; the speed switch only adds .speed-express on the .tier to swap the emphasis. */
.tier-price-slot--express {
  margin: -0.6rem 0 1rem;
  padding: 10px 14px;
  border-radius: var(--r-m);
  background: rgba(255, 255, 255, 0.03);
  border: 1px dashed var(--line-strong);
}

.tier-price-slot--express .price {
  margin: 0.3rem 0 0.2rem;
}

.tier-price-slot--express .tier-price-row .amount {
  font-size: 1.3rem;
  font-stretch: normal;
}

.tier-price-slot--express .tier-time {
  padding-bottom: 0;
  margin-bottom: 0;
  border-bottom: none;
  font-size: 0.85rem;
}

.tier-express-tag {
  margin: 0;
  font-family: var(--mono);
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-2);
}

/* keeps the launch discount visible on the express line too, so switching to express never
   reads as losing the promo, just a smaller-scale reminder than the standard badge. */
.tier-express-promo-badge {
  font-family: var(--mono);
  font-size: 0.625rem;
  letter-spacing: 0.02em;
  text-transform: none;
  color: var(--lime);
}

/* express is an add-on, not a second promotion: no lime, no badge, so it never competes
   visually with the launch price above it. Hidden entirely once the offer ends would be wrong
   too, express always exists, so only .tier-promo-extra (the launch-specific pieces) hides. */
.tier.speed-express .tier-promo-extra {
  display: none;
}

/* promo elements express borrows from the standard slot's markup (tier-price-regular,
   tier-discount-badge, tier-savings): present at every width so there is no no-JS gap, but
   hidden until the speed switch actually puts express in charge of the card's main price, so
   the compact default express line stays a single caption + plain price. */
.tier-price-slot--express .tier-price-regular,
.tier-price-slot--express .tier-price-row .tier-discount-badge,
.tier-price-slot--express .tier-savings {
  display: none;
}

.tier.speed-express .tier-price-slot--express .tier-price-regular {
  display: block;
}

.tier.speed-express .tier-price-slot--express .tier-price-row .tier-discount-badge {
  display: inline-flex;
}

.tier.speed-express .tier-price-slot--express .tier-savings {
  display: inline-block;
}

.tier.speed-express .tier-price-slot--standard {
  margin-bottom: 1rem;
  padding: 10px 14px;
  border-radius: var(--r-m);
  background: rgba(255, 255, 255, 0.03);
  border: 1px dashed var(--line-strong);
}

.tier.speed-express .tier-price-slot--standard .amount {
  font-size: 1.3rem;
}

.tier.speed-express .tier-price-slot--standard .tier-time {
  padding-bottom: 0;
  margin-bottom: 0;
  border-bottom: none;
  font-size: 0.85rem;
}

.tier.speed-express .tier-price-slot--express {
  margin: 0 0 0.4rem;
  padding: 0;
  background: none;
  border: none;
}

.tier.speed-express .tier-price-slot--express .price {
  margin: 1.6rem 0 0.4rem;
}

.tier.speed-express .tier-price-slot--express .tier-price-row .amount {
  font-size: clamp(3rem, 5vw, 4.2rem);
  font-stretch: 66%;
}

.tier.speed-express .tier-price-slot--express .tier-time {
  padding-bottom: 1.4rem;
  margin-bottom: 1.4rem;
  border-bottom: 1px dashed var(--line-strong);
  font-size: 1rem;
}

.checks {
  list-style: none;
  margin: 0 0 1.5rem;
  padding: 0;
}

.checks li {
  position: relative;
  padding: 0.6rem 0 0.6rem 1.4em;
  border-bottom: 1px dashed var(--line);
  font-size: 0.98rem;
  line-height: 1.45;
}

.checks li:last-child {
  border-bottom: none;
}

.checks li::before {
  content: "\2013";
  position: absolute;
  left: 0;
  color: var(--ink-2);
  font-family: var(--mono);
  font-weight: 600;
}

.tier-note {
  margin: 0.75rem 0 0;
  padding: 10px 12px;
  border-radius: var(--r-m);
  background: rgba(200, 255, 61, 0.06);
  border: 1px solid rgba(200, 255, 61, 0.2);
  font-size: 0.8125rem;
  color: var(--ink-2);
}

.tier-excluded {
  margin-top: auto;
  padding-top: 1rem;
  margin-bottom: 1.5rem;
  border-top: 1px dashed var(--line-strong);
  font-size: 0.875rem;
  /* --muted (50% white) reads fine on the flat page background but washes out on the
     lime glow behind .tier-featured, so this line, which carries real price-exclusion
     content, needs the higher-contrast token here. */
  color: var(--ink-2);
}

.tier-excluded span {
  font-weight: 650;
  color: var(--ink);
}

.tier .button {
  width: 100%;
}

.pricing-notes {
  display: grid;
  gap: 0.35rem;
  margin-top: 2rem;
  color: var(--ink-2);
  font-size: 0.9375rem;
}

.note-strong {
  color: var(--ink);
  font-weight: 650;
}

.note-strong::before {
  content: "+";
  display: inline-grid;
  place-items: center;
  width: 1.3em;
  height: 1.3em;
  margin-right: 0.5em;
  border-radius: 50%;
  background: var(--lime);
  color: var(--lime-ink);
  font-weight: 800;
}

.care {
  margin-top: clamp(48px, 7vw, 88px);
}

.care h3 {
  font-size: clamp(2rem, 3.6vw, 3rem);
  margin-bottom: 1rem;
}

.care-intro > p:not(.label) {
  color: var(--ink-2);
  max-width: 42em;
}

.care-notes {
  margin-top: 24px;
}

.care-notes > :first-child {
  margin-top: 0;
}

.care-terms,
.care-smallchange,
.care-hourly-note {
  margin-top: 1rem;
  font-size: 0.9375rem;
  color: var(--ink-2);
  max-width: 42em;
}

/* the form itself now sits right after the hero, so this is for anyone who read the whole
   offer first and wants back to it without hunting for the sticky bar or scrolling up by hand. */
.pricing-back-to-form {
  display: inline-flex;
  margin-top: 2.5rem;
  font-weight: 700;
}

.care-plans {
  display: grid;
  gap: 24px;
  margin-top: 2rem;
}

@media (min-width: 720px) {
  .care-plans {
    grid-template-columns: 1fr 1fr;
    align-items: stretch;
  }
}

.care-plan {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: clamp(24px, 3vw, 32px);
}

.care-plan h4 {
  font-size: 1.5rem;
}

.care-plan-premium {
  border-color: var(--lime);
}

.price-care .amount {
  font-size: clamp(2rem, 3.2vw, 2.6rem);
}

.checks-care {
  margin: 0;
  flex: 1;
}

.checks-care li {
  font-size: 1rem;
}

.care-plan .button {
  margin-top: auto;
  width: 100%;
}

/* process: glass cards along a lit rail. the rail fill draws in with scroll position
   (dual path: animation-timeline where supported, .is-drawn via [data-spine] IO otherwise),
   each step dot fills on its own a beat later via the generic [data-build] IO. */
.process-rail {
  position: relative;
  display: flex;
  gap: 20px;
  overflow-x: auto;
  padding: 8px 4px 28px;
  scroll-snap-type: x proximity;
  list-style: none;
  margin: 0;
  scrollbar-width: none;
}

.process-rail::-webkit-scrollbar {
  display: none;
}

.process-rail::before {
  content: "";
  position: absolute;
  top: 47px;
  left: 4px;
  right: 4px;
  height: 2px;
  background: rgba(200, 255, 61, 0.14);
}

.process-rail::after {
  content: "";
  position: absolute;
  top: 47px;
  left: 4px;
  height: 2px;
  width: calc(100% - 8px);
  background: linear-gradient(90deg, var(--lime), rgba(200, 255, 61, 0.25));
  box-shadow: 0 0 16px 1px rgba(200, 255, 61, 0.35);
  transform: scaleX(0);
  transform-origin: left center;
}

.js .process-rail.is-drawn::after {
  transform: scaleX(1);
  transition: transform var(--m-slow) var(--ease);
}

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .process-rail::after {
      animation: rail-fill linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 80%;
    }
  }
}

@keyframes rail-fill {
  from { transform: scaleX(0.01); }
  to { transform: scaleX(1); }
}

.process-card {
  position: relative;
  scroll-snap-align: start;
  flex: 0 0 260px;
  padding: 26px 22px;
}

.process-step-dot {
  display: block;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--paper);
  border: 2px solid var(--lime);
  box-shadow: 0 0 0 4px rgba(200, 255, 61, 0.12);
  margin-bottom: 20px;
  position: relative;
}

.process-step-dot::after {
  content: "";
  position: absolute;
  inset: 2px;
  border-radius: 50%;
  background: var(--lime);
  transform: scale(0);
}

.js .process-card[data-build].is-built .process-step-dot::after {
  transform: scale(1);
  transition: transform var(--m-base) var(--ease);
}

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .process-step-dot::after {
      animation: dot-fill linear both;
      animation-timeline: view();
      animation-range: entry 10% cover 50%;
    }
  }
}

@keyframes dot-fill {
  from { transform: scale(0); }
  to { transform: scale(1); }
}

.process-when {
  font-family: var(--mono);
  font-size: 0.75rem;
  color: var(--lime);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.process-title {
  font-size: 1.2rem;
  margin-top: 10px;
}

.process-body {
  margin-top: 10px;
  color: var(--ink-2);
}

@media (max-width: 640px) {
  .process-rail { gap: 14px; }
  .process-card { flex-basis: 78vw; }
}

.voices {
  display: grid;
  gap: 20px;
}

@media (min-width: 900px) {
  .voices {
    grid-template-columns: repeat(2, 1fr);
  }
}

.voice {
  margin: 0;
  padding: clamp(24px, 3vw, 40px);
  border-radius: var(--r-xl);
  background: var(--surface);
  border: 1px solid var(--line);
}

.voice blockquote {
  margin: 0 0 1.5rem;
  font-size: clamp(1.25rem, 2vw, 1.6rem);
  line-height: 1.3;
  font-weight: 550;
}

.voice figcaption {
  color: var(--muted);
  font-size: 0.9375rem;
}

.about-grid {
  display: grid;
  gap: 32px clamp(32px, 6vw, 96px);
  align-items: start;
}

/* smoked, textured glass: darker and more opaque than .glass, with a grain layer so it reads
   as rough frosted glass rather than a clear pane. */
.glass-smoke {
  padding: clamp(20px, 5vw, 64px);
  background:
    radial-gradient(120% 90% at 0% 0%, rgba(255, 255, 255, 0.07), transparent 55%),
    linear-gradient(165deg, rgba(22, 24, 28, 0.68), rgba(8, 9, 11, 0.8));
  border-color: rgba(255, 255, 255, 0.11);
  backdrop-filter: blur(var(--blur-lg)) saturate(0.9) brightness(0.75);
  -webkit-backdrop-filter: blur(var(--blur-lg)) saturate(0.9) brightness(0.75);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.1) inset,
    0 -1px 0 rgba(0, 0, 0, 0.5) inset,
    0 40px 80px -36px rgba(0, 0, 0, 0.8),
    0 14px 30px -14px rgba(0, 0, 0, 0.6);
}

.glass-smoke::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: url("../img/grain.svg") 0 0 / 220px 220px;
  opacity: 0.09;
  pointer-events: none;
}

@media (max-width: 640px) {
  .glass-smoke {
    backdrop-filter: blur(var(--blur-md)) saturate(0.9) brightness(0.75);
    -webkit-backdrop-filter: blur(var(--blur-md)) saturate(0.9) brightness(0.75);
  }
}

@media (min-width: 820px) {
  .about-grid {
    grid-template-columns: 260px minmax(0, 780px);
  }
}

@media (min-width: 1680px) {
  .about-grid {
    grid-template-columns: 320px minmax(0, 980px);
  }
}

.portrait {
  margin: 0;
  width: clamp(160px, 40vw, 260px);
}

.portrait img {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: var(--r-xl);
  filter: grayscale(1) contrast(1.05);
  transition: filter 0.5s;
}

.portrait:hover img {
  filter: grayscale(0);
}

.portrait figcaption {
  margin-top: 12px;
  font-family: var(--mono);
  font-size: 0.75rem;
  color: var(--muted);
  text-transform: uppercase;
}

.about h2 {
  font-size: clamp(2.2rem, 4.6vw, 4rem);
  margin-bottom: 1.5rem;
}

.about-text {
  font-size: 1.15rem;
  color: var(--ink-2);
  margin-bottom: 1rem;
  max-width: 36em;
}

.about .text-link {
  margin-top: 0.75rem;
}

.faq-grid {
  display: grid;
  gap: 24px clamp(32px, 6vw, 96px);
}

@media (min-width: 980px) {
  .faq-grid {
    grid-template-columns: 0.8fr 1.4fr;
    align-items: start;
  }
}

.faq {
  display: grid;
  gap: 12px;
}

.faq-item {
  padding: 0 24px;
  transition: border-color 0.3s var(--ease), background-color 0.3s var(--ease);
}

.faq-item[open] {
  border-color: var(--glass-strong);
}

.faq summary {
  position: relative;
  padding: 22px 52px 22px 0;
  font-weight: 750;
  font-stretch: 85%;
  font-size: clamp(1.1rem, 1.6vw, 1.3rem);
  line-height: 1.3;
  cursor: pointer;
  list-style: none;
}

.faq summary::-webkit-details-marker {
  display: none;
}

.faq summary::after {
  content: "+";
  position: absolute;
  right: 0;
  top: 50%;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  margin-top: -17px;
  border-radius: 50%;
  border: 1px solid var(--line);
  font-weight: 400;
  font-size: 1.3rem;
  transition: transform 0.3s var(--ease), background-color 0.2s, border-color 0.2s;
}

.faq-item[open] summary::after {
  transform: rotate(45deg);
  background: var(--lime);
  border-color: var(--lime);
  color: var(--lime-ink);
}

.faq details p {
  padding: 0 52px 24px 0;
  color: var(--ink-2);
  max-width: 42em;
}

/* contact is the one section that matters most, so it gets its own full-bleed, opaque band
   (every other section is a translucent tint over the fixed scene, see .section-tint/-ink
   above) rather than blending into whatever sits above or below it. The hairline edges are the
   section's one allowed lime accent, not a border: a plain 1px line would read as flat. */
.contact {
  position: relative;
  background: var(--dark);
  color: var(--dark-text);
  --ink: var(--dark-text);
  --ink-2: rgba(242, 243, 240, 0.78);
  --muted: var(--dark-muted);
  --line: var(--dark-line);
  --paper: var(--dark);
  --paper-2: var(--dark-2);
  --surface: var(--dark-2);
}

.contact::before,
.contact::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(200, 255, 61, 0.5), transparent);
}

.contact::before {
  top: 0;
}

.contact::after {
  bottom: 0;
}

.contact-grid {
  display: grid;
  gap: clamp(32px, 5vw, 72px);
  align-items: start;
}

@media (min-width: 1040px) {
  .contact-grid {
    grid-template-columns: 1fr 1.35fr;
  }

  .contact-intro {
    position: sticky;
    top: 110px;
  }
}

/* at this width the right-hand form is reliably taller than the left column's own content,
   so sticking it to the top leaves a bare gap below it; centering it against the form's
   height instead reads as a deliberate split rather than a leftover offset. */
@media (min-width: 1680px) {
  .contact-grid {
    align-items: center;
  }
}

.contact-intro h2 {
  font-size: clamp(2.8rem, 6.4vw, 5.6rem);
}

.contact-intro .lead {
  margin: 1.4rem 0 1.6rem;
}

/* same dotted-list pattern as .hero-reassure above: the handful of things worth knowing
   before filling anything in, each line short enough to scan in passing. */
.contact-reassure {
  display: grid;
  gap: 10px;
  margin: 0 0 1.8rem;
  max-width: 480px;
  list-style: none;
  padding: 0;
}

.contact-reassure li {
  position: relative;
  padding-left: 1.5em;
  font-size: 0.9375rem;
  color: var(--ink-2);
}

.contact-reassure li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.5em;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--lime);
  box-shadow: 0 0 10px 1px rgba(200, 255, 61, 0.4);
}

.contact-intro .muted a {
  font-weight: 700;
}

.muted {
  color: var(--muted);
}

.contact-whatsapp {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4em;
  margin-top: 10px;
}

.contact-whatsapp a {
  white-space: nowrap;
}

.contact-whatsapp-note {
  margin-top: 2px;
  font-size: 0.8125rem;
}

/* .inquiry carries .glass for the frosted panel (background, border, blur, shadow); this rule
   adds the grid layout plus its own lime-tinted border, surface and glow, brighter than a plain
   .glass panel, so the one thing a visitor is meant to act on reads as the obvious focal point
   of the section rather than just another dark surface among several. */
.inquiry {
  display: grid;
  gap: 22px;
  padding: clamp(22px, 3.5vw, 44px);
  background: linear-gradient(165deg, rgb(200 255 61 / 0.08), var(--glass) 60%);
  border-color: rgb(200 255 61 / 0.3);
  box-shadow:
    0 0 0 1px rgb(200 255 61 / 0.12),
    0 0 70px -20px rgb(200 255 61 / 0.3),
    0 40px 90px -40px rgba(0, 0, 0, 0.65),
    0 1px 0 rgba(255, 255, 255, 0.07) inset;
}

.field-row {
  display: grid;
  gap: 22px;
}

@media (min-width: 640px) {
  .field-row {
    grid-template-columns: 1fr 1fr;
  }
}

.field {
  display: grid;
  gap: 7px;
  margin: 0;
  padding: 0;
  border: 0;
  min-width: 0;
}

.field label,
.field legend {
  font-size: 0.9375rem;
  font-weight: 650;
  padding: 0;
}

.field legend {
  margin-bottom: 7px;
}

.optional {
  font-family: var(--mono);
  font-size: 0.6875rem;
  font-weight: 400;
  color: var(--muted);
  margin-left: 6px;
  text-transform: uppercase;
}

.hint {
  font-size: 0.875rem;
  color: var(--muted);
  margin-top: -3px;
}

input[type="text"],
input[type="email"],
input[type="tel"],
select,
textarea {
  width: 100%;
  min-height: 52px;
  padding: 13px 16px;
  border: 1px solid var(--line);
  border-radius: var(--r-l);
  background: var(--paper);
  color: var(--ink);
  font: 400 1rem/1.4 var(--sans);
  transition: border-color 0.2s, box-shadow 0.2s;
}

textarea {
  resize: vertical;
  min-height: 140px;
  line-height: 1.55;
}

select {
  appearance: none;
  padding-right: 42px;
  background-image: linear-gradient(45deg, transparent 50%, var(--muted) 50%), linear-gradient(135deg, var(--muted) 50%, transparent 50%);
  background-position: calc(100% - 22px) 23px, calc(100% - 17px) 23px;
  background-size: 5px 5px;
  background-repeat: no-repeat;
}

::placeholder {
  color: var(--muted);
  opacity: 0.7;
}

input:hover,
select:hover,
textarea:hover {
  border-color: var(--muted);
}

input:focus,
select:focus,
textarea:focus {
  outline: none;
  border-color: var(--lime);
  box-shadow: 0 0 0 3px rgb(212 242 74 / 0.25);
}

.field-invalid input,
.field-invalid textarea,
[aria-invalid="true"] {
  border-color: var(--error);
}

.field-error {
  font-size: 0.875rem;
  font-weight: 650;
  color: var(--error);
}

.form-summary {
  padding: 14px 16px;
  border-left: 3px solid var(--error);
  border-radius: var(--r-s);
  background: color-mix(in srgb, var(--error) 14%, transparent);
  font-weight: 650;
}

.trap {
  position: absolute;
  left: -10000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.chip-list,
.radio-list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.chip,
.radio {
  position: relative;
  cursor: pointer;
}

.chip input,
.radio input {
  position: absolute;
  inset: 0;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.chip span,
.radio span {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  padding: 8px 16px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  font-size: 0.9375rem;
  font-weight: 550;
  transition: background-color 0.2s, border-color 0.2s, color 0.2s;
}

.chip span::before {
  content: "+";
  color: var(--muted);
}

.chip:hover span,
.radio:hover span {
  border-color: var(--muted);
}

.chip input:checked + span,
.radio input:checked + span {
  background: var(--lime);
  border-color: var(--lime);
  color: var(--lime-ink);
}

.chip input:checked + span::before {
  content: "✓";
  color: inherit;
}

.radio span::before {
  content: "";
  width: 12px;
  height: 12px;
  border-radius: 50%;
  border: 1.5px solid currentColor;
}

.radio input:checked + span::before {
  background: currentColor;
  box-shadow: inset 0 0 0 2px var(--lime);
}

.chip input:focus-visible + span,
.radio input:focus-visible + span,
.check input:focus-visible + span {
  outline: 2px solid var(--lime);
  outline-offset: 3px;
}

.dropzone {
  position: relative;
  display: grid;
  place-items: center;
  min-height: 104px;
  padding: 20px;
  border: 1.5px dashed var(--line);
  border-radius: var(--r-l);
  text-align: center;
  transition: border-color 0.2s, background-color 0.2s;
}

.dropzone input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  cursor: pointer;
}

.dropzone:hover,
.dropzone.is-over {
  border-color: var(--lime);
  background: rgb(212 242 74 / 0.08);
}

.dropzone:focus-within {
  border-color: var(--lime);
  box-shadow: 0 0 0 3px rgb(212 242 74 / 0.25);
}

.dropzone-text {
  color: var(--muted);
  font-size: 0.9375rem;
}

.dropzone-text span {
  color: var(--ink);
  font-weight: 650;
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.file-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 6px;
}

.file-list:empty {
  display: none;
}

.file-list li {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 8px 8px 14px;
  border: 1px solid var(--line);
  border-radius: var(--r-m);
  font-size: 0.9375rem;
}

.file-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.file-size {
  font-family: var(--mono);
  color: var(--muted);
  font-size: 0.75rem;
}

.file-remove {
  border: 0;
  background: none;
  color: var(--muted);
  font: 650 0.8125rem var(--sans);
  padding: 6px 8px;
  border-radius: var(--r-s);
  cursor: pointer;
}

.file-remove:hover {
  color: var(--error);
  background: var(--paper);
}

.check {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  font-weight: 400 !important;
  font-size: 0.9375rem !important;
  cursor: pointer;
}

.check input {
  position: absolute;
  opacity: 0;
}

.check span {
  position: relative;
  padding-left: 34px;
  color: var(--ink-2);
}

.check span::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  width: 22px;
  height: 22px;
  border: 1.5px solid var(--muted);
  border-radius: var(--r-s);
  transition: background-color 0.2s, border-color 0.2s;
}

.check input:checked + span::before {
  background: var(--lime);
  border-color: var(--lime);
}

.check input:checked + span::after {
  content: "";
  position: absolute;
  left: 7px;
  top: 6px;
  width: 9px;
  height: 5px;
  border-left: 2px solid var(--lime-ink);
  border-bottom: 2px solid var(--lime-ink);
  transform: rotate(-45deg);
}

.form-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px;
}

.form-actions .button {
  min-width: 240px;
}

.form-ownership-note {
  margin: 0 0 1.25rem;
  font-size: 0.8125rem;
  color: var(--muted);
}

.reply-note {
  font-family: var(--mono);
  font-size: 0.75rem;
  color: var(--muted);
}

.progress {
  flex: 1;
  min-width: 120px;
  height: 4px;
  border-radius: var(--r-xxs);
  background: var(--line);
  overflow: hidden;
}

.progress span {
  display: block;
  width: 0;
  height: 100%;
  background: var(--lime);
  transition: width 0.2s;
}

/* upload progress steps, in 5% increments: a class per step instead of bar.style.width, per CSP */
.progress span.p-0 { width: 0%; }
.progress span.p-5 { width: 5%; }
.progress span.p-10 { width: 10%; }
.progress span.p-15 { width: 15%; }
.progress span.p-20 { width: 20%; }
.progress span.p-25 { width: 25%; }
.progress span.p-30 { width: 30%; }
.progress span.p-35 { width: 35%; }
.progress span.p-40 { width: 40%; }
.progress span.p-45 { width: 45%; }
.progress span.p-50 { width: 50%; }
.progress span.p-55 { width: 55%; }
.progress span.p-60 { width: 60%; }
.progress span.p-65 { width: 65%; }
.progress span.p-70 { width: 70%; }
.progress span.p-75 { width: 75%; }
.progress span.p-80 { width: 80%; }
.progress span.p-85 { width: 85%; }
.progress span.p-90 { width: 90%; }
.progress span.p-95 { width: 95%; }
.progress span.p-100 { width: 100%; }

/* stepped form: progressive enhancement over the single <form> above (form.ts, site.js). With
   JS off, nothing here hides a .form-step: every step is just a section of one long page, in
   document order. Once .js lands on <html>, only .is-active shows; which step starts active is
   decided server-side (form.ts), so there is no flash of the whole form before the stepper
   takes over. */
.js .form-step:not(.is-active) {
  display: none;
}

.form-step {
  display: grid;
  gap: 18px;
}

.step-heading {
  font-size: clamp(1.5rem, 3.2vw, 2rem);
  display: flex;
  align-items: baseline;
  gap: 14px;
  flex-wrap: wrap;
}

/* the consent clause that replaced the checkbox on "contact" and "ready" (see form.ts): plain
   text under whichever button actually sends the contact, not a control to fill in. */
.step-consent-note {
  margin: 0;
  font-size: 0.8125rem;
  color: var(--muted);
}

.step-consent-note a {
  color: var(--ink-2);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

/* step 2's "Wyślij kontakt"/"Send my contact" while its fetch to /api/lead is in flight. */
.step-next.is-busy {
  pointer-events: none;
  opacity: 0.7;
}

.step-change {
  font-family: var(--mono);
  font-size: 0.75rem;
  font-weight: 400;
  color: var(--muted);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.step-body-text {
  color: var(--ink-2);
  margin: -8px 0 0;
}

/* back link, step counter, aria-live announcer: do nothing without JS (there is no "current
   step" to count or go back from), so this stays hidden until .js confirms the stepper runs. */
.step-chrome {
  display: none;
}

.js .step-chrome {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: -4px;
}

.step-back {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--muted);
  text-decoration: none;
  font-size: 0.875rem;
  font-weight: 650;
}

.step-back:hover {
  color: var(--ink);
}

.step-progress {
  font-family: var(--mono);
  font-size: 0.75rem;
  color: var(--muted);
  letter-spacing: 0.02em;
}

.step-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px;
}

.step-actions .button {
  min-width: 180px;
}

.step-send {
  border-color: transparent;
  background: transparent;
  color: var(--muted);
  text-decoration: underline;
  text-underline-offset: 0.2em;
  min-height: 44px;
  min-width: 0;
  padding: 0 0.4rem;
}

.step-send:hover {
  color: var(--ink);
}

/* step 1's five choices, tap-sized: same checked/hover states as .chip above, just a bigger
   surface and a left-aligned label instead of a pill. */
.tile-list {
  display: grid;
  grid-template-columns: 1fr;
  gap: 10px;
}

@media (min-width: 480px) {
  .tile-list {
    grid-template-columns: 1fr 1fr;
  }
}

.tile span {
  width: 100%;
  min-height: 64px;
  padding: 16px 20px;
  border-radius: var(--r-l);
  justify-content: space-between;
  font-size: 1rem;
}

.tile span::before {
  order: 2;
}

/* tappable beyond just a border change: a lime tint fills the tile on hover, the same colour
   its checked state already uses, so hover previews what tapping it does. */
.tile:hover span {
  border-color: var(--lime);
  background: rgb(200 255 61 / 0.08);
}

/* step 2's combined phone/e-mail field. It has no name attribute (see form.ts), so with JS off
   it would sit there doing nothing if shown; it only appears once .js confirms site.js is there
   to sync it into the real #email/#phone pair below, which is what the server actually reads
   and what a JS-off visitor sees and fills directly instead. */
.contact-combined {
  display: none;
}

.js .contact-combined {
  display: grid;
}

.contact-combined input {
  font-size: 1.0625rem;
}

.js .real-contact-fields.is-folded {
  display: none;
}

@media (prefers-reduced-motion: no-preference) {
  .js .form-step.is-active {
    animation: step-in var(--m-base) var(--ease);
  }

  @keyframes step-in {
    from {
      opacity: 0;
      transform: translateY(10px);
    }
  }
}

.sticky-cta {
  position: fixed;
  left: 12px;
  right: 12px;
  bottom: max(12px, env(safe-area-inset-bottom));
  z-index: 25;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 8px 8px 18px;
  border-radius: var(--r-pill);
  background: rgba(10, 11, 14, 0.75);
  color: var(--ink);
  transition: transform 0.35s var(--ease), opacity 0.35s;
}

.sticky-cta p {
  font-weight: 700;
  font-stretch: 85%;
}

.sticky-cta span:first-child:not(.sticky-tier-name) {
  font-family: var(--mono);
  font-size: 0.6875rem;
  font-weight: 400;
  color: var(--muted);
  text-transform: uppercase;
}

/* the tier name has to share the line with a price and a badge at 320px, so it gets the
   narrower sans face instead of mono and no letter-spacing, rather than shrinking the number
   or the badge, which are the two things the line exists to show. */
.sticky-tier-name {
  font-family: var(--sans);
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--muted);
  white-space: nowrap;
}

/* the three tier slabs stack in the same grid cell so the container sizes to the tallest one
   and the active slab can crossfade over the others without a layout jump. */
.sticky-price {
  position: relative;
  display: grid;
  flex: 1;
  min-width: 0;
}

.sticky-tier {
  grid-area: 1 / 1;
  min-width: 0;
  opacity: 0;
  pointer-events: none;
}

.sticky-tier.is-active {
  opacity: 1;
  pointer-events: auto;
}

@media (prefers-reduced-motion: no-preference) {
  .sticky-tier {
    transition: opacity 0.25s ease;
  }
}

/* name above, price and badge on their own row below: keeps the "Wyceń" button from crowding
   into the one tier (Custom, with its extra "from") that doesn't fit next to it on one line. */
.sticky-line {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}

.sticky-price-row {
  display: flex;
  align-items: baseline;
  flex-wrap: nowrap;
  gap: 5px;
  min-width: 0;
}

.sticky-price-row .amount,
.sticky-price-row .sticky-discount-badge {
  flex-shrink: 0;
}

.sticky-cta .price-strike {
  font-size: 0.8rem;
  font-weight: 500;
  margin-right: 0.25em;
}

.sticky-cta .price-strike .amount {
  font-size: inherit;
  font-stretch: normal;
}

/* a persistent lime pill, visible at every width the bar shows at, so the discount is loud
   here too and not only on the page above. */
.sticky-discount-badge {
  display: inline-flex;
  font-size: 0.6875rem;
  padding: 3px 8px;
  margin-left: 0.4em;
}

/* both speed lines are always rendered (so the state holds with JS off); [data-sticky] toggles
   .speed-express on the bar itself, same switch the pricing cards use on .tier. */
.sticky-line--express {
  display: none;
}

.sticky-cta.speed-express .sticky-line--standard {
  display: none;
}

.sticky-cta.speed-express .sticky-line--express {
  display: flex;
}

.sticky-cta .amount {
  font-size: 1.25rem;
  font-stretch: 80%;
}

@media (max-width: 400px) {
  /* the WhatsApp icon button next to "Wyceń" leaves less room at the narrowest phones this
     bar supports (320-390px), so tighten the bar's own padding and the action gap first. */
  .sticky-cta {
    gap: 8px;
    padding: 6px 6px 6px 14px;
  }

  .sticky-actions {
    gap: 6px;
  }

  .sticky-cta .button-small {
    padding: 0 0.8rem;
  }
}

/* the tier name plus the "from" word on the Custom tier leave less room than the old single
   "Site from" line had, so the struck price drops earlier, at the same 430px breakpoint the
   amount and tier name shrink at below. */
@media (max-width: 430px) {
  .sticky-cta .amount {
    font-size: 1.1rem;
  }

  .sticky-cta .price-strike {
    display: none;
  }

  .sticky-tier-name {
    font-size: 0.6875rem;
  }

  .sticky-discount-badge {
    font-size: 0.625rem;
    padding: 2px 6px;
    margin-left: 0.2em;
  }
}

/* the 430px tuning above still overflows the narrowest phones (320-360px) on the "Custom"
   tier in English, where the "from" word adds width the other two tiers and PL don't carry:
   shrink the amount, the "from" label and the badge a second time rather than let the row
   wrap or clip under the "Wyceń" button. */
@media (max-width: 360px) {
  .sticky-cta .amount {
    font-size: 1rem;
  }

  .sticky-cta .price-small {
    font-size: 0.6rem;
  }

  .sticky-tier-name {
    font-size: 0.625rem;
  }

  .sticky-price-row {
    gap: 3px;
  }

  .sticky-discount-badge {
    font-size: 0.5625rem;
    padding: 2px 5px;
    margin-left: 0.15em;
  }
}

.sticky-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
  z-index: 1;
}

/* compact square button, same height as .button-small so the pair reads as one group, never
   a floating circular bubble: tight corners per the site's radius tokens, outline style like
   .button-outline so it stays quiet next to the filled "Wyceń" button. */
.icon-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  flex-shrink: 0;
  border-radius: var(--r-m);
  border: 1.5px solid var(--line);
  color: var(--ink);
  background: transparent;
  transition: border-color 0.2s, color 0.2s;
}

.icon-button:hover {
  border-color: var(--lime);
  color: var(--lime);
}

.icon-button .icon-chat {
  width: 1.15em;
  height: 1.15em;
}

/* kept at the same 44px tap-target size at every width this bar supports, even the narrowest
   phones (320-390px): .sticky-price flexes and shrinks around it instead, see its own
   max-width:360/400/430px rules below. */

.sticky-cta.is-away {
  transform: translateY(140%);
  opacity: 0;
  pointer-events: none;
}

/* without JS the show/hide-on-scroll script never runs, so [hidden] (set in the markup, see
   sticky() in home.ts) would otherwise keep this bar off screen forever: the generic [hidden]
   rule below is !important, so this override needs to match it. The inline price in the page
   content already works with JS off, but the bar itself should too: show it plainly, no
   scroll-away behaviour, since .is-away is only ever added by JS. */
.no-js .sticky-cta[hidden] {
  display: flex !important;
}

@media (min-width: 900px) {
  .sticky-cta {
    display: none !important;
  }
}

.prose-page {
  min-height: 60vh;
}

.prose {
  max-width: 780px;
}

.prose h1 {
  font-size: clamp(3rem, 8vw, 6rem);
  margin-bottom: 1rem;
}

.prose h2 {
  font-size: 1.6rem;
  font-stretch: 85%;
  margin: 2.5rem 0 0.6rem;
}

.prose p {
  color: var(--ink-2);
}

.prose .lead {
  margin: 1rem 0 2.5rem;
}

.thanks-mark {
  display: grid;
  place-items: center;
  width: 64px;
  height: 64px;
  margin-bottom: 1.75rem;
  border-radius: 50%;
  background: var(--lime);
  color: var(--lime-ink);
  font-size: 1.8rem;
  font-weight: 800;
}

.steps {
  list-style: none;
  counter-reset: step;
  margin: 0 0 2.5rem;
  padding: 0;
  display: grid;
  gap: 16px;
}

.steps li {
  counter-increment: step;
  display: flex;
  gap: 18px;
  padding-top: 16px;
  border-top: 1px solid var(--line);
}

.steps li::before {
  content: counter(step, decimal-leading-zero);
  font-family: var(--mono);
  font-size: 0.875rem;
  color: var(--muted);
  padding-top: 3px;
}

.site-footer {
  padding-block: 36px 48px;
  font-size: 0.875rem;
  color: var(--muted);
}

.footer-inner {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 12px 32px;
}

.footer-reassurance {
  flex-basis: 100%;
  order: 1;
  max-width: 48em;
}

.footer-links {
  order: 2;
}

.footer-links {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 22px;
  list-style: none;
  margin: 0;
  padding: 0;
}

.footer-links a {
  text-decoration: none;
}

.footer-whatsapp {
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
}

.footer-links a:hover {
  color: var(--ink);
  text-decoration: underline;
}

@media (max-width: 899px) {
  .site-footer {
    padding-bottom: 104px;
  }
}

/* Scroll reveal for [data-reveal] elements, two paths for the same result:
   1) site.js (IO fallback): toggles is-pending/is-in, used when animation-timeline is unsupported.
   2) @supports below (modern Chrome/Edge/Safari): animation-timeline: view() scrubs the same rise by
      scroll position, no JS needed, and it wins over path 1 by resetting its transition to none.
   Either way elements start visible (no [hidden], no flicker) and only get hidden once .js confirms
   a path can bring them back. */
.js [data-reveal].is-pending {
  opacity: 0;
  transform: translateY(28px);
}

.js [data-reveal].is-in {
  opacity: 1;
  transform: none;
  transition: opacity var(--m-base) var(--ease), transform var(--m-base) var(--ease);
}

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .js [data-reveal] {
      opacity: 1;
      transform: none;
      animation: reveal-rise var(--m-base) linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 30%;
    }

    .js [data-reveal].is-pending,
    .js [data-reveal].is-in {
      opacity: 1;
      transform: none;
      transition: none;
    }

    .js .process-rail.is-drawn::after {
      transition: none;
    }

    .js .process-card[data-build].is-built .process-step-dot::after {
      transition: none;
    }
  }
}

@keyframes reveal-rise {
  from {
    opacity: 0;
    transform: translateY(28px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

[hidden] {
  display: none !important;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation: none !important;
    transition: none !important;
    animation-timeline: none !important;
  }

  .hero-slogan .word > span {
    transform: none !important;
    opacity: 1 !important;
  }

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

  .process-rail::after {
    transform: scaleX(1) !important;
  }

  .process-step-dot::after {
    transform: scale(1) !important;
  }
}

