<!doctype html>
<!--
  trentpower.fr
  static, self-managed, privacy-first
  service worker recovery page (local cache reset only).
  no analytics, no cookies, no external assets.
  this page is network-only — never served from the local cache,
  so a stale service worker cannot stop a visitor from reaching it.
-->
<html lang="en" dir="ltr">
<head>
  <!-- foundations -->
  <meta charset="utf-8">
  <script>(()=>{const e=document.documentElement;let t='';try{t=localStorage.getItem('tp-lang')||''}catch{}const n=(navigator.languages&&navigator.languages[0])||navigator.language||'en',a=t&&['en','fr'].includes(t)?t:/^fr\b/i.test(n)?'fr':'en';e.lang=a,e.dataset.lang=a,e.classList.add("js")})();</script>
  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
  <meta name="color-scheme" content="light dark">
  <meta name="supported-color-schemes" content="light dark">
  <meta name="theme-color" content="#E9E5DC" media="(prefers-color-scheme: light)">
  <meta name="theme-color" content="#22201B" media="(prefers-color-scheme: dark)">

  <!-- document -->
  <title>Service Worker Reset — Trent Power</title>
  <meta name="description"
        content="Local recovery utility. Clears the offline cache for trentpower.fr on this device only.">
  <meta name="document-edition" content="2026-05-09">
  <link rel="canonical" href="https://trentpower.fr/sw-reset/">

  <!-- identity -->
  <meta name="author" content="Trent Power">
  <meta name="application-name" content="Trent Power">
  <meta name="apple-mobile-web-app-title" content="Trent Power">
  <link rel="author" href="/.well-known/attribution.txt">
  <link rel="alternate" type="application/ld+json" href="/.well-known/person.json">

  <!-- discovery -->
  <meta name="robots" content="noindex">
  <meta name="referrer" content="no-referrer">

  <!-- social preview -->
  <meta property="og:type" content="website">
  <meta property="og:site_name" content="Trent Power">
  <meta property="og:title" content="Service Worker Reset · Trent Power">
  <meta property="og:description" content="Local recovery utility. Clears the offline cache for trentpower.fr on this device only.">
  <meta property="og:url" content="https://trentpower.fr/sw-reset/">
  <meta property="og:image" content="https://trentpower.fr/images/og/default-og.png">
  <meta property="og:image:width" content="1200">
  <meta property="og:image:height" content="630">
  <meta property="og:image:type" content="image/png">
  <meta property="og:image:alt" content="Service Worker Reset · Trent Power">
  <meta name="twitter:card" content="summary_large_image">
  <meta name="twitter:title" content="Service Worker Reset · Trent Power">
  <meta name="twitter:description" content="Local recovery utility. Clears the offline cache for trentpower.fr on this device only.">
  <meta name="twitter:image" content="https://trentpower.fr/images/og/default-og.png">
  <meta name="twitter:image:alt" content="Service Worker Reset · Trent Power">
  <meta name="twitter:site"    content="@trentpower">
  <meta name="twitter:creator" content="@trentpower">

  <!-- icons and app surface -->
  <link rel="icon" href="/favicon.ico" sizes="any">
  <link rel="icon" href="/favicon.svg" type="image/svg+xml">
  <link rel="apple-touch-icon" href="/apple-touch-icon.png">
  <link rel="manifest" href="/manifest.webmanifest" type="application/manifest+json">
  <link rel="license" href="https://creativecommons.org/licenses/by-sa/4.0/">

  <!-- assets -->
  <link rel="stylesheet" href="/styles.css?v=2026-05-09.fceaf1e4" integrity="sha384-y+VS/OHX/2qm5pl3NOcFOmrRi3kBp8xhdlQQ1N9FBRpJffyKH6rj1vGRYEFlv1zJ">
  <link rel="stylesheet" href="/print.css?v=2026-05-09.fceaf1e4" media="print">

  <!-- structured data -->
  <script type="application/ld+json">{"@context":"https://schema.org","@type":"WebPage","@id":"https://trentpower.fr/sw-reset/#webpage","url":"https://trentpower.fr/sw-reset/","name":"Service Worker Reset · Trent Power","description":"Local recovery utility. Clears the offline cache for trentpower.fr on this device only.","inLanguage":"en","isPartOf":{"@id":"https://trentpower.fr/#website"},"about":{"@id":"https://trentpower.fr/#trent-power"},"primaryImageOfPage":{"@type":"ImageObject","url":"https://trentpower.fr/images/og/default-og.png","width":1200,"height":630},"dateModified":"2026-05-15T00:00:00+00:00"}</script>
</head>
<body data-page="sw-reset" data-surface="record" data-masthead="brand-only" data-edition="2026-05-09">

<a href="#main" class="skip-link">Skip to content</a>

<header class="site-header" data-component="site-header">
  <div class="nav">
    <div class="nav-inner">
      <a class="nav-mark" href="/" aria-label="Trent Power home"><span>Trent</span> <span>Power</span></a>
    </div>
  </div>
</header>

<main class="site sw-reset-page" id="main" tabindex="-1">
  <div class="page">
    <p class="sw-reset-marker" data-i18n="sw_reset.local_marker">LOCAL DEVICE ONLY</p>
    <h1 class="page-title" data-i18n="sw_reset.page_title">Service Worker Reset</h1>
    <div class="page-body">
      <p class="page-lede" data-i18n="sw_reset.lede">Clears the local offline cache for this device only. The live publication and server are unaffected.</p>

      <p data-i18n="sw_reset.secondary">If a recent edition is not appearing correctly, this utility refreshes the local publication cache.</p>

      <section class="verify-card" aria-labelledby="sw-reset-status-label">
        <div class="verify-card__header">
          <p class="eyebrow" data-i18n="sw_reset.status_label">Local cache status</p>
          <h2 id="sw-reset-status-label" data-i18n="sw_reset.page_title">Service Worker Reset</h2>
          <p class="verify-status" data-i18n="sw_reset.local_marker">LOCAL DEVICE ONLY</p>
        </div>
        <dl class="record-grid" role="status" aria-live="polite" id="sw-reset-status">
          <div class="record-grid__row">
            <dt data-i18n="sw_reset.detected_label">Detected</dt>
            <dd id="sw-reset-status-detail" data-i18n="sw_reset.status_initial">Reading local state…</dd>
          </div>
        </dl>
        <div class="record-actions">
          <button type="button" id="sw-reset-btn" class="sw-reset-btn" data-i18n="sw_reset.button">Reset local offline cache</button>
          <a href="/" data-i18n="sw_reset.link_home">Home</a>
          <a href="/sw-reset/" id="sw-reset-reload" data-i18n="sw_reset.link_reload">Reload current edition</a>
        </div>
      </section>

      <section class="edition-panel" aria-labelledby="sw-reset-scope-label">
        <h2 id="sw-reset-scope-label" data-i18n="sw_reset.scope_heading">Scope</h2>
        <dl class="record-grid record-grid--quiet">
          <div class="record-grid__row">
            <dt data-i18n="sw_reset.clears_heading">Clears</dt>
            <dd>
              <code data-i18n="sw_reset.clear_sw">Service Worker registrations</code> ·
              <code data-i18n="sw_reset.clear_caches">Offline cache entries</code> ·
              <code data-i18n="sw_reset.clear_pref">Saved language preference</code>
            </dd>
          </div>
          <div class="record-grid__row">
            <dt data-i18n="sw_reset.preserves_heading">Does not clear</dt>
            <dd>
              <span data-i18n="sw_reset.preserve_history">Browser history</span> ·
              <span data-i18n="sw_reset.preserve_downloads">Downloads</span> ·
              <span data-i18n="sw_reset.preserve_others">Other websites</span> ·
              <span data-i18n="sw_reset.preserve_server">Server content</span>
            </dd>
          </div>
          <div class="record-grid__row">
            <dt data-i18n="sw_reset.api_label">APIs</dt>
            <dd data-i18n="sw_reset.footnote">Offline state is stored locally through the browser Cache Storage and Service Worker APIs.</dd>
          </div>
        </dl>
      </section>
    </div>
    <a href="/" class="page-back" rel="home" data-i18n="acknowledgments.back">← Home</a>
  </div>

</main>


<!-- footer · canonical bem system (phase 35)
     three left-aligned compact rows on mobile, single horizontal
     rail on desktop (>= 760px). language list joined by `·`
     separators via ::before pseudos. one trigger contract: the
     citation button carries [data-cite-open] — cite.js binds to
     every matching trigger across pages.
-->
<footer class="site-footer">
  <p class="site-footer__seal" aria-hidden="true">· · ·</p>
  <p class="site-footer__colophon">2026&nbsp;&nbsp;Trent Power&nbsp;&nbsp;Paris,&nbsp;France</p>
  <nav class="site-footer__language" aria-label="Language">
    <button type="button" data-lang="en" lang="en" aria-pressed="true" aria-label="English">English</button>
    <span class="site-footer__lang-sep" aria-hidden="true">/</span>
    <button type="button" data-lang="fr" lang="fr" aria-pressed="false" aria-label="Français">Français</button>
  </nav>
</footer>
<!-- translated dynamic-status strings. application/json is data, not
     executable; csp script-src does not enforce against it. the inline
     reset script reads templates from here and re-renders when the
     <html lang> attribute changes (footer language switcher). -->
<script type="application/json" id="sw-reset-i18n">{
  "en": {"not_supported":"Service Workers not supported","resetting":"Resetting…","complete":"Local offline cache cleared","warning":"Reset finished with a warning: {msg}","sw_count":"{n} service worker(s)","caches_count":"{n} local cache(s)","pref_stored":"language preference stored","pref_none":"no language preference stored","edition":"cached edition {e}","edition_none":"no cached edition detected"},
  "fr": {"not_supported":"Service Workers non pris en charge","resetting":"Réinitialisation en cours…","complete":"Cache hors-ligne local effacé","warning":"Réinitialisation terminée avec un avertissement : {msg}","sw_count":"{n} Service Worker(s)","caches_count":"{n} cache(s) local(aux)","pref_stored":"préférence de langue enregistrée","pref_none":"aucune préférence de langue enregistrée","edition":"édition en cache {e}","edition_none":"aucune édition en cache détectée"},
  "it": {"not_supported":"Service Worker non supportati","resetting":"Reimpostazione in corso…","complete":"Cache offline locale svuotata","warning":"Reimpostazione completata con un avviso: {msg}","sw_count":"{n} Service Worker","caches_count":"{n} cache locali","pref_stored":"preferenza di lingua salvata","pref_none":"nessuna preferenza di lingua salvata","edition":"edizione in cache {e}","edition_none":"nessuna edizione in cache rilevata"},
  "es": {"not_supported":"Service Workers no soportados","resetting":"Reiniciando…","complete":"Caché sin conexión local borrada","warning":"Reinicio finalizado con una advertencia: {msg}","sw_count":"{n} Service Worker(s)","caches_count":"{n} caché(s) local(es)","pref_stored":"preferencia de idioma guardada","pref_none":"sin preferencia de idioma guardada","edition":"edición en caché {e}","edition_none":"no se detectó edición en caché"},
  "de": {"not_supported":"Service Worker nicht unterstützt","resetting":"Wird zurückgesetzt…","complete":"Lokaler Offline-Cache geleert","warning":"Zurücksetzung mit Warnung beendet: {msg}","sw_count":"{n} Service-Worker","caches_count":"{n} lokale Caches","pref_stored":"Spracheinstellung gespeichert","pref_none":"keine Spracheinstellung gespeichert","edition":"zwischengespeicherte Ausgabe {e}","edition_none":"keine zwischengespeicherte Ausgabe erkannt"}
}</script>

<script>(function(){var sd=document.getElementById('sw-reset-status-detail');var b=document.getElementById('sw-reset-btn');var I18N={};try{var raw=document.getElementById('sw-reset-i18n');if(raw)I18N=JSON.parse(raw.textContent||'{}');}catch(_){I18N={};}function L(k,p){var lang=(document.documentElement.lang||'en').toLowerCase();var t=(I18N[lang]&&I18N[lang][k])||(I18N.en&&I18N.en[k])||k;if(p){Object.keys(p).forEach(function(x){t=t.replace('{'+x+'}',p[x]);});}return t;}function setDetail(m){if(sd)sd.textContent=m;}var swSupported='serviceWorker'in navigator;var cachesSupported='caches'in window;var lastState=null;function readEditionFromCache(){if(!cachesSupported)return Promise.resolve(null);return caches.keys().then(function(ns){if(!ns||!ns.length)return null;var m=String(ns[0]).match(/(\d{4}-\d{2}-\d{2})/);return m?m[1]:null;}).catch(function(){return null;});}function render(){if(!lastState){return;}var sw=lastState.sw,cn=lastState.cn,ed=lastState.ed,pref=lastState.pref;var parts=[L('sw_count',{n:sw}),L('caches_count',{n:cn}),pref?L('pref_stored'):L('pref_none'),ed?L('edition',{e:ed}):L('edition_none')];setDetail(parts.join(' · '));}function refreshState(){if(!swSupported){setDetail(L('not_supported'));if(b)b.disabled=true;return;}var jobs=[];jobs.push(navigator.serviceWorker.getRegistrations().then(function(rs){return(rs||[]).length;}).catch(function(){return 0;}));jobs.push(cachesSupported?caches.keys().then(function(ns){return(ns||[]).length;}).catch(function(){return 0;}):Promise.resolve(0));jobs.push(readEditionFromCache());Promise.all(jobs).then(function(r){var pref=false;try{pref=!!localStorage.getItem('tp-lang');}catch(_){}lastState={sw:r[0],cn:r[1],ed:r[2],pref:pref};render();});}refreshState();var mo=new MutationObserver(function(){render();});mo.observe(document.documentElement,{attributes:true,attributeFilter:['lang']});if(b){b.addEventListener('click',function(){b.disabled=true;setDetail(L('resetting'));var jobs=[];jobs.push(navigator.serviceWorker.getRegistrations().then(function(rs){return Promise.all((rs||[]).map(function(r){return r.unregister();}));}).catch(function(){return null;}));if(cachesSupported){jobs.push(caches.keys().then(function(ns){return Promise.all((ns||[]).map(function(n){return caches.delete(n);}));}).catch(function(){return null;}));}try{localStorage.removeItem('tp-lang');}catch(_){}Promise.all(jobs).then(function(){setDetail(L('complete'));}).catch(function(e){setDetail(L('warning',{msg:(e&&e.message)||'unknown'}));});});}})();</script>

<!-- End-of-body scripts -->

<script src="/i18n-core.js?v=2026-05-09.fceaf1e4" integrity="sha384-lV7pwDwerNfEsW2JaZJujhBg+oHE1T4sxvSjUTIBWlWC1QLCQ+TOOvdN51q9PxZ7" defer></script>

<script src="/app.js?v=2026-05-09.fceaf1e4" integrity="sha384-Z6I7OJ48wrxeNCxv696t8GcWhKvJtNL1k3Jd/jn85IAww6+hao2mMncJK6PoTuZg" defer></script>

<script src="/app-enhance.js?v=2026-05-09.fceaf1e4" integrity="sha384-OcM6fBrT4SLPWzae3KsTFJ+FLo4I/GMnLUPMdgkVk2F6g61xl5HVc3xTkBFTG0dq" defer></script>

<script src="/cite.js?v=2026-05-09.fceaf1e4" integrity="sha384-7bNRCHCsMzonHWF+yMHnIHfqYd1i1jLy3uD+4vAC2ZJ6uMCsLxDO1ooqYyuv/Prp" defer></script>

</body>
</html>
