/* ============ Fini Landing — production slot fills ============
   Replaces the design-canvas placeholder regions with shipped CSS/SVG craft:
   botanical gradient scenes, mini product shots (mock-* patterns), avatar discs. */

/* ---------- Base: every fill covers its region ---------- */
.slot-fill {
  display: block;
  position: absolute;
  inset: 0;
  overflow: hidden;
}
.twostep-nav__visual { position: relative; }

/* ---------- Keyboard focus (token-consistent) ----------
   :focus-visible only — a plain :focus fallback rings mouse clicks
   (e.g. the nav hamburger) which reads as a stuck selected state. */
a:focus-visible,
button:focus-visible {
  outline: 2px solid var(--green-leaf);
  outline-offset: 3px;
}

/* ---------- Skip to content (visually hidden until keyboard focus) ---------- */
.skip-link {
  position: fixed;
  top: 12px;
  left: 12px;
  z-index: 500; /* above the nav (100) */
  padding: 12px 20px;
  background: var(--lime-200);
  color: var(--green-ink);
  border-radius: var(--radius-md);
  font-weight: 600;
  font-size: var(--text-sm);
  box-shadow: 0 8px 24px rgba(20, 40, 8, 0.18);
  transform: translateY(-150%);
  opacity: 0;
  pointer-events: none;
}
.skip-link:focus-visible {
  transform: translateY(0);
  opacity: 1;
  pointer-events: auto;
}

/* ---------- Small utilities (replace repeated inline styles) ---------- */
.section-head.is--center {
  margin-inline: auto;
  align-items: center;
  text-align: center;
}
.btn--lg {
  height: 60px;
  padding: 0 36px;
  font-size: 18px;
}
/* No danger token exists yet — keep the raw accent for the "borrar datos" icon. */
.fini-icon--danger { color: #e5484d; }

/* ---------- Layout-stability + hit-target hardening ---------- */
/* The chat typing indicator toggles display (none→flex→none) during its
   scripted sequence; in flow that changes the bento card height ~42px and
   the browser drags the reader's scroll position along (felt as a "jump"
   at the footer). Overlay it on the reply bubble's already-reserved slot
   (the reply holds space at opacity 0) so page height never changes. */
.mock-chat { position: relative; }
.mock-chat .mock-typing { position: absolute; top: 0; left: 0; }
/* Four-message conversation: keep the copiloto cell compact on small screens */
@media screen and (max-width: 520px) {
  .bento__chat .mock-msg { font-size: var(--text-sm); padding: 9px 13px; }
}

/* At max scroll on phones the footer sitemap's top links (Seguridad/FAQ)
   parked exactly behind the fixed nav pill and could never be clicked at the
   page's natural end position. A shorter leaf drop-zone shifts the sitemap
   below the nav's footprint at max scroll. */
@media screen and (max-width: 480px) {
  .fp-logo-row { min-height: 430px; }
}

/* Footer physics canvas (pointer-events: auto, z-index 3) overlapped the
   bottom ~12px of the social buttons, eating clicks. Rows paint above the
   canvas (text stays readable over settled leaves) but pass pointer events
   through to the canvas except on their actual links/buttons — so leaves
   resting inside those bands stay grabbable. */
.fp-footer .social-share,
.fp-top,
.fp-bottom { position: relative; z-index: 4; pointer-events: none; }
.fp-top a,
.fp-top button,
.fp-bottom a,
.fp-bottom button,
.fp-footer .social-share button { pointer-events: auto; }

/* Saldo bento: show the subtle ink area under the smoothed line (product.css
   hid the default lime area on this cell) */
.bento__card.is--saldo .chart__area { display: block; }

/* ---------- Hero photo ---------- */
.hero__bg img.slot-fill { object-fit: cover; }

/* ---------- Botanical scenes (vida-1..5, emp-4, nav) ---------- */
.fill-scene { background: var(--paper-warm); }
.fill-scene__leaves {
  position: absolute;
  height: auto;
  pointer-events: none;
}
.fill-scene__leaves path:nth-child(1) { fill: rgba(12, 42, 5, 0.30); }
.fill-scene__leaves path:nth-child(2) { fill: rgba(12, 42, 5, 0.20); }
.fill-scene__leaves path:nth-child(3) { fill: rgba(12, 42, 5, 0.38); }
.fill-scene__leaves.is--brand path:nth-child(1) { fill: var(--green-leaf); }
.fill-scene__leaves.is--brand path:nth-child(2) { fill: #d6f597; }
.fill-scene__leaves.is--brand path:nth-child(3) { fill: var(--lime-bright); }
.fill-scene__leaves.is--a {
  left: -7%;
  bottom: -14%;
  width: 58%;
  transform: rotate(12deg);
  opacity: 0.5;
}
.fill-scene__leaves.is--b {
  right: -5%;
  top: -10%;
  width: 34%;
  transform: rotate(-158deg);
  opacity: 0.42;
}

.fill-scene.is--vida1 {
  background:
    radial-gradient(58% 48% at 76% 18%, rgba(252, 244, 222, 0.92) 0%, rgba(252, 244, 222, 0) 62%),
    radial-gradient(95% 85% at 14% 104%, rgba(31, 110, 31, 0.5) 0%, rgba(31, 110, 31, 0) 68%),
    linear-gradient(158deg, var(--lime-200) 0%, #94d967 46%, var(--green-leaf) 100%);
}
.fill-scene.is--vida2 {
  background:
    radial-gradient(52% 44% at 22% 14%, rgba(252, 244, 222, 0.55) 0%, rgba(252, 244, 222, 0) 60%),
    radial-gradient(90% 80% at 86% 108%, rgba(12, 42, 5, 0.55) 0%, rgba(12, 42, 5, 0) 66%),
    linear-gradient(198deg, var(--lime-500) 0%, #4f9a4a 48%, var(--green-deep) 100%);
}
.fill-scene.is--vida2 .fill-scene__leaves.is--a { left: auto; right: -9%; transform: rotate(38deg); }
.fill-scene.is--vida2 .fill-scene__leaves.is--b { right: auto; left: -4%; transform: rotate(-120deg); }
.fill-scene.is--vida3 {
  background:
    radial-gradient(64% 52% at 70% 12%, rgba(255, 255, 255, 0.85) 0%, rgba(255, 255, 255, 0) 58%),
    radial-gradient(100% 70% at 50% 112%, rgba(63, 107, 34, 0.42) 0%, rgba(63, 107, 34, 0) 62%),
    linear-gradient(172deg, var(--paper-cream) 0%, #e2ffb0 44%, var(--lime-500) 100%);
}
.fill-scene.is--vida3 .fill-scene__leaves.is--a { width: 50%; transform: rotate(4deg); }
.fill-scene.is--vida4 {
  background:
    radial-gradient(50% 42% at 82% 20%, rgba(240, 97, 47, 0.16) 0%, rgba(240, 97, 47, 0) 58%),
    radial-gradient(96% 84% at 10% 108%, rgba(20, 40, 8, 0.6) 0%, rgba(20, 40, 8, 0) 64%),
    linear-gradient(150deg, var(--paper-warm) 0%, #c9d99a 42%, var(--green-olive) 100%);
}
.fill-scene.is--vida4 .fill-scene__leaves.is--a { transform: rotate(26deg); width: 62%; }
.fill-scene.is--vida5 {
  background:
    radial-gradient(60% 46% at 30% 12%, rgba(252, 244, 222, 0.95) 0%, rgba(252, 244, 222, 0) 60%),
    radial-gradient(92% 78% at 88% 106%, rgba(31, 110, 31, 0.46) 0%, rgba(31, 110, 31, 0) 64%),
    linear-gradient(164deg, var(--paper-150) 0%, var(--lime-300) 48%, #74c463 100%);
}
.fill-scene.is--vida5 .fill-scene__leaves.is--a { left: auto; right: -8%; transform: rotate(-16deg) scaleX(-1); }
.fill-scene.is--vida5 .fill-scene__leaves.is--b { right: auto; left: -3%; transform: rotate(-172deg); }
.fill-scene.is--emp4 {
  background:
    radial-gradient(62% 50% at 74% 14%, rgba(252, 244, 222, 0.8) 0%, rgba(252, 244, 222, 0) 58%),
    radial-gradient(96% 84% at 16% 106%, rgba(31, 110, 31, 0.44) 0%, rgba(31, 110, 31, 0) 66%),
    linear-gradient(160deg, var(--lime-100) 0%, #b8ec78 48%, var(--green-leaf) 100%);
}

/* Nav menu square: phone mockup with a mini Fini screen on the lime field */
.fill-nav {
  background:
    radial-gradient(78% 66% at 74% 22%, rgba(252, 244, 222, 0.85) 0%, rgba(252, 244, 222, 0) 62%),
    linear-gradient(152deg, var(--lime-200) 0%, var(--lime-500) 58%, var(--green-leaf) 100%);
}
.fill-nav .fill-scene__leaves.is--b {
  right: auto;
  left: -7%;
  top: auto;
  bottom: -10%;
  width: 44%;
  transform: rotate(-24deg);
  opacity: 0.4;
}
.fill-phone {
  position: absolute;
  left: 50%;
  top: 55%;
  width: 56%;
  aspect-ratio: 10 / 19;
  transform: translate(-50%, -50%) rotate(-7deg);
  background: var(--green-ink);
  border-radius: 22px;
  padding: 6px;
  box-shadow:
    0 2px 4px rgba(12, 42, 5, 0.18),
    0 22px 44px rgba(12, 42, 5, 0.32);
}
.fill-phone__screen {
  width: 100%;
  height: 100%;
  border-radius: 17px;
  background: linear-gradient(180deg, var(--paper-150), var(--paper-50));
  overflow: hidden;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 18px 12px 12px;
  position: relative;
}
.fill-phone__notch {
  position: absolute;
  top: 6px;
  left: 50%;
  transform: translateX(-50%);
  width: 34%;
  height: 6px;
  border-radius: var(--radius-pill);
  background: var(--green-ink);
  opacity: 0.9;
}
.fill-phone__greet { font-size: 10px; font-weight: 560; color: var(--warm-gray); }
.fill-phone__amount {
  font-size: 21px;
  font-weight: 640;
  letter-spacing: -0.02em;
  line-height: 1;
  color: var(--green-ink);
  font-variant-numeric: tabular-nums;
}
.fill-phone__chip {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 8px;
  border-radius: var(--radius-pill);
  background: var(--lime-200);
  color: var(--green-ink);
  font-size: 8.5px;
  font-weight: 640;
}
.fill-phone__chip::before {
  content: '';
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--green-success);
}
.fill-phone__spark {
  width: 100%;
  height: auto;
  margin-top: auto;
  overflow: visible;
}
.fill-phone__spark path {
  fill: none;
  stroke: var(--green-leaf);
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.fill-phone__spark circle { fill: #fff; stroke: var(--green-leaf); stroke-width: 2; }
.fill-phone__bar {
  height: 7px;
  border-radius: 4px;
  background: var(--paper-200);
}
.fill-phone__bar.is--w60 { width: 60%; }
.fill-phone__bar.is--w40 { width: 40%; }

/* ---------- Mini product shots (pills + empresas) ---------- */
.fill-shot {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2em;
}
/* Real product screenshots (captured from the live Fini app). The pill
   fills that had a real UI counterpart (anual/mensual/emitir/vigilar/saldo)
   now render an <img> that covers the pane; their .fill-shot.is--* gradient
   backgrounds were removed as fully unused. The product-reveal frame's img
   inherits the .pr-embed height (640/460) and crops from the top. */
.pr-embed--shot { object-fit: cover; object-position: top center; }
.fill-app { display: block; }
.fill-app__img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

.fill-shot.is--copiloto {
  background:
    radial-gradient(66% 58% at 78% 16%, rgba(193, 255, 71, 0.35) 0%, rgba(193, 255, 71, 0) 60%),
    linear-gradient(168deg, var(--paper-150) 0%, var(--paper-warm) 52%, var(--lime-100) 100%);
}
.fill-shot.is--emp1 {
  background:
    radial-gradient(70% 60% at 78% 10%, rgba(252, 244, 222, 0.85) 0%, rgba(252, 244, 222, 0) 60%),
    linear-gradient(158deg, var(--lime-100) 0%, var(--paper-150) 46%, var(--lime-300) 110%);
}
.fill-shot.is--emp2 {
  background:
    radial-gradient(68% 58% at 22% 88%, rgba(54, 181, 96, 0.24) 0%, rgba(54, 181, 96, 0) 60%),
    linear-gradient(200deg, var(--lime-200) 0%, #e2ffb0 52%, var(--paper-150) 100%);
}
.fill-shot.is--emp3 {
  background:
    radial-gradient(70% 58% at 80% 90%, rgba(210, 255, 138, 0.5) 0%, rgba(210, 255, 138, 0) 60%),
    linear-gradient(164deg, var(--paper-warm) 0%, var(--paper-150) 50%, var(--lime-100) 100%);
}

.fill-shot__card {
  width: min(380px, 100%);
  background: var(--paper-0);
  border: var(--hairline-soft);
  border-radius: var(--radius-lg);
  box-shadow:
    0 2px 6px rgba(20, 40, 8, 0.05),
    0 24px 60px rgba(20, 40, 8, 0.14);
  padding: 22px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  position: relative;
}
.fill-shot__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
.fill-shot__head img { height: 22px; display: block; }
.fill-shot__year {
  font-family: var(--font-label);
  font-size: var(--text-sm);
  color: var(--warm-gray);
  letter-spacing: 0.02em; /* match the mono-badge treatment (.pr-frame__badge/.hero-dash__year) */
}
.fill-shot__title {
  font-size: var(--text-sm);
  font-weight: 620;
  color: var(--green-ink);
  letter-spacing: -0.01em;
}
.fill-shot__chip {
  position: absolute;
  top: -13px;
  right: 18px;
  padding: 7px 13px;
  border-radius: var(--radius-pill);
  background: var(--lime-200);
  color: var(--green-ink);
  font-size: var(--text-sm);
  font-weight: 640;
  box-shadow: 0 8px 20px rgba(20, 40, 8, 0.18);
  white-space: nowrap;
}
.fill-shot__amt {
  font-size: 34px;
  font-weight: 640;
  letter-spacing: -0.02em;
  line-height: 1;
  color: var(--green-ink);
  font-variant-numeric: tabular-nums;
}
.fill-shot__amt small {
  font-size: max(0.42em, var(--text-sm));
  font-weight: 580;
  color: var(--green-olive);
  letter-spacing: 0;
}
.fill-shot__label {
  font-family: var(--font-label);
  font-size: var(--text-sm);
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--warm-gray);
}
/* Line placeholders reuse the editorial .acuse-doc__line primitive
   (+ .is--w70/.is--w50, already defined in editorial.css). Only the group
   wrapper is new here. */
.acuse-doc__lines { display: flex; flex-direction: column; gap: 7px; }

.fill-chart svg { display: block; width: 100%; height: auto; overflow: visible; }
.fill-chart .fill-chart__grid { stroke: var(--paper-200); stroke-width: 1; }
.fill-chart .fill-chart__area { fill: rgba(54, 181, 96, 0.16); }
.fill-chart .fill-chart__line {
  fill: none;
  stroke: var(--green-leaf);
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.fill-chart .fill-chart__dot { fill: #fff; stroke: var(--green-leaf); stroke-width: 2.5; }

.fill-shot__tiles {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}
.fill-shot__tile {
  background: var(--paper-50);
  border: var(--hairline-soft);
  border-radius: var(--radius-md);
  padding: 16px;
}
.fill-shot__tile-num {
  font-size: 30px;
  font-weight: 640;
  letter-spacing: -0.02em;
  line-height: 1;
  color: var(--green-ink);
  font-variant-numeric: tabular-nums;
}
.fill-shot__tile-lbl {
  font-family: var(--font-label);
  font-size: var(--text-sm);
  letter-spacing: 0.1em;
  color: var(--warm-gray);
  margin-top: 7px;
}

.fill-shot__prog {
  height: 6px;
  border-radius: var(--radius-pill);
  background: var(--paper-200);
  overflow: hidden;
}
.fill-shot__prog i {
  display: block;
  width: 75%;
  height: 100%;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--lime-bright), var(--green-leaf));
}

/* ---------- Pills cover: brand composition ---------- */
.fill-cover {
  display: flex;
  align-items: center;
  justify-content: center;
  background:
    radial-gradient(72% 60% at 28% 18%, rgba(252, 244, 222, 0.8) 0%, rgba(252, 244, 222, 0) 62%),
    linear-gradient(158deg, var(--lime-100) 0%, var(--lime-300) 52%, var(--lime-500) 100%);
}
.fill-cover__logo {
  width: min(320px, 56%);
  position: relative;
  z-index: 1;
  filter: drop-shadow(0 18px 40px rgba(20, 40, 8, 0.18));
}
.fill-cover .fill-scene__leaves.is--a {
  left: -8%;
  bottom: -16%;
  width: 52%;
  transform: rotate(18deg);
  opacity: 0.28;
}
.fill-cover .fill-scene__leaves.is--b {
  right: -6%;
  top: -14%;
  width: 36%;
  transform: rotate(-146deg);
  opacity: 0.24;
}

/* ---------- Avatar discs — one primitive for the feed shot + testimonials.
   Sized by context: the testimonial slot-fill fills its round-clipped visual;
   the feed shot opts into the fixed 32px .is--sm modifier. Shared gradient set. */
.fill-ava {
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  font-size: 1.7em;
  font-weight: 640;
  letter-spacing: -0.01em;
  color: var(--green-ink);
}
.fill-ava.is--sm { width: 32px; height: 32px; flex: none; font-size: var(--text-sm); }
.fill-ava.is--t1 { background: linear-gradient(135deg, var(--lime-200) 0%, #8fd66a 100%); }
.fill-ava.is--t2 { background: linear-gradient(135deg, var(--paper-warm) 0%, var(--lime-500) 100%); }
.fill-ava.is--t3 { background: linear-gradient(135deg, var(--paper-cream) 0%, var(--lime-300) 100%); }
.fill-ava.is--t4 { background: linear-gradient(135deg, #e4f6d2 0%, #74c463 100%); }

/* ---------- Fit inside the narrower pill pane / sticky column ---------- */
@media screen and (max-width: 1180px) {
  .fill-shot { padding: 1.25em; }
}

/* ============================================================================
   PASS A punch-list overrides (kept here so the base modules stay untouched).
   ============================================================================ */

/* ---------- A2 — magnetic cursor treatment A: the roaming dot retires (fx.js)
   and the control itself lifts on hover. Compose with the existing base.css
   .btn transitions (background/transform/border) + the :active press + the
   arrow nudge, adding box-shadow to the transition set. ---------- */
.btn {
  transition:
    background 180ms var(--ease-out),
    transform 120ms var(--ease-out),
    border-color 180ms var(--ease-out),
    box-shadow 180ms var(--ease-out);
}
.btn:hover { transform: translateY(-1px); box-shadow: 0 6px 18px rgba(20, 40, 8, 0.12); }
.btn:active { transform: scale(0.99); }
.twostep-nav__cta {
  transition:
    background 160ms var(--ease-out),
    transform 120ms var(--ease-out),
    color 160ms var(--ease-out),
    box-shadow 180ms var(--ease-out);
}
.twostep-nav__cta:hover { transform: translateY(-1px); box-shadow: 0 6px 18px rgba(20, 40, 8, 0.12); }

/* ---------- A3 — product-reveal breathing room + reframed corner floats ---------- */
.product-reveal__head { margin-bottom: 80px; }
.pr-float.is--a { top: -28px; right: 3%; bottom: auto; left: auto; }
.pr-float.is--b { bottom: -22px; left: 2.5%; top: auto; right: auto; }

/* ---------- A4 — dark-act glow moved to a child layer so it stays hidden until
   the page darkens; opacity is driven on the overlay's timeline (components2.js).
   Only the section's own gradient is removed — the no-js / reduced-motion
   background-color fallback (editorial.css) is left intact, and the glow child
   is shown statically in those cases. ---------- */
.act-dark { position: relative; background-image: none; }
.act-glow {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(60% 50% at 50% 0%, rgba(54, 181, 96, 0.14) 0%, rgba(0, 0, 0, 0) 70%);
}
html:not(.js) .act-glow { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .act-glow { opacity: 1; } }

/* ---------- A6/A9 — reserve the bento chart's height so injecting the SVG on
   scroll-into-view never shifts layout. Must match the SVG product.js builds
   (viewBox 0 0 320 132); 320/118 was 20px short, so the box grew ~20px on draw. */
.chart { aspect-ratio: 320 / 132; }

/* ---------- A6 — the final-CTA h2 constrained to 800px so its balanced 3-line
   wrap is stable. Root cause of the "3 lines then jumps to 2" scroll-jump: the
   reveal-group runs gsap clearProps:'all' on complete, which stripped the h2's
   INLINE max-width:800 — the heading then widened to the container (~1256px) and
   re-wrapped to 2 lines. As a stylesheet rule it survives clearProps, so the
   width (and the 3-line balance) never changes on reveal. ---------- */
.cta-final h2 { max-width: 800px; }

/* ---------- A7 — the "02 · Impacto" pane now shows the real saldo chart crop.
   Portrait source in a portrait-ish pane: cover, biased so the chart card
   stays centered/visible. ---------- */
/* Impacto pane: live app-style chart card over a botanical field (replaces
   the cropped screenshot — the portrait pane clipped the real capture) */
.fill-scene.is--emp2 {
  background:
    radial-gradient(58% 46% at 26% 12%, rgba(252, 244, 222, 0.85) 0%, rgba(252, 244, 222, 0) 60%),
    radial-gradient(94% 82% at 84% 106%, rgba(31, 110, 31, 0.48) 0%, rgba(31, 110, 31, 0) 66%),
    linear-gradient(166deg, var(--lime-100) 0%, #a9e276 46%, var(--green-leaf) 100%);
  display: flex;
  align-items: center;
  justify-content: center;
}
.fill-chart-card {
  width: min(78%, 420px);
  background: #fff;
  border: 1px solid rgb(232, 232, 228);
  border-radius: 18px;
  padding: 22px 24px 18px;
  box-shadow: 0 24px 60px rgba(12, 42, 5, 0.22);
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.fill-chart-card__title {
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: -0.01em;
  color: #0a0a0a;
}
.fill-chart-card .chart { aspect-ratio: 320 / 132; }
.fill-chart-card__legend { display: flex; gap: 16px; }
.fill-chart-card__key {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: var(--text-sm);
  font-weight: 560;
  color: var(--ink-500);
}
.fill-chart-card__key::before { content: ''; width: 14px; height: 2px; border-radius: 1px; }
.fill-chart-card__key.is--real::before { background: var(--green-leaf); }
.fill-chart-card__key.is--est::before {
  background: repeating-linear-gradient(90deg, var(--warm-gray) 0 3px, transparent 3px 6px);
}
/* Contain the empresas sticky-features horizontally. The section's 2-col layout
   fits the viewport, but the aspect-ratio/percentage-height chain in the image
   column can momentarily overflow (baseline already leaked ~79px at 1440; the
   real emp2 image pushed mobile to ~526px). overflow-x:clip stops any horizontal
   page scroll without creating a scroll container, so the sticky pin/reveal and
   the visible 2-col layout are unaffected. */
.empresas { overflow-x: clip; }

/* ---------- A8 — testimonials label ("Lo que dicen de Fini:") reads as body
   copy, not a mono all-caps eyebrow (overrides editorial.css). The numeric
   counter beside it keeps the mono treatment. ---------- */
.testimonial-lines__main-details .testimonial-lines__p:not(.is--faded) {
  font-family: inherit;
  text-transform: none;
  letter-spacing: -0.01em;
  font-size: var(--text-sm);
  font-weight: 560;
  color: var(--ink-500);
}

/* ---------- A10 — footer physics + anchoring. Full-height matter stage (leaves
   spawn at the footer's top edge), wordmark pinned to the bottom, physics floor
   = true page bottom (no footer bottom padding). ---------- */
.fp-matter { top: 0; bottom: 0; }
/* The full-height matter canvas (z3) now overlaps the sitemap/bottom rows. Those
   rows carry z-index:4, but .fp-footer .container (z-index:1, editorial.css) was
   trapping that inside its own stacking context, below the sibling canvas —
   clicks landed on the canvas. Flattening the container's context lets the rows'
   z4 sit above the canvas while the wordmark (z-auto) stays below it, so leaves
   still fall in front of "hey, fini" but every link stays clickable. */
.fp-footer .container { z-index: auto; }
.fp-footer { padding-bottom: 0; }
.fp-logo-row { margin-top: auto; padding-bottom: 20px; }
.fp-bottom { padding-bottom: 32px; }

/* ============================================================================
   PASS B — "Domina tu situación fiscal" bento (#ecosistema) redesign.
   Overrides kept here so the base modules stay untouched. Every rule is
   verified in BOTH the light entering state and the dark-act held state.
   ============================================================================ */

/* ---------- B1 — Saldo chart adopts the app's SaldoChart language. The dashed
   "estimate/optimal" series and the filled end dot need lime-cell colors that
   read on the lime gradient (the saldo cell stays lime even in the dark act). */
.bento__card.is--saldo .chart__est { stroke: rgba(20, 40, 8, 0.42); }
.bento__card.is--saldo .chart__dot { stroke: var(--green-ink); fill: var(--paper-0); }
.bento__card.is--saldo .chart__dot--end { fill: var(--green-ink); }
/* keep the actual line reading crisp above the lime fill */
.bento__card.is--saldo .chart__line { stroke: var(--green-ink); }

/* ---------- B2 — Declaraciones cell: larger, airier status timeline ---------- */
.bento__card.is--declaraciones .mock-step { padding-bottom: 24px; gap: 15px; }
.bento__card.is--declaraciones .mock-step:last-child { padding-bottom: 0; }
.bento__card.is--declaraciones .mock-step__dot { width: 28px; height: 28px; }
.bento__card.is--declaraciones .mock-step::before { left: 13px; top: 30px; }
.bento__card.is--declaraciones .mock-step__title { font-size: var(--text-md); }
.bento__card.is--declaraciones .mock-step__meta { font-size: var(--text-sm); margin-top: 2px; }

/* ---------- B2 — Depth-tile cards rebuilt as the app's year cards. Taller,
   real content, and a strong shadow so the white/gradient cards pop over the
   dark-act background they float on. ---------- */
.bento .depth-tiles { height: 340px; }
.bento .dt-card {
  aspect-ratio: auto;
  width: clamp(190px, 17vw, 260px);
  background: var(--paper-0);
  border: 1.5px solid transparent;
  border-radius: 16px;
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.4);
  padding: 18px 18px 16px;
  gap: 0;
}
.dt-card__top { display: flex; align-items: flex-start; justify-content: space-between; margin-bottom: 16px; }
.dt-card__yr {
  font-family: var(--font-label);
  font-size: var(--text-sm);
  letter-spacing: 0.04em;
  color: var(--warm-gray);
}
.dt-card__ico {
  width: 32px; height: 32px;
  border-radius: 9px;
  background: var(--lime-200);
  display: grid; place-items: center;
  flex: none;
}
.dt-card__ico svg { width: 16px; height: 16px; }
.dt-card__amount {
  font-weight: 640;
  font-size: 30px;
  letter-spacing: -0.02em;
  line-height: 1;
  color: var(--green-ink);
  font-variant-numeric: tabular-nums;
}
.dt-card__sub { font-size: var(--text-sm); color: var(--warm-gray); margin-top: 6px; }
.dt-card__foot {
  margin-top: auto;
  padding-top: 16px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.dt-card__pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 11px 4px 9px;
  border-radius: 999px;
  background: var(--lime-200);
  color: var(--green-ink);
  font-size: var(--text-sm);
  font-weight: 640;
  letter-spacing: 0.01em;
}
.dt-card__pill::before {
  content: '';
  width: 5px; height: 5px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}
.dt-card__pill.is--done { background: var(--paper-200); color: var(--green-olive); }
.dt-card__arrow {
  width: 26px; height: 26px;
  border-radius: 50%;
  border: 1px solid var(--paper-200);
  display: grid; place-items: center;
  color: var(--warm-gray);
  flex: none;
}
.dt-card__arrow svg { width: 13px; height: 13px; }
/* current year gets an ink border + a slim lime underline */
.dt-card.is--current {
  border-color: var(--green-ink);
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.4), 0 3px 0 -1px var(--lime-200);
}
/* opportunity / unfiled year — the missed-money card */
.dt-card.is--opp {
  background: linear-gradient(135deg, var(--paper-150), var(--lime-100));
  border: 1px dashed var(--green-leaf);
  overflow: hidden;
}
.dt-card.is--opp .dt-card__yr { color: var(--green-olive); }
.dt-card.is--opp .dt-card__ico { background: var(--green-ink); }
.dt-card__spark { color: var(--lime-bright); font-size: var(--text-sm); line-height: 1; }
.dt-card__opp-label {
  font-family: var(--font-label);
  font-size: var(--text-sm);
  letter-spacing: 0.02em;
  color: var(--green-olive);
  margin-bottom: 8px;
}
.dt-card__amount.is--myst { filter: blur(1px); opacity: 0.55; }
.dt-card__opp-cta { font-size: var(--text-sm); color: var(--green-deep); font-weight: 560; margin-top: 6px; }
.dt-card__chip {
  display: inline-flex; align-items: center;
  padding: 5px 11px;
  border-radius: 999px;
  background: rgba(54, 181, 96, 0.1);
  color: var(--green-deep);
  font-size: var(--text-sm);
  font-weight: 620;
}
.dt-card.is--opp::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(115deg, transparent 35%, rgba(255, 255, 255, 0.5) 50%, transparent 65%);
  background-size: 300% 100%;
  background-position: 120% 0;
  animation: dt-shimmer 3s linear infinite;
}
@keyframes dt-shimmer { to { background-position: -120% 0; } }
@media (prefers-reduced-motion: reduce) { .dt-card.is--opp::after { animation: none; } }

/* ---------- B3 — Facturas feed: the "CFE · recibo de luz" (is--out) row icon
   used a dark #3f6b22 stroke that vanished on the near-black dark-act icon
   square. Give it a visible stroke + matching lime tint in both states. ------- */
.mock-fila__icon.is--out svg { stroke: var(--green-olive); }
.act-dark .mock-fila__icon.is--out { background: rgba(193, 255, 71, 0.12); }
.act-dark .mock-fila__icon.is--out svg { stroke: var(--lime-bright); }

/* ---------- B4 — Deducibles: the not-yet-found chips read as missed money /
   opportunities, not disabled state — dashed leaf border, faint lime wash,
   a leading "+" and a gentle attention pulse. ---------- */
.mock-dchip:not(.is--found) {
  border: 1px dashed var(--green-leaf);
  background: rgba(193, 255, 71, 0.06);
  color: var(--green-olive);
  animation: dchip-pulse 3s ease-in-out infinite;
}
.mock-dchip:not(.is--found)::before {
  content: '+';
  font-weight: 700;
  font-size: var(--text-sm);
  line-height: 1;
  color: var(--green-leaf);
}
@keyframes dchip-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(54, 181, 96, 0); }
  50% { box-shadow: 0 0 0 4px rgba(54, 181, 96, 0.09); }
}
.act-dark .mock-dchip:not(.is--found) {
  border-color: rgba(193, 255, 71, 0.5);
  background: rgba(193, 255, 71, 0.08);
  color: rgba(237, 243, 232, 0.85);
}
.act-dark .mock-dchip:not(.is--found)::before { color: var(--lime-bright); }
.act-dark .mock-dchip:not(.is--found) {
  animation-name: dchip-pulse-dark;
}
@keyframes dchip-pulse-dark {
  0%, 100% { box-shadow: 0 0 0 0 rgba(193, 255, 71, 0); }
  50% { box-shadow: 0 0 0 4px rgba(193, 255, 71, 0.12); }
}
@media (prefers-reduced-motion: reduce) {
  .mock-dchip:not(.is--found) { animation: none; }
}

/* ---------- B5 — Copiloto cell top-aligns with the other bento cards (was
   vertically centered). A slight optical offset keeps the chat balanced
   against the taller text column. ---------- */
.bento__card.is--copiloto { align-items: flex-start; }
.bento__card.is--copiloto .bento__chat { margin-top: 6px; }

/* ---------- QA fix F4 — pricing note contrast: warm-gray (~2.6:1) fails AA.
   ink-500 (#717171) lands ~4.8:1 on paper. Its <strong> stays green-deep. ---------- */
.pricing__note { color: var(--ink-500); }

/* ---------- QA fix F7 — reduced-motion guard for the pulse-dot usages
   (hero counter chip + saldo-label live dots). ---------- */
@media (prefers-reduced-motion: reduce) {
  .hero__counter-chip::before,
  .hero-dash__saldo-label::before { animation: none; }
}

/* ============================================================================
   v2 fills — regimes gallery scenes, empresas tab/exp shots, blog editorial
   Each is a botanical gradient scene (one hue family) with leaf motifs, on the
   same system as fill-scene/fill-shot above. All aria-hidden decorative. */

/* ---------- Regimes gallery scenes (4 hue families, reused in #para-quien) ---- */
.fill-scene.is--rg-asalariado {
  background:
    radial-gradient(66% 56% at 22% 16%, rgba(252, 244, 222, 0.92) 0%, rgba(252, 244, 222, 0) 62%),
    radial-gradient(90% 74% at 88% 104%, rgba(31, 110, 31, 0.30) 0%, rgba(31, 110, 31, 0) 64%),
    linear-gradient(158deg, var(--paper-cream) 0%, #dcecb6 50%, var(--lime-500) 100%);
}
.fill-scene.is--rg-resico {
  background:
    radial-gradient(62% 54% at 78% 14%, rgba(193, 255, 71, 0.40) 0%, rgba(193, 255, 71, 0) 60%),
    radial-gradient(96% 80% at 14% 100%, rgba(54, 181, 96, 0.38) 0%, rgba(54, 181, 96, 0) 66%),
    linear-gradient(166deg, var(--lime-100) 0%, #b7e888 52%, var(--green-leaf) 108%);
}
.fill-scene.is--rg-actividad {
  background:
    radial-gradient(64% 54% at 20% 20%, rgba(210, 255, 138, 0.55) 0%, rgba(210, 255, 138, 0) 60%),
    radial-gradient(92% 78% at 90% 108%, rgba(12, 42, 5, 0.42) 0%, rgba(12, 42, 5, 0) 62%),
    linear-gradient(150deg, #c9dfa6 0%, var(--green-olive) 96%);
}
.fill-scene.is--rg-plataformas {
  background:
    radial-gradient(60% 52% at 82% 16%, rgba(168, 224, 96, 0.5) 0%, rgba(168, 224, 96, 0) 58%),
    radial-gradient(96% 84% at 10% 104%, rgba(20, 40, 8, 0.5) 0%, rgba(20, 40, 8, 0) 64%),
    linear-gradient(172deg, #a9e276 0%, var(--green-deep) 100%);
}
/* distinct leaf arrangement per regime so no two scenes read alike */
.fill-scene.is--rg-asalariado .fill-scene__leaves.is--a { transform: rotate(18deg); width: 58%; }
.fill-scene.is--rg-resico    .fill-scene__leaves.is--a { left: auto; right: -8%; transform: rotate(-14deg) scaleX(-1); }
.fill-scene.is--rg-resico    .fill-scene__leaves.is--b { right: auto; left: -5%; transform: rotate(-150deg); }
.fill-scene.is--rg-actividad .fill-scene__leaves.is--a { transform: rotate(32deg); width: 64%; }
.fill-scene.is--rg-plataformas .fill-scene__leaves.is--a { left: auto; right: -6%; transform: rotate(-24deg); width: 54%; }
.fill-scene.is--rg-plataformas .fill-scene__leaves.is--b { right: auto; left: -4%; transform: rotate(-168deg); }
/* deep-hued scenes (actividad/plataformas) get brighter leaves for contrast */
.fill-scene.is--rg-actividad .fill-scene__leaves path:nth-child(1),
.fill-scene.is--rg-plataformas .fill-scene__leaves path:nth-child(1) { fill: rgba(237, 243, 232, 0.34); }
.fill-scene.is--rg-actividad .fill-scene__leaves path:nth-child(3),
.fill-scene.is--rg-plataformas .fill-scene__leaves path:nth-child(3) { fill: rgba(193, 255, 71, 0.42); }
.rg-scene__glow {
  position: absolute;
  inset: 0;
  background: radial-gradient(42% 40% at 30% 78%, rgba(253, 255, 250, 0.28) 0%, rgba(253, 255, 250, 0) 70%);
  pointer-events: none;
}

/* ---------- Empresas tab mini-UI shots (reuse fill-shot vocabulary) ---------- */
.fill-shot.is--emp-rh {
  background:
    radial-gradient(70% 60% at 80% 12%, rgba(210, 255, 138, 0.5) 0%, rgba(210, 255, 138, 0) 60%),
    linear-gradient(160deg, var(--paper-150) 0%, var(--paper-warm) 50%, var(--lime-100) 100%);
}
.fill-shot.is--emp-fin {
  background:
    radial-gradient(66% 56% at 20% 14%, rgba(252, 244, 222, 0.85) 0%, rgba(252, 244, 222, 0) 60%),
    linear-gradient(168deg, var(--lime-100) 0%, var(--paper-150) 54%, var(--lime-300) 116%);
}
.fill-shot__total {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding-top: 12px;
  border-top: var(--hairline-soft);
}
.fill-shot__total-lbl { font-family: var(--font-label); font-size: var(--text-sm); letter-spacing: 0.02em; color: var(--ink-500); }
.fill-shot__total-amt { font-size: 20px; font-weight: 640; letter-spacing: -0.02em; color: var(--green-ink); font-variant-numeric: tabular-nums; }
.fill-shot__doclbl { font-family: var(--font-label); font-size: var(--text-sm); letter-spacing: 0.02em; color: var(--ink-500); }

/* ---------- Empresas "Experiencia" cascading scenes (4 distinct hues) -------- */
.fill-scene.is--emp-exp1 {
  background:
    radial-gradient(60% 52% at 24% 18%, rgba(252, 244, 222, 0.85) 0%, rgba(252, 244, 222, 0) 60%),
    linear-gradient(160deg, var(--lime-100) 0%, #bfe793 54%, var(--green-leaf) 112%);
}
.fill-scene.is--emp-exp2 {
  background:
    radial-gradient(62% 54% at 80% 14%, rgba(193, 255, 71, 0.4) 0%, rgba(193, 255, 71, 0) 58%),
    linear-gradient(150deg, #d7ecb4 0%, var(--green-olive) 100%);
}
.fill-scene.is--emp-exp3 {
  background:
    radial-gradient(60% 52% at 22% 84%, rgba(54, 181, 96, 0.3) 0%, rgba(54, 181, 96, 0) 60%),
    linear-gradient(168deg, var(--paper-cream) 0%, #cfe6a6 52%, var(--lime-500) 106%);
}
.fill-scene.is--emp-exp4 {
  background:
    radial-gradient(64% 54% at 82% 16%, rgba(168, 224, 96, 0.5) 0%, rgba(168, 224, 96, 0) 58%),
    linear-gradient(172deg, #a9e276 0%, var(--green-deep) 100%);
}
.fill-scene.is--emp-exp2 .fill-scene__leaves.is--a { transform: rotate(30deg); width: 60%; }
.fill-scene.is--emp-exp3 .fill-scene__leaves.is--a { left: auto; right: -8%; transform: rotate(-16deg) scaleX(-1); }
.fill-scene.is--emp-exp4 .fill-scene__leaves.is--a { left: auto; right: -6%; transform: rotate(-22deg); }
.fill-scene.is--emp-exp4 .fill-scene__leaves path:nth-child(1) { fill: rgba(237, 243, 232, 0.32); }
.fill-scene.is--emp-exp4 .fill-scene__leaves path:nth-child(3) { fill: rgba(193, 255, 71, 0.42); }

/* ---------- Blog editorial scenes (shared composition, one motif per topic) --- */
.fill-topic__mark {
  position: absolute;
  left: 18px; bottom: 16px;
  width: 46px; height: 46px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 13px;
  background: rgba(253, 255, 250, 0.9);
  box-shadow: 0 8px 20px rgba(20, 40, 8, 0.14);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}
.fill-topic__mark i { width: 24px; height: 24px; display: block; color: var(--green-deep); }
.fill-topic__mark i svg { width: 24px; height: 24px; }
.fill-topic__chip {
  position: absolute;
  right: 16px; top: 16px;
  padding: 5px 11px;
  border-radius: var(--radius-pill);
  background: var(--green-ink);
  color: var(--lime-bright);
  font-family: var(--font-label);
  font-size: var(--text-sm);
  letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
}
.fill-scene.is--blog-c1 { background: radial-gradient(64% 54% at 24% 18%, rgba(252,244,222,0.9) 0%, rgba(252,244,222,0) 60%), linear-gradient(158deg, var(--paper-cream) 0%, #dcecb6 54%, var(--lime-500) 108%); }
.fill-scene.is--blog-c2 { background: radial-gradient(62% 52% at 80% 14%, rgba(193,255,71,0.4) 0%, rgba(193,255,71,0) 58%), linear-gradient(166deg, var(--lime-100) 0%, #b7e888 52%, var(--green-leaf) 110%); }
.fill-scene.is--blog-c3 { background: radial-gradient(60% 52% at 22% 82%, rgba(54,181,96,0.3) 0%, rgba(54,181,96,0) 60%), linear-gradient(150deg, #cfe0ac 0%, var(--green-olive) 100%); }
.fill-scene.is--blog-c4 { background: radial-gradient(66% 56% at 82% 16%, rgba(210,255,138,0.5) 0%, rgba(210,255,138,0) 60%), linear-gradient(168deg, var(--paper-warm) 0%, var(--paper-150) 50%, var(--lime-100) 100%); }
.fill-scene.is--blog-c5 { background: radial-gradient(60% 52% at 20% 16%, rgba(252,244,222,0.85) 0%, rgba(252,244,222,0) 60%), linear-gradient(160deg, #e7f0d6 0%, #a9e276 100%); }
.fill-scene.is--blog-c6 { background: radial-gradient(62% 54% at 80% 84%, rgba(168,224,96,0.5) 0%, rgba(168,224,96,0) 58%), linear-gradient(172deg, #bfe793 0%, var(--green-deep) 116%); }
.fill-scene.is--blog-c3 .fill-scene__leaves path:nth-child(1),
.fill-scene.is--blog-c6 .fill-scene__leaves path:nth-child(1) { fill: rgba(237,243,232,0.32); }
.fill-scene.is--blog-c3 .fill-scene__leaves path:nth-child(3),
.fill-scene.is--blog-c6 .fill-scene__leaves path:nth-child(3) { fill: rgba(193,255,71,0.42); }
.fill-scene.is--blog-c2 .fill-scene__leaves.is--a { left: auto; right: -8%; transform: rotate(-14deg) scaleX(-1); }
.fill-scene.is--blog-c4 .fill-scene__leaves.is--a { transform: rotate(28deg); width: 60%; }
.fill-scene.is--blog-c6 .fill-scene__leaves.is--a { left: auto; right: -6%; transform: rotate(-22deg); }

/* Featured + post cover — the signature saldo-a-favor scene (warm lime, chart) */
.fill-scene.is--blog-feat,
.fill-scene.is--post-cover {
  background:
    radial-gradient(50% 46% at 26% 20%, rgba(252,244,222,0.9) 0%, rgba(252,244,222,0) 62%),
    radial-gradient(80% 70% at 86% 104%, rgba(31,110,31,0.34) 0%, rgba(31,110,31,0) 64%),
    linear-gradient(158deg, var(--lime-100) 0%, #b7e888 50%, var(--green-leaf) 112%);
}
.fill-feat__spark {
  position: absolute;
  right: 8%; bottom: 14%;
  width: 46%; height: auto;
  overflow: visible;
}
.fill-feat__spark path { fill: none; stroke: var(--green-deep); stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
.fill-feat__spark circle { fill: #fff; stroke: var(--green-deep); stroke-width: 2.4; }

/* ---------- v2 scene leaf calibration ----------
   The v2 panes (regime slides, blog cards/featured, emp-exp, post cover) are
   wider/shorter than the tall vida cascading panes, so the base 58%-width leaves
   overflowed into oversized dark blobs. Shrink them to corner accents and soften
   opacity so they read as subtle botanical texture over the gradient fields.
   (Appended last → wins the per-scene width rules above by source order.) */
.fill-scene[class*="is--rg-"] .fill-scene__leaves.is--a,
.fill-scene[class*="is--emp-exp"] .fill-scene__leaves.is--a,
.fill-scene[class*="is--blog-"] .fill-scene__leaves.is--a,
.fill-scene.is--post-cover .fill-scene__leaves.is--a { width: 26%; opacity: 0.30; }
.fill-scene[class*="is--rg-"] .fill-scene__leaves.is--b,
.fill-scene[class*="is--emp-exp"] .fill-scene__leaves.is--b,
.fill-scene[class*="is--blog-"] .fill-scene__leaves.is--b,
.fill-scene.is--post-cover .fill-scene__leaves.is--b { width: 18%; opacity: 0.24; }
/* deep-hued scenes keep their brighter leaves a touch more present */
.fill-scene.is--rg-actividad .fill-scene__leaves.is--a,
.fill-scene.is--rg-plataformas .fill-scene__leaves.is--a,
.fill-scene.is--emp-exp4 .fill-scene__leaves.is--a,
.fill-scene.is--blog-c3 .fill-scene__leaves.is--a,
.fill-scene.is--blog-c6 .fill-scene__leaves.is--a { width: 30%; opacity: 0.42; }

/* === RUN3 scroll-stability === */
/* Chrome scroll anchoring picks the deepest visible element as its anchor and
   follows that anchor's VISUAL movement — including composited transform
   animations. With the hero partially above the fold (e.g. reading #producto),
   it anchored on the hero bg image, whose ambient hero-drift scale/translate
   keyframes then dragged scrollY down 3–7px every ~2.7s (a slow, endless
   downward crawl with zero layout change; reproduced headless, gone with the
   animation off). Exclude the hero's continuously-animated decorative layers
   from anchor selection so Chrome anchors on real (static) content instead.
   Text/CTAs in the hero stay eligible anchors. Applies to every page's hero. */
.hero__bg, .hero__bg *,
.hero__fg, .hero__fg *,
.hero__scrollcue, .hero__scrollcue * { overflow-anchor: none; }

/* Deducibles chips: constant width across the found transition. product.css
   already reserves the 16px check box; but the B4 "+" ::before (above) still
   dropped when .is--found landed, changing the chip's width — at some
   viewports that flips .mock-dchips' wrap point and re-grows #ecosistema.
   For chips that can be found ([data-found="1"] carries the check span), the
   "+" renders INSIDE the reserved slot and morphs into the green check, so
   the chip never changes width. Never-found chips keep the plain B4 "+". */
.mock-dchip[data-found="1"]::before { content: none; }
.mock-dchip[data-found="1"]:not(.is--found) .mock-dchip__check {
  opacity: 1;
  transform: none;
  background: transparent;
}
.mock-dchip[data-found="1"]:not(.is--found) .mock-dchip__check::before {
  content: '+';
  font-weight: 700;
  font-size: var(--text-sm);
  line-height: 1;
  color: var(--green-leaf);
}
.mock-dchip[data-found="1"]:not(.is--found) .mock-dchip__check svg { opacity: 0; }
.act-dark .mock-dchip[data-found="1"]:not(.is--found) .mock-dchip__check::before { color: var(--lime-bright); }

/* === RUN3 mobile-bundle === */
/* Mobile/responsive polish for the home page: B2 phone product view, B4 bento
   full-bleed clip, B5 cascading full-bleed, B6 pill sizing, B7 footer geometry.
   Appended so the base modules stay untouched; fills.css is the last stylesheet
   so these win on ties. Desktop layouts above the noted breakpoints unchanged. */

/* ---- B2 — "Mira todo tu SAT en una pantalla": phone view on mobile ----
   The desktop 3024×1900 dashboard screenshot is illegible on phones. Below the
   product section's own degrade point (760px, where .pr-embed shrinks and the
   float chips hide) we swap the browser-chrome frame for a believable phone
   frame showing real app captures stacked like the Fini app feed. */
.pr-phone { display: none; }
@media screen and (max-width: 760px) {
  .pr-frame { display: none; }
  .pr-phone {
    display: block;
    position: relative;
    z-index: 2;
    width: min(320px, 78vw);
    margin: 0 auto;
    background: var(--green-ink);
    border-radius: 44px;
    padding: 10px;
    box-shadow:
      0 2px 6px rgba(12, 42, 5, 0.18),
      0 30px 60px rgba(12, 42, 5, 0.26);
  }
  .pr-phone__notch {
    position: absolute;
    top: 20px;
    left: 50%;
    transform: translateX(-50%);
    width: 32%;
    height: 6px;
    border-radius: var(--radius-pill);
    background: rgba(253, 255, 250, 0.22);
    z-index: 3;
  }
  .pr-phone__screen {
    border-radius: 34px;
    overflow: hidden;
    background: var(--paper-100);
    box-shadow: inset 0 0 0 1px rgba(12, 42, 5, 0.05);
    padding: 26px 11px 13px;
    display: flex;
    flex-direction: column;
    gap: 11px;
  }
  .pr-phone__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 0 3px 2px;
  }
  .pr-phone__pill {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--warm-gray);
    background: var(--paper-0);
    border: var(--hairline-soft);
    padding: 4px 10px;
    border-radius: var(--radius-pill);
  }
  .pr-phone__pill svg { width: 10px; height: 10px; }
  .pr-phone__badge {
    font-size: var(--text-sm);
    font-weight: 640;
    color: var(--green-deep);
    background: var(--lime-100);
    padding: 4px 9px;
    border-radius: var(--radius-pill);
    white-space: nowrap;
  }
  .pr-phone__feed { display: flex; flex-direction: column; gap: 10px; }
  .pr-phone__shot {
    display: block;
    width: 100%;
    height: auto;
    object-fit: cover;
    object-position: center;
    border-radius: 14px;
    background: var(--paper-100);
  }
  /* Crop the app captures to their card so the feed stays tight (the crops carry
     generous backdrop margins that match the screen bg, so the trim is seamless). */
  .pr-phone__shot.is--saldo { aspect-ratio: 3 / 2; }
  .pr-phone__shot.is--calendar { aspect-ratio: 1 / 1; }
}

/* ---- B4 — "Declaraciones que se presentan solas" bento: full-bleed clip.
   On phones the depth-tile stack was clipped by .depth-tiles' box, which sits
   inset by the card's 32px padding, so cards looked cut off mid-air. Extend the
   strip to the card's rounded border (negative margins = card padding) so the
   cards slide under the card edge instead. .depth-tiles keeps overflow:clip and
   the card keeps overflow:hidden + border-radius, so corners round the strip. */
@media screen and (max-width: 767px) {
  .bento__card.is--declaraciones .depth-tiles {
    margin-left: -32px;
    margin-right: -32px;
    width: calc(100% + 64px);
  }
}

/* ---- B5 — "Vive tu vida. Fini trabaja": cascading slider full-bleed.
   Remove the container's 20px side padding at mobile so the photo component runs
   edge-to-edge. Negative margins against the real container padding (no 100vw,
   which would add scrollbar overflow). The slider list clips its own overflow. */
@media screen and (max-width: 767px) {
  .photo-trio [data-cascading-slider-wrap] {
    margin-left: -20px;
    margin-right: -20px;
    width: calc(100% + 40px);
    max-width: none;
  }
}

/* ---- B6 — "Explora pieza por pieza": larger, tappable feature pills.
   A touch more padding at desktop; noticeably more at mobile (≥48px targets). */
.feature-pills__item-button { padding: 0.9em 1.4em; }
@media screen and (max-width: 767px) {
  .feature-pills__item-button {
    font-size: var(--text-sm);
    padding: 0.95em 1.4em;
    min-height: 48px;
  }
  .feature-pills__item-label { font-size: 1.22em; }
}

/* ---- B7 — Footer geometry.
   Tall viewports: the footer is min-height:96svh (flex column) but its only
   in-flow child is .container (block), so margin-top:auto on .fp-logo-row (set
   above) was inert and the logo/wordmark floated with dead space beneath it.
   Make .container a flex column that fills the footer height so the existing
   margin-top:auto pins the logo block to the true bottom. On mobile the footer
   is min-height:auto (≤860, components2.css), so .container grows only to its
   content — no dead stretch — and .fp-logo-row's reserved leaf zone keeps a
   fixed gap between the sitemap and the logo. */
.fp-footer .container {
  display: flex;
  flex-direction: column;
  flex: 1 0 auto;
}
@media screen and (max-width: 767px) {
  /* Trim the sitemap's top breathing room so the (fit-to-content) footer isn't
     needlessly long; the reserved leaf zone (.fp-logo-row min-height) is kept. */
  .fp-footer { padding-top: 52px; }
}

/* === RUN3 motion === */
/* Motion/design upgrade (run #3, items D1–D6). One appended block; earlier
   blocks untouched. Every animation here is gated behind html.js (reveals are
   hidden only when JS is present, so no-JS/failed-CDN users see all content)
   and fully neutralised under prefers-reduced-motion. */

/* ---------- D1 — button character stagger (Osmo pattern) ----------
   fx.js splits each opted-in CTA label ([data-btn-chars]) into .btn-char spans.
   A currentColor text-shadow ghost sits one line below; on hover each char
   rolls up by the same distance so the ghost slides into its place, staggered
   by --i. nowrap + pre keep the button's width identical and spaces intact; the
   ghost is clipped by the container's overflow until it is called on. The lift
   is a transform on the chars — independent of the button's own magnetic hover
   treatment, so both coexist. */
[data-btn-chars] {
  display: inline-flex;
  flex-wrap: nowrap;
  white-space: nowrap;
  overflow: hidden;
  line-height: 1.2;
  vertical-align: bottom;
}
[data-btn-chars] .btn-char {
  display: inline-block;
  white-space: pre;
}
@media (prefers-reduced-motion: no-preference) {
  [data-btn-chars].btn-chars--ready .btn-char {
    text-shadow: 0 1.2em currentColor;
    transition: transform 0.42s cubic-bezier(0.19, 1, 0.22, 1);
    transition-delay: calc(var(--i, 0) * 0.012s);
    will-change: transform;
  }
  .btn:hover [data-btn-chars] .btn-char,
  .twostep-nav__cta:hover [data-btn-chars] .btn-char {
    transform: translateY(-1.2em);
  }
}

/* ---------- D4 — cursor grows over plain links/buttons ----------
   The roaming dot (.cursor writes transform x/y via GSAP; we never touch that).
   On hover of any link/button that is NOT a magnetic target, the visible disc
   (.cursor-bg) scales up and goes translucent — a subtle lime-family focus.
   Scaling the child (not .cursor) keeps GSAP's xPercent/yPercent centring exact.
   Magnetic targets keep treatment A (the dot retires) untouched. Pure CSS via
   :has(); unsupported browsers simply keep the plain dot. */
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
  .cursor-bg {
    transition: transform 0.3s var(--ease-out), opacity 0.3s var(--ease-out), background-color 0.3s var(--ease-out);
  }
  body:has(a:not([data-magnetic-cursor-target]):hover) .cursor-bg,
  body:has(button:not([data-magnetic-cursor-target]):hover) .cursor-bg {
    transform: scale(3);
    opacity: 0.3;
    background: var(--green-leaf);
  }
}

/* ---------- D5 — cross-fade page-transition overlay ----------
   Fixed full-viewport paper curtain, never interactive. Opaque only under
   html.js so no-JS users never see a blank page; fx.js fades it out on load and
   in before an internal navigation. z-index sits above nav/content but below the
   first-visit loader (200) and the cursor (300). Inert under reduced motion. */
.page-fade {
  position: fixed;
  inset: 0;
  z-index: 180;
  background: var(--paper-150);
  opacity: 0;
  pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
  .js .page-fade { opacity: 1; }
}

/* ---------- D6/D2 — heading blur-zoom + masked lede reveal gates ----------
   Hidden only under html.js + no-reduced-motion; fx.js animates them in. The
   masked lede lines reuse .text-line-mask (sections.css) so descenders aren't
   clipped and the split leaves the element's height identical. */
@media (prefers-reduced-motion: no-preference) {
  .js [data-blur-head] { opacity: 0; }
  .js [data-split="lede"] { opacity: 0; }
}
/* A blurred heading paints a soft halo past its box; keep it from being clipped
   by an ancestor and keep will-change scoped to the animating element only. */
[data-blur-head] { will-change: auto; }

/* === RUN3 polish === */
/* Final pass (run #3 taste items P2/P4). One appended block; earlier blocks
   untouched. */

/* ---------- P2 — footer dead band ----------
   The 96svh footer floor left ~550px of empty green between the sitemap and
   the wordmark on tall viewports (and ~305px on phones via the reserved
   min-height rows). The footer is now content-sized and the sitemap→wordmark
   air is an explicit clamp(120px, 18vh, 260px) spacer on .fp-logo-row:
   - margin-top:auto (set in an earlier block) goes inert once the container
     is no longer stretched, so the gap IS the padding — deterministic at
     every viewport, measured once at load (no post-load height changes).
   - The footer stays the last element, so its bottom stays flush with the
     viewport at max scroll; the wordmark keeps hugging the page bottom.
   - Leaf physics still read: leaves spawn at the footer's very top (full-
     height stage) and fall past the sitemap into the gap + wordmark zone;
     the settled pile (~1 leaf diameter above the P1 floor at the legal row)
     stays inside wordmark height + gap at every width. This supersedes the
     earlier 520px/430px .fp-logo-row reservations — the @≤480 430px rule
     existed to park the sitemap below the fixed nav pill at max scroll, and
     a SHORTER footer moves the sitemap further down still, so that
     protection's intent is preserved (re-verified via elementFromPoint). */
.fp-footer { min-height: 0; }
.fp-logo-row { min-height: 0; padding-top: clamp(120px, 18vh, 260px); }
/* ≤520 the sitemap is a single-column stack: with the clamp gap the footer's
   natural end parked "Ecosistema"/"Plataforma" exactly behind the fixed nav
   pill (rect ≈ y20–84 at 390×844) — the very state the v1 @≤480 fix removed.
   Sixty fewer px below the links (gap 152→100, legal padding 32→24) rests the
   whole sitemap below the pill's footprint at max scroll (first link ≈ y100,
   pill bottom 84). 100px of air still clears the dead-band complaint (was
   ~305px) and the leaf zone (~225px incl. wordmark) still fits the ≤7-leaf
   mobile pile (~90px). */
@media screen and (max-width: 520px) {
  .fp-logo-row { padding-top: 100px; }
  .fp-bottom { padding-bottom: 24px; }
}

/* ---------- P4 — landing hero furniture entrance gate ----------
   CTAs, trust row and scrollcue were static from frame 0 while the heading and
   lede animated in (content-order inversion). fx.js gives them a late entrance
   (opacity/y only) ~0.15s after the lede starts. Hidden ONLY under html.js +
   no-reduced-motion — the exact D6/D2 gate pattern — so no-JS, failed-CDN
   (onerror strips .js) and reduced-motion paths always see them. Scoped to
   #inicio: the Empresas hero shares .hero--lead but not this choreography. */
@media (prefers-reduced-motion: no-preference) {
  .js #inicio .hero__ctas,
  .js #inicio .hero__assure,
  .js #inicio .hero__trust,
  .js #inicio .hero__scrollcue { opacity: 0; }
}

/* === RUN4 scene-motifs === */
/* The taste review called the regime fill-scenes "atmosphere without content".
   Each now carries ONE quiet content motif — a faint UI fragment + one mono
   chip — so the botanical field rewards a look without losing its calm. Static
   and decorative (the scene's own reveal/glow supplies all motion), aria-hidden.
   The SAME markup ships in the #regimenes gallery (44vw landscape pane) and the
   #para-quien sticky (portrait pane), so the motif is sized in container units
   (font-size in cqmin, everything else in em) to compose at both. Biased just
   right-of-centre so it clears the gallery's left copy-overlay mask and the
   top-left caption, and sits in each scene's open area. */
.fill-scene[class*="is--rg-"] { container-type: size; }
.rg-motif {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1.1em;
  /* asymmetric padding nudges the whole motif toward the open right side and a
     touch below true centre (clears caption top-left + is--a leaf bottom-left) */
  padding: 7% 9% 9% 20%;
  font-size: clamp(7px, 4cqmin, 16px);
  color: var(--green-ink);
  pointer-events: none;
}
/* shared mono chip — echoes .slide__caption + .fill-topic__chip grammar */
.rg-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  padding: 0.42em 0.85em;
  border-radius: var(--radius-pill);
  background: rgba(253, 255, 250, 0.72);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  font-family: var(--font-label);
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--green-deep);
  white-space: nowrap;
}
.rg-chip::before {
  content: '';
  width: 0.42em;
  height: 0.42em;
  border-radius: 50%;
  background: var(--green-leaf);
  flex: none;
}

/* asalariado — recibo/payslip fragment: 2 skeleton bars + recovered-saldo pill */
.rg-recibo {
  width: 13.5em;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.62em;
  padding: 1em 1.05em 1.05em;
  border-radius: 0.8em;
  background: rgba(253, 255, 250, 0.5);
  border: 1px solid rgba(20, 40, 8, 0.10);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
}
.rg-recibo__bar { height: 0.5em; border-radius: 0.3em; background: rgba(20, 40, 8, 0.16); }
.rg-recibo__bar.is--w75 { width: 78%; }
.rg-recibo__bar.is--w50 { width: 52%; }
.rg-recibo__amt {
  margin-top: 0.2em;
  padding: 0.34em 0.72em;
  border-radius: var(--radius-pill);
  background: var(--lime-200);
  color: var(--green-ink);
  font-size: var(--text-sm);
  font-weight: 680;
  letter-spacing: -0.015em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

/* resico — oversized, very faint RESICO rate watermark + rate chip. The numeral
   is sized in container units (not the em root) so it stays a genuine watermark
   at both pane sizes. */
.rg-motif.is--rate { gap: 0.9em; }
.rg-rate__num {
  font-size: clamp(42px, 40cqmin, 178px);
  font-weight: 680;
  line-height: 0.82;
  letter-spacing: -0.04em;
  color: rgba(20, 40, 8, 0.19);
  font-variant-numeric: tabular-nums;
}
.rg-rate__pct { font-size: 0.5em; font-weight: 640; letter-spacing: -0.02em; }

/* actividad — spark-line trending up (fill-phone__spark grammar) + chip */
.rg-spark { width: 11em; height: auto; overflow: visible; opacity: 0.9; }
.rg-spark path {
  fill: none;
  stroke: var(--green-deep);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.rg-spark circle { fill: var(--paper-50); stroke: var(--green-deep); stroke-width: 3; }

/* plataformas — cluster of 3 abstract app tiles (no real logos) + chip */
.rg-tiles { display: flex; gap: 0.6em; }
.rg-tile {
  position: relative;
  width: 3em;
  height: 3em;
  border-radius: 0.72em;
  background: rgba(253, 255, 250, 0.5);
  border: 1px solid rgba(20, 40, 8, 0.12);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
}
.rg-tile::before {
  content: '';
  position: absolute;
  inset: 0;
  margin: auto;
  background: rgba(20, 40, 8, 0.22);
}
/* three distinct neutral glyphs so the cluster reads as an app row, not a grid */
.rg-tile.is--t1::before { width: 0.9em; height: 0.9em; border-radius: 50%; }
.rg-tile.is--t2::before {
  width: 1.1em; height: 0.32em; border-radius: 0.16em;
  box-shadow: 0 -0.48em 0 rgba(20, 40, 8, 0.22), 0 0.48em 0 rgba(20, 40, 8, 0.22);
}
.rg-tile.is--t3::before {
  width: 0.9em; height: 0.9em; border-radius: 0.1em; background: none;
  border-right: 0.2em solid rgba(20, 40, 8, 0.22);
  border-bottom: 0.2em solid rgba(20, 40, 8, 0.22);
  transform: rotate(45deg) translateY(-0.12em);
}
/* deep-hued scenes (actividad/plataformas): lift ink motifs to a lighter tone
   so they stay legible over the darker green fields, matching how those scenes'
   leaves were already brightened above. */
.fill-scene.is--rg-actividad .rg-spark path { stroke: var(--lime-bright); }
.fill-scene.is--rg-actividad .rg-spark circle { stroke: var(--lime-bright); fill: var(--green-deep); }
.fill-scene.is--rg-plataformas .rg-tile { background: rgba(253, 255, 250, 0.42); border-color: rgba(253, 255, 250, 0.34); }
.fill-scene.is--rg-plataformas .rg-tile::before,
.fill-scene.is--rg-plataformas .rg-tile.is--t2::before { background: rgba(253, 255, 250, 0.6); box-shadow: none; }
.fill-scene.is--rg-plataformas .rg-tile.is--t2::before {
  box-shadow: 0 -0.48em 0 rgba(253, 255, 250, 0.6), 0 0.48em 0 rgba(253, 255, 250, 0.6);
}
.fill-scene.is--rg-plataformas .rg-tile.is--t3::before {
  background: none;
  border-right-color: rgba(253, 255, 250, 0.6);
  border-bottom-color: rgba(253, 255, 250, 0.6);
}
