.hero {
  position: relative;
  /* Full first viewport on shorter screens, but capped on tall monitors so the
     scene doesn't keep stretching and centering itself in a growing void —
     the rest of that height is just the next section starting sooner. */
  min-height: min(100dvh, 54rem);
  display: grid;
  align-content: center;
  padding-block: calc(var(--nav-height) + var(--space-md)) var(--space-md);
  overflow: hidden;
}

/* Scroll invitation — pure decoration, invites the user further down the page */
.hero::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: 1.75rem;
  width: 11px;
  height: 11px;
  border-left: 2px solid var(--color-primary);
  border-bottom: 2px solid var(--color-primary);
  border-radius: 0 0 0 2px;
  transform: translateX(-50%) rotate(-45deg);
  opacity: 0.4;
  pointer-events: none;
  z-index: 1;
}

@media (prefers-reduced-motion: no-preference) {
  .hero::after {
    animation: scroll-cue 2.2s ease-in-out infinite;
  }
}

@keyframes scroll-cue {
  0%, 100% {
    transform: translateX(-50%) translateY(0) rotate(-45deg);
    opacity: 0.4;
  }
  50% {
    transform: translateX(-50%) translateY(6px) rotate(-45deg);
    opacity: 0.75;
  }
}

@media (max-width: 640px) {
  .hero::after {
    display: none;
  }
}

.hero__inner {
  position: relative;
  display: grid;
  grid-template-columns: 1fr;
  align-items: center;
  gap: var(--space-lg);
  /* Widens past the site's shared 1200px container on large monitors so the
     text column and mockup scale up together instead of sitting fixed-size
     in the middle of a much bigger viewport. */
  max-width: clamp(1200px, 82vw, 1500px);
}

.hero__content {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  max-width: 640px;
  text-align: left;
}

/* Entrance fade on page load, staggered to follow the navbar in. Same pacing
   as the original GSAP timeline — moving it to CSS keeps that pacing but
   drops the wait on GSAP's script download before the hero (LCP element)
   can render, which is what the JS version was blocked on. */
@media (prefers-reduced-motion: no-preference) {
  .hero__eyebrow,
  .hero__title,
  .hero__subtitle,
  .hero__actions,
  .hero__badges {
    animation: hero-fade-in-up 0.8s cubic-bezier(0.16, 1, 0.3, 1) both;
  }

  .hero__eyebrow {
    animation-delay: 0.4s;
  }

  .hero__title {
    animation-delay: 0.7s;
  }

  .hero__subtitle {
    animation-delay: 1s;
  }

  .hero__actions {
    animation-delay: 1.3s;
  }

  .hero__badges {
    animation-delay: 1.7s;
  }
}

@keyframes hero-fade-in-up {
  from {
    opacity: 0;
    transform: translateY(24px);
  }
}

.hero__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--color-primary-dark);
  background: linear-gradient(120deg, rgba(179, 216, 168, 0.35), rgba(163, 209, 198, 0.25));
  padding: 0.45rem 1.05rem;
  border-radius: var(--radius-pill);
  border: 1px solid rgba(163, 209, 198, 0.4);
  margin-bottom: var(--space-md);
}

.hero__title {
  font-size: var(--text-hero);
  line-height: 1.05;
  letter-spacing: -0.03em;
  margin-bottom: var(--space-sm);
}

/* Scoped to the homepage Hero only (.page-hero on other pages keeps the
   shared --text-hero token). The generic fluid scale tops out at 72px,
   which wraps this specific headline to 5–6 lines regardless of column
   width — this tighter clamp keeps it to 2–3 lines so it stops dominating
   the composition and dragging everything else down with it. */
.hero .hero__title {
  font-size: clamp(2.25rem, 1.55rem + 2.4vw, 3.4rem);
}

/* --color-primary-dark is the theme-aware "text-safe" accent token — already
   remapped per theme (darker green on light bg, lighter mint on dark bg) so
   this stays readable in both without a separate dark-mode override. */
.hero__title-accent {
  color: var(--color-primary-dark);
}

.hero__subtitle {
  font-size: var(--text-md);
  color: var(--color-text-muted);
  max-width: 52ch;
  margin-bottom: 1.25rem;
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
  margin-bottom: 1.25rem;
}

/* Reads as a trust bar grouped under the CTAs, not a stray wrapped list */
.hero__badges {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs) var(--space-sm);
  padding-top: var(--space-xs);
  border-top: 1px solid var(--color-border);
}

.hero__badge {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-family: inherit;
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: 0.01em;
  color: var(--color-text-muted);
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  padding: 0.45rem 0.7rem;
  margin: -0.05rem -0.7rem;
  cursor: pointer;
  transition: color var(--transition-base), background-color var(--transition-base),
    border-color var(--transition-base);
}

.hero__badge:hover {
  color: var(--color-primary-dark);
}

.hero__badge:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

.hero__badge.is-active {
  color: var(--color-primary-dark);
  background-color: rgba(61, 141, 122, 0.1);
  border-color: rgba(61, 141, 122, 0.25);
}

.hero__badge svg {
  width: 14px;
  height: 14px;
  color: var(--color-primary);
  opacity: 0.85;
  flex-shrink: 0;
}

/* Visual mockup scene */
.hero__visual {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 460px;
  perspective: 1600px;
}

.hero__visual::before {
  content: '';
  position: absolute;
  inset: -10% -5%;
  background: radial-gradient(45% 45% at 35% 30%, rgba(179, 216, 168, 0.35), transparent 70%),
    radial-gradient(40% 40% at 70% 70%, rgba(163, 209, 198, 0.3), transparent 70%);
  filter: blur(10px);
  z-index: 0;
  pointer-events: none;
}

@media (prefers-reduced-motion: no-preference) {
  .hero__visual::before {
    animation: glow-drift 16s ease-in-out infinite alternate;
  }
}

@keyframes glow-drift {
  0% {
    transform: translate(-2%, -1%) scale(1);
  }
  100% {
    transform: translate(3%, 2%) scale(1.06);
  }
}

/* The mockup depicts a screenshot of a demo website, not the studio's own
   UI — like a product photo, it keeps its own fixed light presentation
   regardless of whether the visitor's system is in light or dark mode.
   (Previously this chrome rode on --color-surface/--color-bg-warm, which
   flip dark in dark mode while the text inside stayed hardcoded dark-on-dark,
   making everything inside unreadable — these local tokens fix that and give
   every panel a single, theme-independent palette to build on.) */
.mockup {
  --mockup-surface: #FCFCFC;
  --mockup-surface-alt: #FBFFE4;
  --mockup-card: rgba(255, 255, 255, 0.78);
  --mockup-border: rgba(163, 209, 198, 0.35);
  --mockup-text: #1F2A24;
  --mockup-text-muted: rgba(31, 42, 36, 0.5);
  --mockup-line: rgba(31, 42, 36, 0.1);
  --mockup-primary: #3D8D7A;
  --mockup-primary-dark: #2F6F5F;
  --mockup-secondary: #B3D8A8;
  --mockup-complementary: #A3D1C6;
  --mockup-on-primary: #FCFCFC;

  position: relative;
  z-index: 1;
  width: min(100%, clamp(360px, 38vw, 460px));
  border-radius: var(--radius-lg);
  background: linear-gradient(160deg, var(--mockup-surface) 0%, var(--mockup-surface-alt) 100%);
  box-shadow: var(--shadow-md);
  overflow: hidden;
  border: 1px solid rgba(163, 209, 198, 0.3);
  transform-style: preserve-3d;
  will-change: transform;
}

.mockup__bar {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.8rem 1.1rem;
  background-color: rgba(255, 255, 255, 0.75);
  border-bottom: 1px solid var(--mockup-border);
}

.mockup__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background-color: var(--mockup-complementary);
  opacity: 0.65;
}

.mockup__dot:nth-child(2) {
  background-color: var(--mockup-secondary);
}

.mockup__dot:nth-child(3) {
  background-color: var(--mockup-primary);
}

.mockup__bar-url {
  display: flex;
  align-items: center;
  margin-left: 0.6rem;
  height: 16px;
  width: 45%;
  padding-inline: 0.4rem;
  border-radius: var(--radius-pill);
  background-color: rgba(31, 42, 36, 0.06);
}

.mockup__bar-favicon {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: linear-gradient(120deg, var(--mockup-primary), var(--mockup-complementary));
  flex-shrink: 0;
}

.mockup__nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.9rem 1.5rem;
  border-bottom: 1px solid rgba(163, 209, 198, 0.2);
}

.mockup__nav-logo {
  width: 22px;
  height: 8px;
  border-radius: var(--radius-pill);
  background: linear-gradient(120deg, var(--mockup-primary), var(--mockup-complementary));
}

.mockup__nav-links {
  display: flex;
  gap: 0.5rem;
}

.mockup__nav-links span {
  width: 20px;
  height: 6px;
  border-radius: var(--radius-pill);
  background-color: var(--mockup-line);
}

.mockup__viewport {
  position: relative;
  height: 360px;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(180deg, #000 88%, transparent 100%);
  mask-image: linear-gradient(180deg, #000 88%, transparent 100%);
}

/* Interactive mockup states — one panel per hero__badge, only one visible
   at a time. Dimensions are inherited from .mockup__viewport above so
   switching state never shifts the mockup's height. */
.mockup__panel {
  position: absolute;
  inset: 0;
  padding: 1.6rem 1.5rem 2.25rem;
  display: flex;
  flex-direction: column;
  gap: 0.95rem;
  opacity: 0;
  pointer-events: none;
}

/* Shared "chapter label" every panel opens with — same pill language as
   .hero__eyebrow, and carries the same icon as the badge that triggered it
   so the control and the preview visibly belong to each other. */
.mockup__eyebrow {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.58rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  color: var(--mockup-primary-dark);
  background-color: rgba(179, 216, 168, 0.35);
  padding: 0.28rem 0.6rem;
  border-radius: var(--radius-pill);
}

.mockup__eyebrow svg {
  width: 10px;
  height: 10px;
}

/* --- Estado: Fácil de encontrar en Google --- */
.mockup__search {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.6rem 0.9rem;
  border-radius: var(--radius-pill);
  background-color: rgba(255, 255, 255, 0.75);
  border: 1px solid var(--mockup-border);
}

.mockup__search svg {
  width: 13px;
  height: 13px;
  color: var(--mockup-primary);
  flex-shrink: 0;
}

.mockup__search-text {
  font-size: 0.68rem;
  color: var(--mockup-text-muted);
}

.mockup__serp {
  display: flex;
  flex-direction: column;
  gap: 0.8rem;
}

.mockup__serp-result {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.mockup__serp-result--active {
  padding: 0.75rem 0.85rem;
  border-radius: var(--radius-md);
  background-color: var(--mockup-card);
  border: 1px solid rgba(61, 141, 122, 0.3);
  box-shadow: 0 8px 20px rgba(61, 141, 122, 0.12);
}

.mockup__serp-badge {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.56rem;
  font-weight: 600;
  letter-spacing: 0.03em;
  color: var(--mockup-primary-dark);
  background-color: rgba(179, 216, 168, 0.35);
  padding: 0.2rem 0.5rem;
  border-radius: var(--radius-pill);
  margin-bottom: 0.1rem;
  transform-origin: left center;
}

.mockup__serp-url {
  font-size: 0.6rem;
  color: var(--mockup-primary);
}

.mockup__serp-title {
  font-family: var(--font-heading);
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--mockup-text);
}

.mockup__serp-desc {
  font-size: 0.64rem;
  line-height: 1.5;
  color: var(--mockup-text-muted);
  max-width: 32ch;
}

.mockup__serp-result--muted {
  padding: 0.1rem 0.85rem;
  opacity: 0.55;
}

.mockup__serp-result--muted .mockup__serp-url {
  display: block;
  width: 40%;
  height: 6px;
  border-radius: var(--radius-pill);
  background-color: var(--mockup-line);
  margin-bottom: 0.35rem;
}

.mockup__serp-line {
  display: block;
  height: 6px;
  width: 85%;
  border-radius: var(--radius-pill);
  background-color: rgba(31, 42, 36, 0.08);
  margin-bottom: 0.3rem;
}

.mockup__serp-line--short {
  width: 55%;
  margin-bottom: 0;
}

/* --- Estado: Se adapta a cualquier pantalla ---
   One frame whose width is actually animated through desktop → tablet →
   mobile (not a scale() trick), with its nav and grid snapping to their
   real breakpoint layout mid-transition — the same way a real responsive
   site behaves, not a simulated resize. The frame is small and isolated
   (position: absolute, no page siblings), so animating its width is cheap:
   only its own handful of children ever reflow. */
.mockup__reflow {
  flex: 1;
  min-height: 150px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.mockup__reflow-frame {
  width: 84%;
  height: 150px;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: 0.6rem 0.7rem;
  background-color: var(--mockup-card);
  border: 1px solid var(--mockup-border);
  border-radius: var(--radius-md);
  box-shadow: 0 10px 24px rgba(31, 42, 36, 0.08);
  overflow: hidden;
}

.mockup__reflow-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-shrink: 0;
}

.mockup__reflow-logo {
  width: 16px;
  height: 6px;
  border-radius: var(--radius-pill);
  background: linear-gradient(120deg, var(--mockup-primary), var(--mockup-complementary));
  flex-shrink: 0;
}

.mockup__reflow-links {
  display: flex;
  gap: 0.3rem;
}

.mockup__reflow-links span {
  width: 16px;
  height: 5px;
  border-radius: var(--radius-pill);
  background-color: var(--mockup-line);
}

.mockup__reflow-burger {
  display: none;
  flex-direction: column;
  gap: 2px;
  width: 13px;
}

.mockup__reflow-burger span {
  display: block;
  height: 1.5px;
  border-radius: 1px;
  background-color: var(--mockup-text-muted);
}

.mockup__reflow-frame.is-compact .mockup__reflow-links {
  display: none;
}

.mockup__reflow-frame.is-compact .mockup__reflow-burger {
  display: flex;
}

.mockup__reflow-heading {
  display: block;
  height: 8px;
  width: 46%;
  min-width: 34px;
  border-radius: var(--radius-pill);
  background: linear-gradient(120deg, var(--mockup-primary), var(--mockup-complementary));
  flex-shrink: 0;
}

.mockup__reflow-grid {
  display: flex;
  gap: 0.35rem;
  flex: 1;
}

.mockup__reflow-grid.is-stacked {
  flex-direction: column;
}

.mockup__reflow-block {
  flex: 1;
  border-radius: 0.35rem;
  background: linear-gradient(150deg, rgba(163, 209, 198, 0.4), rgba(179, 216, 168, 0.3));
  border: 1px solid rgba(163, 209, 198, 0.3);
}

/* Breakpoint rail below the frame — echoes the .mockup__journey dot
   language so the "current stage" idea reads the same across panels. */
.mockup__breakpoints {
  display: flex;
  justify-content: center;
  gap: 0.6rem;
}

.mockup__breakpoint {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background-color: rgba(31, 42, 36, 0.06);
  border: 1.5px solid var(--mockup-border);
}

.mockup__breakpoint svg {
  width: 11px;
  height: 11px;
  color: var(--mockup-text-muted);
}

.mockup__breakpoint.is-active {
  background-color: var(--mockup-primary);
  border-color: var(--mockup-primary);
}

.mockup__breakpoint.is-active svg {
  color: var(--mockup-on-primary);
}

/* --- Estado: Carga rápida ---
   A performance ring that counts up to 100% quickly, paired with content
   that's already there beside it (no skeleton state) — the score and the
   "nothing to wait for" feeling land together, once, on activation. */
.mockup__speed-hero {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.mockup__speed-gauge {
  position: relative;
  width: 88px;
  height: 88px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.mockup__speed-ring {
  position: absolute;
  inset: 0;
  transform: rotate(-90deg);
}

.mockup__speed-ring-track,
.mockup__speed-ring-value {
  fill: none;
  stroke-width: 8;
}

.mockup__speed-ring-track {
  stroke: rgba(31, 42, 36, 0.08);
}

.mockup__speed-ring-value {
  stroke: var(--mockup-primary);
  stroke-linecap: round;
  stroke-dasharray: 251.3;
  stroke-dashoffset: 251.3;
}

.mockup__speed-score {
  font-family: var(--font-heading);
  font-size: 1.1rem;
  font-weight: 800;
  color: var(--mockup-text);
}

.mockup__speed-preview {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.mockup__speed-block {
  display: block;
  height: 9px;
  width: 85%;
  border-radius: var(--radius-pill);
  background-color: var(--mockup-line);
}

.mockup__speed-block--heading {
  height: 11px;
  width: 58%;
}

.mockup__speed-block--short {
  width: 45%;
}

.mockup__speed-block.is-filled {
  background: linear-gradient(120deg, var(--mockup-primary), var(--mockup-complementary));
}

.mockup__speed-block--heading.is-filled {
  background: linear-gradient(120deg, var(--mockup-primary-dark), var(--mockup-primary));
}

/* Naming the categories a performance check covers, alongside the
   headline score above — plain labels, not a second scoreboard. */
.mockup__speed-checklist {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

.mockup__speed-checklist span {
  font-size: 0.58rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--mockup-primary-dark);
  background-color: rgba(163, 209, 198, 0.25);
  padding: 0.28rem 0.55rem;
  border-radius: var(--radius-pill);
}

/* --- Estado: Acompañamiento personalizado ---
   A project journey, not a chat log: four stages with the current one
   highlighted, plus a single personal note — reads as "someone is guiding
   this project," not a support widget. */
.mockup__journey {
  list-style: none;
  display: flex;
  flex-direction: column;
}

.mockup__journey-step {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding-block: 0.3rem;
}

.mockup__journey-step:not(:last-child)::after {
  content: '';
  position: absolute;
  left: 8px;
  top: 100%;
  width: 1px;
  height: 0.36rem;
  background-color: var(--mockup-border);
}

.mockup__journey-dot {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 17px;
  height: 17px;
  border-radius: 50%;
  background-color: rgba(31, 42, 36, 0.06);
  border: 1.5px solid var(--mockup-border);
  flex-shrink: 0;
}

.mockup__journey-dot svg {
  width: 9px;
  height: 9px;
  color: var(--mockup-on-primary);
}

.mockup__journey-step.is-done .mockup__journey-dot {
  background-color: var(--mockup-primary);
  border-color: var(--mockup-primary);
}

.mockup__journey-step.is-active .mockup__journey-dot {
  border-color: var(--mockup-primary);
  box-shadow: 0 0 0 3px rgba(61, 141, 122, 0.16);
}

.mockup__journey-label {
  font-size: 0.66rem;
  font-weight: 600;
  color: var(--mockup-text-muted);
}

.mockup__journey-step.is-done .mockup__journey-label {
  color: var(--mockup-text);
}

.mockup__journey-step.is-active .mockup__journey-label {
  color: var(--mockup-primary-dark);
}

.mockup__note {
  display: flex;
  align-items: flex-start;
  gap: 0.55rem;
  padding: 0.65rem 0.75rem;
  border-radius: var(--radius-md);
  background-color: var(--mockup-card);
  border: 1px solid var(--mockup-border);
}

.mockup__note-avatar {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  flex-shrink: 0;
  background: linear-gradient(120deg, var(--mockup-primary), var(--mockup-complementary));
}

.mockup__note-text {
  font-size: 0.66rem;
  line-height: 1.5;
  color: var(--mockup-text);
}

/* Shared stacked-column composition (phones through portrait tablets).
   Fluid rather than the old fixed 380px/460px blocks, and deliberately
   shorter than desktop: the mockup is meant to peek into the first
   viewport as a "there's more below" cue, not fully replicate the
   desktop scene at a smaller scale. The 260px floor (vs. the old 200px)
   gives the interactive panels below enough room to stay legible — each
   one is measured against it, see the mobile panel overrides below. */
@media (max-width: 959px) {
  .hero__inner {
    gap: var(--space-md);
  }

  .hero__visual {
    min-height: clamp(300px, 50vw, 400px);
    margin-top: var(--space-sm);
  }

  .mockup__viewport {
    height: clamp(260px, 40vw, 320px);
  }

  /* Tighter rhythm than desktop so every panel's content clears the
     shorter viewport above without being clipped by its overflow:hidden. */
  .mockup__panel {
    padding: 1.15rem 1.2rem 1.5rem;
    gap: 0.75rem;
  }

  .mockup__reflow {
    min-height: 100px;
  }

  .mockup__reflow-frame {
    height: 100px;
  }

  .mockup__speed-gauge {
    width: 64px;
    height: 64px;
  }

  .mockup__speed-score {
    font-size: 0.85rem;
  }
}

@media (max-width: 640px) {
  .hero {
    padding-block: calc(var(--nav-height) + var(--space-sm)) var(--space-sm);
  }

  /* The mockup viewport is at its shortest in this range (see the 260px
     clamp floor above) — the muted competitor row is decorative padding
     around the featured result, first to go so the real content never
     gets clipped by the viewport's overflow:hidden. */
  .mockup__serp-result--muted {
    display: none;
  }

  .hero__title {
    margin-bottom: var(--space-xs);
  }

  .hero__subtitle {
    margin-bottom: 1.25rem;
  }

  .hero__actions {
    flex-direction: column;
    align-items: stretch;
    margin-bottom: 1.25rem;
  }

  .hero__actions .btn {
    width: 100%;
  }

  /* Own composition, not a squeezed desktop row: a compact 2-column trust
     bar the visitor sees in full without scrolling, mockup follows after. */
  .hero__badges {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-xs) var(--space-sm);
  }
}

/* On short/narrow phones (e.g. iPhone SE) the 2-column badge grid's bottom-right
   cell lands directly under the fixed WhatsApp button. A single column keeps
   every badge left-aligned and clear of that corner regardless of scroll position. */
@media (max-width: 380px) and (max-height: 600px) {
  .hero__badges {
    grid-template-columns: 1fr;
  }
}

@media (min-width: 960px) {
  .hero__inner {
    grid-template-columns: 1.2fr 0.8fr;
    column-gap: var(--space-xl);
  }

  .hero__content {
    max-width: none;
  }
}

