/* ============================================================
   GMAT CONSTRUTORA — Design System
   Silêncio visual. Precisão. Luxo discreto.
   ============================================================ */

:root {
  /* Cor — extraída da identidade visual (uniformes / logo) */
  --blue-deep: #152B4E;
  --blue-deep-rgb: 21, 43, 78;
  --blue-light: #2E5590;
  --ink: #12161C;

  --white: #FFFFFF;
  --gray-50: #F6F6F4;
  --gray-100: #ECEBE7;
  --gray-200: #DEDDD7;
  --gray-300: #C7C5BD;
  --gray-500: #8B8A82;
  --gray-700: #4B4A45;
  --gray-900: #1C1B18;

  --font-display: "Fraunces", ui-serif, Georgia, serif;
  --font-body: "Hanken Grotesk", -apple-system, sans-serif;

  --container: 1320px;
  --gutter: clamp(24px, 6vw, 96px);
  --radius-s: 6px;
  --radius-m: 14px;
  --radius-l: 28px;

  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --dur-s: 400ms;
  --dur-m: 650ms;
  --dur-l: 900ms;
}

/* ---------------- Reset ---------------- */
*, *::before, *::after { box-sizing: border-box; }
/* Scroll is owned by Lenis (see app.js) — native smooth-scroll would fight it. */
html.lenis { height: auto; }
html.lenis, html.lenis body { overscroll-behavior: contain; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; }
}
html {
  overflow-x: hidden;
  width: 100%;
}
body {
  margin: 0;
  font-family: var(--font-body);
  color: var(--ink);
  background: var(--white);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  width: 100%;
  max-width: 100vw;
}
img, video { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
ul, ol, dl { margin: 0; padding: 0; list-style: none; }
h1, h2, h3, h4, dt, dd, p { margin: 0; }
button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; padding: 0; }
svg { display: block; }

h1, h2, h3 {
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-weight: 460;
  line-height: 0.98;
  letter-spacing: -0.022em;
}
h2 { font-size: clamp(2.4rem, 4.6vw, 3.8rem); font-weight: 460; }
h2 em, h1 em { font-style: italic; color: var(--blue-deep); font-weight: 440; }
h3 { font-size: 1.05rem; font-weight: 600; font-family: var(--font-body); letter-spacing: -0.005em; }

.eyebrow {
  display: block;
  font-size: 0.68rem;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--blue-deep);
  font-weight: 600;
  margin-bottom: 12px;
}
.eyebrow::before {
  content: '';
  display: inline-block;
  width: 22px; height: 1px;
  background: currentColor;
  margin-right: 12px;
  vertical-align: middle;
  opacity: 0.6;
}
/* Dark/photo/video sections need a light eyebrow — the default navy is tuned
   for white section backgrounds and disappears against a sky or dark overlay */
.hero-content .eyebrow, .processo-heading .eyebrow, .depoimentos-inner .eyebrow, .cta-inner .eyebrow {
  color: rgba(255,255,255,0.75);
}
.lead { font-size: 1.15rem; line-height: 1.6; color: var(--gray-700); max-width: 46ch; }
p { line-height: 1.7; color: var(--gray-700); }

/* ---------------- Layout helpers ---------------- */
.section {
  position: relative;
  padding: clamp(70px, 9vw, 130px) var(--gutter);
  max-width: var(--container);
  margin: 0 auto;
}
/* A quiet architectural-drafting mark — the same corner tick recurs at the
   top of every chapter after the Hero, threading the sections together as
   one continuous drawing instead of stacked, unrelated blocks. Color is
   inherited (currentColor) so it reads dark on light sections and light on
   the dark video ones automatically. */
.section::before, .processo::before, .depoimentos::before, .cta-final::before {
  content: '';
  position: absolute; z-index: 4; pointer-events: none;
  top: 28px; width: 20px; height: 20px;
  border-top: 1px solid currentColor;
  border-left: 1px solid currentColor;
  opacity: 0.16;
}
.section::before { left: 0; }
.processo::before, .depoimentos::before, .cta-final::before { left: var(--gutter); }

/* Blueprint texture — near-imperceptible architectural grid, part of the permanent identity */
.hero-blueprint, .footer-blueprint {
  position: absolute; inset: 0;
  background-image:
    linear-gradient(rgba(255,255,255,0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,0.05) 1px, transparent 1px);
  background-size: 64px 64px;
  pointer-events: none;
  opacity: 0.5;
}
.footer-blueprint {
  background-image:
    linear-gradient(rgba(var(--blue-deep-rgb),0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(var(--blue-deep-rgb),0.05) 1px, transparent 1px);
}

/* ---------------- Media slot / placeholder system ---------------- */
.media-slot {
  position: relative;
  overflow: hidden;
  background:
    linear-gradient(rgba(var(--blue-deep-rgb),0.04) 1px, transparent 1px),
    linear-gradient(90deg, rgba(var(--blue-deep-rgb),0.04) 1px, transparent 1px),
    linear-gradient(135deg, var(--gray-100), var(--gray-50));
  background-size: 32px 32px, 32px 32px, cover;
}
.media-slot img, .media-slot video {
  width: 100%; height: 100%;
  object-fit: cover;
  position: relative; z-index: 1;
}
.media-slot::after {
  content: attr(data-label);
  position: absolute; inset: 12px;
  z-index: 2;
  display: flex; align-items: flex-end;
  font-size: 0.68rem;
  letter-spacing: 0.04em;
  color: rgba(var(--blue-deep-rgb), 0.55);
  padding: 10px 12px;
  pointer-events: none;
  opacity: 1;
  transition: opacity var(--dur-s) var(--ease);
}
/* JS adds .has-media once a real image/video successfully loads, hiding the placeholder label */
.media-slot.has-media::after { opacity: 0; }

/* Light label variant for placeholders that sit on dark/video sections */
.hero-media::after, .processo-media::after, .depoimentos-media::after, .cta-media::after,
.media-slot--depoimento::after {
  color: rgba(255,255,255,0.6);
  background: linear-gradient(0deg, rgba(8,14,24,0.5), transparent);
}

/* Full-bleed background slots anchor their label to the top corner — the
   bottom edge is already claimed by page content (hero copy, scroll cue, CTA text) */
.hero-media::after, .processo-media::after, .depoimentos-media::after, .cta-media::after {
  align-items: flex-start;
  background: linear-gradient(180deg, rgba(8,14,24,0.5), transparent);
}
/* Hero's slot sits directly under the fixed (transparent-until-scrolled) header —
   push its label below the header instead of letting the two overlap */
.hero-media::after { top: 96px; }

.media-slot--tall { aspect-ratio: 4 / 5; border-radius: var(--radius-l); }
.media-slot--vertical { aspect-ratio: 9 / 16; border-radius: var(--radius-m); }
/* Source photo is much taller than the 4:5 box — Guilherme and the crew sit
   in the upper third of the frame, so favor that instead of the bare rebar
   mesh at the bottom. */
#consolidacao .media-slot--tall img { object-position: center 18%; }

/* ---------------- Buttons ---------------- */
.btn {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 16px 32px;
  border-radius: 100px;
  font-size: 0.95rem;
  font-weight: 600;
  transition: transform var(--dur-s) var(--ease), background var(--dur-s) var(--ease), box-shadow var(--dur-s) var(--ease);
  white-space: nowrap;
}
.btn-uppercase { text-transform: uppercase; letter-spacing: 0.04em; font-size: 0.85rem; }
/* White pill reads clearly against every background this button appears on
   (hero photo, CTA drone footage) — a navy button was blending into the dark
   overlay it always sits on and losing its shape as a call to action. */
.btn-primary {
  background: var(--white);
  color: var(--blue-deep);
  box-shadow: 0 4px 20px -6px rgba(0,0,0,0.35), 0 1px 2px rgba(0,0,0,0.1);
}
.btn-primary:hover { background: var(--gray-50); transform: translateY(-2px); box-shadow: 0 18px 36px -14px rgba(0,0,0,0.45); }
.btn-secondary {
  background: transparent;
  color: var(--white);
  border: 1.5px solid rgba(255,255,255,0.55);
}
.btn-secondary:hover { border-color: #fff; background: rgba(255,255,255,0.08); transform: translateY(-2px); }
.section .btn-secondary { color: var(--blue-deep); border-color: rgba(var(--blue-deep-rgb), 0.3); }

.text-link {
  display: inline-flex; align-items: center; gap: 8px;
  font-weight: 600; color: var(--blue-deep);
  padding-bottom: 2px; border-bottom: 1px solid rgba(var(--blue-deep-rgb), 0.3);
  transition: gap var(--dur-s) var(--ease), border-color var(--dur-s) var(--ease);
}
.text-link:hover { gap: 13px; border-color: var(--blue-deep); }

/* ---------------- Loader ---------------- */
#loader {
  position: fixed; inset: 0; z-index: 999;
  background: var(--blue-deep);
  display: flex; align-items: center; justify-content: center;
  transition: opacity 700ms var(--ease), visibility 700ms;
}
#loader.loaded { opacity: 0; visibility: hidden; }
.loader-mark { animation: pulse 1.4s ease-in-out infinite; }
.loader-mark img { filter: brightness(0) invert(1); }
@keyframes pulse { 0%,100%{opacity:.4} 50%{opacity:1} }

/* ---------------- Reading progress ---------------- */
#reading-progress { position: fixed; top: 0; left: 0; right: 0; height: 2px; z-index: 200; }
#reading-progress-bar { height: 100%; width: 0; background: var(--blue-deep); transition: width 80ms linear; }

/* ---------------- Header ---------------- */
.header {
  position: fixed; top: 0; left: 0; right: 0; z-index: 150;
  padding: calc(20px + env(safe-area-inset-top)) var(--gutter) 20px;
  transition: background var(--dur-m) var(--ease), padding var(--dur-m) var(--ease), box-shadow var(--dur-m) var(--ease), backdrop-filter var(--dur-m) var(--ease);
  color: var(--white);
}
.header.scrolled {
  background: rgba(255,255,255,0.72);
  backdrop-filter: blur(20px) saturate(1.4);
  -webkit-backdrop-filter: blur(20px) saturate(1.4);
  padding: calc(12px + env(safe-area-inset-top)) var(--gutter) 12px;
  color: var(--ink);
  box-shadow: 0 1px 0 rgba(18,22,28,0.06), 0 12px 32px -20px rgba(18,22,28,0.25);
}
.header-inner { max-width: var(--container); margin: 0 auto; display: flex; align-items: center; justify-content: space-between; }
.logo { display: flex; align-items: center; }
.logo img {
  height: 34px; width: auto;
  transition: height var(--dur-m) var(--ease), filter var(--dur-m) var(--ease);
}
.header.scrolled .logo img { height: 30px; }
/* Navy-ink logo needs to read as white while the header floats transparent over
   the hero photo; once it's on the blurred white bar, the original navy returns. */
.header:not(.scrolled) .logo img { filter: brightness(0) invert(1); }
.footer .logo img { height: 32px; }

.main-nav { display: flex; align-items: center; gap: 40px; }
.main-nav a { font-size: 0.84rem; font-weight: 500; letter-spacing: 0.02em; position: relative; }
.main-nav a:not(.nav-cta)::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -6px; height: 1px;
  background: currentColor; transform: scaleX(0); transform-origin: right; transition: transform var(--dur-m) var(--ease);
}
.main-nav a:not(.nav-cta):hover::after { transform: scaleX(1); transform-origin: left; }
.nav-cta {
  background: var(--blue-deep); color: var(--white);
  padding: 11px 22px; border-radius: 100px; font-weight: 600;
  transition: background var(--dur-s) var(--ease), transform var(--dur-s) var(--ease), box-shadow var(--dur-s) var(--ease);
}
.nav-cta:hover { background: var(--blue-light); transform: translateY(-1px); box-shadow: 0 10px 24px -12px rgba(var(--blue-deep-rgb), 0.55); }

.nav-toggle { display: none; flex-direction: column; gap: 5px; width: 26px; }
.nav-toggle span { height: 2px; background: currentColor; border-radius: 2px; transition: transform var(--dur-s) var(--ease), opacity var(--dur-s) var(--ease); }

/* ---------------- Hero ---------------- */
/* Editorial-cover composition: Guilherme stays in the left frame (already how
   the source photography is composed), the text block sits fully in the
   clear right half — never overlapping the subject, like a magazine cover
   masthead rather than a banner with text stacked over a person. */
.hero {
  position: relative;
  min-height: 100svh;
  display: flex; align-items: center;
  overflow: hidden;
  color: var(--white);
}
.hero-media { position: absolute; top: -4%; left: 0; right: 0; height: 108%; }
/* Favors the house's architectural volume (center-right of the source photo)
   over the driveway foreground and open sky on the left. */
.hero-media video, .hero-media img { object-position: 62% 38%; }
/* Extremely subtle drift so the hero never reads as a static frame — a slow
   scale+pan, well under the threshold of feeling like an "effect". */
.hero-media video { animation: heroDrift 24s ease-in-out infinite; }
@keyframes heroDrift {
  0%   { transform: scale(1.04) translateX(0); }
  50%  { transform: scale(1.065) translateX(-1.6%); }
  100% { transform: scale(1.04) translateX(0); }
}
@media (prefers-reduced-motion: reduce) { .hero-media video { animation: none; } }
.hero-overlay {
  position: absolute; inset: 0;
  /* Dark wash lives on the LEFT, under the text column; the right side of the
     house stays completely clean from the very edge inward — no scrim at all. */
  background: linear-gradient(90deg, rgba(8,12,20,0.88) 0%, rgba(var(--blue-deep-rgb),0.62) 38%, rgba(var(--blue-deep-rgb),0.18) 68%, rgba(var(--blue-deep-rgb),0) 100%),
              linear-gradient(0deg, rgba(8,14,24,0.6) 0%, rgba(8,14,24,0.02) 40%);
}
/* Cinematic hand-off to Capítulo 01: as the user scrolls out of the Hero,
   app.js (initHeroExit) scrubs this scrim's opacity and fades/lifts
   .hero-content in sync with scroll position, so the video darkens and the
   text dissolves right as the next chapter rises into view underneath —
   one continuous motion instead of a hard cut between sections. */
.hero-scrim {
  position: absolute; inset: 0; z-index: 1;
  background: #05070b;
  opacity: 0;
  pointer-events: none;
}
.hero-content {
  position: relative; z-index: 2;
  max-width: var(--container); width: 100%; margin: 0 auto;
  padding: 140px var(--gutter) 64px;
  display: flex; justify-content: flex-start;
}
.hero-content-inner { max-width: 34ch; text-align: left; }
.hero-title {
  font-size: clamp(2.9rem, 5vw, 4.4rem);
  line-height: 0.96;
  margin-bottom: 28px;
}
/* The default navy emphasis color (tuned for white section backgrounds) all
   but disappeared against the dark photo here — a soft ice blue keeps the
   same cool family but reads clearly on a dark base. */
.hero-title em { color: #FFFFFF; text-shadow: 0 2px 18px rgba(0,0,0,0.35); }
.hero-subtitle { font-size: 1.08rem; line-height: 1.65; margin-bottom: 44px; color: rgba(255,255,255,0.82); }
.hero-actions { display: flex; gap: 16px; flex-wrap: wrap; margin-bottom: 64px; }

.hero-stats { display: flex; gap: clamp(28px, 4vw, 48px); }
.stat { text-align: left; }
.stat-number { font-family: var(--font-display); font-size: clamp(1.9rem, 2.6vw, 2.4rem); font-weight: 460; letter-spacing: -0.02em; }
.stat-label { font-size: 0.72rem; color: rgba(255,255,255,0.62); line-height: 1.35; margin-top: 6px; letter-spacing: 0.01em; }
.stats-note { font-size: 0.66rem; color: rgba(255,255,255,0.38); margin-top: 16px; }

.scroll-indicator {
  position: absolute; bottom: 36px; right: var(--gutter); z-index: 2;
  display: flex; align-items: center; gap: 10px; color: rgba(255,255,255,0.55);
}
.scroll-indicator span {
  width: 1px; height: 34px; background: rgba(255,255,255,0.5);
  position: relative; overflow: hidden;
}
.scroll-indicator span::after {
  content: ''; position: absolute; top: -100%; left: 0; right: 0; height: 100%;
  background: #fff; animation: scrollLine 2.2s ease-in-out infinite;
}
@keyframes scrollLine { 0%{top:-100%} 60%{top:100%} 100%{top:100%} }
.scroll-indicator small { font-size: 0.7rem; letter-spacing: 0.08em; text-transform: uppercase; }

/* ---------------- Split sections ---------------- */
.split {
  display: grid; grid-template-columns: 1fr 1fr; gap: clamp(56px, 8vw, 130px);
  align-items: center;
}
.split-reverse { direction: rtl; }
.split-reverse > * { direction: ltr; }
.split-content { max-width: 52ch; }
.split-content h2 { margin-bottom: 24px; }
.split-content .lead { margin-bottom: 18px; }
.split-content > p:not(.lead) { margin-bottom: 32px; }

.mini-cards { display: grid; grid-template-columns: 1fr; gap: 14px; margin-bottom: 40px; }
.mini-card {
  display: flex; align-items: flex-start; gap: 16px;
  padding: 20px 22px; border-radius: var(--radius-m);
  border: 1px solid var(--gray-200);
  transition: border-color var(--dur-s) var(--ease), transform var(--dur-s) var(--ease);
}
.mini-card:hover { border-color: var(--blue-deep); transform: translateY(-3px); }
.mini-card svg { width: 22px; height: 22px; flex-shrink: 0; margin-top: 3px; color: var(--blue-deep); transition: transform var(--dur-s) var(--ease); }
.mini-card:hover svg { transform: translateY(-2px) scale(1.06); }
.mini-card h3 { font-size: 0.95rem; margin-bottom: 4px; }
.mini-card p { font-size: 0.85rem; }


/* ---------------- Processo (pinned video + timeline) ---------------- */
.processo { position: relative; color: var(--white); overflow: hidden; }
.processo-media { position: absolute; top: -4%; left: 0; right: 0; height: 108%; }
/* Stronger, more deliberate mask than a flat wash — the machine footage was
   reading as noise behind the timeline cards. A vignette weighted toward the
   text column plus an overall deeper base keeps the video visible as texture
   without it ever competing with the copy. Lightened slightly so the machine
   itself stays perceptible rather than near-silhouette. */
.processo-overlay {
  position: absolute; inset: 0;
  background:
    radial-gradient(120% 90% at 18% 8%, rgba(8,14,24,0.24), rgba(8,14,24,0.58) 55%, rgba(8,14,24,0.74) 100%),
    linear-gradient(180deg, rgba(8,14,24,0.36) 0%, rgba(8,14,24,0.64) 100%);
}
.processo-inner {
  position: relative; z-index: 2;
  max-width: var(--container); margin: 0 auto;
  padding: clamp(76px, 10vw, 130px) var(--gutter);
}
.processo-heading { max-width: 40ch; margin-bottom: 64px; }
.processo-heading h2 { color: var(--white); }
.timeline { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
.timeline-step {
  display: flex; flex-direction: column; gap: 16px;
  padding: 30px 26px;
  border-radius: var(--radius-m);
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.14);
  backdrop-filter: blur(18px) saturate(1.3);
  -webkit-backdrop-filter: blur(18px) saturate(1.3);
  transition: background var(--dur-m) var(--ease), border-color var(--dur-m) var(--ease), transform var(--dur-m) var(--ease);
}
.timeline-step:hover { background: rgba(255,255,255,0.1); border-color: rgba(255,255,255,0.28); transform: translateY(-4px); }
.timeline-index { font-family: var(--font-display); font-size: 1.9rem; color: rgba(255,255,255,0.42); font-weight: 440; }
.timeline-step h3 { color: var(--white); font-size: 1.02rem; letter-spacing: -0.005em; }
.timeline-step p { color: rgba(255,255,255,0.62); font-size: 0.86rem; line-height: 1.6; }

/* ---------------- Diferenciais ---------------- */
.diferenciais { position: relative; display: grid; grid-template-columns: 0.8fr 1.2fr; gap: clamp(56px, 8vw, 120px); align-items: start; }
/* Blueprint collage as near-imperceptible texture, never as a photo — it must
   reinforce the engineering motif without competing with the card grid */
.diferenciais-bg {
  position: absolute; top: -60px; right: 0; width: 480px; max-width: 42vw;
  opacity: 0.04; pointer-events: none; z-index: -1; filter: grayscale(1);
}
.diferenciais-intro { position: sticky; top: 140px; }
.diferenciais-intro h2 { margin: 0 0 24px; }
.diferenciais-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1px; background: var(--gray-200); border: 1px solid var(--gray-200); border-radius: var(--radius-m); overflow: hidden; }
.diferencial-card { background: var(--white); padding: 48px 40px; transition: background var(--dur-m) var(--ease); }
.diferencial-card:hover { background: var(--gray-50); }
.diferencial-card svg { width: 22px; height: 22px; color: var(--blue-deep); margin-bottom: 28px; stroke-width: 1.25; transition: transform var(--dur-s) var(--ease); }
.diferencial-card:hover svg { transform: translateY(-2px) scale(1.06); }
.diferencial-card h3 { margin-bottom: 10px; }
.diferencial-card p { font-size: 0.86rem; max-width: 26ch; }

/* ---------------- Portfolio carousel ---------------- */
.portfolio { padding-left: 0; padding-right: 0; }
.portfolio-heading { max-width: var(--container); margin: 0 auto 48px; padding: 0 var(--gutter); }
.carousel { position: relative; }
.carousel-track {
  display: flex; gap: 32px;
  overflow-x: auto; scroll-snap-type: x mandatory; scroll-behavior: smooth;
  padding: 4px var(--gutter) 16px;
  scrollbar-width: none;
}
.carousel-track::-webkit-scrollbar { display: none; }
.carousel-card { flex: 0 0 clamp(250px, 27vw, 360px); scroll-snap-align: start; }
.carousel-card .media-slot--vertical { border-radius: var(--radius-l); }
/* The source reels already carry their own burned-in project name, location
   and GMAT watermark — a second on-screen caption from us duplicated (and in
   places contradicted) that text and doubled up the branding. The overlay now
   only adds a minimal index mark; the real name/location stay in markup for
   accessibility and SEO but aren't rendered a second time on top of the clip. */
.carousel-card-overlay {
  position: absolute; inset: 0; z-index: 3;
  padding: 22px;
  pointer-events: none;
}
.carousel-card-index {
  display: inline-block;
  font-family: var(--font-display); font-style: italic; font-size: 0.85rem;
  color: rgba(255,255,255,0.8);
  letter-spacing: 0.02em;
  text-shadow: 0 1px 6px rgba(0,0,0,0.5);
}
.carousel-card-info {
  position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap;
}
.carousel-card .reel-video { transition: transform 1400ms var(--ease); }
.carousel-card:hover .reel-video { transform: scale(1.045); }
.carousel-arrow {
  position: absolute; top: 42%; transform: translateY(-50%); z-index: 3;
  width: 52px; height: 52px; border-radius: 50%;
  background: var(--white); border: 1px solid var(--gray-200);
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 12px 30px -12px rgba(0,0,0,0.18);
  transition: background var(--dur-s) var(--ease), transform var(--dur-s) var(--ease);
}
.carousel-arrow[hidden] { display: none; }
.carousel-arrow svg { width: 20px; height: 20px; color: var(--blue-deep); }
.carousel-arrow:hover { background: var(--blue-deep); transform: translateY(-50%) scale(1.05); }
.carousel-arrow:hover svg { color: var(--white); }
.carousel-arrow--prev { left: 12px; }
.carousel-arrow--next { right: 12px; }

/* ---------------- Portfolio PDF teaser ---------------- */
/* White backdrop with the photo collage faded into it (not a full-bleed dark
   photo) — the blue button is the one solid, opaque thing in the section. */
.portfolio-pdf-cta {
  position: relative;
  height: clamp(340px, 42vw, 560px);
  overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  background: var(--white);
}
.portfolio-pdf-cta .media-slot { position: absolute; inset: 0; border-radius: 0; background: var(--white); }
.portfolio-pdf-cta .media-slot img { opacity: 0.4; transition: transform 1400ms var(--ease); }
.portfolio-pdf-overlay {
  position: absolute; inset: 0; z-index: 1;
  /* Soft white vignette so the collage dissolves at the section's own edges
     into the page background instead of ending on a hard rectangle — the top
     edge gets an extra dedicated fade so it dissolves into the section above
     instead of starting on a flat line. */
  background:
    linear-gradient(180deg, var(--white) 0%, rgba(255,255,255,0) 18%),
    radial-gradient(120% 100% at 50% 50%, transparent 40%, rgba(255,255,255,0.55) 100%);
}
.portfolio-pdf-cta:hover .media-slot img { transform: scale(1.035); }
.portfolio-pdf-cta .btn {
  position: relative; z-index: 2;
  background: var(--blue-deep); color: var(--white);
}
.portfolio-pdf-cta .btn:hover { background: var(--blue-light); }

/* ---------------- Depoimentos ---------------- */
/* Deliberately the opposite language from Portfolio: that section is cool,
   architectural, gradient-and-zoom. This one is warmer and quieter — the
   play button is the single dominant object on each card (not the caption),
   because this section sells people, not buildings. */
.depoimentos { position: relative; color: var(--white); overflow: hidden; }
.depoimentos-media { position: absolute; inset: 0; filter: brightness(0.5) saturate(0.85); }
.depoimentos-overlay { position: absolute; inset: 0; background: linear-gradient(180deg, rgba(8,14,24,0.45), rgba(8,14,24,0.88)); }
.depoimentos-inner {
  position: relative; z-index: 2;
  max-width: var(--container); margin: 0 auto;
  padding: clamp(76px, 10vw, 130px) var(--gutter);
  text-align: center;
}
.depoimentos-inner h2 { color: var(--white); max-width: 34ch; margin: 24px auto 56px; }
.depoimentos-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 40px; max-width: 960px; margin: 0 auto; }
.depoimento-card { position: relative; text-align: center; transition: transform var(--dur-m) var(--ease); }
.depoimento-card:hover { transform: translateY(-6px); }
.media-slot--depoimento {
  border: none; box-shadow: 0 30px 60px -28px rgba(0,0,0,0.55);
  transition: box-shadow var(--dur-m) var(--ease);
}
.depoimento-card:hover .media-slot--depoimento { box-shadow: 0 36px 70px -24px rgba(0,0,0,0.65); }
.depoimento-card .media-slot--depoimento::after { color: rgba(255,255,255,0.5); }
.depoimento-card .media-slot--depoimento::before {
  content: '';
  position: absolute; inset: 0; z-index: 2;
  background: linear-gradient(180deg, rgba(8,14,24,0.05) 0%, transparent 30%, rgba(8,14,24,0.55) 100%);
  pointer-events: none;
}
.play-icon {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%);
  width: 68px; height: 68px; border-radius: 50%; z-index: 4;
  background: rgba(255,255,255,0.16); backdrop-filter: blur(10px);
  border: 1px solid rgba(255,255,255,0.4);
  display: flex; align-items: center; justify-content: center;
  transition: transform var(--dur-m) var(--ease), background var(--dur-m) var(--ease);
}
.play-icon svg { width: 22px; height: 22px; color: var(--white); margin-left: 2px; }
.depoimento-card:hover .play-icon { transform: translate(-50%,-50%) scale(1.1); background: var(--white); }
.depoimento-card:hover .play-icon svg { color: var(--blue-deep); }
.depoimento-name { display: block; margin-top: 22px; font-size: 0.88rem; font-weight: 600; letter-spacing: 0.01em; }
.depoimento-name small { font-weight: 400; color: rgba(255,255,255,0.6); }

/* Video modal */
.video-modal {
  position: fixed; inset: 0; z-index: 500;
  display: flex; align-items: center; justify-content: center;
  opacity: 0; visibility: hidden; transition: opacity var(--dur-s) var(--ease), visibility var(--dur-s);
}
.video-modal.open { opacity: 1; visibility: visible; }
.video-modal-backdrop { position: absolute; inset: 0; background: rgba(6,10,16,0.92); }
.video-modal-frame {
  position: relative; z-index: 2;
  width: min(92vw, 420px); aspect-ratio: 9/16;
  transform: scale(0.94); transition: transform var(--dur-m) var(--ease);
}
.video-modal.open .video-modal-frame { transform: scale(1); }
/* border-radius/overflow-hidden live on the <video> itself, not the frame —
   the frame must stay unclipped so the close button (positioned above it) is clickable */
.video-modal-frame video { width: 100%; height: 100%; object-fit: cover; background: #000; border-radius: var(--radius-m); }
.video-modal-close {
  position: absolute; top: -46px; right: 0; z-index: 3;
  width: 34px; height: 34px; color: var(--white);
}
.video-modal-close svg { width: 100%; height: 100%; }

/* PDF modal — a document viewer, so it takes most of the screen instead of
   the compact 9:16 frame the testimonial videos use. */
.pdf-modal {
  position: fixed; inset: 0; z-index: 500;
  display: flex; align-items: center; justify-content: center;
  opacity: 0; visibility: hidden; transition: opacity var(--dur-s) var(--ease), visibility var(--dur-s);
}
.pdf-modal.open { opacity: 1; visibility: visible; }
.pdf-modal-backdrop { position: absolute; inset: 0; background: rgba(6,10,16,0.92); }
.pdf-modal-frame {
  position: relative; z-index: 2;
  width: min(94vw, 1100px); height: min(90vh, 1400px);
  background: var(--gray-100);
  box-shadow: 0 40px 90px -30px rgba(0,0,0,0.6);
  transform: scale(0.96); transition: transform var(--dur-m) var(--ease);
}
.pdf-modal.open .pdf-modal-frame { transform: scale(1); }
/* border-radius lives on the iframe itself, not the frame — the frame must
   stay unclipped so the close button (positioned above it) is clickable,
   same fix as the testimonial video modal. */
.pdf-modal-frame iframe { width: 100%; height: 100%; border: 0; display: block; border-radius: var(--radius-m); }
.pdf-modal-actions {
  position: absolute; top: -46px; right: 0; z-index: 3;
  display: flex; align-items: center; gap: 20px;
}
/* Native PDF rendering inside an iframe is reliable in every mainstream
   desktop and mobile browser, but a few in-app/embedded webviews don't
   support it — this quiet fallback link always works since it just hands
   the browser the file directly. */
.pdf-modal-newtab {
  font-size: 0.8rem; color: rgba(255,255,255,0.75);
  border-bottom: 1px solid rgba(255,255,255,0.35);
  transition: color var(--dur-s) var(--ease), border-color var(--dur-s) var(--ease);
}
.pdf-modal-newtab:hover { color: var(--white); border-color: var(--white); }
.pdf-modal-close { width: 34px; height: 34px; color: var(--white); }
.pdf-modal-close svg { width: 100%; height: 100%; }
@media (max-width: 640px) {
  .pdf-modal-actions {
    top: 14px; right: 14px; z-index: 4;
    background: rgba(6,10,16,0.55); backdrop-filter: blur(8px);
    padding: 8px 12px; border-radius: 100px;
  }
  .pdf-modal-frame { width: 100vw; height: 100svh; }
  .pdf-modal-frame iframe { border-radius: 0; }
  .pdf-modal-close { top: 14px; right: 14px; }
}

/* ---------------- Marquee band ---------------- */
/* The visual "breath" the brief asked for between two consecutive video
   sections — a quiet, solid-color pause before the final cinematic CTA. */
.marquee-band {
  position: relative;
  overflow: hidden;
  background: var(--blue-deep);
  padding: 30px 0;
  border-top: 1px solid rgba(255,255,255,0.08);
  border-bottom: 1px solid rgba(255,255,255,0.08);
}
.marquee-track {
  display: flex; align-items: center; width: max-content;
  animation: marquee 38s linear infinite;
  will-change: transform;
}
.marquee-track span {
  font-family: var(--font-body);
  font-weight: 600;
  text-transform: uppercase;
  font-size: clamp(0.78rem, 1.3vw, 0.95rem);
  letter-spacing: 0.22em;
  color: rgba(255,255,255,0.82);
  white-space: nowrap;
  padding: 0 20px;
}
.marquee-track .marquee-dot { color: rgba(255,255,255,0.3); }
@keyframes marquee { from { transform: translate3d(0,0,0); } to { transform: translate3d(-50%,0,0); } }
/* Root cause of "frozen on desktop, fine on mobile": the global a11y reset
   above (`*,*::before,*::after{animation-duration:0.01ms!important;
   animation-iteration-count:1!important}`) collapses EVERY animation on the
   page — including this one — the instant prefers-reduced-motion is on,
   which is an OS-level toggle far more commonly left on for a desktop
   (macOS "Reduce Motion" / Windows "Show animations") than for a phone. That
   made the marquee look broken specifically on desktop test machines with
   the setting enabled, with zero relation to viewport width, ScrollTrigger,
   Lenis, or scrollWidth. This is a purely decorative, aria-hidden, low-
   intensity linear scroll — not the kind of motion the preference exists to
   suppress (unlike parallax/zoom) — so it's explicitly exempted here with
   matching !important specificity, while every other reduced-motion rule in
   this file keeps behaving exactly as before. */
@media (prefers-reduced-motion: reduce) {
  .marquee-track { animation: marquee 30s linear infinite !important; }
}

/* ---------------- CTA final ---------------- */
.cta-final { position: relative; color: var(--white); overflow: hidden; }
.cta-media { position: absolute; inset: 0; }
/* The house has to stay fully visible — only a faint wash for overall page
   consistency now. Legibility comes from the glass panel below, not from
   hiding the footage under a dark scrim. */
.cta-overlay {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(6,10,16,0.1) 0%, rgba(6,10,16,0.02) 35%, rgba(6,10,16,0.22) 100%);
}
.cta-inner {
  position: relative; z-index: 2; text-align: center;
  max-width: 780px; margin: 0 auto;
  padding: clamp(70px, 9vw, 110px) var(--gutter);
}
/* Glassmorphism panel: the video reads through it, but the tint + blur give
   white text reliable contrast no matter what's playing behind at that moment. */
.cta-glass {
  background: rgba(8,14,24,0.48);
  backdrop-filter: blur(28px) saturate(1.5);
  -webkit-backdrop-filter: blur(28px) saturate(1.5);
  border: 1px solid rgba(255,255,255,0.16);
  border-radius: var(--radius-l);
  padding: clamp(44px, 6vw, 72px) clamp(32px, 5vw, 64px);
  box-shadow: 0 40px 90px -36px rgba(0,0,0,0.6), inset 0 1px 0 rgba(255,255,255,0.08);
}
.cta-inner h2 { color: var(--white); font-size: clamp(2.4rem, 4.6vw, 3.8rem); margin: 26px auto 22px; }
.cta-inner .lead { font-size: 1.1rem; color: rgba(255,255,255,0.85); margin: 0 auto 40px; }
.cta-inner .hero-actions { justify-content: center; margin-bottom: 36px; }
.cta-contacts { display: flex; align-items: center; justify-content: center; gap: 12px; flex-wrap: wrap; font-size: 0.88rem; color: rgba(255,255,255,0.7); }

/* ---------------- Footer ---------------- */
.footer { position: relative; background: var(--gray-50); overflow: hidden; }
.footer-inner {
  position: relative; z-index: 1;
  max-width: var(--container); margin: 0 auto;
  padding: 90px var(--gutter) 50px;
  display: grid; grid-template-columns: 1.6fr 1fr 1fr 1fr; gap: 40px;
}
.footer-brand p { font-size: 0.88rem; max-width: 32ch; margin-top: 18px; }
.footer-col h4 { font-size: 0.75rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--gray-500); margin-bottom: 18px; }
.footer-col a { display: block; font-size: 0.9rem; margin-bottom: 12px; color: var(--gray-700); transition: color var(--dur-s) var(--ease); }
.footer-col a:hover { color: var(--blue-deep); }
.footer-bottom {
  position: relative; z-index: 1;
  max-width: var(--container); margin: 0 auto;
  padding: 24px var(--gutter);
  border-top: 1px solid var(--gray-200);
  display: flex; justify-content: space-between; flex-wrap: wrap; gap: 12px;
  font-size: 0.8rem; color: var(--gray-500);
}

/* ---------------- WhatsApp floating button ---------------- */
.whatsapp-float {
  position: fixed; right: 24px; bottom: 24px; z-index: 120;
  width: 56px; height: 56px; border-radius: 50%;
  background: var(--blue-deep); color: var(--white);
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 16px 32px -14px rgba(var(--blue-deep-rgb), 0.6);
  transition: transform var(--dur-s) var(--ease), background var(--dur-s) var(--ease);
}
.whatsapp-float:hover { background: var(--blue-light); transform: scale(1.08); }

/* ---------------- Reveal animation system ---------------- */
/* GSAP (see app.js initScrollAnimations) owns the actual animation — it reads
   this hidden state and tweens opacity/transform/filter with ScrollTrigger,
   staggering title → subtitle → description → cards → buttons in DOM order.
   No CSS transition here on purpose: letting both CSS and GSAP drive the same
   properties at once causes stutter. This class is only ever the resting
   "not yet revealed" state; if the CDN scripts fail to load, app.js's
   fallback removes it from every element immediately instead. */
.reveal { opacity: 0; }
.reveal[data-reveal="fade-up"] { transform: translateY(30px); }

/* Very light parallax on full-bleed media (hero, processo) — JS drives a
   translateY custom property on scroll; kept to a few percent of travel so it
   reads as depth, never as a distinct "effect". */
.hero-media, .processo-media { transform: translateY(var(--parallax-y, 0)); will-change: transform; }

/* ============================================================
   Responsive
   ============================================================ */
@media (max-width: 980px) {
  .main-nav { position: fixed; top: 0; right: 0; height: 100svh; width: min(320px, 84vw);
    background: var(--white); color: var(--ink);
    flex-direction: column; align-items: flex-start; justify-content: center; gap: 26px;
    padding: 0 40px; transform: translateX(100%); transition: transform var(--dur-m) var(--ease);
    box-shadow: -16px 0 40px rgba(0,0,0,0.12);
  }
  .main-nav.open { transform: translateX(0); }
  .nav-toggle { display: flex; }
  .nav-toggle.open span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
  .nav-toggle.open span:nth-child(2) { opacity: 0; }
  .nav-toggle.open span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

  .split, .diferenciais { grid-template-columns: 1fr; }
  .diferenciais-intro { position: static; }
  .split-reverse { direction: ltr; }
  .split-media { order: -1; }
  .diferenciais-grid { grid-template-columns: 1fr 1fr; }
  .timeline { grid-template-columns: 1fr 1fr; }
  .depoimentos-grid { grid-template-columns: repeat(3, 1fr); gap: 16px; }
}

@media (max-width: 640px) {
  /* The editorial "text fully right, subject fully left" split needs width to
     breathe — on a narrow screen it collapses to a full-width block with a
     flat dark base instead, so the copy never sits half on sky, half on overlay. */
  .hero-media video, .hero-media img { object-position: 58% 32%; }

  /* Mobile-only cinematic pan: the source video is landscape, so covering a
     portrait viewport crops most of its width — the visitor never sees
     Guilherme and the build together. Widening the video's own box (a real
     layout width, not a transform scale) makes object-fit:cover reveal more
     of that width up front; a slow transform:translateX ping-pongs across
     the resulting slack for a gentle horizontal "travelling" reveal. Content
     (text/logo/button) lives in a separate element entirely, so none of this
     touches it. Desktop keeps the original heroDrift zoom/nudge untouched —
     this overrides it only under 640px. */
  .hero-media video {
    width: 116%;
    max-width: none;
    left: -8%;
    animation: heroPanMobile 20s ease-in-out infinite;
  }
  @keyframes heroPanMobile {
    0%   { transform: translateX(-8%); }
    50%  { transform: translateX(8%); }
    100% { transform: translateX(-8%); }
  }

  .hero-overlay {
    background:
      linear-gradient(0deg, rgba(6,10,16,0.92) 0%, rgba(6,10,16,0.55) 38%, rgba(6,10,16,0.2) 62%, rgba(6,10,16,0.35) 100%);
  }
  .hero-content { padding: 128px var(--gutter) 64px; justify-content: flex-start; }
  .hero-content-inner { max-width: none; }
  .hero-title { max-width: none; }
  .scroll-indicator { left: var(--gutter); right: auto; }
  .hero-actions { flex-direction: column; align-items: stretch; }
  .hero-actions .btn { justify-content: center; }
  .hero-stats { gap: 26px; flex-wrap: wrap; }
  .mini-cards, .diferenciais-grid, .timeline { grid-template-columns: 1fr; }
  .depoimentos-grid { grid-template-columns: 1fr; max-width: 280px; }
  .footer-inner { grid-template-columns: 1fr 1fr; }
  .footer-brand { grid-column: 1 / -1; }
  .carousel-arrow { width: 42px; height: 42px; }
  .whatsapp-float { right: 16px; bottom: 16px; width: 50px; height: 50px; }

  /* Chapter labels sit tighter to their headline on small screens */
  .eyebrow { margin-bottom: 8px; }

  /* Tighten the gap between Capítulo 03 (Diferenciais) and Capítulo 04 (Portfólio) */
  .diferenciais { padding-bottom: 40px; }
  .portfolio { padding-top: 40px; }

  /* Capítulo 06 (#consolidacao) on mobile: the video becomes the section's
     own background — flush against the end of Depoimentos, no white band —
     with the eyebrow + title overlaid near its top, the same pattern already
     used by Hero/Processo/Depoimentos/CTA. Desktop keeps the original
     side-by-side split untouched (this block only applies ≤640px). */
  #consolidacao {
    position: relative;
    display: block;
    padding: 0;
    min-height: 72svh;
    overflow: hidden;
    color: var(--white);
  }
  #consolidacao .split-media {
    position: absolute; inset: 0;
    order: 0;
  }
  #consolidacao .media-slot--tall {
    width: 100%; height: 100%;
    aspect-ratio: auto;
    border-radius: 0;
  }
  #consolidacao .split-content {
    position: relative; z-index: 2;
    padding: 56px var(--gutter) 0;
    max-width: none;
  }
  /* Legibility lives only in the text's own footprint now — no section-wide
     scrim. A blurred, feather-masked patch sits just behind the eyebrow+title
     (bleeding a little past their edges for the fade to complete before it
     reaches the letters) so the rest of the video stays fully clean. No
     visible box: no border, no flat opacity edge, no shadow — the mask fades
     the blur+tint to nothing before it can read as a shape. */
  #consolidacao .split-content::before {
    content: '';
    position: absolute;
    top: 28px; left: -16px; right: -16px; bottom: 12px;
    backdrop-filter: blur(7px);
    -webkit-backdrop-filter: blur(7px);
    background: linear-gradient(180deg, rgba(6,10,16,0.22) 0%, rgba(6,10,16,0.14) 55%, rgba(6,10,16,0) 100%);
    -webkit-mask-image: radial-gradient(110% 100% at 50% 32%, #000 42%, transparent 78%);
    mask-image: radial-gradient(110% 100% at 50% 32%, #000 42%, transparent 78%);
    pointer-events: none;
  }
  #consolidacao .eyebrow, #consolidacao h2 {
    color: var(--white);
    text-shadow: 0 1px 10px rgba(0,0,0,0.3);
  }
  #consolidacao .eyebrow { margin-bottom: 6px; }
  #consolidacao h2 em { color: #FFFFFF; }
}

/* Placed last on purpose so it wins the cascade over both heroDrift (desktop)
   and heroPanMobile regardless of viewport width. */
@media (prefers-reduced-motion: reduce) {
  .hero-media video { animation: none; transform: none; }
}
