/* ==========================================================================
   VP Design System — Section Layouts
   Page-level composition. Class names marked [Lumora] are verbatim.
   ========================================================================== */


/* ==========================================================================
   HERO — #home  [Lumora structure, verbatim]
   Layer order, back to front:
     0  .liquid-wrap      canvas: drifting gradient field + pointer trails
     1  .hero-vignette    top/bottom white falloff so edges stay legible
     1  .hero-watermark   the real VP symbol, oversized, very low alpha
     20 .hero-grid        12-col content
     20 .hero-status-bar  bottom rule
   ========================================================================== */
#home {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  border-radius: 0 0 var(--radius-card) var(--radius-card);
  /* Painted fallback: this is what the hero looks like before the canvas
     field mounts, and what it stays as if canvas is unavailable. */
  background: var(--gradient-hero);
  min-height: 100lvh;
  display: flex; flex-direction: column; justify-content: space-between;
}

.liquid-wrap { position: absolute; inset: 0; z-index: var(--z-base); overflow: hidden; }
.liquid-wrap canvas { position: absolute; inset: 0; width: 100%; height: 100%; }

/* Hero background video — grayscaled, then re-tinted with --gradient-accent
   via mix-blend-mode so it always matches the current brand colour and
   theme, instead of shipping a fixed colour grade baked into the file.
   `--hero-video-invert` flips light-mode's luminance (source clip is dark)
   so it reads as a light texture instead of a dark video on a white page. */
.hero-bg-video {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover;
  filter: grayscale(1) invert(var(--hero-video-invert, 0)) brightness(1.05) contrast(1.08);
}
.hero-video-tint {
  position: absolute; inset: 0;
  background: var(--gradient-accent);
  mix-blend-mode: color;
  opacity: 0.85;
  pointer-events: none;
}

.hero-vignette {
  position: absolute; inset: 0; z-index: var(--z-raised);
  pointer-events: none;
  background: var(--vignette);
}

/* Watermark — the REAL symbol file, not a text glyph and not a redraw */
.hero-watermark {
  pointer-events: none; user-select: none;
  position: absolute; right: 4vw; bottom: 8rem; z-index: var(--z-raised);
  display: grid; place-items: center;
  opacity: 0; transform: translateY(20px);
  transition: opacity var(--duration-line) var(--ease-entrance),
              transform var(--duration-line) var(--ease-entrance);
}
.hero-watermark img { width: min(26rem, 34vw); height: auto; opacity: 0.10; }
.hero-watermark.revealed { opacity: 1; transform: translateY(0); }

.hero-grid {
  position: relative; z-index: var(--z-content);
  display: flex; flex-direction: column; gap: var(--space-8);
  padding: var(--space-28) var(--gutter) var(--space-20);
  width: 100%;
}
@media (min-width: 640px) { .hero-grid { padding-inline: var(--gutter-lg); } }
@media (min-width: 1024px) {
  .hero-grid {
    display: grid; grid-template-columns: repeat(12, 1fr); gap: var(--space-10);
    padding: 9rem var(--gutter-lg) var(--space-28);
    min-height: calc(100lvh - 4rem);
    align-items: start;
  }
}
.hero-left  { display: flex; flex-direction: column; gap: 1.75rem; }
@media (min-width: 1024px) { .hero-left { grid-column: span 7; } }
.hero-right { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-8); }
@media (min-width: 1024px) { .hero-right { grid-column: span 5; align-items: flex-end; } }

/* Hero headline — display tier, solid --foreground (17.99:1 on the field's
   lightest point, 11.4:1 on its darkest). NOT `mix-blend-mode: difference`:
   against this mid-tone field that blend collapses to ~1.03:1. See the
   constraint note on `.blend-difference` in motion.css. */
.hero-headline {
  font-family: var(--font-display);
  font-weight: var(--weight-light);
  font-size: var(--text-display);
  line-height: var(--lh-display);
  letter-spacing: var(--ls-display);
  max-width: 20ch;
}
/* Keeping each .line-reveal-wrap to ONE rendered line is what makes M1b read as
   type being *set* rather than a block sliding up: the lines then arrive one
   after another, 120ms apart, instead of moving as a slab.
   It is a quality choice, not a correctness one — a wrapped line still reveals
   fully, because translateY(100%) is relative to the wrap's own grown height.
   So below 640px, where nowrap would overflow the viewport, it is dropped. */
.hero-headline .line-reveal-wrap { white-space: nowrap; }
@media (max-width: 639.98px) {
  .hero-headline .line-reveal-wrap { white-space: normal; }
}

.hero-status-bar {
  position: relative; z-index: var(--z-content);
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  border-top: 1px solid var(--fg-10);
  padding: var(--gutter);
  font-size: var(--text-caption); font-weight: var(--weight-medium);
  text-transform: uppercase; letter-spacing: var(--ls-wide);
  color: var(--fg-60);
}
@media (min-width: 640px) { .hero-status-bar { padding-inline: var(--gutter-lg); } }
.hero-status-mid { display: none; }
@media (min-width: 640px) { .hero-status-mid { display: inline; } }

/* .partners-grid / .partner-item [Lumora, verbatim] — repurposed as the
   content-pillar strip */
.partners-grid { display: grid; grid-template-columns: repeat(2, 1fr); column-gap: var(--space-4); row-gap: var(--space-3); }
@media (min-width: 480px) { .partners-grid { grid-template-columns: repeat(3, 1fr); } }
.partner-item {
  display: flex; align-items: center; gap: 0.375rem;
  font-size: var(--text-caption); color: var(--fg-70);
  transition: all var(--duration-hover) var(--ease-standard);
}
@media (hover: hover) { .partner-item:hover { transform: translateY(-2px); color: var(--foreground); } }


/* ==========================================================================
   GENERIC SECTION RHYTHM — .section
   Every fold below the hero uses this. One vertical rhythm, no exceptions.
   ========================================================================== */
.section { background: var(--background); padding-block: var(--space-20); }
@media (min-width: 1024px) { .section { padding-block: var(--space-28); } }
.section.tight { padding-block: var(--space-12); }
.section.dark  { background: var(--ink); color: #fff; }
.section.soft  { background: var(--surface); }

.section-header { display: flex; flex-direction: column; gap: var(--space-4); margin-bottom: var(--space-12); }
.section-header .section-title { max-width: 18ch; }
.section-header .section-lede  { max-width: 52ch; color: var(--fg-70); }
.section.dark .section-header .section-lede { color: var(--on-dark-60); }
.section-header.centered { align-items: center; text-align: center; }


/* ==========================================================================
   ABOUT — #about  [Lumora .about-grid, verbatim]
   The signature lives here: it is the human counterweight to a geometric
   system, so it gets the quiet column, not the loud one.
   ========================================================================== */
#about { background: var(--background); }
.about-grid { display: grid; grid-template-columns: 1fr; align-items: center; gap: var(--space-12); padding-block: var(--space-20); }
@media (min-width: 1024px) { .about-grid { grid-template-columns: 1fr 1fr; padding-block: var(--space-28); } }

.signature-block {
  position: relative; min-height: 14rem;
  display: flex; flex-direction: column; justify-content: space-between; gap: var(--space-8);
}
@media (min-width: 1024px) { .signature-block { min-height: 20rem; } }
/* Sits in the gap to the right of the fixed-width (max-width: 20rem) photo,
   not to the left of the block — the left edge is flush with the shell
   gutter and has no room to bleed without colliding with the photo.
   Hidden below 768px: at phone widths that gap is too narrow to hold it. */
.signature-mark {
  display: none;
  position: absolute; right: 0.5rem; top: 50%;
  transform: translateY(-50%);
  width: 12rem; height: auto;
  opacity: 0.06;
  pointer-events: none;
}
@media (min-width: 768px)  { .signature-mark { display: block; } }
@media (min-width: 1024px) { .signature-mark { width: 14rem; right: 1rem; } }

/* About portrait — the signature moves off the page (it was showing up too
   often across the site) and becomes a small corner mark on the photo itself,
   like a print signed by hand. */
.about-photo-wrap {
  position: relative; overflow: hidden;
  max-width: 20rem;
  border-radius: var(--radius-card);
  border: var(--edge);
}
.about-photo { display: block; width: 100%; height: auto; object-fit: cover; }
.about-photo-signature {
  position: absolute; right: var(--space-4); bottom: var(--space-4);
  width: 4rem; height: auto;
  opacity: 0.9;
  pointer-events: none;
}


/* ==========================================================================
   PILLAR BAND — .create-list / .create-tile  [Lumora, verbatim]
   Repurposed to carry the positioning statement across four pill tiles.
   ========================================================================== */
.create-list { display: flex; flex-direction: column; gap: var(--space-3); padding-block: var(--space-10); }
@media (min-width: 640px) { .create-list { flex-direction: row; gap: var(--space-4); } }
.create-item { flex: 1; }
.create-tile {
  display: grid; place-items: center;
  height: 6rem;
  border-radius: var(--radius-pill);
  font-family: var(--font-display);
  font-size: var(--text-h3); font-weight: var(--weight-light);
  letter-spacing: var(--ls-snug);
  text-align: center;
  padding-inline: var(--space-4);
  transition: transform var(--duration-hover) var(--ease-standard);
}
@media (min-width: 640px) { .create-tile { height: 10rem; font-size: 2.25rem; } }
@media (hover: hover) { .create-tile:hover { transform: scale(1.03); } }
.create-tile.surface  { background: var(--surface-warm); color: var(--foreground); }
.create-tile.gradient { background: var(--gradient-accent); color: #fff; }
.create-tile.ink      { background: var(--ink); color: #fff; }
.create-tile.ghost    { background: var(--surface-tint); color: var(--fg-60); }


/* ==========================================================================
   VISION BAND — #vision / .vision-box  [Lumora, verbatim]
   The interactive gradient canvas. Second instance of the M2/liquid mechanism.
   ========================================================================== */
#vision { background: var(--background); padding-block: var(--space-8) var(--space-12); }
@media (min-width: 1024px) { #vision { padding-bottom: var(--space-16); } }
.vision-box {
  position: relative; overflow: hidden;
  border-radius: var(--radius-card);
  min-height: 28rem;
  background: var(--gradient-vision);
  border: 1px solid rgba(229, 228, 226, 0.25);
  box-shadow: var(--shadow-deep);
  display: flex; align-items: center;
  padding: var(--space-12) var(--space-6);
}
@media (min-width: 640px)  { .vision-box { min-height: 32rem; padding: var(--space-16) var(--space-12); } }
@media (min-width: 1024px) { .vision-box { min-height: 35rem; padding: var(--space-20) var(--space-16); } }
.vision-dots {
  position: absolute; inset: 0; z-index: var(--z-raised); pointer-events: none;
  background-image: radial-gradient(rgba(229, 228, 226, 0.14) 1px, transparent 1px);
  background-size: 24px 24px;
}

/* Vision card photo — grayscale by default, tinted with the brand accent on
   hover via mix-blend-mode (the source photo has no colour data to "restore",
   so the reveal is a deliberate brand-colour wash, not the original colour). */
.vision-bg { position: absolute; inset: 0; z-index: var(--z-base); overflow: hidden; }
.vision-bg-img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover;
  object-position: 65% center;
  filter: grayscale(1);
}
.vision-bg-tint {
  position: absolute; inset: 0;
  background: var(--gradient-accent);
  mix-blend-mode: color;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--duration-slow) var(--ease-soft);
}
.vision-box:hover .vision-bg-tint,
.vision-box:focus-within .vision-bg-tint { opacity: 0.85; }

/* Text-protection scrim — the photo's own tones vary too much (a person, a
   bright doorway) to guarantee contrast for the copy sitting on top, so the
   left column always gets a dark wash regardless of what the photo shows. */
.vision-bg::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(to right, rgba(10, 10, 10, 0.82), rgba(10, 10, 10, 0.35) 45%, transparent 72%);
}
/* The gradient above is tuned for a wide desktop card, where .vision-content
   (44rem max) only covers a fraction of the width, leaving the 72–100%
   stop's clear photo visible on the right. On a narrow mobile card the
   content spans nearly the full width, so that same left-anchored gradient
   reads as almost entirely dark — the photo looks gone, not just dimmed.
   Swap to a flatter top-to-bottom wash that keeps the text readable without
   burying the photo under dark edge-to-edge. */
@media (max-width: 767.98px) {
  .vision-bg::after {
    background: linear-gradient(to bottom, rgba(10, 10, 10, 0.35), rgba(10, 10, 10, 0.72));
  }
}
.vision-content { max-width: 44rem; position: relative; z-index: 10; pointer-events: none; }
.vision-content .pill-btn { pointer-events: auto; }
.vision-badge {
  display: inline-flex; align-items: center; gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-pill);
  background: rgba(20, 24, 28, 0.75);
  border: 1px solid rgba(229, 228, 226, 0.3);
  backdrop-filter: blur(10px);
  font-size: var(--text-caption); font-weight: var(--weight-semibold);
  text-transform: uppercase; letter-spacing: var(--ls-wider);
  /* Fixed light text, not a theme-aware token: the pill's own background
     above is a hardcoded dark rgba() in both themes, so --surface-2 (which
     flips dark in dark mode) would go dark-on-dark and disappear. */
  color: var(--on-dark-90);
}
.vision-badge .dot {
  width: 0.5rem; height: 0.5rem; border-radius: var(--radius-pill);
  background: var(--accent); box-shadow: 0 0 10px var(--accent);
}


/* ==========================================================================
   WORK / PILLARS GRID — #works  [Lumora .portfolio-grid, verbatim]
   ========================================================================== */
#works { background: var(--background); padding-block: var(--space-10) var(--space-20); }
@media (min-width: 1024px) { #works { padding-bottom: var(--space-28); } }
.portfolio-grid { display: grid; grid-template-columns: 1fr; gap: var(--space-6); margin-top: var(--space-12); }
@media (min-width: 768px) { .portfolio-grid { grid-template-columns: repeat(2, 1fr); } }


/* ==========================================================================
   SERVICES — #services  [Lumora, verbatim]
   ========================================================================== */
#services { background: var(--background); padding-block: var(--space-20); }
@media (min-width: 1024px) { #services { padding-block: var(--space-28); } }
.service-list > li + li { border-top: 1px solid var(--line-warm); }
.service-num  { width: 1.75rem; font-size: var(--text-body-sm); font-weight: var(--weight-medium); color: var(--fg-60); flex-shrink: 0; }
@media (min-width: 640px) { .service-num { width: 2.5rem; } }
.service-desc { display: none; max-width: 20rem; font-size: var(--text-body-sm); color: var(--fg-60); }
@media (min-width: 1024px) { .service-desc { display: block; } }


/* ==========================================================================
   TESTIMONIALS — #testimonials
   ========================================================================== */
#testimonials { background: var(--surface); padding-block: var(--space-20); overflow: hidden; }
@media (min-width: 1024px) { #testimonials { padding-block: var(--space-28); } }
.testimonial-placeholder-note {
  display: inline-flex; align-items: center; gap: var(--space-2);
  border: 1px dashed var(--accent-25);
  background: var(--accent-05);
  border-radius: var(--radius-pill);
  padding: var(--space-2) var(--space-4);
  font-size: var(--text-caption);
  color: var(--accent);
  font-weight: var(--weight-medium);
}


/* ==========================================================================
   STATS — .stats-panel / .stats-grid  [Lumora, verbatim]
   ========================================================================== */
.stats-panel { border-radius: var(--radius-card); background: var(--ink); padding: var(--space-12) var(--space-6); color: #fff; }
@media (min-width: 640px) { .stats-panel { padding: var(--space-16) var(--space-8); } }
@media (min-width: 768px) { .stats-panel { padding-inline: var(--space-16); } }
.stats-grid { margin-top: var(--space-14); display: grid; grid-template-columns: repeat(2, 1fr); column-gap: var(--space-8); row-gap: var(--space-12); }
@media (min-width: 1024px) { .stats-grid { grid-template-columns: repeat(4, 1fr); } }
.stat-value {
  font-family: var(--font-display);
  font-size: var(--text-h1); font-weight: var(--weight-light);
  letter-spacing: var(--ls-tight);
  font-variant-numeric: tabular-nums;
}
.stat-label { margin-top: var(--space-3); font-size: var(--text-body-sm); color: var(--on-dark-55); }


/* ==========================================================================
   FOOTER  [Lumora, verbatim]
   ========================================================================== */
footer {
  position: relative; overflow: hidden;
  border-radius: var(--radius-card) var(--radius-card) 0 0;
  background: var(--ink); color: #fff;
}
.footer-cta-row {
  display: flex; flex-direction: column; gap: var(--space-8);
  border-bottom: 1px solid var(--on-dark-10);
  padding-bottom: var(--space-16);
}
@media (min-width: 1024px) { .footer-cta-row { flex-direction: row; align-items: flex-end; justify-content: space-between; } }
.footer-cols { display: grid; grid-template-columns: 1fr; gap: var(--space-12); padding-block: var(--space-16); }
@media (min-width: 768px)  { .footer-cols { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .footer-cols { grid-template-columns: repeat(4, 1fr); } }
.footer-col-title {
  font-size: var(--text-caption); text-transform: uppercase; letter-spacing: var(--ls-wide);
  color: var(--on-dark-55); margin-bottom: var(--space-5);
}
.footer-links { display: flex; flex-direction: column; gap: var(--space-3); font-size: var(--text-body-sm); }
.footer-links a { opacity: 0.65; }
.footer-legal {
  display: flex; flex-direction: column; align-items: center; justify-content: space-between; gap: var(--space-4);
  border-top: 1px solid var(--on-dark-10);
  padding-top: var(--space-8);
  font-size: var(--text-caption); color: var(--on-dark-55);
}
@media (min-width: 640px) { .footer-legal { flex-direction: row; } }
.footer-watermark {
  position: absolute; inset-inline: 0; bottom: -2rem; z-index: var(--z-base);
  display: grid; place-items: center;
  pointer-events: none; user-select: none;
}
.footer-watermark img { width: min(40rem, 70vw); height: auto; opacity: 0.045; }
.footer-inner { position: relative; z-index: 10; padding: var(--space-20) var(--gutter) var(--space-10); }
@media (min-width: 640px)  { .footer-inner { padding-inline: var(--gutter-lg); } }
@media (min-width: 1024px) { .footer-inner { padding-top: 6rem; } }


/* ==========================================================================
   PROCESS — #process
   The M4 pin, instantiated. A 200vh track whose child pins for 100vh while
   three stages cross-fade on scrub. Closes open question Q4.

   IMPORTANT: this composes M1–M4, it does not add a fifth pattern.
     · the pin and the curtains are M4 (.sticky-scene, ported from textura)
     · the stage cross-fade is M4 as well — a property scrubbed along the pin,
       exactly like the curtain wipes, not a new kind of motion
     · the ambient rail fill is M2a (vp-gradient-drift)
     · the CTA is the same M3 chain as every other fold
   ========================================================================== */
/* margin-bottom: 0 overrides the shared .sticky-scene's -100vh pull. That pull
   makes #services start exactly where the pin begins sliding away, so the two
   sit on the exact same screen position for the whole exit — whichever one
   paints on top hides the other's content instead of a clean handoff. Zeroing
   it means Serviços only enters once Método has fully slid off, at the cost
   of ~100vh of extra scroll while it exits. */
#process { background: var(--background); margin-bottom: 0; }
#process .sticky { display: grid; place-items: center; background: var(--background); }

.process-inner {
  position: relative; z-index: var(--z-content);
  width: 100%;
  display: flex; flex-direction: column; gap: var(--space-10);
}

/* Stage stack.
   DEFAULT = all three stages in normal flow, fully visible. That is the
   no-JS / no-GSAP state, and it is a legible (if unscrubbed) section.
   `.is-scrubbed` is added by JS only once GSAP is confirmed, which is what
   collapses them into one absolutely-positioned stack for the cross-fade.
   Written this way round so the failure mode is "less motion", never
   "invisible content". */
.process-stages { position: relative; display: flex; flex-direction: column; gap: var(--space-10); }
.process-stage  { display: flex; flex-direction: column; gap: var(--space-5); }

.process-stages.is-scrubbed { display: block; min-height: 20rem; }
.process-stages.is-scrubbed .process-stage {
  position: absolute; inset: 0;
  opacity: 0;
  will-change: opacity, transform;
}
.process-stages.is-scrubbed .process-stage:first-child { opacity: 1; }

.process-num {
  font-family: var(--font-mono);
  font-size: var(--text-caption);
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--ls-wider);
  color: var(--accent);
}
.process-title {
  font-family: var(--font-display);
  font-weight: var(--weight-light);
  font-size: var(--text-h1);
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-tight);
  max-width: 16ch;
}
.process-body { max-width: 46ch; color: var(--fg-70); }

/* Progress rail — three segments, one per stage. The active segment carries
   the M2a drift loop, so the indicator is the same ambient motion as the
   primary CTA rather than a bespoke animation. */
.process-rail { display: flex; gap: var(--space-2); width: 100%; max-width: 34rem; }
.process-rail-seg {
  flex: 1; height: 2px;
  border-radius: var(--radius-pill);
  background: var(--line);
  overflow: hidden;
}
.process-rail-seg span {
  display: block; height: 100%; width: 0%;
  border-radius: var(--radius-pill);
  background: var(--gradient-loop) 0% 0% / 200% 200%;
  animation: vp-gradient-drift var(--loop-gradient) ease 0s infinite normal none running;
}
.process-rail-labels {
  display: flex; gap: var(--space-2); width: 100%; max-width: 34rem;
  font-size: var(--text-helper); color: var(--fg-60);
}
.process-rail-labels span { flex: 1; }

/* The pinned scene keeps its own quiet backdrop: the dotted texture from the
   vision band, at page-surface contrast. No third canvas instance — three
   simultaneous fields would cost more than the fold is worth. */
.process-texture {
  position: absolute; inset: 0; z-index: var(--z-base); pointer-events: none;
  background-image: radial-gradient(var(--fg-10) 1px, transparent 1px);
  background-size: 28px 28px;
  -webkit-mask-image: radial-gradient(ellipse at center, #000 20%, transparent 72%);
          mask-image: radial-gradient(ellipse at center, #000 20%, transparent 72%);
}

/* Below 480px the stage box gets a little extra headroom: the same text at
   the same rem size wraps to more lines on a narrower measure, and
   `.process-stages.is-scrubbed .process-stage` is `position:absolute;inset:0`
   — its content can grow past the box without the box itself growing, which
   would push past the pinned `.sticky`'s `overflow:hidden` 100dvh. */
@media (max-width: 479.98px) {
  #who .process-stages.is-scrubbed { min-height: 27rem; }
  #process .process-stages.is-scrubbed { min-height: 23rem; }
  #about .process-stages.is-scrubbed { min-height: 26rem; }
}


/* ==========================================================================
   THEME-SWAPPED BRAND ASSETS
   Both fills of the symbol and the signature are real, approved files. Which
   one is correct depends on the surface, and in dark mode the surface flips —
   so the page ships both and CSS chooses. This is the reason Vitor supplied
   two variants; it is not a filter or a re-colour of one file.
   ========================================================================== */
[data-theme-img] { display: inline-flex; }
[data-theme-img] > .for-dark  { display: none; }
[data-theme-img] > .for-light { display: block; }

:root[data-theme="dark"] [data-theme-img] > .for-light { display: none; }
:root[data-theme="dark"] [data-theme-img] > .for-dark  { display: block; }

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) [data-theme-img] > .for-light { display: none; }
  :root:not([data-theme="light"]) [data-theme-img] > .for-dark  { display: block; }
}
