/* ============================================================
   REFORMAE — Reusable components
   Duotone photo placeholders · reveals · cursor · marquee
   ============================================================ */

/* ---------- Duotone photo placeholder ----------
   Stands in for real site photography. Architectural,
   textural, never clip-art. Marked "SUBSTITUIR". ---------- */
.ph {
  position: relative;
  overflow: hidden;
  background: var(--stone-100);
  border-radius: var(--radius);
  isolation: isolate;
}
.ph[data-ratio="4/5"]  { aspect-ratio: 4 / 5; }
.ph[data-ratio="16/9"] { aspect-ratio: 16 / 9; }
.ph[data-ratio="3/4"]  { aspect-ratio: 3 / 4; }
.ph[data-ratio="1/1"]  { aspect-ratio: 1 / 1; }
.ph[data-ratio="3/2"]  { aspect-ratio: 3 / 2; }
.ph--flush { border-radius: 0; }

/* concrete-like layered surface (duotone: stone -> ink wash) */
.ph__fill {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(135deg, rgba(21,20,15,.05), rgba(21,20,15,.22)),
    repeating-linear-gradient(115deg,
      rgba(21,20,15,.035) 0 2px,
      transparent 2px 26px),
    radial-gradient(120% 90% at 75% 15%, var(--stone-100), var(--stone-300) 70%, #B4AC9C);
  filter: saturate(.6);
  transition: transform 1s var(--ease), filter .6s var(--ease);
  will-change: transform;
}
.ph--ember .ph__fill {
  background:
    linear-gradient(135deg, rgba(194,65,12,.16), rgba(21,20,15,.4)),
    repeating-linear-gradient(115deg, rgba(255,255,255,.03) 0 2px, transparent 2px 26px),
    radial-gradient(120% 90% at 70% 20%, #D9663A, #8F3414 75%, #5C2410);
}
.ph--ink .ph__fill {
  background:
    linear-gradient(135deg, rgba(255,255,255,.04), rgba(0,0,0,.5)),
    repeating-linear-gradient(115deg, rgba(255,255,255,.03) 0 2px, transparent 2px 26px),
    radial-gradient(120% 90% at 70% 20%, #34302A, #1A1813 80%);
}
/* grain inside the photo */
.ph__fill::after {
  content: "";
  position: absolute; inset: 0;
  opacity: .5; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
/* corner tick + label */
.ph__tag {
  position: absolute;
  left: 14px; bottom: 12px;
  font-family: var(--mono);
  font-size: .62rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: rgba(255,255,255,.82);
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: .55em;
  padding: .4em .6em;
  background: rgba(21,20,15,.42);
  backdrop-filter: blur(2px);
  border-radius: 6px;
}
.ph__tag::before {
  content: ""; width: 5px; height: 5px;
  background: var(--ember); border-radius: 50%;
  box-shadow: 0 0 0 3px rgba(194,65,12,.25);
}
.ph__caption {
  position: absolute;
  right: 14px; top: 14px;
  font-family: var(--mono);
  font-size: .6rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: rgba(255,255,255,.6);
  z-index: 2;
}
/* hover zoom for interactive cards */
.zoomable:hover .ph__fill { transform: scale(1.06); filter: saturate(.78); }

/* ---- Imagens reais dentro de um slot .ph (substituem o placeholder duotone) ----
   Suporta <img class="ph__img"> direto ou <picture><img></picture>.
   Veja imagens.md para o padrão de markup, tamanhos e formatos. */
.ph > img, .ph > picture { position: absolute; inset: 0; z-index: 1; }
.ph > img, .ph > picture > img { width: 100%; height: 100%; object-fit: cover; display: block; will-change: transform; }
.ph img { transition: transform 1s var(--ease); }
.zoomable:hover .ph img { transform: scale(1.06); }

/* ---------- Reveal animations ---------- */
[data-reveal] { will-change: transform, opacity; }

/* ===== Reveal system =====
   DEFAULT = fully visible. Hidden-initial states are armed ONLY
   when JS adds html.reveal-on (i.e. it confirmed the animation
   timeline is live). If JS never runs or the timeline freezes,
   content simply shows — it can never get stuck invisible. */

.reveal-line { display: block; overflow: hidden; }
.reveal-line > span { display: block; transform: none; }
.fade-up { opacity: 1; transform: none; }

html.reveal-on .reveal-line > span {
  transform: translateY(110%);
  transition: transform .9s var(--ease);
}
html.reveal-on .is-in .reveal-line > span { transform: translateY(0); }
html.reveal-on .is-in .reveal-line:nth-child(2) > span { transition-delay: .06s; }
html.reveal-on .is-in .reveal-line:nth-child(3) > span { transition-delay: .12s; }
html.reveal-on .is-in .reveal-line:nth-child(4) > span { transition-delay: .18s; }

html.reveal-on .fade-up {
  opacity: 0; transform: translateY(28px);
  transition: opacity .8s var(--ease), transform .8s var(--ease);
}
html.reveal-on .is-in.fade-up,
html.reveal-on .is-in .fade-up { opacity: 1; transform: none; }
html.reveal-on [data-stagger] .fade-up { transition-delay: calc(var(--i, 0) * .07s); }

/* image mask reveal */
html.reveal-on .mask-reveal .ph__fill { transform: scale(1.12); }
html.reveal-on .mask-reveal::before {
  content: ""; position: absolute; inset: 0; z-index: 3;
  background: var(--bg);
  transform: scaleY(1); transform-origin: bottom;
  transition: transform .9s var(--ease);
}
html.reveal-on .is-in.mask-reveal::before { transform: scaleY(0); }
html.reveal-on .is-in.mask-reveal .ph__fill { transform: scale(1); transition: transform 1.2s var(--ease); }
/* mesma revelação por máscara para imagens reais */
html.reveal-on .mask-reveal .ph img { transform: scale(1.12); }
html.reveal-on .is-in.mask-reveal .ph img { transform: scale(1); transition: transform 1.2s var(--ease); }
html.no-motion .mask-reveal .ph img { transform: none !important; }

/* ---------- Custom cursor — REMOVIDO (cursor nativo do sistema) ---------- */
.cursor-dot, .cursor-ring { display: none !important; }
.cursor-dot, .cursor-ring.__removed {
  position: fixed; top: 0; left: 0;
  pointer-events: none; z-index: 10000;
  border-radius: 50%;
  will-change: transform;
}
.cursor-dot {
  width: 7px; height: 7px; background: #fff;
  transform: translate(-50%, -50%);
}
.cursor-ring {
  width: 38px; height: 38px;
  border: 1px solid rgba(255,255,255,.7);
  transform: translate(-50%, -50%);
  transition: width .3s var(--ease), height .3s var(--ease), background .3s var(--ease), border-color .3s var(--ease);
}
.cursor-ring.is-hover { width: 64px; height: 64px; background: rgba(255,255,255,.08); }
.cursor-ring.is-label {
  width: 84px; height: 84px;
  background: var(--ember);
  border-color: var(--ember);
  mix-blend-mode: normal;
}
.cursor-ring .cursor-label {
  font-family: var(--mono); font-size: .58rem; letter-spacing: .12em;
  text-transform: uppercase; color: #fff;
  opacity: 0; transition: opacity .2s; white-space: nowrap;
  display: flex; align-items: center; justify-content: center;
  width: 100%; height: 100%;
}
.cursor-ring.is-label .cursor-label { opacity: 1; }
@media (hover: none) { .cursor-dot, .cursor-ring { display: none; } }

/* ---------- Marquee ---------- */
.marquee {
  display: flex;
  overflow: hidden;
  user-select: none;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.marquee__track {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  gap: clamp(28px, 4vw, 64px);
  padding-right: clamp(28px, 4vw, 64px);
  animation: marquee-scroll var(--speed, 38s) linear infinite;
}
.marquee:hover .marquee__track { animation-play-state: paused; }
@keyframes marquee-scroll { to { transform: translateX(-100%); } }
.marquee__item {
  font-family: var(--display);
  font-weight: 500;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  gap: clamp(28px, 4vw, 64px);
}
.marquee__dot { width: .42em; height: .42em; border-radius: 50%; background: var(--ember); flex: none; }

/* ---------- Accessibility ---------- */
.skip-link {
  position: absolute; left: 16px; top: -60px; z-index: 10001;
  background: var(--ink); color: var(--bone);
  padding: .7em 1.1em; border-radius: 8px;
  font-family: var(--mono); font-size: .72rem; letter-spacing: .1em; text-transform: uppercase;
  transition: top .25s var(--ease);
}
.skip-link:focus { top: 16px; }
:where(a, button, input, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 4px;
}

/* ---------- Frozen-timeline / no-motion fallback ----------
   If the animation timeline never advances (e.g. offscreen
   render), JS adds .no-motion so content is always visible. */
html.no-motion .reveal-line > span { transform: none !important; transition: none !important; }
html.no-motion .fade-up { opacity: 1 !important; transform: none !important; transition: none !important; }
html.no-motion .mask-reveal::before { display: none !important; }
html.no-motion .mask-reveal .ph__fill { transform: none !important; }
html.no-motion .menu-nav a { opacity: 1 !important; transform: none !important; transition: none !important; }
html.no-motion .menu-overlay.is-open { clip-path: inset(0 0 0 0) !important; transition: none !important; }

/* ---------- Motion toggle (Tweaks) ---------- */
html.motion-off .marquee__track { animation: none !important; }
html.motion-off .cursor-dot, html.motion-off .cursor-ring { display: none !important; }
html.motion-off * { cursor: auto !important; }

/* ---------- Reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .2s !important;
    scroll-behavior: auto !important;
  }
  .marquee__track { animation: none !important; }
  .reveal-line > span, .fade-up { transform: none !important; opacity: 1 !important; }
  .mask-reveal::before { display: none; }
  .cursor-dot, .cursor-ring { display: none !important; }
}
