/* Website UI — layout + component styles, built on colors_and_type.css vars */

*{box-sizing:border-box}
html,body{margin:0;padding:0;background:var(--bg);color:var(--fg);}
img{max-width:100%;display:block}
button{font:inherit;cursor:pointer}

.container{max-width:var(--container);margin:0 auto;padding:0 32px;width:100%}

/* ---- Buttons ---- */
.btn{font-family:var(--font-sans);font-weight:500;font-size:14px;letter-spacing:.02em;border-radius:2px;padding:14px 22px;border:1px solid transparent;cursor:pointer;display:inline-flex;align-items:center;gap:10px;transition:all 200ms var(--ease-out);text-transform:none;}
.btn .arr{transition:transform 200ms var(--ease-out);}
.btn:hover{transform:translateY(-1px);}
.btn:hover .arr{transform:translateX(3px);}
.btn:active{transform:translateY(0);}
.btn-primary{background:var(--ai-blue);color:#fff;}
.btn-primary:hover{background:var(--ai-blue-600);}
.btn-outline-dark{background:transparent;color:#111;border-color:#111;}
.btn-outline-dark:hover{background:#111;color:#fff;}
.btn-outline-white{background:transparent;color:#fff;border-color:#fff;}
.btn-outline-white:hover{background:#fff;color:#0D1B2A;}
.btn-ghost{background:transparent;color:var(--accent);border:0;padding:14px 0;}
.btn-ghost .u{border-bottom:1px solid currentColor;padding-bottom:2px;}
.btn-ghost:hover{color:var(--accent-hover);}

/* ---- Lang toggle ---- */
.lang-toggle{display:inline-flex;border:1px solid rgba(245,245,243,.4);border-radius:999px;overflow:hidden;}
.lang-toggle span{padding:5px 12px;font-size:11px;letter-spacing:.12em;font-weight:500;color:#F5F5F3;cursor:pointer;text-transform:uppercase;}
.lang-toggle span.on{background:#F5F5F3;color:#0D1B2A;}

/* ---- Nav ---- */
.ai-nav{position:fixed;top:0;left:0;right:0;z-index:50;transition:background 280ms var(--ease-out),border-color 280ms;background:transparent;border-bottom:1px solid transparent;}
/* Readability scrim — while the bar is transparent it sits straight on top
   of the hero video, and a bright frame (a white BIM render, a sunlit
   facade) swallows the links. This gradient drops a soft navy wash behind
   the bar that fades to nothing just below it, so the nav always has
   contrast without reading as a solid band. It extends 40px past the bar
   so the fade ends in open air rather than cutting off at the edge.
   Hidden once the bar goes solid on scroll — the solid background does
   the job from there. */
.ai-nav::before{
  content:"";
  position:absolute;left:0;right:0;top:0;bottom:-40px;
  background:linear-gradient(180deg,
    rgba(13,27,42,.78) 0%,
    rgba(13,27,42,.52) 45%,
    rgba(13,27,42,.20) 75%,
    rgba(13,27,42,0)   100%);
  pointer-events:none;
  opacity:1;
  transition:opacity 280ms var(--ease-out);
  z-index:0;
}
.ai-nav--solid::before{opacity:0;}
.ai-nav--solid{background:rgba(13,27,42,.94);backdrop-filter:blur(8px);border-bottom:1px solid rgba(30,43,58,.8);}
/* Above the scrim */
.ai-nav__inner{position:relative;z-index:1;max-width:var(--container);margin:0 auto;height:var(--nav-h);display:flex;align-items:center;gap:40px;padding:0 32px;}
/* --logo-h drives the mark's height (the Logo component reads it, with its
   `size` prop as fallback). Scoped to the nav so the footer logo, which has
   no variable set, keeps its own size. */
.ai-nav__logo{cursor:pointer;flex:0 0 auto;--logo-h:54px;}
.ai-nav__logo img{height:var(--logo-h);width:auto;max-width:none;display:block;aspect-ratio:1055/467;object-fit:contain;}
/* Large screens — NavLogo's <picture> swaps the stacked mark for the
   horizontal lockup (wordmark beside the mark, viewBox 545.63×83.09), so
   the aspect-ratio has to change with it or the SVG gets squashed.
   The bar keeps its normal height: the side lockup is short and wide, which
   is the whole point — it reads bigger without a taller header.
   Two steps because the logo has to share the row with 7 nav links and the
   language toggle, and the Spanish labels are ~150px wider than the English
   ones. At 1280px the row has roughly 375px of slack, so 46px tall (≈302px
   wide) fits; from 1440px there's ~455px, enough for 52px (≈342px). */
@media (min-width:1280px){
  .ai-nav__logo{--logo-h:46px;}
  .ai-nav__logo img{aspect-ratio:545.63/83.09;}
}
@media (min-width:1440px){
  .ai-nav__logo{--logo-h:52px;}
}
.ai-nav__links{display:flex;gap:6px;list-style:none;margin:0 0 0 auto;padding:0;flex-wrap:nowrap;}
.ai-nav__links li{white-space:nowrap;}
.ai-nav__link{color:#F5F5F3;font-size:12px;font-weight:500;letter-spacing:.1em;text-transform:uppercase;cursor:pointer;padding:10px 16px 6px;position:relative;transition:color 180ms var(--ease-out);white-space:nowrap;display:inline-block;}
.ai-nav__link::after{content:"";position:absolute;left:16px;right:16px;bottom:0;height:1px;background:#FFFFFF;transform:scaleX(0);transform-origin:left;transition:transform 320ms var(--ease-out);}
.ai-nav__link:hover{color:#FFFFFF;}
.ai-nav__link:hover::after,
.ai-nav__link.is-active::after{transform:scaleX(1);}
.ai-nav__link.is-active{color:#FFFFFF;}
.ai-nav__right{display:flex;align-items:center;gap:16px;}
.ai-nav__burger{display:none;background:none;border:0;padding:6px;}
/* Full-screen mobile menu. overflow-y:auto is load-bearing, not polish:
   with seven top-level entries plus the four area sub-entries the list runs
   ~1310px, and on a 375x812 phone that left Contacto simply unreachable —
   the content overflowed and nothing scrolled. */
.ai-nav__overlay{
  position:fixed;inset:0;background:#0D1B2A;z-index:60;
  padding:26px 32px calc(26px + env(safe-area-inset-bottom));
  display:flex;flex-direction:column;
  overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;
}
.ai-nav__overlay-top{display:flex;justify-content:space-between;align-items:center;}
.ai-nav__close{background:none;border:0;color:#F5F5F3;}
/* Sizes scale with the viewport instead of sitting at a fixed 44px, which
   was tuned for a tablet and overflowed every phone. The clamps keep the
   original values on large screens and shrink to something that fits a
   375px-wide, 812px-tall phone without scrolling at all. */
.ai-nav__overlay-links{
  list-style:none;padding:0;display:flex;flex-direction:column;
  margin:clamp(28px, 5vh, 60px) 0 0;
  gap:clamp(14px, 2.4vh, 24px);
}
.ai-nav__overlay-links a{
  color:#F5F5F3;font-family:var(--font-display);font-weight:500;
  font-size:clamp(26px, 7vw, 44px);
  line-height:1.15;cursor:pointer;
}
/* Inline sector list under the Proyectos entry in the mobile overlay.
   Indented + smaller than the top-level entries so the hierarchy reads. */
/* Parent entries that carry a sub-list. The chevron is the only signal
   that a tap will expand rather than navigate, so it points right when
   closed and down when open. */
.ai-nav__overlay-parent{
  display:inline-flex;align-items:center;gap:14px;
}
.ai-nav__overlay-chev{
  display:inline-block;
  font-size:0.62em;line-height:1;
  color:rgba(245,245,243,.5);
  transform:rotate(0deg);
  transition:transform 200ms var(--ease-out), color 200ms var(--ease-out);
}
.ai-nav__overlay-chev.is-open{
  transform:rotate(90deg);
  color:rgba(245,245,243,.85);
}
/* Sub-lists mount on expand, so animate them in rather than having them
   appear instantly under the finger. */
.ai-nav__overlay-sub{animation:navSubIn 220ms var(--ease-out);}
@keyframes navSubIn{
  from{opacity:0;transform:translateY(-6px);}
  to  {opacity:1;transform:translateY(0);}
}
@media (prefers-reduced-motion: reduce){
  .ai-nav__overlay-sub{animation:none;}
  .ai-nav__overlay-chev{transition:none;}
}

.ai-nav__overlay-sub > ul{
  list-style:none;padding:0 0 0 20px;display:flex;flex-direction:column;
  margin:clamp(10px, 1.6vh, 14px) 0 0;
  gap:clamp(10px, 1.5vh, 14px);
  border-left:1px solid rgba(245,245,243,.22);
}
.ai-nav__overlay-sub a{
  color:rgba(245,245,243,.78);font-family:var(--font-display);font-weight:500;
  font-size:clamp(17px, 4.6vw, 22px);
  line-height:1.2;letter-spacing:-0.005em;cursor:pointer;display:block;
}
.ai-nav__overlay-sub a:hover{color:#F5F5F3;}

/* ---- Nav dropdown (Proyectos → 6 sectors) ----
   The trigger `li` gets `.ai-nav__has-menu`. The panel opens on hover or
   keyboard-focus — driven by THREE conditions in OR so any one is enough:
     1. JS state via `.is-open` (added by Nav.jsx on mouseenter / focus)
     2. CSS `:hover` on the trigger li (pure CSS, no JS required)
     3. CSS `:focus-within` on the trigger li (keyboard tabbing into the panel)
   The pure-CSS routes (#2 + #3) are belt-and-suspenders: if React state ever
   races or stalls, hover still works.
   The panel itself is anchored below the trigger and slides down a hair under
   the nav bar, with a transparent hover bridge (`padding-top`) so the cursor
   can travel from the trigger into the panel without the dropdown closing. */
.ai-nav__has-menu{position:relative;}

.ai-nav__menu{
  position:absolute;top:100%;left:50%;transform:translateX(-50%) translateY(6px);
  /* Size to widest label (+ panel padding) rather than a hardcoded
     300px floor. Keeps the Talento dropdown tight (just fits "Life
     at Aguilera") and the Proyectos dropdown still gets enough
     room because its longest sector label drives the intrinsic
     width. min-width acts as a safety net for very short labels. */
  width:max-content;
  min-width:180px;
  padding-top:18px;                 /* hover bridge — covers the gap between
                                       the anchor's bottom padding and the
                                       panel's actual content, so the cursor
                                       can travel down without triggering
                                       mouseleave. */
  opacity:0;visibility:hidden;pointer-events:none;
  transition:opacity 180ms var(--ease-out), transform 180ms var(--ease-out), visibility 0s linear 180ms;
  z-index:55;
}
.ai-nav__has-menu.is-open .ai-nav__menu,
.ai-nav__has-menu:hover .ai-nav__menu,
.ai-nav__has-menu:focus-within .ai-nav__menu{
  opacity:1;visibility:visible;pointer-events:auto;
  transform:translateX(-50%) translateY(0);
  transition:opacity 180ms var(--ease-out), transform 180ms var(--ease-out), visibility 0s;
}
/* Dropdown panel — minimalist editorial (F+P cadence). No header separator,
   no per-item arrow reveal, no hover background tint. The parent entry and
   the sector entries share the same typography so the panel reads as a
   single coherent list rather than a banner-plus-menu. */
.ai-nav__menu-inner{
  background:rgba(13,27,42,.98);
  backdrop-filter:blur(10px);
  border:1px solid rgba(245,245,243,.12);
  padding:14px 0;
  box-shadow:0 14px 40px rgba(0,0,0,.45);
}
.ai-nav__menu-inner{
  background:rgba(13,27,42,.98);
  backdrop-filter:blur(10px);
  border:1px solid rgba(245,245,243,.12);
  padding:14px 0;
  box-shadow:0 14px 40px rgba(0,0,0,.45);
}
.ai-nav__menu-list{list-style:none;margin:0;padding:0;}
/* El desplegable habla el mismo idioma que el menú de arriba: versales,
   12 px y el mismo interletrado. Antes usaba la tipografía de titulares
   a 15 px y en caja baja, así que el padre iba en mayúsculas y sus hijos
   parecían texto corrido colgando de la barra. */
.ai-nav__menu-list a{
  display:block;
  padding:10px 22px;
  color:rgba(245,245,243,.78);
  font-weight:500;font-size:12px;
  line-height:1.35;letter-spacing:.1em;
  cursor:pointer;text-transform:uppercase;
  transition:color 160ms var(--ease-out);
}
.ai-nav__menu-list a:hover{color:#FFFFFF;}
/* Primary item in the dropdown — bolder + brighter so it reads as
   the main destination. Used for "Opportunities" in the Talento
   subnav; opt-in via the `primary: true` flag on the i18n entry. */
.ai-nav__menu-list .is-primary a{color:#FFFFFF;font-weight:700;}
/* Label/arrow spans kept in markup for backward-compat; arrow now hidden. */
.ai-nav__menu-label{display:inline;}
.ai-nav__menu-arrow{display:none;}

@media (max-width:900px){
  .ai-nav__links{display:none;}
  .ai-nav__right .lang-toggle{display:none;}
  .ai-nav__burger{display:inline-flex;}
  /* The desktop dropdown panel never renders below 900px — the overlay's
     inline list takes over. Belt-and-suspenders: hide it explicitly. */
  .ai-nav__menu{display:none;}
}

/* ---- Hero ---- */
/* Background uses the same deep navy as the rest of the site so the brief
   instant between page-load and video first-frame doesn't flash a black
   box — instead the area reads as a continuation of the dark surface. */
.hero{position:relative;height:100vh;min-height:640px;overflow:hidden;background:#0a1623;}
/* Bottom scrim — the mirror of the nav's readability gradient at the head
   of the page, doing the same job for the chrome that lives at the foot of
   the hero: the dot strip, the arrows and the architect credit.
   It belongs to .hero rather than to each slide on purpose. The slides
   cross-fade, so a per-slide gradient dips in the middle of a transition
   and the dots wobble in and out of legibility; anchored to the hero it
   holds steady for the whole reel, whatever frame is underneath.
   z-index:2 puts it over the slides (z-index:0) and under the dots and
   credit (z-index:3). */
.hero::after{
  content:"";
  position:absolute;left:0;right:0;bottom:0;
  height:200px;
  background:linear-gradient(180deg,
    rgba(13,27,42,0)   0%,
    rgba(13,27,42,.30) 42%,
    rgba(13,27,42,.66) 76%,
    rgba(13,27,42,.84) 100%);
  pointer-events:none;
  z-index:2;
}
@media (max-width:900px){
  .hero::after{height:160px;}
}
/* Slides are stacked at inset:0 — opacity hides them but the DOM stays
   intact, so without pointer-events:none the LAST slide in DOM order
   captures every click on top of the visible one (which routed every
   "View projects" CTA to the final slide's sector, no matter what was
   on screen). Restoring pointer-events:auto only on the active slide
   fixes the routing. */
.hero__slide{
  position:absolute;inset:0;
  opacity:0;pointer-events:none;
  transition:opacity 1000ms var(--ease-out);
  /* Own stacking context, so the layer order INSIDE a slide (poster ->
     video -> overlay -> copy) stays a private matter and can't compete
     with the hero's own chrome (arrows, dots, credit) that sits outside
     the slides. Without this the video's z-index:1 escaped the slide and
     painted over the overlay gradient and the headline. */
  z-index:0;
  isolation:isolate;
}
.hero__slide.is-active{opacity:1;pointer-events:auto;}
.hero__img{width:100%;height:100%;object-fit:cover;}
/* Video carousel slide — same full-bleed cover treatment as the still img.
   muted + playsInline + autoPlay covers the browsers' silent-autoplay rules.
   No `poster` attribute on purpose: an unloaded video renders as the hero's
   own navy background, which is cleaner than swapping in a still that
   doesn't match the clip's opening frame. */
.hero__video{width:100%;height:100%;object-fit:cover;display:block;position:relative;z-index:1;}
/* Multi-stop gradient — heavier at bottom so the eyebrow + headline read
   regardless of which slide is up. The 60→100% sweep ramps from
   transparent to a deep navy across the lower 40% of the hero, so even bright
   exterior shots (like the Calatrava sunset) don't wash out the headline. */
.hero__overlay{
  position:absolute;inset:0;
  z-index:2;   /* over the video/poster; the copy is hoisted out of the slide */
  /* Per-slide wash. The lower stops are lighter than they used to be
     because the constant bottom scrim (.hero::after) now carries most of
     that weight; the two multiply, so keeping both heavy turned the
     bottom of the frame to mud. */
  background:linear-gradient(180deg,
    rgba(13,27,42,.55) 0%,
    rgba(13,27,42,.18) 22%,
    rgba(13,27,42,0)   45%,
    rgba(13,27,42,.26) 65%,
    rgba(13,27,42,.42) 90%,
    rgba(13,27,42,.48) 100%);
}
/* Inner — just a positioned container that centers a max-width column,
   identical to the stage hero's outer wrapper. Layout itself is delegated
   to .hero__content below (which is pinned absolutely to the bottom-left).
   No flex on this element so child anchor positioning is unambiguous. */
.hero__inner{
  position:absolute;inset:0;
  /* Sibling of the slides, not a child — see the note in HeroCarousel.
     z-index:3 clears the bottom scrim (z-index:2) so the label and button
     sit on top of the gradient rather than under it. */
  z-index:3;
  left:50%;transform:translateX(-50%);
  width:100%;max-width:var(--container);
  padding:0 32px;
  color:#F5F5F3;
  pointer-events:none;   /* arrows + dots underneath stay clickable */
  /* One block per slide, all mounted; only the active one is visible.
     Matches the slides' own 1000ms fade so image and text hand over
     together instead of the text snapping. */
  opacity:0;
  transition:opacity 1000ms var(--ease-out);
}
.hero__inner.is-active{opacity:1;}
.hero__inner.is-active .hero__content{pointer-events:auto;}
/* Content stack — absolutely pinned to the bottom-left of .hero__inner.
   This matches the .shero--stage cadence: the stack hugs the bottom corner
   with a fixed clearance above the dot strip (~32 px). The slide is down to
   two elements now — area name, then button — so the stack reads as one
   tight cluster. */
.hero__content{
  position:absolute;
  left:32px;right:32px;bottom:60px;
  display:flex;flex-direction:column;align-items:flex-start;
  gap:14px;
  pointer-events:none;   /* re-enabled on the active slide only */
  max-width:760px;
}
/* Area name — this used to be a marketing sentence with a small uppercase
   eyebrow above it. Both were replaced by the area name alone, promoted to
   the sentence's old size and weight, so the slide states what it is showing
   and the button states where it goes.
   Set in sentence case, as the strings are authored — the uppercase transform
   it briefly carried over from its eyebrow days is gone.
   --font-display-book, not --font-display: the latter leads with
   'Futura AI Condensed', whose file holds 33 glyphs and no letters at all
   (digits and a colon — it is a numerals subset). Letters fall through it to
   Futura Medium anyway, so naming Futura Medium directly is both honest and
   immune to a string that happens to contain a digit picking up the condensed
   face mid-word. */
.hero__headline{
  font-family:var(--font-display-book);font-weight:500;
  font-size:clamp(30px, 3.6vw, 52px);
  line-height:1.08;
  letter-spacing:-0.015em;
  max-width:760px;margin:0;
  color:#F5F5F3;
  text-wrap:balance;
}
/* Tiny extra nudge above the CTA. The area name's bottom half-leading eats a
   few px of the flex gap, so an extra 8px restores the intended spacing. */
.hero__cta{display:flex;gap:12px;margin-top:8px;}
/* The hero CTA sits on live video, so a plain 1px outline on a transparent
   background vanishes the moment a bright frame comes up — the BIM render
   in the data-centre clip swallowed it completely.
   Giving it its own surface (blurred navy panel + a brighter border + a
   soft drop shadow) lifts it off whatever is playing behind. A flat white
   fill would read forward too, but it turns into a glaring slab on the
   dark night shots; the translucent panel holds up across all four slides.
   Scoped to .hero__cta so the same outline button on the sector pages,
   which sits on static art, keeps its lighter treatment.
   Hover keeps the established inversion to solid white. */
.hero__cta .btn-outline-white{
  background:rgba(13,27,42,.55);
  backdrop-filter:blur(10px);
  -webkit-backdrop-filter:blur(10px);
  border-color:rgba(255,255,255,.85);
  color:#FFFFFF;
  box-shadow:0 6px 24px rgba(13,27,42,.30);
}
.hero__cta .btn-outline-white:hover{
  background:#FFFFFF;
  border-color:#FFFFFF;
  color:#0D1B2A;
  box-shadow:0 8px 28px rgba(13,27,42,.38);
}
/* Mobile tuning — parallels the .shero--stage breakpoints so the home and
   sector stages collapse identically on phones. */
@media (max-width:900px){
  .hero__content{bottom:54px;gap:12px;}
  .hero__headline{font-size:30px;line-height:1.08;margin:0;}
  .hero .eyebrow{font-size:12px;letter-spacing:.16em;}
}
@media (max-width:600px){
  .hero{min-height:520px;}
  .hero__inner{padding-left:24px;padding-right:24px;}
  /* Clear the centred dot strip, which sits at 32px and stands 28px tall.
     The button is left-aligned and wide enough to reach past centre, so at
     48px the two collided. Same stacking the Proyectos hero already uses. */
  .hero__content{left:24px;right:24px;bottom:108px;gap:10px;max-width:none;}
  .hero__headline{font-size:24px;line-height:1.1;letter-spacing:-0.015em;margin:0;max-width:none;}
  .hero .eyebrow{font-size:11px;letter-spacing:.14em;}
}
.hero__arrow{position:absolute;top:50%;transform:translateY(-50%);z-index:3;background:transparent;color:rgba(255,255,255,.75);border:0;width:48px;height:48px;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:color 200ms var(--ease-out), transform 200ms var(--ease-out);padding:0;}
.hero__arrow:hover{color:#fff;}
.hero__arrow--l:hover{transform:translate(-3px,-50%);}
.hero__arrow--r:hover{transform:translate(3px,-50%);}
/* Pin the arrows just outside the container edge so they keep a constant gap
   from the headline text. Falls back to a 12px minimum when the viewport is
   narrower than the container plus the gap. */
.hero__arrow--l{left:max(12px, calc((100vw - var(--container)) / 2 - 96px));}
.hero__arrow--r{right:max(12px, calc((100vw - var(--container)) / 2 - 96px));}
@media (max-width:1200px){.hero__arrow{display:none;}}
/* Dot strip — matches the Data Centers stage hero. Small filled circles;
   active dot wears an SVG progress ring around it. */
.hero__dots{
  position:absolute;left:50%;bottom:32px;
  transform:translateX(-50%);
  display:flex;align-items:center;gap:26px;
  z-index:3;
}
/* Architect credit — bottom-right of the home hero, anchored at the
   same vertical offset as the dot strip so the line of bottom chrome
   reads as one band. Same font / colour vocabulary as the sector
   stage and Proyectos credits. */
.hero__credit{
  position:absolute;right:32px;bottom:36px;z-index:3;
  font-family:var(--font-sans);font-weight:400;
  font-size:10px;letter-spacing:.16em;text-transform:uppercase;
  color:rgba(255,255,255,0.78);
  pointer-events:none;
}
@media (max-width:900px){
  /* The credit is right-aligned and the dots are centred, which is fine on
     a wide screen but not at 375px, where "Arq. Miguel de Oriol e Ybarra"
     reaches back past the middle and lands on top of them. Moved into the
     gap between the dots and the copy above. */
  .hero__credit{right:24px;bottom:76px;font-size:9px;letter-spacing:.14em;}
}
.hero__dot{
  position:relative;
  width:28px;height:28px;
  background:transparent;border:0;padding:0;margin:0;
  cursor:pointer;
  display:flex;align-items:center;justify-content:center;
  -webkit-tap-highlight-color:transparent;
}
.hero__dot:focus-visible{outline:none;}
.hero__dot:focus-visible .hero__dot-core{background:#FFFFFF;}
.hero__dot-core{
  display:block;
  width:4px;height:4px;border-radius:50%;
  background:rgba(255,255,255,0.55);
  transition:width 220ms var(--ease-out), height 220ms var(--ease-out), background 220ms var(--ease-out);
}
.hero__dot:hover .hero__dot-core{background:#FFFFFF;}
.hero__dot.is-on .hero__dot-core{
  background:#FFFFFF;
  width:5px;height:5px;
}
.hero__dot-ring{
  position:absolute;inset:0;pointer-events:none;
}
/* Progress ring fill is driven by requestAnimationFrame in HeroCarousel —
   the ring's stroke-dashoffset is mutated each frame from the active video's
   currentTime/duration ratio. No CSS animation needed; the ring naturally
   syncs with whatever clip length the active slide carries. */

/* ---- Sections ---- */
.section{padding:var(--sp-10) 0;}
.section--light{background:var(--bg);color:var(--fg);}
.section--alt{background:var(--bg-alt);color:var(--fg);}
.section--dark{background:var(--bg-dark);color:var(--fg-on-dark);}
.section--accent{background:var(--accent);color:#fff;}
.section__head{margin-bottom:var(--sp-7);display:flex;flex-direction:column;gap:10px;}
.section__title{font-family:var(--font-display);font-weight:500;font-size:var(--fs-h2);line-height:1.15;letter-spacing:-0.01em;color:var(--fg);max-width:880px;margin:0;}
.section__title--light{color:#F5F5F3;}
.section__foot{margin-top:var(--sp-7);}
@media (max-width:900px){.section{padding:64px 0;}}

/* ---- Memo: photo full-bleed left (top-to-bottom of section),
        pullquote + stats stacked on the right ---- */
.section--memo{
  background:var(--bg);
  /* No vertical padding so the photo extends edge to edge. The right column
     supplies its own internal padding for the text content. */
  padding:0;
  overflow:hidden;
}
.memo{
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:0;
  align-items:stretch;
  min-height:720px;
}
.memo__photo{margin:0;padding:0;}
.memo__photo{position:relative;overflow:hidden;}
.memo__photo img{
  position:absolute;inset:0;
  width:100%;height:100%;object-fit:cover;display:block;
  transition:transform 1200ms var(--ease-out);
}
.memo__photo:hover img{transform:scale(1.03);}
/* Architect credit — sits over the bottom-left of the photo with a
   soft gradient mask so it stays legible on dark or bright frames.
   Mono + uppercase tracking reads as a discreet caption, not a
   competing label. */
.memo__credit{
  position:absolute;left:18px;bottom:14px;z-index:2;
  font-family:var(--font-mono);font-size:10px;font-weight:500;
  letter-spacing:.14em;text-transform:uppercase;
  color:rgba(245,245,243,.78);
  text-shadow:0 1px 6px rgba(0,0,0,.55);
  pointer-events:none;
}

/* Right column — internal padding aligns content with the container's right
   edge. On wide viewports padding-right uses calc to land on the container
   line; on narrow viewports it falls back to a sane minimum. */
.memo__col{
  display:flex;flex-direction:column;
  gap:var(--sp-7);
  justify-content:center;
  padding:var(--sp-9) max(24px, calc((100vw - var(--container)) / 2 + 32px))
          var(--sp-9) var(--sp-8);
}
.memo__l{padding-right:0;}
.memo__r{display:flex;flex-direction:column;gap:var(--sp-6);}
.stat-row{display:flex;flex-direction:column;gap:8px;border-bottom:1px solid var(--ai-hairline);padding-bottom:var(--sp-5);}
.stat-row:last-child{border-bottom:0;}
/* Certifications strip — static grid below the memo. Two rows of
   7 on desktop, wraps naturally on smaller screens. Logos sized
   large enough that the small print on Uptime Tier seals stays
   legible without needing to zoom. */
.credentials-strip{
  background:#F5F5F3;
  padding:var(--sp-7) 0 var(--sp-8);
}
.credentials-strip__eyebrow{
  display:block;text-align:center;
  margin-bottom:var(--sp-6);
}
.credentials-strip__list{
  display:grid;
  grid-template-columns:repeat(7, minmax(0, 1fr));
  gap:var(--sp-6) var(--sp-5);
  align-items:center;justify-items:center;
  max-width:1180px;margin:0 auto;
}
.credentials-strip__item{
  display:inline-flex;align-items:center;justify-content:center;
  height:96px;width:100%;
}
.credentials-strip__item img{
  display:block;
  height:100%;width:auto;
  max-width:100%;
  object-fit:contain;
  /* Full colour at rest — the Uptime reds and bsi/ASHRAE blues are
     the point. Keep the scale-up on hover so the badge still
     responds to interest. */
  transition:transform .25s var(--ease-out);
}
.credentials-strip__item:hover img{transform:scale(1.04);}

/* Estado sin vacantes abiertas. El mensaje solo no bastaba: quedaba una
   sección que terminaba en punto muerto. Debajo va una llamada breve
   para escribir igualmente. */
.talento-positions__empty{display:flex;flex-direction:column;gap:var(--sp-6);}
/* Ojo con el color aquí: Talento pinta casi toda la página sobre fondo
   oscuro, pero la sección de vacantes es la excepción y va sobre claro.
   Escribí este bloque en blanco dando por hecho el fondo del resto de la
   página, y quedaba en blanco sobre blanco: 1,09:1, ilegible. Va en la
   tinta de la sección, que da 15,9:1. */
.talento-positions__empty-cta{
  display:flex;flex-direction:column;align-items:flex-start;gap:10px;
  padding-top:var(--sp-5);
  border-top:1px solid rgba(13,27,42,.16);
  max-width:56ch;
}
.talento-positions__empty-t{
  font-family:var(--font-sans);font-weight:600;
  font-size:20px;color:#0D1B2A;margin:0;
}
.talento-positions__empty-p{
  font-size:16px;line-height:1.6;color:rgba(13,27,42,.82);margin:0 0 6px;
}

/* MailReveal — el estado "ya revelado" del botón de correo. Ocupa el
   sitio del botón sin dar un salto de maquetación: misma altura de
   línea y mismo peso tipográfico que los demás botones. */
.mailreveal{
  display:inline-flex;align-items:center;gap:10px;
  font-family:var(--font-sans);
  font-size:15px;line-height:1.2;
}
.mailreveal__addr{
  color:var(--accent);
  text-decoration:none;
  border-bottom:1px solid currentColor;
  padding-bottom:2px;
  word-break:break-all;
}
.mailreveal__addr:hover{opacity:.75;}
.mailreveal__copy{
  border:0;background:none;cursor:pointer;
  font-size:15px;line-height:1;padding:2px 4px;
  color:var(--fg-mid);
  transition:color .15s var(--ease-out);
}
.mailreveal__copy:hover{color:var(--accent);}
.mailreveal--dark .mailreveal__addr{color:#fff;}
.mailreveal--dark .mailreveal__copy{color:rgba(255,255,255,.7);}
.mailreveal--dark .mailreveal__copy:hover{color:#fff;}

/* Galería de área. Rejilla que se adapta al número de fotos: con dos
   salen a media página, con seis en tres columnas. Cada foto conserva
   su proporción y el pie va debajo, no encima, para no tapar la imagen
   —que es lo que el editor quiere enseñar. */
.sector-gallery__grid{
  display:grid;
  grid-template-columns:repeat(auto-fit, minmax(280px, 1fr));
  gap:var(--sp-5);
}
.sector-gallery__item{
  margin:0;
  display:flex;flex-direction:column;gap:10px;
}
.sector-gallery__item img{
  display:block;width:100%;height:auto;
  aspect-ratio:4 / 3;object-fit:cover;
  background:#EEE;
}
.sector-gallery__item figcaption{
  font-family:var(--font-sans);
  font-size:12px;letter-spacing:.06em;
  color:var(--fg-mid);
  line-height:1.45;
}
@media (max-width:640px){
  .sector-gallery__grid{grid-template-columns:1fr;gap:var(--sp-4);}
}

/* Sellos con dos destinos (PDF propio + verificación en la web del
   organismo). En vez de elegir por el usuario, el sello despliega los
   dos al pasar por encima. El panel vive dentro del propio item, sin
   hueco entre medias, para que el ratón pueda bajar hasta él sin que
   se cierre. */
.credentials-strip__item--dual{position:relative;}
.credentials-strip__choice{
  position:absolute;
  top:100%;left:50%;
  transform:translate(-50%, -4px);
  z-index:3;
  display:flex;flex-direction:column;
  min-width:max-content;
  padding:6px 0;
  background:#FFF;
  border:1px solid rgba(0,0,0,.08);
  border-radius:6px;
  box-shadow:0 8px 24px rgba(0,0,0,.10);
  opacity:0;
  pointer-events:none;
  transition:opacity .18s var(--ease-out), transform .18s var(--ease-out);
}
.credentials-strip__item--dual:hover .credentials-strip__choice,
.credentials-strip__item--dual:focus-within .credentials-strip__choice{
  opacity:1;
  pointer-events:auto;
  transform:translate(-50%, 0);
}
.credentials-strip__choice a{
  padding:6px 14px;
  font-size:12px;
  line-height:1.3;
  white-space:nowrap;
  color:var(--fg);
  text-decoration:none;
  transition:background .15s var(--ease-out), color .15s var(--ease-out);
}
.credentials-strip__choice a:hover,
.credentials-strip__choice a:focus-visible{
  background:#F5F5F3;
  color:var(--accent);
}

@media (max-width:1100px){
  .credentials-strip__list{grid-template-columns:repeat(5, minmax(0, 1fr));}
}
@media (max-width:760px){
  .credentials-strip__list{grid-template-columns:repeat(4, minmax(0, 1fr));}
  .credentials-strip__item{height:78px;}
}
@media (max-width:480px){
  .credentials-strip__list{grid-template-columns:repeat(3, minmax(0, 1fr));gap:24px 18px;}
  .credentials-strip__item{height:68px;}

/* Sin ratón el hover no existe, así que el panel se queda escondido y
   el sello no llevaría a ninguna parte. Ahí se muestran los dos
   enlaces siempre, debajo del sello y en el flujo normal.

   Va después de los breakpoints de la cinta a propósito: las alturas
   fijas de .credentials-strip__item tienen la misma especificidad que
   estas reglas, así que si fuese antes ganarían ellas y el sello
   quedaría recortado dentro de una caja de 68px. */
@media (hover: none){
  .credentials-strip__item--dual{
    flex-direction:column;
    height:auto;
    gap:6px;
  }
  .credentials-strip__item--dual img{height:96px;}
  .credentials-strip__choice{
    position:static;
    transform:none;
    opacity:1;
    pointer-events:auto;
    flex-direction:row;
    padding:0;
    background:none;
    border:0;
    box-shadow:none;
  }
  .credentials-strip__choice a{
    padding:2px 8px;
    font-size:11px;
    color:var(--accent);
  }
}
@media (hover: none) and (max-width:760px){
  .credentials-strip__item--dual img{height:78px;}
}
@media (hover: none) and (max-width:480px){
  .credentials-strip__item--dual img{height:68px;}
}
}

@media (max-width:900px){
  .memo{grid-template-columns:1fr;min-height:0;}
  .memo__photo{min-height:320px;}
  .memo__col{padding:var(--sp-7) 24px;gap:var(--sp-6);}
}

/* ---- Article card ---- */
.grid-3{display:grid;grid-template-columns:repeat(3,1fr);gap:28px;}
@media (max-width:900px){.grid-3{grid-template-columns:1fr;}}
.acard{background:#fff;border-top:3px solid var(--accent);display:flex;flex-direction:column;transition:box-shadow 280ms;cursor:pointer;color:inherit;}
.acard:hover{box-shadow:var(--shadow-card-hover);}
.acard__ph{aspect-ratio:16/9;background:#0D1B2A;overflow:hidden;}
.acard__ph img{width:100%;height:100%;object-fit:cover;}
.acard__body{padding:22px 24px 26px;display:flex;flex-direction:column;gap:10px;}
.acard__tag{font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--accent);font-weight:600;}
.acard__title{font-family:var(--font-display);font-size:20px;font-weight:500;line-height:1.25;color:#111;margin:0;}
.acard__excerpt{font-size:14px;line-height:1.6;color:#555;font-weight:300;margin:0;}
.acard__cta{font-size:13px;font-weight:500;color:var(--accent);margin-top:6px;}

/* ---- Page hero ---- */
.page-hero{height:60vh;min-height:420px;position:relative;background-size:cover;background-position:center;margin-top:0;}
.page-hero__ov{position:absolute;inset:0;background:linear-gradient(180deg,rgba(13,27,42,.55) 0%,rgba(13,27,42,.85) 100%);}
.page-hero__inner{position:absolute;inset:0;display:flex;flex-direction:column;justify-content:flex-end;padding-bottom:var(--sp-8);gap:16px;}

/* ---- Editorial / sticky label ---- */
.editorial{display:grid;grid-template-columns:220px 1fr;gap:var(--sp-8);}
.section-label{font-size:11px;letter-spacing:.16em;text-transform:uppercase;font-weight:500;color:var(--fg-mid);position:sticky;top:110px;}
.editorial__body p{margin:0 0 24px;}
@media (max-width:900px){.editorial{grid-template-columns:1fr;}.section-label{position:static;}}

/* ---- Pillars ---- */
/* Pillars — each column gets its own 3px brand-accent top border (same
   pattern as ArticleCard). Whitespace separates the columns instead of
   vertical dividers, which were cutting visually through the body copy
   on the right-hand columns. */
.pillars{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--sp-8);}
.pillar{
  padding-top:var(--sp-6);
  border-top:var(--bd-accent-top);  /* 3px solid var(--ai-blue) */
  display:flex;flex-direction:column;gap:12px;
}
.pillars--light .pillar{color:var(--fg);}
.pillar__num{font-family:var(--font-mono);font-size:12px;color:var(--accent);margin:0 0 8px;letter-spacing:.04em;}
.pillar__t{font-family:var(--font-display);font-size:24px;font-weight:500;margin:0;letter-spacing:-0.01em;line-height:1.2;}
.pillar p{font-size:15px;line-height:1.6;font-weight:300;color:rgba(245,245,243,.75);margin:0;max-width:32ch;}
.pillars--light .pillar p{color:var(--fg-mid);}
@media (max-width:900px){.pillars{grid-template-columns:1fr;gap:var(--sp-6);}}

/* ---- Quiénes somos · Historia (timeline) ---- */
.timeline{display:flex;flex-direction:column;}
.tl-item{display:grid;grid-template-columns:200px 1fr;gap:var(--sp-8);padding:var(--sp-6) 0;border-top:1px solid var(--ai-hairline);}
.tl-item:first-of-type{border-top:none;padding-top:0;}
.tl-item__year{font-family:var(--font-mono);font-size:13px;color:var(--accent);letter-spacing:.06em;padding-top:6px;}
.tl-item__t{font-family:var(--font-display);font-size:22px;font-weight:500;margin:0 0 10px;letter-spacing:-0.01em;line-height:1.25;color:var(--fg);}
/* Los hitos que llevan más de un párrafo —el de 1961, con la historia
   del fundador— los pegaban uno debajo de otro sin aire y se leían como
   un bloque corrido. El margen va sólo entre párrafos, así que un hito
   de uno solo no gana espacio por debajo. */
.tl-item__body p{margin:0;max-width:62ch;font-size:15px;line-height:1.7;font-weight:300;color:var(--fg-mid);}
.tl-item__body p + p{margin-top:0.9em;}
.tl-item__fig{margin:var(--sp-5) 0 0;max-width:560px;}
.tl-item__fig img{width:100%;height:auto;display:block;}
.tl-item__fig figcaption{font-family:var(--font-mono);font-size:11px;letter-spacing:.05em;text-transform:uppercase;color:var(--fg-mid);margin-top:10px;}
@media (max-width:900px){.tl-item{grid-template-columns:1fr;gap:var(--sp-4);}}

/* ---- Quiénes somos · El fundador ---- */

/* ---- Quiénes somos · Valores ---- */
.values-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:var(--sp-7);}
.value__t{font-family:var(--font-display);font-size:20px;font-weight:500;margin:0 0 10px;letter-spacing:-0.01em;color:var(--fg);}
.value p{font-size:14px;line-height:1.6;font-weight:300;color:var(--fg-mid);margin:0;}
/* Sin titular, la frase ES la tarjeta: sube de tamaño y de contraste, y
   se apoya en una línea de acento que le da el peso que antes daba el
   titular. */
.value--untitled p{
  font-size:16px;line-height:1.55;color:var(--fg);
  padding-left:16px;border-left:2px solid var(--accent);
}

/* ---- Services intro (dark section) ---- */
.svc-intro{font-size:16px;line-height:1.7;font-weight:300;color:rgba(245,245,243,.75);max-width:68ch;margin:0;}

/* ---- Codes ---- */
.codes{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-8);}
.code-list{list-style:none;margin:var(--sp-5) 0 0;padding:0;}
.code-list li{padding:16px 0 16px 18px;border-left:2px solid var(--accent);margin-bottom:10px;font-size:15px;line-height:1.5;color:var(--fg);}
@media (max-width:900px){.codes{grid-template-columns:1fr;}}

/* ---- Accreditations grid ---- */
.accred-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:0;border-top:1px solid var(--ai-hairline);border-left:1px solid var(--ai-hairline);}
.accred{padding:28px 24px;border-right:1px solid var(--ai-hairline);border-bottom:1px solid var(--ai-hairline);min-height:120px;display:flex;flex-direction:column;justify-content:center;gap:6px;}
.accred__label{font-family:var(--font-display);font-weight:500;font-size:17px;color:#111;letter-spacing:.02em;}
.accred__sub{font-size:12px;color:var(--fg-mid);line-height:1.4;}
@media (max-width:900px){.accred-grid{grid-template-columns:repeat(2,1fr);}}

/* ---- Services list ---- */
.svc-list{list-style:none;margin:0;padding:0;column-count:2;column-gap:var(--sp-8);}
.svc-list li{padding:18px 0;border-bottom:1px solid rgba(245,245,243,.15);display:flex;gap:18px;color:#F5F5F3;font-size:16px;line-height:1.4;break-inside:avoid;}
.svc-list__n{font-family:var(--font-mono);font-size:12px;color:var(--accent);min-width:28px;}
@media (max-width:900px){.svc-list{column-count:1;}}

/* =========================================================
   ProyectosHero — 100vh image carousel at the top of /proyectos
   Same visual language as the home carousel (image bg, dark gradient
   overlay, dot strip with ring fill, bottom-left text). Tightened text
   layer: just the "Projects" title — no eyebrow, no sub, no CTA. Adds a
   scroll-down hint at the bottom-centre pointing at the sector grid.
   ========================================================= */
.proj-hero{position:relative;height:100vh;min-height:640px;overflow:hidden;background:#0a1623;}
/* Short variant — used on PagePersonas where the hero is more of a banner
   than a full cinematic stage. ~62% of viewport: enough presence to set
   the tone, but the team grid below is partially visible at first paint
   so the user knows there's more content immediately. */
.proj-hero--short{height:62vh;min-height:480px;}
.proj-hero__slide{
  position:absolute;inset:0;opacity:0;pointer-events:none;
  transition:opacity 1000ms var(--ease-out);
}
.proj-hero__slide.is-active{opacity:1;}
.proj-hero__img{
  width:100%;height:100%;object-fit:cover;display:block;
}
/* Ken-Burns drift — slow zoom on the active slide. Implemented as a CSS
   animation (not a transition) so it RE-FIRES every time the slide enters
   the .is-active state, even after the carousel cycles back to it. */
@keyframes proj-hero-zoom{
  from{transform:scale(1.02);}
  to  {transform:scale(1.10);}
}
.proj-hero__slide.is-active .proj-hero__img{
  animation:proj-hero-zoom 9s linear forwards;
}
/* Overlay matches the home hero curve but the middle stops keep more navy
   even at peak. Home runs dark night-time videos; Proyectos cycles still
   photos that include a bright sunset (Calatrava) — leaving the centre
   fully transparent let that brightness pierce through. A 22% navy floor
   at the brightest point + a light extra darkening either side calms it
   without making the imagery feel flat. */
.proj-hero__overlay{
  position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(180deg,
    rgba(13,27,42,.65) 0%,
    rgba(13,27,42,.35) 22%,
    rgba(13,27,42,.22) 45%,
    rgba(13,27,42,.48) 65%,
    rgba(13,27,42,.85) 90%,
    rgba(13,27,42,.92) 100%);
}
.proj-hero__inner{
  position:absolute;inset:0;
  max-width:var(--container);margin:0 auto;
  padding:0 32px;
  color:#F5F5F3;
  pointer-events:none;
}
.proj-hero__title{
  /* Title sits at the bottom-LEFT corner; dots + scroll arrow sit at the
     bottom-CENTRE. They share the same vertical band (lowest ~80px of the
     hero) but don't overlap horizontally — "Projects" is short enough that
     the text never reaches the centred dot strip. */
  position:absolute;left:32px;right:auto;bottom:40px;
  margin:0;
  font-family:var(--font-display);font-weight:500;
  font-size:clamp(40px, 5vw, 72px);
  line-height:1.04;letter-spacing:-0.02em;
  color:#FFFFFF;
  text-wrap:balance;
}

/* Dot strip — bottom-centre, identical layout vocabulary to the home
   carousel + stage hero. Active dot wears an SVG progress ring whose
   stroke-dashoffset is filled via a CSS keyframe over 6s (matching the
   slide autoplay timer). The ring SVG only renders for the active dot,
   so on slide change the SVG unmounts/remounts and the keyframe restarts
   cleanly from 0. */
.proj-hero__dots{
  position:absolute;left:50%;bottom:62px;z-index:3;
  transform:translateX(-50%);
  display:flex;align-items:center;gap:26px;
}
.proj-hero__dot{
  position:relative;
  width:28px;height:28px;
  background:transparent;border:0;padding:0;margin:0;
  cursor:pointer;
  display:flex;align-items:center;justify-content:center;
  -webkit-tap-highlight-color:transparent;
}
.proj-hero__dot:focus-visible{outline:none;}
.proj-hero__dot:focus-visible .proj-hero__dot-core{background:#FFFFFF;}
.proj-hero__dot-core{
  display:block;
  width:4px;height:4px;border-radius:50%;
  background:rgba(255,255,255,0.55);
  transition:width 220ms var(--ease-out), height 220ms var(--ease-out), background 220ms var(--ease-out);
}
.proj-hero__dot:hover .proj-hero__dot-core{background:#FFFFFF;}
.proj-hero__dot.is-on .proj-hero__dot-core{
  background:#FFFFFF;
  width:5px;height:5px;
}

/* Scroll-down hint — small label + arrow at the bottom-centre. Subtle
   vertical bounce on the arrow draws the eye downward without being noisy.
   Clickable: smooth-scrolls to the sector grid below. */
.proj-hero__scroll{
  position:absolute;left:50%;bottom:22px;z-index:3;
  transform:translateX(-50%);
  background:transparent;border:0;padding:6px 12px;
  display:flex;flex-direction:column;align-items:center;gap:4px;
  cursor:pointer;
  color:rgba(255,255,255,0.78);
  transition:color 200ms var(--ease-out);
}
.proj-hero__scroll:hover{color:#FFFFFF;}
.proj-hero__scroll-label{
  font-family:var(--font-sans);font-weight:500;
  font-size:10px;letter-spacing:.16em;text-transform:uppercase;
}
.proj-hero__scroll-arrow{
  font-size:18px;line-height:1;
  animation:proj-hero-bounce 1.8s ease-in-out infinite;
}
/* Architect credit — bottom-right of the Proyectos hero, anchored at
   the same vertical offset as the scroll hint. Same vocabulary as
   .shero__stage-credit but matched to this hero's padding scale. */
.proj-hero__credit{
  position:absolute;right:32px;bottom:24px;z-index:3;
  font-family:var(--font-sans);font-weight:400;
  font-size:10px;letter-spacing:.16em;text-transform:uppercase;
  color:rgba(255,255,255,0.78);
  pointer-events:none;
}
@keyframes proj-hero-bounce{
  0%, 100% { transform:translateY(0); opacity:.78; }
  50%      { transform:translateY(4px); opacity:1; }
}

@media (max-width:900px){
  .proj-hero__title{font-size:38px;bottom:36px;left:24px;right:auto;}
  .proj-hero__dots{bottom:60px;gap:18px;}
  .proj-hero__scroll{bottom:22px;}
}
@media (max-width:600px){
  .proj-hero{min-height:520px;}
  /* On phones the title would collide with the centred dot strip, so we
     stack title above dots like the original — but very close to the
     bottom edge, keeping the "low" placement. */
  /* Title, dots and scroll hint are three absolutely-positioned things
     stacking off the same bottom edge, and on a phone their bands ran into
     each other — the dot strip sat straight through the "Ver sectores"
     label, overlapping it by 21px. Each now gets its own band with ~20px
     between: scroll hint 24-75, dots 95-123, title 145-174. */
  .proj-hero__title{font-size:28px;bottom:145px;left:24px;right:24px;}
  .proj-hero__dots{bottom:95px;gap:16px;}
}

/* ---- Sector stage (Proyectos page) — F+P-style editorial grid.
   Deep-navy band, 3×2 large tiles with hover-to-play preview videos. Each
   tile mounts a paused <video> showing its poster image; the React handlers
   in SectorTile drive play/pause + currentTime reset on enter/leave/focus.
   The label sits at the bottom-left and stays fully visible at rest. */
.sector-stage{
  background:#0a1623;
  color:var(--fg-on-dark);
  /* Padding-top clears the fixed nav (no parallax hero above any more) and
     gives the title breathing room. Bottom padding kept tight (sp-5 = 24px)
     so the transition into the archive section below reads as one continuous
     navy canvas, not two separate panels. */
  padding:calc(var(--nav-h) + var(--sp-7)) 0 var(--sp-5);
}
.sector-stage__title{
  font-family:var(--font-display);font-weight:600;
  font-size:clamp(36px, 4vw, 54px);
  line-height:1.08;letter-spacing:-0.015em;
  color:#FFFFFF;
  margin:0 0 var(--sp-7);
  max-width:760px;
}
@media (max-width:900px){
  .sector-stage{padding-top:calc(var(--nav-h) + var(--sp-6));}
  .sector-stage__title{font-size:32px;margin-bottom:var(--sp-6);}
}
/* Grid uses a fixed row height (grid-auto-rows) instead of per-tile aspect-
   ratio. This guarantees all tiles in the same row share the EXACT same
   height regardless of the gap between columns — aspect-ratio math can't
   compensate for the gap, but grid-auto-rows just snaps every tile to the
   row. Wide tiles span 2 cols; their width grows but height stays the same.
   The clamp() picks a row height that scales reasonably from ~220px on small
   screens to ~360px on wide ones. */
.sector-stage__grid{
  display:grid;grid-template-columns:repeat(3,1fr);
  grid-auto-rows:clamp(220px, 24vw, 360px);
  gap:16px;
}
.sector-stage__tile{
  position:relative;display:block;overflow:hidden;
  background:#0a1623;cursor:pointer;
  color:inherit;text-decoration:none;
  outline:none;
  border-radius:14px;             /* F+P-style rounded corners */
  height:100%;                    /* fill the row height set by the grid */
}
.sector-stage__tile--wide{
  grid-column:span 2;
}
@media (max-width:900px){
  .sector-stage__grid{
    grid-template-columns:repeat(2,1fr);
    grid-auto-rows:clamp(200px, 30vw, 300px);
    gap:12px;
  }
  /* Below 900px (2-col grid), wide tiles span both columns. */
  .sector-stage__tile--wide{grid-column:span 2;}
}
@media (max-width:600px){
  .sector-stage__grid{
    grid-template-columns:1fr;
    grid-auto-rows:200px;
  }
  /* Below 600px (1-col grid), wide modifier collapses to one column. */
  .sector-stage__tile--wide{grid-column:1;}
}
/* Poster image — always-visible base layer. Renders immediately while the
   video element above is still fetching metadata. */
.sector-stage__poster{
  position:absolute;inset:0;
  width:100%;height:100%;
  object-fit:cover;
  display:block;
  z-index:0;
  transition:transform 600ms var(--ease-out);
}
/* Video sits on top of the poster — invisible at rest (so we don't get the
   browser's black <video> fallback flashing through) and faded in only while
   playing. The CSS class `.is-playing` is added by the React handler when
   play() resolves. */
.sector-stage__video{
  position:absolute;inset:0;
  width:100%;height:100%;
  object-fit:cover;
  display:block;
  z-index:1;
  opacity:0;
  transition:opacity 240ms var(--ease-out), transform 600ms var(--ease-out);
}
.sector-stage__tile.is-playing .sector-stage__video{opacity:1;}
.sector-stage__tile:hover .sector-stage__poster,
.sector-stage__tile:hover .sector-stage__video{
  transform:scale(1.03);
}
/* Subtle bottom-weighted gradient so the label stays legible against any
   frame of the preview. Lifts at rest, lightens slightly on hover so the
   underlying footage breathes. */
.sector-stage__overlay{
  position:absolute;inset:0;z-index:1;pointer-events:none;
  background:linear-gradient(180deg, rgba(13,27,42,0.05) 0%, rgba(13,27,42,0.20) 55%, rgba(13,27,42,0.75) 100%);
  transition:background 320ms var(--ease-out);
}
.sector-stage__tile:hover .sector-stage__overlay{
  background:linear-gradient(180deg, rgba(13,27,42,0.0) 0%, rgba(13,27,42,0.10) 55%, rgba(13,27,42,0.60) 100%);
}
.sector-stage__label{
  position:absolute;left:24px;right:24px;bottom:22px;z-index:2;
  font-family:var(--font-display);font-weight:600;
  font-size:clamp(20px, 1.7vw, 28px);
  line-height:1.2;letter-spacing:-0.005em;
  color:#FFFFFF;
}
.sector-stage__tile:focus-visible{
  box-shadow:inset 0 0 0 2px var(--ai-blue-300);
}
@media (max-width:900px){
  .sector-stage__label{font-size:20px;left:18px;right:18px;bottom:18px;}
}
@media (max-width:600px){
  .sector-stage__tile{aspect-ratio:16/9;}
  .sector-stage__label{font-size:18px;}
}

/* ---- Sector landing page (PageSector) ---- */
.sector-proof{display:grid;grid-template-columns:repeat(3,1fr);gap:0;border-top:1px solid var(--ai-hairline);border-left:1px solid var(--ai-hairline);}
.sector-proof__cell{padding:24px 22px;border-right:1px solid var(--ai-hairline);border-bottom:1px solid var(--ai-hairline);display:flex;flex-direction:column;gap:6px;}
.sector-proof__k{font-size:10px;letter-spacing:.16em;text-transform:uppercase;font-weight:600;color:var(--fg-mid);}
.sector-proof__v{font-family:var(--font-display);font-weight:500;font-size:17px;color:#111;letter-spacing:.01em;}
@media (max-width:900px){.sector-proof{grid-template-columns:1fr;}}
.back-link{display:inline-flex;align-items:center;gap:8px;font-family:var(--font-sans);font-weight:500;font-size:13px;letter-spacing:.06em;text-transform:uppercase;color:var(--accent);cursor:pointer;border-bottom:1px solid currentColor;padding-bottom:2px;text-decoration:none;}
.back-link:hover{color:#111;}

/* =========================================================
   PageSector — sector landing page
   Adopted from the Aguilera Ingenieros Design System bundle
   (Claude Design handoff). Five sections: shero split + eng
   discipline grid + caps spec list + reference projects + cert
   grid + accent CTA band. The visual signature is the framed
   hero panel — engineering-grid background, corner brackets,
   centred building line-drawing (or photo for sectors without
   an isometric drawing), and a reserved video CTA slot.
   ========================================================= */

/* ── Hero ───────────────────────────────────────────────── */
.shero{
  position:relative;background:#0a1623;color:var(--fg-on-dark);
  padding-top:var(--nav-h);overflow:hidden;
}
.shero::before{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:radial-gradient(60% 55% at 78% 45%, rgba(0,80,144,0.14) 0%, transparent 70%);
}
.shero__inner{
  position:relative;z-index:1;
  display:grid;grid-template-columns:1fr 1fr;gap:64px;align-items:center;
  padding-top:72px;padding-bottom:88px;min-height:calc(86vh - var(--nav-h));
}
.shero__left{display:flex;flex-direction:column;gap:22px;max-width:560px;}
.shero__h1{
  font-family:var(--font-display);font-weight:500;
  font-size:clamp(38px,4.2vw,58px);line-height:1.06;letter-spacing:-0.015em;
  color:#F5F5F3;margin:0;text-wrap:balance;
}
.shero__sub{font-size:17px;font-weight:300;line-height:1.6;color:rgba(245,245,243,0.74);margin:0;max-width:520px;}
.shero__stats{
  display:grid;grid-template-columns:repeat(4,1fr);gap:0;margin-top:10px;
  border-top:1px solid rgba(245,245,243,0.14);
}
.shero__stat{padding:18px 14px 0 0;display:flex;flex-direction:column;gap:6px;}
.shero__stat-v{font-family:var(--font-display);font-weight:500;font-size:22px;color:var(--ai-blue-300);letter-spacing:-0.01em;line-height:1;}
.shero__stat-k{font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:rgba(245,245,243,0.5);font-weight:500;line-height:1.3;}

/* Framed building / video panel — same skeleton for both flavours. */
.shero__media{
  position:relative;aspect-ratio:4/3;width:100%;
  background:linear-gradient(165deg, rgba(19,38,58,0.6), rgba(8,16,26,0.9));
  border:1px solid rgba(245,245,243,0.12);
  display:flex;align-items:center;justify-content:center;
  overflow:hidden;
}
.shero__media--photo{
  background-size:cover;background-position:center;
}
/* The photo flavour gets a dimming overlay so the corner brackets and the
   bottom caption strip stay legible — same darkening curve as a project card. */
.shero__media--photo::before{
  content:"";position:absolute;inset:0;
  background:linear-gradient(180deg, rgba(13,27,42,0.35) 0%, rgba(13,27,42,0.85) 100%);
}

/* Video flavour — full-bleed looping clip inside the panel frame. The video
   sits under the corner brackets and caption strip; the same gradient overlay
   as the photo flavour darkens the bottom so the strip stays legible without
   washing out the footage. */
.shero__media--video{background:#0a1623;}
.shero__media--video::before{
  content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
  background:linear-gradient(180deg, rgba(13,27,42,0.18) 0%, rgba(13,27,42,0.78) 100%);
}
.shero__video{
  position:absolute;inset:0;
  width:100%;height:100%;
  object-fit:cover;
  display:block;
}

/* =========================================================
   Deck-style hero (heroVariant: "deck") — used by Hospitales.
   3 square clips visible at once. Centre clip is in forefront
   (full size + full opacity, playing). Flanking clips sit at
   85% scale + 55% opacity, paused. On advance the centre's
   clip src changes; visually it reads as a deck where the
   row of clips slid one step.
   ========================================================= */
.shero--deck{
  position:relative;
  background:#0a1623;
  color:var(--fg-on-dark);
  /* Tight padding so the entire deck fits in the initial viewport: just
     the nav clearance + a small breathing band above, smaller below. */
  padding:calc(var(--nav-h) + var(--sp-3)) 0 var(--sp-4);
  overflow:hidden;
}
.shero-deck__inner{
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:var(--sp-4);
  width:100%;
}
/* Sector title sits in the slim band above the deck. Minimalist
   treatment: light weight, open tracking, extra breathing room
   between the title and the deck below. */
.shero-deck__title{
  margin:0 0 var(--sp-4);
  font-family:var(--font-display, inherit);
  font-weight:300;
  font-size:clamp(1.35rem, 2.4vw, 2rem);
  line-height:1.2;
  letter-spacing:0.005em;
  text-align:center;
  color:var(--fg-on-dark);
}
/* Stage holds the cards absolutely positioned. Cards are 4:3 rectangles
   (source re-cropped to 1200x900, logos pushed out by the tighter height
   crop), so stage height is the card width * 3/4. Centre card is now
   significantly larger; side cards sit BEHIND it and only the outer
   half peeks out (step = w/2 — half of each side card is hidden by
   the centre, scaled down to feel recessed). */
.shero-deck__stage{
  position:relative;
  width:100%;
  height:clamp(240px, 37.5vw, 585px);
}
.shero-deck__card{
  position:absolute;left:50%;top:50%;
  /* Active card width — bumped up significantly; sides are this same
     intrinsic width then visually scaled down + clipped behind centre. */
  --w:clamp(320px, 50vw, 780px);
  /* step = w/2 → side card centre lands at the centre card's left/right
     edge, so half of each side card is tucked behind centre. */
  --step:calc(var(--w) * 0.5);
  width:var(--w);
  aspect-ratio:4/3;
  border-radius:18px;
  overflow:hidden;
  padding:0;margin:0;border:0;
  background:#0a1623;
  cursor:pointer;
  /* The actual move: centre via -50%, then shift by offset * step. Sides
     also scale down (0.65 — smaller than before so the contrast with the
     larger centre reads cleanly). Single transition runs the slide AND
     scale together. */
  transform:translate(calc(-50% + var(--offset, 0) * var(--step)), -50%) scale(0.65);
  opacity:0.5;
  filter:saturate(0.8);
  transition:
    transform 700ms cubic-bezier(0.65, 0, 0.35, 1),
    opacity 700ms var(--ease-out),
    filter 700ms var(--ease-out);
}
.shero-deck__card video{
  width:100%;height:100%;object-fit:cover;display:block;
}
.shero-deck__card.is-active{
  transform:translate(-50%, -50%) scale(1);
  opacity:1;
  filter:none;
  z-index:3;
  cursor:default;
  box-shadow:0 24px 60px rgba(0,0,0,.45);
}
.shero-deck__card.is-prev,
.shero-deck__card.is-next{
  z-index:2;
}
.shero-deck__card.is-far{
  opacity:0;
  pointer-events:none;
  z-index:1;
}
/* is-warp is applied on the single frame where a card's --offset
   jumped > 1 slot (the long-way-around case in an N=3 loop). Killing
   the transition makes it snap to the new side instead of sliding
   across the active card. The class is removed on the next render so
   normal motion resumes. */
.shero-deck__card.is-warp{
  transition:none;
}
.shero-deck__card.is-prev:hover,
.shero-deck__card.is-next:hover{
  opacity:0.78;
}
.shero-deck__card:focus-visible{
  outline:2px solid var(--ai-blue-300);
  outline-offset:4px;
}
.shero-deck__dots{
  display:flex;align-items:center;gap:22px;
  margin-top:var(--sp-3);
}
.shero-deck__dot{
  position:relative;
  width:28px;height:28px;
  background:transparent;border:0;padding:0;margin:0;
  cursor:pointer;
  display:flex;align-items:center;justify-content:center;
}
.shero-deck__dot:focus-visible{outline:none;}
.shero-deck__dot-core{
  display:block;
  width:4px;height:4px;border-radius:50%;
  background:rgba(255,255,255,0.55);
  transition:width 220ms var(--ease-out), height 220ms var(--ease-out), background 220ms var(--ease-out);
}
.shero-deck__dot:hover .shero-deck__dot-core,
.shero-deck__dot:focus-visible .shero-deck__dot-core{background:#FFFFFF;}
.shero-deck__dot.is-on .shero-deck__dot-core{
  background:#FFFFFF;
  width:5px;height:5px;
}
/* Progress ring on the active dot — mutated by rAF from the active
   video's currentTime/duration. */
.shero-deck__dot-ring{
  position:absolute;inset:0;pointer-events:none;
}
@media (max-width:900px){
  .shero--deck{min-height:auto;padding-top:calc(var(--nav-h) + var(--sp-5));}
  /* Tablet: stage = card width × 3/4. Step still w/2 from base rule. */
  .shero-deck__stage{height:clamp(225px, 45vw, 420px);}
  .shero-deck__card{--w:clamp(300px, 60vw, 560px);}
}
@media (max-width:600px){
  /* Only the active centre card stays visible on phones. */
  .shero-deck__card{--w:min(82vw, 420px);}
  .shero-deck__card.is-prev,
  .shero-deck__card.is-next{opacity:0;pointer-events:none;}
}

/* ── Stage hero — full-bleed 100vh video stage (Foster + Partners cadence)
   Used by sectors with `heroVariant: "stage"`. The framed-panel hero stays
   the default for everyone else; this variant replaces the entire .shero
   section with a cinematic stage. */
.shero--stage{
  position:relative;
  background:#000;
  color:var(--fg-on-dark);
  height:100vh;min-height:640px;
  padding-top:0;
  overflow:hidden;
}
/* Background video. object-fit:cover means tall portrait clips will be
   side-cropped, wide clips top/bottom-cropped — matches the editorial
   treatment on F+P and similar studio sites. */
.shero__bg-video{
  position:absolute;inset:0;
  width:100%;height:100%;
  object-fit:cover;
  display:block;
  z-index:0;
}
/* Two-stop gradient: a darker top band so the fixed nav reads cleanly, a
   light middle so the footage breathes, and a heavier bottom so the copy
   stays legible regardless of which clip is on-screen. */
.shero__bg-overlay{
  position:absolute;inset:0;z-index:1;pointer-events:none;
  background:linear-gradient(180deg,
    rgba(13,27,42,.55) 0%,
    rgba(13,27,42,.18) 22%,
    rgba(13,27,42,0)   45%,
    rgba(13,27,42,.40) 65%,
    rgba(13,27,42,.85) 90%,
    rgba(13,27,42,.92) 100%);
}
.shero__stage-inner{
  position:absolute;inset:0;z-index:2;
  display:flex;flex-direction:column;justify-content:flex-end;
  padding-top:var(--nav-h);
  padding-bottom:120px;       /* leaves clearance for the dot strip */
}
.shero__stage-content{
  max-width:720px;
  display:flex;flex-direction:column;gap:14px;
}
/* Eyebrow over the stage hero — slightly larger than the standard one (which
   targets editorial chrome) so it reads as a category label on top of the
   cinematic frame, but still smaller than the headline below it. */
.shero--stage .eyebrow{
  font-size:13px;letter-spacing:.18em;
}
/* Headline — kept tight on purpose. Stage heros only get an eyebrow + h1;
   long sub-paragraphs were pulling focus off the footage. clamp() floor
   has been dropped from 40 → 30 so phones get a calm size that doesn't
   wrap awkwardly behind tall portrait clips. */
.shero__stage-h1{
  font-family:var(--font-display);font-weight:500;
  font-size:clamp(30px,3.6vw,52px);
  line-height:1.06;letter-spacing:-0.02em;
  color:#F5F5F3;margin:0;
  text-wrap:balance;
}

/* Dot strip — bottom-centre, one button per clip in the reel. */
.shero__stage-dots{
  /* Lifted from 44px to make room for the heroHint label + arrow that
     sits beneath. Sectors without a heroHint look the same — the small
     vertical shift reads as breathing room. */
  position:absolute;left:50%;bottom:78px;z-index:3;
  transform:translateX(-50%);
  display:flex;align-items:center;gap:26px;
}
/* Stage hero hint — tiny "Discover our …" label + downward arrow
   directly under the dot strip. Visually quieter than the Proyectos
   page scroll-hint: smaller type, lower opacity. Clicking scrolls
   past the 100vh hero into the sector's content. */
.shero__stage-hint{
  position:absolute;left:50%;bottom:18px;z-index:3;
  transform:translateX(-50%);
  background:transparent;border:0;padding:4px 10px;
  display:flex;flex-direction:column;align-items:center;gap:3px;
  cursor:pointer;
  color:rgba(255,255,255,0.62);
  transition:color 200ms var(--ease-out);
}
.shero__stage-hint:hover{color:#FFFFFF;}
.shero__stage-hint:focus-visible{outline:none;color:#FFFFFF;}
.shero__stage-hint-label{
  font-family:var(--font-sans);font-weight:400;
  font-size:9px;letter-spacing:.18em;text-transform:uppercase;
}
.shero__stage-hint-arrow{
  font-size:14px;line-height:1;
  animation:proj-hero-bounce 1.8s ease-in-out infinite;
}
/* Architect credit — bottom-right corner of the stage hero, anchored
   at the SAME vertical offset as .shero__stage-hint so the two read
   as a matched pair across the bottom of the frame. Reuses the hint
   label's font, weight, tracking and colour exactly. */
.shero__stage-credit{
  position:absolute;right:24px;bottom:18px;z-index:3;
  font-family:var(--font-sans);font-weight:400;
  font-size:9px;letter-spacing:.18em;text-transform:uppercase;
  color:rgba(255,255,255,0.62);
  pointer-events:none;
  /* El crédito se veía cortado por la derecha con los nombres largos
     —"Arq. Francisco Sáenz de Oíza" con este interletrado ocupa
     bastante—. Con un ancho máximo y alineación a la derecha ya no
     puede salirse: si no cabe en una línea, parte en dos. */
  max-width:calc(100% - 48px);
  text-align:right;
  text-wrap:balance;
}
.shero__stage-dot{
  position:relative;
  width:28px;height:28px;
  background:transparent;border:0;padding:0;margin:0;
  cursor:pointer;
  display:flex;align-items:center;justify-content:center;
  -webkit-tap-highlight-color:transparent;
}
.shero__stage-dot:focus-visible{outline:none;}
.shero__stage-dot:focus-visible .shero__stage-dot-core{background:#FFFFFF;}
.shero__stage-dot-core{
  display:block;
  width:4px;height:4px;border-radius:50%;
  background:rgba(255,255,255,0.55);
  transition:width 220ms var(--ease-out), height 220ms var(--ease-out), background 220ms var(--ease-out);
}
.shero__stage-dot:hover .shero__stage-dot-core{background:#FFFFFF;}
.shero__stage-dot.is-on .shero__stage-dot-core{
  background:#FFFFFF;
  width:5px;height:5px;
}
.shero__stage-dot-ring{
  position:absolute;inset:0;pointer-events:none;
}

/* Stage-hero mobile tuning. Two breakpoints:
   - ≤900px: tablet / narrow window. Headline drops a notch, dots tighten.
   - ≤600px: phones. Headline shrinks further, eyebrow comes in at base size,
     padding tightens so the copy isn't crushed against the dot strip on
     short viewports. */
@media (max-width:900px){
  .shero--stage{min-height:560px;}
  .shero__stage-inner{padding-bottom:128px;}
  .shero__stage-h1{font-size:30px;line-height:1.08;}
  .shero--stage .eyebrow{font-size:12px;letter-spacing:.16em;}
  .shero__stage-dots{gap:18px;bottom:60px;}
  .shero__stage-hint{bottom:14px;}
  .shero__stage-credit{bottom:14px;right:18px;}
}
@media (max-width:600px){
  .shero--stage{min-height:520px;height:100svh;}      /* svh = stable on iOS */
  /* Was padding-left/right:0, which put the eyebrow and the headline flush
     against the screen edge — the first character sat on the bezel. Back to
     the 24px gutter the rest of the page uses. Bottom padding grows because
     the dots and the scroll hint now stack rather than overlap. */
  .shero__stage-inner{padding-bottom:132px;padding-left:24px;padding-right:24px;}
  .shero__stage-content{max-width:none;gap:10px;}
  .shero__stage-h1{font-size:24px;line-height:1.1;letter-spacing:-0.015em;}
  .shero--stage .eyebrow{font-size:11px;letter-spacing:.14em;}
  .shero__stage-dots{gap:16px;bottom:76px;}
  .shero__stage-dot{width:24px;height:24px;}
  .shero__stage-dot-ring{width:24px !important;height:24px !important;}
  /* nowrap: at 8px with .16em tracking "Descubre nuestros data centers"
     was breaking to two lines and growing up into the dot strip. */
  .shero__stage-hint{bottom:16px;white-space:nowrap;}
  .shero__stage-hint-label{font-size:8px;letter-spacing:.16em;}
  /* On phones the credit drops a line below the hint to avoid the
     narrow label colliding with the centre arrow; same font scaling. */
  .shero__stage-credit{bottom:12px;right:14px;font-size:8px;letter-spacing:.16em;}
}

/* Reel tick strip — one notch per clip in a cycling playlist. Sits just above
   the caption strip so it visually pairs with the bottom chrome. Active notch
   is solid white, others are dimmed; the colour transition makes the advance
   feel mechanical rather than abrupt. */
.shero__reel-ticks{
  position:absolute;z-index:3;
  left:16px;right:16px;bottom:54px;
  display:flex;justify-content:flex-end;align-items:center;gap:6px;
  pointer-events:none;
}
.shero__reel-tick{
  display:block;
  width:18px;height:2px;
  background:rgba(245,245,243,0.32);
  transition:background 280ms var(--ease-out), width 280ms var(--ease-out);
}
.shero__reel-tick.is-on{
  background:#FFFFFF;
  width:28px;
}
.shero__grid-bg{
  position:absolute;inset:0;
  background-image:linear-gradient(rgba(245,245,243,0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(245,245,243,0.05) 1px, transparent 1px);
  background-size:32px 32px;
  mask-image:radial-gradient(70% 70% at 50% 45%, #000 40%, transparent 100%);
}
.shero__building{
  position:relative;z-index:1;width:82%;height:auto;object-fit:contain;
  filter:drop-shadow(0 0 14px rgba(90,149,208,0.25));
  animation:vt-fade-in 900ms var(--ease-out);
}
.shero__media-foot{
  position:absolute;z-index:2;left:0;right:0;bottom:0;
  display:flex;justify-content:space-between;align-items:center;gap:12px;
  padding:14px 16px;
  background:linear-gradient(180deg, transparent, rgba(8,16,26,0.85));
}
.shero__media-cap{font-family:var(--font-mono);font-size:9.5px;letter-spacing:.14em;color:rgba(245,245,243,0.6);}
.shero__media-video{display:flex;align-items:center;gap:8px;font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:rgba(245,245,243,0.85);font-weight:500;cursor:pointer;}
.shero__play{width:24px;height:24px;border-radius:999px;border:1px solid rgba(245,245,243,0.4);display:flex;align-items:center;justify-content:center;color:#F5F5F3;padding-left:2px;transition:all 200ms var(--ease-out);}
.shero__media-video:hover .shero__play{background:var(--ai-blue);border-color:var(--ai-blue);color:#fff;}
.shero__corner{position:absolute;width:10px;height:10px;z-index:2;border-color:rgba(245,245,243,0.4);}
.shero__corner--tl{top:10px;left:10px;border-top:1px solid;border-left:1px solid;}
.shero__corner--tr{top:10px;right:10px;border-top:1px solid;border-right:1px solid;}
.shero__corner--bl{bottom:10px;left:10px;border-bottom:1px solid;border-left:1px solid;}
.shero__corner--br{bottom:10px;right:10px;border-bottom:1px solid;border-right:1px solid;}

@media (max-width:900px){
  .shero__inner{grid-template-columns:1fr;gap:40px;padding-bottom:56px;}
  .shero__right{order:-1;}
  .shero__stats{grid-template-columns:1fr 1fr;gap:8px 0;}
  .shero__h1{font-size:36px;}
}

/* ── 3. CTA accent band — column layout + extra breathing ─ */
/* padding-top/bottom rather than the `padding:8px 0` shorthand this used
   to carry. The shorthand also set the horizontal padding to zero, and
   .cta-band sits ON the .container element — so it was cancelling the
   gutter that keeps text off the screen edge. Invisible on a desktop,
   where the container is narrower than the viewport and centres itself,
   but on a phone the container is full-width and that padding is the only
   thing holding the "¿" of "¿Tiene un proyecto?" on screen. */
.cta-band{display:flex;flex-direction:column;align-items:flex-start;gap:18px;padding-top:8px;padding-bottom:8px;}
.cta-band .section__title{max-width:880px;}

/* Section foot — centred arrow CTA at the end of a section */
.section__foot{margin-top:var(--sp-7);display:flex;justify-content:center;}

/* ---- Team grid ---- */
.team-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:28px;}
@media (max-width:900px){.team-grid{grid-template-columns:repeat(2,1fr);}}
.tcard{display:flex;flex-direction:column;gap:16px;}
.tcard__photo{
  aspect-ratio:4/5;background:#0D1B2A;color:#F5F5F3;
  display:flex;align-items:center;justify-content:center;
  font-family:var(--font-display);font-size:48px;font-weight:500;letter-spacing:.04em;
  overflow:hidden;
  border-radius:14px;   /* matches the sector tiles on Proyectos */
}
/* `center top` anchors the photo to its TOP edge — heads (which sit in the
   upper part of a portrait) stay fully visible, and the crop comes off the
   feet instead. Fixes Pedro / Joaquín / Almudena who were getting cut
   at the head with the previous center-center crop. */
.tcard__photo img{width:100%;height:100%;object-fit:cover;object-position:center top;display:block;transition:transform 500ms var(--ease-out);}
.tcard:hover .tcard__photo img{transform:scale(1.04);}
.tcard__name{font-family:var(--font-display);font-weight:500;font-size:17px;}
.tcard__degree{font-size:13px;color:var(--fg-mid);margin:4px 0 10px;line-height:1.4;}

/* =========================================================
   PagePersonas — team section on deep navy (matches the Proyectos band).
   Continues the editorial canvas: PersonasHero is full-bleed photo, this
   section opens with the team grid on the same dark surface.
   ========================================================= */
.personas-team{
  background:#0a1623;
  color:var(--fg-on-dark);
  padding:var(--sp-9) 0 var(--sp-7);
}
.personas-team .tcard__name{color:#F5F5F3;}
.personas-team .tcard__degree{color:rgba(245,245,243,0.65);}
.personas-quote{
  background:#0a1623;
  color:var(--fg-on-dark);
  padding:var(--sp-7) 0 var(--sp-9);
  border-top:1px solid rgba(245,245,243,0.08);
}
.pullquote--on-dark{color:#F5F5F3;}
.pullquote--on-dark em, .pullquote--on-dark .accent{color:var(--ai-blue-300);}

/* ---- Accordion ---- */
.acc{border-top:1px solid var(--ai-hairline);}
.acc__item{border-bottom:1px solid var(--ai-hairline);}
.acc__head{width:100%;display:flex;justify-content:space-between;align-items:center;padding:24px 0;background:transparent;border:0;text-align:left;cursor:pointer;gap:20px;}
.acc__title{font-family:var(--font-display);font-size:20px;font-weight:600;color:#111;}
.acc__meta{display:flex;gap:10px;margin-top:6px;}
.acc__pill{background:#F5F5F3;color:#111;padding:4px 10px;border-radius:999px;font-size:11px;letter-spacing:.06em;}
.acc__dept{font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--accent);font-weight:600;padding:4px 0;}
.acc__icon{font-family:var(--font-display);font-size:24px;color:var(--accent);}
.acc__body{padding:0 0 28px;max-width:760px;color:var(--fg-mid);font-size:15px;line-height:1.6;}
.acc__link{color:var(--accent);font-size:14px;display:inline-block;margin-top:10px;}

/* ---- Accent CTA band ---- */
.cta-band .section__title{max-width:880px;}

/* ---- Contact — single dark column, centered ---- */
/* ── Contact page (F+P-inspired single-city card) ──────────────────────
   Light page, one centered rounded card per office. With our single
   Madrid office the card stands alone; the layout scales naturally if
   more cities are ever added (just render the array). The photo lives
   on top of the card; the body holds the city name + icon row + the
   address / phone / email block; a small map CTA closes the body.
   Replaces the old navy `.contacto*` layout which carried a literal
   satellite map (mapa.jpg) — the photo conveys place without the ugly
   render. */
.ai-contact{
  /* Deep-navy page. With the photo now at fixed 16:9 (was flexible
     clamp height), the card is taller and may push past the viewport
     on short laptops — `min-height: 100vh` lets the page grow with
     content while still filling the viewport when shorter. The card
     still sits directly under the nav at the top. */
  background:#0a1623;
  color:var(--fg-on-dark);
  min-height:100vh;
  padding-top:var(--nav-h);
  padding-bottom:18px;
  display:flex;
  align-items:flex-start;
  justify-content:center;
}
.ai-contact__inner{
  display:flex;flex-direction:column;align-items:center;
  gap:18px;
  text-align:center;
  width:100%;
  /* Outer wrapper width — capped at 1320px so on ultra-wide monitors
     the card doesn't span the whole screen, but fluid below that. */
  max-width:1320px;
  margin:0 auto;
  padding-top:18px;
}
/* Outer 2-column wrapper — contact card on the left, map iframe box
   on the right. Each column is half the available width; the gap is
   what separates the two rounded surfaces against the navy page. */
.ai-contact__grid{
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:20px;
  width:calc(100vw - 96px);
  max-width:1280px;
  align-items:stretch;
}
.ai-contact-card{
  /* Vertical stack: photo banner on TOP, body BELOW. The card's width
     is now driven by its grid column (see .ai-contact__grid above)
     so each side of the pair gets equal share. */
  display:flex;flex-direction:column;
  background:var(--ai-paper);
  color:var(--fg);
  border-radius:18px;
  overflow:hidden;
  width:100%;
  text-align:left;
  box-shadow:0 1px 0 rgba(0,0,0,.04), 0 16px 40px rgba(0,0,0,.35);
}
/* Map box — same rounded surface as the card, hosts the Google Maps
   iframe at 100%×100%. `align-items: stretch` on the grid makes the
   map box match the card's height automatically.
   Placeholder + iframe stack via position:relative/absolute: the
   placeholder shows immediately on render; once the iframe fires
   onLoad, .is-loaded flips and the iframe fades in over the
   placeholder. */
.ai-contact-map{
  position:relative;
  background:#0a1623;
  border-radius:18px;
  overflow:hidden;
  width:100%;
  min-height:320px;
  box-shadow:0 1px 0 rgba(0,0,0,.04), 0 16px 40px rgba(0,0,0,.35);
}
.ai-contact-map__placeholder{
  position:absolute;inset:0;z-index:1;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:10px;
  color:rgba(255,255,255,0.55);
  /* Soft radial gradient on top of the navy bg so the box isn't a
     pure flat panel — reads as "this area will be content" before the
     iframe paints. The shimmer keyframe gives a subtle pulse. */
  background:
    radial-gradient(ellipse at center, rgba(255,255,255,0.04), transparent 70%),
    #0a1623;
  animation:ai-contact-map-shimmer 1.6s ease-in-out infinite;
  transition:opacity 360ms var(--ease-out);
}
.ai-contact-map.is-loaded .ai-contact-map__placeholder{
  opacity:0;pointer-events:none;
}
.ai-contact-map__placeholder-text{
  font-family:var(--font-sans);
  font-size:10px;letter-spacing:.16em;text-transform:uppercase;
  font-weight:500;
}
@keyframes ai-contact-map-shimmer{
  0%, 100% { opacity:1; }
  50%      { opacity:.78; }
}
.ai-contact-map__frame{
  position:relative;z-index:2;
  width:100%;height:100%;
  border:0;
  display:block;
  /* Iframe starts invisible so the placeholder owns the visual until
     onLoad. Fade-in is short — the goal is "no blank flash", not a
     showy animation. */
  opacity:0;
  transition:opacity 240ms var(--ease-out);
}
.ai-contact-map.is-loaded .ai-contact-map__frame{
  opacity:1;
}
.ai-contact-card__photo{
  /* Anchored banner — 200px fixed so the photo stays a clean banner
     stripe regardless of the card column width. The map iframe next
     to it has its own height set by the card's total height, so the
     two columns line up. */
  height:200px;
  overflow:hidden;
  /* Desde el 22 de septiembre esto no es una foto sino el logotipo, que
     es una marca sobre fondo claro: se centra con aire en vez de
     recortarse a sangre. Ver la regla --logo de abajo. */
  background:var(--bg-alt);
  display:flex;align-items:center;justify-content:center;
  background:#0a1623;
}
.ai-contact-card__photo img{
  width:auto;height:auto;
  max-width:min(300px, 62%);max-height:104px;
  object-fit:contain;
  display:block;
}
.ai-contact-card__body{
  /* Padding tuned to the card's column width (~half the grid). */
  padding:22px 26px;
  display:flex;flex-direction:column;
  gap:14px;
  flex:1;
}
.ai-contact-card__head{
  display:flex;align-items:center;justify-content:space-between;
  gap:16px;
}
.ai-contact-card__head-text{
  display:flex;flex-direction:column;
  gap:2px;min-width:0;
}
.ai-contact-card__city{
  margin:0;
  font-family:var(--font-display);font-weight:500;
  font-size:clamp(20px, 1.6vw, 28px);
  line-height:1.1;letter-spacing:-0.01em;
  color:var(--fg);
}
.ai-contact-card__addrs{
  /* Office + legal HQ side-by-side inside the (now narrower) card. */
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:24px;
}
.ai-contact-card__col{
  display:flex;flex-direction:column;
  gap:6px;
  min-width:0;
}
.ai-contact-card__icons{
  display:flex;align-items:center;gap:8px;
}
.ai-contact-card__ic{
  /* Round white icon button — F+P pattern. Sits on the light card so
     the white circle reads as a button without needing a border. */
  width:36px;height:36px;
  border-radius:50%;
  background:#FFFFFF;
  color:var(--fg);
  display:inline-flex;align-items:center;justify-content:center;
  text-decoration:none;
  transition:background 200ms var(--ease-out), color 200ms var(--ease-out), transform 200ms var(--ease-out);
}
.ai-contact-card__ic:hover{
  background:var(--accent);
  color:#FFFFFF;
  transform:translateY(-1px);
}
.ai-contact-card__company{
  /* Sub-line under "Madrid" — quieter so the city name leads. */
  font-size:11px;
  letter-spacing:.12em;
  color:var(--fg-mid);
  text-transform:uppercase;
}
/* Small uppercase eyebrow above each address column ("Oficina" /
   "Sede legal"). */
.ai-contact-card__addr-label{
  font-size:10px;
  letter-spacing:.16em;
  text-transform:uppercase;
  font-weight:600;
  color:var(--fg-mid);
}
/* Legal HQ address — identical font / colour to the office address.
   Hierarchy is carried by the eyebrow label ("REGISTERED HQ") above
   each column, not by typographic dimming. */
.ai-contact-card__legal-addr{
  font-style:normal;
  font-size:13px;
  line-height:1.55;
  color:var(--fg);
  margin:0;
}
.ai-contact-card__addr{
  font-style:normal;
  font-size:13px;
  line-height:1.55;
  color:var(--fg);
  margin:0;
}
.ai-contact-card__lines{
  display:flex;flex-direction:column;gap:2px;
  font-size:13px;
}
.ai-contact-card__line{
  color:var(--fg);
  text-decoration:none;
  transition:color 200ms var(--ease-out);
}
.ai-contact-card__line:hover{color:var(--accent);}
.ai-contact-card__line--mail{color:var(--accent);}
/* Etiqueta corta delante del correo comercial: mismo vocabulario que
   .ai-contact-card__addr-label, pero en línea y sin robarle peso al
   propio correo. */
.ai-contact-card__line-tag{
  margin-top:6px;
  font-size:10px;
  letter-spacing:.16em;
  text-transform:uppercase;
  font-weight:600;
  color:var(--fg-mid);
}
.ai-contact-card__note{
  font-size:11px;
  color:var(--fg-mid);
  border-top:1px solid rgba(15,30,50,.08);
  padding-top:10px;
  margin-top:6px;
  line-height:1.5;
}
.ai-contact-card__map-cta{
  display:inline-flex;align-items:center;gap:6px;
  margin-top:4px;
  font-size:13px;letter-spacing:.04em;text-transform:uppercase;font-weight:500;
  color:var(--accent);
  text-decoration:none;
  transition:color 200ms var(--ease-out), transform 200ms var(--ease-out);
}
.ai-contact-card__map-cta:hover{color:var(--accent-hover);transform:translateX(2px);}
.ai-contact__social{
  display:flex;align-items:center;justify-content:center;gap:12px;
  margin-top:var(--sp-2);
}
.ai-contact__social-ic{
  /* On the navy page bg, the social circles are subtle light glass
     rather than card-coloured — keeps them quiet but visible. */
  width:36px;height:36px;border-radius:50%;
  background:rgba(255,255,255,0.08);
  color:var(--fg-on-dark);
  display:inline-flex;align-items:center;justify-content:center;
  cursor:pointer;
  transition:background 200ms var(--ease-out), color 200ms var(--ease-out);
}
.ai-contact__social-ic:hover{background:var(--accent);color:#FFFFFF;}

@media (max-width:700px){
  /* Mobile: page goes `min-height` so the user can scroll if the
     stacked layout exceeds the viewport. 2-column address grid
     collapses to single-column; photo aspect tightens so it still
     reads as a banner without taking too much vertical share. */
  .ai-contact{
    height:auto;
    min-height:100vh;
    padding-top:calc(var(--nav-h) + 24px);
    padding-bottom:32px;
    display:block;
  }
  .ai-contact__inner{padding:0 16px;}
  /* Phones / narrow tablets — collapse the 2-col grid so card and
     map stack vertically. Both reclaim the full available width. */
  .ai-contact__grid{
    grid-template-columns:1fr;
    width:calc(100vw - 32px);
    gap:14px;
  }
  .ai-contact-map{min-height:280px;}
  .ai-contact-card__photo{height:160px;}
  .ai-contact-card__body{padding:16px 18px;gap:12px;}
  .ai-contact-card__addrs{
    /* Stack the office + legal columns. Legal still reads quieter via
       its smaller font / muted colour. */
    grid-template-columns:1fr;
    gap:14px;
  }
  .ai-contact-card__ic{width:32px;height:32px;}
}
@media (max-width:380px){
  .ai-contact-card__photo{height:120px;}
  .ai-contact-card__body{padding:14px 16px;gap:10px;}
}

.ai-footer__col--brand{gap:14px;}
.ai-footer__social{margin-top:12px;display:flex;flex-direction:column;gap:10px;}
.ai-footer__follow{font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:rgba(245,245,243,.55);font-weight:500;}
.ai-footer__icons{display:flex;gap:8px;}
.ai-footer__ic{width:36px;height:36px;display:inline-flex;align-items:center;justify-content:center;border:1px solid rgba(245,245,243,.35);color:#F5F5F3;transition:all 180ms var(--ease-out);border-radius:2px;}
.ai-footer__ic:hover{background:var(--accent);border-color:var(--accent);color:#fff;transform:translateY(-1px);}
.social-strip{background:var(--bg-dark);color:#F5F5F3;padding:36px 0;}
.social-strip__inner{max-width:var(--container);margin:0 auto;padding:0 32px;display:flex;justify-content:space-between;align-items:center;gap:32px;flex-wrap:wrap;}
.social-strip__left{display:flex;align-items:center;gap:20px;}
.social-strip__icons{display:flex;gap:8px;}
.social-strip__ic{width:36px;height:36px;display:inline-flex;align-items:center;justify-content:center;border:1px solid rgba(245,245,243,.35);color:#F5F5F3;transition:all 180ms var(--ease-out);border-radius:2px;}
.social-strip__ic:hover{background:var(--accent);border-color:var(--accent);color:#fff;transform:translateY(-1px);}
.social-strip__right{display:flex;flex-direction:column;align-items:flex-end;gap:4px;}
.social-strip__mail{color:#F5F5F3;font-size:13px;font-weight:500;}
.social-strip__tel{font-family:var(--font-mono);font-size:12px;color:rgba(245,245,243,.7);}

/* ---- Footer ---- */
.ai-footer{background:var(--bg-deep);color:#F5F5F3;padding:var(--sp-8) 0 var(--sp-6);}
.ai-footer__inner{max-width:var(--container);margin:0 auto;padding:0 32px;display:grid;grid-template-columns:1.3fr 1fr 1fr 1.2fr;gap:40px;}
.ai-footer__col{display:flex;flex-direction:column;gap:10px;}
.ai-footer__head{font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:rgba(245,245,243,.55);font-weight:500;margin-bottom:8px;}
.ai-footer__col a{color:#F5F5F3;font-size:14px;line-height:2;cursor:pointer;}
.ai-footer__col a:hover{color:var(--accent);}
.ai-footer__meta{font-size:12px;color:rgba(245,245,243,.55);letter-spacing:.08em;text-transform:uppercase;margin-top:8px;}
.ai-footer__addr,.ai-footer__tel{font-size:14px;line-height:1.7;color:rgba(245,245,243,.85);}
.ai-footer__bottom{max-width:var(--container);margin:48px auto 0;padding:20px 32px 0;border-top:1px solid rgba(245,245,243,.12);display:flex;justify-content:space-between;gap:24px;font-size:12px;color:rgba(245,245,243,.55);flex-wrap:wrap;}
@media (max-width:900px){.ai-footer__inner{grid-template-columns:1fr 1fr;}}

/* ---- Cookie bar ---- */
.cookie{position:fixed;bottom:24px;left:24px;right:24px;z-index:70;background:rgba(13,27,42,.95);color:#F5F5F3;padding:14px 20px;font-size:13px;display:flex;justify-content:space-between;align-items:center;gap:20px;border:1px solid rgba(245,245,243,.12);}
.cookie button{background:var(--accent);color:#fff;border:0;padding:8px 16px;border-radius:2px;font-size:12px;letter-spacing:.08em;text-transform:uppercase;}


/* =========================================================
   ANIMATIONS — reveal-on-scroll, hero entry, page transitions
   ========================================================= */

/* Reveal: starts hidden + 24px below; flips to visible on .is-revealed.
   Apply to any element via the <Reveal/> wrapper (or by adding the class). */
.reveal{
  opacity:0;
  transform:translateY(28px);
  transition:opacity 700ms var(--ease-out), transform 800ms var(--ease-out);
  will-change:opacity, transform;
}
.reveal.is-revealed{
  opacity:1;
  transform:translateY(0);
}

/* Honor reduced motion preference */
@media (prefers-reduced-motion: reduce) {
  .reveal{opacity:1!important;transform:none!important;transition:none!important;}
  .reveal--media .article-block--image img,
  .reveal--media .article-block--image figcaption{
    clip-path:none!important;transform:none!important;opacity:1!important;transition:none!important;
  }
  .hero__inner.is-active .hero__content > *{opacity:1!important;transform:none!important;animation:none!important;}
}

/* Hero — staggered content entry on slide change.
   Keyed off .hero__inner, not .hero__slide: the copy was hoisted out of
   the slides so it could clear the bottom scrim, so the active flag it
   reacts to now lives on its own wrapper. */
.hero__content > *{opacity:0;transform:translateY(28px);transition:none;}
.hero__inner.is-active .hero__content > *{animation:heroIn 900ms var(--ease-out) forwards;}
.hero__inner.is-active .hero__content > *:nth-child(1){animation-delay:120ms;}
.hero__inner.is-active .hero__content > *:nth-child(2){animation-delay:240ms;}
@keyframes heroIn{
  from{opacity:0;transform:translateY(28px);}
  to  {opacity:1;transform:translateY(0);}
}

/* Hero image — slow Ken-Burns drift on the active slide only */
.hero__img{transform:scale(1.02);transition:transform 8s linear, opacity 1000ms var(--ease-out);}
.hero__slide.is-active .hero__img{transform:scale(1.08);}

/* Page-hero fade-in on background. Previously used background-attachment:
   fixed for a parallax feel, but that anchors the photo to the VIEWPORT
   while the hero element starts mid-scroll, so the initial paint shows
   one crop and the first scroll snaps to another — looks like the framing
   "recalculates". With background-attachment: scroll (the default) the
   photo travels with the section, the bgZoom animation lands cleanly on
   the final framing, and mobile/iOS — which never supported fixed
   reliably anyway — gets the same behaviour. */
.page-hero{
  background-attachment:scroll;
  background-position:center;
  background-size:cover;
  animation:bgZoom 1400ms var(--ease-out);
}
@keyframes bgZoom{
  from{transform:scale(1.04);opacity:0;}
  to  {transform:scale(1);opacity:1;}
}

/* Page transition — when the route swaps, fade the main content in */
.page-shell{animation:pageIn 500ms var(--ease-out);}
@keyframes pageIn{
  from{opacity:0;transform:translateY(12px);}
  to  {opacity:1;transform:translateY(0);}
}

/* Accordion smooth height — replace display toggle */
.acc__body{
  max-height:0;
  overflow:hidden;
  transition:max-height 380ms var(--ease-out);
}
.acc__body-inner{padding:0 0 28px;max-width:760px;color:var(--fg-mid);font-size:15px;line-height:1.6;}
.acc__body-inner p{margin:0 0 14px;}
/* Requirements list inside an open position. Bullets are subtle dots
   in the brand accent so they read as a checklist, not a generic ul. */
.acc__reqs{list-style:none;margin:0 0 18px;padding:0;display:flex;flex-direction:column;gap:8px;}
.acc__reqs li{position:relative;padding-left:18px;font-size:14.5px;line-height:1.55;color:var(--fg-mid);}
.acc__reqs li::before{content:"·";position:absolute;left:0;top:-1px;color:var(--reto-accent);font-weight:700;font-size:18px;}

/* Buttons get a soft idle-state hover lift already; add a focus-visible ring */
.btn:focus-visible{outline:2px solid var(--accent);outline-offset:3px;}

/* Nav: subtle slide-in on mount (only first time) */
.ai-nav{animation:navIn 600ms var(--ease-out);}
@keyframes navIn{from{opacity:0;transform:translateY(-6px);}to{opacity:1;transform:translateY(0);}}

/* Stat numerals — once revealed, gently rise into place */
.stat-row{will-change:opacity, transform;}

/* =========================================================
   VERTICALS HERO — Isometric 3D blocks + engineering chrome
   ========================================================= */

.vhero{
  position:relative;
  background:#0a1623;
  color:var(--fg-on-dark);
  padding:var(--sp-8) 0 var(--sp-9);
  overflow:hidden;
}
.vhero::before{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:
    radial-gradient(60% 50% at 70% 50%, rgba(0,80,144,0.10) 0%, transparent 70%),
    radial-gradient(40% 40% at 10% 30%, rgba(0,80,144,0.06) 0%, transparent 60%);
}
/* Intro banner — full-width band across the top of the section */
.vhero__intro-wrap{
  position:relative;z-index:1;
  max-width:var(--container);margin:0 auto;
  padding:0 32px var(--sp-6);
  display:flex;flex-direction:column;gap:14px;
}
.vhero__title{
  font-family:var(--font-display);font-weight:500;
  font-size:clamp(28px,2.8vw,42px);line-height:1.1;
  letter-spacing:-0.015em;color:#F5F5F3;margin:0;max-width:900px;
  text-wrap:balance;
}
.vhero__sub{
  font-size:17px;font-weight:300;color:rgba(245,245,243,0.72);
  line-height:1.55;margin:0;max-width:680px;
}

/* Two-column body — both columns scroll naturally together, sized to match
   row-by-row. The right blueprint stack is taller now (FLOOR_W=480, viewBox
   900×1634) so each block lines up with its corresponding menu row on the
   left. No pinning, no reveal animation — all menus are always visible. */
.vhero__inner{
  position:relative;z-index:1;
  max-width:var(--container);margin:0 auto;
  padding:0 32px;
  display:grid;grid-template-columns:1fr 1.05fr;
  gap:64px;align-items:stretch;
}

/* The left column stretches to match the SVG's natural rendered height
   (viewBox 900×1634 → ~1906px at desktop). Items sit absolutely positioned at
   the vertical centres of their corresponding SVG blocks, so the rows line up
   horizontally with the blueprints; los porcentajes exactos están más abajo,
   en las reglas [data-pos]. */
/* Verticals menu — items are absolute-positioned so their vertical
   centres line up with the matching floors on the SVG blueprint to the
   right. Scroll-driven active picks whichever row is closest to the
   viewport centre; the active row gets full opacity + brighter label,
   and its expand block (long copy + sector link) opens. */
.vhero__list{
  position:relative;
  list-style:none;margin:0;padding:0;
}
.vhero__item{
  position:absolute;left:0;right:0;
  transform:translateY(-50%);
  display:grid;grid-template-columns:48px 1fr 22px;gap:18px;
  align-items:flex-start;
  padding:24px 0;
  cursor:pointer;
  opacity:0.55;
  transition:opacity 480ms var(--ease-out), color 280ms var(--ease-out);
}
/* Cada fila se centra sobre su losa del plano de la derecha. Los
   porcentajes son el centro de cada losa dividido entre el alto del
   viewBox (900×1634, con los huecos cerrados): 219, 581, 943 y 1330,5
   sobre 1634. Si cambian las alturas de VerticalsHero.jsx, hay que
   recalcularlos aquí. */
.vhero__item[data-pos="0"]{top:13.40%;}
.vhero__item[data-pos="1"]{top:35.56%;}
.vhero__item[data-pos="2"]{top:57.71%;}
.vhero__item[data-pos="3"]{top:81.43%;}
.vhero__item.is-active{opacity:1;}
.vhero__item::before{
  content:"";position:absolute;left:0;top:0;width:0;height:1px;
  background:var(--ai-blue-300);
  transition:width 500ms var(--ease-out);
}
.vhero__item.is-active::before{width:100%;}

.vhero__num{
  font-family:var(--font-mono);font-size:12px;font-weight:500;
  color:rgba(245,245,243,0.4);padding-top:6px;letter-spacing:.06em;
  transition:color 280ms var(--ease-out);
}
.vhero__item.is-active .vhero__num{color:var(--ai-blue-300);}
.vhero__body{min-width:0;}
.vhero__label{
  font-family:var(--font-display);font-weight:500;font-size:24px;
  line-height:1.2;letter-spacing:-0.005em;
  color:rgba(245,245,243,0.7);
  transition:color 280ms var(--ease-out);
}
.vhero__item.is-active .vhero__label{color:#FFFFFF;}
/* La frase corta es ya el único texto de la fila, así que sube de 14 a
   15px y gana contraste: antes era el pie de un párrafo y ahora es el
   párrafo. */
.vhero__short{font-size:15px;font-weight:300;color:rgba(245,245,243,0.72);margin-top:6px;line-height:1.55;max-width:420px;}
.vhero__thumb{display:none;}

/* Expand block — ahora sólo el enlace al área. La regla de plegado
   (de 901px para arriba) lo esconde en las filas inactivas, así que el
   enlace aparece únicamente en la fila centrada. En móvil se abren
   todas. El max-height bajó de 600 a 60px al quedarse sin párrafo: con
   600 la transición de plegado tardaba en arrancar porque recorría un
   alto que ya nadie ocupaba. */
.vhero__expand{
  margin-top:14px;
  max-height:60px;
  opacity:1;
  overflow:hidden;
  transition:max-height 360ms var(--ease-out), opacity 320ms var(--ease-out), margin-top 320ms var(--ease-out);
}
/* Sector-link CTA — small uppercase anchor inside the expand block.
   Looks like "VIEW SECTOR PROJECTS →" — drives the user to the matching
   sector landing page. */
.vhero__sector-link{
  display:inline-flex;align-items:center;gap:6px;
  font-family:var(--font-sans);font-size:11px;font-weight:600;
  letter-spacing:.16em;text-transform:uppercase;
  color:var(--ai-blue-300);
  cursor:pointer;
  transition:color 200ms var(--ease-out), transform 200ms var(--ease-out);
}
.vhero__sector-link:hover{
  color:#FFFFFF;
  transform:translateX(2px);
}
.vhero__arrow{
  font-size:18px;color:rgba(245,245,243,0.3);padding:6px 10px 0;
  opacity:0;transform:translateX(-4px);
  cursor:pointer;display:inline-block;
  transition:all 280ms var(--ease-out);
}
.vhero__item.is-active .vhero__arrow,
.vhero__item:hover .vhero__arrow{opacity:1;transform:translateX(0);color:var(--ai-blue-300);}
.vhero__arrow:hover{
  transform:translateX(4px) !important;
  color:#FFFFFF !important;
}

/* Desktop only — collapse the expand block on inactive items so only
   the active vertical carries the prose. Below 900px the layout is a
   single column and every row should remain readable. */
/* Pace of the area-to-area transition, ~1.5x slower than the values on the
   base rules. Scoped to the same breakpoint that owns the accordion: below
   901px every item is expanded and none of these ever fire, so there is
   nothing to slow down there.
   The hover affordances (.vhero__sector-link, .vhero__arrow) deliberately
   keep their original 200–280ms — those answer a cursor, not a scroll, and
   slowing them just makes the section feel unresponsive.
   The isometric drawing's own timings are set at the very end of this file
   instead: .vt-block and .vt-axis are each declared several times further
   down, so an override here lost the cascade. */
@media (min-width: 901px){
  .vhero__item{transition:opacity 720ms var(--ease-out), color 420ms var(--ease-out);}
  .vhero__item::before{transition:width 750ms var(--ease-out);}
  .vhero__num,
  .vhero__label{transition:color 420ms var(--ease-out);}
  .vhero__expand{transition:max-height 540ms var(--ease-out), opacity 480ms var(--ease-out), margin-top 480ms var(--ease-out);}
}
@media (prefers-reduced-motion: reduce){
  .vhero__item,.vhero__item::before,.vhero__num,.vhero__label,
  .vhero__expand,.vt-axis line,.vt-block{transition-duration:1ms !important;}
}

@media (min-width: 901px){
  .vhero__item:not(.is-active) .vhero__expand{
    max-height:0;
    opacity:0;
    margin-top:0;
    pointer-events:none;
  }
}
.vhero__stats{
  display:grid;grid-template-columns:repeat(3,1fr);gap:0;
  border-top:1px solid rgba(245,245,243,0.12);padding-top:14px;
}
.vhero__stat{display:flex;flex-direction:column;gap:4px;padding-right:12px;}
.vhero__stat-k{font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:rgba(245,245,243,0.5);font-weight:500;}
.vhero__stat-v{font-family:var(--font-display);font-weight:500;font-size:14px;color:#F5F5F3;letter-spacing:-0.005em;}
.vhero__arrow{
  font-size:18px;color:rgba(245,245,243,0.3);padding:6px 10px 0;
  opacity:0;transform:translateX(-4px);
  cursor:pointer;display:inline-block;
  transition:all 280ms var(--ease-out);
}
.vhero__item.is-active .vhero__arrow,
.vhero__item:hover .vhero__arrow{opacity:1;transform:translateX(0);color:var(--ai-blue-300);}
.vhero__arrow:hover{
  /* Arrow lifts + brightens further on direct hover so users see it's
     a discrete link target (routes to the sector page), distinct from
     the row's activate-and-scroll click. */
  transform:translateX(4px) !important;
  color:#FFFFFF !important;
}

/* RIGHT side — scrolls with the page; renders the SVG at its natural aspect
   (900×1634 viewBox). Both columns stretch to the same height via the grid. */
.vhero__right{
  position:relative;
  display:flex;align-items:stretch;justify-content:center;
}
.vt-svg{
  width:100%;max-width:1050px;height:auto;display:block;
  animation:vt-fade-in 1000ms var(--ease-out);
}
@keyframes vt-fade-in{
  from{opacity:0;transform:translateY(20px);}
  to  {opacity:1;transform:translateY(0);}
}

/* Drawing chrome */
.vt-corner{stroke:rgba(245,245,243,0.5);stroke-width:1;}
.vt-axis line{stroke:rgba(245,245,243,0.35);stroke-width:0.5;transition:all 480ms var(--ease-out);}
.vt-axis-l{
  font-family:var(--font-mono);font-size:10px;
  fill:rgba(245,245,243,0.5);text-anchor:end;font-weight:500;letter-spacing:.04em;
}

/* Block wrapper */
.vt-block{
  transition:transform 600ms var(--ease-out),opacity 480ms var(--ease-out);
  opacity:0.35;
}
.vt-block.is-active{opacity:1;}
.vt-block:hover{opacity:0.7;}
.vt-block.is-active:hover{opacity:1;}

/* Block ID badge */
.vt-block-id-line{stroke:rgba(245,245,243,0.4);stroke-width:0.75;}
.vt-block.is-active .vt-block-id-line{stroke:var(--ai-blue-300);stroke-width:1;}
.vt-block-id-num{
  font-family:'Inter',sans-serif;font-size:9px;font-weight:600;
  fill:rgba(245,245,243,0.5);letter-spacing:.12em;
}
.vt-block-id-lbl{
  font-family:'Inter',sans-serif;font-size:10px;font-weight:500;
  fill:rgba(245,245,243,0.75);letter-spacing:.16em;
}
.vt-block.is-active .vt-block-id-num,
.vt-block.is-active .vt-block-id-lbl{fill:#FFFFFF;}

/* ----- The 3D isometric faces ----- */
.vt-side{
  fill:rgba(13,27,42,0.92);
  stroke:rgba(245,245,243,0.35);
  stroke-width:0.6;
}
.vt-skin{
  fill:rgba(13,27,42,0.7);
  stroke:rgba(245,245,243,0.5);
  stroke-width:0.75;
}
.vt-top{
  fill:rgba(31,55,82,0.75);
  stroke:rgba(245,245,243,0.55);
  stroke-width:0.6;
}
.vt-floor-base{stroke:rgba(245,245,243,0.45);stroke-width:1;}

.vt-block.is-active .vt-side{fill:rgba(8,18,32,1);stroke:rgba(245,245,243,0.7);}
.vt-block.is-active .vt-skin{
  fill:rgba(0,80,144,0.10);
  stroke:#FFFFFF;stroke-width:1;
}
.vt-block.is-active .vt-top{
  fill:rgba(45,80,120,0.85);
  stroke:#FFFFFF;stroke-width:0.85;
}
.vt-block.is-active .vt-floor-base{stroke:#FFFFFF;stroke-width:1.4;}

/* ----- Per-floor patterns ----- */

/* DC — front louvers + vent unit */
.vt-louver{stroke:rgba(245,245,243,0.25);stroke-width:0.4;}
.vt-block.is-active .vt-louver{stroke:rgba(245,245,243,0.55);}
.vt-unit{fill:rgba(13,27,42,0.6);stroke:rgba(245,245,243,0.45);stroke-width:0.5;}
.vt-block.is-active .vt-unit{stroke:#FFFFFF;}
.vt-unit-l{stroke:rgba(245,245,243,0.3);stroke-width:0.4;}
.vt-block.is-active .vt-unit-l{stroke:rgba(245,245,243,0.6);}
.vt-led{fill:#5A95D0;opacity:0;}
.vt-block.is-active .vt-led{opacity:0.8;animation:vt-led 2.2s ease-in-out infinite;}
@keyframes vt-led{
  0%,30%,100%{opacity:0.2;}
  50%,55%{opacity:1;filter:drop-shadow(0 0 3px #5A95D0);}
}
/* Upright server cabinet rendering — inspired by Nscale's iso server farm */
.vt-cab-front{
  fill:rgba(13,27,42,0.78);
  stroke:rgba(245,245,243,0.35);
  stroke-width:0.35;
}
.vt-cab-side{
  fill:rgba(7,15,26,0.9);
  stroke:rgba(245,245,243,0.28);
  stroke-width:0.3;
}
.vt-cab-top{
  fill:rgba(31,55,82,0.85);
  stroke:rgba(245,245,243,0.4);
  stroke-width:0.3;
}
.vt-cab-u{stroke:rgba(245,245,243,0.22);stroke-width:0.25;}
.vt-cab-cable{stroke:rgba(245,245,243,0.3);stroke-width:0.45;stroke-linecap:round;}
.vt-rack-tray{stroke:rgba(245,245,243,0.3);stroke-width:0.4;}
.vt-block.is-active .vt-cab-front{stroke:#FFFFFF;stroke-width:0.55;fill:rgba(0,80,144,0.18);}
.vt-block.is-active .vt-cab-side{stroke:rgba(245,245,243,0.6);}
.vt-block.is-active .vt-cab-top{stroke:#FFFFFF;fill:rgba(45,85,130,0.95);}
.vt-block.is-active .vt-cab-u{stroke:rgba(245,245,243,0.55);}
.vt-block.is-active .vt-cab-cable{stroke:var(--ai-blue-300);stroke-width:0.6;}
.vt-block.is-active .vt-rack-tray{stroke:#FFFFFF;stroke-width:0.6;}

/* FARMA — sealed envelope + AHU */
.vt-seam{stroke:rgba(245,245,243,0.3);stroke-width:0.4;}
.vt-block.is-active .vt-seam{stroke:rgba(245,245,243,0.6);}
.vt-door{
  fill:rgba(13,27,42,0.5);
  stroke:rgba(245,245,243,0.45);
  stroke-width:0.5;
}
.vt-block.is-active .vt-door{stroke:#FFFFFF;fill:rgba(0,80,144,0.15);}
.vt-equip{fill:rgba(13,27,42,0.6);stroke:rgba(245,245,243,0.5);stroke-width:0.55;}
.vt-block.is-active .vt-equip{stroke:#FFFFFF;}
.vt-equip-line{stroke:rgba(245,245,243,0.35);stroke-width:0.4;}
.vt-vent{fill:rgba(13,27,42,0.7);stroke:rgba(245,245,243,0.45);stroke-width:0.4;}
/* Generic signage plate (DC equipment control panels) */
.vt-sign{fill:rgba(13,27,42,0.6);stroke:rgba(245,245,243,0.45);stroke-width:0.45;}
.vt-block.is-active .vt-sign{stroke:#FFFFFF;}

/* Manifold pipe (FARMA — connects stacks to AHU) */
.vt-pipe-thick{stroke:rgba(245,245,243,0.45);stroke-width:1.5;}
.vt-block.is-active .vt-pipe-thick{stroke:var(--ai-blue-300);}

/* Extraction stacks */
.vt-stack{fill:rgba(13,27,42,0.7);stroke:rgba(245,245,243,0.5);stroke-width:0.5;}
.vt-stack-cap{fill:rgba(31,55,82,0.85);stroke:rgba(245,245,243,0.55);stroke-width:0.5;}
.vt-block.is-active .vt-stack{stroke:#FFFFFF;}
.vt-block.is-active .vt-stack-cap{stroke:#FFFFFF;}
.vt-stack-puff{fill:rgba(245,245,243,0.0);}
.vt-block.is-active .vt-stack-puff{
  fill:rgba(90,149,208,0.6);
  animation:vt-puff 2.2s ease-out infinite;
}
@keyframes vt-puff{
  0%   {opacity:0;transform:translateY(0)   scale(0.6);}
  30%  {opacity:0.7;}
  100% {opacity:0;transform:translateY(-14px) scale(1.6);}
}
.vt-equip-lbl{
  font-family:'Inter',sans-serif;font-size:8px;font-weight:500;
  fill:rgba(245,245,243,0.55);letter-spacing:.16em;text-transform:uppercase;
}
.vt-equip-lbl-sm{
  font-family:'Inter',sans-serif;font-size:7px;font-weight:500;
  fill:rgba(245,245,243,0.75);letter-spacing:.12em;
}
.vt-equip-sm{
  font-family:var(--font-mono);font-size:8.5px;
  fill:rgba(245,245,243,0.55);
}
.vt-block.is-active .vt-equip-lbl,
.vt-block.is-active .vt-equip-lbl-sm,
.vt-block.is-active .vt-equip-sm{fill:#FFFFFF;}

/* Crédito del arquitecto en el plano. Va aparte del pie —y no dentro,
   como estaba— porque el pie es una etiqueta técnica a 8,5 px y el
   crédito es una firma: pide tamaño y color propios. Sólo lo lleva el
   bloque que tiene arquitecto. */
.vt-arch{
  font-family:var(--font-mono);font-size:12px;letter-spacing:.22em;
  fill:rgba(155,196,230,0.62);
  transition:fill 480ms var(--ease-out);
}
.vt-block.is-active .vt-arch{fill:var(--ai-blue-300);}

/* Shared style for image-based isometric line drawings (DC, Farma, Auditorio).
   PNGs are pre-baked with light-blue lines on transparent — no filter needed. */
.vt-iso-drawing,
.vt-ten-drawing{
  opacity:0.55;
  transition:opacity 480ms var(--ease-out), filter 480ms var(--ease-out);
}
.vt-block.is-active .vt-iso-drawing,
.vt-block.is-active .vt-ten-drawing{
  opacity:1;
  filter:drop-shadow(0 0 6px rgba(90,149,208,0.55));
}

/* FARMA — narrow viewing windows on the cleanroom envelope */
.vt-window{fill:rgba(120,170,210,0.06);stroke:none;}
.vt-block.is-active .vt-window{fill:rgba(120,170,210,0.14);}

/* FARMA — HEPA ceiling panels */
.vt-hepa-panel{fill:rgba(245,245,243,0.04);stroke:rgba(245,245,243,0.4);stroke-width:0.45;}
.vt-block.is-active .vt-hepa-panel{
  fill:rgba(120,170,210,0.18);stroke:#FFFFFF;
  animation:vt-hepa-panel 3.4s ease-in-out infinite;
}
@keyframes vt-hepa-panel{
  0%,100%{fill:rgba(120,170,210,0.10);}
  50%    {fill:rgba(120,170,210,0.28);}
}

/* Callouts */
.vt-callout{animation:vt-callout-in 460ms var(--ease-out) both;}
@keyframes vt-callout-in{
  from{opacity:0;transform:translateX(-6px);}
  to  {opacity:1;transform:translateX(0);}
}
.vt-callout-dot{fill:var(--ai-blue-300);stroke:#FFFFFF;stroke-width:0.4;}
.vt-callout-leader{stroke:rgba(245,245,243,0.55);stroke-width:0.55;}
.vt-callout-base{stroke:#FFFFFF;stroke-width:0.7;}
.vt-callout-text{
  font-family:'Inter',sans-serif;font-size:10.5px;font-weight:500;
  fill:#FFFFFF;letter-spacing:0;
}

/* Title block — outer wrapper holds the position (transitions when active
   drawing changes); inner .vt-title runs the one-shot fade-in. */
.vt-title-wrap{transition:transform 520ms var(--ease-out);}
.vt-title{animation:vt-callout-in 600ms var(--ease-out) both;animation-delay:200ms;}
.vt-title-box{fill:rgba(13,27,42,0.6);stroke:rgba(245,245,243,0.55);stroke-width:0.75;}
.vt-title line{stroke:rgba(245,245,243,0.5);stroke-width:0.5;}
.vt-title-h{font-family:'Inter',sans-serif;font-size:10px;font-weight:500;fill:#FFFFFF;letter-spacing:.18em;}
.vt-title-k{font-family:'Inter',sans-serif;font-size:8px;font-weight:500;fill:rgba(245,245,243,0.45);letter-spacing:.12em;text-transform:uppercase;}
.vt-title-v{font-family:var(--font-mono);font-size:11px;font-weight:500;fill:rgba(245,245,243,0.85);letter-spacing:.04em;}

/* Responsive */
@media (max-width: 1024px){.vhero__inner{gap:48px;}}
@media (max-width: 900px){
  .vhero__intro-wrap{padding:0 24px 48px;}
  .vhero__inner{
    grid-template-columns:1fr;gap:48px;padding:0 24px 64px;
  }
  .vhero__right{min-height:540px;order:-1;}
  .vt-svg{max-width:780px;}
  .vhero__title{font-size:30px;}
  /* Below 900px: drop absolute positioning, items flow naturally. Scroll
     listener is detached in the React effect at this breakpoint. */
  .vhero__list{display:flex;flex-direction:column;gap:24px;}
  .vhero__item{position:static;transform:none;opacity:1;}
  .vhero__item[data-pos="0"],
  .vhero__item[data-pos="1"],
  .vhero__item[data-pos="2"],
  .vhero__item[data-pos="3"]{top:auto;}
}
/* Phones — the 900×1634 blueprint SVG renders fine but at this width every
   photo, callout and title-block detail collapses to a thumbnail strip; it's
   also the single biggest paint cost on the home page. The card content below
   already carries the same story in legible type, so we hide the SVG here
   and let the verticals stand on their content alone. */
@media (max-width: 640px){
  .vhero__right{display:none;}
  .vhero__inner{gap:32px;padding-bottom:48px;}
  .vhero__title{font-size:26px;}
  .vhero__sub{font-size:15px;}
  .vhero__label{font-size:20px;}
  .vhero__short{font-size:14px;}
  .vhero__item{grid-template-columns:36px 1fr 18px;gap:14px;padding:22px 0;border-top:1px solid rgba(245,245,243,0.08);}
  .vhero__item:first-child{border-top:0;}
  /* Per-row drawing comes online here. Centered above the label so the
     row reads as: drawing → name → tagline → copy → arrow. */
  .vhero__thumb{
    display:block;
    width:100%;
    max-width:clamp(220px, 70vw, 320px);
    height:auto;
    margin:0 auto 14px;
    opacity:.95;
  }
}
@media (prefers-reduced-motion: reduce){
  .vt-svg{animation:none;}
  .vt-led,.vt-hepa-panel,.vt-stack-puff,.vt-callout,.vt-title{animation:none;}
  .vt-block{transition:opacity 240ms ease;}
}

/* CTA under the 3-card home news grid (links to the full news page) */
.grid-3__cta{margin-top:var(--sp-7);display:flex;justify-content:center;}

/* =========================================================
   Talento page — narrative-driven, photo-led
   ========================================================= */

/* The talento hero uses the full team photo. The default page-hero overlay
   is heavy enough for typical site photography, but the group photo is busy
   — we lift the overlay a touch so the hero copy stays legible. */
.page-hero--people{
  /* darken slightly more than the default page-hero gradient */
  background-color:#0a1623;
}
.page-hero--people .page-hero__ov{
  background:linear-gradient(180deg, rgba(13,27,42,.35) 0%, rgba(13,27,42,.85) 100%);
}

/* =========================================================
   Careers page (PageTalento) — full deep-navy treatment
   ========================================================= */
/* The whole page wears the navy treatment so it reads as one
   continuous narrative: banner → journey → game → find spot →
   positions → CTA → vida-CTA. Section variants used here override
   their light/alt backgrounds; .section--accent (the spontaneous
   candidacy band) keeps brand blue. */
[data-screen-label="talento"]{
  --bg:#0a1623;
  --bg-alt:#0a1623;
  --fg:var(--fg-on-dark);
  --fg-mid:var(--fg-on-dark-mid);
  background:#0a1623;
}
/* Positions section flipped to LIGHT — long accordion lists scan
   far better with dark text on a light bg than the other way round.
   Creates a navy → light → navy sandwich between the game above and
   the vida-CTA below, which gives the list its own visual chapter.
   We RESET --fg/--fg-mid back to their light-mode values inside this
   section because the page-level data-screen-label="talento" block
   reassigns them to fg-on-dark for the rest of /talento; without
   the reset, every var(--fg) here would still resolve to the dark
   theme's white. */
.talento-positions{
  background:#F5F5F3;
  --fg:#0D1B2A;
  --fg-mid:#5A6573;
  color:var(--fg);
}
/* Title now dark + bold (overrides section__title--light if React
   still applies it). */
.talento-positions__title{
  font-weight:700;
  color:var(--fg) !important;
  margin:0 0 14px;
}
.talento-positions__lead{
  color:var(--fg-mid);
  max-width:60ch;
  margin:6px 0 32px;
}
.talento-positions__lead--empty{
  color:var(--fg);
  font-size:20px;
  font-weight:300;
  max-width:60ch;
  margin:6px 0 0;
}
/* Accordion overrides — match the light treatment. Hairlines use
   the standard --ai-hairline, the body copy uses the mid token. */
.talento-positions .acc__item{border-color:var(--ai-hairline);}
.talento-positions .acc__title{color:var(--fg);}
.talento-positions .acc__dept{color:var(--fg-mid);}
.talento-positions .acc__pill{background:rgba(13,27,42,0.06);color:var(--fg);}
.talento-positions .acc__icon{color:var(--fg-mid);}
.talento-positions .acc__head:hover .acc__icon,
.talento-positions .acc__item.is-open .acc__icon{color:var(--fg);}
.talento-positions .acc__body p{color:var(--fg-mid);}
.talento-positions .acc__link{color:var(--reto-accent);}
.talento-cta,
/* Why-work-here intro — opens the careers page between the banner and the
   vacancy list. Same reading measure as the other single-column blocks so
   the paragraph does not run the full container width. */
.talento-intro__inner{
  max-width:780px;margin:0 auto;
  display:flex;flex-direction:column;align-items:flex-start;gap:16px;
}
.talento-intro__title{max-width:20ch;}
.talento-intro__body{color:var(--fg-mid);max-width:680px;margin:0;}
.talento-intro__pillars{margin-top:var(--sp-8);}
@media (max-width:900px){.talento-intro__pillars{grid-template-columns:1fr;gap:var(--sp-6);}}

.talento-find__sub,

/* =========================================================
   Journey path — straight scroll-driven SVG between banner & game
   ========================================================= */
/* Straight vertical line drawn dead-centre. Stops alternate
   left/right of the line for the 4 milestones; start + end labels
   are centred ABOVE/BELOW their dots (NOT around them) so the line
   never cuts through the text. Scroll progress drives the
   stroke-dashoffset (line draws in) and per-stop "passed" state
   (text fades up from 0.42 → 1, dot lights up). */
.journey{
  position:relative;
  background:#0a1623;
  padding:var(--sp-9) 0 var(--sp-9);
  overflow:hidden;
}
.journey__inner{
  position:relative;
  max-width:980px;
  margin:0 auto;
  padding:0 24px;
}
/* The SVG carries the line. Absolute-positioned dead-centre, full
   height of the section. Width is small (just the line). */
.journey__svg{
  position:absolute;
  left:50%;top:0;
  transform:translateX(-50%);
  width:2px;
  height:100%;
  pointer-events:none;
  /* preserveAspectRatio="none" on the element lets the line stretch
     to whatever height the section ends up being. */
}
.journey__track{
  stroke:rgba(255,255,255,0.10);
  stroke-width:1;
}
.journey__line{
  stroke:var(--ai-blue-300);
  stroke-width:1.5;
  filter:drop-shadow(0 0 6px rgba(0,80,144,0.4));
  transition:stroke-dashoffset 200ms linear;
}
.journey__stops{
  list-style:none;margin:0;padding:0;
  position:relative;z-index:1;
  display:flex;flex-direction:column;
  gap:0;
}
.journey__stop{
  position:relative;
  min-height:180px;
  display:flex;align-items:center;justify-content:center;
}
/* Dot lane — a narrow centred column that owns the dot. Keeps the
   dot dead on the line regardless of what the content next to it
   does, and ensures the dot never lands inside a text block. */
.journey__dot-wrap{
  position:absolute;
  left:50%;top:50%;
  width:18px;height:18px;
  transform:translate(-50%, -50%);
  z-index:2;
  display:flex;align-items:center;justify-content:center;
}
.journey__dot{
  width:12px;height:12px;border-radius:50%;
  /* Match the page bg so the dot looks like a notch in the line,
     not a circle drawn on top. */
  background:#0a1623;
  border:1.5px solid rgba(255,255,255,0.3);
  transition:all 380ms var(--ease-out);
}
.journey__stop.is-passed .journey__dot{
  background:var(--ai-blue-300);
  border-color:#FFFFFF;
  box-shadow:0 0 16px rgba(0,80,144,0.7);
}
/* Milestone content — left or right column, offset from the centre
   line so the line never touches the text. */
.journey__stop--milestone .journey__content{
  width:42%;
  padding:0 36px;
  opacity:0.42;
  transition:opacity 480ms var(--ease-out);
}
.journey__stop--milestone.is-passed .journey__content{opacity:1;}
.journey__stop--milestone.is-left .journey__content{margin-right:auto;text-align:right;}
.journey__stop--milestone.is-right .journey__content{margin-left:auto;text-align:left;}
.journey__tag{
  font-family:var(--font-mono);font-size:10px;font-weight:500;
  letter-spacing:.14em;text-transform:uppercase;
  color:rgba(255,255,255,0.5);
  display:block;margin-bottom:8px;
}
.journey__title{
  font-family:var(--font-display);font-weight:500;
  font-size:clamp(20px, 2vw, 28px);
  line-height:1.2;letter-spacing:-0.01em;
  color:#FFFFFF;
}
/* Start + end labels — no dot. The title sits dead-centred on the
   line and gets a page-bg painted around it (via a wide horizontal
   padding + matching background) so the SVG line behind visually
   terminates at the edge of the text. Net effect: the line appears
   to emerge from the centre of "Your journey at Aguilera" and to
   dissolve into "Your journey begins with a challenge". */
.journey__stop--start,
.journey__stop--end{
  min-height:200px;
}
.journey__stop--start .journey__content,
.journey__stop--end .journey__content{
  width:auto;margin:0 auto;text-align:center;
  padding:8px 24px;
  max-width:780px;
  opacity:0.55;
  transition:opacity 480ms var(--ease-out);
  position:relative;z-index:2;
}
.journey__stop--start.is-passed .journey__content,
.journey__stop--end.is-passed .journey__content{opacity:1;}
.journey__stop--start .journey__title,
.journey__stop--end .journey__title{
  font-size:clamp(28px, 3.6vw, 48px);
  letter-spacing:-0.02em;
  font-weight:600;
}

@media (max-width: 700px){
  /* On phones: line tucked to the left edge, stops left-aligned in a
     single column. Start/end labels still centre on the line column
     but their text flows to the right. */
  .journey__svg{left:20px;transform:none;width:2px;}
  .journey__dot-wrap{left:20px;}
  .journey__stop{min-height:160px;}
  .journey__stop--start,
  .journey__stop--end{min-height:200px;}
  .journey__stop--milestone .journey__content,
  .journey__stop--milestone.is-left .journey__content,
  .journey__stop--milestone.is-right .journey__content{
    width:100%;margin:0;text-align:left;padding:0 12px 0 48px;
  }
  .journey__stop--start .journey__content,
  .journey__stop--end .journey__content{
    text-align:left;padding:8px 12px 8px 36px;margin:0;
  }
  .journey__title{font-size:18px;}
  .journey__stop--start .journey__title,
  .journey__stop--end .journey__title{font-size:24px;}
}

/* =========================================================
   El Reto Aguilera — recruiting game embedded on PageTalento
   ========================================================= */
/* Iframe is placed edge-to-edge immediately after the banner — no
   container, no padding, no intro panel, no rounded corners. The
   page reads as: banner → game → manifesto → pillars → positions.
   Visually it looks like the game IS the page; technically it's an
   iframe so the two app shells stay crash- and CSS-isolated.
   The rotate overlay paints when a phone is in portrait mode (the
   game UI is too dense for portrait); CSS-only via @media query,
   no JS listener needed. */
/* Intro panel that sits ABOVE the iframe. Same deep-navy as the
   iframe section so the two read as one continuous block of the
   careers page narrative. Bottom padding stripped so the intro flows
   seamlessly into the iframe below without a gap. */
/* .talento-reto-intro removed — the journey path's closing line
   ("Empieza con un reto") now hands off to the game directly, so the
   intro panel was redundant. */
.talento-reto{
  position:relative;
  background:#0a1623;
  /* No padding — the game stage carries its own internal padding and
     the next section (.talento-find) sets its own top padding, so an
     extra strip here just reads as a mismatched "faldón" below the
     boot: the boot has radial glows + grid, the section padding is
     flat #0a1623, and the eye reads the optical difference as two
     different navies even though the hex is identical. Flush join. */
  padding:0;
}
/* Hide the in-game `.game-embed__bar` (logo + lang toggle) since the
   main site already has both in its own nav. Scoped to the .reto-scope
   wrapper so we don't accidentally hit anything else. */
.reto-scope .game-embed__bar{display:none;}
.reto-scope .game-embed{padding-top:0;padding-bottom:0;}


@media (prefers-reduced-motion: reduce){
  
}

/* Manifesto — dark band, big centred pullquote, small attribution */
.section--manifesto{padding:var(--sp-9) 0;}
.manifesto{display:flex;flex-direction:column;align-items:center;text-align:center;max-width:1020px;}
.manifesto__quote{
  font-family:var(--font-display);font-weight:500;
  font-size:var(--fs-quote);line-height:1.18;letter-spacing:var(--tr-display);
  color:#F5F5F3;margin:var(--sp-6) 0 var(--sp-5);
  text-wrap:balance;
}
.manifesto__caption{
  font-family:var(--font-mono);font-size:13px;
  color:rgba(245,245,243,.55);letter-spacing:.04em;margin:0;
}

/* Three moments — three-up photo grid with a heading + short caption each */
.moments{
  display:grid;grid-template-columns:repeat(3,1fr);
  gap:var(--sp-7);
  margin-top:var(--sp-6);
}
.moments__item{display:flex;flex-direction:column;gap:14px;}
.moments__ph{
  aspect-ratio:4/3;overflow:hidden;background:var(--ai-hairline);
}
.moments__ph img{
  width:100%;height:100%;object-fit:cover;display:block;
  transition:transform 600ms var(--ease-out);
}
.moments__item:hover .moments__ph img{transform:scale(1.04);}
.moments__t{
  font-family:var(--font-display);font-weight:500;font-size:20px;
  letter-spacing:-0.005em;color:var(--fg);margin:6px 0 0;
}
.moments__p{
  font-size:15px;line-height:1.55;color:var(--fg-mid);
  margin:0;max-width:42ch;
}

/* Mentorship — full-bleed photo on the left, copy block on the right,
   same structural pattern as the home Vision memo. */
.section--mentor{padding:0;overflow:hidden;}
.mentor{
  display:grid;grid-template-columns:1fr 1fr;
  gap:0;align-items:stretch;min-height:560px;
}
.mentor__ph{position:relative;overflow:hidden;margin:0;padding:0;}
.mentor__ph img{
  position:absolute;inset:0;
  width:100%;height:100%;object-fit:cover;display:block;
  transition:transform 1200ms var(--ease-out);
}
.mentor__ph:hover img{transform:scale(1.03);}
.mentor__col{
  display:flex;flex-direction:column;justify-content:center;
  padding:var(--sp-9) max(24px, calc((100vw - var(--container)) / 2 + 32px))
          var(--sp-9) var(--sp-8);
}

/* Beyond — two-photo strip with captions */
.beyond{
  display:grid;grid-template-columns:1fr 1fr;
  gap:var(--sp-7);
  margin-top:var(--sp-6);
}

/* Centred CTA wrapped inside the Beyond section (replaces the
   former dark "Listo para el reto" band that sat as its own
   section). Sits below the photo strip with breathing room,
   centre-aligned column, hairline divider above to separate it
   visually from the captions. */
.vida-cta-inline{
  margin-top:var(--sp-8);
  padding-top:var(--sp-6);
  border-top:1px solid var(--ai-hairline);
  display:flex;flex-direction:column;align-items:center;gap:20px;
  text-align:center;
}
.vida-cta-inline__title{max-width:22ch;margin:0;}
.beyond__item{display:flex;flex-direction:column;gap:12px;}
.beyond__ph{
  aspect-ratio:3/2;overflow:hidden;background:var(--ai-hairline);
}
.beyond__ph img{
  width:100%;height:100%;object-fit:cover;display:block;
  transition:transform 600ms var(--ease-out);
}
.beyond__item:hover .beyond__ph img{transform:scale(1.04);}
.beyond__cap{
  font-size:14px;color:var(--fg-mid);line-height:1.5;margin:0;
  font-style:italic;
}

@media (max-width:900px){
  .moments{grid-template-columns:1fr;gap:var(--sp-6);}
  .mentor{grid-template-columns:1fr;min-height:0;}
  .mentor__ph{min-height:280px;}
  .mentor__col{padding:var(--sp-7) 24px;}
  .beyond{grid-template-columns:1fr;gap:var(--sp-6);}
}

/* =========================================================
   Client trust strip — desaturated logos in a left→right marquee.
   Hover any logo to restore colour; hover the strip to pause.
   ========================================================= */
.client-strip{
  background:var(--bg-alt);
  padding:var(--sp-7) 0 var(--sp-8);
  overflow:hidden;
}
.client-strip__head{margin-bottom:var(--sp-6);}

/* Soft fade-out at both edges so logos enter / exit cleanly instead of
   getting clipped against the section background. */
.client-strip__viewport{
  overflow:hidden;
  -webkit-mask-image:linear-gradient(90deg, transparent 0, #000 90px, #000 calc(100% - 90px), transparent 100%);
          mask-image:linear-gradient(90deg, transparent 0, #000 90px, #000 calc(100% - 90px), transparent 100%);
}
.client-strip__track{
  display:flex;align-items:center;gap:80px;
  width:max-content;
  animation:client-marquee 60s linear infinite;
}

.client-strip__item{
  flex-shrink:0;
  /* Per-logo scale is driven by `--logo-scale` (set inline from JS when
     a logo entry has `scale: N`). Defaults to 1 — the original 54×140 box. */
  height:calc(54px * var(--logo-scale, 1));
  min-width:calc(140px * var(--logo-scale, 1));
  display:flex;align-items:center;justify-content:center;
  padding:0 8px;
}
.client-strip__item img{
  max-width:calc(160px * var(--logo-scale, 1));
  max-height:calc(54px * var(--logo-scale, 1));
  width:auto;height:auto;display:block;
  filter:grayscale(1) contrast(.85) opacity(.5);
  /* multiply blends any white background (JPG/WebP logos) into the off-white
     page so the logo sits on the page without a visible rectangle around it. */
  mix-blend-mode:multiply;
  transition:filter 280ms var(--ease-out);
}
.client-strip__item:hover img{
  filter:grayscale(0) contrast(1) opacity(1);
}

/* Placeholder used until a real logo file lands. Renders the client
   name in the brand display face, treated like a wordmark. Gets the
   same grey → colour treatment via colour transition. */
.client-strip__placeholder{
  font-family:var(--font-display);
  font-weight:500;font-size:18px;
  letter-spacing:.04em;text-transform:uppercase;
  color:rgba(17,17,17,.42);
  white-space:nowrap;
  transition:color 280ms var(--ease-out);
}
.client-strip__item:hover .client-strip__placeholder{
  color:var(--accent);
}

@keyframes client-marquee{
  from{transform:translateX(0);}
  to  {transform:translateX(-50%);}
}

@media (prefers-reduced-motion: reduce){
  .client-strip__track{animation:none;}
}
@media (max-width:700px){
  .client-strip__track{gap:48px;animation-duration:42s;}
  .client-strip__item{height:42px;min-width:110px;}
  .client-strip__item img{max-width:120px;max-height:42px;}
  .client-strip__placeholder{font-size:15px;}
}

/* =========================================================
   Article (individual news issue)
   ========================================================= */
.article{padding-top:var(--nav-h);background:#fff;}

/* Hero: full-bleed photo, dark gradient overlay, meta + title + back link */
.article__hero{
  position:relative;
  min-height:480px;
  background-size:cover;background-position:center;
  display:flex;align-items:flex-end;
  padding:var(--sp-9) 0 var(--sp-8);
  color:#F5F5F3;
}
.article__hero-ov{
  position:absolute;inset:0;
  background:linear-gradient(180deg, rgba(13,27,42,.35) 0%, rgba(13,27,42,.85) 100%);
}
.article__hero-inner{position:relative;z-index:1;display:flex;flex-direction:column;gap:18px;}
.article__back{
  align-self:flex-start;
  font-family:var(--font-mono);font-size:12px;letter-spacing:.06em;
  color:rgba(245,245,243,.7);cursor:pointer;
  transition:color 200ms var(--ease-out);
  text-decoration:none;
}
.article__back:hover{color:#FFFFFF;}
.article__meta{
  display:flex;align-items:center;gap:14px;flex-wrap:wrap;
  font-family:var(--font-mono);font-size:12px;letter-spacing:.06em;
  color:rgba(245,245,243,.75);
}
.article__meta-n{color:var(--ai-blue-300);font-weight:600;}
.article__meta-tag{
  text-transform:uppercase;letter-spacing:.14em;font-size:11px;font-weight:600;
  color:var(--ai-blue-300);
  padding-left:14px;border-left:1px solid rgba(245,245,243,.25);
}
.article__meta-read{
  margin-left:auto;text-transform:uppercase;letter-spacing:.14em;
  font-size:11px;color:rgba(245,245,243,.5);
}
.article__title{
  font-family:var(--font-display);font-weight:500;
  font-size:var(--fs-display);line-height:1.05;letter-spacing:var(--tr-display);
  color:#F5F5F3;margin:0;max-width:920px;text-wrap:balance;
}

/* Body — narrow readable column, blocks rendered by ArticleBlock switch */
.article__body{
  max-width:760px;
  padding:var(--sp-9) var(--gutter);
  display:flex;flex-direction:column;
}
/* Area intro — the block list that opens every area page, directly under
   the hero reel. Same reading measure as an article body so the two share
   a rhythm, but no vertical padding of its own: the wrapping .section
   already supplies it. */
/* The reading measure is capped on the BLOCKS, not on the container. The
   container keeps its own max-width and auto margins, so the copy starts at
   exactly the same gutter as the hero headline and the CTA below it —
   narrowing the container instead re-centred the column and left the three
   starting at three different x positions. */
.sector-body{
  display:flex;flex-direction:column;
}
/* La columna de texto va centrada en la página, no pegada al borde
   izquierdo. El ancho máximo se mantiene —760 px es lo que se lee
   cómodo— y lo que cambia es dónde se coloca esa columna dentro del
   contenedor. El texto sigue alineado a la izquierda dentro de ella:
   centrar párrafos largos se lee mal. Vale para las cuatro áreas. */
.sector-body > *{max-width:760px;margin-left:auto;margin-right:auto;}
.article-block{margin:0;}
/* La entradilla iba a 18 px con peso 400 y el cuerpo a 16 px con peso
   400: dos píxeles de diferencia y nada más, así que se leían como el
   mismo texto. Ahora las separan el tamaño y el trazo —más grande y más
   fina—, que es lo que distingue una entradilla sin recurrir al color:
   apagarle el tono al cuerpo habría estropeado el contraste sobre los
   fondos oscuros de las áreas. */
.article-block--lede{
  font-size:clamp(19px, 1.5vw, 22px);
  line-height:1.5;
  font-weight:var(--fw-light);
  letter-spacing:-0.011em;
  color:var(--fg);
  margin-bottom:var(--sp-6);
}
.article-block--p{
  font-size:var(--fs-body);
  line-height:var(--lh-body);
  color:var(--fg);
  margin-bottom:var(--sp-5);
}
.article-block--h2{
  font-family:var(--font-display);font-weight:500;
  font-size:var(--fs-h2);line-height:var(--lh-heading);letter-spacing:var(--tr-display);
  color:var(--fg);
  margin:var(--sp-7) 0 var(--sp-4);
  text-wrap:balance;
}
.article-block--h3{
  font-family:var(--font-display);font-weight:600;
  font-size:var(--fs-h3);line-height:1.3;
  color:var(--fg);
  margin:var(--sp-6) 0 var(--sp-3);
}
/* Menos aire alrededor: 48 px arriba y abajo dejaban la foto flotando
   lejos del texto al que acompaña. Y un desbordamiento lateral pequeño
   —24 px por lado— para que respire algo más ancha que la columna sin
   despegarse de ella. */
.article-block--image{
  margin:var(--sp-6) calc(-1 * var(--sp-5)) var(--sp-6);
  display:flex;flex-direction:column;gap:10px;
}
.article-block--image img{
  width:100%;height:auto;display:block;
}

/* Imagen a sangre: rompe la columna de lectura y llega a los dos bordes.
   La columna va centrada dentro del contenedor, así que basta con
   anularle el ancho máximo y estirarla con márgenes negativos hasta el
   borde de la ventana. El recuadro exterior lleva overflow-x:clip para
   que el ancho de la barra de desplazamiento no saque una barra
   horizontal —100vw la cuenta y el contenido no—. clip y no hidden:
   hidden crea un contexto de desplazamiento y rompería cualquier
   posicionamiento pegajoso de dentro. */
.sector-copy{overflow-x:clip;}
.sector-body > .reveal--wide{
  max-width:none;width:auto;
  margin-left:calc(50% - 50vw);
  margin-right:calc(50% - 50vw);
}
.sector-body > .reveal--wide .article-block--image{margin-left:0;margin-right:0;}

/* Entrada de las imágenes del cuerpo: la foto se descubre de arriba
   abajo mientras cede un punto de escala. Es el gesto de una cortina que
   sube, no un elemento que aterriza, y encaja con el ritmo de la sección
   en vez de competir con él.

   reveal--media anula el desplazamiento del reveal genérico para que no
   se sumen dos movimientos a la vez. Lo pone PageSector a cualquier
   bloque de tipo imagen, así que una foto añadida desde el CMS lo
   hereda sin tocar nada. */
.reveal--media{transform:none;}
.reveal--media .article-block--image img{
  clip-path:inset(0 0 100% 0);
  transform:scale(1.045);
  transition:clip-path 900ms var(--ease-out), transform 1400ms var(--ease-out);
  will-change:clip-path, transform;
}
.reveal--media.is-revealed .article-block--image img{
  clip-path:inset(0 0 0 0);
  transform:scale(1);
}
.reveal--media .article-block--image figcaption{
  opacity:0;
  transition:opacity 600ms var(--ease-out) 400ms;
}
.reveal--media.is-revealed .article-block--image figcaption{opacity:1;}
.article-block--image figcaption{
  font-size:var(--fs-body-sm);color:var(--fg-mid);
  font-style:italic;line-height:1.5;
  padding-left:4px;
}
/* Link and document blocks. Same anatomy — a rule-underlined anchor with a
   trailing glyph — so a body reads consistently whichever an editor picks.
   The arrow says "goes somewhere", the caret says "downloads". */
.article-block--link,
.article-block--file{margin:0 0 var(--sp-5);}
.article-block--link a,
.article-block--file a{
  display:inline-flex;align-items:center;gap:10px;
  font-family:var(--font-sans);font-size:var(--fs-body);font-weight:500;
  color:var(--accent);text-decoration:none;
  border-bottom:1px solid currentColor;padding-bottom:2px;
  transition:color 180ms var(--ease-out);
}
.article-block--link a:hover,
.article-block--file a:hover{color:var(--accent-hover);}
.article-block__ic{transition:transform 180ms var(--ease-out);}
.article-block--link a:hover .article-block__ic{transform:translateX(3px);}
.article-block--file a:hover .article-block__ic{transform:translateY(2px);}

.article-block--quote{
  font-family:var(--font-display);font-weight:500;
  font-size:var(--fs-quote);line-height:1.2;letter-spacing:var(--tr-display);
  color:var(--fg);
  margin:var(--sp-8) 0;padding-left:var(--sp-5);
  border-left:var(--bd-accent-left);
  text-wrap:pretty;
}

@media (max-width:700px){
  .article__hero{min-height:360px;padding:var(--sp-8) 0 var(--sp-6);}
  .article__title{font-size:32px;}
  .article-block--image{margin-left:0;margin-right:0;}
  .article-block--h2{margin-top:var(--sp-6);}
}

/* =========================================================
   News page — articles list + editorial note
   ========================================================= */
.newsletter{max-width:900px;margin:0 auto;}

.newsletter__archive{
  list-style:none;margin:0;padding:0;
  display:flex;flex-direction:column;
  border-top:1px solid var(--ai-hairline);
}
.newsletter__issue{
  padding:var(--sp-6) 0;
  border-bottom:1px solid var(--ai-hairline);
  display:grid;grid-template-columns:220px 1fr;gap:28px;
  align-items:start;
}

/* Thumbnail — sharp 4:3 crop, mild zoom on hover */
.newsletter__issue-thumb{
  display:block;aspect-ratio:4/3;overflow:hidden;
  background:var(--ai-hairline);cursor:pointer;
}
.newsletter__issue-thumb img{
  width:100%;height:100%;object-fit:cover;display:block;
  transition:transform 600ms var(--ease-out);
}
.newsletter__issue:hover .newsletter__issue-thumb img{transform:scale(1.04);}

.newsletter__issue-body{
  display:flex;flex-direction:column;gap:10px;min-width:0;
}
.newsletter__issue-meta{
  display:flex;align-items:center;gap:14px;flex-wrap:wrap;
  font-family:var(--font-mono);font-size:12px;
  letter-spacing:.06em;color:var(--fg-mid);
}
.newsletter__issue-n{color:var(--accent);font-weight:600;}
.newsletter__issue-tag{
  text-transform:uppercase;letter-spacing:.14em;
  font-size:11px;font-weight:600;color:var(--accent);
  padding-left:14px;border-left:1px solid var(--ai-hairline);
}
.newsletter__issue-read{
  margin-left:auto;text-transform:uppercase;letter-spacing:.14em;
  font-size:11px;color:var(--ai-text-muted);
}
.newsletter__issue-title{
  font-family:var(--font-display);font-weight:500;font-size:24px;
  letter-spacing:-0.005em;line-height:1.25;
  color:var(--fg);text-wrap:balance;
  cursor:pointer;display:inline-flex;align-items:baseline;gap:12px;
  transition:color 200ms var(--ease-out);
}
.newsletter__issue-title:hover{color:var(--accent);}
.newsletter__issue-title .arr{
  font-size:18px;opacity:0;transform:translateX(-4px);
  transition:all 220ms var(--ease-out);color:var(--accent);
}
.newsletter__issue:hover .newsletter__issue-title .arr{
  opacity:1;transform:translateX(0);
}
.newsletter__issue-excerpt{
  font-size:14px;line-height:1.6;color:var(--fg-mid);
  margin:0;max-width:60ch;
}

@media (max-width:700px){
  /* Stack instead of the 120px + 1fr split. At 375px that split left the
     text column 173px wide, which is not enough for these headlines — the
     GSK one broke "BSL-4" across two lines. Stacked, the title gets the
     full 311px and the thumbnail stops being a stamp. 16/9 rather than the
     4/3 used beside the text, so a full-width image does not eat the
     screen. */
  .newsletter__issue{grid-template-columns:1fr;gap:14px;}
  .newsletter__issue-thumb{aspect-ratio:16/9;}
  .newsletter__issue-title{font-size:21px;}
  .newsletter__issue-excerpt{display:none;}
  .newsletter__issue-meta{gap:10px;font-size:11px;}
}

/* Article page. The body carried 96px of top padding on a phone, which put
   124px of empty white between the header photo and the first sentence —
   most of a screen spent on nothing. The hero also ran the title to within
   4px of its own bottom edge. */
@media (max-width:700px){
  .article__body{padding-top:var(--sp-7);}
  .article__hero{min-height:320px;padding-bottom:var(--sp-5);}
}

/* =========================================================
   Project-detail page (PageProject)
   ========================================================= */
.pdetail__hero{
  position:relative;
  min-height:460px;
  background-size:cover;background-position:center;
  display:flex;align-items:flex-end;
  padding:var(--sp-9) 0 var(--sp-8);
  color:#F5F5F3;
}
.pdetail__hero-ov{
  position:absolute;inset:0;
  background:linear-gradient(180deg, rgba(13,27,42,.30) 0%, rgba(13,27,42,.88) 100%);
}
.pdetail__hero-inner{position:relative;z-index:1;display:flex;flex-direction:column;gap:16px;}
.back-link--light{color:rgba(245,245,243,.78);border-bottom-color:rgba(245,245,243,.4);}
.back-link--light:hover{color:#FFFFFF;}
.pdetail__cat{
  font-family:var(--font-mono);font-size:12px;letter-spacing:.10em;text-transform:uppercase;
  color:var(--accent-on-dark);
}
.pdetail__title{
  font-family:var(--font-display);font-weight:500;
  font-size:var(--fs-display);line-height:1.05;letter-spacing:-0.01em;
  margin:0;max-width:16ch;text-wrap:balance;
}
.pdetail__loc{
  font-family:var(--font-sans);font-weight:300;font-size:17px;
  color:rgba(245,245,243,.74);margin:0;
}

/* Facts — definition grid */
.pdetail__facts{
  display:grid;grid-template-columns:repeat(3,1fr);gap:1px;
  margin:0;background:var(--ai-hairline);
  border:1px solid var(--ai-hairline);
}
.pdetail__fact{background:var(--bg);padding:var(--sp-5) var(--sp-5);}
.pdetail__fact-k{
  font-family:var(--font-mono);font-size:11px;letter-spacing:.10em;text-transform:uppercase;
  color:var(--fg-mid);margin:0 0 8px;
}
.pdetail__fact-v{
  font-family:var(--font-display-book);font-size:21px;line-height:1.25;
  color:var(--fg);margin:0;
}
@media (max-width:900px){.pdetail__facts{grid-template-columns:repeat(2,1fr);}}
@media (max-width:560px){.pdetail__facts{grid-template-columns:1fr;}}

/* Scope */
.pdetail__scope{max-width:780px;}
.pdetail__scope-text{
  font-family:var(--font-display-book);font-weight:300;
  font-size:clamp(22px,2.2vw,30px);line-height:1.4;
  color:var(--fg-on-dark);margin:18px 0 0;text-wrap:pretty;
}

/* CTA */
.pdetail__cta{max-width:680px;text-align:center;display:flex;flex-direction:column;align-items:center;gap:18px;}

@media (max-width:700px){
  .pdetail__hero{min-height:340px;padding:var(--sp-8) 0 var(--sp-6);}
  .pdetail__title{font-size:34px;}
}

/* ── Sector pages: unified deep-navy treatment ───────────────────────────
   Every section on a sector page sits on the same #0a1623 backdrop. We
   redefine the colour-token swatches inside the data-screen-label="sector"
   wrapper so existing section variants (light / alt / dark) all inherit
   the navy bg and on-dark text without touching the markup of each
   sector child. --accent stays as the brand blue so CTAs/links still
   read as interactive. */
[data-screen-label="sector"]{
  --bg:#0a1623;
  --bg-alt:#0a1623;
  --bg-dark:#0a1623;
  --fg:var(--fg-on-dark);
  --fg-mid:var(--fg-on-dark-mid);
  background:#0a1623;
}
/* The body copy and the CTA sit on ONE continuous navy surface, with no
   edge between them, so their stacked 128px paddings read as dead space
   rather than as separation between two panels. Collapse the seam: 256px
   of gap becomes 96px. Only on sector pages — elsewhere the sections do
   have contrasting backgrounds and need the full breathing room. */
[data-screen-label="sector"] .sector-copy{padding-bottom:var(--sp-7);}
[data-screen-label="sector"] .section--accent{padding-top:var(--sp-7);}
/* Tighter still on phones, where 48+48 plus the band's own inset left
   128px between the last paragraph and the CTA heading — a lot of empty
   navy on a small screen. */
@media (max-width:600px){
  [data-screen-label="sector"] .sector-copy{padding-bottom:var(--sp-5);}
  [data-screen-label="sector"] .section--accent{padding-top:var(--sp-5);}
}

/* The accent CTA section uses var(--accent) directly for its bg — flip
   it to navy too so there's no remaining island of a different colour. */
[data-screen-label="sector"] .section--accent{
  background:#0a1623;
}
/* Section titles that opted out of the token system with a hard light
   colour are already fine. The `.section__title` default reads
   var(--fg), which now resolves to on-dark — automatic. */

/* ── Legal pages (cookies, privacidad, aviso legal) ────────────────────
   Long-form policy pages rendered by PageLegal. Light editorial layout
   with a constrained reading column, generous line-height, and a small
   "back" anchor at the top. Block types — h2/h3, paragraphs, lists,
   tables — share a coherent typographic scale. */
.legal{
  background:var(--bg);
  color:var(--fg);
  min-height:100vh;
  padding-top:calc(var(--nav-h) + var(--sp-6));
  padding-bottom:var(--sp-9);
}
.legal__inner{
  max-width:780px;
  margin:0 auto;
}
.legal__back{
  display:inline-block;
  margin-bottom:var(--sp-5);
  font-size:13px;letter-spacing:.04em;
  color:var(--fg-mid);
  cursor:pointer;
  transition:color 180ms var(--ease-out);
}
.legal__back:hover{color:var(--accent);}
.legal__title{
  font-family:var(--font-display);font-weight:500;
  font-size:clamp(32px, 4vw, 56px);
  line-height:1.05;letter-spacing:-0.02em;
  margin:8px 0 var(--sp-6);
  color:var(--fg);
}
.legal__body{
  font-size:15px;line-height:1.7;
  color:var(--fg);
}
.legal__h2{
  font-family:var(--font-display);font-weight:500;
  font-size:clamp(22px, 2.2vw, 28px);
  line-height:1.2;letter-spacing:-0.01em;
  margin:var(--sp-7) 0 var(--sp-3);
  color:var(--fg);
}
.legal__h3{
  font-family:var(--font-sans);font-weight:600;
  font-size:16px;
  letter-spacing:0;
  margin:var(--sp-5) 0 var(--sp-2);
  color:var(--fg);
}
.legal__p{
  margin:0 0 14px;
}
.legal__p a,
.legal__ul li a{
  color:var(--accent);text-decoration:underline;
  text-underline-offset:2px;text-decoration-thickness:1px;
}
.legal__p a:hover,
.legal__ul li a:hover{color:var(--accent-hover);}
.legal__ul{
  margin:0 0 16px;
  padding-left:22px;
}
.legal__ul li{
  margin-bottom:6px;
  line-height:1.6;
}
.legal__table-wrap{
  overflow-x:auto;
  margin:var(--sp-3) 0 var(--sp-5);
  border:1px solid rgba(15,30,50,.1);
  border-radius:8px;
}
.legal__table{
  width:100%;
  border-collapse:collapse;
  font-size:13px;
}
.legal__table th,
.legal__table td{
  text-align:left;
  padding:10px 14px;
  border-bottom:1px solid rgba(15,30,50,.08);
}
.legal__table th{
  background:var(--bg-alt);
  font-size:11px;letter-spacing:.12em;text-transform:uppercase;font-weight:600;
  color:var(--fg-mid);
}
.legal__table tr:last-child td{border-bottom:0;}

@media (max-width:600px){
  .legal{padding-top:calc(var(--nav-h) + var(--sp-5));}
  .legal__body{font-size:14px;}
}

/* Footer legal-link cluster — tiny clickable anchors that route to the
   policy pages. Inherits the footer's existing typography. */
.ai-footer__legal-links{
  display:inline;
}
/* Sin color propio, estos enlaces heredaban el azul de enlace pensado
   para fondo claro y quedaban en 2,29:1 sobre el pie, que es casi negro.
   Se les da el claro del propio pie: sigue leyéndose como enlace —el
   hover lo lleva a blanco— pero ya no se pierde contra el fondo. */
.ai-footer__legal-link{
  cursor:pointer;
  color:rgba(245,245,243,.72);
  transition:color 180ms var(--ease-out);
}
.ai-footer__legal-link:hover{color:#FFFFFF;}
.ai-footer__legal-sep{
  opacity:.4;
}
/* Cookie bar's "Política de Cookies" inline link — uses the bar's own
   underline-on-hover treatment. */
.cookie__link{
  cursor:pointer;
  text-decoration:underline;
  text-underline-offset:2px;
}

/* ── Isometric drawing pace ─────────────────────────────────────────────
   Kept at the end of the file on purpose: .vt-block is declared in four
   places above and .vt-axis in two, so this is the only position where the
   slower timing actually wins. Same 1.5x as the text column beside it, so
   the drawing and the copy change together rather than the drawing
   arriving first. */
@media (min-width: 901px){
  .vt-axis line{transition:all 720ms var(--ease-out);}
  .vt-block{transition:transform 900ms var(--ease-out), opacity 720ms var(--ease-out);}
}
@media (prefers-reduced-motion: reduce){
  .vt-axis line,.vt-block{transition-duration:1ms !important;}
}
