/* ========================================================
   T1304 — Design tokens & shared styles
   Bg #0E0E0C · Accent #7A9E6A · Warning #B4694A
   Display: DM Serif Display · Body: DM Sans
   ======================================================== */

:root{
  --bg: #0E0E0C;
  --bg-raised: #17171310;
  --card: #16160F;
  --card-border: rgba(245,243,238,0.08);
  --card-border-hover: rgba(122,158,106,0.45);
  --text: #F5F3EE;
  --text-muted: #A6A398;
  --text-faint: #6E6C63;
  --accent: #7A9E6A;
  --accent-soft: rgba(122,158,106,0.14);
  --accent-strong: #93B683;
  --warn: #B4694A;
  --warn-soft: rgba(180,105,74,0.14);
  --serif: -apple-system, BlinkMacSystemFont, "SF Pro Display", "Inter", "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --sans: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Inter", "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --container: 1180px;
  --radius: 14px;
}

*{ box-sizing:border-box; }
html{ scroll-behavior:smooth; overflow-x:hidden; }
body{
  margin:0;
  background:var(--bg);
  color:var(--text);
  font-family:var(--sans);
  font-size:16px;
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
  /* overflow-x:hidden here (not just on html) used to break .site-header's
     position:sticky: the root element's overflow is special-cased onto the
     viewport itself, but this being a non-root element, it forced its own
     real scroll container into existence (the overflow-x/overflow-y
     pairing rule computes an unset overflow-y to "auto" the moment
     overflow-x isn't "visible") — the header then stuck to the top of
     THAT box instead of the actual page scroll, so it visually scrolled
     away instead of staying pinned. html's overflow-x:hidden alone already
     covers the horizontal-bleed case this was for. */
}
em{ font-style:normal; font-weight:600; }
img{ max-width:100%; display:block; }
a{ color:inherit; text-decoration:none; }
::selection{ background:var(--accent); color:#0E0E0C; }

.wrap{
  max-width:var(--container);
  margin:0 auto;
  padding:0 24px;
}

h1,h2,h3,h4{
  font-family:var(--serif);
  font-weight:600;
  line-height:1.05;
  margin:0;
  letter-spacing:-0.025em;
}
h1{ font-size:clamp(2.6rem, 5.6vw, 4.4rem); font-weight:700; }
h2{ font-size:clamp(1.9rem, 3.6vw, 2.8rem); }
h3{ font-size:clamp(1.3rem, 2.2vw, 1.6rem); font-weight:600; }

.eyebrow{
  font-family:var(--sans);
  font-size:0.72rem;
  letter-spacing:0.16em;
  text-transform:uppercase;
  color:var(--accent);
  display:inline-flex;
  align-items:center;
  gap:8px;
  margin-bottom:14px;
}
.eyebrow::before{
  content:"";
  width:18px; height:1px;
  background:var(--accent);
  display:inline-block;
}

.lede{
  color:var(--text-muted);
  font-size:1.08rem;
  max-width:56ch;
}

/* ---------- Buttons ---------- */
.btn{
  position:relative;
  overflow:hidden;
  display:inline-flex;
  align-items:center;
  gap:8px;
  padding:14px 26px;
  border-radius:999px;
  font-size:0.95rem;
  font-weight:500;
  cursor:pointer;
  border:1px solid transparent;
  transition:transform .25s ease, background .25s ease, border-color .25s ease, box-shadow .25s ease, color .25s ease;
  white-space:nowrap;
}
/* Diagonal light sweep on hover, shared by every .btn variant — a cheap,
   consistent "interactive" cue that doesn't fight each variant's own colors.
   Lives on ::before so it layers under the button's text/icon children. */
.btn::before{
  content:"";
  position:absolute; top:0; left:-75%;
  width:50%; height:100%;
  background:linear-gradient(120deg, transparent, rgba(255,255,255,0.35), transparent);
  transform:skewX(-20deg);
  transition:left .5s ease;
  pointer-events:none;
}
.btn:hover::before{ left:125%; }
.btn-primary{
  background:var(--accent);
  color:#0E0E0C;
  box-shadow:0 4px 18px -8px rgba(122,158,106,0.5);
}
.btn-primary:hover{
  background:var(--accent-strong);
  transform:translateY(-3px) scale(1.03);
  box-shadow:0 14px 34px -10px rgba(122,158,106,0.65);
}
.btn-ghost{
  background:rgba(122,158,106,0.07);
  border-color:rgba(122,158,106,0.35);
  color:var(--text);
}
/* Dark fill + glowing ring, not a solid green fill — keeps this visually
   distinct from .btn-primary's hover instead of both converging on the same
   green block. */
.btn-ghost:hover{
  background:#0B0B09;
  border-color:var(--accent-strong);
  color:var(--accent-strong);
  transform:translateY(-3px) scale(1.03);
  box-shadow:0 0 0 1px rgba(122,158,106,0.4), 0 14px 34px -10px rgba(122,158,106,0.55);
}

/* ---------- Nav ---------- */
.site-header{
  position:sticky; top:0; z-index:100;
  padding:18px 20px 0;
}
/* The pill itself carries the background/blur/border — .site-header stays
   transparent so the hero's own background (globe/starfield) shows through
   in the gap around it, which is what makes this read as a floating card
   instead of a full-width bar. */
.nav-inner{
  position:relative;
  display:flex; align-items:center; justify-content:space-between;
  max-width:1400px;
  margin:0 auto;
  padding:14px 30px 14px 28px;
  border:1px solid var(--card-border);
  border-radius:26px;
  transition:border-color .3s ease, box-shadow .3s ease;
}
/* The tint + blur live on this absolutely-positioned pseudo instead of
   directly on .nav-inner: backdrop-filter (like transform) turns its own
   element into the containing block for any position:fixed descendant, and
   .nav-links IS position:fixed below 860px (the slide-in mobile menu) — if
   .nav-inner itself carried the filter, the drawer would size itself
   against this ~70px pill instead of the real viewport. Parking the filter
   on a pseudo means .nav-links (a child of .nav-inner, not of the pseudo)
   never becomes a descendant of a filtered box, so the same frosted-glass
   look is now safe on mobile too, not just desktop. z-index:-1 keeps it
   behind the logo/links/CTA, which stay unpositioned so they paint over it
   in normal flow. */
.nav-inner::before{
  content:"";
  position:absolute; inset:0; z-index:-1;
  border-radius:inherit;
  background:rgba(14,14,12,0.18);
  backdrop-filter:blur(9px);
  -webkit-backdrop-filter:blur(9px);
  transition:background .3s ease;
}
.site-header.scrolled .nav-inner{
  border-color:var(--card-border-hover);
  box-shadow:0 12px 30px -12px rgba(0,0,0,0.5);
}
.site-header.scrolled .nav-inner::before{
  background:rgba(14,14,12,0.38);
  backdrop-filter:blur(12px);
  -webkit-backdrop-filter:blur(12px);
}
.logo{ display:flex; align-items:center; }
.logo-img{ height:34px; width:auto; display:block; }
.footer-grid .logo-img{ height:40px; }
.nav-links{ display:flex; align-items:center; gap:34px; }
.nav-links a{
  font-size:0.92rem; color:var(--text-muted);
  position:relative; padding:4px 0;
  transition:color .2s ease;
}
.nav-links a:hover{ color:var(--text); }
.nav-links a.active{ color:var(--accent); }
/* .nav-links a above (class+type selector) otherwise outranks .btn-primary's
   own color rule (single class) and forces this CTA's text to the muted nav
   color — nearly unreadable against the green fill. This restores the
   intended dark text, and bumps size/position for this header CTA
   (.nav-inner scopes it to the header — the hero's own "Hablemos" button
   lives in .hero-actions, untouched). Two copies of this button exist in
   the header markup (layout.js): .nav-links-cta is the one inside the nav
   links row, used only in the mobile slide-out panel; #navCtaDesktop is a
   separate flex item of .nav-inner, used only on desktop. They're mutually
   exclusive by breakpoint below — .nav-links is a single inline row on
   desktop, so a CTA living inside it can only ever sit snug against
   "Contacto" with the same gap as the other links, never genuinely
   separated at the far right; a sibling flex item of .nav-inner is what
   actually gets pushed there by justify-content:space-between. */
.nav-inner a.btn-primary{
  color:#0E0E0C;
  padding:18px 38px;
  font-size:1.05rem;
  border-color:rgba(223,240,216,0.5);
  box-shadow:0 0 22px 2px rgba(122,158,106,0.4);
}
.nav-inner a.btn-primary:hover{
  box-shadow:0 0 28px 4px rgba(122,158,106,0.6);
}
/* position+z-index: .nav-links is position:fixed covering the full height
   of the right 78% of the screen once open (see the mobile rule below) —
   that includes the space this toggle button sits in, since the button is
   also pinned to the right edge of the header. A positioned ancestor with
   z-index:auto (nav-links) still paints above any non-positioned sibling
   regardless of DOM order, so without lifting .nav-cta into its own
   stacked, higher layer here, the open drawer silently covered the only
   button that closes it. */
.nav-cta{ display:flex; align-items:center; gap:18px; position:relative; z-index:120; }
#navCtaDesktop{ display:none; }
.nav-toggle{
  display:none;
  align-items:center; justify-content:center;
  width:38px; height:38px;
  border-radius:12px;
  background:rgba(245,243,238,0.08);
  border:none; color:var(--text); font-size:1.4rem; line-height:1; cursor:pointer;
}
/* Mobile-only round CTA next to the hamburger — desktop already has the
   full "Hablemos" button (#navCtaDesktop), so this stays hidden until
   that one disappears at the same breakpoint. */
.nav-cta-mobile{
  display:none;
  align-items:center; justify-content:center;
  width:38px; height:38px;
  border-radius:12px;
  background:var(--accent);
  color:#0E0E0C;
  flex-shrink:0;
  box-shadow:0 4px 18px -8px rgba(122,158,106,0.5);
}
.nav-cta-mobile svg{ width:18px; height:18px; }

/* ---------- Nav: Servicios dropdown ----------
   Hover/focus-driven, no JS: .nav-item-dropdown is the positioning context.
   .nav-dropdown is the HOVER HITBOX — it sits flush against the link
   (top:100%, no margin) and uses padding-top instead of margin-top for the
   visual gap, so that gap is still inside its own box and stays
   mouse-over-able while the cursor travels down to the menu. Without this,
   a margin-based gap is dead space belonging to neither element: the
   pointer crosses it, :hover on the parent drops, opacity/pointer-events
   go to 0, and the menu vanishes before the cursor ever reaches it.
   .nav-dropdown-inner is the actual visible card (background/border/shadow)
   nested inside, so the invisible bridge padding doesn't itself look like
   part of the card. */
.nav-item-dropdown{ position:relative; }
.nav-item-dropdown-head{ display:flex; align-items:center; gap:2px; }
.nav-caret-btn{
  background:none; border:none; padding:0; margin:0;
  /* color (not "inherit"): this button sits next to the "Servicios" <a>
     but isn't one itself, so it doesn't pick up .nav-links a's muted
     color — buttons also don't inherit font-size/family from the page by
     default, which is why the old text-glyph caret (▾) rendered at the
     browser's tiny default UI-font size, all but invisible next to the
     link text. An SVG icon sized in px sidesteps that entirely. */
  color:var(--text-muted);
  cursor:pointer; display:inline-flex; align-items:center; line-height:1;
}
.nav-item-dropdown:hover .nav-caret-btn, .nav-item-dropdown:focus-within .nav-caret-btn{ color:var(--text); }
.nav-caret{ width:14px; height:14px; display:inline-block; transition:transform .2s ease; }
.nav-item-dropdown:hover .nav-caret, .nav-item-dropdown:focus-within .nav-caret{ transform:translateY(1px) rotate(180deg); }
.nav-dropdown{
  position:absolute; top:100%; left:50%;
  transform:translateX(-50%);
  padding-top:14px;
  opacity:0; pointer-events:none;
  transition:opacity .2s ease;
  z-index:110;
}
.nav-item-dropdown:hover .nav-dropdown, .nav-item-dropdown:focus-within .nav-dropdown{
  opacity:1; pointer-events:auto;
}
.nav-dropdown-inner{
  min-width:460px; padding:10px;
  background:#16160F; border:1px solid var(--card-border); border-radius:16px;
  box-shadow:0 20px 40px -18px rgba(0,0,0,0.65);
  display:grid; grid-template-columns:repeat(2, minmax(0,1fr)); gap:2px;
  transform:translateY(-4px);
  transition:transform .2s ease;
}
.nav-item-dropdown:hover .nav-dropdown-inner, .nav-item-dropdown:focus-within .nav-dropdown-inner{
  transform:translateY(0);
}
.nav-dropdown a{
  display:flex; align-items:center; gap:10px;
  padding:9px 10px; border-radius:10px; font-size:0.85rem; line-height:1.25;
  color:var(--text-muted);
  transition:background .18s ease, color .18s ease;
}
.nav-dropdown a:hover{ background:var(--accent-soft); color:var(--text); }
.nav-dropdown-icon{
  flex-shrink:0; width:26px; height:26px; border-radius:8px;
  display:flex; align-items:center; justify-content:center;
  background:rgba(122,158,106,0.14); color:var(--accent);
  transition:background .18s ease, transform .18s ease;
}
.nav-dropdown-icon svg{ width:13px; height:13px; }
.nav-dropdown a:hover .nav-dropdown-icon{ background:rgba(122,158,106,0.28); transform:scale(1.08); }

@media (min-width: 861px){
  .nav-links-cta{ display:none; } /* shown instead via #navCtaDesktop, separated from the nav links group */
  #navCtaDesktop{ display:inline-flex; }
}

@media (max-width: 860px){
  /* Full-screen takeover instead of a narrow side drawer — a plain 78%-wide
     panel of small text read as flat and forgettable next to the rest of
     the site. Fading + scaling the whole thing in (rather than sliding)
     plus staggering each link's own entrance is what actually makes it
     feel designed instead of just "a menu that appears". */
  .nav-links{
    position:fixed; inset:0; width:100%; max-width:none;
    background:#0E0E0C; flex-direction:column; align-items:flex-start; justify-content:flex-start;
    padding:120px 32px 40px; gap:4px;
    border-left:none;
    opacity:0; transform:scale(0.96);
    transition:opacity .4s ease, transform .4s ease, visibility .4s ease;
    /* visibility (not just opacity) gates the closed state: some in-app
       browsers (e.g. WhatsApp's Android webview) don't anchor position:fixed
       to the true viewport, which left this panel's services list bleeding
       into view at the edge of the screen even while "closed".
       visibility:hidden guarantees it's never rendered regardless of
       whatever position it lands in. */
    visibility:hidden;
    overflow-y:auto;
  }
  .nav-links.open{ opacity:1; transform:scale(1); visibility:visible; }

  /* Same faint dot-grid ambient texture as the homepage hero card
     (.flow-panel::after) so the full-screen menu still reads as this
     site rather than a generic overlay. Children get position:relative
     purely so their own paint step (later in DOM) lands above this
     absolutely-positioned pseudo instead of under it. */
  .nav-links::before{
    content:"";
    position:absolute; inset:0;
    background-image:radial-gradient(rgba(245,243,238,0.1) 1px, transparent 1.5px);
    background-size:18px 18px;
    -webkit-mask-image:radial-gradient(ellipse 70% 55% at 100% 0%, #000 0%, transparent 70%);
    mask-image:radial-gradient(ellipse 70% 55% at 100% 0%, #000 0%, transparent 70%);
    pointer-events:none;
  }
  .nav-links > *{ position:relative; }

  .nav-toggle{ display:flex; position:relative; z-index:1; }
  .nav-cta-mobile{ display:flex; }
  .nav-cta{ gap:8px; }

  /* Big serif headlines instead of the desktop nav's small muted labels —
     scoped to direct children (plus the "Servicios" head link one level
     in) so the collapsed sub-list below it stays at normal nav-link size. */
  .nav-links > a,
  .nav-item-dropdown-head > a{
    font-family:var(--serif);
    font-size:2rem;
    font-weight:700;
    line-height:1.25;
    color:var(--text);
  }
  .nav-links > a,
  .nav-links > .nav-item-dropdown{
    width:100%;
    padding:9px 0;
    opacity:0; transform:translateY(16px);
    transition:opacity .4s ease, transform .4s ease, color .2s ease;
  }
  .nav-links.open > a,
  .nav-links.open > .nav-item-dropdown{ opacity:1; transform:translateY(0); }
  /* Staggered reveal, one link at a time — 6 direct children total
     (Inicio, Servicios, Blog, Sobre mí, Contacto, the Hablemos CTA). */
  .nav-links.open > *:nth-child(1){ transition-delay:.06s; }
  .nav-links.open > *:nth-child(2){ transition-delay:.12s; }
  .nav-links.open > *:nth-child(3){ transition-delay:.18s; }
  .nav-links.open > *:nth-child(4){ transition-delay:.24s; }
  .nav-links.open > *:nth-child(5){ transition-delay:.3s; }
  .nav-links.open > *:nth-child(6){ transition-delay:.36s; }
  .nav-links > a:active{ color:var(--accent-strong); }
  .nav-links > a.active{ color:var(--accent); }

  /* The mobile header already has its own green contact button next to the
     hamburger, so this second CTA inside the menu itself was redundant. */
  .nav-links-cta{ display:none; }

  .nav-item-dropdown{ display:flex; flex-direction:column; }
  .nav-item-dropdown-head{ width:100%; justify-content:space-between; }
  /* Bigger tap target than the icon itself (negative margin cancels the
     padding's effect on layout/alignment) — a bare 14px caret is too small
     to reliably hit on a touchscreen. Sized up from desktop's 14px and
     given the accent color once expanded, both purely so it reads as an
     obvious, deliberate control rather than a stray mark next to the text. */
  .nav-caret-btn{ padding:10px; margin:-10px -10px -10px 0; }
  .nav-caret{ width:22px; height:22px; transition:transform .25s ease; }
  .nav-item-dropdown.expanded .nav-caret-btn{ color:var(--accent); }
  /* Neutralize the desktop hover/focus-within rotation first — a tapped
     button's lingering :focus-within on touch devices made that rule fire
     on its own, independent of open/closed state, leaving the arrow stuck
     pointing wherever it last happened to land. .expanded (below, so it
     wins the tie) is the only thing that should drive rotation here. */
  .nav-item-dropdown:hover .nav-caret,
  .nav-item-dropdown:focus-within .nav-caret{ transform:none; }
  .nav-item-dropdown.expanded .nav-caret{ transform:rotate(180deg); }

  /* Collapsed by default (a fixed always-open sub-list here is what made
     the services bleed into the hero text right after opening the drawer —
     see the earlier fix on .nav-links itself). grid-template-rows 0fr->1fr
     is used instead of max-height so it animates to the sub-list's actual
     height, not a guessed cutoff value. minmax(0,__fr) — not bare 0fr/1fr —
     because a plain fr track's automatic minimum is still its content's
     size, so "collapsed" was rendering at full (clipped-content) height
     instead of 0, leaving a large dead gap before "Sobre mí". */
  .nav-dropdown{
    position:static; left:auto; top:auto; opacity:1; pointer-events:auto;
    /* The desktop rule above centers this under the link with
       left:50%+translateX(-50%) — position:static makes left a no-op, but
       transform still applies regardless of position, so without this
       reset the sub-list stayed shifted left by half its own width,
       spilling out of the drawer into the hero text underneath it. */
    transform:none;
    /* Desktop's padding-top:14px (the hover hitbox gap before the floating
       card) isn't part of this grid's own row sizing, so it survived
       collapse untouched — extra dead space between "Servicios" and
       "Blog" even at grid-template-rows:0fr. */
    padding-top:0;
    display:grid; grid-template-rows:minmax(0,0fr);
    transition:grid-template-rows .3s ease;
  }
  .nav-item-dropdown.expanded .nav-dropdown{ grid-template-rows:minmax(0,1fr); }
  .nav-dropdown-inner{
    background:none; border:none; box-shadow:none; padding:10px 0 2px;
    grid-template-columns:1fr; gap:2px; transform:none; overflow:hidden; min-height:0;
    /* Desktop's 460px min-width (sized for the 2-column floating card) is
       wider than this drawer's content box on narrow phones, which forced
       the sub-list wider than its container. */
    min-width:0;
  }
  .nav-dropdown a{
    padding:9px 6px; border-radius:10px; color:var(--text-faint); font-size:0.95rem;
    font-family:var(--sans); font-weight:400;
    white-space:normal;
  }
  .nav-dropdown a:active{ background:var(--accent-soft); color:var(--text); }
}

/* ---------- Reveal on scroll ---------- */
.reveal{
  opacity:0; transform:translateY(22px);
  transition:opacity .7s cubic-bezier(.2,.7,.2,1), transform .7s cubic-bezier(.2,.7,.2,1);
}
.reveal.in{ opacity:1; transform:translateY(0); }
.reveal-delay-1{ transition-delay:.08s; }
.reveal-delay-2{ transition-delay:.16s; }
.reveal-delay-3{ transition-delay:.24s; }

/* Cards/steps/mini-stats define their own `transition` for hover (lift +
   border + shadow). `transition` is a single property, so on elements that
   are both e.g. ".card" and ".reveal", whichever rule comes later in the
   stylesheet wins OUTRIGHT — the two lists don't merge. That silently
   dropped the opacity fade from .reveal's entrance (only transform kept
   animating, on the hover rule's faster linear-ish timing), so cards
   popped into view instead of fading+sliding in: read as a "bounce".
   Re-declared here at higher specificity (two classes) so entrance
   (opacity+transform, slow eased curve) and hover (border/shadow, quick)
   both get to animate as intended. */
.reveal.card, .reveal.service-card, .reveal.step, .reveal.mini-stat{
  transition:
    opacity .5s cubic-bezier(.2,.7,.2,1),
    transform .5s cubic-bezier(.2,.7,.2,1),
    border-color .3s ease,
    box-shadow .3s ease;
}

@media (prefers-reduced-motion: reduce){
  .reveal{ opacity:1 !important; transform:none !important; transition:none !important; }
}

/* ---------- Sections ---------- */
section{ padding:96px 0; }
.section-tight{ padding:64px 0; }
.section-border-top{ border-top:1px solid var(--card-border); }
.section-fill{
  min-height:100vh;
  display:flex;
  align-items:center;
  padding:120px 0;
}
@media (max-width:860px){
  .section-fill{ min-height:100svh; padding:100px 0; }
}

/* ---------- Hero ---------- */
.hero{
  position:relative;
  padding:120px 0 90px;
  overflow:hidden;
}
/* Homepage only: pull the hero up behind the (out-of-flow-looking, but
   actually sticky/in-flow) header by exactly its measured height, then add
   that same amount back as top padding so the heading/text ends up exactly
   where it was — only the WebGL background (globe/starfield) now extends
   underneath the header instead of stopping at its bottom edge. This must
   NOT add anything beyond that pure compensation: padding-top pushes the
   text block (normal flow), but the globe lives in .hero-globe-viz
   (position:absolute, doesn't care about .hero's padding at all) — extra
   padding here was a mistake in an earlier pass, since it moved the text
   without proportionally moving the globe, breaking their alignment.
   Clearance for the globe from the header is handled separately, directly
   on .hero-globe-viz below. --header-h is set in layout.js; 96px is only
   the pre-JS fallback. */
body[data-page="inicio"] .hero{
  margin-top:calc(-1 * var(--header-h, 96px));
  padding-top:calc(120px + var(--header-h, 96px));
}
/* Short fade at the very bottom of the hero: whatever the canvas is
   showing there (it's an animated scene, colors shift) just dissolves to
   solid var(--bg) rather than cutting off hard — no color of our own is
   added, this only increases black opacity toward the bottom. Resolves
   well above the hero's edge, so it's fully gone before the logo row
   underneath. z-index:3 sits above the globe canvas (2) but below the
   hint pill/info card (5/6) so those stay untouched. Scoped to the
   homepage only — other pages' .hero has no canvas and shorter padding,
   so this fade was instead landing on top of (and dimming) the lede text. */
body[data-page="inicio"] .hero::after{
  content:"";
  position:absolute; left:0; right:0; bottom:0; height:160px;
  background:linear-gradient(180deg, transparent, var(--bg) 78%);
  z-index:3; pointer-events:none;
}
.hero-bg{
  position:absolute; inset:0; z-index:0;
  /* No competing background here on purpose: the WebGL canvas
     (.hero-globe-viz) is now the single source of truth for the whole
     hero's background (skybox + starfield rendered as scene geometry in
     hero-globe-vehicles.js, spanning 100% of the hero width) — a second,
     CSS-driven backdrop here would be exactly the "two systems that
     happen to look similar" setup that caused a visible seam before.
     var(--bg) from body shows through only in the instant before the
     canvas paints (or if JS fails entirely), as a neutral loading state,
     not a design layer to keep in sync with the 3D one. */
}
.hero-inner{ position:relative; z-index:1; pointer-events:none; }
.hero h1{ max-width:14ch; }
.hero-actions{ display:flex; gap:16px; margin-top:34px; flex-wrap:wrap; pointer-events:auto; }
.trust-line{
  margin-top:56px; display:flex; align-items:center; gap:16px;
  color:var(--text-faint); font-size:0.86rem; pointer-events:auto;
}
.trust-avatars{ display:flex; align-items:center; }
.trust-avatar{
  width:40px; height:40px; border-radius:50%; object-fit:cover;
  border:2px solid var(--bg); margin-left:-10px; flex-shrink:0;
}
.trust-avatar:first-child{ margin-left:0; }
.trust-avatar-more{
  display:flex; align-items:center; justify-content:center;
  background:#0B0B09; color:var(--text); font-size:0.7rem; font-weight:600;
}
.trust-divider{ width:1px; height:32px; background:rgba(255,255,255,0.14); flex-shrink:0; }
/* ---------- Hero stats row (service pages) ----------
   Small row of 2-3 animated figures replacing the old single-line
   "+N personas ya han confiado" trust message — same slot, same spacing,
   but each service page now makes its own distinct claims instead of
   repeating an identical sentence. */
/* grid (not flex-wrap) so the three stats always stay on one row, even on
   narrow screens — each column just wraps its own label onto a second
   line instead of the whole item dropping to a new row. */
.hero-stats{ margin-top:56px; display:grid; grid-template-columns:repeat(3, minmax(0, 1fr)); gap:24px; pointer-events:auto; }
.hero-stat{ display:flex; flex-direction:column; gap:2px; min-width:0; }
.hero-stat-num{ font-family:var(--serif); font-size:1.5rem; font-weight:700; color:var(--text); font-variant-numeric:tabular-nums; }
.hero-stat-label{ font-size:0.82rem; color:var(--text-faint); line-height:1.3; }
@media (max-width:560px){
  .hero-stats{ margin-top:40px; gap:12px; }
  .hero-stat-num{ font-size:1.1rem; }
  .hero-stat-label{ font-size:0.72rem; }
}
.trust-copy-row{ display:flex; align-items:center; gap:10px; }
.trust-icon{
  display:flex; align-items:center; justify-content:center;
  width:20px; height:20px; color:var(--accent); flex-shrink:0;
}
.trust-icon svg{ width:18px; height:18px; }
.trust-copy{ display:flex; flex-direction:column; line-height:1.35; }
.trust-copy b{ color:var(--text); font-weight:600; font-size:0.95rem; }
.trust-copy small{ color:var(--text-faint); font-size:0.82rem; }
@media (max-width:560px){
  .trust-avatar{ width:34px; height:34px; }
  .trust-copy b{ font-size:0.88rem; }
  .trust-copy small{ font-size:0.78rem; }
}

/* ---------- Hero globe (js/hero-globe.js + js/hero-globe-vehicles.js) ----------
   .hero-inner above is pointer-events:none (only .hero-actions re-enables
   it) so clicks anywhere on the hero — including over the text column —
   fall through to the globe canvas underneath instead of being swallowed
   by an invisible div.
   width:100% (not a 64% right panel): the canvas is the single background
   for the WHOLE hero now (skybox + starfield are scene geometry, see
   hero-globe-vehicles.js). The globe itself still visually sits on the
   right — hero-globe.js applies a camera view-offset (lens-shift) so its
   on-screen position matches the old 64% panel's center without moving or
   distorting the camera. */
.hero-globe-viz{
  position:absolute; inset:0; width:100%;
  z-index:2; pointer-events:auto;
}
.hero-globe-china-wrap{
  position:relative;
  display:flex; align-items:center; gap:8px;
  transform:translate(-50%,-50%);
  pointer-events:none;
  user-select:none;
}
.hero-globe-china-marker{
  flex-shrink:0;
  width:14px; height:14px; border-radius:50%;
  background:#7A9E6A;
  box-shadow:0 0 0 0 rgba(122,158,106,0.6);
  animation:heroGlobeChinaPulse 2.2s ease-out infinite;
}
.hero-globe-china-label{
  font-size:0.78rem; font-weight:600; letter-spacing:0.06em;
  text-transform:uppercase; white-space:nowrap;
  color:#DFF0D8;
  text-shadow:0 0 10px rgba(122,158,106,0.85), 0 1px 3px rgba(0,0,0,0.6);
}
@keyframes heroGlobeChinaPulse{
  0%{ box-shadow:0 0 0 0 rgba(122,158,106,0.55); }
  70%{ box-shadow:0 0 0 26px rgba(122,158,106,0); }
  100%{ box-shadow:0 0 0 0 rgba(122,158,106,0); }
}
.hero-globe-office-icon{
  position:relative;
  width:28px; height:28px;
  transform:translate(-50%,-50%);
  display:flex; align-items:center; justify-content:center;
  pointer-events:none;
  user-select:none;
}
.hero-globe-office-pulse{
  position:absolute; inset:0; margin:auto;
  width:16px; height:16px;
  border-radius:50%;
  background:rgba(223,240,216,0.12);
  box-shadow:0 0 0 0 rgba(223,240,216,0.6);
  animation:heroGlobeOfficePulse 1.8s ease-out infinite;
}
.hero-globe-office-svg{
  position:relative; z-index:1;
  width:15px; height:15px;
  color:#DFF0D8;
  filter:drop-shadow(0 0 3px rgba(122,158,106,0.9));
}
@keyframes heroGlobeOfficePulse{
  0%{ box-shadow:0 0 0 0 rgba(223,240,216,0.6); }
  70%{ box-shadow:0 0 0 22px rgba(223,240,216,0); }
  100%{ box-shadow:0 0 0 0 rgba(223,240,216,0); }
}

.hero-info-card{
  position:absolute; bottom:40px; right:40px; z-index:6;
  width:280px;
  background:rgba(22,22,15,0.9); backdrop-filter:blur(10px);
  border:1px solid var(--card-border-hover);
  border-radius:14px; padding:22px;
  opacity:0; transform:translateY(12px); pointer-events:none;
  transition:opacity .3s ease, transform .3s ease;
}
.hero-info-card.show{ opacity:1; transform:translateY(0); pointer-events:auto; }
.hero-info-card .tag{ margin-bottom:8px; }
.hero-info-card h4{ font-size:1rem; margin-bottom:6px; }
.hero-info-card p{ font-size:0.86rem; color:var(--text-muted); margin:0; }
.hero-info-card .close{
  position:absolute; top:12px; right:14px; cursor:pointer;
  color:var(--text-faint); font-size:1.1rem; background:none; border:none;
}

.hero-globe-hint{
  /* left:36% matches .hero-globe-viz's left edge (it's width:64% from the
     right) so this centers within the globe panel, not the whole hero —
     width:max-content + margin:auto is the centering mechanism (absolutely
     positioned element with both left and right set). */
  position:absolute; left:36%; right:0; bottom:36px; z-index:5;
  width:max-content; max-width:calc(64% - 40px); margin:0 auto;
  display:inline-flex; align-items:center; justify-content:center;
  padding:8px 16px; border-radius:999px;
  background:rgba(122,158,106,0.1); border:1px solid rgba(122,158,106,0.35);
  color:var(--accent-strong); font-size:0.78rem; letter-spacing:0.02em;
  text-align:center;
  backdrop-filter:blur(6px);
  pointer-events:none;
  transition:opacity .3s ease;
}
/* The office card can grow tall enough (longest blurb, 3 lines) to sit
   right under this hint at its default bottom:36px — hide the hint instead
   of letting them overlap; it reappears once the card auto-closes (see
   CARD_AUTOCLOSE_MS in hero-globe.js) or is dismissed. */
.hero:has(.hero-info-card.show) .hero-globe-hint{ opacity:0; }

@media (max-width:860px){
  /* pointer-events:none: on mobile the globe is decorative only (no rotate,
     no tap-to-open-office, no click-to-fly — see hero-globe.js/
     hero-globe-vehicles.js). Before this, OrbitControls captured every
     touchstart/touchmove on the canvas to drag-rotate the globe, which ate
     the vertical swipe needed to scroll the page — the hero is nearly the
     full viewport height on mobile, so that made the page almost
     unscrollable. */
  .hero-globe-viz{ opacity:.28; pointer-events:none; }
  .hero-info-card{ left:20px; right:20px; width:auto; bottom:20px; }
  .hero-globe-hint{ display:none; }
}

/* ---------- Logo row (static) ---------- */
.marquee{
  padding:14px 0 36px;
}
.logo-row{
  display:flex;
  align-items:center;
  justify-content:center;
  flex-wrap:wrap;
  gap:64px;
}
.logo-row .logo-mark{
  height:46px; width:auto; object-fit:contain;
  opacity:0.9;
  /* Source files are black artwork on a transparent background;
     the section behind them is dark, so we flip them to white
     in place rather than shipping separate white assets. */
  filter:brightness(0) invert(1);
  flex-shrink:0;
}
/* Larger variant for rows with only a few, tightly-cropped logos (e.g.
   servicios.html's 3-logo row) where the default 46px reads as too small. */
.logo-row-lg{ gap:50px; }
.logo-row-lg .logo-mark{ height:45px; }
.logo-row-lg .logo-mark-featured{ height:58px; }
.logo-row img[alt="Etsy"]{
  /* Etsy's serif wordmark has almost no descender, so once cropped
     tight to its ink it optically sits higher than the other marks
     when vertically centered — nudge it down to match their baseline. */
  transform:translateY(7px);
}
.logo-row img[alt="Amazon"]{
  /* The arrow swoosh beneath the wordmark counts toward the image's
     cropped height, so centering the whole mark leaves the "amazon"
     text itself sitting well above the other logos' optical center —
     nudge down so the text lines up with them, arrow included. */
  transform:translateY(9px);
}
/* Desktop's 46px/64px sizing is scaled for a wide row of marks with room to
   breathe; unscaled on a narrow phone it reads as oversized (each logo
   competing with the page's own headings) — smaller marks tighter together
   read as a compact trust strip instead. */
@media (max-width:600px){
  .logo-row{ gap:32px; }
  .logo-row .logo-mark{ height:24px; }
  .logo-row-lg{ gap:32px; }
  .logo-row-lg .logo-mark{ height:26px; }
  .logo-row-lg .logo-mark-featured{ height:34px; }
}

/* ---------- Logo row (auto-scrolling marquee) ----------
   Same white-on-transparent treatment as .logo-row, but the track holds
   the logo set THREE times back-to-back and animates translateX(-33.3334%)
   — i.e. exactly one copy-width per loop. Three copies (not two) is the
   safety margin: the visible .marquee-viewport can be up to ~2 copy-widths
   wide before a gap could show at the wrap point, which comfortably covers
   even a short 4-6 logo set inside a container this size — so the strip
   never flashes blank when it restarts. Contained to the page's normal
   content width (not edge-to-edge) with a soft mask fade at both ends.
   Top padding stays small — the preceding section already carries its
   own bottom padding, so doubling up here left a lopsided gap (much
   more air above the strip than below it). */
.marquee-scroll{
  padding:4px 0 44px;
}
.marquee-scroll-head{
  text-align:center;
  margin-bottom:28px;
}
.marquee-scroll-title{
  font-size:0.72rem;
  letter-spacing:0.08em;
  text-transform:uppercase;
  color:var(--text-faint);
}
.marquee-viewport{
  max-width:var(--container);
  margin:0 auto;
  padding:0 24px;
  overflow:hidden;
  -webkit-mask-image:linear-gradient(to right, transparent 0, black 80px, black calc(100% - 80px), transparent 100%);
  mask-image:linear-gradient(to right, transparent 0, black 80px, black calc(100% - 80px), transparent 100%);
}
.logo-track{
  display:flex;
  align-items:center;
  width:max-content;
  gap:56px;
  animation:logo-track-scroll 34s linear infinite;
  will-change:transform;
}
.logo-track .logo-mark{
  height:38px; width:auto; object-fit:contain;
  opacity:0.85;
  filter:brightness(0) invert(1);
  flex-shrink:0;
}
@keyframes logo-track-scroll{
  from{ transform:translateX(0); }
  to{ transform:translateX(-33.3334%); }
}
@media (max-width:600px){
  .marquee-viewport{
    -webkit-mask-image:linear-gradient(to right, transparent 0, black 40px, black calc(100% - 40px), transparent 100%);
    mask-image:linear-gradient(to right, transparent 0, black 40px, black calc(100% - 40px), transparent 100%);
  }
  .logo-track{ gap:32px; }
  .logo-track .logo-mark{ height:24px; }
}

/* ---------- Cards ---------- */
.grid{ display:grid; gap:22px; }
.grid-2{ grid-template-columns:repeat(2,1fr); }
.grid-3{ grid-template-columns:repeat(3,1fr); }
.grid-4{ grid-template-columns:repeat(4,1fr); }
@media (max-width:900px){ .grid-2,.grid-3,.grid-4{ grid-template-columns:1fr; } }

.card{
  background:var(--card);
  border:1px solid var(--card-border);
  border-radius:var(--radius);
  padding:30px;
  transition:transform .3s ease, border-color .3s ease, box-shadow .3s ease;
}
.card:hover{
  transform:translateY(-4px);
  border-color:var(--card-border-hover);
  box-shadow:0 20px 40px -24px rgba(0,0,0,0.6);
}
.card img{ border-radius:10px; margin-bottom:18px; aspect-ratio:16/10; object-fit:cover; }
.card h4{ margin-bottom:10px; font-size:1.15rem; }
.card p{ color:var(--text-muted); font-size:0.94rem; margin:0; }

/* ---------- Spotlight card (cursor-follow glow) ----------
   Opt-in modifier (kept off the base .card so it doesn't ripple into every
   card sitewide): solid near-black fill instead of --card, which reads as
   olive-green on big flat areas, plus a radial highlight pinned to the
   cursor via --x/--y (set on mousemove in animations.js, defaulting to the
   card's center so it still looks intentional before the first move). */
.spotlight-card{
  background:#0B0B09;
  position:relative;
  overflow:hidden;
}
.spotlight-card::before{
  content:"";
  position:absolute; inset:0;
  background:radial-gradient(280px circle at var(--x,50%) var(--y,50%), rgba(122,158,106,0.22), transparent 70%);
  opacity:0;
  transition:opacity .35s ease;
  pointer-events:none;
}
.spotlight-card:hover::before{ opacity:1; }
.spotlight-card > *{ position:relative; z-index:1; }
.spotlight-card .icon-badge{ transition:transform .3s ease, background .3s ease; }
.spotlight-card:hover .icon-badge{ transform:scale(1.08); background:rgba(122,158,106,0.24); }

/* ---------- Services showcase carousel (home) ----------
   One slide visible at a time (big media + copy, like a product/case-study
   card), not a static grid — .showcase-track is translateX'd by JS
   (animations.js) to whichever slide is active; dots + arrows below drive
   it, matching the site's existing "controls below the content" pattern
   (stepper, pricing) rather than side-flanking arrows that would overlap
   the card on narrow screens. */
.showcase{ max-width:1000px; margin:0 auto; }
.showcase-viewport{ overflow:hidden; }
.showcase-track{ display:flex; align-items:center; position:relative; transition:transform .65s cubic-bezier(.22,.9,.32,1); will-change:transform; }
.showcase-card{
  flex:0 0 70%; min-width:0; margin:0 2%;
  display:grid; grid-template-columns:1fr 1.1fr;
  background:#0B0B09; border:1px solid var(--card-border); border-radius:18px;
  overflow:hidden;
  transform:scale(0.78); filter:blur(4px); opacity:0.4; cursor:pointer;
  transition:transform .65s cubic-bezier(.22,.9,.32,1), filter .5s ease, opacity .5s ease;
  will-change:transform, filter, opacity;
}
.showcase-card.is-active{ transform:scale(1); filter:blur(0); opacity:1; cursor:default; }
/* Pull the two peeking cards in toward the active one, on top of the scale-down,
   so they read as tucked close to it rather than floating in their full-width slot. */
.showcase-card.is-active + .showcase-card{ transform:scale(0.78) translateX(-16%); }
.showcase-card:has(+ .showcase-card.is-active){ transform:scale(0.78) translateX(16%); }
/* aspect-ratio (not a fixed min-height) so the image scales down with the
   column instead of forcing a tall fixed box regardless of card width —
   that fixed-height version is what made the whole card oversized. */
.showcase-card-media{ position:relative; aspect-ratio:4/5; }
.showcase-card-media img{ width:100%; height:100%; object-fit:cover; display:block; }
.showcase-card-icon{
  position:absolute; top:14px; left:14px; width:30px; height:30px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  background:rgba(14,14,12,0.55); backdrop-filter:blur(8px); -webkit-backdrop-filter:blur(8px);
  border:1px solid rgba(245,243,238,0.16);
}
.showcase-card-icon svg{ width:14px; height:14px; color:var(--accent-strong); }
.showcase-card-tag{
  position:absolute; top:14px; left:14px; right:14px;
  max-width:calc(100% - 28px);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  font-size:0.62rem; font-weight:700; letter-spacing:0.02em; text-transform:uppercase;
  color:var(--accent-strong); background:rgba(14,14,12,0.6);
  backdrop-filter:blur(8px); -webkit-backdrop-filter:blur(8px);
  padding:5px 9px; border-radius:999px; border:1px solid rgba(245,243,238,0.16);
  /* left:auto + margin-left:auto keeps it right-aligned (matches the
     office icon on the opposite corner) while max-width/ellipsis above
     guarantee it never spills past the media box on any real device,
     even if a future label runs longer than expected. */
  width:max-content; margin-left:auto;
}
.showcase-card-body{ padding:22px 24px; display:flex; flex-direction:column; justify-content:center; min-width:0; }
.showcase-card-body .tag{ align-self:flex-start; margin-bottom:0; font-size:0.72rem; padding:5px 10px; }
.showcase-card-body h3{ margin:10px 0 8px; font-size:1.08rem; line-height:1.28; }
.showcase-card-body p{ color:var(--text-muted); font-size:0.82rem; line-height:1.5; margin:0 0 12px; }
.showcase-toggle{
  display:flex; align-items:center; gap:7px;
  width:100%; text-align:left;
  background:none; border:none; padding:0; margin:0 0 12px;
  color:var(--accent-strong); font-family:var(--sans);
  font-size:0.82rem; font-weight:600; cursor:pointer;
}
.showcase-toggle .icon{ color:var(--accent); font-size:1.05rem; line-height:1; transition:transform .3s ease; flex-shrink:0; }
.showcase-card.open .showcase-toggle .icon{ transform:rotate(45deg); }
.showcase-more{ max-height:0; overflow:hidden; transition:max-height .35s ease; }
.showcase-more ul{ list-style:none; margin:0 0 4px; padding:0; display:flex; flex-direction:column; gap:7px; }
.showcase-more li{ font-size:0.78rem; color:var(--text-muted); line-height:1.45; padding-left:16px; position:relative; }
.showcase-more li::before{ content:"→"; position:absolute; left:0; color:var(--accent); font-size:0.7rem; }
.showcase-stats{
  display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:10px;
  margin-top:16px; padding-top:14px; border-top:1px solid var(--card-border);
}
.showcase-stat{ display:flex; flex-direction:column; gap:2px; min-width:0; }
.showcase-stat-num{ font-family:var(--serif); font-size:0.92rem; font-weight:700; color:var(--text); line-height:1.15; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.showcase-stat-label{ font-size:0.62rem; color:var(--text-faint); line-height:1.3; }

.showcase-controls, .cases-controls{ display:flex; align-items:center; justify-content:center; gap:16px; margin-top:22px; }
.showcase-arrow, .cases-arrow{
  flex-shrink:0; width:36px; height:36px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  background:var(--card); border:1px solid var(--card-border); color:var(--text);
  cursor:pointer; transition:background .2s ease, border-color .2s ease, transform .2s ease, color .2s ease;
}
.showcase-arrow:hover, .cases-arrow:hover{ border-color:var(--accent); color:var(--accent-strong); transform:translateY(-2px); }
.showcase-arrow svg, .cases-arrow svg{ width:15px; height:15px; }
.showcase-dots, .cases-dots{ display:flex; align-items:center; gap:7px; }
.showcase-dot, .cases-dot{
  width:6px; height:6px; border-radius:999px; background:var(--card-border-hover);
  border:none; padding:0; cursor:pointer; transition:width .25s ease, background .25s ease;
}
.showcase-dot.active, .cases-dot.active{ width:20px; background:var(--accent); }

@media (max-width:640px){
  .showcase-card{ flex-basis:88%; margin:0 1.5%; grid-template-columns:1fr; }
  .showcase-card-media{ aspect-ratio:16/10; }
  .showcase-card-body{ padding:20px 18px 22px; }
}

/* ---------- Case-studies slider (home "Casos reales") ----------
   Same flat, equal-size card look as a plain 3-column grid, but the
   track shifts by exactly one card at a time — a plain left-aligned
   translateX to the target card's own offsetLeft, not the scale/blur
   peek treatment .showcase uses above. */
.cases-viewport{ overflow:hidden; }
.cases-track{
  display:flex;
  position:relative;
  gap:22px;
  transition:transform .6s cubic-bezier(.22,.9,.32,1);
  will-change:transform;
}
.case-card{
  flex:0 0 calc((100% - 44px)/3);
  min-width:0;
  background:#0B0B09;
  border:1px solid rgba(245,243,238,0.08);
  border-radius:20px;
  padding:14px;
  display:flex;
  flex-direction:column;
}
@media (max-width:900px){
  .case-card{ flex:0 0 100%; }
}

/* ---------- Services grid (servicios.html catalog, home case studies) ---------- */
.service-grid{ display:grid; grid-template-columns:repeat(4,1fr); gap:22px; }
@media (max-width:900px){ .service-grid{ grid-template-columns:1fr; } }

.service-card{
  background:#0B0B09;
  border:1px solid rgba(245,243,238,0.08);
  border-radius:20px;
  padding:14px;
  display:flex;
  flex-direction:column;
  transition:transform .3s ease, border-color .3s ease, box-shadow .3s ease;
}
.service-card:hover{
  transform:translateY(-4px);
  border-color:var(--card-border-hover);
  box-shadow:0 20px 40px -24px rgba(0,0,0,0.6);
}
.service-card-img{
  position:relative;
  border-radius:16px;
  overflow:hidden;
  aspect-ratio:4/3;
}
.service-card-img img{ width:100%; height:100%; object-fit:cover; transition:transform .5s ease; }
.service-card:hover .service-card-img img{ transform:scale(1.06); }
.service-icon{
  position:absolute;
  top:14px; left:14px;
  width:38px; height:38px;
  border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  background:rgba(14,14,12,0.5);
  backdrop-filter:blur(8px);
  -webkit-backdrop-filter:blur(8px);
  border:1px solid rgba(245,243,238,0.14);
}
.service-icon svg{ width:17px; height:17px; color:var(--accent-strong); }
.service-badge{
  position:absolute;
  top:14px; right:14px;
  font-size:0.66rem; font-weight:700; letter-spacing:0.03em; text-transform:uppercase;
  color:var(--accent-strong);
  background:rgba(14,14,12,0.6);
  backdrop-filter:blur(8px);
  -webkit-backdrop-filter:blur(8px);
  padding:5px 10px;
  border-radius:999px;
  border:1px solid rgba(245,243,238,0.14);
}
.service-card-body{
  padding:22px 10px 8px;
  display:flex;
  flex-direction:column;
  flex:1;
}
.service-card-body h4{
  color:var(--text);
  font-size:1.08rem;
  font-weight:700;
  line-height:1.3;
  margin:0 0 14px;
}
.service-divider{
  display:block;
  width:26px; height:2px;
  background:var(--accent);
  border-radius:2px;
  margin-bottom:14px;
}
.service-card-body p{
  color:var(--text-muted);
  font-size:0.9rem;
  line-height:1.65;
  margin:0 0 22px;
  flex:1;
}
.service-arrow{
  color:var(--accent);
  font-size:1.15rem;
  align-self:flex-start;
  display:inline-block;
  transition:transform .25s ease, color .25s ease;
}
.service-card:hover .service-arrow{ transform:translateX(4px); color:var(--accent-strong); }

.service-toggle{
  display:flex; align-items:center; gap:8px;
  width:100%; text-align:left;
  background:none; border:none; padding:0 0 14px; margin-top:-6px;
  color:var(--accent-strong); font-family:var(--sans);
  font-size:0.84rem; font-weight:600; cursor:pointer;
}
.service-toggle .icon{ color:var(--accent); font-size:1.15rem; line-height:1; transition:transform .3s ease; flex-shrink:0; }
.service-card.open .service-toggle .icon{ transform:rotate(45deg); }
.service-more{ max-height:0; overflow:hidden; transition:max-height .35s ease; }
.service-more ul{ list-style:none; margin:0 0 18px; padding:0; display:flex; flex-direction:column; gap:9px; }
.service-more li{ font-size:0.85rem; color:var(--text-muted); line-height:1.5; padding-left:18px; position:relative; }
.service-more li::before{ content:"→"; position:absolute; left:0; color:var(--accent); font-size:0.78rem; }

/* Servicios page: cards double as links to a dedicated page, so instead of
   the homepage's "Cómo lo hago" accordion they end in a plain CTA line —
   the click target is the whole card. */
.service-cta{
  display:flex; align-items:center; gap:6px;
  color:var(--accent-strong); font-size:0.84rem; font-weight:600;
}
.service-cta .arrow{ transition:transform .25s ease; }
.service-card:hover .service-cta .arrow{ transform:translateX(3px); }

/* "Próximamente" services on the same grid: same card family, muted so
   they read as not-yet-clickable next to the four live ones. */
.service-badge.is-soon{ color:var(--text-muted); }
.service-card.is-soon{ cursor:default; }
.service-card.is-soon:hover{ transform:none; box-shadow:none; border-color:rgba(245,243,238,0.08); }
.service-card.is-soon .service-card-img img{ filter:grayscale(70%); opacity:0.7; }
.service-card.is-soon:hover .service-card-img img{ transform:none; }

.btn-glow{ box-shadow:0 0 0 1px rgba(122,158,106,0.3), 0 0 46px 8px rgba(122,158,106,0.3); }
.btn-glow:hover{ box-shadow:0 0 0 1px rgba(122,158,106,0.4), 0 0 56px 10px rgba(122,158,106,0.4); }
.tag{
  display:inline-block; font-size:0.72rem; letter-spacing:0.06em; text-transform:uppercase;
  color:var(--accent); background:var(--accent-soft); padding:4px 10px; border-radius:999px;
  margin-bottom:14px;
}

/* ---------- Stat counters ---------- */
/* nowrap: keeps the stat on one line at every frame of the count-up (the
   number's width grows digit by digit), so the three "Casos de éxito"
   cards always have the same stat-row height and their titles/text line
   up, instead of the 2-line ones sitting lower than the 1-line ones. */
.stat{ text-align:left; margin-bottom:10px; white-space:nowrap; }
.stat .num{ font-family:var(--serif); font-size:clamp(1.3rem,1.8vw,1.6rem); color:var(--accent-strong); font-variant-numeric:tabular-nums; }
/* Reserves the final counted value's width up front, so a label sitting
   right after it (e.g. "asegurados") doesn't slide sideways every frame
   as digits are added during the count-up — it stayed put visually before,
   now it just holds its place while the number fills in behind it. */
.num-reserve{ display:inline-block; min-width:8ch; }
.stat-arrow{ display:inline-block; transition:transform .25s ease; }
.service-card:hover .stat-arrow{ transform:translateX(4px); }
.stat .label{ color:var(--text-muted); font-size:0.9rem; margin-top:4px; }
.stat-label{ font-family:var(--serif); font-size:clamp(1.3rem,1.8vw,1.6rem); color:var(--accent-strong); margin-left:6px; }

/* ---------- Stepper (real ordered process) ---------- */
.stepper{ display:grid; grid-template-columns:repeat(4,1fr); gap:22px; }
@media (max-width:900px){ .stepper{ grid-template-columns:1fr; } }
.step{
  background:var(--card);
  border:1px solid var(--card-border);
  border-radius:var(--radius);
  padding:26px 22px 24px;
  position:relative;
  display:flex;
  flex-direction:column;
  transition:transform .3s ease, border-color .3s ease, box-shadow .3s ease;
}
.step:hover{
  transform:translateY(-4px);
  border-color:var(--card-border-hover);
  box-shadow:0 20px 40px -24px rgba(0,0,0,0.6);
}
.step:not(:last-child)::after{
  content:"";
  position:absolute;
  top:44px; right:-22px;
  width:22px; height:1px;
  background:linear-gradient(90deg, var(--card-border-hover), transparent);
}
@media (max-width:900px){ .step:not(:last-child)::after{ display:none; } }
.step-top{ display:flex; align-items:center; justify-content:space-between; margin-bottom:18px; }
.step-num-badge{
  width:40px; height:40px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  background:var(--accent-soft); border:1px solid rgba(122,158,106,0.3);
  color:var(--accent-strong); font-family:var(--serif); font-weight:700; font-size:1rem;
  flex-shrink:0; transition:transform .3s ease, background .3s ease;
}
.step:hover .step-num-badge{ transform:scale(1.08); background:rgba(122,158,106,0.24); }
.step-icon{
  width:34px; height:34px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  background:rgba(245,243,238,0.04); border:1px solid var(--card-border);
  flex-shrink:0;
}
.step-icon svg{ width:16px; height:16px; color:var(--accent); }
.step h4{ margin:0 0 8px; font-size:1.05rem; }
.step p{ color:var(--text-muted); font-size:0.9rem; line-height:1.6; margin:0 0 18px; flex:1; }
.step-time{
  align-self:flex-start;
  display:inline-flex; align-items:center; gap:5px;
  font-size:0.7rem; font-weight:600; letter-spacing:0.04em; text-transform:uppercase;
  color:var(--accent-strong);
  background:rgba(122,158,106,0.1);
  border:1px solid rgba(122,158,106,0.25);
  padding:5px 11px; border-radius:999px;
}

/* ---------- Traditional vs T1304 (image comparison cards) ----------
   Reuses the site's existing tokens throughout (--card, --card-border,
   --radius, --warn/--accent). .fulfill-card-media takes its photo as a
   CSS background-image (set inline per card) rather than an <img> — until
   the real photo is dropped at that path it just falls back to the
   gradient below instead of showing a broken-image glyph. */
.fulfill-compare{ align-items:stretch; }
.fulfill-card{
  background:var(--card); border:1px solid var(--card-border); border-radius:var(--radius);
  padding:16px; display:flex; flex-direction:column; gap:6px;
}
.fulfill-card--bad{ border-color:rgba(180,105,74,0.55); }
.fulfill-card--good{ border-color:rgba(122,158,106,0.6); }
.fulfill-card-label{
  font-family:var(--serif); font-size:0.92rem; color:var(--text-muted); margin:2px 2px 10px;
}
.fulfill-card--good .fulfill-card-label{ color:var(--accent-strong); }
.fulfill-card-media{
  position:relative; border-radius:16px; overflow:hidden; aspect-ratio:16/10;
  /* --media-src (set inline per card) is the real photo, layered above the
     neutral gradient fallback — same plain treatment as .service-card-img,
     no color wash, so it stays coherent with the rest of the site and
     with whatever real photo eventually replaces it. A missing/404 file
     just fails to paint that top layer, leaving the gradient visible. */
  background-image:var(--media-src, none), linear-gradient(160deg, var(--card), var(--bg));
  background-size:cover; background-position:center;
}
.fulfill-card-tags{ position:absolute; top:14px; left:14px; display:flex; gap:8px; flex-wrap:wrap; }
.fulfill-tag{
  display:inline-flex; align-items:center; gap:6px;
  font-size:0.78rem; font-weight:600; color:var(--text); white-space:nowrap;
  background:rgba(14,14,12,0.55); backdrop-filter:blur(8px); -webkit-backdrop-filter:blur(8px);
  border:1px solid rgba(245,243,238,0.14);
  padding:6px 12px; border-radius:999px;
}
.fulfill-tag--dot i{ display:inline-block; width:6px; height:6px; border-radius:50%; background:var(--warn); }
.fulfill-tag--good.fulfill-tag--dot i{ background:var(--accent); }

/* The list itself sits on its own colored panel (dark base + a corner glow
   built from the same --warn/--accent hues, never a flat bright fill) —
   the card shell and the photo above it stay neutral, so only this block
   carries the red/green gradient, matching the reference without turning
   the whole card green. */
.fulfill-list-panel{
  border-radius:14px; padding:6px 16px 2px; margin-top:14px; flex:1;
}
.fulfill-card--bad .fulfill-list-panel{
  background:
    radial-gradient(130% 110% at 0% 100%, rgba(180,105,74,0.38), transparent 65%),
    linear-gradient(180deg, rgba(180,105,74,0.16), rgba(180,105,74,0.05));
}
.fulfill-card--good .fulfill-list-panel{
  background:
    radial-gradient(130% 110% at 0% 100%, rgba(122,158,106,0.38), transparent 65%),
    linear-gradient(180deg, rgba(122,158,106,0.18), rgba(122,158,106,0.05));
}
.fulfill-list{ list-style:none; margin:8px 0 0; padding:0; display:flex; flex-direction:column; }
.fulfill-list li{ display:flex; align-items:flex-start; gap:14px; padding:14px 4px; border-top:1px solid rgba(245,243,238,0.1); }
.fulfill-list li:first-child{ border-top:none; }
.fulfill-list li strong{ display:block; color:var(--text); font-size:0.95rem; font-weight:600; margin-bottom:2px; }
.fulfill-list li span{ color:var(--text-muted); font-size:0.85rem; line-height:1.5; }
.fulfill-icon{
  flex-shrink:0; width:30px; height:30px; border-radius:8px; margin-top:2px;
  display:flex; align-items:center; justify-content:center;
  background:rgba(255,255,255,0.08); color:var(--warn);
}
.fulfill-list--good .fulfill-icon{ color:var(--accent-strong); }
.fulfill-icon svg{ width:15px; height:15px; }

@media (max-width:900px){
  .fulfill-card-media{ aspect-ratio:16/11; }
}

/* ---------- Testimonials ---------- */
.testi-card{
  background:var(--card); border:1px solid var(--card-border); border-radius:var(--radius);
  padding:30px; display:flex; flex-direction:column; gap:18px;
}
.testi-card img{ border-radius:10px; aspect-ratio:4/3; object-fit:cover; }
.testi-card blockquote{
  margin:0; font-family:var(--serif); font-size:1.05rem; color:var(--text); font-style:italic; line-height:1.5;
}
.testi-card cite{ color:var(--accent); font-style:normal; font-size:0.88rem; }
.testi-card p.context{ color:var(--text-muted); font-size:0.9rem; margin:0; }

/* ---------- Warning / risk block ---------- */
.warn-block{
  background:linear-gradient(180deg, var(--warn-soft), transparent);
  border:1px solid rgba(180,105,74,0.35);
  border-radius:var(--radius);
  padding:44px;
}
.warn-block .eyebrow{ color:var(--warn); }
.warn-block .eyebrow::before{ background:var(--warn); }

/* ---------- Risk callout (fear-framing panel) ----------
   Reuses the exact warm-red recipe already established by
   .fulfill-card--bad .fulfill-list-panel (radial glow + var(--warn) tokens)
   instead of an unrelated saturated red, so this reads as the same "danger"
   language as the rest of the site rather than a one-off color. */
.risk-tag{
  display:inline-flex; align-items:center; gap:8px;
  padding:8px 16px; border-radius:999px;
  background:var(--warn-soft); border:1px solid rgba(180,105,74,0.4);
  color:var(--warn); font-size:0.78rem; font-weight:700; letter-spacing:0.02em;
}
.risk-callout{
  border-radius:var(--radius);
  padding:8px 22px 4px;
  background:
    radial-gradient(130% 110% at 0% 100%, rgba(180,105,74,0.38), transparent 65%),
    linear-gradient(180deg, rgba(180,105,74,0.16), rgba(180,105,74,0.05)),
    var(--card);
  border:1px solid rgba(180,105,74,0.45);
}
.risk-row{
  display:flex; align-items:flex-start; gap:16px;
  padding:20px 4px;
  border-top:1px solid rgba(245,243,238,0.1);
}
.risk-row:first-child{ border-top:none; }
.risk-row-icon{
  flex-shrink:0; width:32px; height:32px; border-radius:8px; margin-top:2px;
  display:flex; align-items:center; justify-content:center;
  background:rgba(255,255,255,0.08); color:var(--warn);
}
.risk-row-icon svg{ width:16px; height:16px; }
.risk-row strong{ display:block; color:var(--text); font-size:0.95rem; font-weight:600; margin-bottom:2px; }
.risk-row span{ color:var(--text-muted); font-size:0.85rem; line-height:1.5; }

/* ---------- Leak table (analisis-costes.html) ----------
   Rows start neutral/unchecked. When the card scrolls into view, js/animations.js
   adds .is-checked to each row one by one (a relay, like the counters above) —
   icon and label light up green, the ✓ status slides in, and a brief pulse
   marks the moment it "gets found". Hover reproduces the same look on demand,
   mostly useful before the sequence has run. */
.acx-leak-row{
  display:flex; align-items:center; gap:14px;
  padding:14px 6px; border-radius:8px;
  border-top:1px solid rgba(245,243,238,0.1);
  transition:background .25s ease;
}
.acx-leak-row:first-child{ border-top:none; }
.acx-leak-icon{
  flex-shrink:0; width:32px; height:32px; border-radius:8px;
  display:flex; align-items:center; justify-content:center;
  background:rgba(245,243,238,0.06); color:var(--text-faint);
  transition:background .25s ease, color .25s ease;
}
.acx-leak-icon svg{ width:16px; height:16px; }
.acx-leak-label{ flex:1; color:var(--text-muted); font-size:0.9rem; transition:color .25s ease; }
.acx-leak-status{
  color:var(--accent-strong); font-size:0.78rem; font-weight:600; white-space:nowrap;
  opacity:0; transform:translateX(-6px);
  transition:opacity .25s ease, transform .25s ease;
}
.acx-leak-row:hover,
.acx-leak-row.is-checked{ background:rgba(122,158,106,0.08); }
.acx-leak-row:hover .acx-leak-icon,
.acx-leak-row.is-checked .acx-leak-icon{ background:rgba(122,158,106,0.22); color:var(--accent-strong); }
.acx-leak-row:hover .acx-leak-label,
.acx-leak-row.is-checked .acx-leak-label{ color:var(--text); }
.acx-leak-row:hover .acx-leak-status,
.acx-leak-row.is-checked .acx-leak-status{ opacity:1; transform:translateX(0); }
.acx-leak-row.is-checked{ animation:acxLeakPulse .7s ease; }
@keyframes acxLeakPulse{
  0%{ background:rgba(122,158,106,0); }
  35%{ background:rgba(122,158,106,0.28); }
  100%{ background:rgba(122,158,106,0.08); }
}
.acx-leak-total{
  display:flex; align-items:center; justify-content:space-between; gap:14px;
  margin-top:6px; padding:14px 6px 4px; border-top:1px solid rgba(245,243,238,0.14);
  font-size:0.9rem; font-weight:600; color:var(--text);
  opacity:0; transform:translateY(4px);
  transition:opacity .4s ease, transform .4s ease;
}
.acx-leak-total.is-visible{ opacity:1; transform:translateY(0); }
.acx-leak-total-value{ color:var(--accent-strong); }

/* ---------- Pricing ---------- */
.price-card{
  background:var(--card); border:1px solid var(--card-border); border-radius:var(--radius);
  padding:34px; display:flex; flex-direction:column; height:100%;
}
.price-card .price{ font-family:var(--serif); font-size:2.6rem; color:var(--accent-strong); margin:20px 0 6px; }
.price-card .price small{ font-family:var(--sans); font-size:0.95rem; color:var(--text-muted); }
.price-card ul{ list-style:none; padding:0; margin:22px 0; display:flex; flex-direction:column; gap:12px; flex:1; }
.price-card li{ font-size:0.92rem; color:var(--text-muted); padding-left:22px; position:relative; }
.price-card li::before{ content:"✓"; position:absolute; left:0; color:var(--accent); }
/* Premium callout for a single standout perk — glow instead of bold so it
   reads as special without shouting like the rest of the list. */
.price-card li.li-highlight{ color:var(--accent-strong); text-shadow:0 0 16px rgba(122,158,106,0.6); }
.price-card li.li-highlight::before{ color:var(--accent-strong); text-shadow:0 0 10px rgba(122,158,106,0.7); }

/* ---------- Pricing: liquid-glass variant ----------
   Sitewide pricing card style (2026-08-25) — an Apple-style frosted glass
   panel: real backdrop-filter blur, a diagonal specular highlight sweep,
   an inset top-edge rim light, and green (not gold — gold/yellow is banned
   sitewide per explicit user instruction, 2026-08-24) for every accent.
   Applied to every .price-card so no tier reads as "the recommended one"
   at rest — any glow/lift only appears on :hover, never by default class.
   Previously scoped to a single flagship card per page; now several
   liquid-glass cards can sit side by side (growthpartner, proveedores,
   etc). That reintroduces the backdrop-filter "seam" bug this variant used
   to dodge by being alone (adjacent blurred siblings can share one
   compositor snapshot that Chromium/WebKit re-tiles on hover-driven
   transform/shadow changes, flashing a 1px seam along a neighboring card's
   edge) — isolation + translateZ(0) below give each card its own
   compositing layer to head that off. */
.price-card.liquid-glass{
  position:relative;
  isolation:isolate;
  transform:translateZ(0);
  background:linear-gradient(135deg, rgba(255,255,255,0.12), rgba(255,255,255,0.02) 40%, rgba(122,158,106,0.14) 100%);
  backdrop-filter:blur(24px) saturate(160%);
  -webkit-backdrop-filter:blur(24px) saturate(160%);
  border:1px solid rgba(255,255,255,0.16);
  border-radius:26px;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.35),
    inset 0 0 40px rgba(122,158,106,0.10),
    0 30px 60px -24px rgba(0,0,0,0.7),
    0 0 50px -18px rgba(122,158,106,0.45);
  transition:transform .35s ease, box-shadow .35s ease;
}
.price-card.liquid-glass::before{
  content:"";
  position:absolute; inset:0;
  border-radius:inherit;
  background:linear-gradient(115deg, rgba(255,255,255,0.22) 0%, rgba(255,255,255,0) 32%, rgba(255,255,255,0) 68%, rgba(255,255,255,0.07) 100%);
  pointer-events:none;
}
.price-card.liquid-glass:hover{
  transform:translateY(-6px) translateZ(0);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.4),
    inset 0 0 50px rgba(122,158,106,0.16),
    0 36px 70px -22px rgba(0,0,0,0.75),
    0 0 70px -14px rgba(122,158,106,0.6);
}
.price-card.liquid-glass .tag{ color:var(--accent-strong); background:rgba(122,158,106,0.2); }
.price-card.liquid-glass .price{ color:var(--accent-strong); text-shadow:0 0 30px rgba(122,158,106,0.45); }
.price-card.liquid-glass li::before{ color:var(--accent-strong); }
.price-card.liquid-glass .price-card-icon{ background:rgba(122,158,106,0.22); border-color:rgba(122,158,106,0.4); color:var(--accent-strong); }
.price-card.liquid-glass:hover .price-card-icon{ background:rgba(122,158,106,0.34); }
.price-card.liquid-glass .btn-primary{ background:linear-gradient(135deg, var(--accent-strong), var(--accent)); box-shadow:0 10px 26px -10px rgba(122,158,106,0.55); }
.price-card.liquid-glass .btn-primary:hover{ box-shadow:0 14px 34px -8px rgba(122,158,106,0.7); }
.price-card-icon{
  display:inline-flex; align-items:center; justify-content:center;
  width:42px; height:42px; border-radius:11px;
  background:var(--accent-soft); border:1px solid rgba(122,158,106,0.3);
  color:var(--accent-strong); margin-bottom:18px;
  transition:transform .3s ease, background .3s ease;
}
.price-card-icon svg{ width:19px; height:19px; }
.price-card:hover .price-card-icon{ transform:scale(1.08); background:rgba(122,158,106,0.26); }

/* ---------- Limited-time promo pill + card badge ----------
   .promo-pill (hero, sits beside plain text): muted translucent green,
   same recipe as .tag/.price-card.liquid-glass .tag — a solid --accent
   gradient there read as just another button, not a badge. .promo-badge
   (corner tag on the liquid-glass pricing card) keeps the solid gradient
   fill — reverted per explicit user request, it reads fine floating on
   the glass card itself. Never gold/yellow — banned sitewide per
   explicit user instruction, 2026-08-24. */
.promo-pill{
  display:inline-flex; align-items:center; gap:8px;
  font-size:0.82rem; font-weight:700;
  color:var(--accent-strong);
  background:rgba(122,158,106,0.14);
  border:1px solid rgba(122,158,106,0.35);
  backdrop-filter:blur(10px); -webkit-backdrop-filter:blur(10px);
  padding:9px 18px; border-radius:999px; margin-bottom:18px;
  transition:transform .25s ease, background .25s ease, border-color .25s ease;
}
.promo-pill:hover{ transform:translateY(-2px); background:rgba(122,158,106,0.22); border-color:rgba(122,158,106,0.55); }
.promo-badge{
  position:absolute; top:-15px; right:28px;
  display:inline-flex; align-items:center; gap:6px;
  font-size:0.76rem; font-weight:700;
  color:#0B140A; background:linear-gradient(135deg, var(--accent-strong), var(--accent));
  backdrop-filter:blur(10px); -webkit-backdrop-filter:blur(10px);
  padding:8px 16px; border-radius:999px;
}
@media (max-width:560px){ .promo-badge{ right:16px; font-size:0.68rem; padding:7px 12px; } }

/* ---------- Comparison table (traditional vs us) ----------
   Radio-driven toggle, no JS: #cmpGood/#cmpBad are the two hidden radios,
   and every mode-dependent bit downstream is a sibling selector off
   `:checked` (labels' active state, which row-set shows, which summary
   line shows). Keeping this CSS-only avoids wiring up a JS listener for
   what is otherwise a two-state visibility switch. */
.cmp-radio{ position:absolute; opacity:0; pointer-events:none; }

.cmp-toggle{
  position:relative;
  display:flex; justify-content:center; gap:4px;
  background:var(--card); border:1px solid var(--card-border);
  border-radius:999px; padding:4px;
  margin:0 auto 28px; width:max-content; max-width:100%;
}
.cmp-toggle-opt{
  padding:11px 22px; border-radius:999px;
  font-size:0.88rem; font-weight:600; text-align:center;
  color:var(--text-muted); cursor:pointer; white-space:nowrap;
  transition:background .3s ease, color .3s ease;
}
#cmpGood:checked ~ .cmp-toggle .cmp-toggle-opt--good{ background:var(--accent); color:#0E0E0C; }
#cmpBad:checked ~ .cmp-toggle .cmp-toggle-opt--bad{ background:var(--warn); color:#0E0E0C; }

.cmp-card{
  background:var(--card); border:1px solid var(--card-border);
  border-radius:20px; overflow:hidden;
  box-shadow:0 30px 60px -30px rgba(0,0,0,0.6);
  transition:border-color .3s ease;
}
.cmp-head{
  display:flex; align-items:center; justify-content:space-between;
  padding:18px 28px; font-size:0.82rem; font-weight:600;
  color:var(--text-faint); text-transform:uppercase; letter-spacing:0.06em;
  border-bottom:2px solid var(--card-border-hover);
  transition:border-color .3s ease;
}
.cmp-head-tag-bad{ display:none; }
.cmp-head-label-bad{ display:none; }
#cmpBad:checked ~ .cmp-card .cmp-head-tag-good{ display:none; }
#cmpBad:checked ~ .cmp-card .cmp-head-tag-bad{ display:inline; }
#cmpBad:checked ~ .cmp-card .cmp-head-label-good{ display:none; }
#cmpBad:checked ~ .cmp-card .cmp-head-label-bad{ display:inline; }
#cmpGood:checked ~ .cmp-card .cmp-head{ border-bottom-color:var(--accent); }
#cmpBad:checked ~ .cmp-card .cmp-head{ border-bottom-color:var(--warn); }

.cmp-rows--bad{ display:none; }
#cmpBad:checked ~ .cmp-card .cmp-rows--good{ display:none; }
#cmpBad:checked ~ .cmp-card .cmp-rows--bad{ display:block; }

.cmp-row{
  display:flex; align-items:center; gap:16px;
  padding:16px 28px; border-bottom:1px solid var(--card-border);
  font-size:0.94rem; color:var(--text);
}
.cmp-row:last-child{ border-bottom:none; }
.cmp-mark{
  flex-shrink:0; width:24px; height:24px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  font-size:0.76rem; font-weight:700;
  background:var(--accent-soft); color:var(--accent-strong);
}
#cmpBad:checked ~ .cmp-card .cmp-mark{ background:var(--warn-soft); color:var(--warn); }

.cmp-summary{ padding:24px 28px; text-align:center; }
.cmp-summary p{
  margin:0; font-family:var(--serif); font-weight:600; font-size:1.15rem;
  color:var(--accent-strong);
}
.cmp-summary-bad{ display:none; }
#cmpBad:checked ~ .cmp-card .cmp-summary-good{ display:none; }
#cmpBad:checked ~ .cmp-card .cmp-summary-bad{ display:block; color:var(--warn); }

@media (max-width:560px){
  .cmp-toggle{ width:100%; }
  .cmp-toggle-opt{ flex:1; padding:11px 14px; }
  .cmp-head-tag{ display:none; }
}

.link-arrow{
  display:inline-flex; align-items:center; gap:6px;
  color:var(--accent-strong); font-weight:600; font-size:0.95rem;
}
.link-arrow span{ transition:transform .25s ease; }
.link-arrow:hover span{ transform:translateX(4px); }

/* Duplicated so the CTA can sit inline after the risk copy on desktop but
   below the risk-callout table on mobile (grid-2 collapses to one column
   there, stacking these as separate grid children) — hidden per breakpoint
   below so only one instance ever shows. */
.risk-solution-mobile-only{ display:none; }
@media (max-width:900px){
  .risk-solution-desktop-only{ display:none; }
  .risk-solution-mobile-only{ display:inline-flex; margin-top:24px; }
}

.grw-results-card{ padding:28px; }
/* Stacked before/after rows replacing the 3-column cost table below
   900px — the table's 420px min-width forced this whole card wider than
   the viewport (reported as the section "not adapting to mobile"), and a
   plain horizontal scroll read as broken rather than intentional. This
   list carries the same numbers without needing a minimum content width. */
.grw-cost-list{ display:none; flex-direction:column; margin-top:18px; }
.grw-cost-row{
  display:flex; align-items:baseline; justify-content:space-between; gap:12px;
  padding:12px 0; border-bottom:1px solid var(--card-border);
  font-size:0.88rem;
}
.grw-cost-row:last-child{ border-bottom:none; }
.grw-cost-label{ color:var(--text); }
.grw-cost-compare{ display:flex; align-items:baseline; gap:6px; white-space:nowrap; flex-shrink:0; }
.grw-cost-compare s{ color:var(--text-faint); text-decoration:line-through; font-weight:400; }
.grw-cost-arrow{ color:var(--text-faint); }
.grw-cost-compare b{ color:var(--accent-strong); font-weight:700; }
.grw-cost-row--total{ padding-top:14px; margin-top:2px; border-top:1px solid var(--card-border); border-bottom:none; }
.grw-cost-row--total .grw-cost-label{ font-weight:700; }
.grw-cost-row--total .grw-cost-compare s{ color:var(--warn); }
.grw-cost-row--total .grw-cost-compare b{ font-size:1rem; }

@media (max-width:900px){
  .grw-results-card{ padding:22px 18px; }
  .grw-cost-table{ display:none; }
  .grw-cost-list{ display:flex; }
}

.cmp-benefits{ display:grid; grid-template-columns:1fr 1fr; gap:28px; margin-top:40px; }
@media (max-width:560px){ .cmp-benefits{ grid-template-columns:1fr; } }
.cmp-benefit-icon{
  display:inline-flex; align-items:center; justify-content:center;
  width:38px; height:38px; border-radius:50%;
  background:var(--accent-soft); color:var(--accent-strong);
  margin-bottom:12px;
}
.cmp-benefit-icon svg{ width:18px; height:18px; }
.cmp-benefit h4{ font-size:1rem; margin-bottom:6px; }
.cmp-benefit p{ color:var(--text-muted); font-size:0.88rem; line-height:1.55; margin:0; }

/* ---------- Profile / qualifier cards ("es para ti si...") ----------
   Replaces the flat .card + small check-circle combo, which read as a
   dull olive box with a throwaway icon. Glass gradient instead of the
   --card olive fill (same complaint as .price-card's own comment: flat
   --card looks muddy on a big area), a bigger duotone badge that tilts
   on hover, and an oversized ghost numeral per card so each qualifier
   reads as "point 01/02/03/04" instead of a generic bullet — makes the
   grid feel like a checklist the visitor is scoring themselves against. */
.profile-card{
  position:relative;
  background:linear-gradient(160deg, rgba(122,158,106,0.09), rgba(245,243,238,0.02));
  border:1px solid rgba(245,243,238,0.10);
  border-radius:var(--radius);
  padding:32px 30px;
  overflow:hidden;
  transition:transform .3s ease, border-color .3s ease, box-shadow .3s ease, background .3s ease;
}
.profile-card::before{
  content:attr(data-num);
  position:absolute; top:-14px; right:14px;
  font-family:var(--serif); font-size:4.6rem; font-weight:700; line-height:1;
  color:rgba(245,243,238,0.045);
  pointer-events:none;
}
.profile-card:hover{
  transform:translateY(-5px);
  border-color:rgba(122,158,106,0.5);
  background:linear-gradient(160deg, rgba(122,158,106,0.16), rgba(245,243,238,0.02));
  box-shadow:0 24px 48px -28px rgba(0,0,0,0.65), 0 0 40px -18px rgba(122,158,106,0.4);
}
.profile-card p{ position:relative; z-index:1; }
.profile-icon{
  position:relative; z-index:1;
  display:inline-flex; align-items:center; justify-content:center;
  width:52px; height:52px; border-radius:15px;
  background:linear-gradient(160deg, rgba(122,158,106,0.32), rgba(122,158,106,0.08));
  border:1px solid rgba(122,158,106,0.4);
  color:var(--accent-strong);
  margin-bottom:18px;
  box-shadow:0 10px 24px -12px rgba(122,158,106,0.55);
  transition:transform .35s ease, box-shadow .35s ease, background .35s ease;
}
.profile-icon svg{ width:26px; height:26px; }
.profile-card:hover .profile-icon{
  transform:scale(1.08) rotate(-6deg);
  background:linear-gradient(160deg, rgba(122,158,106,0.46), rgba(122,158,106,0.12));
  box-shadow:0 14px 30px -10px rgba(122,158,106,0.7);
}

/* ---------- Icon badge (shared: mini-stats + flow diagram) ---------- */
.icon-badge{
  display:inline-flex; align-items:center; justify-content:center;
  width:40px; height:40px; border-radius:10px;
  background:var(--accent-soft); border:1px solid rgba(122,158,106,0.3);
  color:var(--accent-strong); flex-shrink:0;
}
.icon-badge svg{ width:19px; height:19px; }
.icon-badge--dark{ background:rgba(0,0,0,0.28); border-color:var(--card-border-hover); color:var(--text); }

/* ---------- Operativa global: mini-stats + flow panel ---------- */
.mini-stats{ grid-template-columns:repeat(4,1fr); gap:18px; }
@media (max-width:900px){ .mini-stats{ grid-template-columns:repeat(2,1fr); gap:14px; } }
/* Same recipe as .service-card (services grid above) so these read as the
   same design, not a separate component: same bg/border/radius, same
   circular blurred icon treatment, same divider+copy rhythm. */
.mini-stat{
  background:#0B0B09;
  border:1px solid rgba(245,243,238,0.08);
  border-radius:20px;
  padding:22px;
  transition:transform .3s ease, border-color .3s ease, box-shadow .3s ease;
}
.mini-stat:hover{
  transform:translateY(-4px);
  border-color:var(--card-border-hover);
  box-shadow:0 20px 40px -24px rgba(0,0,0,0.6);
}
.mini-stat-icon{
  display:flex; align-items:center; justify-content:center;
  width:38px; height:38px; border-radius:50%;
  background:rgba(14,14,12,0.5);
  backdrop-filter:blur(8px); -webkit-backdrop-filter:blur(8px);
  border:1px solid rgba(245,243,238,0.14);
  margin-bottom:16px;
}
.mini-stat-icon svg{ width:17px; height:17px; color:var(--accent-strong); }
.mini-stat h4{ font-size:1.05rem; font-weight:700; margin:0 0 14px; }
.mini-stat .service-divider{ margin-bottom:14px; }
.mini-stat p{ font-size:0.85rem; color:var(--text-muted); line-height:1.6; margin:0; }

.flow-panel{
  position:relative;
  overflow:hidden;
  border-radius:var(--radius);
  background:
    linear-gradient(125deg, rgba(122,158,106,0.14), transparent 40%),
    radial-gradient(120% 140% at 15% 0%, rgba(122,158,106,0.22), transparent 60%),
    var(--card);
  border:1px solid var(--card-border);
  padding:48px;
}
/* Faint dot-grid in the corner, faded out with a radial mask so it reads
   as ambient texture rather than a hard-edged tiled box. */
.flow-panel::after{
  content:"";
  position:absolute; top:0; right:0; width:55%; height:100%;
  background-image:radial-gradient(rgba(245,243,238,0.16) 1px, transparent 1.5px);
  background-size:15px 15px;
  -webkit-mask-image:radial-gradient(ellipse 90% 100% at 100% 0%, #000 0%, transparent 70%);
  mask-image:radial-gradient(ellipse 90% 100% at 100% 0%, #000 0%, transparent 70%);
  pointer-events:none;
}
.flow-panel > *{ position:relative; z-index:1; }
.flow-panel-intro{ max-width:560px; }
.flow-panel-intro h2{ margin-bottom:16px; }
.flow-panel-intro .lede{ margin-bottom:18px; max-width:56ch; }

.flow-diagram{ display:flex; align-items:flex-start; margin-top:52px; }
.flow-step{ display:flex; flex-direction:column; align-items:center; text-align:center; flex:0 0 auto; width:118px; gap:12px; }
.flow-step p{ margin:0; font-size:0.85rem; font-weight:600; color:var(--text); line-height:1.35; }
/* Same height as .flow-step's icon row (40px), both starting at the flex
   row's top edge — that's what guarantees the connecting line/arc lands
   exactly on the icon badges' vertical center instead of drifting toward
   the caption text below. */
.flow-connector{ flex:1; min-width:32px; height:40px; display:flex; align-items:center; position:relative; }
.flow-slot{
  position:absolute; left:0; right:0; bottom:100%; margin-bottom:10px;
  font-size:0.78rem; font-weight:600; color:var(--text); white-space:nowrap; text-align:center;
}
.flow-icon-row{ height:40px; width:100%; display:flex; align-items:center; justify-content:center; position:relative; }
.flow-line{ width:100%; height:0; border-top:2px dashed var(--card-border-hover); }
.flow-arc{ position:absolute; left:0; top:0; width:100%; height:100%; display:block; }
.flow-plane{
  position:absolute; left:50%; top:50%; transform:translate(-50%,-50%);
  display:flex; align-items:center; justify-content:center;
  background:var(--card); border-radius:8px; padding:7px 10px; color:var(--text);
}
.flow-plane img{ width:20px; height:20px; object-fit:contain; flex-shrink:0; display:block; }
/* Without an explicit width this flex item shrinks to its content's
   intrinsic size instead of filling the connector — .flow-icon-row's own
   width:100% inside it then resolves against that shrunken box instead of
   the full connector, collapsing the arc to near-nothing and throwing the
   plane's centered position off with it. */
.flow-air-desktop-only{ width:100%; }
/* Mobile-only rendering of the "Envío internacional" step (see the media
   query below for why it needs an entirely different shape, not just a
   restyled version of the desktop one) — hidden here so both variants
   don't show up stacked on top of each other above the breakpoint. */
.flow-air-mobile-only{ display:none; }
/* This instance sits inline in a row next to the label instead of overlaid
   on an arc, so it drops the desktop version's floating-badge treatment.
   Unconditional (not inside the media query) since the wrapper above is
   already display:none on desktop, so it never has a visual effect there. */
/* Same 40px dark badge the other three steps use for their icon (see
   .icon-badge/.icon-badge--dark), not the bare 20px glyph the desktop
   version floats over its arc — this is what makes the step read as a full
   peer in the chain instead of a smaller, differently-styled accent. */
.flow-air-icon img{ width:19px; height:19px; object-fit:contain; display:block; }

@media (max-width:900px){
  .flow-panel{ padding:32px 24px; }
  .flow-diagram{ flex-direction:column; align-items:stretch; margin-top:40px; }
  .flow-step{ flex-direction:row; width:auto; text-align:left; justify-content:flex-start; }
  .flow-step p{ text-align:left; }
  .flow-connector{ flex-direction:row; align-self:stretch; min-width:0; height:auto; }
  .flow-slot{ position:static; text-align:left; margin:0 0 0 8px; white-space:nowrap; }
  .flow-icon-row{ height:auto; width:40px; padding:14px 0; }
  .flow-line{ width:0; height:100%; min-height:28px; border-top:none; border-left:2px dashed var(--card-border-hover); }

  /* The curved arc + centered plane + floating label only reads sensibly
     as a wide horizontal shape — squeezed into a narrow column it left the
     label looking stranded next to a short, disconnected line segment
     (reported as looking like it was just "stuck in the middle"). Swapped
     for a version built for a column instead: this step becomes a full
     link in the vertical chain — a plain dashed line in from the icon
     above, the plane + label as their own row, a plain dashed line back
     out to the icon below — so it reads as part of the same sequence
     instead of an annotation floating beside it. */
  .flow-air-desktop-only{ display:none; }
  .flow-air-mobile-only{
    display:flex; flex-direction:column; align-items:flex-start; width:100%;
  }
  /* margin-left centers the curve on the same x-position the icon boxes
     above/below are centered on (40px column, midpoint 20px in; the SVG's
     own path center sits at x=10 of its 20-wide viewBox, so 10px of that
     margin is the icon column's remaining half). A slight bow to each
     side — right on the way in, left on the way out — instead of a plain
     straight dash, purely decorative. */
  .flow-air-curve{ display:block; width:20px; height:28px; margin-left:10px; }
  /* No left offset: the badge aligns flush with the icon boxes above and
     below it (all 40px, all starting at the row's left edge) instead of
     being nudged in from the edge like the old bare-icon version was. */
  .flow-air-row{ display:flex; align-items:center; gap:12px; padding:6px 0; }
  .flow-air-label{ font-size:0.85rem; font-weight:600; color:var(--text); white-space:nowrap; }
}

/* ---------- FAQ accordion ---------- */
.faq-item{ border-top:1px solid var(--card-border); }
.faq-item:last-child{ border-bottom:1px solid var(--card-border); }
.faq-q{
  width:100%; text-align:left; background:none; border:none; color:var(--text);
  font-family:var(--sans); font-size:1.02rem; font-weight:600;
  padding:22px 0; cursor:pointer;
  display:flex; align-items:center; justify-content:space-between; gap:20px;
}
.faq-q .icon{ color:var(--accent); font-size:1.2rem; transition:transform .3s ease; flex-shrink:0; }
.faq-item.open .icon{ transform:rotate(45deg); }
.faq-a{
  max-height:0; overflow:hidden; transition:max-height .35s ease;
  color:var(--text-muted); font-size:0.95rem; line-height:1.7;
}
.faq-a-inner{ padding-bottom:22px; white-space:pre-line; }

/* ---------- CTA band ---------- */
.cta-band{
  border-radius:var(--radius);
  background:radial-gradient(120% 140% at 20% 0%, rgba(122,158,106,0.18), transparent 60%), var(--card);
  border:1px solid var(--card-border);
  padding:64px; text-align:center;
}
.cta-band h2{ max-width:20ch; margin:0 auto 26px; }

/* ---------- Footer ---------- */
.site-footer{ border-top:1px solid var(--card-border); padding:56px 0 30px; }
.footer-grid{ display:flex; justify-content:space-between; gap:40px; flex-wrap:wrap; margin-bottom:40px; }
.footer-grid h5{ font-size:0.75rem; text-transform:uppercase; letter-spacing:0.1em; color:var(--text-faint); margin:0 0 12px; }
.footer-grid p, .footer-grid a{ color:var(--text-muted); font-size:0.94rem; display:block; margin-bottom:6px; }
.footer-bottom{ display:flex; justify-content:space-between; color:var(--text-faint); font-size:0.82rem; border-top:1px solid var(--card-border); padding-top:24px; flex-wrap:wrap; gap:10px;}
.footer-legal-links{ display:flex; gap:18px; }
.footer-legal-links a{ color:var(--text-faint); transition:color .2s ease; }
.footer-legal-links a:hover{ color:var(--accent-strong); }

/* ---------- Cookie consent banner ---------- */
.cookie-banner{
  position:fixed; left:0; right:0; bottom:0; z-index:200;
  background:#0B0B09; border-top:1px solid var(--card-border);
  box-shadow:0 -20px 50px -30px rgba(0,0,0,0.7);
  transform:translateY(100%);
  transition:transform .35s ease;
}
.cookie-banner--visible{ transform:translateY(0); }
.cookie-banner-inner{
  padding:22px 24px;
  display:flex; align-items:center; justify-content:space-between; gap:24px; flex-wrap:wrap;
}
.cookie-banner-inner p{ margin:0; color:var(--text-muted); font-size:0.88rem; line-height:1.6; max-width:64ch; flex:1 1 320px; }
.cookie-banner-inner a{ color:var(--accent-strong); }
.cookie-banner-inner a:hover{ text-decoration:underline; }
.cookie-banner-actions{ display:flex; gap:12px; flex-shrink:0; }
@media (max-width:560px){
  .cookie-banner-inner{ padding:20px; }
  .cookie-banner-actions{ width:100%; }
  .cookie-banner-actions .btn{ flex:1; justify-content:center; }
}

/* ---------- Breadcrumb tag (page identifiers like grw-001) ---------- */
.crumb{ font-size:0.72rem; letter-spacing:0.08em; text-transform:uppercase; color:var(--text-faint); margin-bottom:16px; }

/* ---------- Guías y cursos catalogue (guias.html) ----------
   Only page on the site using a sidebar + grid layout (categories/format/
   level filters on the left, cards on the right) instead of the
   full-width centered sections everywhere else — deliberate, to read as a
   browsable catalogue rather than another marketing section. Filtering
   itself is plain JS (js/guias.js) toggling [hidden] on .guide-card;
   nothing here needs to know about that beyond the layout. */
.guides-layout{
  display:grid;
  grid-template-columns:250px 1fr;
  gap:48px;
  align-items:start;
}
.guides-sidebar{
  position:sticky;
  top:110px;
}
.guides-sidebar-head, .guides-drawer-footer, .guides-sidebar-close, .guides-filters-toggle, .guides-filters-backdrop{ display:none; }
.guides-filter-group{
  padding:22px 0;
  border-top:1px solid var(--card-border);
}
.guides-filter-group:first-child{ padding-top:0; border-top:none; }
.guides-filter-group h5{
  font-size:0.72rem; text-transform:uppercase; letter-spacing:0.1em;
  color:var(--text-faint); margin:0 0 14px;
}
.guides-search{
  display:flex; align-items:center; gap:10px;
  background:#0B0B09; border:1px solid var(--card-border);
  border-radius:999px; padding:12px 16px;
  transition:border-color .2s ease;
}
.guides-search:focus-within{ border-color:var(--card-border-hover); }
.guides-search svg{ width:16px; height:16px; color:var(--text-faint); flex-shrink:0; }
.guides-search input{
  background:none; border:none; outline:none; width:100%;
  color:var(--text); font-family:var(--sans); font-size:0.9rem;
}
.guides-search input::placeholder{ color:var(--text-faint); }

.guides-cat-list{ list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:2px; }
.guides-cat-btn{
  display:flex; align-items:center; justify-content:space-between; gap:10px;
  width:100%; background:none; border:none; text-align:left; cursor:pointer;
  padding:9px 10px; border-radius:8px;
  color:var(--text-muted); font-family:var(--sans); font-size:0.9rem;
  transition:background .2s ease, color .2s ease;
}
.guides-cat-btn span{ color:var(--text-faint); font-size:0.78rem; font-variant-numeric:tabular-nums; }
.guides-cat-btn:hover{ background:rgba(245,243,238,0.05); color:var(--text); }
.guides-cat-btn.active{ background:var(--accent-soft); color:var(--accent-strong); font-weight:600; }
.guides-cat-btn.active span{ color:var(--accent-strong); }

.guides-check{
  display:flex; align-items:center; gap:10px;
  padding:7px 0; cursor:pointer;
  color:var(--text-muted); font-size:0.88rem;
}
.guides-check input{ accent-color:var(--accent); width:16px; height:16px; flex-shrink:0; cursor:pointer; }

.guides-toolbar{
  display:flex; align-items:center; justify-content:space-between; gap:16px;
  flex-wrap:wrap; margin-bottom:26px;
}
.guides-count{ color:var(--text-muted); font-size:0.9rem; }
.guides-sort{
  background:#0B0B09; border:1px solid var(--card-border); color:var(--text);
  border-radius:999px; padding:10px 18px; font-size:0.85rem; font-family:var(--sans);
  cursor:pointer;
}

.guides-grid{ grid-template-columns:repeat(3,1fr); }

.guide-card{
  background:#0B0B09;
  border:1px solid rgba(245,243,238,0.08);
  border-radius:20px;
  padding:14px;
  display:flex; flex-direction:column;
  transition:transform .3s ease, border-color .3s ease, box-shadow .3s ease;
}
/* Author `display:flex` above otherwise beats the UA stylesheet's own
   `[hidden]{display:none}` regardless of specificity (author origin always
   wins over user-agent origin in the cascade) — without this, toggling the
   `hidden` property from js/guias.js left filtered-out cards still
   rendered as flex items, just visually identical to the visible ones. */
.guide-card[hidden]{ display:none; }
.guide-card:hover{
  transform:translateY(-4px);
  border-color:var(--card-border-hover);
  box-shadow:0 20px 40px -24px rgba(0,0,0,0.6);
}
.guide-card-img{ position:relative; border-radius:16px; overflow:hidden; aspect-ratio:4/3; }
.guide-card-img img{
  width:100%; height:100%; object-fit:cover;
  filter:grayscale(65%); opacity:0.75;
  transition:transform .5s ease;
}
.guide-card:hover .guide-card-img img{ transform:scale(1.06); }
.guide-badges{
  position:absolute; top:14px; left:14px; right:14px;
  display:flex; align-items:flex-start; justify-content:space-between; gap:8px;
}
.guide-badge{
  font-size:0.5rem; font-weight:700; letter-spacing:0; text-transform:uppercase;
  background:rgba(14,14,12,0.6); backdrop-filter:blur(8px); -webkit-backdrop-filter:blur(8px);
  border:1px solid rgba(245,243,238,0.14);
  padding:4px 8px; border-radius:999px; white-space:nowrap;
}
.guide-badge-cat{ color:var(--accent-strong); min-width:0; }
.guide-badge-soon{ color:var(--text-muted); flex-shrink:0; }
.guide-card-body{ padding:20px 8px 6px; display:flex; flex-direction:column; flex:1; }
.guide-card-body h4{ font-size:1.02rem; font-weight:700; line-height:1.35; margin:0 0 12px; }
.guide-meta{ display:flex; gap:16px; flex-wrap:wrap; margin-bottom:12px; }
.guide-meta span{ display:flex; align-items:center; gap:6px; font-size:0.76rem; color:var(--text-faint); }
.guide-meta svg{ width:13px; height:13px; color:var(--accent); flex-shrink:0; }
.guide-card-body p{ color:var(--text-muted); font-size:0.87rem; line-height:1.6; margin:0; }
/* Text stand-in for the category/status badges below — those two live as
   absolutely-positioned pills ON the image (.guide-badge-cat/-soon), which
   only works while the image is big enough to hold them; on the compact
   phone row layout (see max-width:640px) the thumbnail shrinks to 104px
   and those pills get hidden outright, so this carries the same two facts
   as plain text instead. Hidden here (desktop/tablet still show the image
   pills) and switched on only inside that breakpoint. */
.guide-tag{ display:none; align-items:center; gap:6px; margin-bottom:4px; }
.guide-tag-cat{
  font-size:0.68rem; font-weight:700; text-transform:uppercase; letter-spacing:0.03em; color:var(--accent-strong);
  min-width:0; overflow:hidden; white-space:nowrap; text-overflow:ellipsis;
}
.guide-tag-soon{ font-size:0.68rem; color:var(--text-faint); flex-shrink:0; white-space:nowrap; }
.guide-tag-soon::before{ content:"· "; }

.guides-empty{ display:none; text-align:center; padding:60px 20px; color:var(--text-muted); }
.guides-empty p{ margin:0 0 18px; }

/* Below 960px the sidebar stops being an inline column (which, with a
   growing catalogue, would push the whole card grid further and further
   down the page before a visitor sees a single card) and becomes an
   off-canvas drawer instead — same slide-in-from-the-right mechanic as the
   mobile nav in styles.css's Nav section, opened via #guiasFiltersToggle
   and driven by js/guias.js (adds/removes .open on sidebar + backdrop). */
@media (max-width:960px){
  .guides-layout{ grid-template-columns:1fr; gap:0; }
  .guides-grid{ grid-template-columns:repeat(2,1fr); }

  .guides-filters-toggle{
    display:inline-flex; align-items:center; gap:8px;
    background:#0B0B09; border:1px solid var(--card-border); color:var(--text);
    border-radius:999px; padding:10px 16px; font-size:0.85rem; font-family:var(--sans);
    cursor:pointer; flex-shrink:0;
  }
  .guides-filters-toggle svg{ width:15px; height:15px; color:var(--accent); }

  .guides-filters-backdrop{
    display:block;
    position:fixed; inset:0; z-index:140;
    background:rgba(0,0,0,0.6);
    opacity:0; pointer-events:none;
    transition:opacity .3s ease;
  }
  .guides-filters-backdrop.open{ opacity:1; pointer-events:auto; }

  .guides-sidebar{
    position:fixed; inset:0 0 0 auto; z-index:150;
    width:86%; max-width:340px;
    background:#111110; border-left:1px solid var(--card-border);
    display:flex; flex-direction:column;
    padding:0 24px;
    overflow-y:auto;
    transform:translateX(100%);
    transition:transform .35s ease, visibility .35s ease;
    /* Same reasoning as .nav-links in the Nav section above: visibility
       (not just transform) guarantees this is never rendered while
       "closed", regardless of how a given mobile browser anchors
       position:fixed. */
    visibility:hidden;
  }
  .guides-sidebar.open{ transform:translateX(0); visibility:visible; }

  .guides-sidebar-head{
    display:flex; align-items:center; justify-content:space-between;
    position:sticky; top:0; z-index:1;
    padding:20px 0 18px; margin-bottom:4px;
    background:#111110; border-bottom:1px solid var(--card-border);
  }
  .guides-sidebar-head h3{ font-size:1.05rem; }
  .guides-sidebar-close{
    display:flex; align-items:center; justify-content:center;
    width:32px; height:32px; margin:-6px;
    background:none; border:none; color:var(--text-muted); cursor:pointer;
  }
  .guides-sidebar-close svg{ width:18px; height:18px; }

  .guides-drawer-footer{
    display:block;
    position:sticky; bottom:0;
    margin-top:auto; padding:18px 0 24px;
    background:#111110; border-top:1px solid var(--card-border);
  }
  .guides-drawer-footer .btn{ width:100%; justify-content:center; }

  .guides-count{ display:none; }
  .guides-toolbar{ justify-content:space-between; }
}
/* Phones: a single column of the full image-on-top cards still meant
   scrolling past one tall card per guide — with a catalogue that only
   grows over time that gets worse, not better. Swapped for a thin
   horizontal row (small square thumbnail + text) instead, so several
   guides fit in the same vertical space a single old card used to take. */
@media (max-width:640px){
  .guides-grid{ grid-template-columns:1fr; gap:12px; }
  .guides-sidebar{ width:100%; max-width:none; }

  .guide-card{ flex-direction:row; gap:14px; padding:10px; border-radius:16px; }
  .guide-card:hover{ transform:none; }
  .guide-card-img{ width:96px; height:96px; flex-shrink:0; border-radius:12px; aspect-ratio:1/1; }
  .guide-badge{ display:none; }
  .guide-tag{ display:flex; }
  .guide-card-body{ padding:0; min-width:0; }
  .guide-card-body h4{
    font-size:0.92rem; margin-bottom:6px;
    display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden;
  }
  .guide-meta{ gap:10px; margin-bottom:6px; }
  .guide-meta span{ font-size:0.7rem; }
  .guide-meta svg{ width:11px; height:11px; }
  .guide-card-body p{
    font-size:0.8rem; line-height:1.5;
    display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden;
  }
}

/* ---------- Premium CTA (glowing button with rising particles) ----------
   Reserved for the single "Guías avanzadas" upsell (guias.html hero) that
   leads to the paywalled guias-avanzadas.html — deliberately more ornate
   than the flat .btn-primary/.btn-ghost pair used everywhere else, so it
   visually announces "this leads somewhere different" before the visitor
   even reads the label.
   .btn-premium itself keeps the base .btn overflow:hidden (unlike an
   earlier version of this that set overflow:visible directly on it) —
   that's what .btn::before's diagonal hover sweep relies on to stay
   clipped inside the pill; overriding it let that sweep spill out as a
   stray white sliver next to the button, and on hover travel past the
   pill's edge onto "Consultar dudas" beside it. The rising particles still
   need to escape the pill's own bounds, so they live in .btn-premium-wrap
   instead — a plain relative-positioned sibling wrapper around the real
   button, not a descendant of it, so its overflow:visible never touches
   the button's own clipping. */
.btn-premium-wrap{ position:relative; display:inline-flex; }
.btn-premium{
  position:relative;
  z-index:2;
  overflow:hidden;
  background:linear-gradient(135deg, var(--accent-strong), var(--accent));
  color:#0E0E0C;
  font-weight:700;
  letter-spacing:0.01em;
  animation:btnPremiumGlow 2.6s ease-in-out infinite;
}
/* Inner top-edge highlight + bottom shade, independent of the animated
   outer glow below — gives the fill a rounded, glossy "gem" feel instead
   of a flat color swatch, which is most of what made it read as "not
   premium" before. */
.btn-premium{
  box-shadow:inset 0 1px 0 rgba(255,255,255,0.5), inset 0 -10px 16px -8px rgba(0,0,0,0.3);
}
.btn-premium:hover{
  transform:translateY(-3px) scale(1.04);
  background:linear-gradient(135deg, #B7D9A8, var(--accent-strong));
}
/* Continuous idle shine, distinct from .btn::before's own hover-only sweep
   (that one still fires too, layering a second highlight on interaction).
   A soft gold tint (not plain white) ties this back to the site's existing
   "premium = gold" language from .price-card.gold, while the button fill
   itself stays the requested green. */
.btn-premium::after{
  content:"";
  position:absolute; top:0; left:-60%; width:35%; height:100%;
  background:linear-gradient(120deg, transparent, rgba(255,247,224,0.75), transparent);
  transform:skewX(-20deg);
  animation:btnPremiumShine 3.4s ease-in-out infinite;
  pointer-events:none;
}
@keyframes btnPremiumShine{
  0%{ left:-60%; }
  40%, 100%{ left:130%; }
}
@keyframes btnPremiumGlow{
  0%,100%{
    box-shadow:inset 0 1px 0 rgba(255,255,255,0.5), inset 0 -10px 16px -8px rgba(0,0,0,0.3),
      0 0 0 1px rgba(217,188,133,0.4), 0 0 24px 3px rgba(122,158,106,0.5), 0 10px 26px -10px rgba(122,158,106,0.6);
  }
  50%{
    box-shadow:inset 0 1px 0 rgba(255,255,255,0.5), inset 0 -10px 16px -8px rgba(0,0,0,0.3),
      0 0 0 1px rgba(217,188,133,0.7), 0 0 42px 10px rgba(122,158,106,0.75), 0 14px 34px -10px rgba(122,158,106,0.8);
  }
}
/* Gold, not the button's own dark text color — a small deliberate accent
   nodding at "premium" (matching .price-card.gold elsewhere) without
   turning the button itself gold. */
.btn-premium-icon{ width:15px; height:15px; flex-shrink:0; position:relative; z-index:1; color:#5C4419; filter:drop-shadow(0 1px 0 rgba(255,255,255,0.35)); }

/* z-index:1, below .btn-premium's own z-index:2 — the button's opaque
   fill then covers the particles for the part of their path that's still
   within its bounds, so they only become visible once they rise clear of
   the top edge, reading as sparks emanating from behind the button rather
   than drifting in front of its text. */
.btn-premium-particles{ position:absolute; inset:0; z-index:1; overflow:visible; pointer-events:none; }
.btn-premium-particles span{
  position:absolute; bottom:10px; width:4px; height:4px; border-radius:50%;
  background:#FBF3DC;
  box-shadow:0 0 6px 2px rgba(217,188,133,0.85);
  opacity:0;
  animation:btnParticleRise 2.4s ease-in infinite;
}
.btn-premium-particles span:nth-child(1){ left:8%;  animation-delay:0s;   animation-duration:2.1s; }
.btn-premium-particles span:nth-child(2){ left:24%; animation-delay:.5s;  animation-duration:2.6s; }
.btn-premium-particles span:nth-child(3){ left:42%; animation-delay:1s;   animation-duration:2s;   }
.btn-premium-particles span:nth-child(4){ left:60%; animation-delay:.2s;  animation-duration:2.8s; }
.btn-premium-particles span:nth-child(5){ left:78%; animation-delay:1.4s; animation-duration:2.3s; }
.btn-premium-particles span:nth-child(6){ left:92%; animation-delay:.8s;  animation-duration:2.5s; }
@keyframes btnParticleRise{
  0%{ transform:translateY(0) scale(0.5); opacity:0; }
  20%{ opacity:1; }
  75%{ opacity:.5; }
  100%{ transform:translateY(-30px) scale(1); opacity:0; }
}
@media (prefers-reduced-motion: reduce){
  .btn-premium, .btn-premium::after{ animation:none; }
  .btn-premium-particles span{ animation:none; display:none; }
}
@media (prefers-reduced-motion: reduce){
  .logo-track{ animation:none; }
}

/* ---------- Locked preview cards (guias-avanzadas.html) ----------
   Same .guide-card family as the public catalogue, just visibly gated: the
   photo is blurred/dimmed with a lock badge centered over it, and the
   teaser paragraph is blurred too (readable as "there's text here", not
   what it says) — the standard paywall-preview treatment. */
.guide-card-locked{ cursor:default; }
.guide-card-locked:hover{ transform:none; box-shadow:none; }
.guide-card-locked:hover .guide-card-img img{ transform:none; }
.guide-card-locked .guide-card-img img{ filter:blur(3px) grayscale(55%); opacity:0.55; }
.guide-badge-locked{ color:#D9BC85; }
.guide-tag-locked{ color:#D9BC85; }
.guide-lock{
  position:absolute; inset:0; margin:auto;
  width:42px; height:42px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  background:rgba(14,14,12,0.65); backdrop-filter:blur(6px); -webkit-backdrop-filter:blur(6px);
  border:1px solid rgba(245,243,238,0.2);
  color:#D9BC85;
}
.guide-lock svg{ width:18px; height:18px; }
.guide-card-blur{ filter:blur(3px); user-select:none; }

/* 3-column variant of .mini-stats (guias.html's trust strip) — collapses to
   a single column on phones instead of the base class's 2-column split,
   since 3 items don't divide evenly into 2. */
.mini-stats-3{ grid-template-columns:repeat(3,1fr); }
@media (max-width:900px){ .mini-stats-3{ grid-template-columns:1fr; } }
.mini-stats-3 .mini-stat{ padding:16px; }
.mini-stats-3 .mini-stat-icon{ width:30px; height:30px; margin-bottom:12px; }
.mini-stats-3 .mini-stat-icon svg{ width:14px; height:14px; }
.mini-stats-3 .mini-stat h4{ font-size:0.95rem; margin:0 0 10px; }
.mini-stats-3 .mini-stat .service-divider{ margin-bottom:10px; }
.mini-stats-3 .mini-stat p{ font-size:0.8rem; }

/* ---------- Guías author byline (guias.html hero) ----------
   Replaces the generic avatar-stack trust-line used on the homepage —
   that exact "+96 · Más de 100 personas ya han confiado en mí" block
   already exists on inicio.html, so repeating it here read as filler
   rather than a real trust signal. A named byline with a real photo is
   more relevant for a content page: it tells the reader who's actually
   behind what they're about to read. */
.guias-author{ display:flex; align-items:center; justify-content:center; gap:14px; margin-top:44px; }
.guias-author-avatar{
  width:52px; height:52px; border-radius:50%;
  object-fit:cover; object-position:center 55%;
  border:2px solid var(--card-border-hover);
  flex-shrink:0;
}
.guias-author-copy{ display:flex; flex-direction:column; text-align:left; line-height:1.35; }
.guias-author-copy b{ color:var(--text); font-weight:600; font-size:0.95rem; }
.guias-author-copy small{ color:var(--text-faint); font-size:0.82rem; }
@media (max-width:560px){
  .guias-author{ gap:12px; }
  .guias-author-avatar{ width:44px; height:44px; }
  .guias-author-copy b{ font-size:0.88rem; }
  .guias-author-copy small{ font-size:0.78rem; }
}

/* ---------- Herramientas (premium tools page) ----------
   Deliberately not a reskin of guias.html's sidebar+card-grid catalogue —
   only 4 items exist here and they're paid, so the page reads more like a
   single-tier pricing showcase: one column of large feature panels instead
   of a browsable grid. Green throughout (not the site's one-off pricing
   gold) — this page isn't a single flagship tier sitting above a cheaper
   green one, it's the whole page's own identity, so it uses the site's
   normal accent instead of borrowing the "top-shelf" hue reserved for
   pricing.
   The "premium" feel here can't rely on :hover the way .spotlight-card
   does elsewhere — most visits are on mobile/touch, which never fires
   hover — so every panel uses the .price-card.featured recipe (static
   gradient + ring border + ambient glow, all visible at rest) instead. */
.tool-list{ display:flex; flex-direction:column; gap:70px; }
/* Marks the start of each tool clearly, before the eye even reaches the
   hero photo: a rule line above every block but the first, plus a running
   "N / 4" label — the generous .tool-list gap alone didn't read as "new
   section" on its own, it just looked like more whitespace. */
.tool-block:not(:first-child){ padding-top:70px; border-top:1px solid var(--card-border); }
.tool-block-head{ display:flex; align-items:center; gap:18px; margin-bottom:22px; }
.tool-block-tag{ font-size:0.72rem; letter-spacing:0.08em; text-transform:uppercase; color:var(--text-faint); white-space:nowrap; }
.tool-block-divider{ flex:1; height:1px; background:var(--card-border); }

/* Bento grid per tool — benefits, use cases, a headline number and what's
   included each get their own small card instead of one long panel, so a
   visitor scanning the page picks up more in the same space. Green stays
   the only accent (no gold): this page isn't a single flagship tier next
   to a cheaper one, so it doesn't borrow the site's pricing-only "top
   shelf" hue (see .price-card.gold's own comment on that rule). */
.tool-bento{
  display:grid;
  grid-template-columns:1.15fr 1fr 1fr;
  grid-template-areas:
    "hero apps  stat"
    "hero steps includes";
  gap:16px;
}
/* Shares the .reveal.card merge-fix pattern (see that rule's comment above):
   a card-like element that's also .reveal needs opacity in its OWN
   transition list, or the entrance fade silently drops. */
.bento-card{
  position:relative;
  background:#0B0B09; border:1px solid var(--card-border); border-radius:20px;
  padding:26px;
  transition:
    opacity .5s cubic-bezier(.2,.7,.2,1),
    transform .5s cubic-bezier(.2,.7,.2,1),
    border-color .3s ease,
    box-shadow .3s ease;
}
.bento-card:hover{
  transform:translateY(-4px);
  border-color:var(--card-border-hover);
  box-shadow:0 20px 40px -24px rgba(0,0,0,0.6);
}
.bento-label{ font-size:0.72rem; letter-spacing:0.08em; text-transform:uppercase; color:var(--text-faint); margin:0 0 16px; }

/* -- hero: image + intro, spans both rows -- */
/* The anchor card of the bento — gets the green ring+glow the whole grid
   used to have back when it was one big panel, so it still reads as "the
   main card" next to four flatter, black supporting ones. */
.bento-hero{
  grid-area:hero; padding:0; overflow:hidden; display:flex; flex-direction:column;
  border-color:rgba(122,158,106,0.45);
  box-shadow:0 0 40px -18px rgba(122,158,106,0.35);
}
.bento-hero::before{
  content:""; position:absolute; top:0; left:0; right:0; height:2px; z-index:2;
  background:linear-gradient(90deg, transparent, rgba(147,182,131,0.8), transparent);
}
.bento-hero:hover{
  border-color:rgba(122,158,106,0.65);
  box-shadow:0 0 60px -12px rgba(122,158,106,0.5), 0 24px 44px -26px rgba(0,0,0,0.6);
}
.bento-hero-media{ position:relative; aspect-ratio:1/1; overflow:hidden; flex-shrink:0; }
.bento-hero-media img{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; transition:transform .6s ease; }
.bento-hero:hover .bento-hero-media img{ transform:scale(1.05); }
/* Reuses guide-badge/-cat/-soon as-is (guias.html's catalogue pattern) —
   same glass pill over a photo, same meaning, so a second badge language
   doesn't need inventing just because this page also shows images. */
.tool-media-badges{
  position:absolute; top:16px; left:16px; right:16px; z-index:1;
  display:flex; align-items:flex-start; justify-content:space-between; gap:8px;
}
.bento-hero-body{
  padding:26px; display:flex; flex-direction:column; flex:1;
  background:linear-gradient(180deg, rgba(122,158,106,0.12), rgba(122,158,106,0.02));
}
.tool-eyebrow{ margin-bottom:14px; }
.tool-num{
  display:inline-flex; align-items:center; justify-content:center;
  font-family:var(--serif); font-size:0.78rem; font-weight:700; letter-spacing:0.05em;
  color:var(--accent-strong);
  background:var(--accent-soft); border:1px solid rgba(122,158,106,0.3);
  padding:5px 12px; border-radius:999px;
}
.bento-hero-body h3{ margin:0 0 10px; font-size:1.24rem; }
.tool-desc{ color:var(--text-muted); font-size:0.88rem; line-height:1.6; margin:0 0 20px; }
.tool-panel-footer{
  display:flex; align-items:center; gap:12px; flex-wrap:wrap;
  margin-top:auto; padding-top:20px; border-top:1px solid var(--card-border);
}
/* Neutral, not green — matches guide-badge-soon's own convention elsewhere
   (category = accent green, status = muted gray). Green here would compete
   with .bento-stat, the one card actually meant to pop per tool. */
.tool-badge-soon{
  display:inline-flex; align-items:center; gap:6px;
  font-size:0.7rem; font-weight:700; letter-spacing:0.04em; text-transform:uppercase;
  color:var(--text-muted); background:rgba(245,243,238,0.05); border:1px solid var(--card-border);
  padding:6px 12px; border-radius:999px;
}
.tool-badge-soon svg{ width:12px; height:12px; }
/* A <span>, never an <a> — these tools aren't purchasable yet, so there is
   no href to visit; aria-disabled plus cursor:not-allowed communicate that
   without a click target that goes nowhere. */
.tool-cta-disabled{
  display:inline-flex; align-items:center; gap:8px;
  font-size:0.8rem; color:var(--text-faint);
  background:rgba(245,243,238,0.03); border:1px solid var(--card-border);
  padding:9px 16px; border-radius:999px;
  cursor:not-allowed; user-select:none;
}
.tool-cta-disabled svg{ width:14px; height:14px; }

/* -- stat: dark green accent, big animated number (reuses the sitewide
   [data-count-to] counter in animations.js — no page-specific JS needed) -- */
.bento-stat{
  grid-area:stat;
  display:flex; flex-direction:column; justify-content:center;
}
.bento-stat-num{
  font-family:var(--serif); font-size:2.4rem; font-weight:700; line-height:1;
  color:var(--text);
  font-variant-numeric:tabular-nums;
}
.bento-stat-label{ margin-top:10px; font-size:0.85rem; color:var(--text-muted); line-height:1.5; }

/* -- apps: chip grid of use cases -- */
.bento-chip-grid{ display:grid; grid-template-columns:1fr 1fr; gap:10px; }
.bento-chip{
  display:flex; flex-direction:column; gap:9px;
  background:rgba(245,243,238,0.03); border:1px solid var(--card-border); border-radius:12px;
  padding:12px; font-size:0.78rem; color:var(--text-muted); line-height:1.35;
  transition:border-color .3s ease;
}
.bento-card:hover .bento-chip{ border-color:rgba(122,158,106,0.3); }
/* Same green icon-badge language as .icon-badge/.step-num-badge/.price-card-icon
   elsewhere on the site — small circular accents are the one thing that
   stays green everywhere; what changed is the CARD backgrounds around them,
   which are black now instead of every card getting a green tint. */
.bento-chip-icon{
  display:inline-flex; align-items:center; justify-content:center;
  width:26px; height:26px; border-radius:8px;
  background:var(--accent-soft); color:var(--accent-strong); flex-shrink:0;
}
.bento-chip-icon svg{ width:13px; height:13px; }

/* -- steps: numbered mini process -- */
.bento-step-list{ list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:14px; }
.bento-step-list li{ display:flex; align-items:flex-start; gap:12px; font-size:0.83rem; color:var(--text-muted); line-height:1.5; }
.bento-step-num{
  flex-shrink:0; width:22px; height:22px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  background:var(--accent-soft); color:var(--accent-strong);
  font-size:0.72rem; font-weight:700;
}

/* -- includes: reuses .tool-features (same check-list language as before) -- */
.tool-features{ list-style:none; padding:0; margin:0; display:flex; flex-direction:column; gap:11px; }
.tool-features li{ font-size:0.83rem; color:var(--text-muted); line-height:1.45; padding-left:22px; position:relative; }
.tool-features li::before{ content:"✓"; position:absolute; left:0; color:var(--accent-strong); text-shadow:0 0 10px rgba(122,158,106,0.6); }

@media (max-width:900px){
  .tool-bento{
    grid-template-columns:1fr;
    grid-template-areas:
      "hero"
      "stat"
      "apps"
      "steps"
      "includes";
  }
  .bento-hero-media{ aspect-ratio:16/11; }
  /* .guide-badge itself goes display:none under 640px sitewide (guias.html's
     catalogue swaps it for a text stand-in on its cramped 96px thumbnails —
     see that rule's own comment). This page's media block is full-width on
     mobile, not a 96px thumbnail, so the badges still fit fine; the extra
     class here outranks that single-class rule regardless of file order. */
  .bento-hero-media .guide-badge{ display:flex; }
}

/* ---------- Blog (blog.html + individual post pages) ----------
   Deliberately imageless cards (icon + category instead of a thumbnail) —
   this is a text-first catalogue that will grow post by post, and a
   round icon badge doesn't require sourcing/cropping a photo per article
   the way .guide-card's thumbnails do. Filtering is plain JS (js/blog.js)
   toggling [hidden] on .blog-card, same approach as guias.html. */
.blog-search{
  display:flex; align-items:center; gap:10px;
  background:#0B0B09; border:1px solid var(--card-border); border-radius:999px;
  padding:12px 18px; margin-bottom:18px; max-width:420px;
  transition:border-color .2s ease;
}
.blog-search:focus-within{ border-color:var(--card-border-hover); }
.blog-search svg{ width:16px; height:16px; color:var(--text-faint); flex-shrink:0; }
.blog-search input{
  background:none; border:none; outline:none; width:100%;
  color:var(--text); font-family:var(--sans); font-size:0.9rem;
}
.blog-search input::placeholder{ color:var(--text-faint); }

.blog-empty{ display:none; text-align:center; padding:50px 20px; }
.blog-empty p{ color:var(--text-muted); margin:0 0 18px; }

.blog-filters{ display:flex; flex-wrap:wrap; gap:10px; }
.blog-filter-btn{
  display:flex; align-items:center; gap:8px;
  background:var(--card); border:1px solid var(--card-border); border-radius:999px;
  padding:10px 18px; color:var(--text-muted); font-family:var(--sans);
  font-size:0.85rem; font-weight:600; cursor:pointer;
  transition:background .2s ease, border-color .2s ease, color .2s ease;
}
.blog-filter-btn svg{ width:15px; height:15px; flex-shrink:0; }
.blog-filter-btn:hover{ border-color:var(--card-border-hover); color:var(--text); }
.blog-filter-btn.active{ background:var(--accent-soft); border-color:transparent; color:var(--accent-strong); }

.blog-toolbar{ display:flex; align-items:center; justify-content:space-between; gap:16px; flex-wrap:wrap; margin:26px 0; }
.blog-count{ color:var(--text-muted); font-size:0.9rem; }

.blog-grid{ display:grid; grid-template-columns:repeat(3,1fr); gap:22px; transition:opacity .2s ease; }
.blog-grid.is-paging{ opacity:0; }
.blog-card{
  background:#0B0B09; border:1px solid var(--card-border); border-radius:18px;
  padding:26px 24px 22px; display:flex; flex-direction:column;
  transition:transform .3s ease, border-color .3s ease, box-shadow .3s ease;
}
.blog-card[hidden]{ display:none; }
a.blog-card:hover{
  transform:translateY(-4px); border-color:var(--card-border-hover);
  box-shadow:0 20px 40px -24px rgba(0,0,0,0.6);
}
.blog-card-top{ display:flex; align-items:center; gap:10px; margin-bottom:18px; }
.blog-card-icon{
  width:32px; height:32px; border-radius:50%; flex-shrink:0;
  display:flex; align-items:center; justify-content:center; background:var(--accent-soft);
}
.blog-card-icon svg{ width:15px; height:15px; color:var(--accent-strong); }
.blog-card-cat{ font-size:0.68rem; font-weight:700; letter-spacing:0.06em; text-transform:uppercase; color:var(--accent-strong); }
.blog-card h3{ font-size:1.1rem; line-height:1.35; margin:0 0 10px; }
.blog-card p{ color:var(--text-muted); font-size:0.87rem; line-height:1.6; margin:0 0 20px; flex:1; }
.blog-card-foot{
  display:flex; align-items:center; justify-content:space-between; gap:12px;
  padding-top:16px; border-top:1px solid var(--card-border);
  font-size:0.74rem; letter-spacing:0.02em; text-transform:uppercase; color:var(--text-faint);
}
.blog-read{ color:var(--accent-strong); font-weight:700; }
.blog-card.is-soon{ cursor:default; }
.blog-card.is-soon .blog-read{ color:var(--text-faint); }

@media (max-width:980px){ .blog-grid{ grid-template-columns:repeat(2,1fr); } }
@media (max-width:640px){
  .blog-grid{ grid-template-columns:1fr; }
  .blog-filter-btn{ padding:8px 14px; font-size:0.8rem; }
}

/* Pagination — same circular-pill language as .showcase-arrow/.showcase-dot,
   rendered by js/blog.js once there are more than PAGE_SIZE matching cards. */
.blog-pagination{ display:flex; align-items:center; justify-content:center; gap:8px; margin-top:34px; flex-wrap:wrap; }
.blog-page-btn{
  min-width:36px; height:36px; padding:0 4px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  background:var(--card); border:1px solid var(--card-border); color:var(--text-muted);
  font-family:var(--sans); font-size:0.85rem; font-weight:600; cursor:pointer;
  transition:background .2s ease, border-color .2s ease, color .2s ease;
}
.blog-page-btn:hover{ border-color:var(--card-border-hover); color:var(--text); }
.blog-page-btn.active{ background:var(--accent-soft); border-color:transparent; color:var(--accent-strong); }
.blog-page-arrow{
  width:36px; height:36px; border-radius:50%; flex-shrink:0;
  display:flex; align-items:center; justify-content:center;
  background:var(--card); border:1px solid var(--card-border); color:var(--text);
  cursor:pointer; transition:background .2s ease, border-color .2s ease, transform .2s ease, color .2s ease;
}
.blog-page-arrow:hover{ border-color:var(--accent); color:var(--accent-strong); transform:translateY(-2px); }
.blog-page-arrow:disabled{ opacity:0.35; cursor:default; pointer-events:none; transform:none; }
.blog-page-arrow svg{ width:15px; height:15px; }

/* ---------- Blog post article layout ---------- */
.post-meta{ display:flex; align-items:center; gap:10px; color:var(--text-faint); font-size:0.82rem; margin-bottom:18px; }
.post-meta span:not(:last-child)::after{ content:"·"; margin-left:10px; color:var(--text-faint); }
.post-content{ max-width:720px; margin:0 auto; }
.post-content h2{ font-size:1.5rem; margin:44px 0 16px; }
.post-content h2:first-child{ margin-top:0; }
.post-content p{ color:var(--text-muted); font-size:1rem; line-height:1.8; margin:0 0 18px; }
.post-content ul{ margin:0 0 18px; padding-left:20px; color:var(--text-muted); font-size:1rem; line-height:1.75; }
.post-content li{ margin-bottom:8px; }
.post-content strong{ color:var(--text); }
/* :not(.btn) — otherwise this beat .btn-primary's own dark text color on
   the promo card's CTA button (same specificity, later in the file), so
   its label rendered pale green on green instead of dark on green. */
.post-content a:not(.btn){ color:var(--accent-strong); }
.post-content a:not(.btn):hover{ text-decoration:underline; }

/* Larger opening paragraph — breaks the "wall of identical gray text"
   look by giving the reader one clearly different beat before the article
   settles into its normal body rhythm. */
.post-lead{ font-size:1.15rem; line-height:1.7; color:var(--text); margin:0 0 22px; }

/* Numbered section headings (listicle-style posts) — a small round badge
   in front of the heading instead of a bare "1." in the text, so each
   section reads as its own beat rather than another paragraph in the
   scroll. Plain (non-numbered) h2s just render without the badge. */
.post-content h2{ display:flex; align-items:center; gap:14px; }
.post-num{
  display:flex; align-items:center; justify-content:center; flex-shrink:0;
  width:34px; height:34px; border-radius:50%;
  background:var(--accent-soft); color:var(--accent-strong);
  font-size:1rem; font-weight:700;
}

/* Callout box — a tip (default) or a red-flag warning (.is-warn), pulled
   out of the paragraph flow with its own background so a key takeaway
   doesn't get lost between two identical-looking blocks of body text. */
.post-callout{
  display:flex; gap:14px; align-items:flex-start;
  background:var(--accent-soft); border:1px solid var(--card-border-hover);
  border-radius:14px; padding:18px 20px; margin:26px 0;
}
.post-callout.is-warn{ background:var(--warn-soft); border-color:rgba(180,105,74,0.4); }
.post-callout-icon{ flex-shrink:0; width:20px; height:20px; color:var(--accent-strong); margin-top:2px; }
.post-callout.is-warn .post-callout-icon{ color:var(--warn); }
.post-callout p{ margin:0; color:var(--text); font-size:0.94rem; line-height:1.65; }

/* Pull quote — one sentence set apart at article scale, the same trick
   long-form editorial pieces use to break a page of body copy visually. */
.post-pullquote{
  border-left:3px solid var(--accent); margin:34px 0; padding:2px 0 2px 24px;
  font-size:1.3rem; font-weight:600; line-height:1.5; color:var(--text);
}

/* Worked-example / calculation card — concrete numbers laid out as rows
   instead of buried in a paragraph, for posts that walk through a real
   cost breakdown. */
.post-example{ background:#0B0B09; border:1px solid var(--card-border); border-radius:14px; padding:22px 24px; margin:28px 0; }
.post-example-title{ font-size:0.7rem; font-weight:700; letter-spacing:0.06em; text-transform:uppercase; color:var(--accent-strong); margin-bottom:14px; }
.post-example-row{ display:flex; justify-content:space-between; gap:12px; padding:9px 0; border-bottom:1px solid var(--card-border); font-size:0.92rem; color:var(--text-muted); }
.post-example-row:last-child{ border-bottom:none; }
.post-example-row strong{ color:var(--text); }
.post-example-total{ display:flex; justify-content:space-between; margin-top:12px; padding-top:14px; border-top:1px solid var(--card-border-hover); font-size:1.08rem; font-weight:700; color:var(--accent-strong); }

/* Method-comparison card (payments post) — each option gets its own
   boxed verdict instead of another paragraph that reads the same as the
   last one. Risk badge uses only the two semantic colors already in the
   palette (green/warn) plus a neutral gray for "medium" — no amber/gold. */
.post-method{ background:#0B0B09; border:1px solid var(--card-border); border-radius:16px; padding:20px 22px; margin:20px 0; }
.post-method-head{ display:flex; align-items:center; justify-content:space-between; gap:12px; margin-bottom:10px; flex-wrap:wrap; }
.post-method-head h3{ margin:0; font-size:1.05rem; color:var(--text); }
.post-method-badge{ font-size:0.66rem; font-weight:700; letter-spacing:0.04em; text-transform:uppercase; padding:4px 10px; border-radius:999px; flex-shrink:0; white-space:nowrap; }
.post-method-badge.risk-low{ background:var(--accent-soft); color:var(--accent-strong); }
.post-method-badge.risk-mid{ background:rgba(245,243,238,0.08); color:var(--text-muted); }
.post-method-badge.risk-high{ background:var(--warn-soft); color:var(--warn); }
.post-method p{ margin:0; color:var(--text-muted); font-size:0.9rem; line-height:1.6; }

/* FAQ block at the end of a post — reuses the exact .faq-list/.faq-item
   markup + JS toggle from the homepage FAQ, so no new JS is needed here. */
.post-faq{ margin-top:8px; }

@media (max-width:640px){
  .post-content h2{ gap:10px; font-size:1.3rem; }
  .post-num{ width:28px; height:28px; font-size:0.88rem; }
  .post-pullquote{ font-size:1.1rem; }
  .post-method-head{ flex-direction:column; align-items:flex-start; gap:8px; }
}

/* Promotional card embedded inside every post — ties the article back to
   the specific service it's most relevant to, not a generic "hablemos". */
.post-promo{
  display:flex; align-items:center; gap:20px; flex-wrap:wrap;
  background:linear-gradient(135deg, rgba(122,158,106,0.14), rgba(122,158,106,0.02));
  border:1px solid var(--card-border-hover); border-radius:18px;
  padding:26px 28px; margin:40px 0;
}
.post-promo-icon{
  width:46px; height:46px; border-radius:50%; flex-shrink:0;
  display:flex; align-items:center; justify-content:center; background:var(--accent-soft);
}
.post-promo-icon svg{ width:22px; height:22px; color:var(--accent-strong); }
.post-promo-body{ flex:1 1 260px; min-width:0; }
.post-promo-eyebrow{ font-size:0.68rem; font-weight:700; letter-spacing:0.06em; text-transform:uppercase; color:var(--accent-strong); margin-bottom:6px; }
.post-promo h4{ margin:0 0 6px; font-size:1.05rem; }
.post-promo p{ margin:0; color:var(--text-muted); font-size:0.87rem; line-height:1.5; }
.post-promo .btn{ flex-shrink:0; }
@media (max-width:560px){ .post-promo{ padding:22px; } .post-promo .btn{ width:100%; text-align:center; } }

.post-back{ display:inline-flex; align-items:center; gap:6px; color:var(--text-muted); font-size:0.85rem; margin-bottom:20px; }
.post-back:hover{ color:var(--text); }

/* ---------- Utility ---------- */
.mt-0{ margin-top:0; }
.center{ text-align:center; margin-left:auto; margin-right:auto; }
.max-w{ max-width:640px; }
.flex-between{ display:flex; align-items:center; justify-content:space-between; gap:20px; flex-wrap:wrap; }
