/* ============================================================
   Phantom Lab — SECTIONS
   Hero, services bento, live demo, process timeline, why,
   contact, footer. Media queries are colocated per section.
   ============================================================ */

/* ============================================================
   Hero
   ============================================================ */
.hero {
  min-height: 100svh;
  display: flex; align-items: center;
  position: relative;
  padding: 140px 0 80px;
  overflow: hidden;
}
.hero-canvas { position: absolute; inset: 0; width: 100%; height: 100%; }

/* Pre-blurred gradients — deliberately no `filter: blur()` here,
   a multi-stop radial gradient is far cheaper to paint. */
.hero-glow {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
  opacity: 0.85;
}
.hero-glow-1 {
  width: 900px; height: 900px;
  top: -330px; right: -260px;
  background: radial-gradient(circle,
    rgba(124, 58, 237, 0.30) 0%,
    rgba(124, 58, 237, 0.20) 22%,
    rgba(124, 58, 237, 0.10) 42%,
    rgba(124, 58, 237, 0.04) 60%,
    transparent 74%);
}
.hero-glow-2 {
  width: 780px; height: 780px;
  bottom: -300px; left: -290px;
  background: radial-gradient(circle,
    rgba(34, 211, 238, 0.20) 0%,
    rgba(34, 211, 238, 0.13) 22%,
    rgba(34, 211, 238, 0.07) 42%,
    rgba(34, 211, 238, 0.03) 60%,
    transparent 74%);
}
[data-theme="light"] .hero-glow { opacity: 0.6; }

.hero-content { position: relative; z-index: 2; text-align: center; }
.hero-badge {
  display: inline-block;
  font-size: 0.85rem; font-weight: 500;
  color: var(--text-muted);
  background: var(--surface-strong);
  border: 1px solid var(--border);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-pill);
  margin-bottom: var(--space-5);
}
.hero-title {
  font-size: clamp(2.4rem, 6.5vw, 4.6rem);
  font-weight: 700;
  max-width: 900px;
  margin: 0 auto var(--space-5);
}
.hero-title .word { display: inline-block; white-space: pre; }
.hero-title .grad-word {
  background: var(--grad);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent;
}
.hero-subtitle {
  color: var(--text-muted);
  font-size: clamp(1rem, 2vw, 1.2rem);
  max-width: 620px;
  margin: 0 auto var(--space-6);
}
.hero-actions {
  display: flex; gap: 16px; justify-content: center; flex-wrap: wrap;
  margin-bottom: var(--space-7);
}

.hero-stats {
  display: flex; justify-content: center; align-items: center;
  gap: clamp(24px, 5vw, 56px);
  flex-wrap: wrap;
}
.stat { text-align: center; }
.stat-num {
  font-family: var(--font-display);
  font-size: clamp(1.8rem, 4vw, 2.6rem);
  font-weight: 700;
  background: var(--grad);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent;
}
.stat-label { color: var(--text-muted); font-size: 0.88rem; margin-top: var(--space-1); }
.stat-divider { width: 1px; height: 44px; background: var(--border); }

.scroll-hint {
  position: absolute; bottom: var(--space-5); left: 50%;
  transform: translateX(-50%);
  z-index: 2;
}
.scroll-hint-mouse {
  width: 26px; height: 42px;
  border: 2px solid var(--text-muted);
  border-radius: 14px;
  display: flex; justify-content: center;
  padding-top: 7px;
  opacity: 0.7;
}
.scroll-hint-wheel {
  width: 4px; height: 8px;
  background: var(--accent-3);
  border-radius: 2px;
  animation: wheel 1.6s ease-in-out infinite;
}

@media (max-width: 560px) {
  .hero-actions .btn { width: 100%; }
  .stat-divider { display: none; }
  .hero-stats { gap: var(--space-4); }
}

/* ============================================================
   Services — dimensional bento
   ============================================================ */
.bento {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-4);
}
.bento-wide { grid-column: span 2; }

.bento-card {
  /* Fallback accent: every card must have one even if a new card is added
     beyond the nth-child list below — an undefined --card-accent-soft makes
     the hover gradient invalid and kills the whole hover effect. */
  --card-accent: var(--c1);
  --card-accent-soft: var(--c1-soft);
  /* Layered depth: inner gradient "border" via background-clip,
     no flat 1px line and no backdrop-filter. */
  padding: var(--space-6) var(--space-5);
  position: relative;
  overflow: hidden;
  border: 1px solid transparent;
  background:
    linear-gradient(180deg, var(--card-bg), var(--card-bg-2)) padding-box,
    var(--grad-border) border-box;
  transform-style: preserve-3d;
  transition: background 0.35s ease, box-shadow 0.35s ease, transform 0.35s ease;
}

/* cursor spotlight */
.bento-card::before {
  content: "";
  position: absolute;
  width: 260px; height: 260px;
  border-radius: 50%;
  background: radial-gradient(circle, var(--card-accent-soft), transparent 70%);
  top: var(--my, 50%); left: var(--mx, 50%);
  transform: translate(-50%, -50%);
  opacity: 0;
  transition: opacity 0.35s ease;
  pointer-events: none;
}
/* top border-glow */
.bento-card::after {
  content: "";
  position: absolute;
  top: 0; left: 12%; right: 12%;
  height: 2px;
  background: linear-gradient(90deg, transparent, var(--card-accent), transparent);
  opacity: 0;
  transition: opacity 0.4s ease;
  pointer-events: none;
}
.bento-card:hover::before { opacity: 0.55; }
.bento-card:hover::after { opacity: 1; }
.bento-card:hover {
  background:
    linear-gradient(180deg, var(--card-bg), var(--card-bg-2)) padding-box,
    linear-gradient(160deg, var(--card-accent-soft), rgba(255, 255, 255, 0.05) 65%) border-box;
  box-shadow: 0 18px 50px -14px var(--card-accent-soft);
}

/* per-card accent hue: violet → blue → cyan */
.bento-card:nth-child(1) { --card-accent: var(--c1); --card-accent-soft: var(--c1-soft); }
.bento-card:nth-child(2) { --card-accent: var(--c2); --card-accent-soft: var(--c2-soft); }
.bento-card:nth-child(3) { --card-accent: var(--c3); --card-accent-soft: var(--c3-soft); }
.bento-card:nth-child(4) { --card-accent: var(--c4); --card-accent-soft: var(--c4-soft); }
.bento-card:nth-child(5) { --card-accent: var(--c5); --card-accent-soft: var(--c5-soft); }
.bento-card:nth-child(6) { --card-accent: var(--c6); --card-accent-soft: var(--c6-soft); }
.bento-card:nth-child(7) { --card-accent: var(--c7); --card-accent-soft: var(--c7-soft); }
.bento-card:nth-child(8) { --card-accent: var(--c4); --card-accent-soft: var(--c4-soft); }

.card-icon {
  position: relative;
  overflow: hidden;
  width: 62px; height: 62px;
  display: grid; place-items: center;
  border-radius: 18px;
  background: linear-gradient(140deg, var(--card-accent-soft), rgba(255, 255, 255, 0.04) 70%);
  border: 1px solid var(--card-accent-soft);
  color: var(--card-accent, var(--accent-3));
  margin-bottom: var(--space-4);
  box-shadow: 0 8px 24px -14px var(--card-accent-soft);
  transition: box-shadow 0.4s ease, transform 0.4s ease;
}
.card-icon svg {
  width: 32px; height: 32px;
  position: relative; z-index: 1;
}
/* gradient sheen sweep */
.card-icon::after {
  content: "";
  position: absolute;
  inset: -20%;
  background: var(--sheen);
  opacity: 0.35;
  transform: translateX(-140%);
  transition: transform 0.75s cubic-bezier(0.22, 1, 0.36, 1);
  pointer-events: none;
}
.bento-card:hover .card-icon::after { transform: translateX(140%); }
.bento-card:hover .card-icon {
  box-shadow: 0 10px 34px -10px var(--card-accent-soft);
  transform: translateZ(30px);
}

.card-title { font-size: 1.25rem; font-weight: 700; margin-bottom: 10px; }
.card-desc { color: var(--text-muted); font-size: 0.95rem; }
.card-chip {
  position: absolute; top: var(--space-5); right: var(--space-5);
  font-size: 0.72rem; font-weight: 600;
  letter-spacing: 0.06em; text-transform: uppercase;
  color: #fff;
  background: var(--grad);
  padding: 5px var(--space-3);
  border-radius: var(--radius-pill);
}

/* touch devices: no tilt, but a tasteful press state */
@media (hover: none), (pointer: coarse) {
  .bento-card { transition: transform 0.18s ease, box-shadow 0.18s ease; }
  .bento-card:active {
    transform: scale(0.982);
    box-shadow: 0 10px 30px -16px var(--card-accent-soft);
  }
  .bento-card:active::after { opacity: 1; }
}

@media (max-width: 1024px) {
  .bento { grid-template-columns: repeat(2, 1fr); }
  .bento-wide { grid-column: span 2; }
}
@media (max-width: 560px) {
  .bento { grid-template-columns: 1fr; }
  .bento-wide { grid-column: span 1; }
  .card-icon { width: 54px; height: 54px; border-radius: 16px; }
  .card-icon svg { width: 28px; height: 28px; }
}

/* ============================================================
   Live demo
   ============================================================ */
/* Fills the viewport while pinned — a shorter block would leave dead
   space above it once ScrollTrigger releases the pin. The heading now lives
   inside here too (see index.html), so align-content:center centers the
   heading + phone/flow together as one composition instead of leaving the
   phone floating in the middle of an otherwise-empty 100svh box. */
.demo-pin {
  position: relative; z-index: 1;
  min-height: 100svh;
  display: grid; align-content: center;
}
.demo-layout {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(32px, 6vw, 80px);
  align-items: center;
  padding-block: var(--space-6);
}
@media (min-width: 821px) {
  /* On desktop the heading shares the pinned 100svh box with the phone/flow
     (see the .demo-pin comment above). A short laptop (e.g. 1280×800) only
     has ~190px of slack above the phone's own height, which the full-size
     heading alone would already exceed — so this is a smaller, compact
     variant of .section-head just for this instance, not the one used by
     every other section, to keep the whole composition inside the pinned
     box instead of pushing its rendered height past 100svh (which would
     clip the bottom of the pinned content for the whole scrubbed
     animation). Mobile isn't pinned and isn't height-constrained, so it
     keeps the roomier, full-size heading above. */
  .demo-pin .section-head {
    margin-bottom: var(--space-4);
    max-width: 520px;
  }
  .demo-pin .section-head .section-title { font-size: clamp(1.3rem, 2.4vw, 1.8rem); }
  .demo-pin .section-head .section-sub { font-size: 0.88rem; }
  .demo-layout { padding-block: var(--space-2); }
}
.phone {
  /* Real-phone proportions. The svh term keeps the mockup inside the pinned
     viewport on short laptops instead of overflowing it (re-tuned below so
     the composition fits at 1024×768 — see the comment on .phone-screen). */
  width: min(330px, 86vw, 37svh);
  margin-inline: auto;
  background: #10141f;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 42px;
  padding: var(--space-3);
  box-shadow: var(--shadow), 0 0 80px rgba(124, 58, 237, 0.18);
  position: relative;
  /* shared fallback — only what actually differs is set per skin below */
  --chat-text-muted: #8A93A6;
  /* Everything inside (font-size, padding, radii, avatar/dot sizes — see the
     .phone-screen font-size and the .tg-* rules below) is sized in cqw
     against THIS box, so the whole mockup scales as one unit. Before this,
     type stayed a fixed rem size while the phone's width shrank with the
     svh/vw terms above, so a narrower phone wrapped the German strings onto
     more lines and the message stack grew taller exactly when there was
     less height to put it in — which is why an ever-taller aspect-ratio
     was needed the narrower/shorter the viewport got. With text and
     spacing both tied to the container's width, the wrapped line count (and
     so the message stack's height as a fraction of the phone's width) is
     now constant at every size, so a single aspect-ratio works everywhere. */
  container-type: inline-size;
}
/* The owner builds bots for several messengers, not just Telegram. The skin
   flips with the language (see setPhoneSkin() in animations.js): Ukrainian
   visitors see the real Telegram flow, German/English see a generic
   WhatsApp-style mockup so the copy isn't tied to one messenger. */
.phone.is-telegram {
  --chat-bg: #17212B;
  --chat-header-bg: #212D3B;
  --bubble-in: #212D3B;
  --bubble-out: #2B5378;
  --chat-accent: #64B5EF;
  --chat-accent-soft: rgba(100, 181, 239, 0.15);
  --chat-accent-border: rgba(100, 181, 239, 0.5);
  --chat-accent-active: rgba(100, 181, 239, 0.35);
}
.phone.is-whatsapp {
  --chat-bg: #0B141A;
  --chat-header-bg: #202C33;
  --bubble-in: #202C33;
  --bubble-out: #005C4B;
  --chat-accent: #00A884;
  --chat-accent-soft: rgba(0, 168, 132, 0.15);
  --chat-accent-border: rgba(0, 168, 132, 0.5);
  --chat-accent-active: rgba(0, 168, 132, 0.35);
}
.phone-notch {
  position: absolute; top: var(--space-3); left: 50%;
  transform: translateX(-50%);
  width: 36cqw; height: 9.2cqw;
  background: #10141f;
  border-radius: 0 0 5.2cqw 5.2cqw;
  z-index: 3;
}
/* .tg-* class names are historical (the mockup started Telegram-only) — they
   now render either skin via the --chat-* custom properties above, so the
   name just means "chat", not "Telegram". */
.phone-screen {
  background: var(--chat-bg);
  border-radius: 10.5cqw;
  overflow: hidden;
  /* One ratio for every width now that everything inside scales together
     (see the container-type comment on .phone) — still a natural phone
     screen ratio (9:16 is the classic one) but tightened from 9/18 to leave
     a small top gap instead of a big one. 9/16.5 (and even 9/17) turned out
     too tight once the date divider and the length-balanced EN/UK strings
     (see demo.date and demo.msg1-4 in the i18n files) were added — both cut
     the safety margin in the German message stack (the tallest, all three
     languages are now within a few px of each other, see the .tg-date
     comment below) below the ~20px floor at the tightest viewport (1024/
     1366×768), so this settled at 17.5. Because the line-wrap count no
     longer changes with the phone's width (see the container-type comment
     on .phone), this one ratio holds without overflowing at every other
     size too, instead of needing a different value per breakpoint. */
  aspect-ratio: 9 / 17.5;
  display: flex; flex-direction: column;
  /* Base unit for every size below (font-size, padding, radii, avatar/dot
     sizes) — calibrated so 1em here matches the chat bubble text's old
     0.875rem/14px at the phone's full 330px width. cqw ties it to the
     container's width (see .phone's container-type) instead of the root
     font-size, so it shrinks with the phone instead of staying fixed. */
  font-size: 4.6cqw;
}
.tg-header {
  display: flex; align-items: center; gap: var(--space-3);
  background: var(--chat-header-bg);
  padding: 11.1cqw 5.2cqw 3.9cqw;
}
.tg-avatar {
  width: 12.4cqw; height: 12.4cqw;
  border-radius: 50%;
  background: var(--grad);
  color: #fff;
  display: grid; place-items: center;
  font-weight: 700; font-family: var(--font-display);
  flex: none;
}
.tg-avatar svg { width: 7.8cqw; height: 7.8cqw; }
.tg-name { color: #fff; font-weight: 600; font-size: 1.09em; }
.tg-status { font-size: 0.89em; }
.tg-status-online { color: var(--chat-accent); }
.tg-chat {
  flex: 1;
  min-height: 0;
  padding: 5.2cqw 3.9cqw;
  display: flex; flex-direction: column;
  /* anchored to the bottom like a real chat; the phone is tall enough for the
     whole conversation, so there is no scrollbar to show */
  justify-content: flex-end;
  gap: 3.3cqw;
  overflow: hidden;
}
/* Real messenger date divider — not a .tg-msg (see the comment in
   index.html), so initDemo()'s scrubbed timeline never touches it and it
   stays visible above the conversation the whole time. Doubles as a bit of
   authentic-looking fill for the top of the chat. */
.tg-date {
  align-self: center;
  color: var(--chat-text-muted);
  background: rgba(255, 255, 255, 0.08);
  font-size: 0.8em;
  padding: 1.3cqw 3.9cqw;
  border-radius: var(--radius-pill);
  flex-shrink: 0;
}
.tg-msg {
  max-width: 82%;
  padding: 2.9cqw 4.2cqw;
  border-radius: 5.2cqw;
  /* no font-size of its own — inherits .phone-screen's 4.6cqw base directly */
  line-height: 1.45;
  color: #fff;
  flex-shrink: 0;
}
.tg-in { background: var(--bubble-in); align-self: flex-start; border-bottom-left-radius: 1.3cqw; }
.tg-out { background: var(--bubble-out); align-self: flex-end; border-bottom-right-radius: 1.3cqw; }
.tg-buttons {
  background: transparent;
  padding: 0;
  display: flex; gap: 2cqw; flex-wrap: wrap;
  max-width: 100%;
}
.tg-btn {
  background: var(--chat-accent-soft);
  border: 1px solid var(--chat-accent-border);
  color: var(--chat-accent);
  border-radius: 3.3cqw;
  padding: 2.3cqw 3.9cqw;
  /* relative to .phone-screen's base, same as .tg-msg above it (that has no
     font-size of its own), so this isn't compounded through a parent em */
  font-size: 0.91em;
}
.tg-btn-active { background: var(--chat-accent-active); color: #fff; }
.tg-typing {
  align-self: flex-start;
  background: var(--bubble-in);
  border-radius: 5.2cqw;
  border-bottom-left-radius: 1.3cqw;
  padding: 3.9cqw 4.6cqw;
  display: flex; gap: 1.3cqw;
  flex-shrink: 0;
}
.tg-typing span {
  width: 2cqw; height: 2cqw;
  border-radius: 50%;
  background: var(--chat-text-muted);
  animation: typing 1.2s ease-in-out infinite;
}
.tg-typing span:nth-child(2) { animation-delay: 0.15s; }
.tg-typing span:nth-child(3) { animation-delay: 0.3s; }

.flow { position: relative; max-width: 360px; margin-inline: auto; }
.flow-svg { position: absolute; inset: 0; width: 100%; height: calc(100% - 60px); }
.flow-line { stroke-dasharray: 60; stroke-dashoffset: 60; }
.flow-nodes { display: flex; flex-direction: column; gap: var(--space-6); position: relative; }
/* Three states, so the viewer always knows where the conversation is:
     (default)   upcoming — dim, no accent
     .is-active  done     — legible, soft accent border, no glow
     .is-current happening now — full accent, glow, slightly scaled up
   `.is-current` is always applied together with `.is-active` and wins because
   it is declared later with the same specificity. */
.flow-node {
  display: flex; align-items: center; gap: 16px;
  /* no backdrop-filter */
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 16px var(--space-4);
  opacity: 0.35;
  transform: scale(1);
  transition: opacity 0.4s ease, border-color 0.4s ease,
              box-shadow 0.4s ease, transform 0.4s ease, background-color 0.4s ease;
}
.flow-node.is-active {
  opacity: 0.72;
  border-color: rgba(124, 58, 237, 0.3);
  box-shadow: none;
}
.flow-node.is-current {
  opacity: 1;
  border-color: var(--accent-1);
  box-shadow: var(--glow);
  transform: scale(1.045);
}
.flow-node.is-current .flow-node-text { color: var(--accent-3); }
.flow-node-icon { font-size: 1.5rem; }
.flow-node-text { font-weight: 600; font-size: 0.95rem; }
.flow-caption {
  margin-top: var(--space-5);
  color: var(--text-muted);
  font-size: 0.95rem;
  text-align: center;
}

@media (max-width: 820px) {
  /* not pinned below 821px (see initDemo) — a full-viewport minimum would only
     add dead space, and the stacked layout is taller than the viewport anyway */
  .demo-pin { min-height: 0; }
  .demo-layout { grid-template-columns: 1fr; }
  /* not pinned here, so the phone may use its natural proportions without
     having to fit a viewport height. No aspect-ratio override needed any
     more: every size inside .phone-screen is in cqw/em against .phone's own
     width (see the container-type comment on .phone), so the same ratio
     that fits the message stack at 330px keeps fitting it here too. */
  .phone { width: min(300px, 74vw); }
  .flow { margin-top: var(--space-4); }
  .flow-nodes { gap: var(--space-4); }
  .flow-node { padding: 14px var(--space-3); }
}

/* ============================================================
   Process — vertical timeline
   ============================================================ */
.timeline {
  position: relative;
  max-width: 1000px;
  margin-inline: auto;
  --tl-axis: 50%;
  --tl-node: 56px;
}
.tl-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
}

/* static rail + animated gradient overlay that "draws" itself */
.tl-rail,
.tl-progress {
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--tl-axis);
  width: 2px;
  margin-left: -1px;
  border-radius: 2px;
  pointer-events: none;
}
.tl-rail { background: var(--border); }
.tl-progress {
  background: var(--grad-v);
  transform: scaleY(0);
  transform-origin: top center;
  box-shadow: 0 0 16px rgba(124, 58, 237, 0.45);
}

.tl-item {
  position: relative;
  display: grid;
  grid-template-columns:
    calc(var(--tl-axis) - var(--tl-node) / 2 - var(--space-5))
    calc(var(--tl-node) + var(--space-5) * 2)
    1fr;
  align-items: center;
}
.tl-item .tl-node { grid-column: 2; justify-self: center; }
.tl-item .tl-card { grid-column: 1; }
.tl-item:nth-child(even) .tl-card { grid-column: 3; }

.tl-node {
  position: relative;
  z-index: 2;
  width: var(--tl-node);
  height: var(--tl-node);
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--bg);
  border: 2px solid var(--border);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.05rem;
  color: var(--text-muted);
  transition: color 0.4s ease, border-color 0.4s ease,
              box-shadow 0.4s ease, transform 0.4s ease;
}
.tl-node::before {
  content: "";
  position: absolute;
  inset: -6px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(124, 58, 237, 0.35), transparent 70%);
  opacity: 0;
  transition: opacity 0.45s ease;
}
.tl-item.is-active .tl-node {
  color: #fff;
  border-color: transparent;
  background: var(--grad);
  box-shadow: 0 0 0 4px rgba(124, 58, 237, 0.14), 0 10px 30px -10px rgba(124, 58, 237, 0.7);
  transform: scale(1.06);
}
.tl-item.is-active .tl-node::before { opacity: 1; }

.tl-card {
  padding: var(--space-5) var(--space-5) var(--space-5);
  position: relative;
}
.tl-card h3 { font-size: 1.2rem; font-weight: 700; margin-bottom: var(--space-2); }
.tl-card p { color: var(--text-muted); font-size: 0.95rem; }
.tl-item.is-active .tl-card {
  border-color: rgba(124, 58, 237, 0.4);
  box-shadow: var(--shadow-card), 0 14px 40px -22px rgba(124, 58, 237, 0.8);
}

@media (max-width: 820px) {
  .timeline { --tl-axis: 26px; --tl-node: 48px; }
  .tl-list { gap: var(--space-5); }
  .tl-item {
    grid-template-columns: calc(var(--tl-axis) * 2) 1fr;
    align-items: start;
    column-gap: var(--space-3);
  }
  .tl-item .tl-node { grid-column: 1; }
  .tl-item .tl-card,
  .tl-item:nth-child(even) .tl-card { grid-column: 2; }
  .tl-card { padding: var(--space-4); }
}

/* ============================================================
   Why
   ============================================================ */
.why-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-5);
}
.why-item { text-align: center; padding: var(--space-5) var(--space-3); }
.why-icon { font-size: 2.2rem; margin-bottom: 16px; }
.why-item h3 { font-size: 1.1rem; margin-bottom: 10px; }
.why-item p { color: var(--text-muted); font-size: 0.92rem; }

@media (max-width: 1024px) {
  .why-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
  .why-grid { grid-template-columns: 1fr; }
}

/* ============================================================
   Contact
   ============================================================ */
.section-contact { padding-bottom: 130px; }
.contact-card {
  padding: clamp(32px, 6vw, 64px);
  position: relative;
  overflow: hidden;
}
.contact-card::before {
  content: "";
  position: absolute;
  width: min(450px, 90%);
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(124, 58, 237, 0.16), transparent 70%);
  top: -30%; right: -18%;
  pointer-events: none;
}
.contact-info { max-width: 560px; margin-bottom: var(--space-6); }
.contact-info .section-title { font-size: clamp(1.7rem, 3.5vw, 2.4rem); }
.contact-form { position: relative; z-index: 2; }

@media (max-width: 560px) {
  .section-contact { padding-bottom: 90px; }
}

/* ============================================================
   Footer
   ============================================================ */
.footer {
  border-top: 1px solid var(--border);
  padding: var(--space-6) 0;
  position: relative;
}
.footer-inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-5); flex-wrap: wrap;
}
.footer-logo { display: inline-flex; align-items: center; gap: 10px; }
.footer-brand p { color: var(--text-muted); font-size: 0.9rem; margin-top: 6px; }
.footer-note { color: var(--text-muted); font-size: 0.85rem; }

/* ---- Legal links (Impressum / Datenschutz) ---- */
.footer-meta {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
}
.footer-legal {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 18px;
}
.footer-legal a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;              /* comfortable tap target on phones */
  color: var(--text-muted);
  font-size: 0.85rem;
  text-decoration: none;
  transition: color 0.25s ease;
}
.footer-legal a:hover { color: var(--text); text-decoration: underline; }
.footer-legal a:focus-visible {
  outline: 2px solid var(--accent-2);
  outline-offset: 2px;
  border-radius: var(--radius-xs);
}

@media (max-width: 640px) {
  .footer-meta { align-items: flex-start; }
}

/* ============================================================
   Growth figures (potential results — shown under "why")
   ============================================================ */
.growth {
  margin-top: var(--space-7);
  padding: var(--space-6) var(--space-5);
  border-radius: var(--radius);
  border: 1px solid transparent;
  background:
    linear-gradient(180deg, var(--card-bg), var(--card-bg-2)) padding-box,
    var(--grad-border) border-box;
  text-align: center;
}
.growth-lead {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.15rem, 2.6vw, 1.5rem);
  margin-bottom: var(--space-5);
}
.growth-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-5);
}
.growth-num {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(2rem, 5vw, 3rem);
  line-height: 1.1;
  background: var(--grad);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent;
}
.growth-label {
  color: var(--text-muted);
  font-size: 0.9rem;
  margin-top: var(--space-2);
  text-wrap: pretty;
}
.growth-note {
  color: var(--text-muted);
  font-size: 0.8rem;
  margin-top: var(--space-5);
  max-width: 62ch;
  margin-inline: auto;
  opacity: 0.8;
  text-wrap: pretty;
}
@media (max-width: 640px) {
  .growth-grid { grid-template-columns: 1fr; gap: var(--space-4); }
  .growth { padding: var(--space-5) var(--space-4); }
}

/* ============================================================
   Testimonials — paged scroll-snap carousel
   --rv-per-page sets how many cards make up one page; js/animations.js
   reads it back via getComputedStyle so the dot/page count always
   matches whatever breakpoint is active, with no number duplicated
   in JS. The track is a real scroll container, so touch swipe,
   trackpad and keyboard all work without any JS — the arrows, dots
   and autoplay in js/animations.js are progressive enhancement.
   ============================================================ */
.reviews {
  position: relative;
  --rv-per-page: 3;
}
.rv-viewport {
  /* identical formula to .container, so the track — and every card
     inside it — can never bleed past the viewport edge */
  width: min(var(--container-w), 100% - var(--container-gutter));
  margin-inline: auto;
}
.rv-track {
  display: flex;
  gap: var(--space-4);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  /* small inline padding only, just enough for the hover lift/focus ring —
     the viewport width above is what keeps the track in bounds, so this no
     longer needs to fake a gutter */
  padding: var(--space-2) 2px;
  scrollbar-width: none;
}
.rv-track::-webkit-scrollbar { display: none; }
.rv-track:focus-visible { outline: 2px solid var(--accent-3); outline-offset: 4px; }

.rv-card {
  /* exactly --rv-per-page cards fill the track width, so a card is always
     either fully in view or fully scrolled off to the side — never clipped */
  flex: 0 0 calc((100% - (var(--rv-per-page) - 1) * var(--space-4)) / var(--rv-per-page));
  scroll-snap-align: start;
  padding: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  transition: transform 0.35s ease, box-shadow 0.35s ease, border-color 0.35s ease;
}
@media (hover: hover) {
  .rv-card:hover {
    transform: translateY(-6px);
    border-color: rgba(124, 58, 237, 0.4);
    box-shadow: var(--shadow-card), 0 18px 46px -24px rgba(124, 58, 237, 0.8);
  }
}
.rv-stars { color: #FBBF24; letter-spacing: 0.12em; font-size: 1rem; }
.rv-text {
  color: var(--text);
  font-size: 0.95rem;
  line-height: 1.65;
  text-wrap: pretty;
  flex: 1;
}
.rv-who {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-top: var(--space-3);
  border-top: 1px solid var(--border-soft);
}
.rv-name { font-family: var(--font-display); font-weight: 700; font-size: 0.98rem; }
.rv-role { color: var(--text-muted); font-size: 0.83rem; }

/* ---- controls: dots + arrows live under the track, never over a card ---- */
.rv-controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  margin-top: var(--space-5);
}
.rv-arrow {
  flex: none;
  width: 44px; height: 44px;
  display: grid; place-items: center;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--surface-strong);
  color: var(--text);
  transition: background 0.25s ease, border-color 0.25s ease, opacity 0.25s ease;
}
.rv-arrow svg { width: 20px; height: 20px; }
.rv-arrow:hover { border-color: var(--accent-3); color: var(--accent-3); }
.rv-arrow[disabled] { opacity: 0.3; pointer-events: none; }

.rv-dots {
  display: flex;
  justify-content: center;
  gap: var(--space-2);
}
.rv-dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  border: 0;
  padding: 0;
  background: var(--border);
  transition: background 0.3s ease, width 0.3s ease;
}
.rv-dot.is-active { width: 26px; border-radius: var(--radius-pill); background: var(--grad); }

@media (max-width: 1024px) {
  .reviews { --rv-per-page: 2; }
}
@media (max-width: 640px) {
  .reviews { --rv-per-page: 1; }
  /* swiping is the natural gesture on phones — arrows would just
     duplicate what the dots already show */
  .rv-arrow { display: none; }
}
