/* Buttons */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  border-radius: var(--radius-pill);
  font-family: var(--font-mono);
  font-size: 14px;
  letter-spacing: 1.68px;
  text-transform: uppercase;
  text-decoration: none;
  border: none;
  cursor: pointer;
  padding: 4px 4px 4px 16px;
  /* Liquid-fill hover, modelled on instantly.ai's buttons: a solid color
     shape sits just below the button (clipped by overflow:hidden) and
     rises to fully cover it on hover, instead of the button itself
     lifting or changing shape. Direct children get z-index so the label
     and icon stay above the rising fill throughout. */
  position: relative;
  isolation: isolate;
  overflow: hidden;
}
.btn > * {
  position: relative;
  z-index: 1;
}
.btn::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  transform: translateY(100%);
  transition: transform 0.35s cubic-bezier(0.2, 0, 0, 1);
}
.btn:hover::before {
  transform: translateY(0);
}
.btn:active {
  transform: scale(0.97);
}

.btn__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 40px;
  flex-shrink: 0;
  transform: rotate(45deg);
  transition: transform 0.2s cubic-bezier(0.2, 0, 0, 1), background 0.2s ease, color 0.2s ease;
}
/* No transform change on hover — the arrow keeps its position and only the
   colors react to the rising fill, staying legible against it. */
.btn:hover .btn__icon {
  background: var(--color-white);
  color: var(--color-dark);
}

/* Buttons without an icon (e.g. "Vamos falar?") shouldn't keep the
   icon-flush padding — it reads as cramped/off-balance without one. */
.btn:not(:has(.btn__icon)) {
  padding: 14px 24px;
}

@media (prefers-reduced-motion: reduce) {
  .btn,
  .btn::before,
  .btn__icon {
    transition: none;
  }
}

.btn--dark {
  background: var(--color-dark);
  color: var(--color-off-white);
}
.btn--dark .btn__icon {
  background: var(--color-purple);
  color: var(--color-white);
}
.btn--dark::before {
  background: var(--color-purple);
}

.btn--primary {
  background: var(--color-purple);
  color: var(--color-off-white);
}
.btn--primary .btn__icon {
  background: var(--color-dark);
  color: var(--color-white);
}
.btn--primary::before {
  background: var(--color-dark);
}

.btn--white {
  background: var(--color-white);
  color: var(--color-dark);
}
.btn--white::before {
  background: var(--color-purple);
}
.btn--white:hover {
  color: var(--color-white);
}

/* Nav pill */
.navbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 32px;
  margin-top: 16px;
  background: var(--color-white);
  border-radius: 24px;
  padding: 12px;
  box-shadow: 0 4px 24px rgba(0, 0, 0, 0);
  transition: box-shadow 0.25s ease;
}
/* .site-nav--scrolled is toggled by main.js once the page scrolls past the
   top — the pill only needs its lift-off shadow once it's floating over
   real content, not while it's sitting at rest over the hero. */
.site-nav--scrolled .navbar {
  box-shadow: 0 4px 24px rgba(0, 0, 0, 0.08);
}

@media (prefers-reduced-motion: reduce) {
  .navbar {
    transition: none;
  }
}

.navbar__brand {
  position: relative;
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
}
.navbar__brand img {
  height: 32px;
  width: auto;
}
/* Subtle sheen sweeping across the logo, angled like "/". Masked to the
   SVG's own shape (mark + wordmark) so the highlight only ever falls on
   the logo itself, never as a rectangle behind it. The gradient band
   (47%-53% of a 320%-wide canvas) is narrow enough, and the hold positions
   (0% and 100%) far enough from it, that it's fully off-canvas — not just
   faded — at rest on both ends; only the ease-in-out transit between them
   at 15%-40% of the 9s cycle ever shows it, leaving several seconds of
   true, blank pause before the pass repeats. */
.navbar__brand::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(115deg, transparent 48%, rgba(255, 255, 255, 0.32) 50%, transparent 52%);
  background-size: 320% 100%;
  background-position: 100% 0;
  -webkit-mask-image: url('/assets/images/brand/logo-wordmark.svg');
  mask-image: url('/assets/images/brand/logo-wordmark.svg');
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
  pointer-events: none;
  animation: navbar-brand-shine 9s ease-in-out infinite;
}
@keyframes navbar-brand-shine {
  0%, 15% { background-position: 100% 0; }
  40% { background-position: 0% 0; }
  100% { background-position: 0% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .navbar__brand::after {
    animation: none;
    display: none;
  }
}

.navbar__links {
  display: flex;
  align-items: center;
  list-style: none;
}
.navbar__links-cta {
  margin-left: 8px;
}

.navbar__links a:not(.btn) {
  display: inline-flex;
  padding: 8px 24px;
  font-family: var(--font-mono);
  font-size: 14px;
  letter-spacing: 1.68px;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--color-dark);
}
/* Active page indicator — set via aria-current="page" in partials.js. */
.navbar__links a[aria-current="page"] {
  border-bottom: 1px solid var(--color-purple);
}

/* Cards */
.card {
  background: var(--color-gray-light);
  border-radius: var(--radius-card);
  padding: 12px;
}

/* Decorative rotated image stack (services + CTA sections) */
.decorative-stack {
  position: relative;
  width: 100%;
  /* Tall enough that the rotated photos below fit without their tops or
     bottoms being clipped — see the post-execution note on why this grew
     from the original 210px. */
  height: 340px;
  /* The rotated children below are intentionally wider than the box (see
     nth-child rules) — without this, they bleed past the section edge and
     force horizontal scroll on viewports just above the 900px breakpoint. */
  overflow: hidden;
}

/* Polaroid-style frame: thick white border (heavier at the bottom, like a
   real instant photo's caption strip), not the previous thin translucent
   line that just looked like a clipped crop. Rounded corners, not sharp
   square ones — a real Polaroid print's corners are gently rounded too. */
.decorative-stack img {
  position: absolute;
  border-style: solid;
  border-color: #fff;
  border-width: 8px 8px 28px 8px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
  border-radius: 12px;
  object-fit: cover;
}

/* Offsets account for the rotated images' EXPANDED bounding boxes, not just
   their left/width: rotating a 204x173 box by 15deg makes its footprint
   ~242px wide, centered on the unrotated box's center. Everything below is
   placed so those expanded boxes stay inside the 440px-wide container (see
   .service-item__media) — the earlier clipping came from checking only the
   unrotated edges. */
.decorative-stack img:nth-child(1) {
  width: 177px;
  height: 225px;
  left: 126px;
  top: 50px;
}
.decorative-stack img:nth-child(2) {
  width: 188px;
  height: 137px;
  left: 212px;
  top: 30px;
  transform: rotate(15deg);
}
.decorative-stack img:nth-child(3) {
  width: 216px;
  height: 177px;
  left: 40px;
  top: 60px;
  transform: rotate(-15deg);
}

/* Rebalance the 2-image case in the SERVICES stacks only (the "Digital"
   service has just 2 photos) — the default nth-child(1)/(2) positions leave
   the lower-left of the box empty once nth-child(3) is missing. Scoped to
   .service-item__media because the CTA visual also has exactly 2 images and
   this rule's :has() specificity would otherwise beat the CTA's own
   right-anchored positioning. */
.service-item__media.decorative-stack:has(img:nth-child(2):last-child) img:nth-child(1) {
  left: 80px;
  top: 65px;
}
.service-item__media.decorative-stack:has(img:nth-child(2):last-child) img:nth-child(2) {
  left: 185px;
  top: 35px;
}

/* Services section only (not the CTA visual, which reuses .decorative-stack
   for its always-visible illustration): the fanned photos stay hidden and
   collapsed until the row is hovered, then fan out + zoom in to their
   normal rotated positions. Selectors here intentionally match/exceed the
   specificity of the base nth-child rules above so they can override them. */
.service-item__media.decorative-stack img {
  opacity: 0;
  transition: opacity 0.4s ease, transform 0.5s cubic-bezier(0.2, 0, 0, 1);
}
.service-item__media.decorative-stack img:nth-child(1) {
  transform: scale(0.7);
}
.service-item:hover .service-item__media.decorative-stack img:nth-child(1),
.service-item.is-in-view .service-item__media.decorative-stack img:nth-child(1) {
  opacity: 1;
  transform: scale(1);
}
.service-item__media.decorative-stack img:nth-child(2) {
  transform: rotate(15deg) scale(0.7);
}
.service-item:hover .service-item__media.decorative-stack img:nth-child(2),
.service-item.is-in-view .service-item__media.decorative-stack img:nth-child(2) {
  opacity: 1;
  transform: rotate(15deg) scale(1);
}
.service-item__media.decorative-stack img:nth-child(3) {
  transform: rotate(-15deg) scale(0.7);
}
.service-item:hover .service-item__media.decorative-stack img:nth-child(3),
.service-item.is-in-view .service-item__media.decorative-stack img:nth-child(3) {
  opacity: 1;
  transform: rotate(-15deg) scale(1);
}

@media (prefers-reduced-motion: reduce) {
  .service-item__media.decorative-stack img {
    transition: none;
  }
}

/* Form fields */
.field {
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex: 1;
}
/* [hidden] is only (0,1,0) specificity, same as .field itself — since this
   author rule loads after the UA stylesheet's [hidden]{display:none}, it
   would otherwise win by source order and the field would stay visible.
   Needs its own rule at (0,2,0) to actually hide. */
.field[hidden] {
  display: none;
}

.field label {
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--color-gray-text);
}

.field input,
.field textarea {
  border: 1px solid #d7d7d7;
  border-radius: 12px;
  padding: 16px 24px;
  font-family: var(--font-body);
  font-size: 16px;
  color: var(--color-dark);
  width: 100%;
}

.field textarea {
  min-height: 80px;
  resize: vertical;
}

/* Additive — .contacto.html's dynamic form is the first to need select and
   file inputs inside .field; doesn't touch the input/textarea rule above. */
.field select,
.field input[type="file"] {
  border: 1px solid #d7d7d7;
  border-radius: 12px;
  padding: 16px 24px;
  font-family: var(--font-body);
  font-size: 16px;
  color: var(--color-dark);
  width: 100%;
  background: var(--color-white);
}

/* Native select chevrons render flush against the box's outer edge,
   ignoring padding-right — replaced with a custom SVG positioned with its
   own inset so it sits at a sane distance from the border, matching the
   text's own padding rhythm. */
.field select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 48px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' fill='none'%3E%3Cpath d='M1 1.5L6 6.5L11 1.5' stroke='%23585858' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 20px center;
}

.field-error {
  color: var(--color-error);
  font-size: 13px;
}

.form-status[data-state="idle"] { display: none; }
.form-status {
  font-family: var(--font-body);
  font-size: 14px;
  padding: 12px 16px;
  border-radius: 8px;
}
.form-status[data-state="success"] { background: var(--color-success-bg); color: var(--color-success); display: block; }
.form-status[data-state="error"] { background: var(--color-error-bg); color: var(--color-error); display: block; }
.form-status[data-state="loading"] { background: var(--color-off-white); color: var(--color-gray-text); display: block; }

/* Hero */
.hero {
  position: relative;
  /* Establishes its own stacking context (position + z-index together do
     this) so the internal bg/noise/content layering below is sealed off
     from the page's — without this, .hero__content's z-index:2 ties with
     the fixed header's z-index:2 and, being later in the DOM, wins the tie
     and paints over it. With containment, the whole .hero box is compared
     to the header as a single unit (0 vs. the header's 2), regardless of
     what z-index its own children use internally. */
  z-index: 0;
  color: var(--color-white);
  background: var(--color-dark);
  border-radius: 32px;
  overflow: hidden;
  /* .section (also on this element) sets width:100% — combined with the
     1rem side margins below, that overflowed the card past the right edge
     of the viewport and erased the right-hand gap. auto lets the margins
     subtract from the available width as intended. */
  width: auto;
  /* .section also sets its own side padding — this explicit padding
     overrides it with the same value, just spelled out so it's not an
     accident of cascade order. */
  padding: 24px var(--space-section-x) 0;
  margin: 0 1rem;
  /* Nav is fixed (out of flow) and sits flush at the top of the viewport, so
     the hero needs its own top margin to clear it instead of starting at y0
     underneath it. ~61px rendered navbar height + a visual gap. */
  margin-top: 96px;
  height: 80vh;
  min-height: 600px;
  display: flex;
  flex-direction: column;
}
/* Same fine grain texture as .services-reasons .container — sits between
   .hero__bg (z:0) and .hero__content/.hero__grid (z:2), so the grain only
   textures the background image and never overlays the text, buttons or
   grid photos above it. */
.hero::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  opacity: 1;
  mix-blend-mode: overlay;
  pointer-events: none;
}

.hero__bg {
  position: absolute;
  inset: 0;
  z-index: 0;
}
.hero__bg img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Single background image (hero-bg-2, the dark purple/blue diagonal
   gradient), matching Figma exactly — no separate photo layer or scrim.
   The gradient is dark/saturated enough on its own to keep the white
   hero text legible. */

.hero__canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.hero__content {
  position: relative;
  z-index: 2;
  /* Protect the heading/CTA content — never shrink it. .hero__grid (below)
     absorbs any shortfall between the 80vh budget and the two full-height
     rows of images instead, since cropping decorative photos is a much
     smaller loss than clipping the actual headline and buttons. */
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 24px;
  padding: 40px 24px 24px;
  text-align: center;
}

/* White, not the usual accent purple — against the hero's dark gradient,
   purple text would fight the background instead of reading as a label. */
.hero__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: 14px;
  letter-spacing: 1.68px;
  text-transform: uppercase;
  color: var(--color-white);
}

/* Every eyebrow tag site-wide is now plain text in the accent color, same
   font as the nav links — no pill background/border and no icon anymore. */
.eyebrow-icon {
  display: none;
}

.hero__title {
  font-family: var(--font-header);
  font-weight: 700;
  font-size: clamp(32px, 5vw, 60px);
  line-height: 1.2;
  letter-spacing: -1px;
  max-width: 1055px;
  /* Dark-background variant of the site's title gradient — white fading to
     a dimmer translucent white instead of dark-to-gray, since the light
     version would be invisible against the hero's dark background. */
  background: linear-gradient(90deg, var(--color-white), rgba(255, 255, 255, 0.5));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
.hero__title em {
  font-style: italic;
  font-weight: 400;
  color: rgba(255, 255, 255, 0.73);
}

.hero__subtitle {
  font-size: 16px;
  letter-spacing: -0.32px;
  max-width: 774px;
}

.hero__actions {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  justify-content: center;
}

/* Horizontally scrollable strip of real project photos (populated by
   js/hero-grid-random.js from window.PROJECTS_DATA) — each card links to
   its case study, so this is real navigation now, not decoration. Items
   stretch to the row's own height (whatever .hero__content leaves under
   the 80vh budget) and derive their width from the 4:3 aspect ratio, so
   the row never needs a vertical scrollbar regardless of viewport height. */
.hero__grid {
  position: relative;
  z-index: 2;
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  align-items: stretch;
  gap: 12px;
  overflow-x: auto;
  overflow-y: hidden;
  /* Top padding has to clear the hover lift below (16px translateY) with
     room to spare, or overflow-y: hidden clips the lifted card; bottom
     padding matches so the entrance slide-up (24px) doesn't clip either. */
  padding: 24px;
  margin: 0 calc(-1 * var(--space-section-x));
  /* Without this, scroll-snap's initial alignment treats the first item's
     own edge as the snap start and silently scrolls the container past its
     own left padding on load, leaving the first photo flush against the
     hero's border instead of inset like the heading above it. */
  scroll-padding-left: var(--space-section-x);
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.hero__grid::-webkit-scrollbar {
  display: none;
}
.hero__grid-item {
  position: relative;
  flex: 0 0 auto;
  height: 100%;
  aspect-ratio: 4 / 3;
  scroll-snap-align: start;
  transition: transform 0.3s cubic-bezier(0.2, 0, 0, 1), opacity 0.5s cubic-bezier(0.2, 0, 0, 1);
}
/* Image + rounding + clipping live on this inner wrapper, not the anchor
   itself — the "Case study" chip below is a sibling of this, not a child,
   so the chip is free to sit slightly past the photo's own edge without
   being cut off by this element's overflow:hidden. */
.hero__grid-item__media {
  width: 100%;
  height: 100%;
  border-radius: 12px;
  overflow: hidden;
}
.hero__grid-item__media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Lifts clear of its neighbours on hover/focus instead of just zooming in
   place — reads as "this one" standing out from the row, matching the
   interaction the rest of the site's project cards already use for
   emphasis (just vertical here, since the row itself scrolls horizontally).
   Scoped under .is-revealed (always present once JS has run — even under
   prefers-reduced-motion) so its higher specificity reliably beats the
   entrance rule below instead of losing the tug-of-war over `transform`. */
.js .hero__grid[data-reveal].is-revealed .hero__grid-item:hover,
.js .hero__grid[data-reveal].is-revealed .hero__grid-item:focus-visible {
  transform: translateY(-16px);
  z-index: 1;
}

/* Entrance: the row opts out of the generic data-reveal fade (higher
   specificity than the `.js [data-reveal]` base rule) and each photo
   slides up and fades in instead, staggered left to right — same
   technique as .cta__visual[data-reveal]'s polaroids, just for a longer
   row of items. */
.js .hero__grid[data-reveal] {
  opacity: 1;
  transform: none;
  transition: none;
}
.js .hero__grid[data-reveal] .hero__grid-item {
  opacity: 0;
  transform: translateY(24px);
}
.js .hero__grid[data-reveal].is-revealed .hero__grid-item {
  opacity: 1;
  transform: translateY(0);
}
.hero__grid-item:nth-child(1) { transition-delay: 0s; }
.hero__grid-item:nth-child(2) { transition-delay: 0.04s; }
.hero__grid-item:nth-child(3) { transition-delay: 0.08s; }
.hero__grid-item:nth-child(4) { transition-delay: 0.12s; }
.hero__grid-item:nth-child(5) { transition-delay: 0.16s; }
.hero__grid-item:nth-child(6) { transition-delay: 0.2s; }
.hero__grid-item:nth-child(7) { transition-delay: 0.24s; }
.hero__grid-item:nth-child(8) { transition-delay: 0.28s; }
.hero__grid-item:nth-child(9) { transition-delay: 0.32s; }
.hero__grid-item:nth-child(10) { transition-delay: 0.36s; }
.hero__grid-item:nth-child(11) { transition-delay: 0.4s; }
.hero__grid-item:nth-child(12) { transition-delay: 0.44s; }
.hero__grid-item:nth-child(13) { transition-delay: 0.48s; }
.hero__grid-item:nth-child(14) { transition-delay: 0.52s; }
.hero__grid-item:nth-child(15) { transition-delay: 0.56s; }
/* Hover/focus shouldn't inherit the entrance's transition-delay — without
   this, once-revealed cards would lift on hover only after that same
   staggered pause every time. */
.hero__grid-item:hover,
.hero__grid-item:focus-visible {
  transition-delay: 0s;
}

@media (prefers-reduced-motion: reduce) {
  .hero__grid-item {
    transition: none;
  }
  .js .hero__grid[data-reveal] .hero__grid-item {
    opacity: 1;
    transform: none;
  }
}

@media (max-width: 900px) {
  .hero__content {
    padding: 16px 0px 24px;
  }
  .hero__grid {
    gap: 8px;
    padding: 24px 24px 16px;
    margin: 0 -24px;
    scroll-padding-left: 24px;
  }
  .hero { padding-left: 24px; padding-right: 24px; }
}

.site-nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 2;
  background: transparent;
}

.logos-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 32px 72px;
  align-items: center;
  justify-items: center;
}
.logo-slot {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 150px;
  height: 56px;
  overflow: hidden;
}
.logo-slot img {
  height: 56px;
  width: auto;
  max-width: 150px;
  object-fit: contain;
  transition: opacity 0.35s ease, transform 0.35s ease;
}
.logo-slot img.logo-slot__exit {
  opacity: 0;
  transform: translateY(-14px);
}
.logo-slot img.logo-slot__enter {
  opacity: 0;
  transform: translateY(14px);
}

@media (prefers-reduced-motion: reduce) {
  .logo-slot img {
    transition: none;
  }
}

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

.transformacao {
  position: relative;
  /* The line below is intentionally wider than the viewport so it gets
     visually cropped at the edges instead of stopping short of them. */
  overflow: hidden;
}
.transformacao__line {
  position: absolute;
  top: 50%;
  left: 50%;
  /* Pre-rotation size (narrow, tall) — rotating 90deg swaps this to the
     wide/short footprint that actually spans the section. Sizing the
     element directly to the post-rotation footprint and then rotating it
     again was the original bug: it produced a mostly off-screen tall
     sliver instead of a wide line behind the heading. Height becomes the
     rendered WIDTH after rotation, so 130vw overshoots the viewport on
     both sides — .transformacao's overflow:hidden then crops it flush to
     the section/viewport edges. */
  width: 327px;
  max-width: none;
  height: 130vw;
  transform: translate(-50%, -50%) rotate(90deg) scaleY(-1);
  z-index: 0;
  pointer-events: none;
}
.transformacao .stack-center {
  position: relative;
  z-index: 1;
}

.contrast-heading {
  text-align: center;
  font-family: var(--font-header);
  font-weight: 500;
  font-size: clamp(28px, 4vw, 48px);
  line-height: 1.2;
  letter-spacing: -1px;
  max-width: 718px;
  margin: 0 auto;
}
.contrast-heading .muted {
  color: var(--color-gray-muted);
}

.services-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 20px;
}
.service-item {
  display: flex;
  gap: 80px;
  align-items: flex-start;
  padding-bottom: 20px;
  border-bottom: 1px solid var(--color-gray-border);
}
.service-item:last-child {
  border-bottom: none;
}
.service-item__index {
  display: inline-flex;
  align-items: center;
  width: 112px;
  flex-shrink: 0;
}
.service-item__index img {
  width: 88px;
  height: 88px;
}
.service-item__body {
  display: flex;
  flex-direction: column;
  gap: 24px;
  flex: 1;
}
.service-item__title {
  font-family: var(--font-header);
  font-weight: 500;
  font-size: 36px;
  letter-spacing: -1px;
}
.service-item__tags {
  font-style: italic;
  color: var(--color-gray-muted);
  font-size: 16px;
}
/* Wide enough to contain the fanned photos' ROTATED bounding boxes (widest
   expanded footprint ends at ~435px — see the offsets note on
   .decorative-stack img) without clipping. This wraps .service-item__media
   so the 440x340 reference frame the images' hardcoded offsets assume can
   stay intact (and unclipped) at any wrapper size — see the mobile override
   below, where the wrapper shrinks but the inner frame doesn't. */
.service-item__media-wrap {
  width: 440px;
  flex-shrink: 0;
}

@media (max-width: 900px) {
  .service-item { flex-direction: column; gap: 24px; }
  /* The fan is authored at 440x340 (see .decorative-stack above); touch
     screens have no hover, and there's rarely 440px of clear width, so it's
     scaled down as a whole and shown below the text instead of on hover.
     The wrapper is sized to the SCALED footprint and clips to it; the inner
     .service-item__media keeps its native 440x340 frame (so the images'
     hardcoded offsets still add up the same way as on desktop) and is then
     visually shrunk to fit via transform — scaling after layout, instead of
     shrinking the frame itself, is what keeps this unclipped. */
  .service-item__media-wrap {
    width: 100%;
    max-width: 320px;
    height: 247px;
    margin: 0 auto;
    overflow: hidden;
    align-self: center;
  }
  .service-item__media.decorative-stack {
    width: 440px;
    transform: scale(0.7273);
    transform-origin: top left;
  }
  .service-item__media.decorative-stack img,
  .service-item:hover .service-item__media.decorative-stack img {
    opacity: 1;
  }
  .service-item__media.decorative-stack img:nth-child(1),
  .service-item:hover .service-item__media.decorative-stack img:nth-child(1) {
    transform: scale(1);
  }
  .service-item__media.decorative-stack img:nth-child(2),
  .service-item:hover .service-item__media.decorative-stack img:nth-child(2) {
    transform: rotate(15deg) scale(1);
  }
  .service-item__media.decorative-stack img:nth-child(3),
  .service-item:hover .service-item__media.decorative-stack img:nth-child(3) {
    transform: rotate(-15deg) scale(1);
  }
}

/* Title + subtitle read as one two-line statement (same scale as
   .heading-xl, just split), not a heading with a small caption under it —
   the subtitle stays large and only a touch lighter/lower-contrast than
   the title, with the italic phrase picking the dark color back up. */
.servicos-intro {
  margin-bottom: 64px;
}
.servicos-intro__text {
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-width: 620px;
}
.servicos-intro__title {
  font-family: var(--font-header);
  font-weight: 700;
  font-size: clamp(28px, 4vw, 48px);
  letter-spacing: -1px;
  line-height: 1.2;
  background: linear-gradient(90deg, var(--color-dark), var(--color-gray-muted));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
.servicos-intro__subtitle {
  font-family: var(--font-header);
  font-weight: 400;
  font-size: clamp(24px, 3.5vw, 40px);
  letter-spacing: -1px;
  line-height: 1.2;
  color: var(--color-gray-text);
}
.servicos-intro__subtitle i {
  font-style: italic;
  color: var(--color-dark);
}
.servicos-cta-row {
  display: flex;
  justify-content: center;
  margin-top: 48px;
}

@media (max-width: 900px) {
  .servicos-cta-row {
    justify-content: flex-start;
  }
}

.testimonials-header {
  flex-direction: row;
  justify-content: space-between;
  align-items: flex-end;
  max-width: none;
}

.testimonials-carousel__controls {
  display: flex;
  gap: 12px;
  flex-shrink: 0;
}
.testimonials-carousel__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 1px solid var(--color-gray-border);
  background: var(--color-white);
  color: var(--color-dark);
  font-size: 16px;
  cursor: pointer;
  transition: background 0.2s ease, color 0.2s ease, transform 0.15s cubic-bezier(0.2, 0, 0, 1);
}
.testimonials-carousel__btn:hover:not(:disabled) {
  background: var(--color-dark);
  color: var(--color-white);
  transform: scale(1.08);
}
.testimonials-carousel__btn:active:not(:disabled) {
  transform: scale(0.95);
}

@media (prefers-reduced-motion: reduce) {
  .testimonials-carousel__btn {
    transition: none;
  }
  .testimonials-carousel__btn:hover:not(:disabled),
  .testimonials-carousel__btn:active:not(:disabled) {
    transform: none;
  }
}
.testimonials-carousel__btn:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

.testimonials-carousel {
  list-style: none;
  display: flex;
  align-items: flex-start;
  gap: 24px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  padding-bottom: 8px;
  scrollbar-width: none;
  /* Break out of the centered .container so cards can scroll edge-to-edge,
     while .testimonials-header (heading + arrows) stays put in the container.
     Padding uses the same max() as .container's own centering math (max-width
     1280px) so the first card lines up with the heading above it at any
     viewport width, instead of drifting left of it once the container starts
     centering with margins wider than --space-section-x. scroll-padding-left
     keeps that padded position a valid, stable resting snap point — without
     it, some engines auto-snap past the padding on load. */
  width: 100vw;
  position: relative;
  left: 50%;
  transform: translateX(-50%);
  padding-left: max(var(--space-section-x), calc((100vw - 1280px) / 2));
  padding-right: max(var(--space-section-x), calc((100vw - 1280px) / 2));
  scroll-padding-left: max(var(--space-section-x), calc((100vw - 1280px) / 2));
}
.testimonials-carousel::-webkit-scrollbar {
  display: none;
}
.testimonial-card {
  background: var(--color-gray-light);
  border-radius: 24px;
  padding: 12px;
  flex: 0 0 min(376px, 85vw);
  scroll-snap-align: start;
}
.testimonial-card__media {
  position: relative;
  border-radius: 12px;
  overflow: hidden;
  aspect-ratio: 376 / 322;
}
.testimonial-card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.testimonial-card__play {
  position: absolute;
  bottom: 16px;
  left: 16px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border: none;
  border-radius: 50%;
  background: rgba(236, 236, 236, 0.24);
  backdrop-filter: blur(8px);
  cursor: pointer;
  transition: transform 0.2s cubic-bezier(0.2, 0, 0, 1), background 0.2s ease;
}
.testimonial-card__play img {
  width: 20px;
  height: 20px;
}
.testimonial-card__play:hover {
  transform: scale(1.1);
  background: rgba(236, 236, 236, 0.4);
}

@media (prefers-reduced-motion: reduce) {
  .testimonial-card__play {
    transition: none;
  }
  .testimonial-card__play:hover {
    transform: none;
  }
}

/* Video modal */
.video-modal {
  position: fixed;
  inset: 0;
  z-index: 3000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.video-modal[hidden] {
  display: none;
}
.video-modal__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(20, 20, 20, 0.8);
}
.video-modal__dialog {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 860px;
  background: var(--color-dark);
  border-radius: 16px;
  padding: 16px;
}
.video-modal__close {
  position: absolute;
  top: -44px;
  right: 0;
  width: 36px;
  height: 36px;
  border: none;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.12);
  color: var(--color-white);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
}
.video-modal__body {
  position: relative;
  aspect-ratio: 16 / 9;
  display: flex;
  align-items: center;
  justify-content: center;
}
.video-modal__body video {
  width: 100%;
  height: 100%;
  border-radius: 8px;
}
.video-modal__body video[src=""],
.video-modal__body video:not([src]) {
  display: none;
}
.video-modal__placeholder {
  display: none;
  color: var(--color-off-white);
  font-family: var(--font-mono);
  font-size: 14px;
  letter-spacing: 1px;
  text-transform: uppercase;
}
.video-modal__body:has(video[src=""]) .video-modal__placeholder,
.video-modal__body:has(video:not([src])) .video-modal__placeholder {
  display: block;
}

/* Contact modal — triggered by the header's "Vamos falar?" button on every
   page (site-contact-modal in partials.js). Same fixed-overlay + backdrop
   pattern as .video-modal, different content: a short list of ways to
   reach the studio. */
.contact-modal {
  position: fixed;
  inset: 0;
  z-index: 3000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.contact-modal[hidden] {
  display: none;
}
.contact-modal__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(20, 20, 20, 0.5);
}
.contact-modal__dialog {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 40vw;
  max-height: 85vh;
  overflow-y: auto;
  background: var(--color-white);
  border-radius: 24px;
  padding: 40px 32px 32px;
}
.contact-modal__close {
  position: absolute;
  top: 16px;
  right: 16px;
  width: 36px;
  height: 36px;
  border: none;
  border-radius: 50%;
  background: var(--color-gray-light);
  color: var(--color-dark);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}
.contact-modal__title {
  font-family: var(--font-header);
  font-weight: 600;
  font-size: 28px;
  letter-spacing: -1px;
  color: var(--color-dark);
  margin-bottom: 8px;
}
.contact-modal__lede {
  color: var(--color-gray-text);
  line-height: 1.5;
  margin-bottom: 24px;
}
.contact-modal__list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.contact-modal__item {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 16px;
  border-radius: 16px;
  background: var(--color-off-white);
  text-decoration: none;
  color: inherit;
  transition: background 0.2s ease;
}
.contact-modal__item:hover {
  background: var(--color-gray-light);
}
.contact-modal__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--color-white);
  color: var(--color-purple);
}
.contact-modal__icon svg {
  width: 20px;
  height: 20px;
}
.contact-modal__item-body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.contact-modal__item-title {
  font-family: var(--font-header);
  font-weight: 600;
  font-size: 15px;
  color: var(--color-dark);
}
.contact-modal__item-desc {
  font-size: 13px;
  line-height: 1.4;
  color: var(--color-gray-text);
}
/* Legally-required disclaimer for the mobile "Ligar" option — visually
   distinct fine print, not a regular description line. */
.contact-modal__item-note {
  font-size: 11px;
  color: var(--color-gray-muted);
  margin-top: 2px;
}
.contact-modal__arrow {
  flex-shrink: 0;
  color: var(--color-gray-muted);
  font-size: 18px;
}

@media (max-width: 600px) {
  .contact-modal {
    align-items: flex-end;
    padding: 0;
  }
  .contact-modal__dialog {
    max-width: 100%;
    max-height: 90vh;
    border-radius: 24px 24px 0 0;
  }
}

.testimonial-card__body {
  background: var(--color-white);
  border-radius: 12px;
  padding: 20px;
  margin-top: 12px;
}
.testimonial-card__quote {
  font-size: 20px;
  line-height: 1.4;
  letter-spacing: -0.4px;
  margin-bottom: 16px;
}
.testimonial-card__author {
  font-size: 16px;
  color: var(--color-dark);
}

@media (max-width: 900px) {
  .testimonials-carousel {
    padding-left: 24px;
    padding-right: 24px;
  }
}

.mission {
  display: flex;
  gap: 48px;
  align-items: center;
}
.mission__image {
  position: relative;
  flex: 1;
  border-radius: 24px;
  overflow: hidden;
  aspect-ratio: 4 / 3;
}
.mission__image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Name-tag caption over the photo, like a press/portrait credit — a soft
   dark scrim (not a solid bar) keeps the photo itself unobstructed while
   still guaranteeing contrast for the white text above it. */
.mission__image-caption {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 32px 24px 20px;
  background: linear-gradient(to top, rgba(0, 0, 0, 0.65), rgba(0, 0, 0, 0));
}
.mission__image-name {
  font-family: var(--font-header);
  font-weight: 600;
  font-size: 17px;
  color: var(--color-white);
}
.mission__image-role {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.8px;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.78);
}
.mission__text {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 20px;
}
/* Reads as André speaking directly to the visitor — a large, faint quote
   mark above the headline is enough to cue "quote" without a border or
   background box fighting the rest of the section's plain layout. */
.mission__quote {
  margin: 0;
}
.mission__quote::before {
  content: '\201C';
  display: block;
  font-family: var(--font-header);
  font-size: 96px;
  line-height: 0.4;
  color: var(--color-purple);
  opacity: 0.25;
  margin-bottom: -16px;
}
.mission__heading {
  font-family: var(--font-header);
  font-weight: 700;
  font-size: clamp(28px, 4vw, 48px);
  letter-spacing: -1px;
  line-height: 1.2;
  background: linear-gradient(90deg, var(--color-dark), var(--color-gray-muted));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
.mission__body p {
  margin-bottom: 16px;
  color: var(--color-gray-text);
}
.mission__signature {
  height: 54px;
  width: auto;
  /* Without this, being a flex item in a column container stretches it to
     the container's full cross-axis width (align-items: stretch default). */
  align-self: flex-start;
}

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

.press-logos {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 80px;
}
.press-logos img {
  height: 40px;
  width: auto;
}
.press-logos a {
  display: inline-flex;
  transition: transform 0.2s cubic-bezier(0.2, 0, 0, 1);
}
.press-logos a:hover {
  transform: translateY(-2px);
}

@media (prefers-reduced-motion: reduce) {
  .press-logos a {
    transition: none;
  }
  .press-logos a:hover {
    transform: none;
  }
}

@media (max-width: 900px) {
  .press-logos {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    justify-items: center;
    gap: 32px;
  }
}

.press-section {
  display: flex;
  flex-direction: column;
  gap: 40px;
}

.press-heading {
  margin-bottom: 16px;
}

.press-lede {
  color: var(--color-gray-text);
  max-width: 716px;
}

/* CTA + contact form */
.cta-section {
  margin-bottom: 48px;
}
.cta {
  position: relative;
  background: var(--color-dark);
  border-radius: 24px;
  overflow: hidden;
  color: var(--color-white);
  padding: 64px 52px;
}
.cta__bg {
  position: absolute;
  inset: 0;
  z-index: 0;
}
.cta__bg img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Same single background image as .hero__bg — see the note there. */

.cta__grid {
  position: relative;
  z-index: 1;
  display: flex;
  gap: 48px;
  flex-wrap: wrap;
}
.cta__text-col {
  flex: 1;
  min-width: 320px;
  display: flex;
  flex-direction: column;
  gap: 32px;
}
.cta__intro {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.cta__intro h2 {
  font-family: var(--font-header);
  font-weight: 500;
  font-size: clamp(28px, 4vw, 48px);
  letter-spacing: -1px;
  line-height: 1.2;
}

/* Illustrative visual on the right — same rotated-card language as
   .decorative-stack (services section), sized for this larger context. */
.cta__visual {
  flex: 1;
  min-width: 260px;
  height: 380px;
  /* Cancels the card's right padding so the visual's right edge IS the
     card's right edge — the polaroids below anchor to it with right: 0
     and get their overhang cropped by .cta's overflow:hidden. */
  margin-right: calc(-1 * var(--space-section-x));
}
.decorative-stack--cta img:nth-child(1) {
  width: 210px;
  height: 210px;
  right: 230px;
  left: auto;
  top: 90px;
  transform: rotate(-5.92deg);
}
.decorative-stack--cta img:nth-child(2) {
  width: 249px;
  height: 249px;
  right: 0;
  left: auto;
  top: 40px;
  transform: rotate(9.41deg);
}

/* Entrance: the container itself opts out of the generic data-reveal
   hide/slide (higher specificity than the `.js [data-reveal]` base rule in
   base.css) and instead each polaroid slides up and settles into its final
   tilt, staggered, once scroll-reveal marks the container .is-revealed. */
.js .cta__visual[data-reveal] {
  opacity: 1;
  transform: none;
  transition: none;
}
.js .cta__visual[data-reveal] img {
  opacity: 0;
  transition: opacity 0.6s cubic-bezier(0.2, 0, 0, 1), transform 0.6s cubic-bezier(0.2, 0, 0, 1);
}
.js .cta__visual[data-reveal] img:nth-child(1) {
  transform: translateY(48px) rotate(4deg);
}
.js .cta__visual[data-reveal] img:nth-child(2) {
  transform: translateY(48px) rotate(-4deg);
}
.js .cta__visual[data-reveal].is-revealed img {
  opacity: 1;
}
.js .cta__visual[data-reveal].is-revealed img:nth-child(1) {
  transform: translateY(0) rotate(-5.92deg);
  transition-delay: 0.1s;
}
.js .cta__visual[data-reveal].is-revealed img:nth-child(2) {
  transform: translateY(0) rotate(9.41deg);
  transition-delay: 0.25s;
}

@media (prefers-reduced-motion: reduce) {
  .js .cta__visual[data-reveal] img {
    opacity: 1;
    transition: none;
  }
  .js .cta__visual[data-reveal] img:nth-child(1) {
    transform: rotate(-5.92deg);
  }
  .js .cta__visual[data-reveal] img:nth-child(2) {
    transform: rotate(9.41deg);
  }
}

.contact-form {
  background: var(--color-white);
  border-radius: 24px;
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 24px;
  color: var(--color-dark);
}
.contact-form__row {
  display: flex;
  gap: 24px;
  flex-wrap: wrap;
}
.contact-form__consent {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  font-size: 14px;
  color: var(--color-gray-text);
}
.contact-form__consent input {
  appearance: none;
  width: 24px;
  height: 24px;
  margin: 0;
  flex-shrink: 0;
  border: 1px solid #d7d7d7;
  border-radius: 8px;
  background: var(--color-white);
  cursor: pointer;
  position: relative;
}
.contact-form__consent input:checked {
  background: var(--color-dark);
  border-color: var(--color-dark);
}
/* Required by Google's ToS whenever the default bottom-right badge is
   hidden (see .grecaptcha-badge in base.css — that badge would otherwise
   collide with site-whatsapp-float, which already owns that corner). */
.recaptcha-disclosure {
  font-size: 13px;
  color: var(--color-gray-muted);
  line-height: 1.5;
}
.recaptcha-disclosure a {
  color: inherit;
  text-decoration: underline;
}
.contact-form__consent input:checked::after {
  content: "";
  position: absolute;
  left: 7px;
  top: 3px;
  width: 6px;
  height: 11px;
  border: solid var(--color-white);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
.honeypot-field {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.contact-form__submit {
  align-self: flex-start;
}

@media (max-width: 700px) {
  /* .cta's own padding + .cta__text-col/.cta__visual's min-widths otherwise
     force the card wider than the viewport, causing horizontal scroll on
     phones. Stacking to a column (rather than just zeroing min-width, which
     would let both columns shrink side by side into an unreadable overlap)
     matches the same pattern used by .mission and .hero__grid. */
  .cta {
    padding: 32px 20px;
  }
  .cta__grid {
    flex-direction: column;
  }
  .cta__text-col,
  .cta__visual {
    min-width: 0;
    width: 100%;
  }
  .cta__visual {
    /* Match the card's narrower 20px mobile padding (see .cta above) so the
       polaroids still reach exactly the card's right edge, not past it. */
    margin-right: -20px;
    width: calc(100% + 20px);
  }
  .contact-form__row {
    flex-direction: column;
  }
}

.site-footer {
  background: var(--color-dark);
  color: var(--color-white);
  padding: 0 52px 32px;
  overflow: hidden;
  /* Same width and corner treatment as the hero (margin 0 1rem, 32px
     rounding), plus its own 1rem gap from the true bottom of the page. */
  margin: 0 1rem 1rem;
  border-radius: 32px;
}

@media (max-width: 900px) {
  .site-footer {
    padding-left: 24px;
    padding-right: 24px;
  }
}
/* A normal in-flow block that sits above (before) the heading row — per
   Figma this is not a background watermark behind the content, it's a huge,
   very low-opacity heading-like block that comes first, non-overlapping,
   flush against the footer's top edge. */
.site-footer__watermark {
  display: block;
  width: clamp(320px, 60vw, 1181px);
  margin: 0 auto 24px;
  opacity: 1;
}
.site-footer__row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 24px;
  padding-top: 64px;
  padding-bottom: 32px;
}
.site-footer__heading {
  font-family: var(--font-header);
  font-weight: 500;
  font-size: clamp(28px, 4vw, 48px);
  line-height: 56px;
  letter-spacing: -0.06em;
  max-width: 503px;
}
@media (max-width: 900px) {
  .site-footer__row {
    padding-top: 8px;
  }
  .site-footer__heading {
    line-height: 36px;
  }
}
.site-footer__social {
  display: flex;
  gap: 16px;
}
.site-footer__social-icon {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
}
.site-footer__social-bg {
  position: absolute;
  inset: 0;
  width: 48px;
  height: 48px;
}
.site-footer__social-glyph {
  position: relative;
  width: 24px;
  height: 24px;
}
.site-footer__social-standalone {
  width: 48px;
  height: 48px;
}
.site-footer__bottom {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 16px;
  border-top: 1px solid rgba(255, 255, 255, 0.15);
  padding-top: 32px;
  font-size: 14px;
}
.site-footer__links {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  row-gap: 6px;
  list-style: none;
}
.site-footer__links li {
  white-space: nowrap;
}
.site-footer__links li:not(:last-child)::after {
  content: "·";
  margin: 0 12px;
  color: rgba(255, 255, 255, 0.4);
}
.site-footer__links a {
  text-decoration: none;
}
.site-footer__links button {
  padding: 0;
  border: none;
  background: none;
  font: inherit;
  color: inherit;
  cursor: pointer;
}

/* Mobile nav toggle */
.navbar {
  position: relative;
}
.nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border: none;
  background: transparent;
  cursor: pointer;
  padding: 0;
  flex-shrink: 0;
}
.nav-toggle__icon,
.nav-toggle__icon::before,
.nav-toggle__icon::after {
  display: block;
  width: 20px;
  height: 2px;
  background: var(--color-dark);
  transition: transform 0.25s cubic-bezier(0.2, 0, 0, 1), opacity 0.2s ease, top 0.25s cubic-bezier(0.2, 0, 0, 1);
}
.nav-toggle__icon {
  position: relative;
}
.nav-toggle__icon::before,
.nav-toggle__icon::after {
  content: "";
  position: absolute;
  left: 0;
}
.nav-toggle__icon::before {
  top: -6px;
}
.nav-toggle__icon::after {
  top: 6px;
}

/* Hamburger -> X when the mobile menu is open */
.nav-toggle[aria-expanded="true"] .nav-toggle__icon {
  background: transparent;
}
.nav-toggle[aria-expanded="true"] .nav-toggle__icon::before {
  top: 0;
  transform: rotate(45deg);
}
.nav-toggle[aria-expanded="true"] .nav-toggle__icon::after {
  top: 0;
  transform: rotate(-45deg);
}

@media (prefers-reduced-motion: reduce) {
  .nav-toggle__icon,
  .nav-toggle__icon::before,
  .nav-toggle__icon::after {
    transition: none;
  }
}

@media (max-width: 900px) {
  .nav-toggle {
    display: inline-flex;
    position: relative;
    z-index: 1;
  }
  /* The brand mark sits BEFORE .navbar__links in the DOM, so once the full-
     screen panel below is in the same paint layer it would otherwise paint
     over the logo — lift the logo above it too. The toggle comes AFTER
     .navbar__links in the DOM, so it already paints on top without needing
     this. */
  .navbar__brand {
    position: relative;
    z-index: 1;
  }
  /* Full-screen takeover menu (instantly.ai-style): fixed to the viewport,
     covering it entirely (including the pill) so it reads as one continuous
     white surface rather than a dark overlay dropped below the header.
     Kept in the DOM and faded in via opacity/transform (not display:none)
     so the transition can run; pointer-events stays off while closed so it
     can't eat clicks behind it. */
  .navbar__links {
    display: flex;
    position: fixed;
    inset: 0;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    background: var(--color-white);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-16px);
    pointer-events: none;
    transition: opacity 0.3s cubic-bezier(0.2, 0, 0, 1), transform 0.3s cubic-bezier(0.2, 0, 0, 1), visibility 0s linear 0.3s;
  }
  .navbar__links--open {
    opacity: 1;
    visibility: visible;
    transform: none;
    pointer-events: auto;
    transition: opacity 0.3s cubic-bezier(0.2, 0, 0, 1), transform 0.3s cubic-bezier(0.2, 0, 0, 1);
  }
  .navbar__links a:not(.btn) {
    padding: 16px 24px;
    font-size: 28px;
    letter-spacing: 0;
    text-transform: none;
    color: var(--color-dark);
  }
  .navbar__links-cta {
    margin-left: 0;
    margin-top: 24px;
  }
  .navbar__links-cta .btn {
    padding: 16px 28px;
  }
}

@media (max-width: 900px) and (prefers-reduced-motion: reduce) {
  .navbar__links,
  .navbar__links--open {
    transition: none;
  }
}

/* Cookie banner */
.cookie-banner {
  position: fixed;
  bottom: 16px;
  left: 16px;
  right: 16px;
  max-width: 720px;
  margin: 0 auto;
  background: var(--color-white);
  border: 1px solid var(--color-gray-border);
  border-radius: 16px;
  padding: 20px;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.15);
  z-index: 2000;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.cookie-banner[hidden] {
  display: none;
}

/* Floating WhatsApp contact button. z-index deliberately sits just below
   .cookie-banner's 2000 — on narrow viewports the banner goes edge-to-edge
   and would otherwise overlap this corner; sitting behind it means the
   (opaque) banner simply covers the button until dismissed, no media-query
   juggling needed to keep them apart. */
.whatsapp-float {
  position: fixed;
  right: 24px;
  bottom: 24px;
  z-index: 1900;
  width: 56px;
  height: 56px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--color-dark);
  color: var(--color-white);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
  transition: transform 0.2s cubic-bezier(0.2, 0, 0, 1), background 0.2s ease;
}
.whatsapp-float:hover {
  background: var(--color-purple);
  transform: scale(1.08);
}
.whatsapp-float svg {
  width: 28px;
  height: 28px;
}

@media (prefers-reduced-motion: reduce) {
  .whatsapp-float {
    transition: none;
  }
  .whatsapp-float:hover {
    transform: none;
  }
}

@media (max-width: 900px) {
  .whatsapp-float {
    right: 16px;
    bottom: 16px;
  }
}

.cookie-banner__details {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--color-gray-border);
}
.cookie-banner__details[hidden] {
  display: none;
}
.cookie-banner__category-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.cookie-banner__category-title {
  font-size: 13px;
  font-weight: 600;
  margin-bottom: 4px;
}
.cookie-banner__category-head .cookie-banner__category-title {
  margin-bottom: 0;
}
.cookie-banner__category-always {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--color-gray-muted);
}
.cookie-banner__category-text {
  font-size: 13px;
  color: var(--color-gray-text);
  line-height: 1.5;
}

/* Toggle switch for the analytics/marketing categories — checkbox stays in
   the DOM (visually hidden, not display:none) so it's still keyboard- and
   screen-reader-operable; the pill + circle are purely decorative siblings
   driven by :checked. */
.cookie-banner__switch {
  position: relative;
  display: inline-flex;
  flex-shrink: 0;
  width: 36px;
  height: 20px;
}
.cookie-banner__switch input {
  position: absolute;
  inset: 0;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}
.cookie-banner__switch-track {
  position: absolute;
  inset: 0;
  background: var(--color-gray-border);
  border-radius: var(--radius-pill);
  transition: background 0.2s ease;
}
.cookie-banner__switch-track::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--color-white);
  transition: transform 0.2s ease;
}
.cookie-banner__switch input:checked + .cookie-banner__switch-track {
  background: var(--color-dark);
}
.cookie-banner__switch input:checked + .cookie-banner__switch-track::after {
  transform: translateX(16px);
}
.cookie-banner__switch input:focus-visible + .cookie-banner__switch-track {
  outline: 2px solid var(--color-purple);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  .cookie-banner__switch-track,
  .cookie-banner__switch-track::after {
    transition: none;
  }
}
.cookie-banner__actions {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
}
.cookie-banner__actions button {
  flex: 1;
  min-width: 120px;
  padding: 10px 18px;
  border-radius: 32px;
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 1px;
  text-transform: uppercase;
  border: 1px solid var(--color-dark);
  background: var(--color-white);
  color: var(--color-dark);
  cursor: pointer;
}
.cookie-banner__actions button[data-action="customize"] {
  border-color: var(--color-purple);
  color: var(--color-purple);
}
/* "Aceitar essenciais" / "Aceitar tudo" deliberadamente com o mesmo peso
   visual (mesmo contorno neutro, nenhum dos dois preenchido) — um "aceitar
   tudo" a preto sólido ao lado de uma opção mais fraca empurra visualmente
   para o consentimento, o que o RGPD (art. 7.º/3) e a orientação da CNPD
   tratam como um problema de conformidade, não só de estética. */

.cookie-banner__title {
  font-weight: 600;
  margin-bottom: 8px;
}

.cookie-banner__text {
  font-size: 14px;
  color: var(--color-gray-text);
}

/* ==========================================================================
   Estúdio page
   ========================================================================== */

/* Intro: page h1 + two offset office photos */
.studio-intro {
  /* Clears the fixed nav pill — same 96px used by .hero on the homepage. */
  margin-top: 96px;
}
.studio-intro__grid {
  display: flex;
  gap: 48px;
  align-items: center;
}
.studio-intro__text {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 24px;
}
.studio-intro__heading {
  font-family: var(--font-header);
  font-weight: 700;
  font-size: clamp(32px, 5vw, 60px);
  letter-spacing: -2px;
  line-height: 1.2;
  background: linear-gradient(90deg, var(--color-dark), var(--color-gray-muted));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
.studio-intro__lede {
  color: #4c4c4c;
  font-size: 16px;
  line-height: 1.5;
  max-width: 480px;
}
.studio-intro__gallery {
  flex: 1;
  display: flex;
  gap: 20px;
  align-items: flex-start;
}
.studio-intro__gallery img {
  flex: 1;
  /* Flex items default to min-width:auto, which for an <img> resolves to
     its intrinsic pixel width — without this it refuses to shrink below
     that and overflows the container instead of sharing the row. */
  min-width: 0;
  width: 100%;
  /* Matches the source's 298:497 card ratio — both cards are the same
     size; the stagger comes from offsetting the first one down, not from
     giving it a different size. */
  aspect-ratio: 298 / 497;
  border-radius: 32px;
  object-fit: cover;
  display: block;
}
.studio-intro__gallery img:nth-child(1) {
  margin-top: 22%;
}

@media (max-width: 900px) {
  .studio-intro__grid {
    flex-direction: column;
  }
  .studio-intro__gallery {
    width: 100%;
  }
  .studio-intro__gallery img:nth-child(1) {
    margin-top: 15%;
  }
}

/* Hero: founder story card + portrait */
.studio-hero__grid {
  display: flex;
  gap: 24px;
  align-items: stretch;
}
.studio-hero__card {
  /* Wider than the photo (roughly 60/40), matching the source design where
     the story card reads as the primary element and the portrait as support. */
  flex: 1.6;
  background: #f2f2f2;
  border-radius: var(--radius-card);
  padding: 64px 40px;
  display: flex;
  flex-direction: column;
  gap: 32px;
  justify-content: center;
}
.studio-hero__heading {
  font-family: var(--font-header);
  font-weight: 700;
  font-size: clamp(28px, 4vw, 40px);
  letter-spacing: -1px;
  line-height: 1.2;
  background: linear-gradient(90deg, var(--color-dark), var(--color-gray-muted));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
.studio-hero__body {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.studio-hero__body p {
  color: var(--color-gray-text);
  line-height: 1.5;
}
.studio-hero__signature {
  height: 54px;
  width: auto;
  /* Without this, being a flex item in a column container stretches it to
     the container's full cross-axis width (align-items: stretch default). */
  align-self: flex-start;
}
.studio-hero__photo {
  flex: 1;
  border-radius: var(--radius-card);
  overflow: hidden;
}
.studio-hero__photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

@media (max-width: 900px) {
  .studio-hero__grid {
    flex-direction: column;
  }
  .studio-hero__card {
    padding: 32px 24px;
  }
  .studio-hero__photo {
    aspect-ratio: 4 / 3;
  }
  /* The 4:3 crop is much shorter than the source portrait — default center
     cropping cut off André's face. Anchoring to the top keeps it in frame. */
  .studio-hero__photo img {
    object-position: top center;
  }
}

/* About: "O que nos define" */
.studio-about__grid {
  display: flex;
  gap: 48px;
  align-items: flex-start;
  justify-content: space-between;
}
.studio-about__eyebrow {
  display: inline-flex;
  /* Without this, being a flex item in a column container (.studio-intro__text)
     stretches it to the container's full cross-axis width (align-items:
     stretch default) — inline-flex only controls its OWN children's layout,
     not how the pill itself is sized within its parent. */
  align-self: flex-start;
  align-items: center;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: 14px;
  letter-spacing: 1.68px;
  text-transform: uppercase;
  color: var(--color-purple);
  flex-shrink: 0;
}
.studio-about__content {
  display: flex;
  flex-direction: column;
  gap: 64px;
  max-width: 776px;
}
.studio-about__lede p {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: clamp(16px, 1.6vw, 19px);
  letter-spacing: normal;
  line-height: 1.6;
  color: var(--color-gray-text);
  margin-bottom: 16px;
}
.studio-about__lede strong {
  font-weight: 600;
  color: var(--color-dark);
}
.studio-about__stats {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  width: 100%;
  flex-wrap: wrap;
}
.studio-about__stat {
  display: flex;
  align-items: center;
  gap: 12px;
}
.studio-about__stat-number {
  font-family: var(--font-header);
  font-weight: 700;
  font-size: 36px;
  letter-spacing: -1px;
  color: var(--color-dark);
}
.studio-about__stat-label {
  font-size: 16px;
  color: var(--color-dark);
  line-height: 1.5;
}

@media (max-width: 900px) {
  .studio-about__grid {
    flex-direction: column;
    gap: 24px;
  }
  .studio-about__content {
    gap: 40px;
  }
  .studio-about__stats {
    flex-direction: column;
    align-items: center;
    gap: 20px;
  }
  /* Number stacked above the label, both centred — the side-by-side desktop
     layout reads oddly once the stats are full-width and centred. */
  .studio-about__stat {
    flex-direction: column;
    align-items: center;
    gap: 4px;
    text-align: center;
  }
  /* The <br> in each label forces the desktop 2-line layout — drop it here
     so the text runs as one line (wrapping naturally only if it has to)
     instead of always breaking at that fixed point. */
  .studio-about__stat-label br {
    display: none;
  }
}

/* Team collage — decorative, aria-hidden. Deliberately NOT aligned to a
   shared baseline: each photo has its own vertical offset and a slight
   constant tilt, plus an independent floating bob (own duration + delay),
   so nothing reads as a grid. Overlap comes from negative margins, with
   avatars layered above the smaller atmosphere shots. Entrance only fades
   opacity in — transform is owned entirely by the float animation, so
   nothing fights it once revealed. */
.studio-team__heading {
  text-align: center;
}
.studio-team__row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  margin-top: 40px;
  width: 100%;
  /* No overflow clip here: a rotated image's bounding box is wider/taller
     than its own box (see the .decorative-stack rotated-bbox notes above),
     so clipping tightly to the row cut corners off at random depending on
     the float phase. Any real bleed is caught by body's overflow-x:hidden
     instead, at the page edge rather than mid-photo. */
}
.studio-team__item {
  position: relative;
  /* Below .site-nav's z-index:2 (fixed header) on purpose — these photos'
     negative margins/float can reach up near the header, and without this
     equal-or-higher z-index plus later DOM order would paint them over it. */
  z-index: 0;
  border-radius: 4px;
  object-fit: cover;
  flex-shrink: 0;
  animation-name: studio-team-float;
  animation-timing-function: ease-in-out;
  animation-iteration-count: infinite;
}
.studio-team__item--avatar {
  z-index: 1;
  border-radius: 8px;
  border: 3px solid var(--color-white);
  box-shadow: 0 12px 24px rgba(0, 0, 0, 0.1);
}

@keyframes studio-team-float {
  0%, 100% { transform: translateY(0) rotate(var(--float-rot, 0deg)); }
  50% { transform: translateY(var(--float-y, -14px)) rotate(var(--float-rot, 0deg)); }
}

/* Each photo is a genuinely one-off size, offset and float — sized and
   tuned positionally rather than via one modifier class per image. */
.studio-team__row img:nth-child(1) { width: 90px; height: 130px; margin-top: 34px; --float-rot: -4deg; --float-y: -10px; animation-duration: 5.5s; animation-delay: 0s; }
.studio-team__row img:nth-child(2) { width: 150px; height: 210px; margin-left: -20px; margin-top: -22px; --float-rot: 3deg; --float-y: -16px; animation-duration: 6.5s; animation-delay: 0.4s; }
.studio-team__row img:nth-child(3) { width: 105px; height: 150px; margin-top: 46px; --float-rot: -2deg; --float-y: -12px; animation-duration: 5s; animation-delay: 0.8s; }
.studio-team__row img:nth-child(4) { width: 105px; height: 150px; margin-right: -16px; margin-top: -12px; --float-rot: 5deg; --float-y: -18px; animation-duration: 7s; animation-delay: 0.2s; }
.studio-team__row img:nth-child(5) { width: 230px; height: 320px; --float-rot: -1.5deg; --float-y: -10px; animation-duration: 6s; animation-delay: 0.6s; }
.studio-team__row img:nth-child(6) { width: 90px; height: 130px; margin-left: -24px; margin-top: 24px; --float-rot: 4deg; --float-y: -14px; animation-duration: 5.8s; animation-delay: 1s; }
.studio-team__row img:nth-child(7) { width: 170px; height: 230px; margin-top: -34px; --float-rot: -3deg; --float-y: -16px; animation-duration: 6.8s; animation-delay: 0.3s; }
.studio-team__row img:nth-child(8) { width: 80px; height: 110px; margin-top: 56px; --float-rot: 2deg; --float-y: -8px; animation-duration: 5.2s; animation-delay: 0.9s; }
.studio-team__row img:nth-child(9) { width: 190px; height: 260px; margin-left: -16px; margin-top: -16px; --float-rot: -4deg; --float-y: -12px; animation-duration: 6.3s; animation-delay: 0.5s; }

/* Staggered entrance, same technique as .cta__visual[data-reveal]: the
   container stays visible (overriding the generic [data-reveal] fade), only
   the individual photos fade in, each with its own delay. */
.js .studio-team__row[data-reveal] {
  opacity: 1;
  transform: none;
  transition: none;
}
.js .studio-team__row[data-reveal] img {
  opacity: 0;
  transition: opacity 0.6s cubic-bezier(0.2, 0, 0, 1);
}
.js .studio-team__row[data-reveal].is-revealed img {
  opacity: 1;
}
.js .studio-team__row[data-reveal].is-revealed img:nth-child(1) { transition-delay: 0s; }
.js .studio-team__row[data-reveal].is-revealed img:nth-child(2) { transition-delay: 0.06s; }
.js .studio-team__row[data-reveal].is-revealed img:nth-child(3) { transition-delay: 0.12s; }
.js .studio-team__row[data-reveal].is-revealed img:nth-child(4) { transition-delay: 0.18s; }
.js .studio-team__row[data-reveal].is-revealed img:nth-child(5) { transition-delay: 0.24s; }
.js .studio-team__row[data-reveal].is-revealed img:nth-child(6) { transition-delay: 0.18s; }
.js .studio-team__row[data-reveal].is-revealed img:nth-child(7) { transition-delay: 0.12s; }
.js .studio-team__row[data-reveal].is-revealed img:nth-child(8) { transition-delay: 0.06s; }
.js .studio-team__row[data-reveal].is-revealed img:nth-child(9) { transition-delay: 0s; }

@media (prefers-reduced-motion: reduce) {
  .js .studio-team__row[data-reveal] img {
    opacity: 1;
    transition: none;
  }
  .studio-team__item {
    animation: none;
  }
}

@media (max-width: 900px) {
  /* Scaled to ~40% of desktop — big enough to actually read faces.
     `safe center` keeps the row centred when it fits, but falls back to
     start-alignment (scrollable) instead of clipping the left edge once
     it doesn't — plain `center` on an overflowing scroller clips content
     that scrollLeft can never reach (no negative scroll position), which
     is what silently cut off the first photo before this. */
  .studio-team__row {
    justify-content: center;
    justify-content: safe center;
    overflow-x: auto;
    gap: 4px;
    /* Vertical only — .section already insets the container horizontally
       on mobile, so side padding here would double that inset. */
    padding: 16px 0 24px;
  }
  .studio-team__row img:nth-child(1) { width: 36px; height: 52px; margin-top: 14px; --float-y: -4px; }
  .studio-team__row img:nth-child(2) { width: 60px; height: 84px; margin-left: -8px; margin-top: -9px; --float-y: -6px; }
  .studio-team__row img:nth-child(3) { width: 42px; height: 60px; margin-top: 18px; --float-y: -5px; }
  .studio-team__row img:nth-child(4) { width: 42px; height: 60px; margin-right: -6px; margin-top: -5px; --float-y: -7px; }
  .studio-team__row img:nth-child(5) { width: 92px; height: 128px; --float-y: -4px; }
  .studio-team__row img:nth-child(6) { width: 36px; height: 52px; margin-left: -10px; margin-top: 10px; --float-y: -5px; }
  .studio-team__row img:nth-child(7) { width: 68px; height: 92px; margin-top: -14px; --float-y: -6px; }
  .studio-team__row img:nth-child(8) { width: 32px; height: 44px; margin-top: 22px; --float-y: -3px; }
  .studio-team__row img:nth-child(9) { width: 76px; height: 104px; margin-left: -6px; margin-top: -6px; --float-y: -5px; }
}

/* Beliefs: "As nossas convicções" — on desktop the 3 cards share the
   container's full width equally; on mobile there's no room for that, so
   they switch to fixed-width cards in a horizontally scrolling row instead. */
.studio-beliefs__heading {
  margin-bottom: 32px;
}
.studio-beliefs__grid {
  display: flex;
  gap: 20px;
}
.studio-beliefs__card {
  flex: 1;
  min-width: 0;
  background: var(--color-gray-light);
  border-radius: var(--radius-card);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.studio-beliefs__illustration {
  width: 100%;
  aspect-ratio: 424 / 421;
  object-fit: cover;
  display: block;
}
.studio-beliefs__content {
  background: var(--color-white);
  margin: 12px;
  border-radius: 12px;
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.studio-beliefs__content h3 {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 24px;
  letter-spacing: -0.5px;
  color: var(--color-dark);
}
.studio-beliefs__content p {
  font-size: 16px;
  color: var(--color-dark);
  opacity: 0.5;
  line-height: 1.4;
}

@media (max-width: 900px) {
  .studio-beliefs__grid {
    flex-direction: column;
  }
  .studio-beliefs__card {
    flex: 1 1 auto;
    width: 100%;
  }
}

/* Projetos page */
.projects-hero {
  margin-top: 96px; /* clears fixed nav pill, same convention as .studio-intro */
  /* .section--loose's own 80px is replaced with this 24px — padding, not
     a child's margin-bottom, because a margin here would collapse through
     the section's bottom edge (no padding/border to stop it) and merge
     with .projects-list's own top spacing, making the gap uncontrollable. */
  padding-bottom: 24px;
}
.projects-list {
  padding-top: 0;
}
.projects-hero__heading {
  font-family: var(--font-header);
  font-weight: 700;
  font-size: clamp(28px, 4vw, 48px);
  letter-spacing: -1.5px;
  line-height: 1.2;
  max-width: 860px;
  margin-bottom: 32px;
  background: linear-gradient(90deg, var(--color-dark), var(--color-gray-muted));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
.projects-filterbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 16px;
  padding-top: 24px;
  border-top: 1px solid var(--color-gray-border);
}
.projects-filterbar__group {
  display: flex;
  align-items: center;
  gap: 12px;
}
.projects-filterbar__label {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--color-gray-text);
}
.projects-filterbar__pills {
  position: relative;
  display: flex;
  gap: 8px;
}
/* The "switch" — a single dark pill that js/projects-view.js slides
   between buttons on hover, snapping back to whichever is active when the
   mouse leaves the group. Sits behind the buttons (z-index below their
   default background) so it's only visible through the one button that's
   currently marked .is-covered (background made transparent for that). */
.projects-filterbar__indicator {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: 0;
  background: var(--color-dark);
  border-radius: var(--radius-pill);
  transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  pointer-events: none;
}
.projects-filterbar__pill {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 1px;
  text-transform: uppercase;
  border: none;
  border-radius: var(--radius-pill);
  padding: 10px 18px;
  background: var(--color-gray-light);
  color: var(--color-dark);
  cursor: pointer;
  transition: background 0.2s ease, color 0.2s ease;
}
.projects-filterbar__pill.is-covered {
  background: transparent;
  color: var(--color-white);
}
.projects-filterbar__pill--icon svg {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
}

/* Mobile-only accordion summary row — "Filtrar" and the current view name
   ("Pilha"/"Grelha", its icon+label copied in by js/projects-view.js) each
   collapse their matching .projects-filterbar__group panel below into a
   single tap target, since showing both groups' pills open at once (the
   desktop layout) wraps to too many lines on a narrow screen. Hidden here,
   shown only in the max-width:900px block below; desktop never sees it and
   both groups stay permanently visible there, exactly as before. */
.projects-filterbar__toggles {
  display: none;
}
.projects-filterbar__toggle-group {
  display: flex;
  align-items: center;
  gap: 8px;
}
.projects-filterbar__toggle {
  display: none;
  align-items: center;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 1px;
  text-transform: uppercase;
  border: none;
  border-radius: var(--radius-pill);
  padding: 10px 18px;
  background: var(--color-gray-light);
  color: var(--color-dark);
  cursor: pointer;
  transition: background 0.2s ease, color 0.2s ease;
}
.projects-filterbar__toggle.is-active {
  background: var(--color-dark);
  color: var(--color-white);
}
.projects-filterbar__toggle svg {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
}

@media (max-width: 900px) {
  .projects-filterbar {
    flex-direction: column;
    align-items: flex-start;
    gap: 20px;
  }
  .projects-filterbar__pills {
    flex-wrap: wrap;
  }
  .projects-filterbar__toggles {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
  }
  .projects-filterbar__toggle {
    display: inline-flex;
  }
  /* Redundant once the toggle row exists — "Filtrar"/"Ver" are already the
     toggle buttons' own labels, so repeating them inside the opened panel
     would just duplicate the word right above its own pill row. */
  .projects-filterbar__label {
    display: none;
  }
  /* Panels are the same .projects-filterbar__group markup desktop always
     shows — on mobile they start closed and only appear once their toggle
     above is tapped (js/projects-view.js adds/removes .is-open). */
  .projects-filterbar__group {
    display: none;
    width: 100%;
  }
  .projects-filterbar__group.is-open {
    display: flex;
  }
}

/* Client logos marquee — a continuous single-row strip that bleeds edge to
   edge of the viewport (breaks out of .container the same way
   .testimonials-carousel does), distinct from the homepage's fixed-slot
   grid rotator. js/logos-marquee.js renders a fresh random selection on
   every load and duplicates it once so the -50% loop point is seamless.
   The animation only starts once js/logos-marquee.js adds .is-ready
   (after every image has finished loading) — starting it any earlier
   would animate against a track whose width is still growing as each
   image's intrinsic size resolves, producing a visible jump/snap once
   loading settles and the "-50%" endpoint suddenly means a different
   pixel distance than it did a moment before. */
.logos-marquee {
  width: 100vw;
  position: relative;
  left: 50%;
  transform: translateX(-50%);
  overflow: hidden;
}
.logos-marquee__track {
  display: flex;
  align-items: center;
  gap: 64px;
  width: max-content;
}
.logos-marquee__track.is-ready {
  animation: logos-marquee-scroll 60s linear infinite;
}
.logos-marquee__track img {
  height: 40px;
  width: auto;
  object-fit: contain;
  flex-shrink: 0;
}
@keyframes logos-marquee-scroll {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}
@media (prefers-reduced-motion: reduce) {
  .logos-marquee__track.is-ready {
    animation: none;
  }
}
@media (max-width: 900px) {
  .logos-marquee__track {
    gap: 40px;
  }
  .logos-marquee__track img {
    height: 28px;
  }
}

.projects-hero__feature {
  flex: 0 0 476px;
  position: relative;
  height: 408px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  text-decoration: none; /* now an <a> (links to its case-study page) */
}
.projects-hero__side {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}
.projects-hero__card {
  flex: 1;
  min-width: 0;
  position: relative;
  text-decoration: none; /* now an <a> (links to its case-study page) — this and the child spans' own explicit colors keep it from looking like a plain link */
  display: flex;
  flex-direction: column;
  gap: 12px;
}
/* Both hero cards' photo now uses the exact same .project-card__media wrapper
   as every other card (radius, overflow-clip and the zoomed-in-by-default
   hover effect all come from those shared rules — see .project-card__media
   above) — this pair of selectors only supplies the un-zoom trigger, since
   the ancestor here is .projects-hero__feature/__card, not .project-card. */
.projects-hero__feature:hover .project-card__media img,
.projects-hero__card:hover .project-card__media img {
  transform: scale(1);
}
/* The two hero cards are taller/shorter than a normal card's aspect-ratio
   media, so their own fixed box height wins over .project-card__media's
   (aspect-ratio-driven) height instead. */
.projects-hero__feature .project-card__media,
.projects-hero__card .project-card__media {
  flex: 1;
  min-height: 0;
}
.projects-hero__caption {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.projects-hero__caption-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.projects-hero__caption-client {
  font-size: 13px;
  color: var(--color-gray-text);
}
.projects-hero__caption-title {
  font-family: var(--font-header);
  font-weight: 600;
  font-size: 16px;
  color: var(--color-dark);
}
/* Hidden per explicit request — same treatment as .project-card__tag. */
.projects-hero__caption-tag {
  display: none;
}
.projects-hero__caption-services {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  color: var(--color-gray-text);
}
@media (max-width: 900px) {
  .projects-hero__grid {
    flex-direction: column;
  }
  .projects-hero__feature {
    flex: none;
    width: 100%;
    height: auto;
    aspect-ratio: 476 / 408;
  }
  .projects-hero__card {
    aspect-ratio: 338 / 198;
  }
  /* In "grelha" the two hero cards drop their special wide/short ratios
     (476/408 and 338/198 above are "pilha"-only, for the curated
     feature+side layout) and go back to auto height, same as every other
     card in this view — the square 1:1 look comes from their inner
     .project-card__media (already forced 1:1 a few rules up), with the
     caption sitting below it in normal flow instead of a fixed-ratio box
     fighting that caption for space. */
  .projects-collection[data-view="grid"] .projects-hero__feature,
  .projects-collection[data-view="grid"] .projects-hero__card {
    aspect-ratio: auto;
  }
}

/* Project collection — rows mirror Figma's alternating layout (the hero
   feature+side row, a wide+narrow pair, its mirror, an even half/half row,
   then three even-thirds rows) in "stack" view. In "grid" view (toggled via
   js/projects-view.js) every .projects-row becomes display:contents so its
   cards unwrap directly into a single uniform 4-column grid. */
.projects-collection {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.projects-collection[data-view="grid"] {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
}
.projects-collection[data-view="grid"] .projects-row,
.projects-collection[data-view="grid"] .projects-hero__side {
  display: contents;
}
.projects-collection[data-view="grid"] .projects-hero__feature,
.projects-collection[data-view="grid"] .projects-hero__card {
  height: auto;
  /* A 1fr grid track won't shrink below its content's intrinsic width by
     default — without this, the feature card (much wider content than the
     small AVK-ONE-style side card) stretches its own column and starves
     the other, instead of the two splitting the row evenly. */
  min-width: 0;
}
/* "Grelha" gives each project a uniform square photo (instead of "pilha"'s
   curated mix of aspect ratios) — same plain media-then-caption layout as
   everywhere else, just with the photo itself forced to 1:1 (caption still
   sits below it, at its own natural height, same as every other card). */
.projects-collection[data-view="grid"] .project-card__media {
  aspect-ratio: 1 / 1;
  flex: none;
}
.projects-collection[data-view="grid"] .projects-list-cards {
  display: contents;
}
.projects-list-cards {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.projects-marquee-slot {
  padding: 24px 0;
}
@media (max-width: 900px) {
  .projects-collection[data-view="grid"] {
    grid-template-columns: repeat(2, 1fr);
  }
}

.projects-row {
  display: flex;
  gap: 12px;
}
.projects-row--even > * {
  flex: 1;
  min-width: 0;
}
.projects-row--wide-left > :first-child {
  flex: 63;
  min-width: 0;
}
.projects-row--wide-left > :last-child {
  flex: 37;
  min-width: 0;
}
.projects-row--wide-right > :first-child {
  flex: 37;
  min-width: 0;
}
.projects-row--wide-right > :last-child {
  flex: 63;
  min-width: 0;
}

.project-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-width: 0;
  text-decoration: none; /* some variants are now <a> (link to their case-study page) */
}
.project-card__media {
  position: relative;
  border-radius: 16px;
  overflow: hidden;
}
.project-card__media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Starts slightly zoomed in; hovering the card zooms back out to 100%,
     revealing a touch more of the shot instead of the more common (and
     more expected) zoom-in-on-hover. */
  transform: scale(1.1);
  transition: transform 0.5s cubic-bezier(0.2, 0, 0, 1), opacity 0.3s ease;
}
.project-card:hover .project-card__media img {
  transform: scale(1);
}
.project-card--a .project-card__media { aspect-ratio: 732 / 535; }
.project-card--b .project-card__media { aspect-ratio: 432 / 535; }
.project-card--c .project-card__media { aspect-ratio: 582 / 535; }
/* Every row using variant "d" (row 4 onward in the "pilha" list) is a plain
   3-up grid, not the varying-width treatment of the first 3 rows — square
   media keeps every card in it visually equal regardless of how many end
   up in a row after filtering. */
.project-card--d .project-card__media { aspect-ratio: 1 / 1; }

/* "Case study" hover chip — on every project card, every size variant,
   plus both hero cards. A real element (not ::after) because
   js/projects-view.js repositions it on mousemove, tracking the cursor —
   but only while the pointer is over the card's image area (its
   .project-card__media, or directly the <img> for the two hero cards),
   not the caption below; the JS toggles .is-visible for that same reason,
   rather than a plain CSS :hover on the whole card. left/top are set
   inline to the cursor's position; the fixed 16px translate here is what
   offsets the chip to the cursor's bottom-right instead of centering it. */
.project-card__chip {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 2;
  background: rgba(255, 255, 255, 0.92);
  color: var(--color-dark);
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  white-space: nowrap;
  padding: 8px 14px;
  border-radius: var(--radius-pill);
  opacity: 0;
  transform: translate(16px, 16px) scale(0.9);
  transform-origin: top left;
  transition: opacity 0.2s ease, transform 0.2s ease;
  pointer-events: none;
}
.project-card__chip.is-visible {
  opacity: 1;
  transform: translate(16px, 16px) scale(1);
}

.project-card__info {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.project-card__text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.project-card__client {
  font-size: 13px;
  color: var(--color-gray-text);
}
.project-card__title {
  font-family: var(--font-header);
  font-weight: 600;
  font-size: 16px;
  color: var(--color-dark);
}
/* Hidden per explicit request — kept in markup/CSS (not removed) so the
   category is still there for anything that might read it later (JS
   filtering already uses the item's own data-category, not this tag). */
.project-card__tag {
  display: none;
}
/* Deliverables/services for the project (from its own detail page's own
   "Serviços" list, capped at 2) — small mono caption under the title,
   deliberately not a pill/chip: with 40+ cards on this page, a repeated
   background shape everywhere would out-compete the photos and titles. */
.project-card__services {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  color: var(--color-gray-text);
}

/* display:none (not visibility) — filtered-out cards are fully removed
   from flow so the grid/stack rows close the gap and reflow around
   whatever's left, rather than leaving empty holes behind. */
.project-item.is-filtered-out {
  display: none;
}

/* Filter-change and load-more transitions. js/projects-view.js drives these
   by adding/removing the classes at the right moments — .is-leaving plays
   while a card is still in-flow (before .is-filtered-out removes it),
   .is-entering is added then removed one frame later so the browser
   commits the "from" state before animating to visible. */
.project-item {
  transition: opacity 0.3s ease, transform 0.3s ease;
}
.project-item.is-leaving,
.project-item.is-entering {
  opacity: 0;
  transform: scale(0.95);
  pointer-events: none;
}

/* Load-more skeleton: the real card is already in its final slot/size (the
   reflow placed it there before this class is added), so no placeholder
   shape has to be faked — the card's own image and text are just swapped
   for a shimmer block until the skeleton class is removed. */
@keyframes project-card-shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
.project-item.is-skeleton .project-card__media img {
  opacity: 0;
}
.project-item.is-skeleton .project-card__media::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, #ececec 25%, #f5f5f5 50%, #ececec 75%);
  background-size: 200% 100%;
  animation: project-card-shimmer 1.4s ease-in-out infinite;
}
.project-item.is-skeleton .project-card__client,
.project-item.is-skeleton .project-card__title {
  color: transparent;
  border-radius: 4px;
  background: linear-gradient(90deg, #ececec 25%, #f5f5f5 50%, #ececec 75%);
  background-size: 200% 100%;
  animation: project-card-shimmer 1.4s ease-in-out infinite;
}

/* Invisible trigger for the load-more IntersectionObserver — needs real
   layout (not display:none/hidden) to ever be observed as intersecting. */
.projects-load-more-sentinel {
  height: 1px;
}

@media (prefers-reduced-motion: reduce) {
  .project-item {
    transition: none;
  }
  .project-item.is-skeleton .project-card__media::before,
  .project-item.is-skeleton .project-card__client,
  .project-item.is-skeleton .project-card__title {
    animation: none;
  }
}

@media (max-width: 900px) {
  .projects-row {
    flex-direction: column;
  }
  /* One continuous 2-column grid across the whole list, not a separate grid
     per desktop row (some rows are half/half pairs, others thirds, and a
     filtered-out card would leave a hole in its own row's grid) — every
     .projects-row here becomes display:contents so its cards unwrap
     directly into .projects-list-cards' grid and reflow continuously, same
     trick already used for the "grid" view toggle above. The rule above
     still stacks .projects-row--hero's feature/side blocks full width,
     since that row isn't wrapped in .projects-list-cards. */
  .projects-list-cards {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 12px;
  }
  .projects-list-cards .projects-row {
    display: contents;
  }
  .projects-list-cards .projects-row > * {
    min-width: 0;
  }
  .project-card--a .project-card__media,
  .project-card--b .project-card__media,
  .project-card--c .project-card__media,
  .project-card--d .project-card__media {
    aspect-ratio: 4 / 3;
  }
}


/* Deliberate exception to this page's "always white section" convention
   (see note below) — requested explicitly for this section only, to
   match a reference layout with a dark gradient card and white content
   cards inside it. Background lives on .container (not the <section>),
   so it stays a contained, rounded card instead of a full-bleed strip. */
.services-reasons .container {
  position: relative;
  background:
    radial-gradient(120% 100% at 20% 15%, rgba(133, 89, 255, 0.35), transparent 55%),
    linear-gradient(140deg, #2a1252 0%, #170b2e 45%, #0a0714 100%);
  border-radius: 32px;
  padding: 64px 48px;
  overflow: hidden;
}
/* Fine grain texture over the gradient card, matching the reference's
   noise-on-dark-gradient look. SVG feTurbulence tiled as a background
   image rather than a canvas/JS approach, so it's free and static. */
.services-reasons .container::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  opacity: 1;
  mix-blend-mode: overlay;
  pointer-events: none;
}
.services-reasons__heading {
  margin-bottom: 40px;
  text-align: center;
  max-width: 640px;
  margin-left: auto;
  margin-right: auto;
  /* Dark-background variant of the site's title gradient — see .hero__title. */
  background: linear-gradient(90deg, var(--color-white), rgba(255, 255, 255, 0.5));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
.services-reasons__grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 20px;
}
.services-reasons__card {
  background: var(--color-white);
  border-radius: var(--radius-card);
  padding: 28px 24px;
}
.services-reasons__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--color-purple);
  color: var(--color-white);
  margin-bottom: 20px;
}
.services-reasons__icon svg {
  width: 22px;
  height: 22px;
}
.services-reasons__card-title {
  font-family: var(--font-header);
  font-weight: 600;
  font-size: 17px;
  letter-spacing: -0.3px;
  margin-bottom: 10px;
  color: var(--color-dark);
}
.services-reasons__card-desc {
  color: var(--color-gray-text);
  font-size: 14px;
  line-height: 1.5;
}

@media (max-width: 900px) {
  .services-reasons .container {
    padding: 40px 24px;
    border-radius: 24px;
  }
  .services-reasons__grid {
    grid-template-columns: 1fr;
  }
}
.services-reasons__card {
  transition: transform 0.3s cubic-bezier(0.2, 0, 0, 1), box-shadow 0.3s cubic-bezier(0.2, 0, 0, 1);
}
.services-reasons__card:hover {
  transform: translateY(-4px);
  box-shadow: 0 16px 32px rgba(0, 0, 0, 0.08);
}

/* Serviços page (servicos.html) — every section here keeps a plain white
   background per an explicit request; only individual CARDS within a
   section carry gray/purple accents, never the section itself. */
.servicos-hero {
  margin-top: 96px; /* clears fixed nav pill, same convention as .studio-intro */
}
.servicos-hero__eyebrow {
  display: inline-flex;
  align-self: flex-start;
  align-items: center;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: 14px;
  letter-spacing: 1.68px;
  text-transform: uppercase;
  color: var(--color-purple);
  margin-bottom: 24px;
}
.servicos-hero__heading {
  font-family: var(--font-header);
  font-weight: 700;
  font-size: clamp(32px, 5vw, 56px);
  letter-spacing: -2px;
  line-height: 1.15;
  max-width: 780px;
  margin-bottom: 16px;
  background: linear-gradient(90deg, var(--color-dark), var(--color-gray-muted));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
.servicos-hero__lede {
  font-family: var(--font-mono);
  font-size: 14px;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--color-gray-text);
}

/* Pulls the bento block closer to the hero above it — .section--loose's
   own 80px top padding would otherwise stack with the hero's 80px bottom
   padding for a 160px gap. */
.servicos-bento-section {
  padding-top: 0;
}

/* Bento grid for the Serviços page's three pillars (Marca/Web/Digital) —
   independent from the homepage's .service-item row list (different
   markup entirely), so this can't affect that section. Marca spans both
   rows in column 1 (repeated area name), Web/Digital stack in column 2. */
.servicos-bento {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
  grid-template-rows: repeat(2, minmax(240px, auto));
  grid-template-areas:
    "marca web"
    "marca digital";
  gap: 20px;
  background: var(--color-off-white);
  border-radius: 32px;
  padding: 20px;
}
.servicos-bento__card--marca { grid-area: marca; }
.servicos-bento__card--web { grid-area: web; }
.servicos-bento__card--digital { grid-area: digital; }

.servicos-bento__card {
  background: var(--color-white);
  border-radius: 24px;
  padding: 32px;
  display: flex;
  position: relative;
}
.servicos-bento__card--marca {
  flex-direction: column;
}
.servicos-bento__card--web,
.servicos-bento__card--digital {
  flex-direction: row;
  align-items: center;
  gap: 28px;
}
.servicos-bento__card:nth-child(1) { transition-delay: 0s; }
.servicos-bento__card:nth-child(2) { transition-delay: 0.12s; }
.servicos-bento__card:nth-child(3) { transition-delay: 0.24s; }

.servicos-bento__content {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-width: 0;
}
.servicos-bento__card--web .servicos-bento__content,
.servicos-bento__card--digital .servicos-bento__content {
  flex: 1 1 55%;
}
.servicos-bento__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 40px;
  height: 40px;
  color: var(--color-purple);
  margin-bottom: 20px;
}
.servicos-bento__icon svg,
.servicos-bento__icon img {
  width: 40px;
  height: 40px;
}
.servicos-bento__title {
  font-family: var(--font-header);
  font-weight: 600;
  font-size: 30px;
  letter-spacing: -0.5px;
  color: var(--color-dark);
  margin-bottom: 12px;
}
.servicos-bento__desc {
  color: var(--color-gray-text);
  line-height: 1.6;
  max-width: 400px;
  margin-bottom: 16px;
}
.servicos-bento__chip-list {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.servicos-bento__chip-list li {
  background: var(--color-gray-light);
  border-radius: var(--radius-pill);
  padding: 8px 16px;
  font-size: 13px;
  color: var(--color-dark);
}

/* Decorative image cluster: percentage-based (not fixed px like the
   homepage's .decorative-stack), so it scales fluidly with the grid
   card's actual rendered width instead of needing a breakpoint-specific
   scale factor. overflow:hidden on the wrapper crops any rotated bleed. */
.servicos-bento__media {
  position: relative;
  overflow: hidden;
}
.servicos-bento__card--marca .servicos-bento__media {
  width: 100%;
  flex: 1;
  min-height: 200px;
  margin-top: 28px;
}
.servicos-bento__card--web .servicos-bento__media,
.servicos-bento__card--digital .servicos-bento__media {
  flex: 0 0 38%;
  align-self: center;
  aspect-ratio: 1 / 1;
}
.servicos-bento__media img {
  position: absolute;
  border: 6px solid #fff;
  border-bottom-width: 20px;
  border-radius: 10px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.16);
  object-fit: cover;
}
.servicos-bento__media img:nth-child(1) {
  width: 60%;
  height: 76%;
  left: 28%;
  top: 14%;
}
.servicos-bento__media img:nth-child(2) {
  width: 52%;
  height: 40%;
  left: 40%;
  top: 6%;
  transform: rotate(6deg);
}
.servicos-bento__media img:nth-child(3) {
  width: 56%;
  height: 48%;
  left: 6%;
  top: 12%;
  transform: rotate(-6deg);
}

@media (max-width: 900px) {
  .servicos-bento {
    grid-template-columns: 1fr;
    grid-template-rows: none;
    grid-template-areas:
      "marca"
      "web"
      "digital";
    padding: 16px;
    gap: 16px;
  }
  .servicos-bento__card--web,
  .servicos-bento__card--digital {
    flex-direction: column;
  }
  .servicos-bento__card--web .servicos-bento__media,
  .servicos-bento__card--digital .servicos-bento__media {
    width: 100%;
    min-height: 180px;
    margin-top: 24px;
  }
}

.servicos-process__header {
  display: flex;
  flex-direction: column;
  margin-bottom: 48px;
}
.servicos-process__eyebrow {
  display: inline-flex;
  align-self: flex-start;
  align-items: center;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: 14px;
  letter-spacing: 1.68px;
  text-transform: uppercase;
  color: var(--color-purple);
  margin-bottom: 24px;
}
.servicos-process__heading-row {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 40px;
}
.servicos-process__heading {
  font-family: var(--font-header);
  font-weight: 700;
  font-size: clamp(28px, 4vw, 44px);
  letter-spacing: -1.5px;
  line-height: 1.15;
  margin-bottom: 16px;
  background: linear-gradient(90deg, var(--color-dark), var(--color-gray-muted));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
.servicos-process__lede {
  max-width: 340px;
  color: var(--color-gray-text);
  line-height: 1.5;
}
.servicos-process__list {
  list-style: none;
  display: flex;
  gap: 16px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  padding-bottom: 8px;
  scrollbar-width: none;
  /* Break out of the centered .container so cards can scroll edge-to-edge,
     matching .testimonials-carousel's technique. The padding uses the same
     max() as .container's own centering math (max-width 1280px) so the
     first card lines up with the heading/lede above it at any viewport
     width, instead of drifting left of it once the container starts
     centering with margins wider than --space-section-x. */
  width: 100vw;
  position: relative;
  left: 50%;
  transform: translateX(-50%);
  padding-left: max(var(--space-section-x), calc((100vw - 1280px) / 2));
  padding-right: max(var(--space-section-x), calc((100vw - 1280px) / 2));
  /* Without this, some engines treat resting scrollLeft:0 as "before" the
     first valid snap point and auto-advance past the leading padding on
     load, leaving card 1 flush with the viewport edge instead of aligned
     with the heading above it. */
  scroll-padding-left: max(var(--space-section-x), calc((100vw - 1280px) / 2));
}
.servicos-process__list::-webkit-scrollbar {
  display: none;
}
.servicos-process__card {
  scroll-snap-align: start;
  flex: 0 0 min(320px, 80vw);
  height: 400px;
  background: #F5F5F5;
  border-radius: var(--radius-card);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.servicos-process__card-media {
  flex: none;
  height: 50%;
  overflow: hidden;
}
.servicos-process__card-media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.servicos-process__card-body {
  flex: none;
  height: 50%;
  box-sizing: border-box;
  padding: 24px 28px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}
.servicos-process__card-label {
  font-family: var(--font-mono);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--color-gray-text);
}
.servicos-process__card-title {
  font-family: var(--font-header);
  font-weight: 600;
  font-size: 22px;
  letter-spacing: -0.5px;
  max-width: 200px;
  margin-top: 8px;
}
.servicos-process__card-number {
  font-family: var(--font-header);
  font-weight: 300;
  font-size: 40px;
  color: var(--color-gray-muted);
  align-self: flex-end;
}

@media (max-width: 900px) {
  .servicos-process__heading-row {
    flex-direction: column;
    align-items: flex-start;
    gap: 16px;
  }
  .servicos-process__list {
    padding-left: 24px;
    padding-right: 24px;
  }
}

.servicos-scope__block {
  display: flex;
  gap: 64px;
}
.servicos-scope__block + .servicos-scope__block {
  margin-top: 80px;
  padding-top: 80px;
  border-top: 1px solid var(--color-gray-border);
}
.servicos-scope__text {
  flex: 0 0 320px;
}
.servicos-scope__eyebrow {
  display: inline-flex;
  align-self: flex-start;
  align-items: center;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: 14px;
  letter-spacing: 1.68px;
  text-transform: uppercase;
  color: var(--color-purple);
  margin-bottom: 16px;
}
.servicos-scope__heading {
  font-family: var(--font-header);
  font-weight: 700;
  font-size: clamp(24px, 3vw, 32px);
  letter-spacing: -1px;
  line-height: 1.25;
  margin-bottom: 16px;
  background: linear-gradient(90deg, var(--color-dark), var(--color-gray-muted));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
.servicos-scope__lede {
  color: var(--color-gray-text);
  line-height: 1.5;
}
.servicos-scope__grid {
  flex: 1;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 20px;
}
.servicos-scope__item {
  background: #F5F5F5;
  border-radius: var(--radius-card);
  padding: 24px;
}
.servicos-scope__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--color-white);
  color: var(--color-purple);
  margin-bottom: 16px;
}
.servicos-scope__icon svg {
  width: 20px;
  height: 20px;
}
.servicos-scope__item-title {
  font-family: var(--font-header);
  font-weight: 600;
  font-size: 17px;
  color: var(--color-dark);
  margin-bottom: 8px;
}
.servicos-scope__item-desc {
  color: var(--color-gray-text);
  font-size: 15px;
  line-height: 1.5;
}

/* Indústrias block: heading sits centered on top and the grid runs 3-up,
   matching the reference. Entregáveis (below) uses the same centered-header
   layout, just with its own icon-led item style instead of photo cards. */
.servicos-scope__block--industries,
.servicos-scope__block--deliverables {
  flex-direction: column;
}
.servicos-scope__text--center {
  flex: none;
  max-width: 620px;
  margin: 0 auto 40px;
  text-align: center;
}
.servicos-scope__grid--3col {
  grid-template-columns: repeat(3, 1fr);
}

/* Entregáveis grid — icon-led rows (icon to the left, title+desc stacked
   to its right), no card background, matching the reference's plain
   "feature list" look rather than the boxed .servicos-scope__item cards
   used elsewhere on this page. */
.deliverables-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  column-gap: 48px;
  row-gap: 40px;
}
.deliverables-item {
  display: flex;
  align-items: flex-start;
  gap: 16px;
}
.deliverables-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  border-radius: 12px;
  background: var(--color-gray-light);
  color: var(--color-purple);
  flex-shrink: 0;
}
.deliverables-icon svg {
  width: 22px;
  height: 22px;
}
.deliverables-item-title {
  font-family: var(--font-header);
  font-weight: 600;
  font-size: 17px;
  color: var(--color-dark);
  margin-bottom: 6px;
}
.deliverables-item-desc {
  color: var(--color-gray-text);
  font-size: 15px;
  line-height: 1.5;
}

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

/* Photo cards: same composition as .testimonial-card — gray outer card,
   photo on top, white text panel below (industry name included in it). */
.servicos-scope__item--photo {
  background: var(--color-gray-light);
  border-radius: var(--radius-card);
  padding: 12px;
}
.servicos-scope__item-media {
  border-radius: 12px;
  overflow: hidden;
  aspect-ratio: 16 / 9;
}
.servicos-scope__item-media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.servicos-scope__item-body {
  background: var(--color-white);
  border-radius: 12px;
  padding: 20px;
  margin-top: 12px;
}
.servicos-scope__item--photo .servicos-scope__item-title {
  font-size: 18px;
  margin-bottom: 8px;
}
.servicos-scope__item--photo .servicos-scope__item-desc {
  margin: 0;
}

/* Stacked client logos — "quem já trabalhámos nesta área", one small ring
   per client, each overlapping the previous one (later markup order paints
   on top, no z-index needed). The body panel itself is white, so the ring
   uses the card's own gray tone instead of white to stay visible against it. */
.servicos-scope__clients {
  display: flex;
  margin-top: var(--space-4);
}
.servicos-scope__clients img {
  width: 36px;
  height: 36px;
  padding: 0;
  box-sizing: border-box;
  border-radius: 50%;
  background: var(--color-white);
  border: 2px solid var(--color-gray-light);
  object-fit: contain;
}
.servicos-scope__clients img:not(:first-child) {
  margin-left: -12px;
}

@media (max-width: 900px) {
  .servicos-scope__block {
    flex-direction: column;
    gap: 32px;
  }
  .servicos-scope__text {
    flex: none;
  }
  .servicos-scope__text--center {
    margin: 0 0 32px;
    text-align: left;
  }
  .servicos-scope__block + .servicos-scope__block {
    margin-top: 48px;
    padding-top: 48px;
  }
  .servicos-scope__grid,
  .servicos-scope__grid--3col {
    grid-template-columns: 1fr;
    gap: 16px;
  }
}

@media (min-width: 901px) and (max-width: 1100px) {
  .servicos-scope__grid--3col {
    grid-template-columns: repeat(2, 1fr);
  }
}

.servicos-faq {
  background: var(--color-white);
}
.servicos-faq__layout {
  display: flex;
  align-items: flex-start;
  gap: 64px;
}
.servicos-faq__intro {
  flex: 0 0 320px;
  position: sticky;
  top: 120px;
}
.servicos-faq__eyebrow {
  display: inline-flex;
  align-self: flex-start;
  align-items: center;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: 14px;
  letter-spacing: 1.68px;
  text-transform: uppercase;
  color: var(--color-purple);
  margin-bottom: 20px;
}
.servicos-faq__heading {
  font-family: var(--font-header);
  font-weight: 700;
  font-size: clamp(48px, 6vw, 88px);
  letter-spacing: -3px;
  line-height: 0.95;
  margin: 0;
  background: linear-gradient(90deg, var(--color-dark), var(--color-gray-muted));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
.servicos-faq__list {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.servicos-faq__item {
  background: var(--color-white);
  border: 1px solid #F5F5F5;
  border-radius: 20px;
  padding: 0 28px;
  transition: box-shadow 0.3s cubic-bezier(0.2, 0, 0, 1);
}
.servicos-faq__item.is-open {
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.06);
}
.servicos-faq__question {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  background: none;
  border: none;
  color: var(--color-dark);
  font-family: var(--font-header);
  font-size: 18px;
  font-weight: 500;
  letter-spacing: -0.3px;
  text-align: left;
  padding: 24px 0 16px;
  cursor: pointer;
}
.servicos-faq__icon {
  position: relative;
  flex-shrink: 0;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 1px solid rgba(0, 0, 0, 0.12);
  transition: background 0.3s cubic-bezier(0.2, 0, 0, 1), border-color 0.3s cubic-bezier(0.2, 0, 0, 1);
}
.servicos-faq__icon span {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 12px;
  height: 1.5px;
  background: var(--color-dark);
  transform: translate(-50%, -50%);
  transition: transform 0.3s cubic-bezier(0.2, 0, 0, 1), background 0.3s cubic-bezier(0.2, 0, 0, 1);
}
.servicos-faq__icon span:last-child {
  transform: translate(-50%, -50%) rotate(90deg);
}
.servicos-faq__item.is-open .servicos-faq__icon {
  background: var(--color-dark);
  border-color: var(--color-dark);
}
.servicos-faq__item.is-open .servicos-faq__icon span {
  background: var(--color-white);
}
.servicos-faq__item.is-open .servicos-faq__icon span:last-child {
  transform: translate(-50%, -50%) rotate(0deg) scaleY(0);
}
.servicos-faq__answer {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.35s cubic-bezier(0.2, 0, 0, 1);
}
.servicos-faq__item.is-open .servicos-faq__answer {
  grid-template-rows: 1fr;
}
.servicos-faq__answer-inner {
  overflow: hidden;
}
.servicos-faq__answer-inner p {
  max-width: 560px;
  color: var(--color-gray-text);
  line-height: 1.6;
  padding-bottom: 24px;
}

@media (max-width: 900px) {
  .servicos-faq__layout {
    flex-direction: column;
    gap: 32px;
  }
  .servicos-faq__intro {
    position: static;
    flex: none;
  }
  .servicos-faq__heading {
    font-size: clamp(40px, 14vw, 64px);
  }
  .servicos-faq__question {
    font-size: 16px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .servicos-faq__answer,
  .servicos-faq__icon,
  .servicos-faq__icon span,
  .servicos-faq__item {
    transition: none;
  }
}

/* Contacto page (contacto.html) — two-column layout, form on the right
   with a type selector that shows/reveals fields per motive (handled by
   js/contact-page-form.js via [hidden] on [data-type-group]). */
.contact-page {
  background: var(--color-white);
  margin-top: 96px; /* clears the fixed nav pill, same convention as .servicos-hero */
}
.contact-page__layout {
  display: flex;
  align-items: flex-start;
  gap: 64px;
}
.contact-page__intro {
  flex: 0 0 340px;
  position: sticky;
  top: 120px;
}
.contact-page__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: 14px;
  letter-spacing: 1.68px;
  text-transform: uppercase;
  color: var(--color-purple);
  margin-bottom: 24px;
}
.contact-page__heading {
  font-family: var(--font-header);
  font-weight: 700;
  font-size: clamp(32px, 5vw, 48px);
  letter-spacing: -2px;
  line-height: 1.15;
  margin-bottom: 16px;
  background: linear-gradient(90deg, var(--color-dark), var(--color-gray-muted));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
.contact-page__lede {
  color: var(--color-gray-text);
  line-height: 1.6;
}
.contact-page__form {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.contact-type {
  border: none;
  padding: 0;
  margin: 0;
}
.contact-type__legend {
  display: block;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--color-gray-text);
  margin-bottom: 12px;
  padding: 0;
}
.contact-type__options {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
}
.contact-type__option {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 16px 40px 16px 16px;
  border: 1px solid var(--color-gray-border);
  border-radius: 16px;
  cursor: pointer;
  transition: border-color 0.2s ease, background 0.2s ease;
}
.contact-type__option:has(input:checked) {
  border-color: var(--color-purple);
  background: var(--color-off-white);
}
.contact-type__option input {
  position: absolute;
  top: 16px;
  right: 16px;
  margin: 0;
  accent-color: var(--color-purple);
}
.contact-type__option-title {
  font-family: var(--font-header);
  font-weight: 600;
  font-size: 15px;
  color: var(--color-dark);
}
.contact-type__option-desc {
  font-size: 13px;
  color: var(--color-gray-text);
}

.contact-page__row {
  display: flex;
  gap: 20px;
}

.contact-page__footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  margin-top: 8px;
}
.contact-page__alt {
  font-size: 14px;
  color: var(--color-gray-text);
  line-height: 1.5;
}
.contact-page__alt a {
  color: var(--color-dark);
}
.contact-page__submit {
  flex-shrink: 0;
}

@media (max-width: 900px) {
  .contact-page__layout {
    flex-direction: column;
    gap: 32px;
  }
  .contact-page__intro {
    position: static;
    flex: none;
  }
  .contact-type__options {
    grid-template-columns: 1fr;
  }
  .contact-page__row {
    flex-direction: column;
    gap: 20px;
  }
  .contact-page__footer {
    flex-direction: column;
    align-items: flex-start;
    gap: 24px;
  }
  /* Visual order only (DOM/reading order stays as-is): the submit button
     reads as the primary action, so it comes first on mobile instead of
     the "prefer e-mail" alternative sitting above it. */
  .contact-page__submit {
    order: 1;
  }
  .contact-page__alt {
    order: 2;
    width: 100%;
    padding-top: 24px;
    border-top: 1px solid var(--color-gray-border);
  }
}

/* Fade helper for text that swaps when the contact type changes (js/
   contact-dynamic-content.js) — the class is toggled briefly around the
   textContent swap so the change reads as a soft crossfade, not a jump. */
[data-dynamic] {
  transition: opacity 0.2s ease;
}
[data-dynamic].is-fading {
  opacity: 0;
}
@media (prefers-reduced-motion: reduce) {
  [data-dynamic] {
    transition: none;
  }
}

/* Contacto page: "What's next" timeline + continuous project gallery. */
.contact-next {
  background: var(--color-white);
}
.contact-next__header {
  max-width: 640px;
  margin-bottom: 56px;
}
.contact-next__eyebrow {
  display: inline-flex;
  align-self: flex-start;
  align-items: center;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: 14px;
  letter-spacing: 1.68px;
  text-transform: uppercase;
  color: var(--color-purple);
  margin-bottom: 12px;
}
.contact-next__heading {
  font-family: var(--font-header);
  font-weight: 700;
  font-size: clamp(28px, 4vw, 40px);
  letter-spacing: -1px;
  line-height: 1.2;
  background: linear-gradient(90deg, var(--color-dark), var(--color-gray-muted));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
.contact-next__grid {
  display: flex;
  gap: 48px;
  align-items: stretch;
}
.contact-next__timeline {
  list-style: none;
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 48px;
  padding-left: 64px;
  flex: 1.6;
}
/* Illustrative side image, same "text card + photo" proportion as
   .studio-hero__grid on the Estúdio page — swapped per contact type by
   js/contact-dynamic-content.js (fades via the shared [data-dynamic]
   helper, same as the heading/steps/FAQ text). Split into an inner frame
   (clips the photo to the rounded corners) and a sibling chip layer that
   is allowed to overflow slightly, so the scattered pill chips can bleed
   past the edge a little without also un-cropping the photo underneath. */
.contact-next__visual {
  position: relative;
  flex: 1;
  min-height: 320px;
}
.contact-next__visual-frame {
  width: 100%;
  height: 100%;
  border-radius: var(--radius-card);
  overflow: hidden;
}
.contact-next__visual-frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Tidy word-chip cluster over the photo — a real flex-wrap layout (not
   absolute-positioned slots), so the pills sit neatly packed with a fixed
   gap and can never overlap, however the words' lengths change per
   contact type. Hovering the photo nudges each chip up/down a few pixels
   (well within the gap, so neighbours never touch) with a staggered
   delay — a gentle "loose pieces settling" feel without real rotation or
   risk of overlap. */
.contact-next__chips {
  position: absolute;
  left: 20px;
  right: 20px;
  bottom: 20px;
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  pointer-events: none;
}
.contact-next__chip {
  background: var(--color-white);
  color: var(--color-dark);
  font-family: var(--font-header);
  font-weight: 700;
  font-size: 14px;
  letter-spacing: -0.2px;
  padding: 10px 18px;
  border-radius: var(--radius-pill);
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.18);
  white-space: nowrap;
  transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.contact-next__chip--dark {
  background: var(--color-dark);
  color: var(--color-white);
}
.contact-next__chip--purple {
  background: var(--color-purple);
  color: var(--color-white);
}

.contact-next__visual:hover .contact-next__chip:nth-child(1) { transform: translateY(-5px); transition-delay: 0s; }
.contact-next__visual:hover .contact-next__chip:nth-child(2) { transform: translateY(5px); transition-delay: 0.03s; }
.contact-next__visual:hover .contact-next__chip:nth-child(3) { transform: translateY(-5px); transition-delay: 0.06s; }
.contact-next__visual:hover .contact-next__chip:nth-child(4) { transform: translateY(5px); transition-delay: 0.09s; }
.contact-next__visual:hover .contact-next__chip:nth-child(5) { transform: translateY(-5px); transition-delay: 0.12s; }
.contact-next__visual:hover .contact-next__chip:nth-child(6) { transform: translateY(5px); transition-delay: 0.15s; }

@media (prefers-reduced-motion: reduce) {
  .contact-next__chip {
    transition: none;
  }
}
.contact-next__timeline::before {
  content: "";
  position: absolute;
  left: 19px;
  top: 8px;
  bottom: 60px;
  width: 1px;
  background: var(--color-gray-border);
}
.contact-next__step {
  position: relative;
}
.contact-next__step-number {
  position: absolute;
  left: -64px;
  top: 0;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 1px solid var(--color-gray-border);
  background: var(--color-white);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-header);
  font-weight: 600;
  font-size: 14px;
  color: var(--color-dark);
}
.contact-next__step-title {
  font-family: var(--font-header);
  font-weight: 600;
  font-size: 20px;
  letter-spacing: -0.3px;
  color: var(--color-dark);
  margin-bottom: 8px;
}
.contact-next__step-desc {
  color: var(--color-gray-text);
  line-height: 1.6;
  max-width: 480px;
}

/* Continuous marquee (same technique as .logos-marquee): js/contact-
   gallery-marquee.js renders a random selection of project photos twice
   back to back so the -50% loop point is seamless, then adds .is-ready
   once every image has loaded — starting the animation any earlier would
   animate against a track whose width is still growing. */
.contact-next__gallery {
  width: 100vw;
  position: relative;
  left: 50%;
  transform: translateX(-50%);
  overflow: hidden;
  margin-top: 64px;
}
.contact-next__gallery-track {
  display: flex;
  align-items: center;
  gap: 20px;
  width: max-content;
}
.contact-next__gallery-track.is-ready {
  animation: contact-gallery-scroll 90s linear infinite;
}
@keyframes contact-gallery-scroll {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}
@media (prefers-reduced-motion: reduce) {
  .contact-next__gallery-track.is-ready {
    animation: none;
  }
}

/* Each gallery photo now links to its case study — same zoom-out-on-hover
   image treatment and cursor-tracking "Case study" chip as the main
   projects grid (see .project-card__media / .project-card__chip), just
   under a dedicated class since the fixed marquee size doesn't fit the
   grid's variant system. */
.contact-gallery-item {
  position: relative;
  display: block;
  flex-shrink: 0;
  text-decoration: none;
}
.contact-gallery-item__media {
  height: 260px;
  width: 360px;
  border-radius: 20px;
  overflow: hidden;
}
.contact-gallery-item__media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: scale(1.1);
  transition: transform 0.5s cubic-bezier(0.2, 0, 0, 1);
}
.contact-gallery-item:hover .contact-gallery-item__media img {
  transform: scale(1);
}

@media (max-width: 900px) {
  .contact-next__grid {
    flex-direction: column;
  }
  .contact-next__visual {
    min-height: 0;
    aspect-ratio: 4 / 3;
  }
  .contact-next__chip {
    font-size: 12px;
    padding: 7px 12px;
  }
  .contact-next__timeline {
    padding-left: 52px;
    gap: 36px;
  }
  .contact-next__timeline::before {
    left: 15px;
  }
  .contact-next__step-number {
    left: -52px;
    width: 32px;
    height: 32px;
    font-size: 12px;
  }
  .contact-gallery-item__media {
    height: 180px;
    width: 260px;
  }
}

/* Project detail page template (projeto/*.html) — same white-first,
   light-section style as the rest of the site (no dark theme). */
.project-detail {
  background: var(--color-white);
  color: var(--color-dark);
}
.project-detail__hero {
  margin-top: 96px; /* clears the fixed nav pill, same convention as .servicos-hero */
  /* .section--loose's own 80px is replaced with this 0 — same reasoning as
     .projects-hero above: a child margin here would collapse through the
     section's open bottom edge, so the gap to .project-detail__intro-section
     (which keeps its own 80px padding-top) has to be controlled from this
     side instead. Net gap to the content below: 80px, down from 160px. */
  padding-bottom: 0;
}

.project-detail__back-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 32px;
  color: var(--color-gray-text);
  text-decoration: none;
  transition: color 0.2s ease;
}
.project-detail__back-link:hover {
  color: var(--color-dark);
}

/* "Browser window" frame around screenshots — a thin top chrome bar with
   traffic-light dots for the ones that are actual website screenshots;
   --frame--plain drops the chrome for straight lifestyle/product photos. */
.project-detail__frame {
  max-width: 1040px;
  margin: 0 auto;
  border-radius: 20px;
  overflow: hidden;
  background: var(--color-off-white);
  border: 1px solid var(--color-gray-border);
  box-shadow: 0 24px 64px rgba(0, 0, 0, 0.12);
}
.project-detail__frame-chrome {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 16px;
  background: var(--color-gray-light);
}
.project-detail__frame-chrome span {
  width: 10px;
  height: 10px;
  border-radius: 50%;
}
.project-detail__frame-chrome span:nth-child(1) { background: #ff5f56; }
.project-detail__frame-chrome span:nth-child(2) { background: #ffbd2e; }
.project-detail__frame-chrome span:nth-child(3) { background: #27c93f; }
.project-detail__frame img {
  display: block;
  width: 100%;
  height: auto;
}
/* Desktop only — a fixed 40vh keeps every project's hero shot the same
   height regardless of its native aspect ratio, so the page never has to
   scroll further than that before reaching the actual text content below.
   object-fit:cover crops instead of letterboxing to fill that height. */
@media (min-width: 901px) {
  .project-detail__frame img {
    height: 56vh;
    object-fit: cover;
  }
}

.project-detail__intro-grid {
  display: flex;
  align-items: flex-start;
  gap: 48px;
  margin-bottom: 48px;
}
.project-detail__intro {
  flex: 1.4;
}
.project-detail__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: 14px;
  letter-spacing: 1.68px;
  text-transform: uppercase;
  color: var(--color-purple);
  margin-bottom: 16px;
}
.project-detail__heading {
  font-family: var(--font-header);
  font-weight: 700;
  font-size: clamp(32px, 4.5vw, 52px);
  letter-spacing: -1.5px;
  line-height: 1.15;
  background: linear-gradient(90deg, var(--color-dark), var(--color-gray-muted));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
.project-detail__date {
  margin-top: 20px;
  font-size: 14px;
  color: var(--color-gray-muted);
}
.project-detail__meta {
  flex: 1;
  display: flex;
  gap: 32px;
}
.project-detail__meta-col {
  flex: 1;
  min-width: 0;
}
.project-detail__meta-label {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--color-gray-muted);
  margin-bottom: 12px;
}
.project-detail__meta-col ul {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.project-detail__meta-col li {
  font-size: 14px;
  color: var(--color-dark);
}
.project-detail__meta-col a {
  color: var(--color-dark);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.project-detail__meta-col a:hover {
  color: var(--color-purple);
}
.project-detail__lede {
  max-width: 760px;
  color: var(--color-gray-text);
  line-height: 1.6;
  font-size: 17px;
}

.project-detail__text-grid {
  display: flex;
  align-items: flex-start;
  gap: 64px;
}
.project-detail__text-heading {
  flex: 0 0 300px;
  font-family: var(--font-header);
  font-weight: 700;
  font-size: clamp(24px, 3vw, 32px);
  letter-spacing: -0.5px;
  background: linear-gradient(90deg, var(--color-dark), var(--color-gray-muted));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
.project-detail__text-body {
  flex: 1;
  max-width: 640px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  color: var(--color-gray-text);
  line-height: 1.7;
  font-size: 16px;
}

.project-detail__next {
  background: var(--color-off-white);
}
.project-detail__next-inner {
  max-width: 640px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
  text-align: center;
}
.project-detail__next-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: 14px;
  letter-spacing: 1.68px;
  text-transform: uppercase;
  color: var(--color-purple);
}
.project-detail__next-heading {
  font-family: var(--font-header);
  font-weight: 700;
  font-size: clamp(24px, 3.5vw, 36px);
  letter-spacing: -0.5px;
  background: linear-gradient(90deg, var(--color-dark), var(--color-gray-muted));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
.project-detail__next-actions {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
  justify-content: center;
}

/* Related projects — reuses the page's random-3-of-N + exclude-self
   pattern (js/related-projects.js + js/projects-data.js), rendered as a
   simple card, distinct from (and simpler than) the curated projetos.html
   grid's aspect-ratio modifiers, which assume that page's specific
   row layout. */
.related-projects__heading {
  font-family: var(--font-header);
  font-weight: 700;
  font-size: clamp(24px, 3vw, 32px);
  letter-spacing: -0.5px;
  margin-bottom: 32px;
  background: linear-gradient(90deg, var(--color-dark), var(--color-gray-muted));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
.related-projects__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
}
.related-project-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 12px;
  text-decoration: none;
  color: inherit;
}
.related-project-card__media {
  border-radius: 16px;
  overflow: hidden;
  aspect-ratio: 4 / 3;
}
.related-project-card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 0.4s cubic-bezier(0.2, 0, 0, 1);
}
.related-project-card:hover .related-project-card__media img {
  transform: scale(1.05);
}
.related-project-card__info {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.related-project-card__client {
  font-size: 13px;
  color: var(--color-gray-text);
}
.related-project-card__title {
  font-family: var(--font-header);
  font-weight: 600;
  font-size: 16px;
  color: var(--color-dark);
}
.related-project-card__tag {
  display: none;
}

@media (max-width: 900px) {
  .project-detail__intro-grid {
    flex-direction: column;
    gap: 32px;
  }
  /* Wraps instead of stacking full-column, so "Serviços" and "Entregáveis"
     (the first two columns) stay side by side at ~50% each; "Links" (the
     3rd) just wraps onto its own line below them. */
  .project-detail__meta {
    flex-wrap: wrap;
    row-gap: 24px;
  }
  .project-detail__meta-col {
    flex: 1 1 calc(50% - 16px);
  }
  .project-detail__text-grid {
    flex-direction: column;
    gap: 16px;
  }
  .project-detail__text-heading {
    flex: none;
  }
  .related-projects__grid {
    grid-template-columns: 1fr;
  }
}

/* Logos API page (logosapi.html) — standalone product page, not in the
   main nav. Reuses .servicos-hero / .servicos-scope wholesale (see above);
   only the pieces with no existing equivalent get new rules here: the
   hero's extra description line, the coverage stats row, the centered
   statement block and the pricing cards. */
.logosapi-hero__desc {
  color: var(--color-gray-text);
  line-height: 1.6;
  max-width: 560px;
  margin-bottom: 24px;
}
.logosapi-hero__actions {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
}

/* Pulls this block closer to the hero above it, same reasoning as
   .servicos-bento-section right after .servicos-hero. */
.logosapi-projects-section {
  padding-top: 0;
}
.logosapi-stats-section {
  padding-top: 0;
}
.logosapi-stats {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 32px;
  background: #f5f5f5;
  border-radius: var(--radius-card);
  padding: 40px;
}
.logosapi-stats__stat {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.logosapi-stats__stat-number {
  font-family: var(--font-header);
  font-weight: 700;
  font-size: 40px;
  letter-spacing: -1px;
  color: var(--color-dark);
}
.logosapi-stats__stat-label {
  font-size: 15px;
  color: var(--color-gray-text);
}

.logosapi-statement {
  max-width: 640px;
  margin: 0 auto;
  text-align: center;
}
.logosapi-statement__heading {
  font-family: var(--font-header);
  font-weight: 700;
  font-size: clamp(24px, 3vw, 32px);
  letter-spacing: -1px;
  line-height: 1.25;
  margin-bottom: 16px;
  background: linear-gradient(90deg, var(--color-dark), var(--color-gray-muted));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
.logosapi-statement__lede {
  color: var(--color-gray-text);
  line-height: 1.6;
}

.logosapi-pricing__header {
  text-align: center;
  max-width: 560px;
  margin: 0 auto 40px;
}
.logosapi-pricing__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
  align-items: stretch;
}
.logosapi-pricing__card {
  display: flex;
  flex-direction: column;
  gap: 20px;
  background: #f5f5f5;
  border-radius: var(--radius-card);
  padding: 32px 28px;
  position: relative;
}
.logosapi-pricing__card--highlight {
  background: var(--color-dark);
  color: var(--color-white);
}
.logosapi-pricing__badge {
  position: absolute;
  top: 32px;
  right: 28px;
  background: var(--color-purple);
  color: var(--color-white);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  padding: 4px 12px;
  border-radius: var(--radius-pill);
}
.logosapi-pricing__name {
  font-family: var(--font-header);
  font-weight: 600;
  font-size: 20px;
}
.logosapi-pricing__volume {
  font-size: 14px;
  color: var(--color-gray-text);
}
.logosapi-pricing__card--highlight .logosapi-pricing__volume {
  color: rgba(255, 255, 255, 0.7);
}
.logosapi-pricing__price {
  font-family: var(--font-header);
  font-weight: 700;
  font-size: 36px;
  letter-spacing: -1px;
}
.logosapi-pricing__price span {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 14px;
  color: var(--color-gray-text);
}
.logosapi-pricing__card--highlight .logosapi-pricing__price span {
  color: rgba(255, 255, 255, 0.7);
}
.logosapi-pricing__card .btn {
  margin-top: auto;
  align-self: flex-start;
}

@media (max-width: 900px) {
  .logosapi-stats {
    flex-direction: column;
    gap: 24px;
    padding: 28px;
  }
  .logosapi-pricing__grid {
    grid-template-columns: 1fr;
  }
}

