☰

Sleazy Fork is available in English.

FL Tools Notes

Manually saved local notes for FetLife pages

Ajankohdalta 8.10.2026. Katso uusin versio.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         FL Tools Notes
// @namespace    https://gitlab.com/fl-tools-lite/fl-tools-notes
// @version      0.1.0
// @description  Manually saved local notes for FetLife pages
// @author       TypicalBits
// @icon         data:image/png;base64,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
// @icon64       data:image/png;base64,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
// @license      PolyForm-Noncommercial-1.0.0
// @match        https://fetlife.com/*
// @run-at       document-end
// @noframes
// @grant        GM.getValue
// @grant        GM.setValue
// @homepageURL  https://gitlab.com/fl-tools-lite/fl-tools-notes
// @supportURL   https://gitlab.com/fl-tools-lite/fl-tools-notes/-/issues
// ==/UserScript==

// Copyright 2026 TypicalBits.
(function(){
'use strict';
// dock.js
// Copyright 2026 TypicalBits. Shared FL Tools Lite coordination.
const LITE_ORDER = ['view','read','calendar','notes','return'];
const LITE_CORNERS = ['bottom-left','bottom-right','top-left','top-right'];
const LITE_COLORS = {view:'#62A8DE',read:'#B9A0F5',calendar:'#65D8EB',notes:'#F39BC8',return:'#CCD4E0'};
const LITE_REPAIR = 'flt-lite:repair-v1';
function claimProduct(document,id) {
  if (!LITE_ORDER.includes(id) || document.querySelector(`[data-flt-lite-claim="${id}"]`)) return null;
  const claim=document.createElement('span');claim.hidden=true;claim.dataset.fltLiteClaim=id;
  document.documentElement.append(claim);
  return {ensure(){if(!claim.isConnected)document.documentElement.append(claim);},release(){claim.remove();}};
}
function setLiteCorner(document,host,corner) {
  host.dataset.corner=corner; document.documentElement.dataset.fltLiteCorner=corner;
  for(const panel of document.querySelectorAll('[data-flt-lite-panel]'))panel.dataset.fltLiteCorner=corner;
}
function ownLiteDock(document,host,storage,restoreSaved=true) {
  const w=document.defaultView; const shadow=host.attachShadow({mode:'open'});
  const style=document.createElement('style');style.textContent=`
  :host{position:fixed;bottom:16px;left:16px;z-index:2147483001;color-scheme:dark;font:12px/1.4 system-ui,sans-serif}
  :host([data-corner="bottom-right"]){left:auto;right:16px}
  :host([data-corner="top-left"]){bottom:auto;top:16px}
  :host([data-corner="top-right"]){left:auto;right:16px;bottom:auto;top:16px}
  :host([data-fallback="true"]){transform:translateY(-58px)}:host([data-fallback="true"][data-corner^="top"]){transform:translateY(58px)}
  .dock{display:flex;flex-wrap:wrap;gap:5px;max-width:calc(100vw - 32px)}
  button{display:flex;align-items:center;justify-content:center;padding:3px;width:46px;height:46px;border:1px solid var(--accent);border-radius:8px;background:#17171a;cursor:pointer;color:var(--accent);font:inherit}
  button:focus-visible{outline:2px solid var(--accent);outline-offset:2px}button[aria-expanded="true"]{box-shadow:0 0 0 1px var(--accent)}img{width:38px;height:38px;display:block}
  `;const bar=document.createElement('nav');bar.className='dock';bar.setAttribute('aria-label','FL Tools Lite');shadow.append(style,bar);
  let cornerRevision=0;
  let current=null;const buttons=new Map(); let disposed=false;let writes=Promise.resolve();
  function ports(){return [...host.children].filter(x=>x.hasAttribute('data-flt-lite-port'));}
  function close(port,focus=false){port?.dispatchEvent(new w.Event('flt-lite:close'));buttons.get(port)?.setAttribute('aria-expanded','false');if(current===port)current=null;if(focus)buttons.get(port)?.focus();}
  function open(port){if(current===port){close(port,true);return;}if(current)close(current);current=port;buttons.get(port)?.setAttribute('aria-expanded','true');port.dispatchEvent(new w.Event('flt-lite:open'));}
  function render(){
    const active=ports().sort((a,b)=>LITE_ORDER.indexOf(a.dataset.product)-LITE_ORDER.indexOf(b.dataset.product));
    for(const [port,button]of buttons)if(!active.includes(port)){if(current===port)close(port);button.remove();buttons.delete(port);}
    for(const port of active){
      let button=buttons.get(port);
      if(!button){port.dispatchEvent(new w.Event('flt-lite:close'));button=document.createElement('button');button.type='button';button.dataset.product=port.dataset.product;button.setAttribute('aria-label','Open FL Tools '+port.dataset.label);button.setAttribute('aria-expanded','false');button.style.setProperty('--accent',LITE_COLORS[port.dataset.product]);
        if(port.dataset.icon){const image=document.createElement('img');image.src=port.dataset.icon;image.alt='';button.append(image);}else button.textContent=port.dataset.label;
        button.addEventListener('click',()=>open(port));buttons.set(port,button);
      }
      if(bar.children[active.indexOf(port)]!==button)bar.append(button);
    }
    setLiteCorner(document,host,host.dataset.corner||'bottom-left');
  }
  const route=event=>{const port=event.target;if(port.parentNode!==host||!port.hasAttribute('data-flt-lite-port'))return;
    if(event.type==='flt-lite:register')render();
    if(event.type==='flt-lite:toggle')open(port);
    if(event.type==='flt-lite:hide')close(port,true);
    if(event.type==='flt-lite:focus')buttons.get(port)?.focus();
    if(event.type==='flt-lite:corner'&&LITE_CORNERS.includes(port.dataset.corner)){
      cornerRevision++;const corner=port.dataset.corner;setLiteCorner(document,host,corner);
      if(storage)writes=writes.then(()=>storage.setValue('flt-lite:dock:v1',corner)).catch(()=>{});
    }
  };
  for(const name of ['register','toggle','hide','focus','corner'])host.addEventListener('flt-lite:'+name,route);
  const escape=event=>{if(current&&event.key==='Escape'){close(current,true);event.stopPropagation();}};
  document.addEventListener('keydown',escape);
  const observer=new w.MutationObserver(()=>{if(!disposed)render();});observer.observe(host,{childList:true});render();
  if(storage&&restoreSaved)Promise.resolve().then(()=>storage.getValue('flt-lite:dock:v1','bottom-left')).then(corner=>{if(!disposed&&cornerRevision===0&&host.isConnected&&LITE_CORNERS.includes(corner))setLiteCorner(document,host,corner);}).catch(()=>{});
  return {destroy(){disposed=true;observer.disconnect();document.removeEventListener('keydown',escape);for(const name of ['register','toggle','hide','focus','corner'])host.removeEventListener('flt-lite:'+name,route);},render};
}
function registerDock(document,{id,label,icon,onOpen=()=>{},onClose=()=>{},storage}) {
  const w=document.defaultView;const port=document.createElement('span');port.hidden=true;port.dataset.fltLitePort='';port.dataset.product=id;port.dataset.label=label;port.dataset.icon=icon;
  port.addEventListener('flt-lite:open',onOpen);port.addEventListener('flt-lite:close',onClose);
  let owner=null,ownedHost=null,destroyed=false,scheduled=false;
  function ensure(){
    if(destroyed||!document.body)return;
    let host=document.querySelector('[data-flt-lite-dock="1"]');
    if(!host){const restoreSaved=!document.documentElement.dataset.fltLiteCorner;owner?.destroy();host=document.createElement('div');host.dataset.fltLiteDock='1';host.dataset.corner=document.documentElement.dataset.fltLiteCorner||ownedHost?.dataset.corner||'bottom-left';host.dataset.fallback=String(!!document.querySelector('[data-flt-lite-dock]:not([data-flt-lite-dock="1"])'));document.body.append(host);ownedHost=host;owner=ownLiteDock(document,host,storage,restoreSaved);}
    if(port.parentNode!==host){host.append(port);port.dispatchEvent(new w.Event('flt-lite:register',{bubbles:true}));}
    owner?.render();
  }
  const schedule=()=>{if(scheduled||destroyed)return;scheduled=true;w.queueMicrotask(()=>{scheduled=false;ensure();});};
  const observer=new w.MutationObserver(records=>{if(!port.isConnected||!document.querySelector('[data-flt-lite-dock="1"]'))schedule();});observer.observe(document.documentElement,{childList:true,subtree:true});
  document.addEventListener(LITE_REPAIR,schedule);ensure();
  const send=name=>{ensure();port.dispatchEvent(new w.Event('flt-lite:'+name,{bubbles:true}));};
  return {
    ensure,open(){send('toggle');},close(){send('hide');},focus(){send('focus');},
    setCorner(corner){if(!LITE_CORNERS.includes(corner))return;port.dataset.corner=corner;send('corner');},
    get corner(){return port.parentNode?.dataset.corner||'bottom-left';},
    destroy(){if(destroyed)return;destroyed=true;observer.disconnect();document.removeEventListener(LITE_REPAIR,schedule);onClose();const host=port.parentNode;port.remove();
      if(owner&&host===ownedHost){const survivors=[...host.children];owner.destroy();for(const survivor of survivors)document.body.append(survivor);host.remove();document.dispatchEvent(new w.Event(LITE_REPAIR));}
      else if(host&&!host.querySelector('[data-flt-lite-port]'))host.remove();
      port.removeEventListener('flt-lite:open',onOpen);port.removeEventListener('flt-lite:close',onClose);
    }
  };
}

// storage.js
// Copyright 2026 TypicalBits.
function createRecordStore(storage,key,normalize,locks=globalThis.navigator?.locks) {
  let value={},loaded=false,error='',queue=Promise.resolve();
  return {
    get value(){return structuredClone(value);},get error(){return error;},
    async load(){try{value=normalize(await storage.getValue(key,{}));loaded=true;error='';}catch{error='Saved data could not be read. Reload before saving.';}return structuredClone(value);},
    transact(change){const job=queue.then(async()=>{
      if(!loaded)throw Error(error||'Saved data has not loaded.');
      if(!locks?.request){error='This browser cannot safely save across tabs. Use a browser with Web Locks support.';throw Error(error);}
      const controller=new AbortController();const timeout=setTimeout(()=>controller.abort(),10000);
      try{return await locks.request('flt-lite:storage:'+key,{mode:'exclusive',signal:controller.signal},async()=>{
        let latest;try{latest=normalize(await storage.getValue(key,{}));}catch{error='Saved data could not be read. Nothing was overwritten.';throw Error(error);}
        const next=normalize(change(structuredClone(latest)));
        try{await storage.setValue(key,next);value=next;error='';return structuredClone(value);}catch{error='Could not save. Your previous saved data is unchanged.';throw Error(error);}
      });}catch(problem){if(controller.signal.aborted){error='Another tab is busy saving. Please try again.';throw Error(error);}throw problem;}finally{clearTimeout(timeout);}
    });queue=job.catch(()=>{});return job;}

  };
}
function pageKey(input) {
  const url=new URL(input);
  if(url.protocol!=='https:'||url.hostname!=='fetlife.com'||url.username||url.password||url.port)throw Error('This is not a FetLife page.');
  url.hash='';return url.href;
}

// panel.js
// Copyright 2026 TypicalBits.
function liteElement(document,tag,attributes={},text='') {
  const element=document.createElement(tag);for(const [key,value]of Object.entries(attributes))element.setAttribute(key,String(value));if(text)element.textContent=text;return element;
}
function createLitePanel(document,{id,name,accent,icon,version,storage,onOpen=()=>{}}) {
  const e=(tag,attrs,text)=>liteElement(document,tag,attrs,text);
  const host=e('div',{'data-flt-lite-panel':id,'data-flt-lite-corner':'bottom-left'});const shadow=host.attachShadow({mode:'open'});
  const style=e('style');style.textContent=`
  :host{all:initial;position:fixed;left:16px;bottom:16px;z-index:2147483002;font:12px/1.5 system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;color:#eeeef4;color-scheme:dark;--accent:${accent}}
  :host([data-flt-lite-corner$="right"]){left:auto;right:16px}:host([data-flt-lite-corner^="top"]){bottom:auto;top:16px}
  *,*::before,*::after{box-sizing:border-box}[hidden]{display:none!important}button,input,textarea,select{font:inherit;color:inherit}button{cursor:pointer}button:disabled{opacity:.5;cursor:default}
  button,input,textarea,select{background:#222228;border:1px solid #4b4b59;border-radius:6px;padding:6px 8px;min-width:0}button{min-height:32px}button:focus-visible,input:focus-visible,textarea:focus-visible,summary:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
  .panel{position:absolute;bottom:54px;left:0;width:min(320px,calc(100vw - 32px));max-height:calc(100dvh - 90px);overflow:auto;padding:12px;background:#131318;border:1px solid var(--accent);border-radius:10px;box-shadow:0 8px 26px #0008}
  :host([data-flt-lite-corner$="right"]) .panel{left:auto;right:0}:host([data-flt-lite-corner^="top"]) .panel{bottom:auto;top:54px}
  .heading{display:flex;align-items:center;gap:8px;margin-bottom:12px}.heading strong{flex:1;font-size:14px}.heading img{width:30px;height:30px}.version{font-size:10px;color:#b5b5c4}.close{width:30px;min-height:30px;padding:0}
  p{margin:0 0 10px}fieldset{border:0;padding:0;margin:0 0 12px;min-width:0}legend,label{font-weight:600;padding:0;margin-bottom:6px;display:block}input,textarea,select{display:block;width:100%;margin-bottom:10px}textarea{min-height:160px;resize:vertical}
  .choices,.actions{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:10px}.choices button{flex:1}.choices button[aria-pressed=true],.primary{background:var(--accent);border-color:var(--accent);color:#101015;font-weight:600}
  .row{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:12px}.row label{margin:0;min-width:0}.switch{position:relative;flex:none;width:34px;min-height:20px;height:20px;padding:0;border-radius:5px}.switch::after{content:"";position:absolute;top:3px;left:3px;width:12px;height:12px;background:#b5b5c4;border-radius:3px}.switch[aria-checked=true]{background:var(--accent)}.switch[aria-checked=true]::after{left:17px;background:#131318}
  .note,.status,.page{font-size:11px;color:#b5b5c4;overflow-wrap:anywhere}.status{border-top:1px solid #3d3d46;padding-top:8px;margin:10px 0 0}.status:empty{display:none}details{border-top:1px solid #3d3d46;margin-top:10px;padding-top:8px}summary{cursor:pointer;color:var(--accent);font-weight:600;margin-bottom:8px}.record{border-top:1px solid #3d3d46;padding:8px 0;overflow-wrap:anywhere}.record strong{display:block;margin-bottom:4px}.confirmation{border:1px solid var(--accent);padding:8px;border-radius:6px;margin-bottom:10px}
  `;
  const panel=e('section',{class:'panel','aria-label':'FL Tools '+name});panel.hidden=true;
  const heading=e('div',{class:'heading'});if(icon)heading.append(e('img',{src:icon,alt:''}));heading.append(e('strong',{},'FL Tools '+name),e('span',{class:'version'},version));const close=e('button',{class:'close',type:'button','aria-label':'Close '+name},'×');heading.append(close);
  const body=e('div',{'data-content':''}),settings=e('details');settings.append(e('summary',{},'Settings'));const corners=e('div',{class:'choices','aria-label':'Dock position'});
  let dock;for(const corner of ['bottom-left','bottom-right','top-left','top-right']){const button=e('button',{type:'button','aria-label':corner.replace('-',' '),'aria-pressed':'false'},corner.startsWith('top')?'↑ '+(corner.endsWith('left')?'Left':'Right'):'↓ '+(corner.endsWith('left')?'Left':'Right'));button.addEventListener('click',()=>{dock.setCorner(corner);for(const b of corners.children)b.setAttribute('aria-pressed',String(b===button));});corners.append(button);}settings.append(e('p',{class:'note'},'Dock position'),corners);
  const status=e('p',{class:'status',role:'status','data-status':''});panel.append(heading,body,settings,status);shadow.append(style,panel);document.body.append(host);
  dock=registerDock(document,{id,label:name,icon,storage,onOpen:()=>{panel.hidden=false;onOpen();close.focus();},onClose:()=>{panel.hidden=true;}});close.addEventListener('click',()=>dock.close());
  return {host,shadow,panel,body,settings,dock,e,setStatus(text){if(status.textContent!==text)status.textContent=text;},ensure(){if(!host.isConnected)document.body.append(host);dock.ensure();},destroy(){dock.destroy();host.remove();}};
}
function watchLitePage(document,callback) {
  const window=document.defaultView;let queued=false,destroyed=false;
  const owned=node=>{const element=node.nodeType===1?node:node.parentElement;const host=element?.getRootNode()?.host;return !!element?.closest('[data-flt-lite-panel],[data-flt-lite-dock],[data-flt-lite-port],[data-flt-lite-claim],[data-flt-lite-style],[data-flt-view-root],[data-flt-view-style]')||(typeof host?.hasAttribute==='function'&&host.hasAttribute('data-flt-lite-panel'));};
  const schedule=()=>{if(queued||destroyed)return;queued=true;window.queueMicrotask(()=>{queued=false;if(!destroyed)callback();});};
  const observer=new window.MutationObserver(records=>{if(records.some(record=>!owned(record.target)&&[...record.addedNodes,...record.removedNodes].some(node=>!owned(node))))schedule();});observer.observe(document.documentElement,{childList:true,subtree:true});
  const events=['popstate','pageshow','turbo:load','turbo:render','turbolinks:load'];for(const event of events)window.addEventListener(event,schedule);
  return ()=>{destroyed=true;observer.disconnect();for(const event of events)window.removeEventListener(event,schedule);};
}

// bootstrap.js
// Copyright 2026 TypicalBits.
async function bootstrapLite({document,window,storage,product,setup}) {
  const claim=claimProduct(document,product.id);if(!claim)return {duplicate:true,destroy(){}};
  let feature,stop=()=>{},ui;
  try {
    const refresh=()=>{claim.ensure();ui.ensure();feature?.refresh?.();};
    ui=createLitePanel(document,{...product,storage,onOpen:refresh});ui.setStatus('Loading saved settings…');
    feature=await setup({ui,document,window,storage});stop=watchLitePage(document,refresh);refresh();
    return {refresh,destroy(){stop();feature?.destroy?.();ui.destroy();claim.release();}};
  }catch(error){stop();feature?.destroy?.();ui?.destroy();claim.release();throw error;}
}
function liteButton(ui,label,attributes={},handler=()=>{}) {
  const button=ui.e('button',{type:'button',...attributes},label);button.addEventListener('click',handler);return button;
}
function liteField(ui,name,label,value='') {
  const id='flt-'+ui.host.dataset.fltLitePanel+'-'+name;const node=ui.e('input',{id,type:'text','data-field':name});node.value=value;
  ui.body.append(ui.e('label',{for:id},label),node);return node;
}

// icon.js
const PRODUCT_ICON = "data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2064%2064%22%20role%3D%22img%22%20aria-labelledby%3D%22title%20desc%22%3E%0A%20%20%3Ctitle%20id%3D%22title%22%3EFL%20Tools%20Notes%20badge%3C%2Ftitle%3E%0A%20%20%3Cdesc%20id%3D%22desc%22%3EFL%20Tools%20Notes%20badge.%20Artwork%20is%20border-free%3B%20CSS%20supplies%20the%20launcher%20and%20menu%20frames.%3C%2Fdesc%3E%0A%20%20%3Cdefs%3E%0A%20%20%20%20%3CradialGradient%20id%3D%22surface%22%20cx%3D%2238%25%22%20cy%3D%2228%25%22%20r%3D%2285%25%22%3E%0A%20%20%20%20%20%20%3Cstop%20offset%3D%220%22%20stop-color%3D%22%2325242a%22%2F%3E%0A%20%20%20%20%20%20%3Cstop%20offset%3D%22.58%22%20stop-color%3D%22%2317171a%22%2F%3E%0A%20%20%20%20%20%20%3Cstop%20offset%3D%221%22%20stop-color%3D%22%230e0e10%22%2F%3E%0A%20%20%20%20%3C%2FradialGradient%3E%0A%20%20%20%20%3Cfilter%20id%3D%22labelGlow%22%20x%3D%22-40%25%22%20y%3D%22-60%25%22%20width%3D%22180%25%22%20height%3D%22220%25%22%3E%0A%20%20%20%20%20%20%3CfeGaussianBlur%20in%3D%22SourceGraphic%22%20stdDeviation%3D%22.85%22%20result%3D%22blur%22%2F%3E%0A%20%20%20%20%20%20%3CfeFlood%20flood-color%3D%22%23F39BC8%22%20flood-opacity%3D%22.42%22%20result%3D%22glowColor%22%2F%3E%0A%20%20%20%20%20%20%3CfeComposite%20in%3D%22glowColor%22%20in2%3D%22blur%22%20operator%3D%22in%22%20result%3D%22softGlow%22%2F%3E%0A%20%20%20%20%20%20%3CfeMerge%3E%0A%20%20%20%20%20%20%20%20%3CfeMergeNode%20in%3D%22softGlow%22%2F%3E%0A%20%20%20%20%20%20%20%20%3CfeMergeNode%20in%3D%22SourceGraphic%22%2F%3E%0A%20%20%20%20%20%20%3C%2FfeMerge%3E%0A%20%20%20%20%3C%2Ffilter%3E%0A%20%20%3C%2Fdefs%3E%0A%20%20%3Crect%20width%3D%2264%22%20height%3D%2264%22%20rx%3D%2214%22%20fill%3D%22url%28%23surface%29%22%2F%3E%0A%20%20%3Cimage%20href%3D%22data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAE90lEQVR4AcyZW4hWVRTH%2FzM5NamVGXQhrKjHLCqsJgeMLhBGQaCkZEqXyWns60JBRUJkD0UQZMVoWSFJt4dIKOqpHoIQqgepXkpKRcuKKCu0LK%2B%2F5ezvzNnn7HPxm%2FMdz8daZ%2B%2B199prrf86%2B%2By9z%2Fl6VfB7SZpfoNKV7tXSqa9IVxcZzwWAkYsx8BBcOxHYrgPS2lFpap5z9MLdB6WeHmmVpD64djpewr3OmiQ9rpxfb1Yft%2B9GLAzAJ2fpdLP9P6nt915mwplZvoIALPvwCjfoNFfWWuyXTncO%2B4%2BRHnH1VBEE8Kp0FZoXwUZTmEftbJhcF0dZJ5l3viCdGHIcBMDDsySuTAYujct11Jm6cZ%2BT%2BzNWwxSAl6XJBDgPjtPlcaGm%2BkDCz%2BKEfFhMAQD5bHqmwhHRdkMk1FAhiSfhxuKgGCOm0SDtltyxBndNAUAxlW3aLmPwBW5M1wsStggnrKRcx6mP6iWwRykA9KYA0GbUsku3%2BQlpEgkbCfkBWHJaqTegeE6gzZqGOFbMsko3%2BQzpbuzPhFMEsLOTjSEAJySVnNxLBlaztc8wZlk7zrVPuFgn2VJ9LpvnhRh7Es4ieza8vhCA4HrrRs1ia99mTPR7eC5%2BhNetkebZrXc6hcVaaRpjlsEfMv6vf6VdLNU%2FsHx%2FxeDMPYcEpmILATgWI2XJNpvF3Np3ufWbCaaVB4QNcjrTcOX%2F0nbGjMLX4ygVFG1Z1JfsCAH4I6lUUp6B3osA2eimAuI4EfgCjgebyOL9tHrLNHIpAnAqthCAbaWsZSvNZCp8zvSwQMV06efOPE%2Fg7zDkFLhjwsbW5OAUAJQ2J5U6kPvJ1koCX7VX%2Bpjx98ETJhKTis0DYIc2HFe5645gb3DCkTsDJPc2V40KDwArgW0g06Pe5lXmcFe9jdYDQLwL4abTLfEAIwA8bNPoOB%2FOoMY0e4e8CAAPmx0hIrkx4aYDOS%2FeFAXMGj0l3tHgureHRAB4gP9scNDx0HbGhQgAe%2FRPdLDUcm0wsSxvj4cXAbhdsjvwrRr%2BI%2BAN8RCR46Le96QGCkyRD%2BJheQDY6VhNhU5cpVH1Lb9In8Qj8gAslTbR%2BSbcVFrBcd1LsAfAot4nLaf8G24UMTu%2B4E3njWRQKQD38LKBUiWnR%2BxURbtJ7JKbJbYr32QKgHUPS69T8k2V69Gng2R%2FaJn0XSiUIACnaC8kR31VIviHeTbtZciF5ReZALgLHI80n41jvT%2BkVmk5wT%2Bb5zETgA0yEGRgAfX34FoJv4%2Fh%2F6kip7kAbDBG7E4sxOBrJtfAe%2FG1lMw%2FXcZXIQAzYiAwOIThB5C9dRi5StrJlJ2LLz5slDNbCkDbFIbt64L9a7m73VZh%2BT1r5BV8V%2FR22iL7RwTAjAFiPYPsrWiLyRXxp5yGZ2ctlXk%2BiCWvO9x3l%2FQ1D4b9g2KfTMJK5VvX%2FCxde4f0W%2Fkh45odAbDhLel3HM%2Bl%2FhzcCfFJVIt4voY537DRdmJC6hiAuTPHw9KD1O0PiT2UY1R83dEjXcnYt4pV8zUmBKBt2gIhoGuQf4WLaCPpHuBZ%2BrJIsUx%2FJQDMEQFtYH21f1C%2BMTnEgHyb5WvQHRhDKkfcVhkA8zwibeXb%2FBzqn8FJGt0h3cp8s7mf7OtYrhSAReHera8j2x%2BZbEz9GaZZi2eGm2Qt1XHlACw0gv2HHfUm6vYC0mJ6PUq9K3QIAAD%2F%2F1wKF9MAAAAGSURBVAMAjeXXP35naSYAAAAASUVORK5CYII%3D%22%20x%3D%2216%22%20y%3D%226%22%20width%3D%2232%22%20height%3D%2232%22%20preserveAspectRatio%3D%22xMidYMid%20meet%22%2F%3E%0A%20%20%3Ctext%20x%3D%2232%22%20y%3D%2254%22%20fill%3D%22%23F39BC8%22%20font-family%3D%22Arial%2C%20sans-serif%22%20font-size%3D%2212%22%20font-weight%3D%22800%22%20letter-spacing%3D%22.1%22%20text-anchor%3D%22middle%22%20filter%3D%22url%28%23labelGlow%29%22%3ENOTES%3C%2Ftext%3E%0A%3C%2Fsvg%3E%0A";

// notes.js
// Copyright 2026 TypicalBits.
function normalizeNotes(input) {
  if(!input||typeof input!=='object'||Array.isArray(input)||Object.keys(input).length>500)throw Error('Invalid saved notes.');
  const output={};for(const [url,record]of Object.entries(input)){
    if(pageKey(url)!==url||!record||typeof record.text!=='string'||record.text.length>20000)throw Error('Invalid saved note.');
    output[url]={text:record.text,updated:Number.isFinite(record.updated)?record.updated:0};
  }return output;
}
function createNotes(store,input) {
  let page=pageKey(input),draft=store.value[page]?.text||'';
  return {
    get page(){return page;},get draft(){return draft;},get dirty(){return draft!==(store.value[page]?.text||'');},
    edit(text){if(typeof text!=='string'||text.length>20000)throw Error('Notes can contain up to 20,000 characters.');draft=text;},
    discard(){draft=store.value[page]?.text||'';},
    switchPage(url){const next=pageKey(url);if(next===page)return true;if(this.dirty)return false;page=next;draft=store.value[page]?.text||'';return true;},
    async save(){const snapshot=draft,key=page;await store.transact(value=>{
      if(!Object.hasOwn(value,key)&&Object.keys(value).length>=500)throw Error('The 500-note limit has been reached.');
      return {...value,[key]:{text:snapshot,updated:Date.now()}};
    });},
    async remove(){const key=page;await store.transact(value=>{delete value[key];return value;});if(page===key)draft='';}
  };
}

// main.js
// Copyright 2026 TypicalBits.
function startNotes({document,window,storage,copy=text=>window.navigator.clipboard.writeText(text)}) {
  return bootstrapLite({document,window,storage,product:{id:'notes',name:'Notes',version:'0.1.0',icon:PRODUCT_ICON,accent:'#F39BC8'},setup:async({ui})=>{
    const store=createRecordStore(storage,'flt-notes:records:v1',normalizeNotes,window.navigator.locks);await store.load();const notes=createNotes(store,window.location.href);let busy=false,message='';
    const page=ui.e('p',{class:'page'});const label=ui.e('label',{for:'notes-text'},'Your note');const text=ui.e('textarea',{id:'notes-text',maxlength:'20000','aria-label':'Your note'});
    text.addEventListener('input',()=>{try{notes.edit(text.value);message='';}catch(error){message=error.message;}refresh();});
    const actions=ui.e('div',{class:'actions'});const save=liteButton(ui,'Save',{class:'primary','data-save':''},()=>perform(async()=>{await notes.save();message='Note saved.';}));
    const copyButton=liteButton(ui,'Copy',{'data-copy':''},()=>perform(async()=>{try{await copy(notes.draft);message='Note copied.';}catch{message='Copy is unavailable. Select the note text and copy it manually.';}}));
    const remove=liteButton(ui,'Delete',{},()=>{confirmDelete.hidden=false;});actions.append(save,copyButton,remove);
    const confirmDelete=ui.e('div',{class:'confirmation'});confirmDelete.hidden=true;confirmDelete.append(ui.e('p',{},'Delete the saved note and discard this page’s draft?'),liteButton(ui,'Delete note',{},()=>perform(async()=>{await notes.remove();confirmDelete.hidden=true;message='Note deleted.';})),liteButton(ui,'Cancel',{},()=>confirmDelete.hidden=true));
    const switching=ui.e('div',{class:'confirmation','data-switch':''});switching.hidden=true;switching.append(ui.e('p',{},'You have an unsaved draft for the previous page.'),liteButton(ui,'Save & switch',{'data-save-switch':''},()=>perform(async()=>{await notes.save();notes.switchPage(window.location.href);message='Previous note saved.';})),liteButton(ui,'Discard & switch',{},()=>{notes.discard();notes.switchPage(window.location.href);message='';refresh();}));
    ui.body.append(page,label,text,actions,confirmDelete,switching,ui.e('p',{class:'note'},'Only text you enter is stored. Notes stay in this userscript manager.'));
    async function perform(action){if(busy)return;busy=true;refresh();try{await action();}catch(error){message=error.message;}finally{busy=false;refresh();}}
    function refresh(){const target=pageKey(window.location.href);if(target!==notes.page)notes.switchPage(target);switching.hidden=target===notes.page;page.textContent=new URL(notes.page).pathname; if(text.value!==notes.draft)text.value=notes.draft;text.disabled=busy;for(const b of ui.body.querySelectorAll('button'))b.disabled=busy;ui.setStatus(message||store.error||(notes.dirty?'Unsaved draft.':'Enter a note and select Save.'));}
    return {refresh};
  }});
}

void startNotes({document,window,storage:GM}).catch(()=>{});
})();