/* ============================================================
   KONCEPTO · SECTIONS
   ============================================================ */

.section { position: relative; padding-block: var(--section-pad); }
.theme-light { background: var(--light-bg); color: var(--ink); }
.theme-lime  { background: var(--lime); color: var(--lime-ink); }

.section__head { margin-bottom: var(--s-8); display: grid; gap: var(--s-4); }
.section__head--split {
  grid-template-columns: 1.2fr 0.8fr; align-items: end; gap: var(--s-7);
}
@media (max-width: 860px) { .section__head--split { grid-template-columns: 1fr; } }

/* ============================================================
   HERO  (sticky; scroll-scrubbed frame sequence in the background)
   ============================================================ */
/* tall enough that the macbook reel can't be flung past in one gesture — it spreads
   the 120 frames over ~160vh of scroll so it plays at a deliberate, watchable pace */
.stage--hero { position: relative; height: 260vh; }
.hero {
  position: sticky; top: 0;
  height: 100vh; min-height: 600px;
  overflow: hidden;
  display: flex; align-items: stretch;
}
/* Dark scrim for headline legibility; clears quickly as the copy leaves */
.hero::after {
  content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none;
  background:
    linear-gradient(96deg, rgba(8,9,11,0.9) 0%, rgba(8,9,11,0.6) 30%, rgba(8,9,11,0.2) 55%, rgba(8,9,11,0.4) 100%),
    linear-gradient(0deg, rgba(8,9,11,0.7) 0%, transparent 34%);
  opacity: calc(1 - var(--p, 0) * 3.4);
}

.hero__canvas { position: absolute; inset: 0; z-index: 0; }
.hero__grad { position: absolute; inset: 0; }
/* dark base behind the frames (fallback before they paint) */
.hero__grad--base {
  background: radial-gradient(140% 120% at 30% 0%, #16170f 0%, #0d0d10 36%, #08090b 100%);
}

/* scroll-scrubbed frame sequence (canvas). First frame as a CSS poster so the
   hero shows the still even before JS paints / with JS disabled. */
.hero__frames {
  position: absolute; inset: 0; width: 100%; height: 100%; display: block; z-index: 0;
  background: #08090b url("../assets/conceptbook-frames/cb0001.webp") center / cover no-repeat;
}

/* fine grain over the frames */
.hero__grain {
  position: absolute; inset: 0; z-index: 1; pointer-events: none; opacity: 0.045;
  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'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
  mix-blend-mode: overlay;
}

/* fade-to-white at the end of the scrub → straight into the light page */
.hero__flash {
  position: absolute; inset: 0; z-index: 4; pointer-events: none;
  background: var(--light-bg);
  opacity: var(--hero-fade, 0);
}

/* ---- Hero content: eyebrow top · GIANT headline centred · aside bottom ---- */
.hero__content {
  position: relative; z-index: 5;
  width: 100%;
  display: flex; flex-direction: column;
  padding-block: clamp(102px, 14.5vh, 168px) clamp(24px, 5vh, 52px);
  opacity: calc(1 - var(--p, 0) * 3.4);
  transform: translateY(calc(var(--p, 0) * -4vh));
  will-change: transform, opacity;
}

.hero__title {
  margin: 0;
  font-weight: var(--fw-black);
  font-size: clamp(3.1rem, 11.6vw, 13rem);
  line-height: 0.88;
  letter-spacing: -0.045em;
  text-transform: uppercase;
  color: var(--text);
}
.hero__title .line { display: block; }
.hero__title .line:last-child { color: var(--lime); }
/* NOTE: on ≥1400px the headline outgrows the 1240px shell and "no promesas" wraps, giving
   the RESULTADOS / NO / PROMESAS three-line stack. That is DELIBERATE — the user prefers
   it over the two-line lockup, so do NOT widen `.hero .shell` to "fix" the wrap. */

/* compressed copy block, pinned to the bottom of the hero */
.hero__aside {
  margin-top: auto;
  display: grid; grid-template-columns: minmax(0, 38ch) auto;
  align-items: end; justify-content: space-between; gap: var(--s-5) var(--s-7);
}
.hero__sub {
  font-size: var(--fs-18); line-height: 1.45; color: var(--text-dim); max-width: 42ch;
}
.hero__actions { display: flex; flex-wrap: wrap; gap: var(--s-3); align-self: end; }

/* SHORT VIEWPORTS (landscape phones ~390px tall, small laptop windows, 320x568).
   `.hero { min-height: 600px }` made the hero TALLER than the screen, and since the
   sub + CTAs are pinned to the hero's bottom (margin-top:auto) they fell outside the
   visible 100vh and disappeared entirely. Drop the floor and tighten the vertical rhythm
   so the whole lockup fits. */
@media (max-height: 620px) {
  .hero { min-height: 0; }
  .hero__content { padding-block: clamp(58px, 15vh, 96px) clamp(12px, 3vh, 24px); }
  .hero__title { font-size: clamp(2rem, 7.4vw, 3.2rem); }
  .hero__sub { font-size: var(--fs-14); max-width: 38ch; }
  .hero__aside { gap: var(--s-3) var(--s-5); }
}

/* set ignition step order via custom prop */
.ignite-item[data-ignite="1"] { --ignite-step: 0; }
.ignite-item[data-ignite="2"] { --ignite-step: 1; }
.ignite-item[data-ignite="3"] { --ignite-step: 2; }
.ignite-item[data-ignite="4"] { --ignite-step: 3; }
.ignite-item[data-ignite="5"] { --ignite-step: 4; }
.ignite-item[data-ignite="6"] { --ignite-step: 5; }

/* ============================================================
   SERVICES — full-screen scroll-pinned blocks (wipe + typewriter)
   JS drives panel transforms (--wipe) and typewriter from scroll.
   ============================================================ */
/* margin-top overlaps the hero's trailing 100vh so the intro is PINNED the instant
   the hero ends (it appears in place — no rise-from-below); +100vh height keeps the
   internal pacing and leaves the outro at the same document position (reachable). */
.svc-stage { position: relative; height: 780vh; margin-top: -100vh; pointer-events: none; }
/* ^ pointer-events:none on the whole services subtree so its -100vh overlap over the
   hero's lower 100vh never blocks the hero buttons (no svc content is interactive;
   scroll is window-level so this doesn't affect it). Re-enable per element if needed. */
.svc-pin { position: sticky; top: 0; height: 100vh; overflow: hidden; }

.svc-panel { position: absolute; inset: 0; overflow: hidden; will-change: clip-path; contain: paint; }
/* transparent: during the hero overlap the hero flash (#F4F4F2) shows through, and
   after the hero scrolls away the fixed light bg (#F4F4F2) shows — seamless, and no
   off-white strip intruding over the dark macbook at the top of the page. */
.svc-panel--intro { z-index: 1; background: transparent; color: var(--ink); }
/* blocks reveal by growing a rounded rect from a corner (JS drives clip-path).
   Only the LEADING (interior) corner is rounded so the screen-edge corners stay
   flush — no leftover empty corner. Radius stays constant, JS collapses it at the end. */
/* reveal order: AI → Tours → Web (z-index must increase in that order so each covers
   the previous). Web is now DARK (was light) and last. Corners alternate R/L/R. */
/* reveal order = ascending z-index: AI (dark) → Web (LIGHT, middle) → Tours (dark).
   Corners alternate right → left → right so consecutive panels never wipe the same way. */
.svc-panel--ai    { z-index: 2; background: var(--bg-0);    color: var(--text); clip-path: inset(100% 0 0 100% round 34px 0 0 0); }
.svc-panel--web   { z-index: 3; background: var(--light-bg); color: var(--ink); clip-path: inset(100% 100% 0 0 round 0 34px 0 0); }
.svc-panel--tours { z-index: 4; background: var(--bg-0);    color: var(--text); clip-path: inset(100% 0 0 100% round 34px 0 0 0); }

/* drone fly-over layers (intro). LTR sits above chevrons, below the text; RTL above all. */
.drone { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.drone--ltr { z-index: 2; }
.drone--rtl { z-index: 4; }
.svc-intro__chevrons { z-index: 1; }
.svc-intro__lead, .svc-intro__title { z-index: 3; }

/* --- intro: chevrons top-left · lead top-right · title bottom-left --- */
.svc-intro {
  height: 100%; display: grid;
  grid-template-columns: 1.05fr 0.95fr; grid-template-rows: auto 1fr auto;
  padding-block: clamp(104px, 17vh, 200px) clamp(48px, 10vh, 120px); gap: var(--s-6);
}
.svc-intro__chevrons { grid-column: 1; grid-row: 1; display: flex; gap: 2px; align-items: center; }
.chev { height: clamp(78px, 11.5vw, 176px); width: auto; }
/* chevrons enter strictly L→R (horizontal only) */
.chev:nth-child(1) { transform: translateX(calc((var(--chev,0) - 1) * 150px)); opacity: var(--chev,0); }
.chev:nth-child(2) { transform: translateX(calc((var(--chev2,0) - 1) * 150px)); opacity: var(--chev2,0); }
.chev:nth-child(3) { transform: translateX(calc((var(--chev3,0) - 1) * 150px)); opacity: var(--chev3,0); }
/* lead types in place (left-aligned, full space reserved) */
.svc-intro__lead {
  grid-column: 2; grid-row: 1; justify-self: end; align-self: center; text-align: left;
  font-size: var(--fs-24); color: var(--ink-dim); max-width: 30ch; line-height: 1.4;
}
.svc-intro__title {
  grid-column: 1 / -1; grid-row: 3;
  font-size: var(--fs-section); font-weight: var(--fw-black);
  letter-spacing: -0.035em; line-height: 0.95; max-width: 13ch;
  transform: translateX(calc((var(--introT,0) - 1) * 110px)); opacity: var(--introT,0);
}

/* --- blocks (ai / web / tours): huge static title + typewriter desc --- */
.svc-block {
  height: 100%; display: flex; flex-direction: column; justify-content: center; gap: var(--s-5);
  padding-block: clamp(104px, 14vh, 170px);
}
.svc-block__title {
  font-size: var(--fs-section); font-weight: var(--fw-black);
  letter-spacing: -0.035em; line-height: 0.95; max-width: 15ch; overflow-wrap: anywhere;
}
.svc-block__desc { font-size: var(--fs-24); line-height: 1.45; max-width: 40ch; }
.svc-panel--ai .svc-block__desc, .svc-panel--tours .svc-block__desc { color: var(--text-dim); }
.svc-panel--ai .svc-block__desc { max-width: 34ch; }
/* FLAT text (no shadow). Legibility comes from the BACKGROUND: a left→right scrim
   dims the dashboard dark where the white title/desc sit, fading to show the
   dashboard on the right. Same scrim on Web (now dark, with the device mockups).
   (Mobile overrides these with a flat dim — see ≤860.) */
.svc-panel--ai::after {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: linear-gradient(95deg, rgba(8,9,11,0.97) 0%, rgba(8,9,11,0.9) 52%, rgba(8,9,11,0.5) 80%, rgba(8,9,11,0.28) 100%);
}
/* Web is LIGHT again (off-white bg + ink copy) and the ipad+phone frames are flattened
   onto the same off-white with a clear top-left, so it needs NO scrim — flat ink on
   off-white reads cleanly (the dark radial scrim the dark version needed is gone). */
.svc-panel--web .svc-block__desc { color: var(--ink-dim); max-width: 34ch; }
/* Ultra-wide (21:9 and wider): the 16:9 frame is cover-fit, so it gets cropped vertically
   and the devices scale UP — the tablet's left edge creeps under the end of the title line.
   Tighten the measure there so the copy always stays clear of it. 16:9 and narrower are
   unaffected (no vertical crop, plenty of clearance). */
@media (min-aspect-ratio: 1.9) and (min-width: 1200px) {
  .svc-panel--web .svc-block__title { max-width: 11ch; }
  .svc-panel--web .svc-block__desc { max-width: 26ch; }
}

/* tours: full-bleed image with a dark scrim */
.svc-panel__bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: 0; }
/* The scrim used to fade out by 50%, but the description line runs to ~65% — its tail
   landed on the model's lit fingers / white headset and washed out. Hold the dark band
   further right so the full text column stays on protected pixels. */
.svc-panel--tours::after {
  content: ""; position: absolute; inset: 0; z-index: 0;
  background: linear-gradient(90deg, rgba(8,9,11,0.92) 0%, rgba(8,9,11,0.84) 40%, rgba(8,9,11,0.6) 62%, rgba(8,9,11,0.22) 82%, rgba(8,9,11,0.1) 100%);
}
.svc-panel--tours .svc-block__desc { max-width: 32ch; }
.svc-panel--tours .svc-block { position: relative; z-index: 1; }
/* AI block: dashboard video sits between the black bg and the text. No gradient
   scrim — the dashboard's left side is already near-black (#0A0B0D) so the text is
   legible, and skipping the full-screen gradient avoids a costly repaint during the
   corner-reveal (keeps the AI block at 60fps). */
.svc-panel--ai .svc-block { position: relative; z-index: 1; }
/* Web block (now DARK, last service block): white copy over the device mockups, with
   the same scrim as AI for legibility. Raised further so the title clears the mockups. */
.svc-panel--web .svc-block { position: relative; z-index: 1; gap: var(--s-4); transform: translateY(-13vh); }

/* typewriter — full text always reserves space; untyped chars are transparent
   so the title above never shifts while the line types */
.tw { white-space: pre-wrap; }
.tw__rest { color: transparent; }
/* caret = a BORDER on the typed span, not an inline-block between typed and rest.
   The old inline-block caret was an atomic inline = a soft-wrap opportunity that split
   the word being typed, so the typed partial-word overshot the line and the break
   happened late. A border creates no break opportunity → the partial word stays glued
   to its full word and wraps in sync (no overshoot). */
.tw.is-typing .tw__typed { border-right: 2px solid var(--lime); animation: tw-blink 0.9s steps(1) infinite; }
@keyframes tw-blink { 50% { border-right-color: transparent; } }

/* ============================================================
   REAL ESTATE
   ============================================================ */
.realestate__inner { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-9); align-items: center; }
.realestate .section__title { margin-top: var(--s-4); }
.realestate .section__lead { margin-top: var(--s-5); }
.checklist { margin-top: var(--s-6); display: grid; gap: var(--s-4); }
.checklist li {
  position: relative; padding-left: 30px; font-size: var(--fs-18); color: var(--ink-dim);
}
/* clean lime dash marker — no checkmark tics */
.checklist li::before {
  content: ""; position: absolute; left: 0; top: 0.65em;
  width: 18px; height: 3px; border-radius: 2px; background: var(--lime);
}

/* laptop device */
.device--laptop { width: 100%; max-width: 520px; margin-inline: auto; }
.device--laptop .device__screen { position: relative; overflow: hidden; aspect-ratio: 16/10; padding: 12px; border-radius: 14px 14px 4px 4px; }
.device--laptop .device__hinge {
  height: 10px; margin: 0 auto; width: 100%;
  background: linear-gradient(180deg, #1c1c1f, #0e0e10);
  box-shadow: var(--edge-dark);
}
.device--laptop .device__base {
  height: 14px; width: 112%; margin: 0 -6% ; border-radius: 0 0 14px 14px;
  background: linear-gradient(180deg, #161619, #0c0c0e);
  box-shadow: var(--shadow-2);
  position: relative;
}
.device--laptop .device__base::after {
  content: ""; position: absolute; top: 0; left: 50%; transform: translateX(-50%);
  width: 14%; height: 5px; border-radius: 0 0 6px 6px; background: #0a0a0c;
}
.re-ui {
  position: absolute; inset: 12px; border-radius: 8px; background: var(--bg-1);
  padding: 16px; display: flex; flex-direction: column; gap: 12px; overflow: hidden;
}
.re-ui__top { display: flex; gap: 6px; }
.re-ui__dot { width: 9px; height: 9px; border-radius: 50%; background: var(--surface-3); }
.re-ui__grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; flex: 1; }
.re-ui__card { border-radius: var(--r-sm); background: var(--surface-2); box-shadow: var(--edge-dark); }
.re-ui__card--lime { background: var(--lime); }
.re-ui__card--wide { grid-column: 1 / -1; min-height: 40px; }
.re-ui__ph { font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-muted); }

/* ============================================================
   "Más leads" panel — the LAST services panel. Opaque; JS slides it UP
   (translateY 100%→0) over the pinned Tours panel (which stays static),
   then the pin releases and it scrolls away normally into the outro.
   ============================================================ */
.svc-panel--realestate {
  z-index: 5;                       /* above the tours panel */
  background: var(--light-bg);      /* opaque so it covers the tours as it rises */
  color: var(--ink);
  transform: translateY(100%);      /* JS slides it up */
  will-change: transform;
  display: flex; align-items: center;
}
/* compress the realestate copy + mockup so the whole block fits one 100vh panel */
.svc-panel--realestate .realestate__inner {
  width: 100%; grid-template-columns: 1.1fr 0.9fr; gap: var(--s-7); align-items: center;
}
.svc-panel--realestate .section__title { font-size: var(--fs-section); margin-top: 0; line-height: 0.95; letter-spacing: -0.035em; }
/* body + checklist animate in (driven by JS as the panel pins) — see initServices */
.svc-panel--realestate .checklist li { will-change: opacity, transform; }
.svc-panel--realestate .section__lead { font-size: var(--fs-18); margin-top: var(--s-4); }
.svc-panel--realestate .checklist { margin-top: var(--s-5); gap: var(--s-3); }
.svc-panel--realestate .checklist li { font-size: var(--fs-16); }
.svc-panel--realestate .device--laptop { max-width: 420px; }
/* quiet descriptive paragraph (who/where/for whom) — carries the crawlable summary */
.svc-panel--realestate .realestate__about {
  margin-top: var(--s-5);
  font-size: var(--fs-14);
  line-height: 1.55;
  color: var(--ink-dim);
  max-width: 54ch;
}

/* ============================================================
   PROCESS
   ============================================================ */
.steps {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--s-5);
}
.step {
  position: relative; padding-top: var(--s-6);
  border-top: 2px solid var(--light-hairline);
}
/* loading bar — the lime fill grows left→right over the top hairline as --fill 0→1 */
.step__bar {
  position: absolute; top: -2px; left: 0; height: 2px;
  width: calc(var(--fill, 0) * 100%);
  background: var(--lime);
}
/* title + desc fade and rise in as the step's bar finishes filling (--show 0→1) */
.step__title, .step__desc {
  opacity: var(--show, 0);
  transform: translateY(calc((1 - var(--show, 0)) * 10px));
}
.step__title { font-size: var(--fs-24); font-weight: var(--fw-extra); letter-spacing: -0.02em; color: var(--ink); }
.step__desc { margin-top: var(--s-3); font-size: var(--fs-18); color: var(--ink-dim); }

/* ============================================================
   OUTRO — process pins; the end screen slides up over it as one block
   ============================================================ */
/* taller: process title types + 4 steps animate, THEN the end block slides up */
.outro-stage { position: relative; height: 320vh; }
.outro-pin { position: sticky; top: 0; height: 100vh; overflow: hidden; }
.outro-pin .process {
  position: absolute; inset: 0; display: flex; align-items: center; padding-block: 0;
}
.outro-pin .process > .shell { width: 100%; }

.final-block {
  position: absolute; inset: 0; z-index: 5;
  display: flex; flex-direction: column;
  transform: translateY(100%);          /* JS slides it up over the process */
  will-change: transform;
}

/* lime CTA ≈ 4/5, footer ≈ 1/5 */
.final-block .final-cta { flex: 1 1 auto; display: grid; place-items: center; text-align: center; background: var(--lime); color: var(--lime-ink); }
.final-cta__inner { display: grid; justify-items: center; gap: var(--s-5); }
.final-cta__title {
  font-weight: var(--fw-black); font-size: var(--fs-section); line-height: 0.95;
  letter-spacing: -0.035em; color: var(--lime-ink); max-width: 16ch;
  text-wrap: balance;   /* stops "próximo" / "proyecto." each stranding on their own line */
}
.final-cta__sub { font-size: var(--fs-24); color: rgba(10,14,7,0.74); max-width: 44ch; }
.final-cta__actions { margin-top: var(--s-4); display: flex; flex-wrap: wrap; gap: var(--s-4); justify-content: center; }

/* footer: one line — logo + tagline (left) · socials + mail (right) */
.final-block .site-footer { flex: 0 0 auto; display: flex; align-items: center; }
.site-footer { background: var(--bg-0); color: var(--text); }
.footer__bar {
  width: 100%; display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-5); padding-block: var(--s-5);
}
.footer__brand-line { display: flex; align-items: center; gap: var(--s-4); min-width: 0; }
.footer__word { height: clamp(26px, 2.6vw, 38px); width: auto; }
.footer__tag { font-size: var(--fs-16); font-weight: var(--fw-medium); color: var(--text-dim); }
.footer__contact { display: flex; align-items: center; gap: var(--s-5); }
.footer__email {
  font-size: var(--fs-18); font-weight: var(--fw-semibold); color: var(--text);
  transition: color var(--dur-fast) var(--ease-out);
}
.footer__email:hover { color: var(--lime); }
/* privacy link — deliberately quiet: small, muted, end of the contact row */
.footer__legal {
  font-size: var(--fs-14); color: var(--text-muted);
  transition: color var(--dur-fast) var(--ease-out);
}
.footer__legal:hover { color: var(--text); }

.footer__social { display: flex; gap: var(--s-3); }
.footer__social-link {
  display: inline-grid; place-items: center; width: 44px; height: 44px; border-radius: 50%;
  color: var(--text-dim); background: rgba(35,35,39,0.6);
  transition: color var(--dur) var(--ease-out), background-color var(--dur) var(--ease-out),
              transform var(--dur) var(--ease-overshoot);
}
.footer__social-link svg { width: 20px; height: 20px; }
@media (hover: hover) and (pointer: fine) {
  .footer__social-link:hover { color: var(--lime-ink); background: var(--lime); transform: translateY(-3px); }
}
.footer__social-link:active { transform: scale(0.92); }

.footer__bottom {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-4);
  padding-block: var(--s-4);
  border-top: 1px solid var(--hairline); font-size: var(--fs-14); color: var(--text-muted);
}

/* ============================================================
   RESPONSIVE
   ============================================================ */
@media (max-width: 1024px) {
  .realestate__inner { gap: var(--s-7); }
}

@media (max-width: 860px) {
  /* header: logo left, burger right; toggle + CTA live in the menu */
  .nav { display: none; }
  .header__cta { display: none; }
  .header__actions .lang-toggle { display: none; }
  .burger { display: grid; }

  /* mobile type: subtler than desktop. ALL section titles share ONE size on mobile via a
     single redeclaration of --fs-section (mirrors the desktop unification). Hero stays the
     giant exception. (Was: 4 separate per-title clamps — section/final-cta/svc-intro/svc-block.) */
  :root { --fs-section: clamp(2.4rem, 11vw, 3.6rem); }
  .stage--hero { height: 240vh; }
  .hero__title { font-size: clamp(2.6rem, 13vw, 4.2rem); }
  .hero__sub { font-size: var(--fs-16); }
  .section__lead { font-size: var(--fs-18); }
  .final-cta__sub { font-size: var(--fs-18); }

  /* stronger bottom scrim so the headline stays legible over the frames */
  .hero::after {
    background:
      linear-gradient(0deg, rgba(8,9,11,0.9) 0%, rgba(8,9,11,0.5) 30%, rgba(8,9,11,0.15) 60%, rgba(8,9,11,0.3) 100%);
  }

  /* services pinned blocks: single column, smaller type (+100vh keeps the -100vh
     hero-overlap margin balanced, same as desktop) */
  .svc-stage { height: 660vh; }
  .svc-intro { grid-template-columns: 1fr; grid-template-rows: auto auto 1fr auto; }
  .svc-intro__chevrons { grid-column: 1; grid-row: 1; }
  .svc-intro__lead { grid-column: 1; grid-row: 2; justify-self: start; font-size: var(--fs-18); max-width: 30ch; }
  /* Tablet portrait (768/820) is inside the mobile breakpoint but is wide enough to keep
     the intended side-by-side lockup — stacking there left the chevrons orphaned above a
     big empty band. Phones (<700px) keep the stack, where side-by-side would be cramped. */
  @media (min-width: 700px) {
    .svc-intro { grid-template-columns: auto minmax(0, 1fr); grid-template-rows: auto 1fr auto; }
    .svc-intro__chevrons { grid-column: 1; grid-row: 1; }
    .svc-intro__lead { grid-column: 2; grid-row: 1; align-self: center; max-width: 34ch; }
    .svc-intro__title { grid-column: 1 / -1; grid-row: 3; }
  }
  .svc-intro__title { grid-row: 4; max-width: 100%; }
  .svc-block { grid-template-columns: 1fr; align-content: center; gap: var(--s-6); }
  .svc-block__desc { font-size: var(--fs-18); max-width: 36ch; }
  .svc-block__media { height: 34vh; }
  .svc-tours__badge { top: clamp(88px, 12vh, 130px); }

  .realestate__inner { grid-template-columns: 1fr; gap: var(--s-7); }
  /* realestate panel on mobile: single column, hide the mockup so the copy fits 100vh */
  .svc-panel--realestate .realestate__inner { grid-template-columns: 1fr; }
  .svc-panel--realestate .realestate__visual { display: none; }
  /* The panel CENTRES its copy in 100vh. On small phones the copy is taller than the
     panel, and centred overflow spills equally out of BOTH ends — so the top of "Somos
     Koncepto." slid up under the floating header pill (fully hidden at 320px). Reserving
     padding alone doesn't help while it still centres; anchor it to the top instead, so
     any overflow can only go downward and the heading is always clear of the header. */
  .svc-panel--realestate {
    align-items: flex-start;
    padding-block: clamp(84px, 12vh, 112px) var(--s-6);
  }
  /* ≤380px there is simply not enough height for the crawlable closing paragraph too —
     drop it there so the heading, lead and checklist all fit on screen. */
  @media (max-width: 380px) {
    .svc-panel--realestate .realestate__about { display: none; }
    .svc-panel--realestate .section__lead { font-size: var(--fs-16); }
  }
  /* AI on mobile: the bright dashboard fills the screen behind the copy — flat dim it
     (no text-shadow) so the white title + desc stay clearly legible */
  /* 0.6 left the description at only ~3.1:1 where it crossed the dashboard (AA wants 4.5).
     Dim a bit harder AND brighten the description from --text-dim to full --text. */
  .svc-panel--ai::after {
    content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
    background: rgba(8,9,11,0.72);
  }
  .svc-panel--ai .svc-block__desc { color: var(--text); }
  /* Web on mobile needs NO scrim — it's the light panel (ink copy on off-white).
     But cover-fitting a 16:9 frame into a portrait viewport only shows its centre ~26%,
     and that slice is the TABLET, which sits low-centre. So anchor the copy to the TOP of
     the panel instead of centring it + raising it by a fixed -13vh: top-anchoring clears
     the device deterministically at any phone height. */
  .svc-panel--web .svc-block {
    justify-content: flex-start;
    transform: none;
    padding-block-start: clamp(84px, 11vh, 116px);
  }
  /* process: keep a 2×2 grid (4 stacked steps overflow the 100vh pin) + smaller type */
  .steps { grid-template-columns: 1fr 1fr; gap: var(--s-6) var(--s-5); }
  .step { padding-top: var(--s-5); }
  .step__desc { font-size: var(--fs-16); }
  /* at 320px the last CTA's rounded bottom landed exactly on the black footer edge and
     read as a clipped shape — give the lime block real breathing room */
  .final-block .final-cta { padding-block: var(--s-7) var(--s-8); }

  /* hero copy block stacks under the giant headline */
  .hero__aside { grid-template-columns: 1fr; align-items: start; }
  .hero__actions { align-self: start; }

  /* footer stacks on mobile (one line is a desktop look) */
  .final-block .site-footer { padding-block: var(--s-4); }
  .footer__bar { flex-direction: column; align-items: flex-start; gap: var(--s-3); }
  .footer__brand-line { flex-wrap: wrap; gap: var(--s-2) var(--s-3); }
  .footer__tag { font-size: var(--fs-14); }
  .footer__contact { width: 100%; justify-content: space-between; gap: var(--s-3); }
}

@media (max-width: 560px) {
  .steps { grid-template-columns: 1fr 1fr; gap: var(--s-5) var(--s-4); }
  .hero__actions { width: 100%; }
  .hero__actions .btn { flex: 1 1 auto; }
}
