/* FriendlyPhotons — Marketing site REDESIGN · sections part 1. A rebalanced, more editorial layout: alternating immersive photography, clean product moments, and data — all within the existing brand. */ const RD_ASSET = "assets/"; // ── Shared EMR spectrum scale ──────────────────────────────────────────────── const RD_SCALE = [ { n: 1, label: "Quiet", c: "var(--emr-1)" }, { n: 2, label: "Audible", c: "var(--emr-2)" }, { n: 3, label: "Noisy", c: "var(--emr-3)" }, { n: 4, label: "Loud", c: "var(--emr-4)" }, { n: 5, label: "Blaring", c: "var(--emr-5)" }, ]; // Rose Middle School rating — single source of truth for the rating Tweak. const RD_RATING = { quiet: { level: 1, label: "Quiet", elf: "0.21", rf: "0.04" }, audible: { level: 2, label: "Audible", elf: "0.95", rf: "0.38" }, noisy: { level: 3, label: "Noisy", elf: "3.40", rf: "2.10" }, loud: { level: 4, label: "Loud", elf: "6.80", rf: "7.50" }, blaring: { level: 5, label: "Blaring", elf: "10.87", rf: "14.342" }, }; function SpectrumBar({ labels = true, compact = false, marker = null }) { // marker = 1..5 → render a gauge mark centered over that segment const markerLeft = marker ? `${(marker - 0.5) * 20}%` : null; return (
{marker && (
)}
{RD_SCALE.map(s => (
{s.n}
))}
{labels && (
{RD_SCALE.map(s => {s.label})}
)}
); } // ── HERO ───────────────────────────────────────────────────────────────────── const HERO_PLACES = [ { name: "Crestline Home", type: "Home", icon: "home", level: 1, label: "Quiet", top: "21%", left: "26%", below: true }, { name: "Harbor Point Offices", type: "Office", icon: "building", level: 2, label: "Audible", top: "27%", left: "73%", below: true }, { name: "Rose Middle School", type: "School", icon: "school", level: 3, label: "Noisy", top: "75%", left: "50%", big: true, rest: true }, { name: "Large Cell Tower", type: "Cell Tower", icon: "tower", level: 5, label: "Blaring", top: "55%", left: "48%", source: true }, { name: "Northgate Apartments", type: "Apartments", icon: "building", level: 4, label: "Loud", top: "55%", left: "79%" }, { name: "Maple Hotel", type: "Hotel", icon: "bed", level: 5, label: "Blaring", top: "85%", left: "23%" }, ]; const HERO_SOURCES = [ { kind: "tower", top: "14%", left: "55%" }, { kind: "tower", top: "44%", left: "20%" }, { kind: "powerline", top: "74%", left: "76%" }, ]; function SourceGlyph({ kind }) { if (kind === "powerline") return ( ); if (kind === "smallcell") return ( ); return ( ); } function RHero({ onDownload, rating = "noisy" }) { const roseLevel = (RD_RATING[rating] || RD_RATING.noisy).level; const others = [1, 2, 3, 4, 5].filter(l => l !== roseLevel); const rotate = { "Crestline Home": others[0], "Harbor Point Offices": others[1], "Northgate Apartments": others[2], "Maple Hotel": others[3] }; const places = HERO_PLACES.map(p => { const lvl = p.name === "Rose Middle School" ? roseLevel : (rotate[p.name] != null ? rotate[p.name] : p.level); return { ...p, level: lvl, label: RD_SCALE[lvl - 1].label }; }); const restIdx = places.findIndex(p => p.rest); const [active, setActive] = React.useState(restIdx); React.useEffect(() => { const mq = window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)"); if (mq && mq.matches) { setActive(restIdx); return; } let i = restIdx; let interval; const start = setTimeout(() => { interval = setInterval(() => { i = (i + 1) % places.length; setActive(i); }, 3800); }, 1500); return () => { clearTimeout(start); clearInterval(interval); }; }, []); return (
A community map of electromagnetic readings

See the invisible energy in any space.

FriendlyPhotons makes electromagnetic radiation visible in your everyday spaces — homes, hotels, offices, schools, and everywhere in between.

See how it works
A neighborhood map of electromagnetic readings
{places.map((p, idx) => (
{p.type} {p.name} {p.level}{p.label}
{p.source ? : }
))}
You
{HERO_SOURCES.map((src, i) => (
))}
); } // ── STAKES — full-bleed immersive photography band ─────────────────────────── function RStakes() { return (

The air around you is alive with invisible energy.

Every building you enter, room you sleep in, and street you walk on has an electromagnetic environment. Some are quiet. Some aren't. Until now, there was no easy way to know the difference.

You can't see it, but it's everywhere.

); } // ── ANSWER — product spotlight; rating diagram tucked behind a right-column tray ─ function RAnswer({ rating = "noisy" }) { const R = RD_RATING[rating] || RD_RATING.noisy; const [open, setOpen] = React.useState(false); const [inview, setInview] = React.useState(false); const secRef = React.useRef(null); React.useEffect(() => { function onClick(e) { const a = e.target.closest && e.target.closest('a[href="#how"]'); if (a) { e.preventDefault(); setOpen(true); if (secRef.current) secRef.current.scrollIntoView({ behavior: "smooth", block: "start" }); } } document.addEventListener("click", onClick); if (typeof location !== "undefined" && location.hash === "#how") { setOpen(true); setTimeout(() => secRef.current && secRef.current.scrollIntoView({ behavior: "smooth" }), 300); } let io; if (secRef.current && "IntersectionObserver" in window) { io = new IntersectionObserver((es) => es.forEach((en) => { if (en.isIntersecting) setInview(true); }), { threshold: 0.3 }); io.observe(secRef.current); } else { setInview(true); } return () => { document.removeEventListener("click", onClick); if (io) io.disconnect(); }; }, []); return (
{"FriendlyPhotons
Rose Middle School
ELF {R.elf}mG Powerlines & electrical
RF {R.rf}mW/m² Cell towers & wireless
EMR rating {R.level}{R.label}
{RD_SCALE.map(s => (
{s.n}
))}
QuietBlaring

Two readings, distilled into one number.

FriendlyPhotons
makes it visible.

Contributors with EMF meters take readings everywhere they go — homes, parks, hotels, schools, offices. We distill what they find into a single rating, from 1 (Quiet) to 5 (Blaring), that anyone can read at a glance — one for every place on the map.

That rating blends the two kinds of energy in the air: Extremely Low Frequency (ELF), which radiates from powerlines and electrical wiring, and Radio Frequency (RF) from cell towers, Wi-Fi, and wireless devices. You don't need an EMF meter or a background in physics to make sense of it.

); } // ── WHO IT'S FOR + WHAT YOU DO (merged) ────────────────────────────────────── function RWho({ personas = "statements" }) { const usecases = [ { icon: "activity", who: "Citizen scientists", why: "concerned about the environment." }, { icon: "bulb", who: "The curious", why: "who want to make informed choices." }, { icon: "school", who: "Parents", why: "checking a new school." }, { icon: "home", who: "Renters", why: "touring an apartment." }, { icon: "bed", who: "Travelers", why: "vetting a hotel room." }, { icon: "building", who: "Remote workers", why: "picking a place to work." }, ]; return (

For anyone who cares about what's in the air around them.

Whether you're a citizen scientist concerned about the environment,
or a health-conscious traveler looking for a quiet night's sleep,
there's a place for you here.

{personas !== "none" && (
Built for
{usecases.map(u => (
{u.who} {u.why}
))}
)}
); } function RWhoCard({ img, imgPos, eyebrow, color, title, acts }) { return (
{eyebrow}
{eyebrow}

{title}

); } // ── Walkthrough modal — opens a clickable, step-through demo ────────────────── function WalkthroughModal({ role, onClose }) { const BASE_W = 440, BASE_H = 1056; const [scale, setScale] = React.useState(0.7); React.useEffect(() => { if (!role) return; const fit = () => { const availH = window.innerHeight - 96; const availW = Math.min(window.innerWidth - 56, 560); setScale(Math.min(1, availH / BASE_H, availW / BASE_W)); }; fit(); window.addEventListener("resize", fit); const onKey = (e) => { if (e.key === "Escape") onClose(); }; window.addEventListener("keydown", onKey); document.body.style.overflow = "hidden"; return () => { window.removeEventListener("resize", fit); window.removeEventListener("keydown", onKey); document.body.style.overflow = ""; }; }, [role]); if (!role) return null; const src = role === "contributor" ? "../app/contributor-story.html" : "../app/explorer-story.html"; return (
e.stopPropagation()}>
); } Object.assign(window, { RHero, RStakes, RAnswer, RWho, RWhoCard, WalkthroughModal, SpectrumBar });