/* ==========================================================================
   Header — overlays the hero's video stage as a plain transparent bar with a
   dark scrim for legibility (nav text + logo flip to white/inverted), then
   settles into a solid paper backing + ink text once scrolled past the hero.
   ========================================================================== */

.site-header {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 100;
  height: var(--header-height);
  display: flex;
  align-items: center;
  background: transparent;
  transition: background-color 0.25s ease, box-shadow 0.25s ease;
}

.site-header::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 240%;
  /* Strengthened per direct client feedback (2026-08-15): the logo mark
     (circled over the solar-aerial hero frame) wasn't reading clearly —
     that clip's bright, light-blue/white panels washed out the previous
     0.5-opacity single-stop fade by the time it reached the header's own
     height. The added 42% mid-stop (roughly where the header bar's own
     bottom edge sits inside this 240%-tall gradient) keeps the scrim
     strong across the full header height regardless of what's playing
     behind it, instead of only guaranteeing contrast right at the top. */
  background: linear-gradient(to bottom, rgba(10, 8, 6, 0.78) 0%, rgba(10, 8, 6, 0.55) 42%, rgba(10, 8, 6, 0) 100%);
  pointer-events: none;
  opacity: 1;
  transition: opacity 0.25s ease;
  z-index: -1;
}

.site-header.is-scrolled {
  background: rgba(247, 247, 245, 0.92);
  backdrop-filter: blur(10px);
  box-shadow: 0 1px 0 rgba(34,26,20,0.08);
}

.site-header.is-scrolled::before { opacity: 0; }

/* Load intro — nav reveal is deliberately separate from and delayed
   after the hero reveal (js/animations.js), same as Virya's real
   header.hidden → header split-timing. Static/unconditional so the
   header doesn't flash visible before the intro script runs. */
.site-header.header--intro { opacity: 0; }

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 56px;
  width: 100%;
}

.site-logo img {
  height: 28px;
  width: auto;
  filter: brightness(0) invert(1);
  transition: filter 0.25s ease;
}

.site-header.is-scrolled .site-logo img { filter: none; }

.site-nav {
  display: flex;
  align-items: center;
  flex: 1;
  justify-content: space-between;
  gap: 40px;
}

/* Links centered in the space between the logo and the lang switch/CTA,
   rather than clustering as a tight right-aligned group. */
.site-nav__list {
  display: flex;
  align-items: center;
  list-style: none;
  flex: 1;
  justify-content: center;
  gap: 36px;
  padding: 0;
}

.nav-actions {
  display: flex;
  align-items: center;
  gap: 20px;
}

.site-nav__list a {
  color: var(--white);
  font-size: 15px;
  font-weight: 400;
  opacity: 0.85;
  padding: 6px 0;
  border-bottom: 2px solid transparent;
  transition: color 0.25s ease, opacity 0.15s ease, border-color 0.15s ease;
}

.site-nav__list a:hover { opacity: 1; border-color: var(--sungwon-red); }

.site-header.is-scrolled .site-nav__list a { color: var(--ink); }

.lang-switch { position: relative; }

.lang-switch__toggle {
  display: flex;
  align-items: center;
  gap: 4px;
  background: none;
  border: none;
  color: var(--white);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  padding: 6px 4px;
  transition: color 0.25s ease;
}

.site-header.is-scrolled .lang-switch__toggle { color: var(--ink); }

.lang-switch__menu {
  position: absolute;
  top: 100%; right: 0;
  background: var(--white);
  border-radius: 6px;
  box-shadow: 0 12px 32px rgba(14,26,43,0.22);
  padding: 6px;
  min-width: 120px;
  display: flex;
  flex-direction: column;
  transform-origin: top right;
  transform: scale(0.95) translateY(-4px);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: transform 0.15s ease-out, opacity 0.15s ease-out, visibility 0s linear 0.15s;
}

.lang-switch.is-open .lang-switch__menu {
  transform: scale(1) translateY(0);
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transition: transform 0.15s ease-out, opacity 0.15s ease-out, visibility 0s linear 0s;
}

@media (prefers-reduced-motion: reduce) {
  .lang-switch__menu { transform: none; }
  .lang-switch.is-open .lang-switch__menu { transform: none; }
}

.lang-switch__option {
  padding: 8px 10px;
  border-radius: 4px;
  color: var(--graphite);
  font-size: 14px;
}

.lang-switch__option:hover { background: var(--drafting-white); }
.lang-switch__option.is-active { color: var(--sungwon-red); font-weight: 600; }

.nav-toggle {
  display: none;
  background: none;
  border: none;
  width: 32px; height: 24px;
  flex-direction: column;
  justify-content: space-between;
  cursor: pointer;
  padding: 0;
}

.nav-toggle span {
  display: block;
  height: 2px;
  background: var(--white);
  border-radius: 2px;
  transition: background-color 0.25s ease;
}

.site-header.is-scrolled .nav-toggle span { background: var(--ink); }

/* Own breakpoint, wider than the sitewide 900px content-stacking one used
   everywhere else in this file — found via mobile review (2026-08-15):
   the desktop nav (5 links + lang switch + CTA) doesn't have room between
   901px and ~950px, so "Áreas de negocio" wraps to 2-3 lines and the
   header visibly misaligns/grows taller. That range isn't a devtools
   edge case — it's real phone-landscape width (e.g. iPhone 14 Pro Max
   landscape is 932px), so testing the site in a browser's mobile/
   responsive mode in landscape orientation landed exactly in this dead
   zone: no hamburger (only shows under 900px) and a cramped, wrapping
   desktop nav instead. 1024px covers every common phone width in either
   orientation plus small tablets in portrait; confirmed the full desktop
   nav still fits comfortably at 1024px+ before widening this. */
@media (max-width: 1024px) {
  .site-nav {
    display: flex;
    position: fixed;
    top: var(--header-height);
    left: 0; right: 0;
    flex-direction: column;
    align-items: stretch;
    background: var(--paper);
    padding: 8px 20px 24px;
    box-shadow: 0 12px 24px rgba(34,26,20,0.14);
    transform: translateY(-8px);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: transform 0.2s ease-out, opacity 0.2s ease-out, visibility 0s linear 0.2s;
  }

  .site-nav.is-open {
    transform: translateY(0);
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transition: transform 0.2s ease-out, opacity 0.2s ease-out, visibility 0s linear 0s;
  }

  .site-nav { justify-content: flex-start; }

  /* align-items: stretch overrides the base (desktop row) rule's
     align-items: center — without it, each <li> shrink-wraps to its own
     link text and centers in the column instead of spanning full width,
     which left every mobile menu link looking like a narrow floating
     label with a short underline instead of a proper full-width row
     (also found during the 2026-08-15 mobile review). */
  .site-nav__list {
    flex: none;
    flex-direction: column;
    justify-content: flex-start;
    align-items: stretch;
    gap: 0;
    width: 100%;
  }

  .site-nav__list a,
  .site-header.is-scrolled .site-nav__list a {
    display: block;
    padding: 14px 0;
    border-bottom: 1px solid rgba(34,26,20,0.1);
    color: var(--ink);
  }

  .nav-actions {
    flex-direction: column;
    align-items: stretch;
    gap: 12px;
    margin-top: 12px;
  }

  .lang-switch { align-self: flex-start; }

  /* Desktop anchors the dropdown with right:0 because the toggle sits near
     the header's right edge there, so the menu safely expands leftward.
     On mobile the toggle is left-aligned near the screen edge instead
     (align-self: flex-start above), so that same right:0 anchor pushed the
     120px-wide menu off the left edge of the viewport (found via mobile
     review, 2026-08-15) — flip the anchor to expand rightward instead. */
  .lang-switch__menu { left: 0; right: auto; transform-origin: top left; }

  .lang-switch__toggle,
  .site-header.is-scrolled .lang-switch__toggle { color: var(--ink); }

  .nav-toggle { display: flex; }
}

/* ==========================================================================
   Heading accents — one consistent color technique reused at the hero,
   áreas de negocio, and proyectos headlines: same real copy, split by color
   to read with more confidence (never a rewrite, only a two-tone treatment).
   ========================================================================== */

.hl-accent { color: var(--sungwon-red); }

.heading-split__muted {
  color: var(--steel-gray);
  font-weight: 500;
}

/* Pill buttons — used across the homepage's bolder, Virya-referenced sections
   without changing the global --button-radius the rest of the site still uses. */
.btn--pill { border-radius: 100px; }

/* ==========================================================================
   Hero — full-bleed cycling video with white overlay text; on scroll
   (desktop only, see js/animations.js) the video shrinks into one big,
   straight-aligned card (no photos, no rotation — see .hero__video-wrap
   below) while the headline fades out and the "Desde 2010..." copy fades
   in beneath the card.
   ========================================================================== */

.hero {
  position: relative;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  overflow: hidden;
  background: var(--paper);
  padding-top: var(--header-height);
  /* Load intro (js/animations.js) reveals this — kept invisible
     unconditionally (not behind a toggle class) so there's no flash of
     the fully-built hero before that script runs; our <script> tags sit
     at the end of <body>, unlike Virya's server-rendered hidden state. */
  opacity: 0;
}

.hero__video-wrap {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
  z-index: 1;
}

.hero__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 0.7s ease;
}

.hero__video.is-active {
  opacity: 1;
}

.hero__video-scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(18, 14, 11, 0.32) 0%, rgba(18, 14, 11, 0.1) 42%, rgba(18, 14, 11, 0.58) 100%);
}

.hero__collage { display: none; }
.hero__img { display: none; }

.hero__collage-copy {
  position: relative;
  z-index: 4;
  max-width: 46ch;
  margin: 0 auto;
  padding: 0 24px 56px;
  color: var(--white);
  font-size: 16px;
  line-height: 1.6;
}

@media (min-width: 1101px) {
  .hero__collage {
    display: block;
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
  }

  .hero__img {
    display: block;
    position: absolute;
    object-fit: cover;
    border-radius: var(--card-radius);
    box-shadow: 0 20px 50px rgba(18, 14, 11, 0.3);
  }

  /* .hero__img--1/--5 rules below are kept only for
     archive/hero-static-collage-v1.html's benefit (see that file's own
     header comment — it depends on these classes still existing) — the
     live hero no longer places any .hero__img elements in its markup.
     Second round of direct client feedback (2026-08-15): reducing the
     scattered photos from 4 to 2 still read as "split into pieces"
     ("5개로 쪼개지는 거는 안해도 됨" was about the fragmenting/scatter
     itself, not the count). Replaced the whole fly-in-photos idea with
     the video settling into one big, straight (non-rotated) card instead
     — see .hero__video-wrap below. */
  .hero__img--1 { top: 10%;  left: 27%; width: clamp(150px, 15vw, 210px);   aspect-ratio: 0.8;  transform: rotate(-9deg); z-index: 1; }
  .hero__img--5 { top: 46%;  left: 61%; width: clamp(140px, 14vw, 195px);   aspect-ratio: 1;    transform: rotate(-6deg); z-index: 2; }

  /* Big, straight-aligned card (not edge-to-edge) — replaces the earlier
     small rotated card + flanking photos. 60%-width/20%-left is plain
     percentage math (20+60+20=100) so the card sits exactly centered
     without needing a translate(-50%)-style centering transform — same
     "plain top/left, no percentage translate" constraint as the old
     .hero__img rules above, since GSAP's x/y FLIP animation discards any
     translate() already on the element the first time it takes over.
     Height is a fixed 44vh (not aspect-ratio-derived from width) so the
     card's bottom edge sits at a predictable 12%+44vh regardless of
     window width — an aspect-ratio-based height scales with vw, which on
     a wide-but-short real browser window (not just a short devtools
     viewport) pushed the card low enough to collide with
     .hero__collage-copy's text below it. .hero__video already has
     object-fit:cover, so a shorter box than the source's 16:9 just crops
     a bit more — no letterboxing risk either way. */
  .hero__video-wrap {
    position: absolute;
    inset: auto;
    top: 12%;
    left: 20%;
    width: 60%;
    height: 44vh;
    z-index: 3;
    border-radius: var(--card-radius);
    transform: none;
    box-shadow: 0 24px 60px rgba(18, 14, 11, 0.34);
  }

  /* top (not bottom) anchored, computed straight off .hero__video-wrap's
     own fixed 12%+44vh box so there's always a guaranteed ~40px gap below
     the card no matter the paragraph's wrapped line count or the
     viewport's height — bottom-anchoring here previously left the actual
     gap dependent on both the card's (width-derived, so vw-sensitive)
     height and the text's own height, which on a real, shorter browser
     window (not just devtools) collapsed to the two visibly touching. */
  .hero__collage-copy {
    position: absolute;
    left: 0;
    right: 0;
    top: calc(12% + 44vh + 40px);
    max-width: 54ch;
    margin: 0 auto;
    z-index: 4;
    padding: 0 24px;
    color: var(--ink);
  }
}

@media (prefers-reduced-motion: reduce) and (max-width: 900px) {
  .site-nav { transform: none; }
  .site-nav.is-open { transform: none; }
}

.hero__content {
  position: relative;
  z-index: 4;
  color: var(--white);
  max-width: 680px;
  margin: 0 auto;
  padding-top: 8px;
  padding-bottom: 72px;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.hero__cycle-line {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.8);
  margin-bottom: 22px;
}

.hero__cycle {
  position: relative;
  height: 1.3em;
  min-width: 13ch;
  flex-shrink: 0;
  overflow: hidden;
  display: inline-block;
  text-align: left;
}

.hero__cycle-track {
  position: absolute;
  top: 0;
  left: 0;
  display: flex;
  flex-direction: column;
}

.hero__cycle-item {
  height: 1.3em;
  line-height: 1.3em;
  color: var(--sungwon-red);
  font-weight: 600;
  white-space: nowrap;
}

.hero__content h1 {
  max-width: 34ch;
  margin-bottom: 28px;
}

.hero__headline {
  font-size: clamp(2.1rem, 1.5rem + 2.4vw, 3.5rem);
  font-weight: 500;
  line-height: 1.1;
  max-width: 17ch;
  margin-left: auto;
  margin-right: auto;
}

.hero__buttons {
  display: flex;
  justify-content: center;
  gap: 14px;
  flex-wrap: wrap;
  margin-bottom: 28px;
}

/* ==========================================================================
   Service cards — "Áreas de negocio". Real photography for the three proven
   disciplines; a distinct graphic/gradient treatment (no stock or borrowed
   photos passed off as real work) for the two newly added areas.
   ========================================================================== */

/* Draggable Swiper carousels — the same horizontal-drag pattern Virya's real
   .items-slider / .projects-slider use, instead of a static CSS grid. */
.items-slider { position: relative; }

.items-swiper, .projects-swiper {
  overflow: visible;
  padding-bottom: 8px;
}

.items-swiper .swiper-slide,
.projects-swiper .swiper-slide {
  flex-shrink: 0;
  height: auto;
}

.items-swiper .swiper-slide { width: 280px; }
.projects-swiper .swiper-slide { width: 420px; }

@media (max-width: 560px) {
  .items-swiper .swiper-slide { width: 78vw; }
  .projects-swiper .swiper-slide { width: 72vw; }
}

.items-slider__scrollbar.swiper-scrollbar {
  position: relative;
  width: 160px;
  height: 4px;
  margin: 32px auto 0;
  background: var(--warm-gray-light);
  border-radius: 100px;
  opacity: 1;
}

.items-slider__scrollbar .swiper-scrollbar-drag {
  background: var(--sungwon-red);
  border-radius: 100px;
}

.service-card {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  border-radius: 20px;
  background: var(--white);
  border: 1px solid rgba(14,26,43,0.08);
  color: var(--graphite);
  min-height: 400px;
  padding: 32px 26px;
  transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
}

@media (hover: hover) and (pointer: fine) {
  .service-card:hover {
    transform: translateY(-4px);
    box-shadow: 0 20px 40px rgba(14,26,43,0.10);
    border-color: rgba(14,26,43,0.14);
  }
}

/* Video always visible (poster frame at rest, plays on hover) — the photo/
   video itself is no longer gated behind interaction per direct client
   feedback (2026-08-15): "그냥 사진이 보이게 해주세요" (just show the photo).
   The <video> carries a poster="" attribute (a real extracted frame of the
   same clip) so a still frame renders before the lazy-loaded src is
   fetched on hover; js/animations.js's existing mouseenter/mouseleave
   play/pause logic is unchanged, so hovering still plays the clip exactly
   like before. */
.service-card__media {
  position: absolute;
  inset: 0;
  z-index: 0;
}

.service-card__media video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.service-card__scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(18,14,11,0.15) 0%, rgba(18,14,11,0.35) 55%, rgba(18,14,11,0.82) 100%);
}

.service-card__icon-badge {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 52px; height: 52px;
  border-radius: 14px;
  background: rgba(255,255,255,0.16);
  color: var(--white);
}

.service-card__icon-badge svg { width: 26px; height: 26px; }

.service-card__body {
  position: relative;
  z-index: 1;
  margin-top: 32px;
  transition: color 0.3s ease;
}

.service-card__label {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 20px;
  font-weight: 600;
  color: var(--white);
  margin-bottom: 10px;
  transition: color 0.3s ease;
}

.service-card__body p {
  color: var(--white);
  font-size: 15px;
  transition: color 0.3s ease, opacity 0.35s ease, transform 0.35s ease, max-height 0.35s ease, margin-top 0.35s ease;
}

/* Hover-only reveal of the description, like Virya's real cards — only for
   hover-capable pointers. Touch devices have no hover to reveal it with, so
   they keep the description always visible (unchanged mobile behavior).
   Collapsed via max-height (not just opacity) so the title sits flush at
   the card's bottom at rest, then the description grows/slides up into
   place from underneath it on hover, instead of just fading in place.
   Text color is white unconditionally (not just on hover) since the photo/
   video + scrim behind it is now always visible, not hover-gated. */
@media (hover: hover) and (pointer: fine) {
  .service-card__body p {
    max-height: 0;
    margin-top: 0;
    opacity: 0;
    transform: translateY(10px);
    overflow: hidden;
  }

  .service-card:hover .service-card__body p {
    max-height: 160px;
    margin-top: 10px;
    opacity: 1;
    transform: translateY(0);
  }
}

/* ==========================================================================
   Impact block — text on the left, a dot-matrix map of Mexico on the right
   with Monterrey/Nuevo León picked out in red. The copy is the same real
   figures already stated elsewhere on this page (2010, 30+, 300+), just
   folded into flowing text instead of separate stat cards.
   ========================================================================== */

.impact {
  display: grid;
  grid-template-columns: minmax(320px, 460px) 1fr;
  gap: 64px;
  align-items: center;
}

.impact__heading {
  margin: 18px 0 24px;
}

.impact__heading .hl-muted { color: var(--warm-gray); }

.impact__lead {
  font-size: 18px;
  line-height: 1.6;
}

.impact__lead strong {
  color: var(--sungwon-red);
  font-weight: 600;
}

.impact__source {
  margin-top: 14px;
}

.impact__cta {
  margin-top: 32px;
}

.impact__map {
  position: relative;
}

.impact__map-svg { width: 100%; height: auto; display: block; }

.mx-dot--base { fill: rgba(34, 26, 20, 0.16); }
.mx-dot--mid { fill: rgba(216, 72, 31, 0.45); }
.mx-dot--core { fill: var(--sungwon-red); }

.radar-pin { position: absolute; display: flex; align-items: center; gap: 8px; }

.radar-pin__dot {
  width: 10px; height: 10px;
  border-radius: 50%;
  background: var(--sungwon-red);
  box-shadow: 0 0 0 6px rgba(216,72,31,0.22);
}

.radar-pin__label {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  white-space: nowrap;
}

@media (max-width: 900px) {
  .impact { grid-template-columns: 1fr; gap: 40px; }
}

/* ==========================================================================
   Flagship project cards — tall, portrait photo cards in the style of
   Virya's project-slider cards: a frosted glass panel floats at the bottom
   of each photo holding the service badges and the client's real logo +
   location, no chrome around the image itself.
   ========================================================================== */

.flagship-card {
  display: block;
  position: relative;
  border-radius: var(--card-radius);
  overflow: hidden;
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}

@media (hover: hover) and (pointer: fine) {
  .flagship-card:hover {
    transform: translateY(-4px);
    box-shadow: 0 20px 40px rgba(14,26,43,0.2);
  }

  .flagship-card:hover .flagship-card__photo-img.is-active {
    transform: scale(1.06);
  }

  .flagship-card:hover .flagship-card__reveal {
    max-height: 30px;
    opacity: 1;
    margin-top: 10px;
  }
}

.flagship-card__photo {
  position: relative;
  height: 620px;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}

/* Two stacked layers crossfade between a project's real photos on hover
   (JS-driven, see animations.js) — same "swap the active layer" pattern as
   the hero video crossfade above, applied to still photography instead. */
.flagship-card__photo-img {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  opacity: 0;
  transition: opacity 0.6s ease, transform 0.6s ease;
}

.flagship-card__photo-img.is-active { opacity: 1; }

.flagship-card__footer {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 22px 24px 26px;
  background: linear-gradient(180deg, rgba(20,15,10,0.32) 0%, rgba(20,15,10,0.62) 100%);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
}

.flagship-card__badges {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px;
}

.flagship-card__badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  font-weight: 500;
  color: var(--white);
}

.flagship-card__badge svg { width: 14px; height: 14px; }

.flagship-card__logo {
  height: 32px;
  width: auto;
  max-width: 140px;
  object-fit: contain;
  filter: brightness(0) invert(1) drop-shadow(0 1px 3px rgba(0,0,0,0.3));
}

.flagship-card__info span:last-child {
  display: block;
  font-size: 13px;
  color: rgba(247,248,249,0.78);
  margin-top: 10px;
}

.flagship-card__reveal {
  display: flex;
  gap: 16px;
  max-height: 0;
  margin-top: 0;
  opacity: 0;
  overflow: hidden;
  transition: max-height 0.35s ease, opacity 0.3s ease, margin-top 0.35s ease;
}

.flagship-card__reveal-stat {
  font-size: 12px;
  color: rgba(247,248,249,0.65);
}

.flagship-card__reveal-stat strong {
  color: var(--white);
  font-weight: 600;
}

@media (max-width: 900px) {
  .flagship-card__photo { height: 480px; }
}

/* Touch devices have no hover — show the stats line by default instead of
   gating it behind an interaction that doesn't exist there. */
@media not all and (hover: hover) {
  .flagship-card__reveal {
    max-height: 30px;
    margin-top: 10px;
    opacity: 1;
  }
}

/* ==========================================================================
   Client logo strip
   ========================================================================== */

.client-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 32px;
}

.client-grid__item {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 72px;
  padding: 12px;
}

.client-grid__logo {
  max-height: 40px;
  max-width: 100%;
  width: auto;
  object-fit: contain;
  filter: grayscale(1);
  opacity: 0.62;
  transition: filter 0.2s ease, opacity 0.2s ease;
}

@media (hover: hover) and (pointer: fine) {
  .client-grid__item:hover .client-grid__logo { filter: grayscale(0); opacity: 1; }
}

@media (max-width: 900px) {
  .client-grid { grid-template-columns: repeat(2, 1fr); }
}

/* Sits directly above the footer — .section--tight's default padding reads
   too cramped against the footer's own dark band, so give it extra room. */
.client-strip { padding-bottom: 120px; }

/* ==========================================================================
   Fit-purpose promise — replaces the old pre-footer CTA (client feedback:
   no pre-footer banner). Left: single-contractor promise copy + CTA. Right:
   the 5 áreas de negocio auto-cycling through an expand/collapse stack,
   echoing Virya's real "Our Fit For Purpose" section — which turned out to
   be a pre-baked Lottie animation (5 layers cycling on a ~10.4s loop), not
   scroll-driven DOM. Reimplemented here as 5 real DOM items (same icons/
   labels as the áreas de negocio swiper above) auto-cycling at a matching
   ~2.3s-per-item pace via class-toggle + CSS transition — the same
   "swap the active layer" idiom already used for the hero video crossfade
   and flagship card photo crossfade (see js/animations.js).
   ========================================================================== */

.fit-purpose__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 64px;
  align-items: center;
}

.fit-purpose__text h2 {
  font-weight: 400;
  font-size: clamp(28px, 3.2vw, 44px);
  max-width: 440px;
  margin-top: 12px;
  margin-bottom: 24px;
}

.fit-purpose__text > p:not(.eyebrow) {
  max-width: 440px;
  color: var(--warm-gray);
  margin-bottom: 32px;
}

.fit-purpose__stack {
  display: flex;
  flex-direction: column;
  gap: 14px;
  width: 100%;
  max-width: 420px;
  height: clamp(340px, 34vw, 420px);
  margin-left: auto;
}

.fit-purpose__item {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  flex-grow: 1;
  flex-shrink: 1;
  flex-basis: 0;
  min-height: 40px;
  padding: 0 28px;
  border-radius: var(--card-radius);
  background: var(--cream);
  color: var(--sungwon-red);
  overflow: hidden;
  transition: flex-grow 0.6s ease, background-color 0.6s ease, color 0.6s ease;
}

.fit-purpose__item.is-active {
  flex-grow: 7;
  background: var(--sungwon-red);
  color: var(--white);
}

.fit-purpose__icon {
  width: 34px;
  height: 34px;
  flex-shrink: 0;
  opacity: 0;
  transition: opacity 0.35s ease;
}

.fit-purpose__icon svg { width: 100%; height: 100%; }

.fit-purpose__label {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 21px;
  opacity: 0;
  transition: opacity 0.35s ease;
}

.fit-purpose__item.is-active .fit-purpose__icon,
.fit-purpose__item.is-active .fit-purpose__label {
  opacity: 1;
  transition-delay: 0.2s;
}

@media (max-width: 900px) {
  .fit-purpose__grid { grid-template-columns: 1fr; gap: 40px; }
  .fit-purpose__stack { height: 420px; }
}

/* ==========================================================================
   Footer — simplified. Logo sits directly on the dark background (no white
   box), forced to a light mark via filter. Only essential contact info and
   copyright remain — no sitemap column, no coverage-cities list.
   ========================================================================== */

.site-footer {
  background: var(--blueprint-navy);
  color: rgba(247, 248, 249, 0.82);
  padding: 64px 0 28px;
}

.footer-grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 40px;
  padding-bottom: 40px;
  border-bottom: 1px solid rgba(247,248,249,0.12);
}

.footer-grid__logo img {
  filter: brightness(0) invert(1);
  height: 26px;
  width: auto;
  margin-bottom: 14px;
}

.footer-grid__about {
  max-width: 34ch;
  font-size: 14px;
  color: rgba(247,248,249,0.6);
}

.footer-contact {
  list-style: none;
  padding: 0;
  font-size: 14px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.footer-contact a { display: inline-flex; align-items: center; gap: 8px; }
.footer-contact a svg { flex-shrink: 0; }
.footer-contact a:hover { color: var(--white); }
.footer-contact__address { display: flex; align-items: flex-start; gap: 8px; }
.footer-contact__address svg { flex-shrink: 0; margin-top: 2px; }

.footer-bottom {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
  padding-top: 24px;
  font-size: 13px;
  color: rgba(247,248,249,0.45);
}

@media (max-width: 900px) {
  .footer-grid { flex-direction: column; }
}

/* ==========================================================================
   Inner pages (Nosotros, etc.) — no scroll-jacked video hero, so the header
   can't rely on the hero's dark video for legibility while transparent.
   Static "always solid" modifier instead of the homepage's is-scrolled
   transition; JS's onScroll may also add .is-scrolled here, harmlessly
   redundant with this. Do NOT pair with .header--intro/is-loading — those
   depend on js/animations.js's heroIntro(), which only runs when #hero +
   #heroVideoWrap both exist (see CLAUDE.md).
   ========================================================================== */
.site-header--solid {
  background: rgba(247, 247, 245, 0.92);
  backdrop-filter: blur(10px);
  box-shadow: 0 1px 0 rgba(34,26,20,0.08);
}
.site-header--solid::before { opacity: 0; }
.site-header--solid .site-logo img { filter: none; }
.site-header--solid .site-nav__list a { color: var(--ink); }
.site-header--solid .lang-switch__toggle { color: var(--ink); }
.site-header--solid .nav-toggle span { background: var(--ink); }

/* ==========================================================================
   Nosotros — About page. Text-forward page header (not the homepage's
   video/scroll-jack .hero), a photo pair, an origin blurb, a navy mission
   quote, a reused-pattern world map, certification badges, a how-we-work
   split, a Mexico timeline, and a values grid.
   ========================================================================== */

.page-hero {
  padding: calc(var(--header-height) + 56px) 0 96px;
}

.page-hero__intro {
  display: grid;
  grid-template-columns: 200px 1fr;
  gap: 48px;
  max-width: 820px;
  margin: 40px auto 0;
  align-items: start;
}

.page-hero__intro p { text-align: left; }

/* Opt-in modifier for pages whose page-hero__intro has no eyebrow label
   (servicios.html, proyectos.html) — the paragraph takes the full measure
   instead of sitting in the 200px/1fr label+text grid every other inner
   page's page-hero__intro uses. Also drops the base rule's 820px
   max-width/auto-center — this should span the same width as the <h1>
   above it, not sit narrow and centered. */
.page-hero__intro--full {
  grid-template-columns: 1fr;
  max-width: none;
  margin-left: 0;
  margin-right: 0;
}

@media (max-width: 720px) {
  .page-hero { padding-bottom: 56px; }
  .page-hero__intro { grid-template-columns: 1fr; gap: 12px; margin-top: 28px; }
}

/* contacto.html — the only inner page whose .page-hero has no photo-pair/
   video/marquee filling the space below the intro paragraph (2026-08-15
   client feedback: "way too much space" once the hero photo pair was
   removed). The base .page-hero's 96px bottom padding plus the next
   .section's own clamp(64px, 40px+8vw, 140px) top padding was designed
   assuming a tall visual (photos/video/marquee) sits between them and
   absorbs part of that space — with only text in the hero, the same
   combined gap (up to ~236px) reads as an oversized void instead of
   breathing room. Scoped to this bare-text case only; every other inner
   page's page-hero keeps the default spacing since it still has a photo/
   video/marquee filling that role. */
.page-hero--compact { padding-bottom: 40px; }
.page-hero--compact + .section { padding-top: 56px; }

@media (max-width: 720px) {
  .page-hero--compact { padding-bottom: 28px; }
  .page-hero--compact + .section { padding-top: 40px; }
}

.hero-photo-pair {
  display: grid;
  grid-template-columns: 0.75fr 1.25fr;
  gap: 20px;
  height: 320px;
  margin-top: 40px;
}

.hero-photo-pair__item {
  position: relative;
  border-radius: var(--card-radius);
  overflow: hidden;
  height: 100%;
}

.hero-photo-pair__slide {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  opacity: 0;
  animation: hero-photo-crossfade 16s ease-in-out infinite;
}

.hero-photo-pair__item--wide .hero-photo-pair__slide { animation-duration: 18s; }

@keyframes hero-photo-crossfade {
  0%, 100% { opacity: 0; }
  6%, 50% { opacity: 1; }
  56% { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .hero-photo-pair__slide { animation: none; opacity: 0; }
  .hero-photo-pair__slide:first-child { opacity: 1; }
}

@media (max-width: 720px) {
  .hero-photo-pair { grid-template-columns: 1fr; height: auto; margin-top: 28px; gap: 12px; }
  .hero-photo-pair__item { aspect-ratio: 4/3; }
}

/* clientes.html page-hero — the scrolling .project-marquee (see its own
   rules further below) moved up into the hero in place of .hero-photo-pair
   (2026-08-15 client feedback: "remove the top two images and replace it
   with the gallery that is scrolling"). .project-marquee itself has no
   margin-top of its own — it previously relied on the padding of the
   separate <section> that used to wrap it — so this scoped selector gives
   it the same spacing .hero-photo-pair/.hero-video-card use in this exact
   slot on every other inner page. */
@media (min-width: 721px) {
  .page-hero .project-marquee { margin-top: 40px; }
}
@media (max-width: 720px) {
  .page-hero .project-marquee { margin-top: 28px; }
}

/* servicios.html page-hero — single large video card, replacing the old
   2-box .hero-photo-pair (2026-08-15 client feedback: "the same video
   thing... the card with the videos looping", one big card, not several).
   Holds all 5 real area clips stacked via .hero__video/.hero__video.is-active
   (same classes/CSS as the homepage hero, reused verbatim so the existing
   crossfade-cycling JS in js/animations.js — which just queries
   `.hero__video` sitewide — picks these up with no new code): only the
   first (Eléctrico) autoplays/is-active on load, the rest cycle in every
   2.2s exactly like the homepage. Originally shipped as one static
   Eléctrico-only video with icon/label/scrim, but that mismatched the
   page's own "Cinco áreas de negocio" framing (client feedback, same day:
   "is this just supposed to be one video, not all the videos... all i see
   is the electrico one") — the icon-badge/label/scrim were already
   dropped in an earlier follow-up, and now the single clip is dropped too
   in favor of the same 5-clip rotation as the homepage. See
   js/animations.js for a defensive .play() fallback in case the native
   autoplay attribute alone doesn't kick in for the initial clip. */
.hero-video-card {
  position: relative;
  overflow: hidden;
  border-radius: var(--card-radius);
  height: 380px;
  margin-top: 40px;
}

/* Purely decorative (aria-hidden) — without the scrim that used to sit on
   top of it, the bare <video> is the top-most hoverable element, and
   Chrome shows its native picture-in-picture/scrub hover affordance on any
   plain video by default. Suppress it; nothing here should be clickable. */
.hero-video-card video {
  pointer-events: none;
}

@media (max-width: 720px) {
  .hero-video-card { height: 320px; margin-top: 28px; }
}

/* Hero photo scatter — nosotros.html only (Virya's About Us hero: centered
   2-tone heading + subtext, 3 photos staggered at different heights rather
   than paired side-by-side, with a scroll-scrubbed parallax shift added in
   js/animations.js). Kept as a new component alongside .hero-photo-pair
   above, not a replacement — proyectos/clientes/servicios/contacto.html all
   still use the pair layout. */
.page-hero__title {
  text-align: center;
  max-width: 900px;
  margin: 20px auto 0;
}

.page-hero__subtext {
  text-align: center;
  max-width: 540px;
  margin: 20px auto 0;
  color: var(--warm-gray);
  font-size: 1.05rem;
}

.hero-scatter {
  position: relative;
  height: 460px;
  margin-top: 56px;
}

.hero-scatter__item {
  position: absolute;
  border-radius: var(--card-radius);
  background-size: cover;
  background-position: center;
  will-change: transform;
}

.hero-scatter__item--a { left: 2%; top: 60px; width: 30%; height: 380px; }
.hero-scatter__item--b { left: 36%; top: 190px; width: 21%; height: 250px; }
.hero-scatter__item--c { right: 4%; top: 0; width: 26%; height: 460px; }

@media (max-width: 900px) {
  .hero-scatter__item--a { width: 34%; }
  .hero-scatter__item--b { left: 38%; width: 24%; }
  .hero-scatter__item--c { width: 28%; }
}

@media (max-width: 720px) {
  .page-hero__title { margin-top: 16px; }
  .hero-scatter {
    position: static;
    height: auto;
    margin-top: 28px;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
  }
  .hero-scatter__item {
    position: static;
    width: auto;
    height: 200px;
  }
  .hero-scatter__item--a { grid-column: 1 / -1; height: 240px; }
}

@media (prefers-reduced-motion: reduce) {
  .hero-scatter__item { transform: none !important; }
}

.mission-quote {
  max-width: 860px;
  margin: 0 auto;
  text-align: center;
  font-size: var(--text-h3);
  font-weight: 500;
  line-height: 1.5;
}

.map-caption {
  margin-top: 32px;
  font-size: 16px;
  color: var(--warm-gray);
  text-align: center;
  max-width: 720px;
  margin-left: auto;
  margin-right: auto;
}

.map-caption + .map-caption { margin-top: 12px; }

/* World map (Presencia global) — same static-SVG-rasterization idiom as the
   homepage's Mexico dot-matrix map: real geography, no runtime JS. */
.dot-map {
  position: relative;
  width: 100%;
  min-height: 220px;
  aspect-ratio: 900 / 460;
  border-radius: var(--card-radius);
  border: 1px solid rgba(143, 127, 110, 0.2);
  overflow: hidden;
  background-color: var(--white);
  background-image:
    linear-gradient(160deg, rgba(255,255,255,0.95) 0%, rgba(143,127,110,0.14) 100%),
    repeating-linear-gradient(0deg, rgba(143,127,110,0.16) 0, rgba(143,127,110,0.16) 1px, transparent 1px, transparent 28px),
    repeating-linear-gradient(90deg, rgba(143,127,110,0.16) 0, rgba(143,127,110,0.16) 1px, transparent 1px, transparent 28px);
}

.dot-map__land { position: absolute; inset: 0; width: 100%; height: 100%; }
.dot-map__land path { fill: rgba(143, 127, 110, 0.32); }

.dot-map__arcs { position: absolute; inset: 0; width: 100%; height: 100%; }

.dot-map__arc {
  fill: none;
  stroke: var(--sungwon-red);
  stroke-width: 1.25;
  stroke-dasharray: 3 4;
  opacity: 0.4;
  vector-effect: non-scaling-stroke;
}

.dot-map__pin { position: absolute; }

.dot-map__dot {
  position: absolute;
  top: 0; left: 0;
  transform: translate(-50%, -50%);
  width: 10px; height: 10px;
  border-radius: 50%;
  background: var(--sungwon-red);
}

.dot-map__dot--hub {
  width: 15px; height: 15px;
  background: var(--sungwon-teal);
}

.dot-map__dot--hub::before,
.dot-map__dot--hub::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 1px solid var(--sungwon-teal);
  animation: radar-ping 2.6s ease-out infinite;
}

.dot-map__dot--hub::after { animation-delay: 1.3s; }

@keyframes radar-ping {
  0% { transform: scale(1); opacity: 0.6; }
  100% { transform: scale(2.4); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .dot-map__dot--hub::before,
  .dot-map__dot--hub::after { animation: none; opacity: 0; }
}

.dot-map__label {
  position: absolute;
  top: 12px; left: 0;
  transform: translateX(-50%);
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink);
  white-space: nowrap;
}

.dot-map__label--hub { font-weight: 600; }

@media (max-width: 720px) {
  .dot-map { min-height: 160px; }
  .dot-map__label { font-size: 10px; }
  .dot-map__pin--pl .dot-map__label { top: -18px; }
  .dot-map__pin--hu .dot-map__label { top: 22px; }
}

/* Certification / license badges */
.badge-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: var(--gutter);
}

.badge {
  padding: 28px 24px;
  border-radius: var(--card-radius);
  background: var(--white);
  border: 1px solid rgba(143, 127, 110, 0.2);
  transition: transform 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}

.badge:hover {
  transform: translateY(-4px);
  border-color: var(--sungwon-red);
  box-shadow: 0 10px 24px rgba(34,26,20,0.14);
}

.badge__ribbon {
  width: 60px; height: 68px;
  background: var(--sungwon-teal);
  clip-path: polygon(0 0, 100% 0, 100% 76%, 50% 100%, 0 76%);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding-top: 13px;
  margin-bottom: 18px;
  transition: transform 0.15s ease;
}

.badge:hover .badge__ribbon { transform: scale(1.08); }

.badge__icon { width: 26px; height: 26px; color: var(--white); }

.badge__marker {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 16px;
}

.badge__dot {
  flex-shrink: 0;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--sungwon-red);
}

.badge__year {
  font-family: var(--font-mono);
  font-size: 22px;
  font-weight: 600;
  color: var(--sungwon-teal);
}

.badge__text { font-size: 15px; color: var(--ink); line-height: 1.5; }

/* How we work — photo collage + copy */
.how-we-work {
  display: grid;
  grid-template-columns: 0.9fr 1.1fr;
  gap: 64px;
  align-items: center;
}

.how-we-work__collage {
  display: grid;
  grid-template-columns: 1.3fr 1fr;
  grid-template-rows: 1fr 1fr;
  gap: 12px;
  aspect-ratio: 4/3;
}

.how-we-work__collage-item {
  border-radius: var(--card-radius);
  background-size: cover;
  background-position: center;
}

.how-we-work__collage-item--tall { grid-row: 1 / 3; }

.how-we-work p + p { margin-top: 16px; }

@media (max-width: 860px) {
  .how-we-work { grid-template-columns: 1fr; gap: 32px; }
}

/* Mexico timeline */
.timeline-wrap {
  position: relative;
  width: 100vw;
  margin: 48px calc(50% - 50vw) 0;
}

.timeline {
  overflow-x: auto;
  padding: 80px max(24px, calc((100vw - 1320px) / 2 + 24px)) 20px;
  scrollbar-width: none;
}

.timeline::-webkit-scrollbar { display: none; }

.timeline-scrollbar {
  position: relative;
  width: 160px;
  height: 4px;
  margin: 4px auto 0;
  background: var(--warm-gray-light);
  border-radius: 100px;
}

.timeline-scrollbar__drag {
  position: absolute;
  top: 0; left: 0;
  height: 100%;
  background: var(--sungwon-red);
  border-radius: 100px;
}

.timeline__track {
  position: relative;
  display: flex;
  gap: 40px;
  width: max-content;
}

.timeline__track::before {
  content: '';
  position: absolute;
  left: 40px; right: 180px;
  top: -47px;
  height: 2px;
  background: linear-gradient(90deg, var(--sungwon-red) 0%, var(--sungwon-teal) 100%);
}

.timeline__item {
  position: relative;
  flex: 0 0 220px;
  padding: 24px 20px 22px;
  background: var(--white);
  border: 1px solid rgba(143, 127, 110, 0.2);
  border-radius: var(--card-radius);
  transition: transform 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}

.timeline__item:hover {
  transform: translateY(-6px);
  border-color: var(--sungwon-red);
  box-shadow: 0 10px 24px rgba(34,26,20,0.14);
}

.timeline__marker {
  position: absolute;
  top: -68px; left: 20px;
  width: 40px; height: 40px;
  border-radius: 50%;
  background: var(--sungwon-teal);
  border: 3px solid var(--paper);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 2;
  transition: transform 0.15s ease, background 0.15s ease;
}

.timeline__item:hover .timeline__marker { transform: scale(1.12); background: var(--sungwon-red); }

.timeline__icon { width: 20px; height: 20px; color: var(--white); }

.timeline__item::after {
  content: '';
  position: absolute;
  top: -7px; left: 33px;
  width: 14px; height: 14px;
  background: var(--white);
  border-left: 1px solid rgba(143, 127, 110, 0.2);
  border-top: 1px solid rgba(143, 127, 110, 0.2);
  transform: rotate(45deg);
  transition: border-color 0.15s ease;
}

.timeline__item:hover::after { border-color: var(--sungwon-red); }

.timeline__year {
  display: block;
  font-family: var(--font-mono);
  font-size: 20px;
  font-weight: 600;
  color: var(--sungwon-teal);
  margin-bottom: 8px;
}

.timeline__text { font-size: 14px; color: var(--ink); line-height: 1.5; }

@media (max-width: 720px) {
  .timeline-wrap { width: auto; margin: 48px 0 0; }
  .timeline-scrollbar { display: none; }
  .timeline { overflow-x: visible; padding: 4px 0 4px 66px; }
  .timeline__track { flex-direction: column; width: auto; gap: 32px; }
  .timeline__track::before {
    left: 33px; top: 0; bottom: 0; right: auto;
    width: 2px; height: auto;
    background: linear-gradient(180deg, var(--sungwon-red) 0%, var(--sungwon-teal) 100%);
  }
  .timeline__item { flex: none; }
  .timeline__marker { top: 50%; left: -56px; transform: translateY(-50%); }
  .timeline__item:hover .timeline__marker { transform: translateY(-50%) scale(1.12); }
  .timeline__item::after { top: 50%; left: -43px; transform: translateY(-50%) rotate(45deg); }
  .timeline__item:hover { transform: translateX(4px); }
  .timeline__track::before { left: -37px; }
}

/* Values grid */
.values-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--gutter);
  margin-top: 48px;
}

/* Tall Virya-style value cards: static icon + copy at rest, video fades
   in behind on hover (same idiom as the homepage's .service-card hover
   video). Unlike every other video/photo on this site, these 3 clips are
   free stock footage (Mixkit License — free for commercial use, no
   attribution required), not real Sungwon project footage: the user
   explicitly asked for higher-quality Virya-style b-roll here after
   rejecting an earlier version sourced from raw, unedited client phone
   video. This is a deliberate, requested exception to the sitewide
   "nothing fabricated" rule, scoped to just these 3 clips. */
.value-card {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  border-radius: var(--card-radius);
  border: 1px solid rgba(143, 127, 110, 0.2);
  padding: 28px;
  background: var(--white);
  min-height: 560px;
  transition: transform 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}

.value-card:hover {
  transform: translateY(-4px);
  border-color: rgba(34,26,20,0.18);
  box-shadow: 0 10px 24px rgba(34,26,20,0.14);
}

/* Permanently visible (not hover-gated) — same fix as .service-card__media
   on the homepage's business-area cards (client feedback, 2026-08-15):
   the video/poster is the card's base state now, not a hover reveal, so
   icon-badge/heading/paragraph are promoted to their old hover-only white
   styling as the permanent default (see below). */
.value-card__media {
  position: absolute;
  inset: 0;
  z-index: 0;
  opacity: 1;
}

.value-card__media video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.value-card__scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(18,14,11,0.1) 0%, rgba(18,14,11,0.3) 55%, rgba(18,14,11,0.8) 100%);
}

.value-card__icon-badge {
  position: absolute;
  top: 28px; left: 28px;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 52px; height: 52px;
  border-radius: 14px;
  background: rgba(255,255,255,0.16);
  color: var(--white);
}

.value-card__icon-badge svg { width: 26px; height: 26px; }

.value-card__body { position: relative; z-index: 1; }
.value-card__body h3 { color: var(--white); }
.value-card__body p { margin-top: 10px; color: var(--white); }

@media (max-width: 860px) {
  .values-grid { grid-template-columns: 1fr; }
  .value-card { min-height: 420px; }
}

/* Closing CTA band */
.cta-band { text-align: center; }
.cta-band h2 { color: var(--sungwon-teal); }
.cta-band p {
  margin-top: 16px;
  color: var(--warm-gray);
  max-width: 560px;
  margin-left: auto;
  margin-right: auto;
}
.cta-band .btn { margin-top: 32px; }

/* ==========================================================================
   Servicios (services) — the five business-area sections. All five now
   share the .service-feature video-led zigzag layout (see below) — the
   bullet list / proof-stat styles below were originally scoped to a
   separate .service-detail two-column layout, kept and reused as-is
   inside .service-feature__body after that layout was retired
   (2026-08-15 client feedback: match the SEAN ENC-style "one main image,
   alternating left/right" reference layout, video as the main image). */

.service-detail__list {
  margin-top: 32px;
  list-style: none;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.service-detail__list li {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 15px;
  color: var(--ink);
}

.service-detail__list li svg {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  color: var(--sungwon-red);
}

.service-detail__proof {
  margin-top: 20px;
  font-size: 15px;
  color: var(--warm-gray);
}

.service-detail__proof .dimension-number {
  color: var(--sungwon-teal);
  font-weight: 600;
}

/* Video-led feature blocks — one real video as the main image, text
   (heading + intro paragraph + optional .service-detail__list/__proof)
   beside it, alternating sides down the page via --reverse for a zigzag
   rhythm. Originally built for Solar/Reubicación only (see git history);
   extended to all five sections 2026-08-15 to match client-referenced
   layout — real hero-crossfade footage already shot for the homepage,
   reassigned here at a larger size, same "nothing fabricated" allowance
   used everywhere else on this site for real-asset reuse. */
.service-feature {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 48px;
  align-items: center;
}

.service-feature--reverse .service-feature__media { order: 2; }
.service-feature--reverse .service-feature__body { order: 1; }

.service-feature__media {
  position: relative;
  border-radius: var(--card-radius);
  overflow: hidden;
  aspect-ratio: 4/3;
}

.service-feature__media video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.service-feature__body h2 { margin-bottom: 16px; }
.service-feature__body p { color: var(--warm-gray); font-size: 16px; }

@media (max-width: 860px) {
  .service-feature { grid-template-columns: 1fr; gap: 20px; }
  .service-feature__media,
  .service-feature__body,
  .service-feature--reverse .service-feature__media,
  .service-feature--reverse .service-feature__body { order: initial; }
  .service-feature__media { aspect-ratio: 16/9; }
}

/* ==========================================================================
   Proyectos — flagship-card overrides, featured-card (tier-2 projects), and
   the full-history timeline.
   ========================================================================== */

/* On the homepage the m² reveal and photo crossfade are hover-gated (a
   teaser inside a carousel). Here the 4 flagship cards sit in a static
   grid on their own dedicated page, so the reveal stat stays permanently
   visible and a dates line is added — the hover crossfade itself still
   works unchanged (js/animations.js binds to any .flagship-card__photo
   with data-gallery, not just the swiper instance). */
#flagshipGrid .flagship-card__reveal {
  max-height: none;
  opacity: 1;
  margin-top: 10px;
}

.flagship-card__dates {
  font-size: 13px;
  color: rgba(247,248,249,0.75);
}

.featured-card {
  position: relative;
  display: flex;
  align-items: flex-end;
  min-height: 220px;
  padding: 16px;
  border-radius: var(--card-radius-sm);
  overflow: hidden;
  background-size: cover;
  background-position: center;
}

.featured-card::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(34,26,20,0.05) 0%, rgba(34,26,20,0.8) 100%);
  transition: background 0.2s ease;
}

@media (hover: hover) and (pointer: fine) {
  .featured-card:hover::before {
    background: linear-gradient(180deg, rgba(34,26,20,0.15) 0%, rgba(34,26,20,0.9) 100%);
  }
}

.featured-card__logo-chip {
  position: absolute;
  z-index: 2;
  top: 14px;
  left: 14px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 30px;
  padding: 5px 10px;
  border-radius: 6px;
  background: rgba(255,255,255,0.95);
}

.featured-card__logo-chip--dark { background: rgba(34,26,20,0.85); }
.featured-card__logo { max-height: 100%; max-width: 110px; object-fit: contain; }

.featured-card__year {
  position: absolute;
  z-index: 2;
  top: 14px;
  right: 14px;
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 600;
  color: var(--white);
}

.featured-card__scope {
  position: relative;
  z-index: 2;
  color: var(--white);
  font-size: var(--text-caption);
  font-weight: 500;
}

/* Full project history, rendered as a vertical timeline: a center line with
   cards alternating left/right of it on desktop, collapsing to a single
   left-aligned column (line + dot fixed at the edge) on mobile. */
.history-timeline { position: relative; max-width: 820px; margin: 48px auto 0; padding: 8px 0; }

.history-timeline::before {
  content: '';
  position: absolute; top: 0; bottom: 0; left: 50%;
  width: 2px; transform: translateX(-50%);
  background: linear-gradient(180deg, var(--sungwon-red) 0%, var(--sungwon-teal) 100%);
}

.history-timeline__item {
  position: relative; display: grid;
  grid-template-columns: 1fr 40px 1fr; align-items: center;
  column-gap: 20px; padding: 8px 0;
}

.history-timeline__dot {
  grid-column: 2; grid-row: 1; justify-self: center;
  display: flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; border-radius: 50%;
  border: 3px solid var(--white);
  box-shadow: 0 0 0 1px rgba(143,127,110,0.4);
  position: relative; z-index: 2;
  color: var(--white);
}

.history-timeline__dot svg { width: 14px; height: 14px; }
.history-timeline__dot--electrico { background: var(--sungwon-teal); }
.history-timeline__dot--red { background: var(--warm-gray); }
.history-timeline__dot--incendios { background: var(--sungwon-red); }

.history-timeline__card {
  grid-column: 1; grid-row: 1;
  position: relative;
  display: flex; align-items: stretch;
  background: var(--white);
  border: 1px solid rgba(34,26,20,0.1);
  border-radius: var(--card-radius-sm);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.history-timeline__card-main {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column; gap: 2px;
  padding: 14px 18px;
}

.history-timeline__card-date {
  flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  padding: 14px 20px;
  border-left: 1px solid rgba(34,26,20,0.08);
}

/* Date compartment sits nearest the center line — flip it to the leading
   edge for right-column cards so it stays adjacent to the dot on both sides. */
.history-timeline__item:nth-child(even) .history-timeline__card { flex-direction: row-reverse; }
.history-timeline__item:nth-child(even) .history-timeline__card-date {
  border-left: none;
  border-right: 1px solid rgba(34,26,20,0.08);
}

/* Speech-bubble-style pointer from each card toward its dot on the center
   line — ::before is a slightly larger outline triangle, ::after the white
   fill 1px inset on top of it, so the pointer reads as an outlined shape
   like the card. */
.history-timeline__card::before,
.history-timeline__card::after {
  content: '';
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 0; height: 0;
}

.history-timeline__card::before {
  border-top: 9px solid transparent;
  border-bottom: 9px solid transparent;
}

.history-timeline__card::after {
  border-top: 8px solid transparent;
  border-bottom: 8px solid transparent;
}

.history-timeline__item:nth-child(odd) .history-timeline__card::before {
  right: -9px;
  border-left: 9px solid rgba(34,26,20,0.15);
}

.history-timeline__item:nth-child(odd) .history-timeline__card::after {
  right: -8px;
  border-left: 8px solid var(--white);
}

.history-timeline__item:nth-child(even) .history-timeline__card { grid-column: 3; }
.history-timeline__item:nth-child(even) .history-timeline__card::before {
  left: -9px;
  border-right: 9px solid rgba(34,26,20,0.15);
}

.history-timeline__item:nth-child(even) .history-timeline__card::after {
  left: -8px;
  border-right: 8px solid var(--white);
}

.history-timeline__card:hover { border-color: var(--sungwon-red); box-shadow: 0 6px 16px rgba(34,26,20,0.10); }
.history-timeline__item:nth-child(odd) .history-timeline__card:hover::before { border-left-color: var(--sungwon-red); }
.history-timeline__item:nth-child(even) .history-timeline__card:hover::before { border-right-color: var(--sungwon-red); }

.history-timeline__year { font-family: var(--font-mono); font-size: 20px; font-weight: 600; color: var(--ink); }

.history-timeline__logo-chip {
  display: inline-flex; align-items: center; justify-content: center;
  align-self: flex-start; flex-shrink: 0;
  height: 24px;
  margin-bottom: 4px;
}

.history-timeline__logo-chip--tall { height: 44px; }

.history-timeline__logo-chip--dark {
  padding: 3px 8px;
  border-radius: 4px;
  background: rgba(34,26,20,0.9);
}

.history-timeline__logo { max-height: 100%; max-width: 80px; object-fit: contain; }
.history-timeline__client { font-weight: 500; font-size: var(--text-caption); }
.history-timeline__scope { color: var(--warm-gray); font-size: var(--text-caption); }

@media (max-width: 720px) {
  .history-timeline { padding-left: 28px; }
  .history-timeline::before { left: 6px; transform: none; }
  .history-timeline__item { grid-template-columns: 1fr; padding: 6px 0; }
  .history-timeline__dot {
    grid-column: unset; position: absolute; left: -35px; top: 50%; transform: translateY(-50%);
  }
  .history-timeline__card,
  .history-timeline__item:nth-child(even) .history-timeline__card { grid-column: 1; flex-direction: row; }
  .history-timeline__item:nth-child(even) .history-timeline__card-date {
    border-left: 1px solid rgba(34,26,20,0.08);
    border-right: none;
  }
  .history-timeline__item:nth-child(odd) .history-timeline__card::before,
  .history-timeline__item:nth-child(even) .history-timeline__card::before {
    left: -9px; right: auto;
    border-right: 9px solid rgba(34,26,20,0.15);
    border-left: none;
  }
  .history-timeline__item:nth-child(odd) .history-timeline__card::after,
  .history-timeline__item:nth-child(even) .history-timeline__card::after {
    left: -8px; right: auto;
    border-right: 8px solid var(--white);
    border-left: none;
  }
  .history-timeline__item:nth-child(odd) .history-timeline__card:hover::before,
  .history-timeline__item:nth-child(even) .history-timeline__card:hover::before {
    border-right-color: var(--sungwon-red);
  }
}

/* ==========================================================================
   Clientes page — project photo marquee + detailed client grid
   ========================================================================== */

/* Full-bleed breakout: clientes.html client feedback (2026-08-15) asked
   for this to run edge-to-edge rather than sit inside the page's
   .container measure. Same width:100vw / calc(50%-50vw) technique
   .timeline-wrap already uses on nosotros.html — safe here too since
   body has overflow-x:hidden (css/base.css). */
.project-marquee {
  position: relative;
  overflow: hidden;
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
}

/* Edge fade, previously a mask-image on this element (2026-08-15 mobile
   perf fix: applying mask-image over a continuously-animating child forces
   the mobile GPU to recomposite the mask every frame — reported by the
   client as the marquee running "super super slow" on a real phone despite
   being smooth in a desktop browser; not reproducible via CPU throttling
   alone, consistent with a masking-specific compositing cost rather than a
   generic slow-device issue). Solid-color gradient overlays achieve the
   same visual fade without masking the animating layer underneath — cheap
   alpha-blended static pseudo-elements instead of a per-frame GPU mask. */
.project-marquee::before,
.project-marquee::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  width: 96px;
  z-index: 1;
  pointer-events: none;
}

.project-marquee::before {
  left: 0;
  background: linear-gradient(90deg, var(--paper) 0, transparent 100%);
}

.project-marquee::after {
  right: 0;
  background: linear-gradient(90deg, transparent 0, var(--paper) 100%);
}

.project-marquee__track {
  display: flex;
  gap: 24px;
  width: max-content;
  animation: project-marquee-scroll 36s linear infinite;
  will-change: transform;
}

.project-marquee:hover .project-marquee__track {
  animation-play-state: paused;
}

/* Sized up from the original 260x170 (2026-08-15 client feedback: "the
   cards seem really small") — kept the same ~3:2 aspect ratio, just
   larger, since the extra edge-to-edge width now needs bigger cards to
   read as a deliberate gallery rather than a thin strip. */
.project-marquee__card {
  flex: 0 0 400px;
  height: 260px;
  border-radius: var(--card-radius);
  background-size: cover;
  background-position: center;
}

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

@media (prefers-reduced-motion: reduce) {
  .project-marquee__track { animation: none; }
}

@media (max-width: 640px) {
  .project-marquee__card { flex-basis: 280px; height: 182px; }
}

/* Detailed variant of the homepage's .client-grid — logos shown at full
   color (this page's whole purpose is showcasing clients, not a muted
   background strip) plus a permanently-visible project-count/year caption. */
.client-grid--detailed { grid-template-columns: repeat(4, 1fr); gap: 20px; }

.client-grid--detailed .client-grid__item {
  flex-direction: column;
  justify-content: center;
  gap: 10px;
  height: auto;
  min-height: 108px;
  padding: 20px 12px;
  border-radius: var(--card-radius-sm);
  background: var(--cream);
}

.client-grid--detailed .client-grid__logo {
  filter: none;
  opacity: 1;
  max-height: 32px;
}

.client-grid__meta {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--warm-gray);
}

@media (max-width: 900px) {
  .client-grid--detailed { grid-template-columns: repeat(2, 1fr); }
}

/* ==========================================================================
   Contacto page — coverage map + contact info block
   ========================================================================== */

.contact-grid {
  display: grid;
  grid-template-columns: minmax(320px, 460px) 1fr;
  gap: 64px;
  align-items: start;
}

@media (max-width: 900px) {
  .contact-grid { grid-template-columns: 1fr; gap: 40px; }
}

.radar-pin--hub .radar-pin__dot {
  width: 13px;
  height: 13px;
}

.radar-pin--label-left { flex-direction: row-reverse; }

/* Monterrey/Apodaca/Saltillo/Reynosa sit within ~2% of each other on this
   map — dropping the label below the dot instead of beside it keeps their
   text from colliding, without moving the (geographically real) pin. */
.radar-pin--label-below { flex-direction: column; align-items: flex-start; gap: 4px; }

/* Apodaca's dot sits ~10px from Saltillo's on this map — pulling the hub's
   label above instead of below keeps the two from overlapping. */
.radar-pin--label-above { flex-direction: column-reverse; align-items: flex-start; gap: 4px; }

.info-block dl { margin: 0; }

.info-block dt {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--warm-gray);
  margin-top: 28px;
}

.info-block dt:first-child { margin-top: 0; }

.info-block dd {
  margin: 6px 0 0;
  font-size: 18px;
  font-weight: 500;
}

.info-block dd a { color: inherit; text-decoration: none; }
.info-block dd a:hover { color: var(--sungwon-red); }

.contact-direct {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  margin-top: 40px;
}

@media (max-width: 480px) {
  .contact-direct { flex-direction: column; }
  .contact-direct .btn { width: 100%; text-align: center; }
}

/* WhatsApp CTA — filled with WhatsApp's own brand green instead of the
   generic .btn-secondary outline, plus its logo mark, so it reads as the
   recognizable WhatsApp action rather than a plain text button (contacto.html
   only, 2026-08-15 request). Brand colors (#25D366 / #1DA851 hover) are
   WhatsApp's own, not invented. */
.btn-whatsapp {
  background: #25D366;
  color: var(--white);
  border-color: #25D366;
}
.btn-whatsapp:hover { background: #1DA851; border-color: #1DA851; }
.btn-whatsapp svg { flex-shrink: 0; }

/* ==========================================================================
   Nosotros — Virya-parity section headings + history intro card. Added when
   auditing nosotros.html against Virya's live About Us page: Virya pairs a
   small label with a large 2-tone heading on every section, and opens its
   history row with a large-statement card before the year-by-year cards.
   Same treatment here, using only real Sungwon facts already on the page. */
.mission-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 56px; height: 56px;
  border-radius: 50%;
  background: rgba(247,247,245,0.1);
  color: var(--drafting-white);
}
.mission-icon svg { width: 26px; height: 26px; }

.timeline__item--intro {
  flex: 0 0 300px;
  display: flex;
  align-items: center;
  padding: 32px 28px 36px;
  background: var(--blueprint-navy);
  border-color: transparent;
}
.timeline__item--intro:hover { transform: none; box-shadow: none; }
.timeline__item--intro::after { display: none; }
.timeline__intro-text {
  font-family: var(--font-display);
  font-size: 19px;
  font-weight: 500;
  line-height: 1.4;
  color: var(--drafting-white);
}

/* ==========================================================================
   Proyectos — photo gallery lightbox. Ported back from v1 (js/gallery.js
   there), re-styled to v2's tokens: cards with [data-lightbox] (a JSON array
   of real project photo URLs) open a full-screen swipeable gallery on click,
   with a "Ver galería" hint that appears on hover/focus.
   ========================================================================== */

[data-lightbox] { cursor: pointer; }

.gallery-hint {
  position: absolute;
  z-index: 2;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 18px;
  border-radius: var(--button-radius);
  background: rgba(34,26,20,0.55);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  color: var(--white);
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.02em;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease;
}

.gallery-hint svg { width: 16px; height: 16px; }

@media (hover: hover) and (pointer: fine) {
  [data-lightbox]:hover .gallery-hint { opacity: 1; }
}

/* Touch devices have no hover — show the tap affordance by default instead
   of gating it behind an interaction that doesn't exist there, same
   convention as .flagship-card__reveal above. */
@media not all and (hover: hover) {
  .gallery-hint { opacity: 1; }
}

/* ...except on mobile viewports specifically (2026-08-15 client feedback):
   the always-on pill was cluttering the card on small screens. Tapping the
   card still opens the lightbox — js/gallery.js delegates the click handler
   to [data-lightbox] itself, not this button — so hiding it doesn't remove
   any functionality, just the visible label. Desktop's hover-reveal above
   is untouched. */
@media (max-width: 900px) {
  .gallery-hint { display: none; }
}

body.lightbox-open { overflow: hidden; }

.lightbox {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 300;
}

.lightbox.is-open { display: block; }

.lightbox__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(20,15,10,0.92);
}

.lightbox__stage {
  position: relative;
  z-index: 1;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 40px 96px;
}

.lightbox__img {
  max-width: 100%;
  max-height: calc(100vh - 140px);
  border-radius: var(--card-radius);
  box-shadow: 0 30px 60px rgba(0,0,0,0.4);
  object-fit: contain;
}

.lightbox__close,
.lightbox__nav {
  position: absolute;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 50%;
  background: rgba(255,255,255,0.12);
  color: var(--white);
  cursor: pointer;
  transition: background 0.2s ease;
}

.lightbox__close:hover,
.lightbox__nav:hover { background: rgba(255,255,255,0.22); }

.lightbox__close {
  top: 24px; right: 24px;
  width: 44px; height: 44px;
}
.lightbox__close svg { width: 20px; height: 20px; }

.lightbox__nav {
  top: 50%;
  transform: translateY(-50%);
  width: 52px; height: 52px;
}
.lightbox__nav svg { width: 22px; height: 22px; }
.lightbox__nav--prev { left: 24px; }
.lightbox__nav--next { right: 24px; }

.lightbox__meta {
  position: absolute;
  left: 0; right: 0;
  bottom: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  font-family: var(--font-mono);
  font-size: 13px;
  color: rgba(247,247,245,0.7);
}

.lightbox__title { color: var(--white); font-weight: 600; }

@media (max-width: 640px) {
  .lightbox__stage { padding: 24px 16px; }
  .lightbox__img { max-height: calc(100vh - 120px); }
  .lightbox__close { top: 12px; right: 12px; width: 38px; height: 38px; }
  .lightbox__nav { width: 42px; height: 42px; }
  .lightbox__nav--prev { left: 8px; }
  .lightbox__nav--next { right: 8px; }
}
