/* global React */ // Brief-provided headline + subheadline pairs (exposed as a Tweak). const HEADLINES = [ { h: 'Precisão técnica em cada detalhe', sub: 'Apoio técnico a advogados e escritórios em disputas patrimoniais, judiciais, extrajudiciais ou arbitragem.' }, { h: 'Onde há dúvida, há método', sub: 'Análises técnicas que transformam questionamentos em evidências.' }, { h: 'A resposta está nos detalhes', sub: 'Perícias e avaliações conduzidas com rigor técnico e respaldo profissional.' }, { h: 'Evidências que falam por si', sub: 'Quando a decisão exige precisão, a análise técnica faz a diferença.' }, { h: 'Veja além do que é visível', sub: 'Identificamos causas, riscos e responsabilidades com metodologia e experiência.' }, ]; window.HEADLINES = HEADLINES; // Technical terms that drift behind the inspection lens. const TERMS = [ { x: 6, y: 9, s: 16, m: false, r: -4, t: 'Trincas estruturais' }, { x: 60, y: 6, s: 13, m: true, r: 0, t: 'NBR 14653' }, { x: 32, y: 19, s: 18, m: false, r: 2, t: 'Infiltrações' }, { x: 67, y: 22, s: 14, m: false, r: -3, t: 'Inspeção predial' }, { x: 5, y: 31, s: 13, m: true, r: 0, t: 'NBR 13752' }, { x: 38, y: 38, s: 20, m: false, r: 0, t: 'Vícios construtivos' }, { x: 74, y: 40, s: 14, m: false, r: 3, t: 'Laudo técnico' }, { x: 9, y: 50, s: 16, m: false, r: -2, t: 'Patologia das construções' }, { x: 56, y: 55, s: 14, m: false, r: 0, t: 'Perícia judicial' }, { x: 28, y: 63, s: 16, m: false, r: 2, t: 'Engenharia diagnóstica' }, { x: 71, y: 66, s: 13, m: false, r: -3, t: 'Parecer técnico' }, { x: 6, y: 74, s: 14, m: false, r: 0, t: 'Avaliação imobiliária' }, { x: 42, y: 81, s: 15, m: false, r: -2, t: 'Conformidade construtiva' }, { x: 67, y: 85, s: 14, m: false, r: 2, t: 'Assistência técnica' }, { x: 16, y: 91, s: 13, m: false, r: 0, t: 'Responsabilidade técnica' }, ]; function TermField({ sharp, navy, dim }) { const blurColor = navy ? 'var(--blue-300)' : 'var(--ink-400)'; const sharpColor = navy ? 'var(--cream-50)' : 'var(--blue-700)'; const cls = sharp ? 'term-layer term-layer-sharp' : ('term-layer term-layer-blur' + (dim ? ' term-layer-dim' : '')); return (
); } // Shared inspection-lens animation: drives clip-path + reticle position via rAF. function useInspectionLens({ hostRef, sharpRef, frameRef, circle, reticle, sweep, deps }) { React.useEffect(() => { const host = hostRef.current; if (!host) return; const reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches; const { RW, RH, R } = reticle; const halfW = circle ? R : RW / 2; const halfH = circle ? R : RH / 2; const s = { hover: false, mx: sweep.cx0, my: sweep.cy0, cx: sweep.cx0, cy: sweep.cy0 }; let raf; const start = performance.now(); function tick(now) { const w = host.clientWidth || 1; const h = host.clientHeight || 1; let tx, ty; if (s.hover) { tx = s.mx; ty = s.my; } else if (reduce) { tx = sweep.cx0; ty = sweep.cy0; } else { const e = now - start; tx = sweep.cx0 + sweep.ax * Math.sin(e * sweep.fx); ty = sweep.cy0 + sweep.ay * Math.sin(e * sweep.fy + 1.2); } const k = s.hover ? 0.20 : 0.045; s.cx += (tx - s.cx) * k; s.cy += (ty - s.cy) * k; const minx = halfW / w, maxx = 1 - halfW / w; const miny = halfH / h, maxy = 1 - halfH / h; const fx = Math.min(maxx, Math.max(minx, s.cx)); const fy = Math.min(maxy, Math.max(miny, s.cy)); const x = fx * w, y = fy * h; if (sharpRef.current) { sharpRef.current.style.clipPath = circle ? 'circle(' + R + 'px at ' + x + 'px ' + y + 'px)' : 'inset(' + (y - RH / 2) + 'px ' + (w - (x + RW / 2)) + 'px ' + (h - (y + RH / 2)) + 'px ' + (x - RW / 2) + 'px)'; } if (frameRef.current) { frameRef.current.style.left = (circle ? x - R : x - RW / 2) + 'px'; frameRef.current.style.top = (circle ? y - R : y - RH / 2) + 'px'; } raf = requestAnimationFrame(tick); } raf = requestAnimationFrame(tick); const onMove = (ev) => { const r = host.getBoundingClientRect(); s.mx = (ev.clientX - r.left) / r.width; s.my = (ev.clientY - r.top) / r.height; }; const onEnter = () => { s.hover = true; }; const onLeave = () => { s.hover = false; }; host.addEventListener('mousemove', onMove); host.addEventListener('mouseenter', onEnter); host.addEventListener('mouseleave', onLeave); return () => { cancelAnimationFrame(raf); host.removeEventListener('mousemove', onMove); host.removeEventListener('mouseenter', onEnter); host.removeEventListener('mouseleave', onLeave); }; }, deps); } function LensReticle({ innerRef, width, height, circle, markColor, initialLeft, initialTop }) { return ({msg.sub}
{msg.sub}