Site Builder
Editing:
index0.php
writable 0666
<!doctype html> <html lang="en" data-theme="light"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width,initial-scale=1" /> <title>TruthCase™ — The Case for Truth | RF SAFE</title> <meta name="description" content="A first‑principles phone case that teaches real RF risk reduction—design, usage, policy, and procedure. Choose your phone and get two clean options: Buy on Amazon or Buy Now. Models load from truthcases.json." /> <meta name="color-scheme" content="light dark" /> <style> /* ========================= THEME TOKENS (2025) ========================= */ :root{ --bg:#0b0b0c; --ink:#f6f6f7; --muted:#cfcfd4; --card:#121317; --border:#24262c; --shadow:0 18px 42px rgba(0,0,0,.45); --brand:#0ea5e9; --brand-ink:#e0f2fe; /* cyan/sky accent (high trust) */ --cta:#f59e0b; --cta-ink:#1a1309; /* warm orange for action */ --ok:#10b981; --warn:#f97316; --ring:rgba(14,165,233,.35); --soft:rgba(14,165,233,.10); --soft2:rgba(245,158,11,.10); --radius:20px; --font: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, "Apple Color Emoji","Segoe UI Emoji"; } /* Conversion‑friendly light theme (default) */ html[data-theme="light"]{ --bg:#f7f7fb; --ink:#0f1115; --muted:#5c6270; --card:#ffffff; --border:#e7e8ee; --shadow:0 18px 42px rgba(16,24,40,.08); --brand:#0ea5e9; --brand-ink:#075985; --cta:#f59e0b; --cta-ink:#1a1309; --soft:rgba(14,165,233,.08); --soft2:rgba(245,158,11,.10); } /* Low‑blue Amber Dark (accessibility + night) */ html[data-theme="amber"]{ --bg:linear-gradient(180deg,#0e0b06 0%, #171208 100%); --ink:#ffe8c8; --muted:#d7c9ad; --card:#151109; --border:#372b1a; --shadow:0 14px 36px rgba(0,0,0,.45); --brand:#ffb020; --brand-ink:#ffe1a6; --cta:#ffb020; --cta-ink:#1a1309; --ring:rgba(255,176,32,.35); --soft:rgba(255,176,32,.10); --soft2:rgba(255,176,32,.08); } /* Base */ *{box-sizing:border-box} html,body{margin:0;background:var(--bg);color:var(--ink);font:16px/1.7 var(--font);letter-spacing:.2px} a{color:var(--brand);text-decoration:none} a:hover{text-decoration:underline} .wrap{max-width:1200px;margin:0 auto;padding:28px 18px 120px} /* Nav */ .nav{position:sticky;top:0;z-index:50;backdrop-filter:saturate(1.1) blur(8px); background:color-mix(in oklab, var(--bg) 70%, transparent);border-bottom:1px solid var(--border)} .navin{max-width:1200px;margin:0 auto;display:flex;gap:12px;align-items:center;justify-content:space-between;padding:10px 18px} .brand{display:flex;gap:10px;align-items:center;font-weight:900;color:var(--brand-ink)} .dot{width:10px;height:10px;border-radius:50%;background:var(--brand);box-shadow:0 0 18px var(--ring)} .row{display:flex;gap:8px;align-items:center;flex-wrap:wrap} /* Buttons */ .btn{display:inline-flex;align-items:center;gap:10px;border-radius:999px;padding:11px 16px;font-weight:900;border:2px solid var(--brand); background:transparent;color:var(--brand);box-shadow:0 8px 20px var(--ring);transition:.2s;cursor:pointer} .btn:hover{transform:translateY(-1px)} .btn.primary{background:var(--cta);border-color:var(--cta);color:var(--cta-ink)} .btn.ghost{border-color:var(--border);color:var(--brand)} .btn.small{padding:8px 12px;font-size:.92rem} .kbd{border:1px solid var(--border);border-radius:6px;padding:0 6px;background:color-mix(in oklab, var(--card) 85%, transparent)} /* Theme toggle */ .theme{display:flex;gap:6px;border:1px solid var(--border);border-radius:999px;padding:4px;background:color-mix(in oklab, var(--card) 80%, transparent)} .theme button{border:0;background:transparent;color:var(--muted);padding:6px 10px;border-radius:999px;cursor:pointer} .theme button[aria-pressed="true"]{background:var(--soft);color:var(--brand);font-weight:800} /* Hero */ .hero{ margin-top:18px;background: radial-gradient(800px 300px at 10% -20%, var(--soft), transparent 60%), radial-gradient(800px 300px at 90% -40%, var(--soft2), transparent 60%), var(--card); border-radius:24px;box-shadow:var(--shadow);padding:28px } .eyebrow{display:inline-flex;align-items:center;gap:8px;font-weight:900;letter-spacing:.08em;text-transform:uppercase;color:var(--brand); border:1px solid var(--border);background:color-mix(in oklab, var(--card) 90%, transparent);border-radius:999px;padding:6px 12px} h1{margin:10px 0 8px;font-size:clamp(28px,4.6vw,56px);line-height:1.06} .subtitle{color:var(--muted);max-width:980px} .badges{display:flex;flex-wrap:wrap;gap:10px;margin-top:12px} .badge{font-size:12px;font-weight:900;border:1px solid var(--border);background:color-mix(in oklab, var(--card) 90%, transparent);color:var(--brand); border-radius:999px;padding:6px 10px} .cta-row{display:flex;gap:12px;flex-wrap:wrap;margin-top:16px} /* Trust bar */ .trust{display:flex;gap:14px;flex-wrap:wrap;margin-top:14px} .trust .pill{display:flex;gap:8px;align-items:center;border:1px solid var(--border);background:color-mix(in oklab, var(--card) 90%, transparent); padding:8px 12px;border-radius:999px;color:var(--muted);font-weight:700} .trust svg{width:18px;height:18px} /* Sections */ .section{margin-top:44px} .card{background:var(--card);border-radius:var(--radius);box-shadow:var(--shadow);padding:22px;border:1px solid var(--border)} .grid{display:grid;gap:18px} @media(min-width:980px){.cols-2{grid-template-columns:1fr 1fr}.cols-3{grid-template-columns:1fr 1fr 1fr}} .lead{font-size:1.05rem;color:color-mix(in oklab, var(--ink) 80%, var(--muted))} .slogan{border-left:4px solid var(--brand);padding-left:12px;margin:6px 0;font-weight:900;color:var(--ink)} .callout{background:color-mix(in oklab, var(--card) 92%, transparent);border:1px solid var(--border);border-radius:16px;padding:14px} /* Details (accordion) */ details{border:1px solid var(--border);border-radius:14px;background:color-mix(in oklab, var(--card) 94%, transparent);padding:10px} summary{cursor:pointer;font-weight:900} summary::-webkit-details-marker{display:none} details[open]{background:color-mix(in oklab, var(--card) 88%, transparent)} /* Table */ .table{overflow:auto;border-radius:14px;border:1px solid var(--border)} table{width:100%;border-collapse:separate;border-spacing:0;min-width:820px} th,td{padding:12px 14px;border-bottom:1px solid var(--border);text-align:left;vertical-align:top} thead th{background:color-mix(in oklab, var(--card) 90%, transparent);font-size:14px;color:var(--brand)} /* Modal (high-contrast) */ .modal-backdrop{position:fixed;inset:0;z-index:100; background:radial-gradient(900px 420px at 50% 10%, color-mix(in oklab, var(--brand) 20%, transparent), rgba(0,0,0,.78) 58%), rgba(0,0,0,.55); display:none;opacity:0;pointer-events:none;transition:opacity .25s ease} .modal{position:fixed;inset:0;z-index:101;display:none;place-items:center;pointer-events:none;opacity:0;transition:opacity .25s ease} .modal-panel{ width:min(720px,94vw);background:var(--card);border-radius:20px;border:1px solid color-mix(in oklab, var(--brand) 35%, var(--border)); box-shadow:0 22px 60px rgba(0,0,0,.35), 0 0 0 6px color-mix(in oklab, var(--brand) 12%, transparent); padding:18px;pointer-events:auto;transform:translateY(6px) scale(.985);transition:transform .25s ease} .modal-head{display:flex;justify-content:space-between;align-items:center;gap:10px;margin-bottom:8px} .modal-title{font-weight:900;margin:0} .close{appearance:none;border:1px solid var(--border);background:color-mix(in oklab, var(--card) 85%, transparent);color:var(--brand); border-radius:999px;padding:8px 12px;font-weight:900;cursor:pointer} .form-row{display:grid;gap:14px;margin-top:12px} @media(min-width:700px){.form-row{grid-template-columns:1fr 1fr}} label{font-weight:800} select{width:100%;padding:12px;border:1px solid var(--border);border-radius:12px;background:color-mix(in oklab, var(--card) 80%, transparent); color:var(--ink);font-size:16px;box-shadow:0 8px 20px rgba(0,0,0,.08) inset} select:focus-visible{outline:2px solid color-mix(in oklab, var(--brand) 55%, transparent)} .modal-actions{display:flex;flex-wrap:wrap;gap:10px;margin-top:18px} .helper{font-size:.9rem;color:var(--muted)} .is-hidden{display:none !important} /* Open state toggles */ body.modal-open .modal-backdrop{display:block;opacity:1;pointer-events:auto} body.modal-open .modal{display:grid;opacity:1;pointer-events:auto} body.modal-open .modal-panel{transform:translateY(0) scale(1)} body.modal-open .wrap, body.modal-open .nav{filter:blur(1.2px) saturate(.9);opacity:.9;transform:scale(.998);transition:.2s} /* Mobile bottom-sheet */ @media (max-width:560px){ .modal{align-items:end} .modal-panel{width:100vw;max-height:85vh;overflow:auto;border-radius:16px 16px 0 0;padding:16px 16px 20px} .modal-panel::after{content:"";display:block;width:44px;height:4px;border-radius:999px; background:color-mix(in oklab, var(--ink) 40%, transparent);opacity:.5;margin:4px auto 8px} .modal-actions{position:sticky;bottom:-16px;background:linear-gradient(180deg, transparent 0%, color-mix(in oklab, var(--card) 96%, transparent) 42%); padding-top:10px;padding-bottom:4px} } /* Reveal-on-scroll */ .reveal{opacity:0;transform:translateY(12px);transition:all .5s ease} .reveal.in{opacity:1;transform:none} /* Sticky mobile CTA */ .mobile-cta{position:fixed;left:0;right:0;bottom:10px;z-index:30;display:none;justify-content:center} @media (max-width:760px){ .mobile-cta{display:flex} } .mobile-cta .btn{box-shadow:0 18px 32px color-mix(in oklab, var(--cta) 30%, transparent)} /* Accessibility helpers */ .sr-only{position:absolute !important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0} /* Reduce motion */ @media (prefers-reduced-motion:reduce){ .modal-backdrop,.modal,.modal-panel,body.modal-open .wrap,body.modal-open .nav{transition:none !important} } </style> </head> <body> <!-- NAV --> <div class="nav" role="navigation" aria-label="Primary"> <div class="navin"> <div class="brand"><span class="dot"></span><span>RF SAFE • TruthCase™</span></div> <div class="row"> <a class="btn ghost" href="#truths">The Four Truths</a> <a class="btn ghost" href="#how">How to Use</a> <a class="btn ghost" href="#policy">Policy Roadmap</a> <!-- Theme toggle --> <div class="theme" role="group" aria-label="Theme"> <button id="tLight" aria-pressed="true" title="Light theme">Light</button> <button id="tAmber" aria-pressed="false" title="Amber dark (low blue)">Amber</button> </div> <button class="btn primary" id="openModalBtn" type="button">Select Your Phone</button> </div> </div> </div> <div class="wrap"> <!-- HERO --> <header class="hero reveal"> <span class="eyebrow">RF SAFE • Since the 1990s</span> <h1>TruthCase™ — the case that tells the truth</h1> <p class="subtitle"> RF SAFE pioneered exposure‑reduction cases in the <strong>1990s</strong>. TruthCase™ stays honest: a first‑principles design to reduce everyday microwave exposure, plus the roadmap to safer defaults (<em>design • usage • policy • procedure</em>). </p> <div class="badges" role="list"> <span class="badge" role="listitem">Shield between you & phone</span> <span class="badge" role="listitem">No metal loops • No magnets</span> <span class="badge" role="listitem">Antenna‑aware & ultra‑thin</span> <span class="badge" role="listitem">Ohmmeter‑checkable shield</span> </div> <!-- Trust bar --> <div class="trust" aria-label="Key assurances"> <span class="pill"> <!-- shield --> <svg viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="M12 3l7 3v5c0 5-3.5 9-7 10-3.5-1-7-5-7-10V6l7-3z" stroke="currentColor" stroke-width="1.5"/></svg> First‑principles design </span> <span class="pill"> <!-- check --> <svg viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="M5 12l4 4 10-10" stroke="currentColor" stroke-width="1.7"/></svg> Honest usage guidance </span> <span class="pill"> <!-- roadmap --> <svg viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="M4 19l6-6-2-2 4-4 8 8" stroke="currentColor" stroke-width="1.6"/></svg> Roadmap beyond products </span> </div> <div class="cta-row"> <button class="btn primary" id="openModalBtn2" type="button">Select Your Phone</button> <a class="btn" href="#truths">Why TruthCase™ is different</a> </div> </header> <!-- DIFFERENT ON PURPOSE --> <section class="section card reveal"> <h2 style="margin:0 0 8px">Different on purpose</h2> <p class="lead">Most “anti‑radiation” cases are built around convenience hardware and marketing numbers. TruthCase™ is built around physics and behavior.</p> <div class="grid cols-3"> <div class="card"> <h3 style="margin:.2rem 0 6px">Design</h3> <p>Directional shielding when it matters (between you & phone). No metal loops, magnets, or plate steel. Continuity near the ear.</p> </div> <div class="card"> <h3 style="margin:.2rem 0 6px">Usage</h3> <p>Habits that move the needle: call posture, pocket orientation, night distance, and turning off idle radios.</p> </div> <div class="card"> <h3 style="margin:.2rem 0 6px">Roadmap</h3> <p>From better cases now to <strong>light‑based networking</strong> and modernized policy—so indoor connectivity relies more on light and less on microwaves.</p> </div> </div> </section> <!-- FOUR TRUTHS --> <section id="truths" class="section card reveal"> <h2 style="margin:0 0 6px">The Four Truths the market ignores</h2> <details open> <summary>Truth #1 — Unshielded ear‑side holes break protection where you need it most</summary> <p>Large speaker apertures on the ear side create a direct path for higher‑frequency signals and defeat continuity exactly where you rely on protection during calls. TruthCase™ keeps a shielded ear‑side path by design.</p> </details> <details> <summary>Truth #2 — Detachable magnets & steel plates can provoke higher transmit power</summary> <p>Magnets and plate steel behind the phone obstruct or detune antennas. Modern handsets compensate by boosting transmit power to keep the link. Result: more exposure, not less. TruthCase™ excludes magnetic detachables and plate steel.</p> </details> <details> <summary>Truth #3 — Metal loops and decorative hardware near antennas can detune the system</summary> <p>Conductive hardware close to radiators alters near‑field behavior and can degrade antenna efficiency. Phones react with higher output. TruthCase™ has <strong>no metal loops</strong> and stays thin where radios live.</p> </details> <details> <summary>Truth #4 — “99% protection” fabric numbers ≠ everyday exposure</summary> <p>A swatch test isn’t your life. Real‑world reduction depends on <em>where</em> the shield sits, <em>how</em> antennas perform, and <em>how long</em> radios are active. We focus on device behavior and user practice—no “99% everywhere.”</p> </details> <div class="card" style="margin-top:12px"> <h3 style="margin:0 0 6px">Ten short truths</h3> <p class="slogan">Shield the person, not the phone.</p> <p class="slogan">Placement beats percentage.</p> <p class="slogan">Thin near antennas. Always.</p> <p class="slogan">No magnets, no loops, no plate steel.</p> <p class="slogan">Continuity at the ear matters.</p> <p class="slogan">Duty cycle is exposure—turn off idle radios.</p> <p class="slogan">Distance at night is free protection.</p> <p class="slogan">Honest design beats “99% everywhere.”</p> <p class="slogan">Personal mitigation now, public defaults next.</p> <p class="slogan">Light indoors, fewer microwaves—future‑ready.</p> </div> </section> <!-- TRUTH STANDARD --> <section class="section card reveal"> <h2 style="margin:0 0 6px">The Truth Standard™</h2> <div class="table"> <table> <thead><tr><th>Principle</th><th>Meaning</th><th>TruthCase™ Position</th></tr></thead> <tbody> <tr> <td><strong>Shield the person, not the phone</strong></td> <td>Place the shield <em>between</em> you & the source during calls and pocket carry.</td> <td>Front cover toward head/body; directional use is the point.</td> </tr> <tr> <td><strong>Keep antennas efficient</strong></td> <td>Avoid obstructing/detuning radiators (which triggers power boosts).</td> <td><strong>No metal loops, no magnets, no plate steel</strong>; thin near antenna zones.</td> </tr> <tr> <td><strong>Continuity at the ear</strong></td> <td>Don’t break the shield path with a large ear‑aligned aperture.</td> <td>Shielded ear‑side path; continuity in call posture.</td> </tr> <tr> <td><strong>Field behavior > fabric %</strong></td> <td>Measure outcomes in real use, not swatch percentages.</td> <td>No “99% everywhere” claims; we teach correct use.</td> </tr> <tr> <td><strong>Verifiable materials</strong></td> <td>Let people confirm a conductive shield path.</td> <td>Ohmmeter‑checkable access in the front cover.</td> </tr> </tbody> </table> </div> </section> <!-- HOW TO USE --> <section id="how" class="section grid cols-2 reveal"> <div class="card"> <h3 style="margin:0 0 6px">How to use TruthCase™ (habits that help)</h3> <ul> <li><strong>Calls:</strong> answer/start, then close the cover <em>toward your head</em>; use speaker or wired for long calls.</li> <li><strong>Pocket:</strong> shielded cover toward your body (back pocket often best).</li> <li><strong>Night:</strong> increase distance or airplane mode; don’t park the phone near your head.</li> <li><strong>Duty cycle:</strong> turn off transmitters you don’t need (Wi‑Fi, Bluetooth, hotspot).</li> </ul> <p class="lead">Protection = design + practice. The case enables the practice to work.</p> </div> <div class="card"> <h3 style="margin:0 0 6px">Why thin matters</h3> <p>Over‑thick “armor” near antenna zones degrades efficiency and can make the phone transmit harder. TruthCase™ stays deliberately slim and antenna‑aware so the phone can do the same job with less output.</p> <p class="slogan">Not anti‑radiation. <strong>Pro‑truth.</strong></p> </div> </section> <!-- POLICY ROADMAP --> <section id="policy" class="section card reveal"> <h2 style="margin:0 0 6px">From personal mitigation to public defaults</h2> <p class="lead">Reducing exposure at scale requires policy and standards—not just products.</p> <div class="grid cols-3"> <div class="card"> <h3 style="margin:.2rem 0 6px">1) Update siting law</h3> <p><strong>Section 704 (1996)</strong> limits local health‑based arguments on RF emissions for compliant facilities. Communities need a modern framework that allows health to be weighed alongside coverage and aesthetics.</p> <p><a href="#refs">See references</a></p> </div> <div class="card"> <h3 style="margin:.2rem 0 6px">2) Finish the science</h3> <p>Maintain and fund federal RF research and performance standards (e.g., under the 1968 radiation control law) to keep guidance current with today’s signals and duty cycles.</p> <p><a href="#refs">See references</a></p> </div> <div class="card"> <h3 style="margin:.2rem 0 6px">3) Promote light indoors</h3> <p>Adopt <strong>light‑based networking</strong> (Li‑Fi) where feasible. The <strong>IEEE 802.11bb</strong> standard makes optical networking a first‑class citizen alongside Wi‑Fi. Indoors, light stays in the room—performance with privacy.</p> <p><a href="#refs">See references</a></p> </div> </div> <div class="callout" style="margin-top:10px"> <strong>The TruthCase™ is a bridge:</strong> reduce exposure now—and help advocate for healthier defaults (schools, bedrooms, offices) where the goal is less routine microwave traffic and more light‑based links. </div> </section> <!-- FAQ --> <section class="section card reveal"> <h2 style="margin:0 0 6px">Quick answers</h2> <div class="grid cols-2"> <div class="card"> <h3>Does it “block 99%”?</h3> <p>No slogans. Real‑world reduction depends on placement, antenna performance, and duty cycle. We teach the practice that lowers exposure; we don’t promise swatch numbers.</p> </div> <div class="card"> <h3>Is thicker better?</h3> <p>Not near antennas. Over‑thick materials can degrade efficiency and provoke higher transmit power. Thin + correct placement wins.</p> </div> </div> </section> <!-- REFERENCES --> <section id="refs" class="section card reveal"> <h2 style="margin:0 0 6px">References & Further Reading</h2> <ol> <li>FTC consumer guidance noting that some “shields” can interfere with signal and cause phones to draw more power (which can increase emissions). <br><a href="https://consumer.ftc.gov/articles/cell-phone-radiation-scams" target="_blank" rel="noopener">consumer.ftc.gov/articles/cell-phone-radiation-scams</a> </li> <li>Telecommunications Act of 1996, 47 U.S.C. §332(c)(7) (often cited as “Section 704”). <br><a href="https://www.law.cornell.edu/uscode/text/47/332" target="_blank" rel="noopener">law.cornell.edu/uscode/text/47/332</a> </li> <li>Environmental Health Trust v. FCC (D.C. Cir. 2021) — court remand requiring a reasoned explanation on non‑cancer harms and modern usage patterns before reaffirming 1996 limits. <br><a href="https://law.justia.com/cases/federal/appellate-courts/cadc/20-1025/20-1025-2021-08-13.html" target="_blank" rel="noopener">law.justia.com/.../20-1025-2021-08-13.html</a> </li> <li>U.S. National Toxicology Program (cell phone RFR studies) — program pages and fact sheets. <br><a href="https://ntp.niehs.nih.gov/whatwestudy/topics/cellphones/index.html" target="_blank" rel="noopener">ntp.niehs.nih.gov/.../cellphones</a> </li> <li>IEEE 802.11bb — optical (Li‑Fi) standard in the 802.11 family (2023). <br><a href="https://standards.ieee.org/ieee/802.11bb/11055/" target="_blank" rel="noopener">standards.ieee.org/ieee/802.11bb/11055/</a> </li> </ol> <p class="muted">Educational content only. Not medical, legal, or engineering advice.</p> </section> <!-- CTA --> <section class="section card reveal" style="text-align:center"> <h2 style="margin:0 0 6px">The only case for your phone should be a TruthCase™</h2> <p style="max-width:840px;margin:0 auto"> A case should <strong>reduce exposure in real use</strong>—without forcing your phone to work harder and without promising “99% everywhere.” TruthCase™ is built for <strong>physics</strong>, for <strong>people</strong>, and for a <strong>future</strong> where indoor connectivity relies more on light and less on microwaves. </p> <div class="cta-row" style="justify-content:center"> <button class="btn primary" id="openModalBtn3" type="button">Select Your Phone</button> </div> </section> <footer style="text-align:center;color:var(--muted);font-size:14px"> <p><strong>RF SAFE</strong> introduced exposure‑reduction cases in the 1990s and continues to set a first‑principles standard: no metal loops, no magnets or plate steel, a shielded ear‑side aperture, antenna‑aware thin design, and ohmmeter‑verified shielding—paired with honest usage guidance.</p> <p>© RF SAFE — This page focuses on reducing RF (microwave) exposure in everyday device use.</p> </footer> </div> <!-- Sticky Mobile CTA --> <div class="mobile-cta" aria-hidden="false"> <button class="btn primary" id="openModalBtn4" type="button" aria-label="Select your phone (quick access)">Select Your Phone</button> </div> <!-- MODAL: Manufacturer → Model (chained) → Buy buttons --> <div class="modal-backdrop" id="backdrop" aria-hidden="true"></div> <div class="modal" id="modal" aria-hidden="true"> <div class="modal-panel" role="dialog" aria-modal="true" aria-labelledby="modalTitle"> <div class="modal-head"> <h3 id="modalTitle" class="modal-title">Select Your Phone</h3> <button class="close" id="closeModalBtn" type="button" aria-label="Close">✕</button> </div> <p id="announce" class="sr-only" aria-live="polite"></p> <div class="form-row" id="manuRow" style="display:none"> <div> <label for="manuSelect">Manufacturer</label> <select id="manuSelect" aria-describedby="manuHelp"></select> <div id="manuHelp" class="helper">Choose a brand to filter models.</div> </div> <div id="modelCol" class="is-hidden"> <label for="modelSelect">Model</label> <select id="modelSelect" aria-describedby="modelHelp" disabled></select> <div id="modelHelp" class="helper">Pick your specific phone model.</div> </div> </div> <div class="form-row" id="modelOnlyRow" style="display:none"> <div style="grid-column:1/-1"> <label for="modelSelectSolo">Model</label> <select id="modelSelectSolo" aria-describedby="modelOnlyHelp"></select> <div id="modelOnlyHelp" class="helper">Models loaded from <code>truthcases.json</code>.</div> </div> </div> <div class="modal-actions" id="buyButtons" style="display:none"> <a class="btn" id="buyAmazonBtn" href="#" target="_blank" rel="noopener">Buy on Amazon</a> <a class="btn primary" id="buyDirectBtn" href="#" target="_blank" rel="noopener">Buy Now</a> </div> </div> </div> <script> /* ---------- Utilities ---------- */ const $ = s => document.querySelector(s); const $$ = s => Array.from(document.querySelectorAll(s)); const norm = s => (s||'').toString().toLowerCase().replace(/\s+/g,' ').trim(); function unique(arr){ return [...new Set(arr)]; } function getQS(name){ try{ return new URL(location.href).searchParams.get(name); }catch{return null;} } function appendParam(urlStr, key, val){ if(!val) return urlStr; try{ const u=new URL(urlStr,location.href); u.searchParams.set(key,val); return u.toString(); } catch{ const sep=urlStr.includes('?')?'&':'?'; return urlStr+sep+encodeURIComponent(key)+'='+encodeURIComponent(val); } } /* ---------- Theme toggle (persist) ---------- */ const tLight = $('#tLight'); const tAmber = $('#tAmber'); function setTheme(mode){ document.documentElement.setAttribute('data-theme', mode); localStorage.setItem('truth_theme', mode); tLight.setAttribute('aria-pressed', String(mode==='light')); tAmber.setAttribute('aria-pressed', String(mode==='amber')); } (function initTheme(){ const saved = localStorage.getItem('truth_theme'); setTheme(saved || 'light'); })(); tLight.addEventListener('click', ()=>setTheme('light')); tAmber.addEventListener('click', ()=>setTheme('amber')); /* ---------- State ---------- */ let DATA = { settings:{}, products:[] }; let manufacturers = []; let selectedManufacturer = ''; let filteredProducts = []; let affiliateRef = ''; let amazonTag = ''; /* ---------- DOM refs ---------- */ const openModalBtns = ['#openModalBtn','#openModalBtn2','#openModalBtn3','#openModalBtn4'].map(sel=>$(sel)).filter(Boolean); const backdrop = $('#backdrop'); const modal = $('#modal'); const closeModalBtn = $('#closeModalBtn'); const manuRow = $('#manuRow'); const manuSelect = $('#manuSelect'); const modelCol = $('#modelCol'); const modelOnlyRow = $('#modelOnlyRow'); const modelSelect = $('#modelSelect'); const modelSelectSolo = $('#modelSelectSolo'); const buyButtons = $('#buyButtons'); const buyDirectBtn = $('#buyDirectBtn'); const buyAmazonBtn = $('#buyAmazonBtn'); const announceEl = $('#announce'); /* ---------- Modal open/close ---------- */ const focusable = `a[href],button:not([disabled]),select:not([disabled]),input:not([disabled]),[tabindex]:not([tabindex="-1"])`; let lastFocused = null; function trapFocus(e){ if(e.key !== 'Tab') return; const items = Array.from(modal.querySelectorAll(focusable)).filter(el=>el.offsetParent!==null); if(!items.length) return; const first = items[0], last = items[items.length - 1]; if(e.shiftKey && document.activeElement===first){ last.focus(); e.preventDefault(); } else if(!e.shiftKey && document.activeElement===last){ first.focus(); e.preventDefault(); } } function openModal(){ lastFocused = document.activeElement; document.body.classList.add('modal-open'); document.body.style.overflow='hidden'; backdrop.style.display='block'; modal.style.display='grid'; requestAnimationFrame(()=>{ backdrop.style.opacity='1'; modal.style.opacity='1'; }); modal.setAttribute('aria-hidden','false'); setTimeout(()=>{ (manuRow.style.display!=='none' ? manuSelect : modelSelectSolo).focus(); },30); document.addEventListener('keydown', trapFocus); } function closeModal(){ document.removeEventListener('keydown', trapFocus); document.body.classList.remove('modal-open'); document.body.style.overflow=''; backdrop.style.opacity='0'; modal.style.opacity='0'; modal.setAttribute('aria-hidden','true'); setTimeout(()=>{ backdrop.style.display='none'; modal.style.display='none'; }, 200); if(lastFocused && lastFocused.focus) lastFocused.focus(); } backdrop.addEventListener('click', closeModal); closeModalBtn.addEventListener('click', closeModal); openModalBtns.forEach(b=>b && b.addEventListener('click', openModal)); document.addEventListener('keydown', e=>{ if(e.key==='Escape' && modal.getAttribute('aria-hidden')==='false') closeModal(); }); /* ---------- Load data ---------- */ async function loadData(){ try{ const r = await fetch('truthcases.json',{cache:'no-store'}); if(!r.ok) throw new Error('HTTP '+r.status); const j = await r.json(); DATA = Object.assign({settings:{}, products:[]}, j||{}); if(!Array.isArray(DATA.products) || !DATA.products.length) throw new Error('No products in truthcases.json'); }catch(e){ console.warn('truthcases.json missing/invalid. Using demo.', e); DATA = { settings:{ defaultAffiliateParam:'ref', defaultAmazonTagParam:'tag' }, products:[ { manufacturer:'Apple', title:'TruthCase™ for iPhone 15 Pro Max (Black)', sku:'QC-IP15PM-BLK', asin:'B0DEMO1234', price:69.99, salePrice:59.99, buyUrl:'https://www.rfsafe.com/product/truthcase-iphone-15-pro-max/', affiliateId:'RFS_DEFAULT', amazonTag:'rfsafe-20' }, { manufacturer:'Samsung', title:'TruthCase™ for Galaxy S24 Ultra (Black)', sku:'QC-S24U-BLK', asin:'', price:69.99, salePrice:59.99, buyUrl:'https://www.rfsafe.com/product/truthcase-s24-ultra/', affiliateId:'RFS_DEFAULT', amazonTag:'' } ] }; } } /* ---------- Build selects ---------- */ function buildManufacturers(){ manufacturers = unique((DATA.products||[]).map(p => (p.manufacturer||'').trim()).filter(Boolean)); } function renderManufacturerSelect(){ manuSelect.innerHTML=''; const ph = document.createElement('option'); ph.value=''; ph.textContent='Choose manufacturer…'; manuSelect.appendChild(ph); manufacturers.forEach(m=>{ const o=document.createElement('option'); o.value=m; o.textContent=m; manuSelect.appendChild(o); }); manuSelect.value = selectedManufacturer || ''; } function renderModelSelect(list, el){ el.innerHTML=''; const ph = document.createElement('option'); ph.value=''; ph.textContent='Choose model…'; el.appendChild(ph); list.forEach((p,i)=>{ const o=document.createElement('option'); o.value=String(i); o.textContent=p.title || `Model ${i+1}`; el.appendChild(o); }); el.value=''; } /* ---------- Links ---------- */ function currentAffiliateRef(p){ return (affiliateRef || p.affiliateId || '').trim(); } function currentAmazonTag(p){ return (amazonTag || p.amazonTag || '').trim(); } function buildDirectUrl(p){ const base=(p.buyUrl||'').trim(); if(!base) return ''; const key=(DATA.settings && DATA.settings.defaultAffiliateParam) || 'ref'; return appendParam(base, key, currentAffiliateRef(p) || ''); } function buildAmazonUrl(p){ const asin=(p.asin||'').trim(); if(!asin) return ''; const key=(DATA.settings && DATA.settings.defaultAmazonTagParam) || 'tag'; const tag=currentAmazonTag(p); const base=`https://www.amazon.com/dp/${encodeURIComponent(asin)}`; return tag ? appendParam(base, key, tag) : base; } /* ---------- Select handlers ---------- */ const announce = msg => { const el=$('#announce'); if(el) el.textContent=msg||''; }; manuSelect.addEventListener('change', ()=>{ selectedManufacturer = manuSelect.value; filteredProducts = selectedManufacturer ? DATA.products.filter(p => (p.manufacturer||'').trim()===selectedManufacturer) : DATA.products.slice(); if(selectedManufacturer){ modelCol.classList.remove('is-hidden'); modelSelect.disabled=false; renderModelSelect(filteredProducts, modelSelect); announce(`Manufacturer ${selectedManufacturer} selected. Choose a model.`); }else{ modelCol.classList.add('is-hidden'); modelSelect.disabled=true; modelSelect.innerHTML=''; announce(`Manufacturer cleared. Please select a manufacturer.`); } buyButtons.style.display='none'; }); modelSelect.addEventListener('change', ()=>{ const idx=parseInt(modelSelect.value,10); if(Number.isFinite(idx) && idx>=0){ const p=filteredProducts[idx]; const dir=buildDirectUrl(p); const amz=buildAmazonUrl(p); if(amz){ buyAmazonBtn.href=amz; buyAmazonBtn.style.display='inline-flex'; } else { buyAmazonBtn.style.display='none'; } if(dir){ buyDirectBtn.href=dir; buyDirectBtn.style.display='inline-flex'; } else { buyDirectBtn.style.display='none'; } buyButtons.style.display=(amz||dir)?'flex':'none'; announce(`Model ${p.title} selected.`); }else{ buyButtons.style.display='none'; } }); modelSelectSolo.addEventListener('change', ()=>{ const idx=parseInt(modelSelectSolo.value,10); if(Number.isFinite(idx) && idx>=0){ const p=DATA.products[idx]; const dir=buildDirectUrl(p); const amz=buildAmazonUrl(p); if(amz){ buyAmazonBtn.href=amz; buyAmazonBtn.style.display='inline-flex'; } else { buyAmazonBtn.style.display='none'; } if(dir){ buyDirectBtn.href=dir; buyDirectBtn.style.display='inline-flex'; } else { buyDirectBtn.style.display='none'; } buyButtons.style.display=(amz||dir)?'flex':'none'; announce(`Model ${p.title} selected.`); }else{ buyButtons.style.display='none'; } }); /* ---------- Deep link ---------- */ function pickFromDeepLink(){ const qSku = getQS('sku'); const qAsin = getQS('asin'); const qManu = getQS('manu') || getQS('manufacturer'); const qModel= getQS('model') || getQS('title'); if(qSku){ const p = DATA.products.find(pr => pr.sku && norm(pr.sku)===norm(qSku)); if(p) return p; } if(qAsin){ const p = DATA.products.find(pr => pr.asin && norm(pr.asin)===norm(qAsin)); if(p) return p; } if(qModel){ let p = DATA.products.find(pr => norm(pr.title)===norm(qModel)); if(!p) p = DATA.products.find(pr => norm(pr.title).includes(norm(qModel))); if(p) return p; } if(qManu) return { __manuOnly:true, manufacturer:qManu }; return null; } /* ---------- Init ---------- */ (async function init(){ // Affiliates from URL (persist quietly) const qRef=getQS('ref'); const qTag=getQS('atag'); if(qRef) localStorage.setItem('truthcase_ref', qRef); if(qTag) localStorage.setItem('truthcase_atag', qTag); affiliateRef = qRef || localStorage.getItem('truthcase_ref') || ''; amazonTag = qTag || localStorage.getItem('truthcase_atag') || ''; await loadData(); buildManufacturers(); if(manufacturers.length){ manuRow.style.display=''; modelOnlyRow.style.display='none'; renderManufacturerSelect(); modelCol.classList.add('is-hidden'); modelSelect.disabled=true; }else{ manuRow.style.display='none'; modelOnlyRow.style.display=''; renderModelSelect(DATA.products, modelSelectSolo); } // Deep‑link const pick = pickFromDeepLink(); if(pick){ openModal(); if(pick.__manuOnly){ const manuName = manufacturers.find(m => norm(m)===norm(pick.manufacturer)) || pick.manufacturer; selectedManufacturer = manuName || ''; if(manufacturers.length){ manuSelect.value=selectedManufacturer; manuSelect.dispatchEvent(new Event('change')); } buyButtons.style.display='none'; }else{ if(manufacturers.length){ manuSelect.value = pick.manufacturer || ''; manuSelect.dispatchEvent(new Event('change')); const idx = filteredProducts.findIndex(pr => norm(pr.title)===norm(pick.title)); const idx2 = idx>=0 ? idx : filteredProducts.findIndex(pr => norm(pr.title).includes(norm(pick.title))); if(idx2>=0){ modelSelect.value=String(idx2); modelSelect.dispatchEvent(new Event('change')); } }else{ const i = DATA.products.findIndex(pr => norm(pr.title)===norm(pick.title)); if(i>=0){ modelSelectSolo.value=String(i); modelSelectSolo.dispatchEvent(new Event('change')); } } } } // Reveal-on-scroll const io=new IntersectionObserver(es=>es.forEach(e=>{ if(e.isIntersecting){ e.target.classList.add('in'); io.unobserve(e.target);} }),{threshold:.12}); $$('.reveal').forEach(el=>io.observe(el)); })(); </script> </body> </html>
Save changes
Create folder
writable 0777
Create
Cancel