(function () { const BACKEND_URL = "https://script.google.com/macros/s/AKfycby6dBLPx4NxC-5bA7IISjYjaQN75vUCABvtn80yveJP9cWf8i_RTCylE6nkPBXR2Urvbg/exec"; const EXECUTER_ID = "executer"; const WORKING_TEXT = "FORGOTYOU NGINE 1.0 is working"; const RETRY_TEXT = "FORGOTYOU NGINE 1.0 has found a dead end. Calling Sky Sakari, please wait"; const WORKING_DOT_SPEED = 450; const POLL_DELAY = 300; const RETRY_DELAY = 500; const INPUT_FONT = "'Jost', sans-serif"; if (window.__forgotyouSearchAbort) { window.__forgotyouSearchAbort.abort(); } const abort = new AbortController(); window.__forgotyouSearchAbort = abort; function waitForEverything() { if ( !window.FORGOTYOU_DISPLAY || !window.FORGOTYOU_SEARCH_HELPERS ) { setTimeout( waitForEverything, 50 ); return; } start(); } function start() { const display = window.FORGOTYOU_DISPLAY; const helpers = window.FORGOTYOU_SEARCH_HELPERS; const executer = document.getElementById( EXECUTER_ID ); if (!executer) { console.error( "Could not find #executer" ); return; } let form = null; if ( executer.tagName && executer.tagName.toLowerCase() === "form" ) { form = executer; } else { form = executer.querySelector( "form" ); } const input = executer.matches && executer.matches( 'input[type="text"], input[type="search"], textarea' ) ? executer : executer.querySelector( 'input[type="text"], input[type="search"], textarea' ); if (!input) { display.setStatus( "Error: No text field found." ); return; } const originalInputStyle = captureInputStyle( input ); installAutofillStyleFix( input, originalInputStyle ); const buttons = Array.from( executer.querySelectorAll( 'button, input[type="submit"], input[type="button"]' ) ); const sendButton = helpers.findSendButton( buttons ); helpers.initializeButton( sendButton ); let searchController = null; let searchRunning = false; let searchSequence = 0; let currentSearchId = null; let workingInterval = null; let pollTimeout = null; let retryTimeout = null; display.setStatus( "Ready" ); input.addEventListener( "input", restoreInputStyleSoon, { signal:abort.signal } ); input.addEventListener( "change", restoreInputStyleSoon, { signal:abort.signal } ); input.addEventListener( "focus", restoreInputStyleSoon, { signal:abort.signal } ); input.addEventListener( "animationstart", restoreInputStyleSoon, { signal:abort.signal } ); if (sendButton) { sendButton.addEventListener( "click", function(event) { if (searchRunning) { event.preventDefault(); event.stopPropagation(); if ( typeof event.stopImmediatePropagation === "function" ) { event.stopImmediatePropagation(); } cancelSearch( true ); return; } if (!form) { event.preventDefault(); executeSearch( input.value ); } }, { signal:abort.signal, capture:true } ); } if (form) { form.addEventListener( "submit", function(event) { event.preventDefault(); if (searchRunning) { return; } executeSearch( input.value ); }, { signal:abort.signal } ); } input.addEventListener( "keydown", function(event) { if ( event.key !== "Enter" ) { return; } if ( input.tagName.toLowerCase() === "textarea" && event.shiftKey ) { return; } if (searchRunning) { event.preventDefault(); return; } if (form) { return; } event.preventDefault(); executeSearch( input.value ); }, { signal:abort.signal } ); abort.signal.addEventListener( "abort", function() { stopWorkingAnimation(); clearPollTimeout(); clearRetryTimeout(); if (searchController) { try { searchController.abort(); } catch (error) { } } }, { once:true } ); function captureInputStyle( element ) { const style = window.getComputedStyle( element ); return { color: style.color, fontSize: style.fontSize, fontWeight: style.fontWeight, fontStyle: style.fontStyle, letterSpacing: style.letterSpacing, lineHeight: style.lineHeight, textAlign: style.textAlign, backgroundColor: style.backgroundColor, caretColor: style.caretColor }; } function restoreInputStyleSoon() { requestAnimationFrame( function() { restoreInputStyle(); setTimeout( restoreInputStyle, 0 ); setTimeout( restoreInputStyle, 50 ); setTimeout( restoreInputStyle, 150 ); } ); } function restoreInputStyle() { input.style.setProperty( "color", originalInputStyle.color, "important" ); input.style.setProperty( "-webkit-text-fill-color", originalInputStyle.color, "important" ); input.style.setProperty( "font-family", INPUT_FONT, "important" ); input.style.setProperty( "font-size", originalInputStyle.fontSize, "important" ); input.style.setProperty( "font-weight", originalInputStyle.fontWeight, "important" ); input.style.setProperty( "font-style", originalInputStyle.fontStyle, "important" ); input.style.setProperty( "letter-spacing", originalInputStyle.letterSpacing, "important" ); input.style.setProperty( "line-height", originalInputStyle.lineHeight, "important" ); input.style.setProperty( "text-align", originalInputStyle.textAlign, "important" ); input.style.setProperty( "caret-color", originalInputStyle.caretColor, "important" ); } function installAutofillStyleFix( element, style ) { const old = document.getElementById( "forgotyou-autofill-style-fix" ); if (old) { old.remove(); } if (!element.id) { element.id = "forgotyou-search-input"; } const escapedId = CSS.escape( element.id ); const sheet = document.createElement( "style" ); sheet.id = "forgotyou-autofill-style-fix"; sheet.textContent = ` #${escapedId}:-webkit-autofill, #${escapedId}:-webkit-autofill:hover, #${escapedId}:-webkit-autofill:focus, #${escapedId}:-webkit-autofill:active { -webkit-text-fill-color:${style.color} !important; font-family:${INPUT_FONT} !important; font-size:${style.fontSize} !important; font-weight:${style.fontWeight} !important; font-style:${style.fontStyle} !important; letter-spacing:${style.letterSpacing} !important; line-height:${style.lineHeight} !important; text-align:${style.textAlign} !important; caret-color:${style.caretColor} !important; -webkit-box-shadow:0 0 0 1000px ${style.backgroundColor} inset !important; box-shadow:0 0 0 1000px ${style.backgroundColor} inset !important; transition:background-color 999999s ease-out 0s !important; } `; document.head.appendChild( sheet ); } async function executeSearch( rawQuery ) { const query = String( rawQuery || "" ) .trim(); if (!query) { display.setStatus( "Type something first." ); return; } if (searchRunning) { return; } if ( !BACKEND_URL || BACKEND_URL.indexOf( "YOUR_GOOGLE_APPS_SCRIPT" ) !== -1 ) { display.setStatus( "Backend URL has not been configured." ); return; } searchRunning = true; searchSequence++; const thisSearch = searchSequence; currentSearchId = null; searchController = new AbortController(); helpers.setCancelButton( sendButton ); if ( typeof display.startLiveSearch === "function" ) { display.startLiveSearch( query ); } else { display.clearImage(); } startWorkingAnimation( WORKING_TEXT ); try { const data = await requestJSONWith404Retry( buildStartURL( query ), searchController.signal ); if ( thisSearch !== searchSequence ) { return; } if ( !data || data.success !== true || !data.searchId ) { throw new Error( data && data.error ? data.error : "Could not start search." ); } currentSearchId = data.searchId; console.log( "FORGOTYOU live search started:", data ); await runPollingLoop( thisSearch, searchController.signal ); } catch (error) { if ( error && error.name === "AbortError" ) { return; } if ( thisSearch !== searchSequence ) { return; } stopWorkingAnimation(); console.error( error ); display.setStatus( "Could not reach the backend.\n\n" + String( error && error.message ? error.message : error ) ); if ( typeof display.failLiveSearch === "function" ) { display.failLiveSearch( error ); } else { display.clearImage(); } } finally { if ( thisSearch === searchSequence ) { stopWorkingAnimation(); clearPollTimeout(); clearRetryTimeout(); searchRunning = false; searchController = null; currentSearchId = null; helpers.restoreSendButton( sendButton ); } } } async function runPollingLoop( thisSearch, signal ) { while ( thisSearch === searchSequence && !signal.aborted ) { await waitForPoll( POLL_DELAY, signal ); if ( thisSearch !== searchSequence ) { return; } const data = await requestJSONWith404Retry( buildPollURL( currentSearchId ), signal ); if ( thisSearch !== searchSequence ) { return; } console.log( "FORGOTYOU live poll:", data ); if (!data) { continue; } handleLiveEvent( data ); if ( data.status === "complete" ) { stopWorkingAnimation(); if ( data.result && data.result.success === true ) { if ( typeof display.showHit === "function" ) { display.showHit( data.event || null, data.result ); } else { display.showResult( data.result ); } } else { throw new Error( "Search completed without a usable result." ); } return; } if ( data.status === "failed" ) { stopWorkingAnimation(); const message = data.error || ( data.result && data.result.error ) || "No matching character found."; display.setStatus( message ); if ( typeof display.failLiveSearch === "function" ) { display.failLiveSearch( data ); } else { display.clearImage(); } return; } if ( data.status === "expired" ) { throw new Error( data.error || "Search session expired." ); } } } function handleLiveEvent( data ) { const event = data.event; if (!event) { return; } if ( event.type === "candidate" ) { if ( typeof display.addCandidate === "function" ) { display.addCandidate( event, data ); } return; } if ( event.type === "candidate_rejected" ) { if ( typeof display.rejectCandidate === "function" ) { display.rejectCandidate( event, data ); } return; } } function buildStartURL( query ) { return ( BACKEND_URL + "?action=start" + "&q=" + encodeURIComponent( query ) + "&_=" + Date.now() + "&nonce=" + Math.random() .toString(36) .slice(2) ); } function buildPollURL( searchId ) { return ( BACKEND_URL + "?action=poll" + "&searchId=" + encodeURIComponent( searchId ) + "&_=" + Date.now() + "&nonce=" + Math.random() .toString(36) .slice(2) ); } function buildCancelURL( searchId ) { return ( BACKEND_URL + "?action=cancel" + "&searchId=" + encodeURIComponent( searchId ) + "&_=" + Date.now() ); } async function requestJSONWith404Retry( url, signal ) { let response = await fetch( url, { method:"GET", cache:"no-store", signal:signal } ); if ( response.status === 404 ) { startWorkingAnimation( RETRY_TEXT ); await waitForRetry( RETRY_DELAY, signal ); response = await fetch( url + "&retryNonce=" + Math.random() .toString(36) .slice(2), { method:"GET", cache:"no-store", signal:signal } ); if (searchRunning) { startWorkingAnimation( WORKING_TEXT ); } } if (!response.ok) { throw new Error( "Backend HTTP " + response.status ); } const data = await response.json(); if ( data && data.success === false && ( data.status === "failed" || data.status === "expired" ) ) { return data; } if ( data && data.success === false ) { throw new Error( data.error || "Backend request failed." ); } return data; } function startWorkingAnimation( text ) { stopWorkingAnimation(); let dots = 1; display.setStatus( text + "." ); workingInterval = setInterval( function() { dots++; if (dots > 3) { dots = 1; } display.setStatus( text + ".".repeat( dots ) ); }, WORKING_DOT_SPEED ); } function stopWorkingAnimation() { if ( workingInterval !== null ) { clearInterval( workingInterval ); workingInterval = null; } } function waitForPoll( milliseconds, signal ) { return new Promise( function(resolve,reject) { if (signal.aborted) { const error = new Error( "Search aborted" ); error.name = "AbortError"; reject( error ); return; } pollTimeout = setTimeout( function() { pollTimeout = null; resolve(); }, milliseconds ); signal.addEventListener( "abort", function() { clearPollTimeout(); const error = new Error( "Search aborted" ); error.name = "AbortError"; reject( error ); }, { once:true } ); } ); } function clearPollTimeout() { if ( pollTimeout !== null ) { clearTimeout( pollTimeout ); pollTimeout = null; } } function waitForRetry( milliseconds, signal ) { return new Promise( function(resolve,reject) { if (signal.aborted) { const error = new Error( "Search aborted" ); error.name = "AbortError"; reject( error ); return; } retryTimeout = setTimeout( function() { retryTimeout = null; resolve(); }, milliseconds ); signal.addEventListener( "abort", function() { clearRetryTimeout(); const error = new Error( "Search aborted" ); error.name = "AbortError"; reject( error ); }, { once:true } ); } ); } function clearRetryTimeout() { if ( retryTimeout !== null ) { clearTimeout( retryTimeout ); retryTimeout = null; } } function cancelSearch( showMessage ) { if (!searchRunning) { return; } const searchId = currentSearchId; searchSequence++; searchRunning = false; stopWorkingAnimation(); clearPollTimeout(); clearRetryTimeout(); const controller = searchController; searchController = null; currentSearchId = null; if (controller) { try { controller.abort(); } catch (error) { } } if (searchId) { fetch( buildCancelURL( searchId ), { method:"GET", cache:"no-store" } ) .catch( function() { } ); } helpers.restoreSendButton( sendButton ); if ( typeof display.cancelLiveSearch === "function" ) { display.cancelLiveSearch(); } if (showMessage) { display.setStatus( "Search cancelled." ); } } } if ( document.readyState === "loading" ) { document.addEventListener( "DOMContentLoaded", waitForEverything, { once:true } ); } else { waitForEverything(); } })();
(function () { const CANCEL_BACKGROUND = "#ff2b2b"; const CANCEL_TEXT_COLOR = "#ffffff"; const CANCEL_BORDER_COLOR = "#ff2b2b"; let originalButtonState = null; function initializeButton( button ) { originalButtonState = captureButtonState( button ); } function setCancelButton( button ) { if (!button) { return; } setButtonText( button, "Cancel" ); button.disabled = false; button.style.background = CANCEL_BACKGROUND; button.style.backgroundColor = CANCEL_BACKGROUND; button.style.color = CANCEL_TEXT_COLOR; button.style.borderColor = CANCEL_BORDER_COLOR; button.style.opacity = "1"; button.style.cursor = "pointer"; button.style.pointerEvents = "auto"; } function restoreSendButton( button ) { if ( !button || !originalButtonState ) { return; } setButtonText( button, originalButtonState.text ); button.disabled = originalButtonState.disabled; button.style.background = originalButtonState.background; button.style.backgroundColor = originalButtonState.backgroundColor; button.style.color = originalButtonState.color; button.style.borderColor = originalButtonState.borderColor; button.style.opacity = originalButtonState.opacity; button.style.cursor = originalButtonState.cursor; button.style.pointerEvents = originalButtonState.pointerEvents; } function captureButtonState( button ) { if (!button) { return { text:"Send", disabled:false, background:"", backgroundColor:"", color:"", borderColor:"", opacity:"", cursor:"", pointerEvents:"" }; } return { text: getButtonText( button ), disabled: button.disabled, background: button.style.background, backgroundColor: button.style.backgroundColor, color: button.style.color, borderColor: button.style.borderColor, opacity: button.style.opacity, cursor: button.style.cursor, pointerEvents: button.style.pointerEvents }; } function findSendButton( buttonList ) { if ( !buttonList || !buttonList.length ) { return null; } for ( let i = 0; i < buttonList.length; i++ ) { const button = buttonList[i]; if ( button.matches( 'button[type="submit"], input[type="submit"]' ) ) { return button; } } return buttonList[0]; } function getButtonText( button ) { if (!button) { return "Send"; } if ( button.tagName.toLowerCase() === "input" ) { return ( button.value || "Send" ); } return ( button.textContent || "Send" ); } function setButtonText( button, text ) { if (!button) { return; } if ( button.tagName.toLowerCase() === "input" ) { button.value = text; return; } button.textContent = text; } window.FORGOTYOU_SEARCH_HELPERS = { initializeButton: initializeButton, setCancelButton: setCancelButton, restoreSendButton: restoreSendButton, findSendButton: findSendButton, getButtonText: getButtonText, setButtonText: setButtonText }; })();
(function () { const LOGS_ID = "logs"; const INFO_DISPLAY_ID = "infodisplay"; const LOG_PADDING_TOP = 24; const LOG_PADDING_RIGHT = 24; const LOG_PADDING_BOTTOM = 24; const LOG_PADDING_LEFT = 24; const NORMAL_LOG_COLOR = "#ffffff"; const CATEGORY_FONT = "AneroRegular"; const CATEGORY_SCALE = 0.90; const COLON_REGULAR_FONT = "AneroRegular"; const COLON_OUTLINE_FONT = "Anerooutline"; const COLON_BLINK_SPEED = 900; const CANDIDATE_GAP = 2; const CANDIDATE_BACKGROUND = "#000000"; const CANDIDATE_TRANSITION = 250; const REJECTED_OPACITY = 0.38; const FINAL_MAIN_WIDTH = 66; const FINAL_SIDE_WIDTH = 34; const FINAL_GAP = 2; const FINAL_SIDE_COLUMNS = 2; const FINAL_TRANSITION = 400; if (window.__forgotyouDisplayAbort) { window.__forgotyouDisplayAbort.abort(); } const abort = new AbortController(); window.__forgotyouDisplayAbort = abort; [ "forgotyou-logs-overlay", "forgotyou-image-overlay", "forgotyou-category-font-style", "forgotyou-live-display-style" ].forEach( function(id) { const old = document.getElementById( id ); if (old) { old.remove(); } } ); const categoryStyle = document.createElement( "style" ); categoryStyle.id = "forgotyou-category-font-style"; categoryStyle.textContent = ` #forgotyou-logs-overlay .forgotyou-category-label { font-family:AneroRegular !important; font-size:${CATEGORY_SCALE}em !important; font-weight:400 !important; font-style:normal !important; } #forgotyou-logs-overlay .forgotyou-category-colon { font-size:${CATEGORY_SCALE}em !important; font-weight:400 !important; font-style:normal !important; } `; document.head.appendChild( categoryStyle ); const liveStyle = document.createElement( "style" ); liveStyle.id = "forgotyou-live-display-style"; liveStyle.textContent = ` #forgotyou-image-overlay { box-sizing:border-box !important; } #forgotyou-image-overlay * { box-sizing:border-box !important; } .forgotyou-live-grid { position:absolute; inset:0; display:grid; background:${CANDIDATE_BACKGROUND}; gap:${CANDIDATE_GAP}px; overflow:hidden; } .forgotyou-candidate { position:relative; display:block; width:100%; height:100%; min-width:0; min-height:0; overflow:hidden; background:${CANDIDATE_BACKGROUND}; opacity:1; transform:scale(1); cursor:default !important; transition: opacity ${CANDIDATE_TRANSITION}ms ease, transform ${CANDIDATE_TRANSITION}ms ease, filter ${CANDIDATE_TRANSITION}ms ease; } .forgotyou-candidate.entering { opacity:0; transform:scale(.90); } .forgotyou-candidate.rejected { opacity:${REJECTED_OPACITY}; filter:grayscale(.75); } .forgotyou-candidate.hit { opacity:1; filter:none; transform:scale(1); } .forgotyou-candidate img { position:absolute; inset:0; display:block; width:100%; height:100%; object-fit:cover; object-position:center; cursor:default !important; pointer-events:none !important; } .forgotyou-candidate-placeholder { position:absolute; inset:0; display:flex; align-items:center; justify-content:center; padding:8px; background:#000000; color:#ffffff; font-family:'Jost',sans-serif; font-size:11px; font-weight:400; line-height:1.2; text-align:center; overflow:hidden; pointer-events:none !important; } .forgotyou-final-layout { position:absolute; inset:0; display:flex; width:100%; height:100%; gap:${FINAL_GAP}px; overflow:hidden; background:#000000; opacity:0; transition:opacity ${FINAL_TRANSITION}ms ease; } .forgotyou-final-layout.visible { opacity:1; } .forgotyou-final-main { position:relative; flex:0 0 calc(${FINAL_MAIN_WIDTH}% - ${FINAL_GAP / 2}px); height:100%; overflow:hidden; background:#000000; cursor:default !important; } .forgotyou-final-main img { display:block; width:100%; height:100%; object-fit:cover; object-position:center; cursor:default !important; pointer-events:none !important; } .forgotyou-final-side { position:relative; flex:0 0 calc(${FINAL_SIDE_WIDTH}% - ${FINAL_GAP / 2}px); height:100%; min-width:0; display:grid; grid-template-columns:repeat(${FINAL_SIDE_COLUMNS},1fr); grid-auto-rows:1fr; gap:${FINAL_GAP}px; overflow:hidden; background:#000000; } .forgotyou-final-thumb { position:relative; min-width:0; min-height:0; overflow:hidden; background:#000000; cursor:default !important; } .forgotyou-final-thumb img { display:block; width:100%; height:100%; object-fit:cover; object-position:center; cursor:default !important; pointer-events:none !important; } `; document.head.appendChild( liveStyle ); function start() { const logsElement = document.getElementById( LOGS_ID ); const infoElement = document.getElementById( INFO_DISPLAY_ID ); if (!logsElement) { console.error( "Could not find #logs" ); return; } if (!infoElement) { console.error( "Could not find #infodisplay" ); return; } const logsOverlay = document.createElement( "div" ); logsOverlay.id = "forgotyou-logs-overlay"; logsOverlay.style.cssText = ` position:fixed; z-index:2147483646; box-sizing:border-box; pointer-events:none; color:${NORMAL_LOG_COLOR}; font-family:Arial,sans-serif; font-size:16px; font-weight:400; line-height:1.45; white-space:pre-wrap; overflow-wrap:anywhere; word-break:break-word; padding:${LOG_PADDING_TOP}px ${LOG_PADDING_RIGHT}px ${LOG_PADDING_BOTTOM}px ${LOG_PADDING_LEFT}px; overflow:auto; background:transparent; `; document.body.appendChild( logsOverlay ); const imageOverlay = document.createElement( "div" ); imageOverlay.id = "forgotyou-image-overlay"; imageOverlay.style.cssText = ` position:fixed; z-index:2147483645; display:block; overflow:hidden; background:transparent; opacity:0; pointer-events:none; transition:opacity 250ms ease; `; document.body.appendChild( imageOverlay ); let animationFrame = null; let colonBlinkInterval = null; let colonOutline = false; let currentMode = "empty"; let candidateGrid = null; let candidateTiles = new Map(); let candidateOrder = []; let currentResult = null; function syncPositions() { const logsRect = logsElement.getBoundingClientRect(); const infoRect = infoElement.getBoundingClientRect(); logsOverlay.style.left = logsRect.left + "px"; logsOverlay.style.top = logsRect.top + "px"; logsOverlay.style.width = logsRect.width + "px"; logsOverlay.style.height = logsRect.height + "px"; imageOverlay.style.left = infoRect.left + "px"; imageOverlay.style.top = infoRect.top + "px"; imageOverlay.style.width = infoRect.width + "px"; imageOverlay.style.height = infoRect.height + "px"; logsOverlay.style.display = logsRect.width > 0 && logsRect.height > 0 ? "block" : "none"; imageOverlay.style.display = infoRect.width > 0 && infoRect.height > 0 ? "block" : "none"; } function forceCategoryFonts() { const labels = logsOverlay.querySelectorAll( ".forgotyou-category-label" ); labels.forEach( function(label) { label.style.setProperty( "font-family", CATEGORY_FONT, "important" ); label.style.setProperty( "font-size", CATEGORY_SCALE + "em", "important" ); label.style.setProperty( "font-weight", "400", "important" ); label.style.setProperty( "font-style", "normal", "important" ); } ); const colons = logsOverlay.querySelectorAll( ".forgotyou-category-colon" ); colons.forEach( function(colon) { colon.style.setProperty( "font-family", colonOutline ? COLON_OUTLINE_FONT : COLON_REGULAR_FONT, "important" ); colon.style.setProperty( "font-size", CATEGORY_SCALE + "em", "important" ); colon.style.setProperty( "font-weight", "400", "important" ); colon.style.setProperty( "font-style", "normal", "important" ); } ); } function startColonBlink() { if (colonBlinkInterval !== null) { return; } colonOutline = false; forceCategoryFonts(); colonBlinkInterval = setInterval( function() { colonOutline = !colonOutline; forceCategoryFonts(); }, COLON_BLINK_SPEED ); } function stopColonBlink() { if ( colonBlinkInterval !== null ) { clearInterval( colonBlinkInterval ); colonBlinkInterval = null; } } function loop() { syncPositions(); forceCategoryFonts(); animationFrame = requestAnimationFrame( loop ); } syncPositions(); loop(); startColonBlink(); abort.signal.addEventListener( "abort", function() { if (animationFrame) { cancelAnimationFrame( animationFrame ); } stopColonBlink(); logsOverlay.remove(); imageOverlay.remove(); [ "forgotyou-category-font-style", "forgotyou-live-display-style" ].forEach( function(id) { const style = document.getElementById( id ); if (style) { style.remove(); } } ); }, { once:true } ); function clearImage() { currentMode = "empty"; currentResult = null; candidateGrid = null; candidateTiles = new Map(); candidateOrder = []; imageOverlay.innerHTML = ""; imageOverlay.style.opacity = "0"; imageOverlay.style.pointerEvents = "none"; } function startLiveSearch() { currentMode = "searching"; currentResult = null; candidateTiles = new Map(); candidateOrder = []; imageOverlay.innerHTML = ""; imageOverlay.style.opacity = "1"; imageOverlay.style.pointerEvents = "none"; candidateGrid = document.createElement( "div" ); candidateGrid.className = "forgotyou-live-grid"; imageOverlay.appendChild( candidateGrid ); updateCandidateGrid(); } function addCandidate( event ) { if ( !event || !event.candidate ) { return; } if ( currentMode !== "searching" ) { startLiveSearch(); } const candidate = String( event.candidate ); if ( candidateTiles.has( candidate ) ) { return; } const tile = document.createElement( "div" ); tile.className = "forgotyou-candidate entering"; tile.dataset.candidate = candidate; const imageURL = event.image || event.thumbnail || null; if (imageURL) { const img = document.createElement( "img" ); img.alt = event.name || candidate; img.draggable = false; img.src = imageURL; img.onerror = function() { img.remove(); addCandidatePlaceholder( tile, event.name || candidate ); }; tile.appendChild( img ); } else { addCandidatePlaceholder( tile, event.name || candidate ); } candidateTiles.set( candidate, tile ); candidateOrder.push( candidate ); candidateGrid.appendChild( tile ); updateCandidateGrid(); requestAnimationFrame( function() { requestAnimationFrame( function() { tile.classList.remove( "entering" ); } ); } ); } function addCandidatePlaceholder( tile, name ) { const placeholder = document.createElement( "div" ); placeholder.className = "forgotyou-candidate-placeholder"; placeholder.textContent = String( name || "" ) .replace( /_/g, " " ) .trim(); tile.appendChild( placeholder ); } function updateCandidateGrid() { if (!candidateGrid) { return; } const count = Math.max( 1, candidateOrder.length ); const dimension = Math.ceil( Math.sqrt( count ) ); candidateGrid.style.gridTemplateColumns = "repeat(" + dimension + ", 1fr)"; candidateGrid.style.gridTemplateRows = "repeat(" + dimension + ", 1fr)"; } function rejectCandidate( event ) { if ( !event || !event.candidate ) { return; } const tile = candidateTiles.get( String( event.candidate ) ); if (!tile) { return; } tile.classList.add( "rejected" ); } function normalizeGallery( gallery, mainImage, data ) { const output = []; const seen = new Set(); function add( item ) { if (!item) { return; } let normalized; if ( typeof item === "string" ) { normalized = { image:item, thumbnail:item, furtrackURL: data.furtrackURL || null }; } else { normalized = { image: item.image || item.thumbnail || null, thumbnail: item.thumbnail || item.image || null, furtrackURL: item.furtrackURL || data.furtrackURL || null, postId: item.postId || null }; } const url = normalized.image || normalized.thumbnail; if (!url) { return; } if ( mainImage && url === mainImage ) { return; } if ( seen.has( url ) ) { return; } seen.add( url ); output.push( normalized ); } gallery.forEach( add ); return output; } function renderFinalLayout( mainImage, gallery, data, character ) { imageOverlay.innerHTML = ""; candidateGrid = null; imageOverlay.style.opacity = "1"; imageOverlay.style.pointerEvents = "none"; const layout = document.createElement( "div" ); layout.className = "forgotyou-final-layout"; const main = document.createElement( "div" ); main.className = "forgotyou-final-main"; if (mainImage) { const mainImg = document.createElement( "img" ); mainImg.alt = character && character.name ? character.name : "FORGOTYOU result"; mainImg.draggable = false; mainImg.src = mainImage; main.appendChild( mainImg ); } else { const placeholder = document.createElement( "div" ); placeholder.className = "forgotyou-candidate-placeholder"; placeholder.textContent = character && character.name ? character.name : "HIT"; main.appendChild( placeholder ); } const side = document.createElement( "div" ); side.className = "forgotyou-final-side"; gallery.forEach( function(item) { const imageURL = item.image || item.thumbnail || null; if (!imageURL) { return; } const thumb = document.createElement( "div" ); thumb.className = "forgotyou-final-thumb"; const img = document.createElement( "img" ); img.alt = character && character.name ? character.name : "FORGOTYOU gallery image"; img.draggable = false; img.src = imageURL; thumb.appendChild( img ); side.appendChild( thumb ); } ); layout.appendChild( main ); layout.appendChild( side ); imageOverlay.appendChild( layout ); requestAnimationFrame( function() { requestAnimationFrame( function() { layout.classList.add( "visible" ); } ); } ); } window.FORGOTYOU_DISPLAY_CORE = { abort: abort, logsOverlay: logsOverlay, imageOverlay: imageOverlay, clearImage: clearImage, startLiveSearch: startLiveSearch, addCandidate: addCandidate, rejectCandidate: rejectCandidate, normalizeGallery: normalizeGallery, renderFinalLayout: renderFinalLayout, forceCategoryFonts: forceCategoryFonts, getCurrentMode: function() { return currentMode; }, setCurrentMode: function(value) { currentMode = value; }, getCurrentResult: function() { return currentResult; }, setCurrentResult: function(value) { currentResult = value; }, getCandidateTiles: function() { return candidateTiles; } }; } if ( document.readyState === "loading" ) { document.addEventListener( "DOMContentLoaded", start, { once:true } ); } else { start(); } })();
(function () { const NORMAL_LOG_COLOR = "#ffffff"; const SOCIAL_LINK_COLOR = "#4da6ff"; const CATEGORY_FONT = "AneroRegular"; const CATEGORY_SCALE = 0.90; const COLON_REGULAR_FONT = "AneroRegular"; const COLON_OUTLINE_FONT = "Anerooutline"; function waitForCore() { if ( !window.FORGOTYOU_DISPLAY_CORE ) { setTimeout( waitForCore, 50 ); return; } start(); } function start() { const core = window.FORGOTYOU_DISPLAY_CORE; const logsOverlay = core.logsOverlay; let colonOutline = false; function setStatus( text ) { logsOverlay.style.pointerEvents = "none"; logsOverlay.style.color = NORMAL_LOG_COLOR; logsOverlay.textContent = String( text || "" ); } function clearImage() { core.clearImage(); } function startLiveSearch( query ) { core.startLiveSearch( query ); } function addCandidate( event, data ) { core.addCandidate( event, data ); } function rejectCandidate( event, data ) { core.rejectCandidate( event, data ); } function showHit( event, data ) { if ( !data || data.success !== true ) { return; } core.setCurrentMode( "hit" ); core.setCurrentResult( data ); const character = data.character || {}; const profile = data.profile || {}; const selectedCandidate = data.match && data.match.selectedCandidate ? String( data.match.selectedCandidate ) : event && event.candidate ? String( event.candidate ) : null; if (selectedCandidate) { const tiles = core.getCandidateTiles(); if ( tiles.has( selectedCandidate ) ) { const winningTile = tiles.get( selectedCandidate ); winningTile.classList.remove( "rejected" ); winningTile.classList.add( "hit" ); } } renderResultLogsFromData( data ); const mainImage = event && ( event.image || event.thumbnail ) ? ( event.image || event.thumbnail ) : ( profile.image || profile.thumbnail || null ); let gallery = event && Array.isArray( event.gallery ) ? event.gallery : Array.isArray( data.gallery ) ? data.gallery : []; gallery = core.normalizeGallery( gallery, mainImage, data ); setTimeout( function() { if ( core.getCurrentMode() !== "hit" || core.getCurrentResult() !== data ) { return; } core.renderFinalLayout( mainImage, gallery, data, character ); }, 180 ); } function showResult( data ) { showHit( null, data ); } function failLiveSearch() { core.clearImage(); } function cancelLiveSearch() { core.clearImage(); } function renderResultLogsFromData( data ) { const character = data.character || {}; const name = character.name || character.rawName || "Unknown character"; const imageCount = Number( character.imageCount || 0 ); const species = Array.isArray( data.species ) ? data.species : []; const makers = Array.isArray( data.makers ) ? data.makers : []; const generalTags = Array.isArray( data.generalTags ) ? data.generalTags : []; const socials = Array.isArray( data.socials ) ? data.socials : []; const photoWord = imageCount === 1 ? "photo" : "photos"; const successLine = "FORGOTYOU NGINE 1.0 has successfully extracted " + imageCount + " " + photoWord + " from public databases."; renderResultLogs( successLine, { name:name, species:species, makers:makers, generalTags:generalTags }, socials ); } function createCategoryLabel( text ) { const label = document.createElement( "span" ); label.className = "forgotyou-category-label"; label.textContent = text; label.style.setProperty( "font-family", CATEGORY_FONT, "important" ); label.style.setProperty( "font-size", CATEGORY_SCALE + "em", "important" ); label.style.setProperty( "font-weight", "400", "important" ); label.style.setProperty( "font-style", "normal", "important" ); label.style.setProperty( "color", NORMAL_LOG_COLOR, "important" ); return label; } function createColon() { const colon = document.createElement( "span" ); colon.className = "forgotyou-category-colon"; colon.textContent = ":"; colon.style.setProperty( "font-family", colonOutline ? COLON_OUTLINE_FONT : COLON_REGULAR_FONT, "important" ); colon.style.setProperty( "font-size", CATEGORY_SCALE + "em", "important" ); colon.style.setProperty( "font-weight", "400", "important" ); colon.style.setProperty( "font-style", "normal", "important" ); colon.style.setProperty( "color", NORMAL_LOG_COLOR, "important" ); return colon; } function appendCategory( container, text ) { container.appendChild( createCategoryLabel( text ) ); container.appendChild( createColon() ); container.appendChild( document.createTextNode( " " ) ); } function renderResultLogs( successLine, infoData, socials ) { logsOverlay.innerHTML = ""; logsOverlay.style.pointerEvents = "auto"; const success = document.createElement( "div" ); success.textContent = successLine; success.style.color = NORMAL_LOG_COLOR; logsOverlay.appendChild( success ); const spacer = document.createElement( "div" ); spacer.style.height = "12px"; logsOverlay.appendChild( spacer ); const info = document.createElement( "div" ); appendCategory( info, "Found" ); const characterName = document.createElement( "span" ); characterName.textContent = formatDisplayName( infoData.name ) + "."; info.appendChild( characterName ); if ( infoData.species.length ) { info.appendChild( document.createElement( "br" ) ); appendCategory( info, "Species" ); const speciesValue = document.createElement( "span" ); speciesValue.textContent = infoData.species .map( formatDisplayName ) .join(", "); info.appendChild( speciesValue ); } if ( infoData.makers.length ) { info.appendChild( document.createElement( "br" ) ); appendCategory( info, "Maker" ); const makerValue = document.createElement( "span" ); makerValue.textContent = infoData.makers .map( formatDisplayName ) .join(", "); info.appendChild( makerValue ); } if ( infoData.generalTags.length ) { info.appendChild( document.createElement( "br" ) ); appendCategory( info, "Tags" ); const tagsValue = document.createElement( "span" ); tagsValue.textContent = infoData.generalTags .map( formatDisplayName ) .join(", "); info.appendChild( tagsValue ); } logsOverlay.appendChild( info ); if ( socials && socials.length ) { const socialContainer = document.createElement( "div" ); socialContainer.style.marginTop = "12px"; const title = document.createElement( "div" ); appendCategory( title, "Socials" ); socialContainer.appendChild( title ); socials.forEach( function(social) { if ( !social || !social.app || !social.id ) { return; } const row = document.createElement( "div" ); appendCategory( row, social.app ); const socialURL = buildSocialURL( social.app, social.id ); if (socialURL) { const link = document.createElement( "a" ); link.textContent = social.id; link.href = socialURL; link.target = "_blank"; link.rel = "noopener noreferrer"; link.style.color = SOCIAL_LINK_COLOR; link.style.textDecoration = "underline"; link.style.cursor = "pointer"; link.style.pointerEvents = "auto"; row.appendChild( link ); } else { const username = document.createElement( "span" ); username.textContent = social.id; username.style.color = NORMAL_LOG_COLOR; row.appendChild( username ); } socialContainer.appendChild( row ); } ); logsOverlay.appendChild( socialContainer ); } core.forceCategoryFonts(); } function buildSocialURL( app, id ) { const platform = String( app || "" ) .toLowerCase() .trim(); let username = String( id || "" ) .trim(); if (!username) { return null; } if ( /^https?:\/\//i.test( username ) ) { return username; } if ( username.charAt(0) === "@" ) { username = username.slice( 1 ); } if ( platform === "twitter" || platform === "x" || platform.indexOf( "twitter" ) !== -1 ) { return ( "https://x.com/" + encodeURIComponent( username ) ); } if ( platform === "bluesky" || platform === "bsky" || platform.indexOf( "bluesky" ) !== -1 ) { return ( "https://bsky.app/profile/" + encodeURIComponent( username ) ); } if ( platform === "instagram" || platform.indexOf( "instagram" ) !== -1 ) { return ( "https://www.instagram.com/" + encodeURIComponent( username ) + "/" ); } if ( platform === "tiktok" || platform.indexOf( "tiktok" ) !== -1 ) { return ( "https://www.tiktok.com/@" + encodeURIComponent( username ) ); } if ( platform === "threads" || platform.indexOf( "threads" ) !== -1 ) { return ( "https://www.threads.net/@" + encodeURIComponent( username ) ); } if ( platform === "telegram" || platform.indexOf( "telegram" ) !== -1 ) { return ( "https://t.me/" + encodeURIComponent( username ) ); } if ( platform === "youtube" || platform.indexOf( "youtube" ) !== -1 ) { return ( "https://www.youtube.com/@" + encodeURIComponent( username ) ); } if ( platform === "mastodon" || platform.indexOf( "mastodon" ) !== -1 ) { const parts = username.split( "@" ); if ( parts.length === 2 && parts[0] && parts[1] ) { return ( "https://" + parts[1] + "/@" + encodeURIComponent( parts[0] ) ); } } return null; } function formatDisplayName( value ) { return String( value || "" ) .replace( /_/g, " " ) .trim(); } window.FORGOTYOU_DISPLAY = { setStatus: setStatus, showResult: showResult, clearImage: clearImage, startLiveSearch: startLiveSearch, addCandidate: addCandidate, rejectCandidate: rejectCandidate, showHit: showHit, failLiveSearch: failLiveSearch, cancelLiveSearch: cancelLiveSearch }; } waitForCore(); })();
(function () { const EXECUTER_ID = "executer"; const SEND_BUTTON_FONT = "AneroRegular"; if (window.__forgotyouSavedKeywordsAbort) { window.__forgotyouSavedKeywordsAbort.abort(); } const abort = new AbortController(); window.__forgotyouSavedKeywordsAbort = abort; function start() { const executer = document.getElementById( EXECUTER_ID ); if (!executer) { console.error( "Could not find #executer" ); return; } const input = executer.querySelector( 'input[type="text"], input[type="search"], textarea' ); if (!input) { console.error( "Could not find the #executer textbox" ); return; } /* Apply AneroRegular to the Send button. */ const sendButton = executer.querySelector( 'button, input[type="submit"], input[type="button"]' ); if (sendButton) { sendButton.style.setProperty( "font-family", SEND_BUTTON_FONT, "important" ); sendButton.style.setProperty( "font-weight", "400", "important" ); sendButton.style.setProperty( "font-style", "normal", "important" ); } /* Keep forcing the font in case Carrd or another script changes the button. */ function forceSendButtonFont() { const button = executer.querySelector( 'button, input[type="submit"], input[type="button"]' ); if (!button) { return; } button.style.setProperty( "font-family", SEND_BUTTON_FONT, "important" ); button.style.setProperty( "font-weight", "400", "important" ); button.style.setProperty( "font-style", "normal", "important" ); } forceSendButtonFont(); const fontInterval = setInterval( forceSendButtonFont, 250 ); abort.signal.addEventListener( "abort", function() { clearInterval( fontInterval ); }, { once:true } ); document.addEventListener( "click", function(event) { const keywordButton = event.target.closest( "[data-keyword]" ); if (!keywordButton) { return; } const keyword = String( keywordButton.getAttribute( "data-keyword" ) || "" ).trim(); if (!keyword) { return; } event.preventDefault(); setInputValue( input, keyword ); }, { signal:abort.signal } ); } function setInputValue( input, value ) { const prototype = Object.getPrototypeOf( input ); const descriptor = Object.getOwnPropertyDescriptor( prototype, "value" ); if ( descriptor && typeof descriptor.set === "function" ) { descriptor.set.call( input, value ); } else { input.value = value; } input.dispatchEvent( new Event( "input", { bubbles:true } ) ); input.dispatchEvent( new Event( "change", { bubbles:true } ) ); input.focus(); const length = String( value ).length; if ( typeof input.setSelectionRange === "function" ) { input.setSelectionRange( length, length ); } } if ( document.readyState === "loading" ) { document.addEventListener( "DOMContentLoaded", start, { once:true } ); } else { start(); } })();
(function () { if (window.__displayOutlineCleanup) { window.__displayOutlineCleanup(); } const IMAGE_DISPLAY_ID = "infodisplay"; const LOGS_ID = "logs"; const EXECUTER_ID = "executer"; const OUTLINE_COLOR = "#ffffff"; const OUTLINE_WIDTH = 2; const CUT_FILL_COLOR = "#000000"; const CUT_SIZE = 16; /* Thick extrusion ONLY for the outside left/right edges. */ const SIDE_EXTRUDE_X = 8; /* Thin internal outline: left side of #executer connects to left side of #logs. */ const INNER_OUTLINE_WIDTH = 2; /* Fine X positioning. Negative = left Positive = right */ const INNER_EXECUTER_OFFSET = -1; const INNER_LOGS_OFFSET = -1; const TOP_OFFSET = -1; const BOTTOM_OFFSET = -1; const LEFT_OFFSET = -1; const RIGHT_OFFSET = -1; let outline = null; let svg = null; let polygon = null; let innerSvg = null; let innerPath = null; let observer = null; let frame = null; function removeOutline() { if (outline) { outline.remove(); outline = null; svg = null; polygon = null; } if (innerSvg) { innerSvg.remove(); innerSvg = null; innerPath = null; } } function createOutline() { removeOutline(); outline = document.createElement( "div" ); outline.id = "display-extended-outline"; outline.style.cssText = ` position:fixed; pointer-events:none; background:transparent; z-index:2147483647; overflow:visible; `; svg = document.createElementNS( "http://www.w3.org/2000/svg", "svg" ); svg.style.cssText = ` position:absolute; left:0; top:0; width:100%; height:100%; overflow:visible; pointer-events:none; `; polygon = document.createElementNS( "http://www.w3.org/2000/svg", "polygon" ); polygon.setAttribute( "fill", "none" ); polygon.setAttribute( "stroke", OUTLINE_COLOR ); polygon.setAttribute( "stroke-width", OUTLINE_WIDTH ); polygon.setAttribute( "vector-effect", "non-scaling-stroke" ); polygon.setAttribute( "stroke-linejoin", "miter" ); svg.appendChild( polygon ); outline.appendChild( svg ); document.body.appendChild( outline ); /* Separate full-screen SVG for the thin executer/logs outline. */ innerSvg = document.createElementNS( "http://www.w3.org/2000/svg", "svg" ); innerSvg.id = "display-inner-outline"; innerSvg.style.cssText = ` position:fixed; left:0; top:0; width:100vw; height:100vh; overflow:visible; pointer-events:none; z-index:2147483647; `; innerPath = document.createElementNS( "http://www.w3.org/2000/svg", "path" ); innerPath.setAttribute( "fill", "none" ); innerPath.setAttribute( "stroke", OUTLINE_COLOR ); innerPath.setAttribute( "stroke-width", INNER_OUTLINE_WIDTH ); innerPath.setAttribute( "vector-effect", "non-scaling-stroke" ); innerPath.setAttribute( "stroke-linejoin", "miter" ); innerPath.setAttribute( "stroke-linecap", "square" ); innerSvg.appendChild( innerPath ); document.body.appendChild( innerSvg ); } function createFilledPolygon( className, points, color ) { const shape = document.createElementNS( "http://www.w3.org/2000/svg", "polygon" ); shape.setAttribute( "class", className ); shape.setAttribute( "points", points .map(function(point) { return ( point[0] + "," + point[1] ); }) .join(" ") ); shape.setAttribute( "fill", color ); shape.setAttribute( "stroke", "none" ); svg.insertBefore( shape, polygon ); } function updatePolygon( width, height ) { if ( !polygon || !svg ) { return; } svg .querySelectorAll( ".display-generated-shape" ) .forEach(function(element) { element.remove(); }); const halfStroke = OUTLINE_WIDTH / 2; const cut = Math.min( CUT_SIZE, width / 2, height / 2 ); const left = halfStroke; const top = halfStroke; const right = Math.max( halfStroke, width - halfStroke ); const bottom = Math.max( halfStroke, height - halfStroke ); const outlinePoints = [ [ left + cut, top ], [ right - cut, top ], [ right, top + cut ], [ right, bottom - cut ], [ right - cut, bottom ], [ left + cut, bottom ], [ left, bottom - cut ], [ left, top + cut ] ]; polygon.setAttribute( "points", outlinePoints .map(function(point) { return ( point[0] + "," + point[1] ); }) .join(" ") ); /* Black chamfer fills. */ createFilledPolygon( "display-generated-shape", [ [0, 0], [cut, 0], [0, cut] ], CUT_FILL_COLOR ); createFilledPolygon( "display-generated-shape", [ [width, 0], [width - cut, 0], [width, cut] ], CUT_FILL_COLOR ); createFilledPolygon( "display-generated-shape", [ [width, height], [width - cut, height], [width, height - cut] ], CUT_FILL_COLOR ); createFilledPolygon( "display-generated-shape", [ [0, height], [cut, height], [0, height - cut] ], CUT_FILL_COLOR ); /* Outside side extrusion. */ if (SIDE_EXTRUDE_X > 0) { /* LEFT */ createFilledPolygon( "display-generated-shape", [ [ left + cut, top ], [ left, top + cut ], [ left, bottom - cut ], [ left + cut, bottom ], [ left + cut - SIDE_EXTRUDE_X, bottom ], [ left - SIDE_EXTRUDE_X, bottom - cut ], [ left - SIDE_EXTRUDE_X, top + cut ], [ left + cut - SIDE_EXTRUDE_X, top ] ], OUTLINE_COLOR ); /* RIGHT */ createFilledPolygon( "display-generated-shape", [ [ right - cut, top ], [ right, top + cut ], [ right, bottom - cut ], [ right - cut, bottom ], [ right - cut + SIDE_EXTRUDE_X, bottom ], [ right + SIDE_EXTRUDE_X, bottom - cut ], [ right + SIDE_EXTRUDE_X, top + cut ], [ right - cut + SIDE_EXTRUDE_X, top ] ], OUTLINE_COLOR ); } } function updateInnerOutline() { if (!innerPath) { return; } const executer = document.getElementById( EXECUTER_ID ); const logs = document.getElementById( LOGS_ID ); if ( !executer || !logs ) { innerPath.setAttribute( "d", "" ); return; } const execRect = executer.getBoundingClientRect(); const logsRect = logs.getBoundingClientRect(); /* LEFT edge of #executer. */ const execX = execRect.left + INNER_EXECUTER_OFFSET; const execTop = execRect.top; const execBottom = execRect.bottom; /* LEFT edge of #logs. */ const logsX = logsRect.left + INNER_LOGS_OFFSET; const logsTop = logsRect.top; const logsBottom = logsRect.bottom; /* Continuous thin line: left side of executer ↓ bottom-left of executer → / diagonal connection top-left of logs ↓ bottom-left of logs */ const path = [ "M", execX, execTop, "L", execX, execBottom, "L", logsX, logsTop, "L", logsX, logsBottom ].join(" "); innerPath.setAttribute( "d", path ); } function updateOutline() { if (!outline) { return; } const imageDisplay = document.getElementById( IMAGE_DISPLAY_ID ); const logs = document.getElementById( LOGS_ID ); if ( !imageDisplay || !logs ) { console.log( "FORGOTYOU border missing IDs:", { infodisplay:!!imageDisplay, logs:!!logs } ); return; } const imageRect = imageDisplay.getBoundingClientRect(); const logsRect = logs.getBoundingClientRect(); const left = Math.min( imageRect.left, logsRect.left ) + LEFT_OFFSET; const right = Math.max( imageRect.right, logsRect.right ) - RIGHT_OFFSET; const top = Math.min( imageRect.top, logsRect.top ) + TOP_OFFSET; const bottom = Math.max( imageRect.bottom, logsRect.bottom ) - BOTTOM_OFFSET; const width = Math.max( 0, right - left ); const height = Math.max( 0, bottom - top ); outline.style.left = left + "px"; outline.style.top = top + "px"; outline.style.width = width + "px"; outline.style.height = height + "px"; updatePolygon( width, height ); updateInnerOutline(); } function scheduleUpdate() { if (frame) { cancelAnimationFrame( frame ); } frame = requestAnimationFrame(function () { frame = null; updateOutline(); }); } function start() { const imageDisplay = document.getElementById( IMAGE_DISPLAY_ID ); const logs = document.getElementById( LOGS_ID ); const executer = document.getElementById( EXECUTER_ID ); if ( !imageDisplay || !logs ) { console.error( "FORGOTYOU border: Could not find #infodisplay or #logs.", { infodisplay:!!imageDisplay, logs:!!logs } ); return; } createOutline(); updateOutline(); observer = new ResizeObserver( scheduleUpdate ); observer.observe( imageDisplay ); observer.observe( logs ); if (executer) { observer.observe( executer ); } window.addEventListener( "resize", scheduleUpdate ); window.addEventListener( "scroll", scheduleUpdate, true ); setTimeout( scheduleUpdate, 100 ); setTimeout( scheduleUpdate, 500 ); setTimeout( scheduleUpdate, 1000 ); setTimeout( scheduleUpdate, 2000 ); window.__displayOutlineCleanup = function () { removeOutline(); if (observer) { observer.disconnect(); observer = null; } if (frame) { cancelAnimationFrame( frame ); frame = null; } window.removeEventListener( "resize", scheduleUpdate ); window.removeEventListener( "scroll", scheduleUpdate, true ); }; } if ( document.readyState === "loading" ) { document.addEventListener( "DOMContentLoaded", start, { once:true } ); } else { start(); } })();
(function () { const EXECUTER_ID = "executer"; const CUT_SIZE = 15; const CUT_COLOR = "#ff1493"; const STYLE_ID = "forgotyou-send-corner-style"; function start() { const executer = document.getElementById( EXECUTER_ID ); if (!executer) { return; } const button = executer.querySelector( 'button, input[type="submit"], input[type="button"]' ); if (!button) { return; } /* Give the button a unique class. Nothing is wrapped or moved. */ button.classList.add( "forgotyou-send-cut" ); /* Remove old version if script is executed again. */ const old = document.getElementById( STYLE_ID ); if (old) { old.remove(); } const style = document.createElement( "style" ); style.id = STYLE_ID; style.textContent = ` #${EXECUTER_ID} { position:relative !important; } /* Pink triangle positioned directly over the Send button's top-left corner. Does NOT affect layout. */ #${EXECUTER_ID} .forgotyou-send-cut { position:relative !important; } /* Cut the actual button corner. */ #${EXECUTER_ID} .forgotyou-send-cut { clip-path: polygon( ${CUT_SIZE}px 0, 100% 0, 100% 100%, 0 100%, 0 ${CUT_SIZE}px ) !important; -webkit-clip-path: polygon( ${CUT_SIZE}px 0, 100% 0, 100% 100%, 0 100%, 0 ${CUT_SIZE}px ) !important; } `; document.head.appendChild( style ); /* Create the pink triangle separately so Carrd's button structure is never modified. */ let triangle = document.getElementById( "forgotyou-send-pink-corner" ); if (triangle) { triangle.remove(); } triangle = document.createElement( "div" ); triangle.id = "forgotyou-send-pink-corner"; triangle.style.cssText = ` position:fixed; width:${CUT_SIZE}px; height:${CUT_SIZE}px; background:${CUT_COLOR}; clip-path:polygon( 0 0, 100% 0, 0 100% ); -webkit-clip-path:polygon( 0 0, 100% 0, 0 100% ); pointer-events:none; z-index:2147483645; `; document.body.appendChild( triangle ); function positionTriangle() { const r = button.getBoundingClientRect(); triangle.style.left = r.left + "px"; triangle.style.top = r.top + "px"; } /* Keep it locked to the button. */ let frame; function update() { positionTriangle(); frame = requestAnimationFrame( update ); } update(); window.__forgotyouSendCornerCleanup = function () { if (frame) { cancelAnimationFrame(frame); } triangle.remove(); style.remove(); button.classList.remove( "forgotyou-send-cut" ); }; } if ( document.readyState === "loading" ) { document.addEventListener( "DOMContentLoaded", start, { once:true } ); } else { start(); } })();
(function () { const TARGET_TEXT = "FORGOTYOU"; const TARGET_FONT = "AneroRegular"; const ENGINE_FONT = "AneroRegular"; const VERSION_NUMBER_FONT = "AneroRegular"; const VERSION_DOT_REGULAR_FONT = "AneroRegular"; const VERSION_DOT_OUTLINE_FONT = "Anerooutline"; const PINK_COLOR = "#ff1493"; const WHITE_COLOR = "#ffffff"; const SIZE_MULTIPLIER = 1.00; const LETTER_SCALE = 1.05; const CENTER_BOX_SCALE = 0.80; const CENTER_BOX_X = 0.7; const CENTER_BOX_Y = -0.4; const CENTER_BOX_RADIUS = 2; const Y_ADJUST = 0; const OTHER_LOGO_SCALE = 1.05; const OTHER_LOGO_Y_ADJUST = 0.5; /* #title spacing. These preserve your current title exactly. */ const TITLE_RIGHT_GAP = -0.37; const TITLE_VERSION_GAP = -0.38; /* All logos OUTSIDE #title. Increase these to create more space. Example: -0.15 = more gap 0.00 = even more gap 0.10 = larger gap */ const OTHER_RIGHT_GAP = -0.25; const OTHER_VERSION_GAP = -0.25; const ENGINE_TEXT = "NGINE"; const VERSION_TEXT = "1.0"; const CYCLE_SPEED = 900; const CLASS_NAME = "forgotyou-stacked-text"; const ENGINE_CLASS = "forgotyou-engine-text"; const VERSION_CLASS = "forgotyou-version-text"; const VERSION_NUMBER_CLASS = "forgotyou-version-number"; const VERSION_DOT_CLASS = "forgotyou-version-dot"; const VERSION_DOT_OUTLINE_CLASS = "forgotyou-version-dot-outline"; const CENTER_BOX_CLASS = "forgotyou-center-box-cell"; if ( window.__forgotyouFontObserver ) { window.__forgotyouFontObserver.disconnect(); window.__forgotyouFontObserver = null; } if ( window.__forgotyouResizeHandler ) { window.removeEventListener( "resize", window.__forgotyouResizeHandler ); window.__forgotyouResizeHandler = null; } if ( window.__forgotyouColorTimer ) { clearInterval( window.__forgotyouColorTimer ); window.__forgotyouColorTimer = null; } if ( window.__forgotyouDotTimer ) { clearInterval( window.__forgotyouDotTimer ); window.__forgotyouDotTimer = null; } const oldStyle = document.getElementById( "forgotyou-stacked-font-style" ); if (oldStyle) { oldStyle.remove(); } const style = document.createElement( "style" ); style.id = "forgotyou-stacked-font-style"; style.textContent = ` .${CLASS_NAME} { display:inline-block; position:relative; width:var(--forgotyou-size); height:var(--forgotyou-size); padding:0; margin: 0 var(--forgotyou-right-gap, ${TITLE_RIGHT_GAP}em) 0 0; vertical-align:baseline; transform: translateY( calc( var(--forgotyou-descent) + ${Y_ADJUST}px + var(--forgotyou-extra-y, 0px) ) ); overflow:visible; white-space:nowrap; } .${CLASS_NAME} .forgotyou-grid { position:absolute; left:0; bottom:0; display:grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(3, 1fr); width:100%; height:100%; padding:0; margin:0; gap:0; font-family: ${TARGET_FONT} !important; } .${CLASS_NAME} .forgotyou-letter { display:flex; align-items:center; justify-content:center; position:relative; width:100%; height:100%; min-width:0; min-height:0; box-sizing:border-box; padding:0; margin:0; font-family: ${TARGET_FONT} !important; font-size: calc( (var(--forgotyou-size) / 3) * ${LETTER_SCALE} ) !important; font-style:normal !important; font-variant:normal !important; font-weight:400 !important; line-height:1 !important; text-align:center; text-decoration:none !important; text-transform:none !important; text-shadow:none !important; -webkit-text-stroke: 0 !important; transition:none !important; animation:none !important; } .${CLASS_NAME} .forgotyou-pink { color: ${PINK_COLOR} !important; -webkit-text-fill-color: ${PINK_COLOR} !important; } .${CLASS_NAME} .forgotyou-white { color: ${WHITE_COLOR} !important; -webkit-text-fill-color: ${WHITE_COLOR} !important; } .${CLASS_NAME} .${CENTER_BOX_CLASS} { position:relative !important; display:block !important; width:100% !important; height:100% !important; padding:0 !important; margin:0 !important; overflow:visible !important; pointer-events:none !important; } .${CLASS_NAME} .forgotyou-center-square { position:absolute !important; left:50% !important; top:50% !important; width:100% !important; height:100% !important; background: ${PINK_COLOR} !important; border-radius: ${CENTER_BOX_RADIUS}px !important; padding:0 !important; margin:0 !important; border:0 !important; outline:0 !important; box-sizing:border-box !important; transform-origin: 50% 50% !important; transform: translate( calc(-50% + ${CENTER_BOX_X}px), calc(-50% + ${CENTER_BOX_Y}px) ) scale( ${CENTER_BOX_SCALE} ) !important; transition:none !important; animation:none !important; pointer-events:none !important; } .${CLASS_NAME} .forgotyou-center-square.forgotyou-square-pink { background: ${PINK_COLOR} !important; } .${CLASS_NAME} .forgotyou-center-square.forgotyou-square-white { background: ${WHITE_COLOR} !important; } .${ENGINE_CLASS} { display:inline !important; font-family: ${ENGINE_FONT} !important; font-style:normal !important; font-variant:normal !important; font-weight:400 !important; font-stretch:normal !important; color: ${WHITE_COLOR} !important; -webkit-text-fill-color: ${WHITE_COLOR} !important; letter-spacing:inherit !important; word-spacing:0 !important; line-height:inherit !important; text-decoration:none !important; text-transform:none !important; text-shadow:none !important; -webkit-text-stroke: 0 !important; transition:none !important; animation:none !important; } .${VERSION_CLASS} { display:inline-block; margin-left: var(--forgotyou-version-gap, ${TITLE_VERSION_GAP}em) !important; color: ${PINK_COLOR} !important; -webkit-text-fill-color: ${PINK_COLOR} !important; letter-spacing:inherit !important; line-height:inherit !important; text-decoration:none !important; text-transform:none !important; text-shadow:none !important; -webkit-text-stroke: 0 !important; } .${VERSION_CLASS} .${VERSION_NUMBER_CLASS} { display:inline !important; font-family: ${VERSION_NUMBER_FONT} !important; font-style:normal !important; font-variant:normal !important; font-weight:400 !important; color: ${PINK_COLOR} !important; -webkit-text-fill-color: ${PINK_COLOR} !important; transition:none !important; animation:none !important; } .${VERSION_CLASS} .${VERSION_DOT_CLASS} { display:inline !important; font-family: ${VERSION_DOT_REGULAR_FONT} !important; font-style:normal !important; font-variant:normal !important; font-weight:400 !important; color: ${PINK_COLOR} !important; -webkit-text-fill-color: ${PINK_COLOR} !important; transition:none !important; animation:none !important; } .${VERSION_CLASS} .${VERSION_DOT_CLASS}.${VERSION_DOT_OUTLINE_CLASS} { font-family: ${VERSION_DOT_OUTLINE_FONT} !important; } `; document.head.appendChild( style ); function createStackedText( text ) { const wrapper = document.createElement( "span" ); wrapper.className = CLASS_NAME; const grid = document.createElement( "span" ); grid.className = "forgotyou-grid"; text .split("") .forEach(function ( letter, index ) { const cell = document.createElement( "span" ); cell.className = "forgotyou-letter"; if ( index === 4 ) { cell.classList.add( CENTER_BOX_CLASS ); const square = document.createElement( "span" ); square.className = "forgotyou-center-square forgotyou-square-pink"; cell.appendChild( square ); } else { cell.textContent = letter; if ( index % 2 === 0 ) { cell.classList.add( "forgotyou-pink" ); } else { cell.classList.add( "forgotyou-white" ); } } grid.appendChild( cell ); }); wrapper.appendChild( grid ); return wrapper; } function syncCenterSquare( block ) { const firstLetter = block.querySelector( ".forgotyou-letter:not(." + CENTER_BOX_CLASS + ")" ); const square = block.querySelector( ".forgotyou-center-square" ); if ( !firstLetter || !square ) { return; } if ( firstLetter.classList.contains( "forgotyou-pink" ) ) { square.classList.remove( "forgotyou-square-white" ); square.classList.add( "forgotyou-square-pink" ); } else { square.classList.remove( "forgotyou-square-pink" ); square.classList.add( "forgotyou-square-white" ); } } function syncDotToForgotyou() { const firstBlock = document.querySelector( "." + CLASS_NAME ); if (!firstBlock) { return; } const firstLetter = firstBlock.querySelector( ".forgotyou-letter:not(." + CENTER_BOX_CLASS + ")" ); if (!firstLetter) { return; } const dots = document.querySelectorAll( "." + VERSION_DOT_CLASS ); const shouldOutline = firstLetter.classList.contains( "forgotyou-pink" ); dots.forEach(function ( dot ) { dot.classList.toggle( VERSION_DOT_OUTLINE_CLASS, shouldOutline ); }); } function swapColors() { const blocks = document.querySelectorAll( "." + CLASS_NAME ); blocks.forEach(function ( block ) { const letters = block.querySelectorAll( ".forgotyou-letter:not(." + CENTER_BOX_CLASS + ")" ); letters.forEach(function ( letter ) { if ( letter.classList.contains( "forgotyou-pink" ) ) { letter.classList.remove( "forgotyou-pink" ); letter.classList.add( "forgotyou-white" ); } else { letter.classList.remove( "forgotyou-white" ); letter.classList.add( "forgotyou-pink" ); } }); syncCenterSquare( block ); }); syncDotToForgotyou(); } function createEngineText( text ) { const span = document.createElement( "span" ); span.className = ENGINE_CLASS; span.textContent = text; span.style.setProperty( "font-family", ENGINE_FONT, "important" ); span.style.setProperty( "font-style", "normal", "important" ); span.style.setProperty( "font-weight", "400", "important" ); span.style.setProperty( "color", WHITE_COLOR, "important" ); span.style.setProperty( "-webkit-text-fill-color", WHITE_COLOR, "important" ); span.style.setProperty( "-webkit-text-stroke", "0", "important" ); return span; } function createVersionText( text ) { const span = document.createElement( "span" ); span.className = VERSION_CLASS; text .split("") .forEach(function ( character ) { const characterSpan = document.createElement( "span" ); if ( character === "." ) { characterSpan.className = VERSION_DOT_CLASS; } else { characterSpan.className = VERSION_NUMBER_CLASS; } characterSpan.textContent = character; span.appendChild( characterSpan ); }); return span; } function processTextNode( textNode ) { if (!textNode) { return; } const parent = textNode.parentElement; if (!parent) { return; } if ( parent.closest( "." + CLASS_NAME ) || parent.closest( "." + ENGINE_CLASS ) || parent.closest( "." + VERSION_CLASS ) ) { return; } if ( parent.closest( "script, style, textarea, input" ) ) { return; } const text = textNode.nodeValue; if (!text) { return; } const upper = text.toUpperCase(); const hasForgotyou = upper.includes( TARGET_TEXT ); const hasEngine = upper.includes( ENGINE_TEXT ); const hasVersion = text.includes( VERSION_TEXT ); if ( !hasForgotyou && !hasEngine && !hasVersion ) { return; } const regex = new RegExp( "(" + TARGET_TEXT + "|" + ENGINE_TEXT + "|" + VERSION_TEXT.replace( ".", "\\." ) + ")", "gi" ); const parts = text.split( regex ); if ( parts.length <= 1 ) { return; } const fragment = document.createDocumentFragment(); parts.forEach(function ( part ) { if ( part.toUpperCase() === TARGET_TEXT ) { fragment.appendChild( createStackedText( part ) ); } else if ( part.toUpperCase() === ENGINE_TEXT ) { fragment.appendChild( createEngineText( part ) ); } else if ( part === VERSION_TEXT ) { fragment.appendChild( createVersionText( part ) ); } else { fragment.appendChild( document.createTextNode( part ) ); } }); textNode.replaceWith( fragment ); } function getFontString( element ) { const computed = window.getComputedStyle( element ); return [ computed.fontStyle, computed.fontVariant, computed.fontWeight, computed.fontSize, computed.fontFamily ].join(" "); } function measureTextHeight( element ) { const computed = window.getComputedStyle( element ); const canvas = document.createElement( "canvas" ); const context = canvas.getContext( "2d" ); context.font = getFontString( element ); const metrics = context.measureText( "ENGINE 1.0" ); let ascent = metrics.actualBoundingBoxAscent; let descent = metrics.actualBoundingBoxDescent; if ( !Number.isFinite(ascent) || ascent <= 0 ) { ascent = parseFloat( computed.fontSize ) * 0.8; } if ( !Number.isFinite(descent) || descent < 0 ) { descent = parseFloat( computed.fontSize ) * 0.2; } const height = ( ascent + descent ) * SIZE_MULTIPLIER; return { height: height, descent: descent * SIZE_MULTIPLIER }; } function updateSizes() { const title = document.getElementById( "title" ); const blocks = document.querySelectorAll( "." + CLASS_NAME ); blocks.forEach(function ( block ) { const parent = block.parentElement; if (!parent) { return; } const measurement = measureTextHeight( parent ); const isTitle = title && title.contains( block ); const scale = isTitle ? 1 : OTHER_LOGO_SCALE; block.style.setProperty( "--forgotyou-size", ( measurement.height * scale ) + "px" ); block.style.setProperty( "--forgotyou-descent", ( measurement.descent * scale ) + "px" ); block.style.setProperty( "--forgotyou-extra-y", isTitle ? "0px" : OTHER_LOGO_Y_ADJUST + "px" ); block.style.setProperty( "--forgotyou-right-gap", isTitle ? TITLE_RIGHT_GAP + "em" : OTHER_RIGHT_GAP + "em" ); const parentElement = block.parentElement; if (parentElement) { const version = findFollowingVersion( block ); if (version) { version.style.setProperty( "--forgotyou-version-gap", isTitle ? TITLE_VERSION_GAP + "em" : OTHER_VERSION_GAP + "em" ); } } }); } function findFollowingVersion( block ) { let node = block.nextSibling; while (node) { if ( node.nodeType === Node.ELEMENT_NODE && node.classList.contains( VERSION_CLASS ) ) { return node; } node = node.nextSibling; } return null; } function scan( root ) { if (!root) { return; } if ( root.nodeType === Node.TEXT_NODE ) { processTextNode( root ); return; } if ( root.nodeType !== Node.ELEMENT_NODE && root.nodeType !== Node.DOCUMENT_NODE ) { return; } const walker = document.createTreeWalker( root, NodeFilter.SHOW_TEXT ); const nodes = []; while ( walker.nextNode() ) { nodes.push( walker.currentNode ); } nodes.forEach( processTextNode ); updateSizes(); } function start() { scan( document.body ); syncDotToForgotyou(); window.__forgotyouColorTimer = setInterval( swapColors, CYCLE_SPEED ); const observer = new MutationObserver(function ( mutations ) { let needsUpdate = false; mutations.forEach(function ( mutation ) { if ( mutation.type === "characterData" ) { processTextNode( mutation.target ); needsUpdate = true; return; } mutation.addedNodes.forEach(function ( node ) { scan( node ); needsUpdate = true; }); }); if (needsUpdate) { requestAnimationFrame( function () { updateSizes(); syncDotToForgotyou(); } ); } }); observer.observe( document.body, { childList:true, subtree:true, characterData:true } ); window.__forgotyouFontObserver = observer; const resizeHandler = function () { requestAnimationFrame( updateSizes ); }; window.__forgotyouResizeHandler = resizeHandler; window.addEventListener( "resize", resizeHandler ); if ( document.fonts && document.fonts.ready ) { document.fonts.ready.then(function () { updateSizes(); syncDotToForgotyou(); setTimeout( updateSizes, 100 ); setTimeout( updateSizes, 500 ); }); } } if ( document.readyState === "loading" ) { document.addEventListener( "DOMContentLoaded", start, { once:true } ); } else { start(); } })();
(function(){ const ID="executer"; const REG="AneroRegular"; const OUT="Anerooutline"; /* Entire FORGOTYOU NGINE 1.0 scale. 1.00 = original 0.95 = 5% smaller 0.92 = 8% smaller 0.90 = 10% smaller */ const ENTIRE_LOGO_SCALE=.82; /* Lower ONLY NGINE + 1.0. 0 = original 1 = slightly lower 2 = lower 3 = even lower Negative values move it upward. */ const ENGINE_VERSION_Y=0.9; /* 3x3 FORGOTYOU block proportions. */ const LOGO_SCALE=1.05; const LETTER_SCALE=1.05; const BOX_SCALE=.80; const BOX_X=.7; const BOX_Y=-.4; const BOX_RADIUS=2; const BOX_BORDER=1.5; /* FORGOTYOU -> NGINE gap. */ const RIGHT_GAP=-.00; /* NGINE -> 1.0 gap. */ const VERSION_GAP=-.25; const Y_ADJUST=.5; const SPEED=900; if(window.__fyExecCleanup){ window.__fyExecCleanup(); } let input; let host; let root; let content; let timer; let frame; let ro; let state=false; let placeholder=""; let color=""; function getInput(){ const el= document.getElementById(ID); if(!el)return null; if( el.matches && el.matches( 'input[type="text"],input[type="search"],textarea' ) ){ return el; } return el.querySelector( 'input[type="text"],input[type="search"],textarea' ); } function isOutline(i){ const group= i===0|| i===2|| i===6|| i===8; return state ?group :!group; } function makeHost(){ host= document.createElement("div"); host.id= "fy-exec-shadow-host"; host.style.cssText=` position:fixed; z-index:2147483646; pointer-events:none; overflow:hidden; box-sizing:border-box; background:transparent; `; document.body.appendChild(host); root= host.attachShadow({ mode:"open" }); const style= document.createElement("style"); style.textContent=` :host{ color:${color}; } .content{ display:inline-block; position:relative; white-space:pre; color:${color}; -webkit-text-fill-color:${color}; } .brand{ display:inline-block; transform: scale(${ENTIRE_LOGO_SCALE}); transform-origin: left center; vertical-align:baseline; margin-right: calc( (1 - ${ENTIRE_LOGO_SCALE}) * -100% ); } .logo{ display:inline-block; position:relative; width:var(--size); height:var(--size); margin: 0 ${RIGHT_GAP}em 0 0; vertical-align:baseline; transform: translateY( calc( var(--desc) + ${Y_ADJUST}px ) ); } .grid{ position:absolute; left:0; bottom:0; width:100%; height:100%; display:grid; grid-template-columns: repeat(3,1fr); grid-template-rows: repeat(3,1fr); } .letter{ display:flex; align-items:center; justify-content:center; position:relative; width:100%; height:100%; padding:0; margin:0; font-size: calc( (var(--size) / 3) * ${LETTER_SCALE} ); font-weight:400; font-style:normal; line-height:1; color:${color}; -webkit-text-fill-color: ${color}; -webkit-text-stroke:0; } .reg{ font-family:${REG}; } .out{ font-family:${OUT}; } .box{ position:absolute; left:50%; top:50%; width:100%; height:100%; box-sizing:border-box; border-radius: ${BOX_RADIUS}px; transform: translate( calc(-50% + ${BOX_X}px), calc(-50% + ${BOX_Y}px) ) scale( ${BOX_SCALE} ); } .fill{ background:${color}; border: ${BOX_BORDER}px solid ${color}; } .boxout{ background:transparent; border: ${BOX_BORDER}px solid ${color}; } /* NGINE display:inline-block is important so translateY can move it. */ .engine{ display:inline-block; font-family:${REG}; font-weight:400; font-style:normal; color:${color}; -webkit-text-fill-color: ${color}; -webkit-text-stroke:0; transform: translateY( ${ENGINE_VERSION_Y}px ); } /* 1.0 Uses the same Y offset as NGINE. */ .version{ display:inline-block; margin-left: ${VERSION_GAP}em; color:${color}; -webkit-text-fill-color: ${color}; transform: translateY( ${ENGINE_VERSION_Y}px ); } .num{ font-family:${REG}; font-weight:400; color:${color}; -webkit-text-fill-color: ${color}; } .dot{ font-weight:400; color:${color}; -webkit-text-fill-color: ${color}; } .dotreg{ font-family:${REG}; } .dotout{ font-family:${OUT}; } `; content= document.createElement("span"); content.className= "content"; root.appendChild(style); root.appendChild(content); } function makeLogo(){ const logo= document.createElement("span"); logo.className="logo"; const grid= document.createElement("span"); grid.className="grid"; "FORGOTYOU" .split("") .forEach(function(ch,i){ const cell= document.createElement("span"); cell.className="letter"; if(i===4){ const box= document.createElement("span"); box.className= "box "+ ( isOutline(0) ?"boxout" :"fill" ); cell.appendChild(box); }else{ cell.textContent=ch; cell.classList.add( isOutline(i) ?"out" :"reg" ); } grid.appendChild(cell); }); logo.appendChild(grid); return logo; } function makeBrand(){ const brand= document.createElement("span"); brand.className="brand"; brand.appendChild( makeLogo() ); const engine= document.createElement("span"); engine.className= "engine"; engine.textContent= "NGINE"; brand.appendChild( engine ); brand.appendChild( document.createTextNode(" ") ); const version= document.createElement("span"); version.className= "version"; ["1",".","0"] .forEach(function(ch){ const el= document.createElement("span"); if(ch==="."){ el.className= "dot "+ ( isOutline(0) ?"dotreg" :"dotout" ); }else{ el.className= "num"; } el.textContent= ch; version.appendChild( el ); }); brand.appendChild( version ); return brand; } function geometry(){ const r= input.getBoundingClientRect(); const c= getComputedStyle(input); Object.assign( host.style, { left: r.left+"px", top: r.top+"px", width: r.width+"px", height: r.height+"px", paddingTop: c.paddingTop, paddingRight: c.paddingRight, paddingBottom: c.paddingBottom, paddingLeft: c.paddingLeft, fontFamily: c.fontFamily, fontSize: c.fontSize, fontWeight: c.fontWeight, fontStyle: c.fontStyle, letterSpacing: c.letterSpacing, lineHeight: c.lineHeight, textAlign: c.textAlign } ); } function sizeLogo(){ const c= getComputedStyle(input); const canvas= document.createElement("canvas"); const ctx= canvas.getContext("2d"); ctx.font=[ c.fontStyle, c.fontVariant, c.fontWeight, c.fontSize, c.fontFamily ].join(" "); const m= ctx.measureText( "ENGINE 1.0" ); const fs= parseFloat( c.fontSize )||16; const a= m.actualBoundingBoxAscent|| fs*.8; const d= m.actualBoundingBoxDescent|| fs*.2; const size= (a+d)* LOGO_SCALE; root .querySelectorAll( ".logo" ) .forEach(function(el){ el.style.setProperty( "--size", size+"px" ); el.style.setProperty( "--desc", (d*LOGO_SCALE)+"px" ); }); } function render(){ geometry(); content.innerHTML= ""; /* When typing, use the real input. */ if(input.value){ host.style.display= "none"; return; } host.style.display= "block"; const re= /FORGOTYOU\s+NGINE\s+1\.0/i; const match= re.exec( placeholder ); if(!match){ content.textContent= placeholder; return; } content.appendChild( document.createTextNode( placeholder.slice( 0, match.index ) ) ); content.appendChild( makeBrand() ); content.appendChild( document.createTextNode( placeholder.slice( match.index+ match[0].length ) ) ); sizeLogo(); } function animate(){ state= !state; root .querySelectorAll( ".letter" ) .forEach(function(el,i){ if(i===4){ const box= el.querySelector( ".box" ); if(!box)return; const o= isOutline(0); box.classList.toggle( "boxout", o ); box.classList.toggle( "fill", !o ); return; } const o= isOutline(i); el.classList.toggle( "out", o ); el.classList.toggle( "reg", !o ); }); const f= isOutline(0); root .querySelectorAll( ".dot" ) .forEach(function(dot){ dot.classList.toggle( "dotreg", f ); dot.classList.toggle( "dotout", !f ); }); } function schedule(){ if(frame){ cancelAnimationFrame( frame ); } frame= requestAnimationFrame( function(){ frame=null; render(); } ); } function cleanup(){ if(timer){ clearInterval( timer ); } if(frame){ cancelAnimationFrame( frame ); } if(ro){ ro.disconnect(); } window.removeEventListener( "resize", schedule ); window.removeEventListener( "scroll", schedule, true ); if(input){ input.setAttribute( "placeholder", placeholder ); } if(host){ host.remove(); } } function start(){ input= getInput(); if(!input){ console.error( "Could not find #executer textbox" ); return; } placeholder= input.getAttribute( "placeholder" )||""; try{ color= getComputedStyle( input, "::placeholder" ).color; }catch(e){ color= getComputedStyle( input ).color; } if( !color || color==="transparent" || color==="rgba(0, 0, 0, 0)" ){ color= getComputedStyle( input ).color; } /* Remove native placeholder. */ input.setAttribute( "placeholder", "" ); makeHost(); render(); input.addEventListener( "input", schedule ); input.addEventListener( "change", schedule ); input.addEventListener( "focus", schedule ); input.addEventListener( "blur", schedule ); window.addEventListener( "resize", schedule ); window.addEventListener( "scroll", schedule, true ); ro= new ResizeObserver( schedule ); ro.observe( input ); timer= setInterval( animate, SPEED ); window.__fyExecCleanup= cleanup; if( document.fonts && document.fonts.ready ){ document.fonts.ready.then( schedule ); } } if( document.readyState=== "loading" ){ document.addEventListener( "DOMContentLoaded", start, { once:true } ); }else{ start(); } })();
(function () { const LOG_FONT = "jost"; const LOG_FONT_SIZE = "18px"; const SKIP_SELECTORS = [ ".forgotyou-stacked-text", ".forgotyou-engine-text", ".forgotyou-version-text", ".forgotyou-version-number", ".forgotyou-version-dot" ].join(","); function applyFontToElement(element) { if (!element) { return; } if ( element.matches && element.matches(SKIP_SELECTORS) ) { return; } element.childNodes.forEach(function (node) { if ( node.nodeType === Node.ELEMENT_NODE ) { if ( node.matches(SKIP_SELECTORS) || node.closest(SKIP_SELECTORS) ) { return; } node.style.setProperty( "font-family", LOG_FONT, "important" ); node.style.setProperty( "font-size", LOG_FONT_SIZE, "important" ); applyFontToElement(node); } }); } function findLogsOverlay() { const logs = document.getElementById("logs"); if (!logs) { return; } const logsRect = logs.getBoundingClientRect(); const candidates = Array.from( document.body.querySelectorAll("*") ); candidates.forEach(function (element) { if ( element === logs || logs.contains(element) ) { return; } if ( element.matches(SKIP_SELECTORS) || element.closest(SKIP_SELECTORS) ) { return; } const style = window.getComputedStyle(element); if ( style.position !== "fixed" && style.position !== "absolute" ) { return; } const rect = element.getBoundingClientRect(); const overlaps = rect.right > logsRect.left && rect.left < logsRect.right && rect.bottom > logsRect.top && rect.top < logsRect.bottom; if (!overlaps) { return; } if ( !element.textContent || !element.textContent.trim() ) { return; } element.style.setProperty( "font-family", LOG_FONT, "important" ); element.style.setProperty( "font-size", LOG_FONT_SIZE, "important" ); applyFontToElement( element ); }); } function update() { findLogsOverlay(); requestAnimationFrame( findLogsOverlay ); } function start() { update(); const observer = new MutationObserver(function () { update(); }); observer.observe( document.body, { childList:true, subtree:true, characterData:true } ); window.__aneroLogsObserver = observer; window.addEventListener( "resize", update ); } if ( document.readyState === "loading" ) { document.addEventListener( "DOMContentLoaded", start, { once:true } ); } else { start(); } })();