From e5b8504bc613497dab5936fe4c1231500c4b6723 Mon Sep 17 00:00:00 2001 From: type-two Date: Fri, 24 Jul 2026 13:47:09 +1000 Subject: [PATCH] =?UTF-8?q?Import=20pliceclogs=20as-is=20=E2=80=94=20the?= =?UTF-8?q?=20original=20Discogs=20seller=20extension?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Snapshot of the working tree exactly as it stood, no edits. This is the predecessor PRICEGOD was rewritten from ("kept intact, untouched" per pricegod/README.md), and it is still the only place the DYMO scale is actually implemented — rfid-daemon/index.js:1068-1265: HID discovery, parseScaleReport, one-shot read, and a streaming /weight + /scale/start|stop session whose JSON shape PRICEGOD's daemon.js already speaks. Preserved verbatim on purpose (hence -og), including the known bug: DYMO_PIDS at index.js:1082 is [0x8003, 0x8004], so it cannot see the bench M25 (0x8009). Fix that in whatever daemon inherits the scale, not here. node_modules stays ignored (22M of the 24M tree). No credentials in the import: the two PEM markers in utils.js/sheets.js only strip headers off a key read from settings, and mrpadmin / johnking are an SSH and a Postgres username, both key/trust auth. Co-Authored-By: Claude Opus 4.8 --- .gitignore | 7 + README.md | 55 + background.js | 1098 ++++ barcode.js | 21 + blagginate-bridge.js | 152 + constants.js | 37 + content.js | 776 +++ deepseek.js | 346 ++ .../plans/2026-04-12-inventory-sku-lookup.md | 680 +++ .../2026-04-12-inventory-sku-lookup-design.md | 167 + fonts/NotoSans-Regular.ttf | Bin 0 -> 569208 bytes gemini.js | 513 ++ label.css | 92 + large.css | 1152 ++++ logo.svg | 10 + manifest.json | 106 + monster_capture.js | 262 + monster_master.js | 231 + popup.html | 1148 ++++ popup.js | 4930 +++++++++++++++++ print.js | 1 + rfid-daemon/diagnostics/compare.sh | 91 + rfid-daemon/diagnostics/known-good-config.txt | 5 + rfid-daemon/index.js | 1439 +++++ rfid-daemon/package-lock.json | 1444 +++++ rfid-daemon/package.json | 17 + rfid-daemon/plice_server.py | 688 +++ rfid-daemon/probe.js | 154 + rfid-daemon/recover.js | 165 + rfid-daemon/start.bat | 7 + rfid-daemon/start.command | 5 + rfid-daemon/start.sh | 6 + rfid-daemon/variants/_core.js | 792 +++ rfid-daemon/variants/broadcast.js | 8 + rfid-daemon/variants/control.js | 8 + rfid-daemon/variants/keepalive.js | 8 + rfid-daemon/variants/log.js | 75 + rfid-daemon/variants/preflight.js | 8 + rfid-daemon/variants/slowpace.js | 8 + sheets.js | 815 +++ small.css | 179 + textlabel.css | 379 ++ ui.js | 444 ++ utils.js | 142 + wp.js | 198 + xlarge.css | 175 + 46 files changed, 19044 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 background.js create mode 100644 barcode.js create mode 100644 blagginate-bridge.js create mode 100644 constants.js create mode 100644 content.js create mode 100644 deepseek.js create mode 100644 docs/superpowers/plans/2026-04-12-inventory-sku-lookup.md create mode 100644 docs/superpowers/specs/2026-04-12-inventory-sku-lookup-design.md create mode 100644 fonts/NotoSans-Regular.ttf create mode 100644 gemini.js create mode 100644 label.css create mode 100644 large.css create mode 100644 logo.svg create mode 100644 manifest.json create mode 100644 monster_capture.js create mode 100644 monster_master.js create mode 100644 popup.html create mode 100644 popup.js create mode 100644 print.js create mode 100755 rfid-daemon/diagnostics/compare.sh create mode 100644 rfid-daemon/diagnostics/known-good-config.txt create mode 100644 rfid-daemon/index.js create mode 100644 rfid-daemon/package-lock.json create mode 100644 rfid-daemon/package.json create mode 100644 rfid-daemon/plice_server.py create mode 100644 rfid-daemon/probe.js create mode 100644 rfid-daemon/recover.js create mode 100644 rfid-daemon/start.bat create mode 100755 rfid-daemon/start.command create mode 100755 rfid-daemon/start.sh create mode 100644 rfid-daemon/variants/_core.js create mode 100644 rfid-daemon/variants/broadcast.js create mode 100644 rfid-daemon/variants/control.js create mode 100644 rfid-daemon/variants/keepalive.js create mode 100644 rfid-daemon/variants/log.js create mode 100644 rfid-daemon/variants/preflight.js create mode 100644 rfid-daemon/variants/slowpace.js create mode 100644 sheets.js create mode 100644 small.css create mode 100644 textlabel.css create mode 100644 ui.js create mode 100644 utils.js create mode 100644 wp.js create mode 100644 xlarge.css diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..43db421 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +.DS_Store +node_modules/ +*.bak +prompt-prep*.txt +pliceclogs-labelcode.txt +__pycache__/ +*.pyc diff --git a/README.md b/README.md new file mode 100644 index 0000000..1db9203 --- /dev/null +++ b/README.md @@ -0,0 +1,55 @@ +This Chrome extension streamlines pricing, inventory management, and label printing for Discogs sellers. It integrates directly with Discogs release pages to automate price tag generation, Google Sheets logging, and price data collection. + +Features + +Core Functionality + • Price Tag Generation: Works on discogs.com/release/ pages. When adding a release to your collection, set media condition, sleeve condition, price, and notes. Clicking the popup button generates a price tag for printing. + • Discogs API Integration: Fetches price suggestions via an authenticated API call. + • Google Sheets Sync: Logs pricing details in a Google Sheet using a service account. + +Label & Sheet Buttons + • Label: Opens a printable price tag. + • Sheet: Logs the release details in Google Sheets. + • Both: Performs both actions simultaneously. + +Label Printing & Customization + • Thermal Printer Support: Designed for generic thermal label printers. + • Dynamic Label Layout: Labels are mapped to Discogs info (artist, genre, etc.), and the container size, div positions, and SVG logo can be adjusted. + • Planned UI Panel: A future update will add a UI settings panel for live preview and customization of label layout, size, and elements. + +Additional Modes + • Average Price Mode: Once a release is logged in the sheet, the extension can fetch the “average price” visible on https://www.discogs.com/sell/post/ (manual HTML load required). + • Global Seller Data Mode: Retrieves pricing data from https://www.discogs.com/sell/release/ for future auto-pricing algorithms (manual HTML load required due to Discogs’ robots.txt restrictions). + +Google Sheets Integration + • Requires a Google Sheets service account for write access. + • A future update will add a UX settings panel to input credentials and auto-generate credentials.json. + +Installation + 1. Install the extension via Chrome Developer Mode. + 2. Navigate to discogs.com/release/ pages to use the popup. + 3. Configure Google Sheets access (for write functionality). + +Future Plans + • UI settings panel for live label customization and preview. + • Automated pricing algorithm using global seller data. + + + + Pricing & Workflow Summary + + 1. Find Release on Discogs → Locate the exact release page. + 2. Add to Collection → Input media condition, sleeve condition, price, notes, and assign to a folder. + 3. Generate Price Label & Log Data: + • Press Popup → Loads price suggestions and saved details. + • Press BOTH → Opens a new window with a printable price label and writes data to Google Sheets. + • Press Label → Prints a new label without writing to Sheets. + • Press Sheet → Writes to Sheets without printing a new label. + 4. Sell a Copy Workflow: + • Click “Sell a Copy” (https://www.discogs.com/sell/post/). + • Popup changes to show average price from Discogs. + • Press Update → Saves the average price to Google Sheets (matching by Release ID). + 5. Global Seller Data: + • Click “Copies for Sale” (https://www.discogs.com/sell/release/). + • Popup updates to show all global sellers’ prices and conditions. + • Press Zap to Sheet → Logs this data to Google Sheets for future auto-pricing algorithms. \ No newline at end of file diff --git a/background.js b/background.js new file mode 100644 index 0000000..52c00de --- /dev/null +++ b/background.js @@ -0,0 +1,1098 @@ +// Shared capture helpers (parseSalesHistoryHtml, parseListingsHtml, +// buildResearchJson, combineReleaseData) — same module the popup loads. +importScripts('monster_capture.js'); + +// ── MV3 keepalive ───────────────────────────────────────────────────── +// chrome.alarms fires even when the service worker is hibernated, waking it. +// Combined with the setInterval pollers below, this keeps PliceCogs's COGS +// proxy poll loop alive indefinitely without needing an open discogs tab. +chrome.alarms.create('plicecogs-keepalive', { periodInMinutes: 0.5 }); +chrome.alarms.onAlarm.addListener(() => { /* wake-only, no work */ }); + +// YouTube Cookie Management + +// BLAGGINATE bridge connection variables +let blagginateTabId = null; +let isBlagginateConnected = false; +let lastBlagginateConnectionAttempt = 0; +let blagginateConnectionAttempts = 0; + +// Listen for YouTube tab updates +chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => { + if (changeInfo.status === 'complete' && tab.url?.includes('youtube.com')) { + chrome.storage.local.get(['autoUpdate'], function(result) { + if (result.autoUpdate === true) { + updateCookies(); + } + }); + } +}); + +function updateCookies() { + console.log('Starting updateCookies function...'); + return new Promise((resolve, reject) => { + try { + chrome.cookies.getAll({ domain: ".youtube.com" }, function(cookies) { + if (chrome.runtime.lastError) { + reject(chrome.runtime.lastError); + return; + } + + console.log(`Found ${cookies.length} cookies`); + + // Format cookies in Netscape format + let cookieText = "# Netscape HTTP Cookie File\n"; + cookieText += "# https://curl.haxx.se/rfc/cookie_spec.html\n"; + cookieText += "# This file was generated by YouTube Cookie Extractor\n\n"; + + cookies.forEach(cookie => { + cookieText += [ + ".youtube.com", + "TRUE", + cookie.path, + cookie.secure ? "TRUE" : "FALSE", + Math.floor(cookie.expirationDate || (Date.now() / 1000) + 31536000), + cookie.name, + cookie.value + ].join('\t') + '\n'; + }); + + // Store cookie text in local storage + chrome.storage.local.set({ + lastCookie: cookieText, + lastUpdate: Date.now() + }, () => { + console.log('Cookie saved to storage'); + + // Push to ytanalyse cookie server if it's running (silently no-ops if not) + fetch('http://localhost:7792/cookies', { + method: 'POST', + headers: { 'Content-Type': 'text/plain' }, + body: cookieText, + }).catch(() => {}); // ytanalyse not running — that's fine + + // Send cookie update to BLAGGINATE page if connected + if (blagginateTabId && isBlagginateConnected) { + chrome.tabs.sendMessage(blagginateTabId, { + type: 'cookieUpdate', + cookies: cookieText, + timestamp: Date.now() + }).catch(error => { + console.log('Failed to send cookie to BLAGGINATE page:', error); + // Reset connection status if tab is no longer available + isBlagginateConnected = false; + blagginateTabId = null; + }); + console.log('Cookie sent to BLAGGINATE page'); + } + + // Resolve with cookie text + resolve({ cookieText: cookieText, success: true }); + }); + }); + } catch (error) { + reject(error); + } + }); +} + +// Build Cookie-Editor / EditThisCookie style JSON array — the format +// JDownloader 2 (and most cookie-importers) expect when pasting cookies. +function getYouTubeCookiesJson() { + return new Promise((resolve, reject) => { + chrome.cookies.getAll({ domain: ".youtube.com" }, (cookies) => { + if (chrome.runtime.lastError) { + reject(chrome.runtime.lastError); + return; + } + const out = cookies.map(c => ({ + domain: c.domain, + expirationDate: c.expirationDate, // omitted for session cookies + hostOnly: !!c.hostOnly, + httpOnly: !!c.httpOnly, + name: c.name, + path: c.path, + // chrome.cookies sameSite: "no_restriction" | "lax" | "strict" | "unspecified" + // Cookie-Editor uses the same vocabulary, so pass through. + sameSite: c.sameSite || "unspecified", + secure: !!c.secure, + session: !!c.session, + storeId: c.storeId || null, + value: c.value + })); + resolve(JSON.stringify(out, null, 2)); + }); + }); +} + +function keepAlive() { + setInterval(() => { + chrome.runtime.getPlatformInfo(() => { + if (chrome.runtime.lastError) { + console.log('Keeping service worker alive'); + } + }); + }, 20000); +} + +// BLAGGINATE bridge connection system +function connectToBlagginate() { + // Check if BLAGGINATE bridge is enabled + chrome.storage.local.get(['blagginateBridge'], (result) => { + if (result.blagginateBridge === false) { + return; // Bridge is disabled, don't attempt connection + } + + const now = Date.now(); + + // Throttle connection attempts and logging + if (now - lastBlagginateConnectionAttempt < 30000) { // 30 seconds + return; + } + + lastBlagginateConnectionAttempt = now; + blagginateConnectionAttempts++; + + // Look for BLAGGINATE page tab + chrome.tabs.query({}, (tabs) => { + const blagginateTab = tabs.find(tab => + tab.url && tab.url.includes('wowplatter-admin-blagginate') + ); + + if (blagginateTab) { + blagginateTabId = blagginateTab.id; + // Test connection by sending a ping + chrome.tabs.sendMessage(blagginateTabId, { + type: 'ping', + timestamp: Date.now() + }).then(() => { + isBlagginateConnected = true; + blagginateConnectionAttempts = 0; // Reset counter on successful connection + console.log('Connected to BLAGGINATE page'); + // Send initial cookie update + updateCookies(); + }).catch(error => { + if (blagginateConnectionAttempts <= 3) { // Only log first 3 attempts + console.log('BLAGGINATE page not ready for communication:', error); + } + isBlagginateConnected = false; + blagginateTabId = null; + }); + } else { + if (blagginateConnectionAttempts <= 3) { // Only log first 3 attempts + console.log('BLAGGINATE page not found'); + } + isBlagginateConnected = false; + blagginateTabId = null; + } + }); + }); +} + +// Listen for messages from content scripts (including BLAGGINATE page) +chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { + if (message.type === 'toggle_blagginate_bridge') { + // Handle BLAGGINATE bridge toggle from popup + const enabled = message.enabled; + chrome.storage.local.set({ blagginateBridge: enabled }, () => { + if (!enabled) { + // If disabled, disconnect from BLAGGINATE + isBlagginateConnected = false; + blagginateTabId = null; + console.log('BLAGGINATE bridge disabled'); + } else { + console.log('BLAGGINATE bridge enabled'); + // Try to reconnect if enabled + connectToBlagginate(); + } + }); + sendResponse({ success: true }); + return; + } + + if (message.type === 'blagginate_ready') { + // BLAGGINATE page is ready to receive messages + blagginateTabId = sender.tab.id; + isBlagginateConnected = true; + console.log('BLAGGINATE page connected'); + + // Send current cookies + updateCookies().then(() => { + sendResponse({ success: true }); + }); + return true; // Keep message channel open for async response + } + + if (message.type === 'get_cookies') { + // BLAGGINATE page requesting current cookies + chrome.storage.local.get(['lastCookie'], (result) => { + sendResponse({ + cookies: result.lastCookie || null, + timestamp: Date.now() + }); + }); + return true; // Keep message channel open for async response + } +}); + +// Check for BLAGGINATE connection periodically +setInterval(() => { + if (!isBlagginateConnected) { + connectToBlagginate(); + } +}, 10000); // Check every 10 seconds + +// Listen for tab removal to clean up connection +chrome.tabs.onRemoved.addListener((tabId) => { + if (tabId === blagginateTabId) { + console.log('BLAGGINATE tab closed'); + isBlagginateConnected = false; + blagginateTabId = null; + } +}); + +// PriceClogs functionality +chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { + // YouTube Cookie requests + if (request.action === "getCookies") { + console.log('Received getCookies request from popup'); + updateCookies() + .then(result => { + console.log('UpdateCookies completed:', result); + sendResponse(result); + }) + .catch(error => { + console.error('UpdateCookies failed:', error); + sendResponse({ + error: error.message || 'Failed to update cookies', + success: false + }); + }); + return true; + } + + // YouTube cookies in Cookie-Editor JSON format (for JDownloader 2 paste-into-password-field flow) + if (request.action === "getCookiesJson") { + getYouTubeCookiesJson() + .then(json => sendResponse({ success: true, cookieJson: json })) + .catch(err => sendResponse({ success: false, error: err.message || String(err) })); + return true; + } + + if (request.action === "postGeminiResult") { + const result = request.result || {}; + console.log('[gemini] postGeminiResult received', { + release_id: result.release_id, + job_id: result.job_id, + prompt_chars: (result.prompt || '').length, + output_chars: (result.output_text || '').length, + }); + chrome.storage.local.get(['monsterSettings'], async (r) => { + const cfg = r.monsterSettings || {}; + const remoteBase = cfg.serverUrl ? cfg.serverUrl : 'http://100.91.239.7:5002'; + const bases = []; + if (cfg.preferLocalhost === true) bases.push('http://localhost:5002'); + bases.push(remoteBase); + const urls = bases + .map(b => String(b || '').trim()) + .filter(Boolean) + .map(b => b.replace(/\/$/, '') + '/plice/gemini'); + try { + let lastErr = null; + for (const url of urls) { + try { + const resp = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(result), + signal: AbortSignal.timeout(8000), + }); + if (!resp.ok) { + const text = await resp.text().catch(() => ''); + console.log('[gemini] POST failed', { url, status: resp.status, body: text.slice(0, 500) }); + lastErr = `HTTP ${resp.status} ${text}`.trim(); + continue; + } + const data = await resp.json().catch(() => ({})); + console.log('[gemini] POST ok', { url, data }); + chrome.storage.local.set({ + geminiPostLast: { + ok: true, + url, + data, + at: new Date().toISOString(), + } + }); + sendResponse({ ok: true, data, url }); + return; + } catch (e) { + const msg = e.message || String(e); + console.log('[gemini] POST exception', { url, error: msg }); + lastErr = msg; + continue; + } + } + + chrome.storage.local.set({ + geminiPostLast: { + ok: false, + urls, + error: lastErr || 'All POST attempts failed', + at: new Date().toISOString(), + } + }); + sendResponse({ ok: false, error: lastErr || 'All POST attempts failed' }); + } catch (e) { + sendResponse({ ok: false, error: e.message || 'Fetch failed' }); + } + }); + return true; + } + + if (request.action === "closeSenderTab") { + const tabId = sender && sender.tab ? sender.tab.id : null; + if (!tabId) { + sendResponse({ ok: false, error: 'No sender tab' }); + return true; + } + chrome.tabs.remove(tabId, () => { + if (chrome.runtime.lastError) { + sendResponse({ ok: false, error: chrome.runtime.lastError.message }); + } else { + sendResponse({ ok: true }); + } + }); + return true; + } + + // PriceClogs file management + if (request.action === "checkFileExists") { + chrome.downloads.search({ + filename: request.filename, + exists: true + }, async (downloadItems) => { + try { + if (downloadItems && downloadItems.length > 0) { + const response = await fetch(`file://${downloadItems[0].filename}`); + if (response.ok) { + const data = await response.json(); + sendResponse({ exists: true, data: data }); + } else { + sendResponse({ exists: false }); + } + } else { + sendResponse({ exists: false }); + } + } catch (error) { + console.error('Error checking file:', error); + sendResponse({ exists: false }); + } + }); + return true; + } + + if (request.action === "downloadFile") { + chrome.downloads.download({ + url: request.url, + filename: request.filename, + conflictAction: 'overwrite', + saveAs: false + }, (downloadId) => { + if (chrome.runtime.lastError) { + sendResponse({ success: false, error: chrome.runtime.lastError }); + } else { + sendResponse({ success: true, downloadId }); + } + }); + return true; + } + + if (request.action === "getBeatportToken") { + fetchBeatportToken(sendResponse); + return true; + } + + if (request.action === "refreshBeatportToken") { + fetchBeatportToken((result) => { + if (result && result.success && result.tokenJson) { + chrome.storage.local.set({ + beatportAuth: { data: result.tokenJson, timestamp: Date.now() } + }, () => sendResponse(result)); + } else { + sendResponse(result); + } + }); + return true; + } +}); + +function fetchBeatportToken(sendResponse) { + console.log("Fetching Beatport token..."); + + // Cloudflare blocks service-worker fetches with a bot challenge (cf-mitigated: challenge → 403). + // So we run the fetch inside an open beatport.com tab where the page already has CF clearance. + // Fall back to a direct SW fetch only if no tab exists (will likely 403, but worth a try). + chrome.tabs.query({ url: "*://*.beatport.com/*" }, (tabs) => { + const handleResult = (data, errMsg) => { + if (errMsg) { + console.error("Beatport fetch error:", errMsg); + sendResponse({ + success: false, + error: "fetch_failed", + message: "Failed to connect to Beatport. Are you logged in? (Open a beatport.com tab and try again.)" + }); + return; + } + if (data && data.token && data.token.accessToken && data.token.accessToken !== 'session') { + sendResponse({ success: true, tokenJson: JSON.stringify(data) }); + } else { + sendResponse({ + success: false, + error: "token_empty", + message: "Beatport returned an empty session. Please log out and back in on beatport.com." + }); + } + }; + + if (tabs && tabs.length > 0) { + const tabId = tabs[0].id; + chrome.scripting.executeScript({ + target: { tabId }, + world: "MAIN", + func: async () => { + try { + const r = await fetch('/api/auth/session', { credentials: 'include' }); + if (!r.ok) return { __err: `HTTP ${r.status}` }; + return await r.json(); + } catch (e) { + return { __err: String(e && e.message || e) }; + } + } + }, (results) => { + if (chrome.runtime.lastError) { + handleResult(null, chrome.runtime.lastError.message); + return; + } + const data = results && results[0] && results[0].result; + if (data && data.__err) { + handleResult(null, data.__err); + } else { + handleResult(data, null); + } + }); + return; + } + + // No beatport tab open — try direct fetch as a last resort. + fetch('https://www.beatport.com/api/auth/session', { credentials: 'include' }) + .then(async (resp) => { + if (!resp.ok) throw new Error(`HTTP ${resp.status}`); + handleResult(await resp.json(), null); + }) + .catch((err) => handleResult(null, err && err.message || String(err))); + }); +} + +// Add external message handler for YouTube cookies +chrome.runtime.onMessageExternal.addListener( + function(request, sender, sendResponse) { + if (request.action === "refreshCookie") { + updateCookies() + .then(result => { + console.log('Cookies refreshed via external request'); + sendResponse({ success: true, timestamp: Date.now() }); + }) + .catch(error => { + console.error('Failed to refresh cookies:', error); + sendResponse({ success: false, error: error.message }); + }); + return true; + } + } +); + +function setActionPopup(tabId, url) { + chrome.action.setPopup({ tabId: tabId, popup: 'popup.html' }); +} + +chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => { + if (changeInfo.status === 'complete' && tab.url) { + // console.log('Tab updated:', tab.url); + + setActionPopup(tabId, tab.url); + + // Check if we're on a Discogs release page + if (tab.url.includes('discogs.com/release/')) { + // console.log('Discogs release page detected'); + + // Check if settings are configured before injecting + chrome.storage.local.get(['discogsToken', 'googleSettings', 'wpSettings'], (result) => { + // console.log('Checking settings for tab:', tabId); + // console.log('Settings found:', { + // hasDiscogsToken: !!result.discogsToken, + // hasGoogleSettings: !!result.googleSettings, + // hasWpSettings: !!result.wpSettings + // }); + + const hasDiscogsToken = result.discogsToken && result.discogsToken.trim() !== ''; + + if (hasDiscogsToken) { + // console.log('Settings configured, injecting content script'); + chrome.scripting.executeScript({ + target: { tabId: tabId }, + files: ['content.js'] + }).catch(err => { + // console.error('Failed to inject content script:', err); + }); + } else { + // console.log('Settings not configured, skipping content script injection'); + } + }); + } + } +}); + +chrome.tabs.onActivated.addListener(activeInfo => { + chrome.tabs.get(activeInfo.tabId, (tab) => { + if(tab) { + setActionPopup(tab.id, tab.url); + } + }); +}); + +// Set for currently active tab when the extension is loaded +chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => { + if (tabs[0]) { + setActionPopup(tabs[0].id, tabs[0].url); + } +}); + +// Initialize YouTube Cookie functionality +chrome.runtime.onInstalled.addListener(() => { + // console.log('Extension installed'); + keepAlive(); +}); + +// Handle messages from content scripts and popup +chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { + console.log('Background: Received message:', message.type); + + if (message.type === 'blagginate_ready') { + // BLAGGINATE page is ready for communication + if (sender.tab) { + blagginateTabId = sender.tab.id; + isBlagginateConnected = true; + console.log('BLAGGINATE page ready, tab ID:', blagginateTabId); + + // Send initial cookies + updateCookies(); + sendResponse({ success: true }); + } + return true; + } + + if (message.type === 'get_cookies') { + // Request for fresh cookies from BLAGGINATE page + chrome.storage.local.get(['youtubeCookies'], (result) => { + if (result.youtubeCookies) { + sendResponse({ + success: true, + cookies: result.youtubeCookies + }); + } else { + // Get fresh cookies + updateCookies().then(() => { + chrome.storage.local.get(['youtubeCookies'], (freshResult) => { + sendResponse({ + success: true, + cookies: freshResult.youtubeCookies || null + }); + }); + }); + } + }); + return true; // Keep message channel open for async response + } + + if (message.type === 'force_cookie_update') { + // Force update cookies (can be called from popup) + updateCookies(); + sendResponse({ success: true }); + return true; + } +}); + +// Handle tab removal - clean up if BLAGGINATE tab is closed +chrome.tabs.onRemoved.addListener((tabId) => { + if (tabId === blagginateTabId) { + console.log('BLAGGINATE tab closed'); + isBlagginateConnected = false; + blagginateTabId = null; + } +}); + +// External message listener for WordPress BLAGGINATE communication +chrome.runtime.onMessageExternal.addListener((request, sender, sendResponse) => { + console.log('External message received:', request, 'from:', sender); + + // Handle WordPress BLAGGINATE cookie requests + if (request.action === "getCookies") { + console.log('WordPress requesting cookies via external message'); + + updateCookies() + .then(result => { + console.log('Cookies updated for WordPress:', result); + sendResponse({ + success: true, + cookieText: result.cookieText, + timestamp: Date.now() + }); + }) + .catch(error => { + console.error('Failed to get cookies for WordPress:', error); + sendResponse({ + success: false, + error: error.message || 'Failed to get cookies' + }); + }); + + return true; // Keep message channel open for async response + } + + // Handle Beatport token extraction requests + if (request.action === "getBeatportToken") { + fetchBeatportToken(sendResponse); + return true; + } + + // Handle WordPress ping/status requests + if (request.action === "ping" || request.action === "status") { + console.log('WordPress ping received'); + sendResponse({ + success: true, + status: 'connected', + timestamp: Date.now() + }); + return true; + } + + // Get Discogs cookies for the batch researcher node script + if (request.action === "getDiscogsCookies") { + chrome.cookies.getAll({ url: "https://www.discogs.com" }, (cookies) => { + const cookieHeader = cookies.map(c => `${c.name}=${c.value}`).join('; '); + sendResponse({ success: true, cookieHeader }); + }); + return true; + } + + // Get Discogs page HTML via a real Chrome tab (bypasses Cloudflare JS challenge) + // Used by the batch researcher node script via the local proxy server + if (request.action === "fetchDiscogsPage") { + fetchPageViaTab(request.url) + .then(html => sendResponse({ success: true, html })) + .catch(err => sendResponse({ success: false, error: err.message })); + return true; // async + } + + // Handle unknown requests + console.log('Unknown external message action:', request.action); + sendResponse({ + success: false, + error: 'Unknown action: ' + request.action + }); + return true; +}); + +// ─── Batch researcher page proxy ────────────────────────────────────────────── +// Polls the node batch script's local proxy server (localhost:7789). +// When a Discogs URL is queued, opens it in a real background Chrome tab so +// Cloudflare's JS challenge can execute, then returns the HTML to the node script. + +let batchProxyTabId = null; + +function ensureBatchProxyTab() { + return new Promise((resolve) => { + if (batchProxyTabId !== null) { + chrome.tabs.get(batchProxyTabId, (tab) => { + if (chrome.runtime.lastError || !tab) { + batchProxyTabId = null; + chrome.tabs.create({ url: 'about:blank', active: false }, (t) => { + batchProxyTabId = t.id; + resolve(t.id); + }); + } else { + resolve(batchProxyTabId); + } + }); + } else { + chrome.tabs.create({ url: 'about:blank', active: false }, (t) => { + batchProxyTabId = t.id; + resolve(t.id); + }); + } + }); +} + +function fetchPageViaTab(url) { + return ensureBatchProxyTab().then(tabId => new Promise((resolve, reject) => { + let done = false; + + const hardTimeout = setTimeout(() => { + if (!done) { done = true; reject(new Error('Proxy tab timeout after 60s')); } + }, 60000); + + function extractAfterLoad() { + if (done) return; + // Run in the tab: scroll to reviews, click Load More until gone, return outerHTML + chrome.scripting.executeScript({ + target: { tabId }, + func: async () => { + // Quick CF check first + if (document.title === 'Just a moment...' || document.body?.innerHTML?.includes('__cf_chl_')) { + return '__CF_BLOCKED__'; + } + + // Scroll to the reviews section to trigger lazy loading + const reviewSection = document.querySelector('#release-reviews'); + if (reviewSection) { + reviewSection.scrollIntoView({ behavior: 'instant' }); + } else { + window.scrollTo(0, document.body.scrollHeight); + } + + // Wait for the loading spinner inside #release-reviews to disappear + // Discogs uses svg[aria-label="loading"] while fetching reviews + for (let i = 0; i < 40; i++) { + await new Promise(r => setTimeout(r, 500)); + const spinner = document.querySelector('#release-reviews svg[aria-label="loading"]'); + if (!spinner) break; // reviews loaded (or section has no reviews) + } + + // Click "Load More Reviews" button until gone + for (let clicks = 0; clicks < 30; clicks++) { + const btn = document.querySelector('#release-reviews button'); + if (!btn) break; + btn.click(); + await new Promise(r => setTimeout(r, 1500)); + // Wait for any new spinner to clear after clicking + for (let i = 0; i < 10; i++) { + await new Promise(r => setTimeout(r, 500)); + if (!document.querySelector('#release-reviews svg[aria-label="loading"]')) break; + } + } + + return document.documentElement.outerHTML; + } + }, (results) => { + if (done) return; + const html = results?.[0]?.result || ''; + if (html === '__CF_BLOCKED__') { + if (!done) { setTimeout(() => extractAfterLoad(), 3000); } + return; + } + const isCF = html.includes('Just a moment') || html.includes('__cf_chl_') || html.length < 500; + if (isCF) { + setTimeout(() => extractAfterLoad(), 3000); + return; + } + done = true; + clearTimeout(hardTimeout); + resolve(html); + }); + } + + function onUpdated(updTabId, changeInfo) { + if (updTabId !== tabId || changeInfo.status !== 'complete') return; + chrome.tabs.onUpdated.removeListener(onUpdated); + setTimeout(extractAfterLoad, 1500); + } + + chrome.tabs.onUpdated.addListener(onUpdated); + chrome.tabs.update(tabId, { url }); + })); +} + +/** + * Run the Discogs DeferredReleaseData GraphQL query. + * Uses a GET request to the correct endpoint with URL-encoded params. + * Executed inside a real Discogs tab so cookies are automatically included. + */ +async function fetchDiscogsGraphQLViaTab(discogsId) { + // Prefer an already-open Discogs tab so we don't need to wait for a page load + const tabs = await new Promise(resolve => + chrome.tabs.query({ url: '*://*.discogs.com/*' }, resolve)); + + let tabId = tabs && tabs.length > 0 ? tabs[0].id : null; + let createdTab = false; + + if (!tabId) { + const t = await new Promise(resolve => + chrome.tabs.create({ url: 'https://www.discogs.com/', active: false }, resolve)); + tabId = t.id; + createdTab = true; + await new Promise((resolve, reject) => { + const timeout = setTimeout(() => reject(new Error('Tab load timeout')), 20000); + function onUpd(id, info) { + if (id !== tabId || info.status !== 'complete') return; + chrome.tabs.onUpdated.removeListener(onUpd); + clearTimeout(timeout); + resolve(); + } + chrome.tabs.onUpdated.addListener(onUpd); + }); + } + + try { + const results = await new Promise((resolve, reject) => { + chrome.scripting.executeScript({ + target: { tabId }, + func: async (id) => { + try { + const params = new URLSearchParams({ + operationName: 'DeferredReleaseData', + variables: JSON.stringify({ discogsId: id }), + extensions: JSON.stringify({ + persistedQuery: { + version: 1, + sha256Hash: 'd11719156ba242b7a0c478272025ba913c71a934c8597ef9cb51e30962a17fb4', + }, + }), + }); + const url = `https://www.discogs.com/service/catalog/api/graphql?${params}`; + const resp = await fetch(url, { + method: 'GET', + headers: { + 'Accept': 'application/json, */*', + 'apollographql-client-name': 'release-page-client', + }, + }); + return await resp.text(); + } catch (e) { + return JSON.stringify({ __fetchError: e.message }); + } + }, + args: [discogsId], + }, (r) => { + if (chrome.runtime.lastError) reject(new Error(chrome.runtime.lastError.message)); + else resolve(r); + }); + }); + + const text = results && results[0] && results[0].result; + if (!text) throw new Error('executeScript returned no result'); + return text; + } finally { + if (createdTab) chrome.tabs.remove(tabId); + } +} + +async function batchProxyPoll() { + try { + // ── HTML page fetch (opens a real tab) ──────────────────────────────── + const resp = await fetch('http://localhost:7789/pending-fetch', + { signal: AbortSignal.timeout(3000) }); + if (resp.status === 200) { + const { requestId, url } = await resp.json(); + + let html = null, error = null; + try { html = await fetchPageViaTab(url); } + catch (e) { error = e.message; } + + await fetch('http://localhost:7789/fetch-result', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ requestId, html, error }), + }); + } + } catch { + // Node server not running — normal when batch script isn't active + } + + try { + // ── GraphQL fetch (executed inside a Discogs tab — same-origin, cookies automatic) ─ + const gresp = await fetch('http://localhost:7789/pending-graphql', + { signal: AbortSignal.timeout(3000) }); + if (gresp.status === 200) { + const { requestId, discogsId } = await gresp.json(); + + let json = null, error = null; + try { + json = await fetchDiscogsGraphQLViaTab(Number(discogsId)); + } catch (e) { error = e.message; } + + await fetch('http://localhost:7789/graphql-result', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ requestId, json, error }), + }); + } + } catch { + // Normal when server not running + } +} + +// Poll every 2 seconds. Silently no-ops when the node server isn't running. +setInterval(batchProxyPoll, 2000); + +// ─── Beatport token refresh poll (for beatport_fill.py) ─────────────────────── +// Polls the ytanalyse cookie-server to see if Python has requested a fresh token. +// When it has, fetches from beatport.com/api/auth/session and delivers it. +async function beatportTokenPoll() { + try { + const resp = await fetch('http://localhost:7792/beatport-pending', + { signal: AbortSignal.timeout(2000) }); + if (resp.status !== 200) return; + const { pending } = await resp.json(); + if (!pending) return; + + console.log('Beatport token requested by Python — attempting live fetch...'); + + // Always try a live fetch first so we get the freshest token. + // Falls back to whatever is in storage only if the live fetch returns 'session' + // (meaning the Beatport browser session has expired). + fetchBeatportToken((result) => { + if (result && result.success && result.tokenJson) { + console.log('Beatport: live fetch succeeded, delivering to cookie-server'); + fetch('http://localhost:7792/beatport-token', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: result.tokenJson, + }).catch(() => {}); + return; + } + + // Live fetch returned 'session' — Beatport browser session likely expired. + // Fall back to storage, but only if the stored token is less than 55 minutes old. + console.warn('Beatport: live fetch returned session/empty, checking storage...'); + chrome.storage.local.get(['beatportAuth'], (stored) => { + const auth = stored.beatportAuth; + const ageMs = Date.now() - (auth?.timestamp || 0); + const tokenJson = auth?.data; + if (tokenJson && ageMs < 55 * 60 * 1000) { + try { + const parsed = JSON.parse(tokenJson); + const tokenObj = parsed.token || parsed; + const accessToken = tokenObj.accessToken || tokenObj.access_token; + if (accessToken && accessToken !== 'session') { + console.log('Beatport: delivering stored token (age: ' + Math.round(ageMs/60000) + 'min)'); + fetch('http://localhost:7792/beatport-token', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: tokenJson, + }).catch(() => {}); + return; + } + } catch { /* invalid JSON */ } + } + // Nothing usable — POST an error so Python stops waiting immediately + console.error('Beatport: no valid token available — browser session expired?'); + fetch('http://localhost:7792/beatport-token-error', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ error: 'session_expired' }), + }).catch(() => {}); + }); + }); + } catch { + // cookie-server not running — normal + } +} + +// Poll every 3 seconds. Silently no-ops when cookie-server isn't running. +setInterval(beatportTokenPoll, 3000); + +// ─── MONSTERWIKI passive auto-capture ───────────────────────────────────────── +// When "Auto-capture while browsing" is on, every Discogs release page you open +// is harvested silently (DOM via content.js + 1 Discogs API call for the +// canonical release object + sell-page scrape) and POSTed to the plice server. +// No popup needed. + +const mcRecent = new Map(); // release_id → last-capture epoch ms +const MC_DEDUP_MS = 10 * 60 * 1000; // ponytail: re-capture same release after 10min, not every scroll/SPA re-render + +async function mcGetReleaseApi(id, token) { + for (let attempt = 0; attempt < 3; attempt++) { + try { + const r = await fetch(`https://api.discogs.com/releases/${id}`, { + headers: { 'Authorization': `Discogs token=${token}`, 'User-Agent': 'PriceClogs/1.0' } + }); + if (r.status === 429) { await new Promise(s => setTimeout(s, 1500 * (attempt + 1))); continue; } + const data = await r.json(); + if (data && data.artists) return data; + } catch (_) {} + await new Promise(s => setTimeout(s, 1000)); + } + return null; +} + +async function mcGetPriceSuggestions(id, token) { + try { + const r = await fetch(`https://api.discogs.com/marketplace/price_suggestions/${id}`, { + headers: { 'Authorization': `Discogs token=${token}`, 'User-Agent': 'PriceClogs/1.0' } + }); + return r.ok ? await r.json() : null; + } catch (_) { return null; } +} + +function mcResolveBase(cfg) { + if (cfg.preferLocalhost) return 'http://localhost:5002'; + return (cfg.serverUrl || 'http://100.91.239.7:5002').replace(/\/$/, ''); +} + +async function monsterAutoCapture(tabId, releaseId) { + const cfg = await new Promise(res => chrome.storage.local.get(['monsterSettings'], r => res(r.monsterSettings || {}))); + if (!cfg.autoCapture) return; + + const last = mcRecent.get(releaseId); + if (last && (Date.now() - last) < MC_DEDUP_MS) return; + mcRecent.set(releaseId, Date.now()); // mark early so concurrent loads don't double-fire + + const token = await new Promise(res => chrome.storage.local.get('discogsToken', d => res((d.discogsToken || '').trim() || null))); + if (!token) { console.warn('[autocapture] no Discogs token — skipping', releaseId); mcRecent.delete(releaseId); return; } + + try { + // DOM scrape (content.js already auto-injected on discogs.com) — gives + // market stats, reviews, recommendations, apple id, cover image. + const dom = await new Promise(res => { + chrome.tabs.sendMessage(tabId, { action: 'getInitialValues' }, resp => { + res(chrome.runtime.lastError ? {} : (resp || {})); + }); + }); + + const [api, priceSuggestions, histHtml, listHtml] = await Promise.all([ + mcGetReleaseApi(releaseId, token), + mcGetPriceSuggestions(releaseId, token), + fetch(`https://www.discogs.com/sell/history/${releaseId}`, { credentials: 'include' }).then(r => r.ok ? r.text() : null).catch(() => null), + fetch(`https://www.discogs.com/sell/list?release_id=${releaseId}`, { credentials: 'include' }).then(r => r.ok ? r.text() : null).catch(() => null), + ]); + + if (!api) { console.warn('[autocapture] API release fetch failed', releaseId); mcRecent.delete(releaseId); return; } + + const rd = combineReleaseData(api, dom, priceSuggestions); + const payload = { + ...buildResearchJson(rd), + sales_history: histHtml ? parseSalesHistoryHtml(histHtml) : null, + current_listings: listHtml ? parseListingsHtml(listHtml) : null, + }; + + const base = mcResolveBase(cfg); + const resp = await fetch(`${base}/plice`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload), + signal: AbortSignal.timeout(12000), + }); + if (resp.ok) console.log('[autocapture] ✓ release', releaseId, '→', base); + else { console.warn('[autocapture] POST failed', resp.status, releaseId); mcRecent.delete(releaseId); } + } catch (e) { + console.warn('[autocapture] error', releaseId, e.message); + mcRecent.delete(releaseId); // allow retry on next navigation + } +} + +chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => { + if (changeInfo.status !== 'complete' || !tab.url) return; + // Release pages only: /release/ or //release/, not master/sell. + const m = tab.url.match(/discogs\.com\/(?:[^/]+\/)?release\/(\d+)/); + if (m) monsterAutoCapture(tabId, m[1]); +}); diff --git a/barcode.js b/barcode.js new file mode 100644 index 0000000..0aa3856 --- /dev/null +++ b/barcode.js @@ -0,0 +1,21 @@ +document.addEventListener('DOMContentLoaded', () => { + const barcodeField = document.querySelector('.print-barcode'); + if (barcodeField && window.releaseData) { + generateQRCode(window.releaseData.id, barcodeField); + } +}); + +function generateQRCode(releaseId, element) { + if (!element || !releaseId) return; + + const qrUrl = `https://api.qrserver.com/v1/create-qr-code/?size=100x100&data=${releaseId}`; + element.innerHTML = `${releaseId}`; +} + +// Export function for use in other modules +window.generateQRCode = generateQRCode; + +function generateBarcode(data) { + // Logic to generate barcode using Code128 font + return `*${data}*`; // Example format +} \ No newline at end of file diff --git a/blagginate-bridge.js b/blagginate-bridge.js new file mode 100644 index 0000000..fcaee02 --- /dev/null +++ b/blagginate-bridge.js @@ -0,0 +1,152 @@ +// BLAGGINATE Bridge Content Script +// This script runs on the BLAGGINATE admin page to establish communication with the extension + +console.log('BLAGGINATE Bridge: Content script loaded'); + +// Global variable to store cookies +window.youtubeCookies = null; +window.lastCookieUpdate = null; + +// Function to handle cookie updates from the extension +function handleCookieUpdate(cookies) { + window.youtubeCookies = cookies; + window.lastCookieUpdate = Date.now(); + console.log('BLAGGINATE Bridge: YouTube cookies updated'); + + // Trigger custom event for the BLAGGINATE page to listen to + const event = new CustomEvent('youtubeCookiesUpdated', { + detail: { + cookies: cookies, + timestamp: window.lastCookieUpdate + } + }); + document.dispatchEvent(event); +} + +// Function to get current cookies (can be called by BLAGGINATE page) +window.getYouTubeCookies = function() { + return { + cookies: window.youtubeCookies, + timestamp: window.lastCookieUpdate + }; +}; + +// Beatport token bridge — mirrors the YouTube cookies pattern +window.getBeatportToken = function() { + return new Promise(function(resolve) { + chrome.storage.local.get(['beatportAuth'], function(result) { + resolve(result.beatportAuth || null); + }); + }); +}; + +window.requestFreshBeatportToken = function() { + return new Promise(function(resolve, reject) { + chrome.runtime.sendMessage({ action: 'refreshBeatportToken' }, function(response) { + if (chrome.runtime.lastError) return reject(new Error(chrome.runtime.lastError.message)); + resolve(response); + }); + }); +}; + +// Function to request fresh cookies from extension +window.requestFreshCookies = function() { + return new Promise((resolve, reject) => { + chrome.runtime.sendMessage({ + type: 'get_cookies' + }, (response) => { + if (chrome.runtime.lastError) { + reject(chrome.runtime.lastError); + return; + } + + if (response && response.cookies) { + handleCookieUpdate(response.cookies); + resolve(response); + } else { + reject(new Error('No cookies available')); + } + }); + }); +}; + +// Listen for messages from the background script +chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { + console.log('BLAGGINATE Bridge: Received message:', message.type); + + if (message.type === 'cookieUpdate') { + handleCookieUpdate(message.cookies); + sendResponse({ success: true }); + return true; + } + + if (message.type === 'ping') { + console.log('BLAGGINATE Bridge: Ping received'); + sendResponse({ success: true, timestamp: Date.now() }); + return true; + } +}); + +// Notify background script that BLAGGINATE page is ready +function notifyReady() { + chrome.runtime.sendMessage({ + type: 'blagginate_ready' + }, (response) => { + if (chrome.runtime.lastError) { + console.log('BLAGGINATE Bridge: Failed to connect to background script:', chrome.runtime.lastError); + // Retry after a delay + setTimeout(notifyReady, 2000); + } else { + console.log('BLAGGINATE Bridge: Successfully connected to extension background'); + } + }); +} + +// Wait for page to be fully loaded before notifying +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', () => { + setTimeout(notifyReady, 1000); // Small delay to ensure page is ready + }); +} else { + setTimeout(notifyReady, 1000); +} + +// Add visual indicator that the bridge is active +function addBridgeIndicator() { + const indicator = document.createElement('div'); + indicator.id = 'youtube-cookie-bridge-indicator'; + indicator.style.cssText = ` + position: fixed; + top: 10px; + right: 10px; + background: #4CAF50; + color: white; + padding: 8px 12px; + border-radius: 4px; + font-size: 12px; + font-family: Arial, sans-serif; + z-index: 10000; + box-shadow: 0 2px 4px rgba(0,0,0,0.2); + `; + indicator.textContent = 'YouTube Cookie Bridge: Connected'; + document.body.appendChild(indicator); + + // Update indicator when cookies are received + document.addEventListener('youtubeCookiesUpdated', () => { + indicator.style.background = '#2196F3'; + indicator.textContent = 'YouTube Cookie Bridge: Cookies Updated'; + setTimeout(() => { + indicator.style.background = '#4CAF50'; + indicator.textContent = 'YouTube Cookie Bridge: Connected'; + }, 2000); + }); +} + +// Add indicator when page is ready +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', addBridgeIndicator); +} else { + addBridgeIndicator(); +} + +console.log('BLAGGINATE Bridge: Initialization complete'); \ No newline at end of file diff --git a/constants.js b/constants.js new file mode 100644 index 0000000..bf929fb --- /dev/null +++ b/constants.js @@ -0,0 +1,37 @@ +const SELECTORS = { + collectionBox: 'div.box_PFmyl.collection_DQxgF', + boxSelectors: { + mediaCondition: '.field_nm6Jt:nth-of-type(1) .dvalue_fevTQ', + sleeveCondition: '.field_nm6Jt:nth-of-type(2) .dvalue_fevTQ', + price: '.field_nm6Jt:nth-of-type(4) .markup_Cngxi', + comment: '.field_nm6Jt:nth-of-type(3) .markup_Cngxi', + collectionFolder: '.field_nm6Jt:nth-of-type(6) .dvalue_fevTQ' + }, + appleMusic: '#audio-iframe', + marketStats: { + have: '#release-stats .items_PQSxS li:nth-child(1) a', + want: '#release-stats .items_PQSxS li:nth-child(2) a', + lastSold: '#release-stats .items_PQSxS li:nth-child(5) a time', + lowPrice: '#release-stats .items_PQSxS li:nth-child(6) span', + medianPrice: '#release-stats .items_PQSxS li:nth-child(7) span', + highPrice: '#release-stats .items_PQSxS li:nth-child(8) span', + artistElement: 'h1.title_Brnd1 a', + labelElement: ".info_LD8Ql a[href*='/label/']", + imageElement: '.thumbnail_cgf1w img' + }, + reviews: { + container: '#reviews', + loadMoreButton: '#release-reviews > div > button', + seeRepliesButton: 'button', + reviewItem: '.review_luKwE:not(.replies_r6FWL .review_luKwE)', + replyItem: '.review_luKwE', + username: '.username_N7O6q', + profileUrl: '.username_N7O6q', + avatar: '.pic_Z6wyD img', + date: 'time.created_EKCAa', + rating: '.rating_pea6E', + text: '.markup_Cngxi', + helpfulButton: '.button_PgYDF.link_ijVx7.button_YXKHZ', + repliesContainer: '.replies_r6FWL' + } +}; \ No newline at end of file diff --git a/content.js b/content.js new file mode 100644 index 0000000..0b8fd13 --- /dev/null +++ b/content.js @@ -0,0 +1,776 @@ +// Only run on Discogs pages to avoid interfering with other sites +if (window.location.hostname.includes('discogs.com') && !window.hasRun) { + // console.log('PriceClogs: Initializing on Discogs page'); + window.hasRun = true; + + const SELECTORS = { + releaseTitle: 'h1.title_Brnd1', + collectionBox: 'div.box_PFmyl.collection_DQxgF', + statsBox: '#release-stats', + appleMusic: '#audio-iframe', + marketStats: { + artistElement: 'h1.title_Brnd1 a', + labelElement: ".info_LD8Ql a[href*='/label/']", + imageElement: '.thumbnail_cgf1w img' + } + }; + + async function waitForElement(selector, timeout = 7000) { + return new Promise((resolve, reject) => { + const element = document.querySelector(selector); + if (element) { + return resolve(element); + } + const observer = new MutationObserver((mutations, obs) => { + const element = document.querySelector(selector); + if (element) { + obs.disconnect(); + resolve(element); + } + }); + observer.observe(document.body, { childList: true, subtree: true }); + setTimeout(() => { + observer.disconnect(); + reject(new Error(`Timeout waiting for element: ${selector}`)); + }, timeout); + }); + } + + function extractReleaseId() { + try { + const href = window.location.href; + const match = href.match(/\/release\/(\d+)/); + if (match) return match[1]; + const sellMatch = href.match(/\/sell\/release\/(\d+)/); + if (sellMatch) return sellMatch[1]; + const link = document.querySelector('a[href*="/release/"]'); + if (link) { + const lm = link.href.match(/\/release\/(\d+)/); + if (lm) return lm[1]; + } + const pathNum = (window.location.pathname.match(/\d{5,}/) || [])[0]; + if (pathNum) return pathNum; + } catch (e) {} + return null; + } + + async function expandAllReviews() { + console.log('[DEBUG] Starting to expand all reviews...'); + + // First, scroll to bottom to trigger review loading + console.log('[DEBUG] Scrolling to bottom to load reviews...'); + const originalScroll = window.scrollY; + window.scrollTo(0, document.body.scrollHeight); + await new Promise(resolve => setTimeout(resolve, 1000)); + + // Click "Load More" buttons until no more exist + while (true) { + const loadMoreButton = document.querySelector('#release-reviews > div > button'); + if (!loadMoreButton) { + console.log('[DEBUG] No more "Load More" buttons found'); + break; + } + try { + loadMoreButton.click(); + console.log('[DEBUG] Clicked "Load More Reviews"'); + await new Promise(resolve => setTimeout(resolve, 1000)); + } catch (error) { + console.error('[DEBUG] Error clicking load more:', error); + break; + } + } + + // Then expand all "See Replies" buttons + let keepChecking = true; + while (keepChecking) { + const seeRepliesButtons = document.querySelectorAll('button.button_PgYDF.link_ijVx7.button_YXKHZ'); + keepChecking = false; + + for (const button of seeRepliesButtons) { + if (button.textContent.includes('See')) { + try { + button.click(); + console.log('[DEBUG] Clicked "See Replies"'); + keepChecking = true; + await new Promise(resolve => setTimeout(resolve, 500)); + } catch (error) { + console.error('[DEBUG] Error clicking see replies:', error); + } + } + } + if (keepChecking) { + await new Promise(resolve => setTimeout(resolve, 1000)); + } + } + + // Restore original scroll position + window.scrollTo(0, originalScroll); + console.log('[DEBUG] Finished expanding all reviews'); + } + + function extractHelpfulCount(reviewEl) { + const helpfulButton = Array.from(reviewEl.querySelectorAll('.button_PgYDF.link_ijVx7.button_YXKHZ')) + .find(button => button.textContent.includes('Helpful')); + const helpfulText = helpfulButton?.textContent?.trim() || ''; + return helpfulText === 'Helpful' ? 0 : parseInt(helpfulText) || 0; + } + + function extractReviews() { + console.log('[DEBUG] Starting review extraction...'); + const reviews = []; + + // Get all top-level review elements (those not in replies containers) + const reviewElements = document.querySelectorAll('.review_luKwE:not(.replies_r6FWL .review_luKwE)'); + console.log(`[DEBUG] Found ${reviewElements.length} top-level review elements`); + + reviewElements.forEach(reviewEl => { + // Extract the main review data + const review = { + id: reviewEl.id?.replace('#', '') || '', + username: reviewEl.querySelector('.username_N7O6q')?.innerText?.trim() || '', + profileUrl: reviewEl.querySelector('.username_N7O6q')?.href || '', + avatarUrl: reviewEl.querySelector('.pic_Z6wyD img')?.src || '', + date: reviewEl.querySelector('time.created_EKCAa')?.getAttribute('datetime') || '', + rating: extractRating(reviewEl), + text: reviewEl.querySelector('.markup_Cngxi')?.innerText?.trim() || '', + helpfulCount: extractHelpfulCount(reviewEl), + replies: [] + }; + + // Find replies container that follows this review + const repliesContainer = reviewEl.nextElementSibling; + if (repliesContainer?.classList.contains('replies_r6FWL')) { + // Get all reply elements within this container + const replyElements = repliesContainer.querySelectorAll('.review_luKwE'); + replyElements.forEach(replyEl => { + const reply = { + id: replyEl.id?.replace('#', '') || '', + username: replyEl.querySelector('.username_N7O6q')?.innerText?.trim() || '', + profileUrl: replyEl.querySelector('.username_N7O6q')?.href || '', + avatarUrl: replyEl.querySelector('.pic_Z6wyD img')?.src || '', + date: replyEl.querySelector('time.created_EKCAa')?.getAttribute('datetime') || '', + rating: extractRating(replyEl), + text: replyEl.querySelector('.markup_Cngxi')?.innerText?.trim() || '', + helpfulCount: extractHelpfulCount(replyEl), + parentId: review.id + }; + review.replies.push(reply); + }); + } + + reviews.push(review); + }); + + // Sort top-level reviews by date (newest first) + reviews.sort((a, b) => new Date(b.date) - new Date(a.date)); + + // Debug logging + console.log(`[DEBUG] Extracted reviews: ${reviews.length}`); + reviews.forEach(review => { + console.log(`[DEBUG] Review ${review.id} has ${review.replies.length} replies`); + }); + + return reviews; + } + + function extractRating(reviewEl) { + const ratingLabel = reviewEl.querySelector('.rating_pea6E')?.getAttribute('aria-label') || ''; + const match = ratingLabel.match(/rated this release (\d+) star/); + return match ? parseInt(match[1]) : 0; + } + + function extractRecommendations() { + console.log('[DEBUG] Starting recommendation extraction...'); + const recommendations = []; + const items = document.querySelectorAll("#release-recommendations > div > div > ul > li"); + + console.log(`[DEBUG] Found ${items.length} recommendation elements`); + + items.forEach(item => { + const recommendation = { + title: item.querySelector(".title_XMp5_")?.innerText?.trim() || '', + artist: item.querySelector("._artistName_1xmn1_9")?.innerText?.trim() || '', + releaseLink: item.querySelector("._link_bcmpa_1._hideUnderLine_bcmpa_25")?.href || '', + coverImage: item.querySelector(".thumbnailContainer_pYnh1 img")?.src || '', + releaseDetails: item.querySelector(".dateAndCountry_Yllip")?.innerText?.trim() || '', + format: { + primary: item.querySelector(".primaryFormat_Fy_7v")?.innerText?.trim() || '', + details: item.querySelector("._concatenatedText_14c0h_1")?.innerText?.trim() || '' + } + }; + + if (recommendation.title || recommendation.artist) { + recommendations.push(recommendation); + } + }); + + console.log(`[DEBUG] Extracted ${recommendations.length} recommendations`); + return recommendations; + } + + async function extractMarketData() { + console.log('[DEBUG] extractMarketData called.'); + const data = { artistId: 'N/A', labelId: 'N/A', imageUrl: 'N/A', lastSold: 'N/A', lowPrice: 'N/A', medianPrice: 'N/A', highPrice: 'N/A', have: 'N/A', want: 'N/A', sellerPriceRange: '' }; + try { + const statsContainer = await waitForElement(SELECTORS.statsBox); + console.log('[DEBUG] #release-stats container found.'); + const statItems = statsContainer.querySelectorAll('.items_PQSxS li'); + statItems.forEach(item => { + const nameEl = item.querySelector('.name_qjn4_'); + if (!nameEl) return; + const name = nameEl.textContent.replace(/|:/g, '').trim(); + const valueEl = item.querySelector('a, span:not(.name_qjn4_)'); + if (!valueEl) return; + const valueText = valueEl.textContent.trim(); + if (name.includes('Have')) data.have = valueText; + else if (name.includes('Want')) data.want = valueText; + else if (name.includes('Last Sold')) data.lastSold = valueEl.querySelector('time')?.getAttribute('datetime') || 'N/A'; + else if (name.includes('Low')) data.lowPrice = valueText.replace(/^[A-Z$£€¥₹]+/, ''); + else if (name.includes('Median')) data.medianPrice = valueText.replace(/^[A-Z$£€¥₹]+/, ''); + else if (name.includes('High')) data.highPrice = valueText.replace(/^[A-Z$£€¥₹]+/, ''); + }); + const artistElement = document.querySelector(SELECTORS.marketStats.artistElement); + if (artistElement) data.artistId = artistElement.getAttribute('href').match(/\/artist\/(\d+)/)?.[1] || 'N/A'; + const labelElement = document.querySelector(SELECTORS.marketStats.labelElement); + if (labelElement) data.labelId = labelElement.getAttribute('href').match(/\/label\/(\d+)/)?.[1] || 'N/A'; + const imageElement = document.querySelector(SELECTORS.marketStats.imageElement); + if (imageElement) data.imageUrl = imageElement.src; + // Extract seller price range from shopping box + const shoppingPriceEl = document.querySelector('.shopping-box-price .shopping-box-copy'); + if (shoppingPriceEl) { + const rangeMatch = shoppingPriceEl.textContent.trim().match(/From\s+[A-Z]*\$?([\d,.]+)\s+to\s+[A-Z]*\$?([\d,.]+)/i); + if (rangeMatch) { + data.sellerPriceRange = `$${rangeMatch[1]}-$${rangeMatch[2]}`; + } + } + } catch (error) { + console.error('[DEBUG] CRITICAL ERROR in extractMarketData:', error); + } + console.log('[DEBUG] Extracted market data object:', data); + return data; + } + + function getCollectionData(collectionBoxElement) { + console.log('[DEBUG] getCollectionData called.'); + const collectionData = { mediaCondition: '', sleeveCondition: '', price: 'N/A', comment: 'N/A', collectionFolder: 'N/A' }; + if (!collectionBoxElement) { + console.log('[DEBUG] Collection box element was NOT found.'); + return collectionData; + } + console.log('[DEBUG] Collection box element found. Extracting data...'); + const fields = collectionBoxElement.querySelectorAll('.field_nm6Jt'); + fields.forEach(field => { + const labelEl = field.querySelector('label.label_KxNWU'); + if (!labelEl) return; + const label = labelEl.textContent.trim(); + let value = field.querySelector('.dvalue_fevTQ, .markup_Cngxi')?.textContent.trim() || ''; + if (label.includes('Media Condition')) collectionData.mediaCondition = value; + else if (label.includes('Sleeve Condition')) collectionData.sleeveCondition = value; + else if (label.includes('comment')) collectionData.comment = value || 'N/A'; + else if (label.includes('price')) collectionData.price = value || 'N/A'; + else if (label.includes('Folder')) collectionData.collectionFolder = value || 'N/A'; + else if (label === 'SKU') collectionData.collectionSku = value || ''; + }); + console.log('[DEBUG] Extracted collection data:', collectionData); + return collectionData; + } + + async function getInitialValues() { + console.log('[DEBUG] getInitialValues called.'); + + // Check if we should run extraction based on settings + const shouldExtract = await checkIfShouldExtract(); + if (!shouldExtract) { + console.log('[DEBUG] Settings not configured, returning minimal data'); + return { + mediaCondition: 'Very Good Plus (VG+)', + sleeveCondition: 'Very Good Plus (VG+)', + price: '', + comment: '', + collectionFolder: '', + reviews: [], + recommendations: [] + }; + } + + try { + await waitForElement(SELECTORS.releaseTitle); + console.log('[DEBUG] Sanity check passed: Release title found.'); + } catch (error) { + console.error('[DEBUG] SANITY CHECK FAILED: Could not find release title. Aborting.', error); + return {}; + } + let collectionBoxElement; + try { + // Wait for at least one collection box to appear + await waitForElement(SELECTORS.collectionBox, 3000); + + // Find all collection boxes and select the last one + const collectionBoxes = document.querySelectorAll(SELECTORS.collectionBox); + if (collectionBoxes.length > 0) { + collectionBoxElement = collectionBoxes[collectionBoxes.length - 1]; + console.log(`[DEBUG] Found ${collectionBoxes.length} collection box(es), using the last one.`); + } else { + collectionBoxElement = null; + } + } catch (error) { + console.log('[DEBUG] "In Collection" box not found on this page.'); + collectionBoxElement = null; + } + const values = getCollectionData(collectionBoxElement); + // Expose multi-box info so the popup can render a copy selector + const allBoxes = document.querySelectorAll(SELECTORS.collectionBox); + values.collectionBoxCount = allBoxes.length; + values.collectionBoxSkus = Array.from(allBoxes).map(b => getCollectionData(b).collectionSku || ''); + values.collectionBoxIndex = allBoxes.length - 1; + const marketData = await extractMarketData(); + Object.assign(values, marketData); + + // Extract reviews with nested structure + await expandAllReviews(); + values.reviews = extractReviews(); + + // Extract recommendations + values.recommendations = extractRecommendations(); + + const iframe = document.querySelector(SELECTORS.appleMusic); + if (iframe && iframe.src) { + // URL shape: https://embed.music.apple.com/{country}/album/{slug?}/{id} + const match = iframe.src.match(/\/([a-z]{2})\/album\/(?:[^/?]+\/)?(\d+)/); + values.appleId = match ? match[2] : null; + values.appleCountry = match ? match[1] : null; + } + console.log('[DEBUG] FINAL EXTRACTED DATA with nested reviews and recommendations:', values); + return values; + } + + // Function to check if extraction should run based on settings + async function checkIfShouldExtract() { + return new Promise((resolve) => { + chrome.storage.local.get(['discogsToken', 'googleSettings', 'wpSettings'], (result) => { + const hasDiscogsToken = result.discogsToken && result.discogsToken.trim() !== ''; + const hasGoogleSettings = result.googleSettings && + result.googleSettings.spreadsheetId && + result.googleSettings.clientEmail && + result.googleSettings.privateKey; + const hasWpSettings = result.wpSettings && + result.wpSettings.url && + result.wpSettings.username && + result.wpSettings.password; + + // At least one service should be configured + const hasValidSettings = hasDiscogsToken && (hasGoogleSettings || hasWpSettings); + console.log('[DEBUG] Content script settings check:', { hasDiscogsToken, hasGoogleSettings, hasWpSettings, hasValidSettings }); + resolve(hasValidSettings); + }); + }); + } + + chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { + try { + if (request.action === 'getInitialValues') { + getInitialValues().then(sendResponse).catch(error => sendResponse({ error: error.message })); + return true; + } + if (request.action === 'getMarketData') { + extractMarketData().then(sendResponse).catch(error => sendResponse({ error: error.message })); + return true; + } + if (request.action === 'selectCollectionBox') { + const boxes = document.querySelectorAll(SELECTORS.collectionBox); + const box = boxes[request.index]; + if (box) sendResponse({ ok: true, ...getCollectionData(box) }); + else sendResponse({ ok: false, error: 'Box not found' }); + return true; + } + if (request.action === 'getReviews') { + expandAllReviews().then(() => { + const reviews = extractReviews(); + sendResponse({ reviews }); + }).catch(error => { + // console.error('Error extracting reviews:', error); + sendResponse({ error: error.message }); + }); + return true; + } + } catch (error) { + // console.error('Error processing message:', error); + sendResponse({ error: error.message }); + } + return true; + }); +} else { + // console.log('PriceClogs: Skipping initialization - not on Discogs page'); +} + +// Global, synchronous helpers used by the bottom message listener +function extractReleaseId() { + try { + const href = window.location.href; + const match = href.match(/\/release\/(\d+)/); + if (match) return match[1]; + const sellMatch = href.match(/\/sell\/release\/(\d+)/); + if (sellMatch) return sellMatch[1]; + const link = document.querySelector('a[href*="/release/"]'); + if (link) { + const lm = link.href.match(/\/release\/(\d+)/); + if (lm) return lm[1]; + } + const pathNum = (window.location.pathname.match(/\d{5,}/) || [])[0]; + if (pathNum) return pathNum; + } catch (e) {} + return null; +} + +function extractInitialValues() { + const values = { + mediaCondition: '', + sleeveCondition: '', + price: '', + comment: '', + collectionFolder: '', + artistId: 'N/A', + labelId: 'N/A', + imageUrl: 'N/A', + lastSold: 'N/A', + lowPrice: 'N/A', + medianPrice: 'N/A', + highPrice: 'N/A', + have: 'N/A', + want: 'N/A', + sellerPriceRange: '', + appleId: null, + reviews: [], + recommendations: [] + }; + + try { + // Collection box values (last one if multiple) + const collectionBoxes = document.querySelectorAll('div.box_PFmyl.collection_DQxgF'); + const collectionBoxElement = collectionBoxes.length ? collectionBoxes[collectionBoxes.length - 1] : null; + if (collectionBoxElement) { + const fields = collectionBoxElement.querySelectorAll('.field_nm6Jt'); + fields.forEach(field => { + const labelEl = field.querySelector('label.label_KxNWU'); + if (!labelEl) return; + const label = labelEl.textContent.trim(); + let value = field.querySelector('.dvalue_fevTQ, .markup_Cngxi')?.textContent.trim() || ''; + if (label.includes('Media Condition')) values.mediaCondition = value; + else if (label.includes('Sleeve Condition')) values.sleeveCondition = value; + else if (label.toLowerCase().includes('comment')) values.comment = value; + else if (label.toLowerCase().includes('price')) values.price = value; + else if (label.includes('Folder')) values.collectionFolder = value; + else if (label === 'SKU') values.collectionSku = value || ''; + }); + } + + // Market stats and related IDs + const statsContainer = document.querySelector('#release-stats'); + if (statsContainer) { + const statItems = statsContainer.querySelectorAll('.items_PQSxS li'); + statItems.forEach(item => { + const nameEl = item.querySelector('.name_qjn4_'); + if (!nameEl) return; + const name = nameEl.textContent.replace(/|:/g, '').trim(); + const valueEl = item.querySelector('a, span:not(.name_qjn4_)'); + if (!valueEl) return; + const valueText = valueEl.textContent.trim(); + if (name.includes('Have')) values.have = valueText; + else if (name.includes('Want')) values.want = valueText; + else if (name.includes('Last Sold')) values.lastSold = valueEl.querySelector('time')?.getAttribute('datetime') || 'N/A'; + else if (name.includes('Low')) values.lowPrice = valueText.replace(/^[A-Z$£€¥₹]+/, ''); + else if (name.includes('Median')) values.medianPrice = valueText.replace(/^[A-Z$£€¥₹]+/, ''); + else if (name.includes('High')) values.highPrice = valueText.replace(/^[A-Z$£€¥₹]+/, ''); + }); + + const artistEl = document.querySelector('h1.title_Brnd1 a'); + if (artistEl) values.artistId = artistEl.getAttribute('href').match(/\/artist\/(\d+)/)?.[1] || 'N/A'; + const labelEl = document.querySelector(".info_LD8Ql a[href*='/label/']"); + if (labelEl) values.labelId = labelEl.getAttribute('href').match(/\/label\/(\d+)/)?.[1] || 'N/A'; + const imageEl = document.querySelector('.thumbnail_cgf1w img'); + if (imageEl) values.imageUrl = imageEl.src; + } + + // Seller price range from shopping box + const shoppingPriceEl = document.querySelector('.shopping-box-price .shopping-box-copy'); + if (shoppingPriceEl) { + const rangeMatch = shoppingPriceEl.textContent.trim().match(/From\s+[A-Z]*\$?([\d,.]+)\s+to\s+[A-Z]*\$?([\d,.]+)/i); + if (rangeMatch) { + values.sellerPriceRange = `$${rangeMatch[1]}-$${rangeMatch[2]}`; + } + } + + // Apple Music album id + const iframe = document.querySelector('#audio-iframe'); + if (iframe && iframe.src) { + const match = iframe.src.match(/album\/(\d+)/); + values.appleId = match ? match[1] : null; + } + } catch (e) { + // fail silently; return whatever we collected + } + + return values; +} + +// Function to update the Discogs price field on the page +async function updateDiscogsPrice(priceValue) { + console.log('[DEBUG] updateDiscogsPrice called with:', priceValue); + + // Find ALL price labels on the page and take the last one (= newest collection box) + const allPriceLabels = Array.from(document.querySelectorAll('.label_KxNWU')) + .filter(el => el.textContent.toLowerCase().trim() === 'price'); + + console.log('[DEBUG] Found', allPriceLabels.length, 'price label(s) on page'); + + if (!allPriceLabels.length) { + console.error('[DEBUG] Price label not found'); + return { success: false, error: 'Price label not found' }; + } + + const priceLabel = allPriceLabels[allPriceLabels.length - 1]; // last = newest collection box + console.log('[DEBUG] Found price label (last one)'); + + // Get the parent field container + const priceField = priceLabel.closest('.field_nm6Jt'); + if (!priceField) { + console.error('[DEBUG] Price field container not found'); + return { success: false, error: 'Price field container not found' }; + } + console.log('[DEBUG] Found price field container, innerHTML:', priceField.innerHTML.substring(0, 200)); + + // Check if there's already an input/textarea visible (edit mode already active) + let input = priceField.querySelector('textarea.textarea_pO4kR, textarea, input[type="text"]'); + console.log('[DEBUG] Initial input search result:', input); + + if (!input) { + // Click the button to enter edit mode - try multiple approaches + const editButton = priceField.querySelector('button.wrapper_F6O4e, button[aria-label="Edit Notes"]'); + if (!editButton) { + console.error('[DEBUG] Edit button not found'); + return { success: false, error: 'Edit button not found' }; + } + + console.log('[DEBUG] Found edit button, clicking...'); + + // Try multiple click methods + editButton.focus(); + editButton.click(); + + // Also try dispatching mouse events + editButton.dispatchEvent(new MouseEvent('mousedown', { bubbles: true, cancelable: true, view: window })); + editButton.dispatchEvent(new MouseEvent('mouseup', { bubbles: true, cancelable: true, view: window })); + editButton.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true, view: window })); + + console.log('[DEBUG] Clicked edit button, waiting for textarea...'); + + // Wait for the textarea to appear with polling + for (let i = 0; i < 10; i++) { + await new Promise(resolve => setTimeout(resolve, 100)); + input = priceField.querySelector('textarea.textarea_pO4kR, textarea, input[type="text"]'); + if (input) { + console.log('[DEBUG] Found input after', (i + 1) * 100, 'ms'); + break; + } + } + } + + if (!input) { + console.error('[DEBUG] Input/textarea not found after clicking edit. Current field HTML:', priceField.innerHTML); + return { success: false, error: 'Input field not found after clicking edit' }; + } + + console.log('[DEBUG] Found input field:', input.tagName, input.className); + + // Focus the input first + input.focus(); + await new Promise(resolve => setTimeout(resolve, 50)); + + // Clear and set the value using native setter for React compatibility + const isTextarea = input.tagName.toLowerCase() === 'textarea'; + const nativeSetter = Object.getOwnPropertyDescriptor( + isTextarea ? window.HTMLTextAreaElement.prototype : window.HTMLInputElement.prototype, + 'value' + )?.set; + + // Clear first + if (nativeSetter) { + nativeSetter.call(input, ''); + } + input.dispatchEvent(new Event('input', { bubbles: true })); + + await new Promise(resolve => setTimeout(resolve, 50)); + + // Now set the value + if (nativeSetter) { + nativeSetter.call(input, priceValue); + } else { + input.value = priceValue; + } + + // Dispatch events to ensure React picks up the change + input.dispatchEvent(new Event('input', { bubbles: true })); + input.dispatchEvent(new Event('change', { bubbles: true })); + + // Simulate typing by dispatching input event with data + input.dispatchEvent(new InputEvent('input', { + bubbles: true, + cancelable: true, + inputType: 'insertText', + data: priceValue + })); + + console.log('[DEBUG] Set price value to:', priceValue, 'Current input value:', input.value); + + // Wait a moment for React to process the input + await new Promise(resolve => setTimeout(resolve, 200)); + + // Find and click the save button + const saveButton = priceField.querySelector('button.save_q8lO5, button.green_DL05T, button:has(.save), button[class*="save"]'); + if (saveButton) { + console.log('[DEBUG] Found save button, clicking...'); + saveButton.click(); + saveButton.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true, view: window })); + console.log('[DEBUG] Clicked save button'); + } else { + console.log('[DEBUG] Save button not found, trying blur instead'); + input.blur(); + document.body.click(); + } + + return { success: true }; +} + +// Function to update the Discogs SKU field on the page +async function updateDiscogsSkuField(skuValue, boxIndex) { + console.log('[DEBUG] updateDiscogsSkuField called with:', skuValue, 'boxIndex:', boxIndex); + + // Target the specific collection box (by index) or fall back to the last one + const allBoxes = document.querySelectorAll('div.box_PFmyl.collection_DQxgF'); + const targetBox = (boxIndex != null && allBoxes[boxIndex]) ? allBoxes[boxIndex] : allBoxes[allBoxes.length - 1]; + + const allSkuLabels = targetBox + ? Array.from(targetBox.querySelectorAll('.label_KxNWU')).filter(el => el.textContent.trim() === 'SKU') + : Array.from(document.querySelectorAll('.label_KxNWU')).filter(el => el.textContent.trim() === 'SKU'); + + console.log('[DEBUG] Found', allSkuLabels.length, 'SKU label(s) in target box'); + + if (!allSkuLabels.length) { + return { success: false, error: 'SKU label not found' }; + } + + const skuLabel = allSkuLabels[0]; // first (only) SKU field in this box + + const skuField = skuLabel.closest('.field_nm6Jt'); + if (!skuField) { + return { success: false, error: 'SKU field container not found' }; + } + + let input = skuField.querySelector('textarea.textarea_pO4kR, textarea, input[type="text"]'); + + if (!input) { + const editButton = skuField.querySelector('button.wrapper_F6O4e, button[aria-label="Edit Notes"]'); + if (!editButton) { + return { success: false, error: 'Edit button not found' }; + } + editButton.focus(); + editButton.click(); + editButton.dispatchEvent(new MouseEvent('mousedown', { bubbles: true, cancelable: true, view: window })); + editButton.dispatchEvent(new MouseEvent('mouseup', { bubbles: true, cancelable: true, view: window })); + editButton.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true, view: window })); + + for (let i = 0; i < 10; i++) { + await new Promise(resolve => setTimeout(resolve, 100)); + input = skuField.querySelector('textarea.textarea_pO4kR, textarea, input[type="text"]'); + if (input) break; + } + } + + if (!input) { + return { success: false, error: 'Input field not found after clicking edit' }; + } + + input.focus(); + await new Promise(resolve => setTimeout(resolve, 50)); + + const isTextarea = input.tagName.toLowerCase() === 'textarea'; + const nativeSetter = Object.getOwnPropertyDescriptor( + isTextarea ? window.HTMLTextAreaElement.prototype : window.HTMLInputElement.prototype, + 'value' + )?.set; + + if (nativeSetter) { + nativeSetter.call(input, ''); + } + input.dispatchEvent(new Event('input', { bubbles: true })); + await new Promise(resolve => setTimeout(resolve, 50)); + + if (nativeSetter) { + nativeSetter.call(input, String(skuValue)); + } else { + input.value = String(skuValue); + } + + input.dispatchEvent(new Event('input', { bubbles: true })); + input.dispatchEvent(new Event('change', { bubbles: true })); + input.dispatchEvent(new InputEvent('input', { + bubbles: true, + cancelable: true, + inputType: 'insertText', + data: String(skuValue) + })); + + await new Promise(resolve => setTimeout(resolve, 200)); + + const saveButton = skuField.querySelector('button.save_q8lO5, button.green_DL05T, button:has(.save), button[class*="save"]'); + if (saveButton) { + saveButton.click(); + saveButton.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true, view: window })); + } else { + input.blur(); + document.body.click(); + } + + return { success: true }; +} + +// Guard: only register this listener once per page context +// (executeScript re-injects the file each time the popup opens, +// without the guard we'd accumulate duplicate listeners) +if (!window._discogsTagListenerAdded) { + window._discogsTagListenerAdded = true; + +chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { + // console.log('CONTENT: Received message:', request); + + // NOTE: getInitialValues is handled by the async listener registered earlier + // (inside the window.hasRun block) which properly calls expandAllReviews() + // and extractReviews(). Do NOT handle it here — this sync handler would + // respond first and return empty reviews, stomping the async result. + + if (request.action === 'updateDiscogsPrice') { + updateDiscogsPrice(request.price).then(result => { + console.log('[DEBUG] updateDiscogsPrice result:', result); + sendResponse(result); + }).catch(error => { + console.error('[DEBUG] Error in updateDiscogsPrice:', error); + sendResponse({ success: false, error: error.message }); + }); + return true; // Will respond asynchronously + } + + if (request.action === 'updateDiscogsSku') { + updateDiscogsSkuField(request.sku, request.boxIndex).then(result => { + console.log('[DEBUG] updateDiscogsSkuField result:', result); + sendResponse(result); + }).catch(error => { + console.error('[DEBUG] Error in updateDiscogsSkuField:', error); + sendResponse({ success: false, error: error.message }); + }); + return true; + } + + return true; // Keep the message channel open for async response +}); // end onMessage listener + +} // end _discogsTagListenerAdded guard \ No newline at end of file diff --git a/deepseek.js b/deepseek.js new file mode 100644 index 0000000..6da6616 --- /dev/null +++ b/deepseek.js @@ -0,0 +1,346 @@ +const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms)); + +function normMarker(v) { + return String(v || '') + .trim() + .replace(/^"+|"+$/g, '') + .replace(/[\s_]+/g, '') + .toUpperCase(); +} + +function isVisible(el) { + if (!el) return false; + const style = window.getComputedStyle(el); + if (style.display === 'none' || style.visibility === 'hidden' || style.opacity === '0') return false; + const rect = el.getBoundingClientRect(); + return rect.width > 0 && rect.height > 0; +} + +async function waitForInputEl(timeoutMs) { + const start = Date.now(); + while (Date.now() - start < timeoutMs) { + const named = document.querySelector('textarea[name="search"]'); + if (isVisible(named)) return named; + const els = [ + ...document.querySelectorAll('textarea'), + ...document.querySelectorAll('div[contenteditable="true"]'), + ].filter(isVisible); + const best = els.find(e => (e.getAttribute('aria-label') || '').toLowerCase().includes('message')) + || els.find(e => (e.getAttribute('aria-label') || '').toLowerCase().includes('prompt')) + || els[0]; + if (best) return best; + await sleep(250); + } + return null; +} + +function setInputText(el, text) { + el.focus(); + if (el.tagName === 'TEXTAREA' || el.tagName === 'INPUT') { + const proto = el.tagName === 'TEXTAREA' + ? HTMLTextAreaElement.prototype + : HTMLInputElement.prototype; + const desc = Object.getOwnPropertyDescriptor(proto, 'value'); + if (desc && desc.set) desc.set.call(el, text); + else el.value = text; + try { + el.dispatchEvent(new InputEvent('beforeinput', { bubbles: true, cancelable: true, inputType: 'insertFromPaste', data: text })); + } catch {} + try { + el.dispatchEvent(new InputEvent('input', { bubbles: true, inputType: 'insertFromPaste', data: text })); + } catch { + el.dispatchEvent(new Event('input', { bubbles: true })); + } + el.dispatchEvent(new Event('change', { bubbles: true })); + return; + } + const editable = el.getAttribute('contenteditable') === 'true'; + if (editable) { + el.focus(); + const sel = window.getSelection && window.getSelection(); + if (sel) { + const range = document.createRange(); + range.selectNodeContents(el); + sel.removeAllRanges(); + sel.addRange(range); + } + try { + document.execCommand('insertText', false, text); + } catch { + el.textContent = text; + } + } else { + el.textContent = text; + } + try { + el.dispatchEvent(new InputEvent('input', { bubbles: true, inputType: 'insertFromPaste', data: text })); + } catch { + el.dispatchEvent(new Event('input', { bubbles: true })); + } +} + +function isAriaDisabled(el) { + const v = (el?.getAttribute('aria-disabled') || '').toLowerCase(); + return v === 'true'; +} + +function findSendButtonNear(inputEl) { + const containers = []; + let p = inputEl; + for (let i = 0; i < 7 && p; i++) { + if (p.parentElement) containers.push(p.parentElement); + p = p.parentElement; + } + + const selectors = [ + 'div._52c986b[role="button"]', + 'div._52c986b', + 'div.ds-icon-button[role="button"]', + '[role="button"].ds-icon-button', + 'button[type="submit"]', + 'button[aria-label*="Send"]', + 'button[aria-label*="send"]', + ]; + + for (const c of containers) { + for (const sel of selectors) { + const btns = [...c.querySelectorAll(sel)].filter(isVisible); + const usable = btns.filter(b => !isAriaDisabled(b)); + if (usable.length) return usable[usable.length - 1]; + } + } + + const any = [ + ...document.querySelectorAll('div._52c986b[role="button"]'), + ...document.querySelectorAll('div._52c986b'), + ...document.querySelectorAll('div.ds-icon-button[role="button"]'), + ].filter(isVisible); + const usable = any.filter(b => !isAriaDisabled(b)); + return usable.length ? usable[usable.length - 1] : null; +} + +function clickLikeAUser(el) { + if (!el) return; + const r = el.getBoundingClientRect ? el.getBoundingClientRect() : null; + const clientX = r ? Math.round(r.left + r.width / 2) : 1; + const clientY = r ? Math.round(r.top + r.height / 2) : 1; + try { el.dispatchEvent(new PointerEvent('pointerdown', { bubbles: true, clientX, clientY, pointerType: 'mouse', isPrimary: true })); } catch {} + try { el.dispatchEvent(new MouseEvent('mousedown', { bubbles: true, clientX, clientY })); } catch {} + try { el.dispatchEvent(new PointerEvent('pointerup', { bubbles: true, clientX, clientY, pointerType: 'mouse', isPrimary: true })); } catch {} + try { el.dispatchEvent(new MouseEvent('mouseup', { bubbles: true, clientX, clientY })); } catch {} + try { el.dispatchEvent(new MouseEvent('click', { bubbles: true, clientX, clientY })); } catch {} + try { el.click(); } catch {} +} + +function isGenerating() { + const stop = document.querySelector('[aria-label*="Stop"], [aria-label*="stop"]'); + if (isVisible(stop)) return true; + const progress = document.querySelector('[role="progressbar"]'); + if (isVisible(progress)) return true; + const spinner = document.querySelector('.ds-loading, .loading, [class*="loading"]'); + if (isVisible(spinner)) return true; + return false; +} + +function extractJsonObjects(text, maxObjects = 25) { + if (!text) return []; + const s = String(text); + const out = []; + let i = 0; + while (i < s.length && out.length < maxObjects) { + const start = s.indexOf('{', i); + if (start === -1) break; + let depth = 0; + let inStr = false; + let esc = false; + for (let j = start; j < s.length; j++) { + const ch = s[j]; + if (inStr) { + if (esc) esc = false; + else if (ch === '\\\\') esc = true; + else if (ch === '"') inStr = false; + continue; + } + if (ch === '"') { inStr = true; continue; } + if (ch === '{') depth++; + else if (ch === '}') { + depth--; + if (depth === 0) { + out.push(s.slice(start, j + 1)); + i = j + 1; + break; + } + } + if (j === s.length - 1) i = s.length; + } + if (i === start) i = start + 1; + } + return out; +} + +function chooseBestJsonFromText(text, marker) { + const markerNorm = normMarker(marker); + const candidates = extractJsonObjects(text, 25); + const expectedKeys = [ + 'summary', + 'store_description', + 'features', + 'sound_profile', + 'highlight_tracks', + 'production', + 'market_insight', + 'sales_angles', + 'embedding', + ]; + + let best = null; + let bestScore = -Infinity; + for (const cand of candidates) { + let parsed; + try { parsed = JSON.parse(cand); } catch { continue; } + if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) continue; + + let score = 0; + const eomNorm = normMarker(parsed.eom); + if (markerNorm && eomNorm === markerNorm) score += 200; + + for (const k of expectedKeys) if (Object.prototype.hasOwnProperty.call(parsed, k)) score += 10; + + if (parsed.summary === 'Short factual description (1-2 sentences)') score -= 50; + if (parsed.store_description === 'Punchy, slightly opinionated record store blurb (max 80 words, human tone, not generic AI)') score -= 50; + + if (cand.length > 2000) score += 5; + if (score > bestScore) { bestScore = score; best = parsed; } + } + return best; +} + +function extractLastResponseText() { + const selectors = [ + 'main', + '[role="main"]', + '[class*="chat"]', + ]; + const parts = []; + for (const sel of selectors) { + const el = document.querySelector(sel); + if (!el || !isVisible(el)) continue; + const t = (el.innerText || '').trim(); + if (t.length > 50) parts.push(t); + } + if (!parts.length) return (document.body?.innerText || '').trim() || null; + parts.sort((a, b) => b.length - a.length); + return parts[0]; +} + +async function waitForJsonAndText(marker, timeoutMs) { + const start = Date.now(); + const want = normMarker(marker); + while (Date.now() - start < timeoutMs) { + const txt = extractLastResponseText() || ''; + if (txt) { + const parsed = chooseBestJsonFromText(txt, marker); + if (parsed) { + const got = normMarker(parsed?.eom); + if (!want || got === want) return { text: txt, json: parsed }; + return { text: txt, json: parsed }; + } + if (!isGenerating() && txt.trimStart().startsWith('{')) { + const fallback = chooseBestJsonFromText(txt, marker); + if (fallback) return { text: txt, json: fallback }; + } + } + await sleep(500); + } + const finalTxt = extractLastResponseText(); + return { text: finalTxt, json: chooseBestJsonFromText(finalTxt, marker) || null }; +} + +async function sendToBackground(message) { + return await new Promise(resolve => { + try { + chrome.runtime.sendMessage(message, (resp) => { + const err = chrome.runtime?.lastError?.message; + if (err) resolve({ ok: false, error: err }); + else resolve(resp || { ok: false, error: 'No response' }); + }); + } catch (e) { + resolve({ ok: false, error: e.message || 'sendMessage failed' }); + } + }); +} + +async function run() { + const job = await new Promise(resolve => chrome.storage.local.get(['geminiJob'], r => resolve(r.geminiJob || null))); + if (!job || !job.prompt) return; + const provider = job.provider || 'gemini'; + if (provider !== 'deepseek') return; + if (job.status !== 'pending' && job.status !== 'running') return; + + if (job.status === 'pending') { + await new Promise(resolve => chrome.storage.local.set({ geminiJob: { ...job, status: 'running', started_at: new Date().toISOString() } }, resolve)); + } + + const inputEl = await waitForInputEl(45000); + if (!inputEl) { + await new Promise(resolve => chrome.storage.local.set({ geminiJob: { ...job, status: 'error', error: 'DeepSeek input box not found.', failed_at: new Date().toISOString() } }, resolve)); + return; + } + + setInputText(inputEl, job.prompt); + await sleep(600); + + const sendBtn = findSendButtonNear(inputEl); + if (!sendBtn) { + await new Promise(resolve => chrome.storage.local.set({ geminiJob: { ...job, status: 'error', error: 'DeepSeek send button not found.', failed_at: new Date().toISOString() } }, resolve)); + return; + } + + try { sendBtn.scrollIntoView({ block: 'center', inline: 'center' }); } catch {} + clickLikeAUser(sendBtn); + + const marker = '__PLICE_EOM__'; + const { text: responseText, json: outputJson } = await waitForJsonAndText(marker, 300000); + if (!responseText) { + await new Promise(resolve => chrome.storage.local.set({ geminiJob: { ...job, status: 'error', error: 'No DeepSeek response detected.', failed_at: new Date().toISOString() } }, resolve)); + return; + } + + const result = { + job_id: job.job_id, + model: job.model || 'deepseek-web', + provider: 'deepseek', + release_id: job.release_id || null, + discogs_url: job.discogs_url || null, + ai_url: location.href, + created_at: job.created_at, + prompt: job.prompt, + input_json: job.input_json || null, + output_text: responseText, + output_json: outputJson, + }; + + await new Promise(resolve => chrome.storage.local.set({ geminiJob: { ...job, status: 'posting', posting_at: new Date().toISOString() } }, resolve)); + const postResp = await sendToBackground({ action: 'postGeminiResult', result }); + + if (!postResp || !postResp.ok) { + const err = postResp?.error || 'Post failed.'; + await new Promise(resolve => chrome.storage.local.set({ geminiJob: { ...job, status: 'error', error: err, failed_at: new Date().toISOString() }, geminiLastExchange: result }, resolve)); + return; + } + + await new Promise(resolve => chrome.storage.local.set({ geminiJob: { ...job, status: 'done', done_at: new Date().toISOString() }, geminiLastExchange: result }, resolve)); + + const closeOnSuccess = await new Promise(resolve => + chrome.storage.local.get(['geminiCloseTabOnSuccess'], r => resolve(r.geminiCloseTabOnSuccess !== false)) + ); + if (closeOnSuccess) { + await sendToBackground({ action: 'closeSenderTab' }); + } +} + +if (document.readyState === 'complete' || document.readyState === 'interactive') { + run(); +} else { + window.addEventListener('DOMContentLoaded', () => run(), { once: true }); +} diff --git a/docs/superpowers/plans/2026-04-12-inventory-sku-lookup.md b/docs/superpowers/plans/2026-04-12-inventory-sku-lookup.md new file mode 100644 index 0000000..4d4eeaf --- /dev/null +++ b/docs/superpowers/plans/2026-04-12-inventory-sku-lookup.md @@ -0,0 +1,680 @@ +# Inventory SKU Lookup — Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** When the popup opens on a Discogs release page with the feature toggled on, automatically SSH-tunnel to the VPS MariaDB, look up inventory SKUs for the release, and fill the Discogs collection SKU field(s) — or show a manual picker if row/box counts don't match. + +**Architecture:** A new `/inventory-lookup` endpoint is added to the existing `rfid-daemon` (port 7790). It opens an SSH tunnel via `ssh2` to `mrpadmin@`, queries `wp_rmp_disc_inventory` via `mysql2`, and returns sorted rows. `popup.js` auto-triggers this on load when enabled, auto-fills matching boxes, or renders a click-to-assign picker on mismatch. + +**Tech Stack:** Node.js (`ssh2`, `mysql2`), Chrome Extension MV3 (`chrome.storage.local`, `chrome.tabs.sendMessage`), existing `updateDiscogsSku` content-script message. + +--- + +## File Map + +| File | Action | What changes | +|---|---|---| +| `rfid-daemon/package.json` | Modify | Add `ssh2`, `mysql2` deps | +| `rfid-daemon/index.js` | Modify | Add `/inventory-lookup` endpoint | +| `popup.html` | Modify | Add inventory settings fields in Connect section + `#inventory-sku-panel` div in Discogs tab | +| `popup.js` | Modify | Save/load `inventorySettings`, auto-trigger `inventorySkuLookup()`, picker render/interaction | + +--- + +## Task 1: Add npm dependencies to rfid-daemon + +**Files:** +- Modify: `rfid-daemon/package.json` + +- [ ] **Step 1: Add ssh2 and mysql2 to package.json** + +Replace the `dependencies` block in `rfid-daemon/package.json`: + +```json +{ + "name": "rfid-daemon", + "version": "1.0.0", + "description": "Local HTTP daemon bridging Chafon H102 UHF RFID reader to browser extension", + "main": "index.js", + "scripts": { + "start": "node index.js" + }, + "dependencies": { + "cors": "^2.8.5", + "express": "^4.18.2", + "serialport": "^12.0.0", + "ssh2": "^1.16.0", + "mysql2": "^3.9.0" + } +} +``` + +- [ ] **Step 2: Install the new dependencies** + +```bash +cd /Users/jingk/Documents/pliceclogs-ultra-yt-omega-999999-truth/rfid-daemon +npm install +``` + +Expected: `added N packages` with no errors. `node_modules/ssh2` and `node_modules/mysql2` now exist. + +- [ ] **Step 3: Verify imports load without error** + +```bash +cd /Users/jingk/Documents/pliceclogs-ultra-yt-omega-999999-truth/rfid-daemon +node -e "require('ssh2'); require('mysql2/promise'); console.log('OK')" +``` + +Expected output: `OK` + +- [ ] **Step 4: Commit** + +```bash +cd /Users/jingk/Documents/pliceclogs-ultra-yt-omega-999999-truth/rfid-daemon +git add package.json package-lock.json +git commit -m "feat: add ssh2 and mysql2 deps for inventory lookup" +``` + +--- + +## Task 2: Add `/inventory-lookup` endpoint to rfid-daemon + +**Files:** +- Modify: `rfid-daemon/index.js` + +The endpoint receives `release_id`, `dbHost`, `dbName`, `dbUser`, `dbPass`, `sshKeyPath` as query params. It SSH-tunnels to `mrpadmin@dbHost`, connects mysql2 through the tunnel stream, queries `wp_rmp_disc_inventory`, and returns rows sorted ASC by `sku`. + +- [ ] **Step 1: Add require statements at the top of rfid-daemon/index.js** + +After the existing `require` lines at the top of `rfid-daemon/index.js` (after the `const cors = require('cors');` line), add: + +```javascript +const { Client: SshClient } = require('ssh2'); +const mysql = require('mysql2/promise'); +const fs = require('fs'); +``` + +- [ ] **Step 2: Add the inventoryLookup helper function** + +Add this function anywhere before the `app.listen(...)` call at the bottom of `rfid-daemon/index.js`: + +```javascript +// ── Inventory lookup via SSH tunnel ────────────────────────────────────────── + +async function inventoryLookup({ releaseId, dbHost, dbName, dbUser, dbPass, sshKeyPath }) { + const keyPath = (sshKeyPath || '~/.ssh/id_rsa').replace(/^~/, os.homedir()); + + let privateKey; + try { + privateKey = fs.readFileSync(keyPath); + } catch (e) { + throw new Error(`Cannot read SSH key at ${keyPath}: ${e.message}`); + } + + return new Promise((resolve, reject) => { + const ssh = new SshClient(); + + ssh.on('ready', () => { + ssh.forwardOut('127.0.0.1', 0, '127.0.0.1', 3306, async (err, stream) => { + if (err) { ssh.end(); return reject(new Error(`SSH forward failed: ${err.message}`)); } + + try { + const conn = await mysql.createConnection({ + host: '127.0.0.1', + user: dbUser, + password: dbPass, + database: dbName, + stream + }); + + const [rows] = await conn.execute( + 'SELECT sku, price, media_condition, sleeve_condition FROM wp_rmp_disc_inventory WHERE release_id = ? ORDER BY sku ASC', + [parseInt(releaseId, 10)] + ); + + await conn.end(); + ssh.end(); + resolve(rows); + } catch (e) { + ssh.end(); + reject(e); + } + }); + }); + + ssh.on('error', (e) => reject(new Error(`SSH error: ${e.message}`))); + + ssh.connect({ + host: dbHost || '100.123.123.64', + port: 22, + username: 'mrpadmin', + privateKey + }); + }); +} +``` + +- [ ] **Step 3: Add the /inventory-lookup express route** + +Add this route block immediately after the `inventoryLookup` function (still before `app.listen`): + +```javascript +app.get('/inventory-lookup', async (req, res) => { + const { release_id, dbHost, dbName, dbUser, dbPass, sshKeyPath } = req.query; + + if (!release_id) { + return res.status(400).json({ error: 'release_id is required' }); + } + if (!dbUser || !dbPass || !dbName) { + return res.status(400).json({ error: 'dbUser, dbPass, and dbName are required' }); + } + + try { + const rows = await inventoryLookup({ + releaseId: release_id, + dbHost: dbHost || '100.123.123.64', + dbName, + dbUser, + dbPass, + sshKeyPath: sshKeyPath || '~/.ssh/id_rsa' + }); + + res.json({ + rows: rows.map(r => ({ + sku: r.sku, + price: r.price != null ? String(r.price) : null, + media_condition: r.media_condition || null, + sleeve_condition: r.sleeve_condition || null + })) + }); + } catch (e) { + console.error('[inventory-lookup]', e.message); + res.status(500).json({ error: e.message }); + } +}); +``` + +- [ ] **Step 4: Smoke-test the endpoint (daemon must be running)** + +Start the daemon in one terminal: +```bash +cd /Users/jingk/Documents/pliceclogs-ultra-yt-omega-999999-truth/rfid-daemon +node index.js -q +``` + +In another terminal, substitute real values for DB_USER, DB_PASS, DB_NAME, RELEASE_ID: +```bash +curl "http://localhost:7790/inventory-lookup?release_id=RELEASE_ID&dbHost=100.123.123.64&dbName=DB_NAME&dbUser=DB_USER&dbPass=DB_PASS" +``` + +Expected: `{"rows":[...]}` — either an array of objects or an empty array. A JSON error object means SSH/DB credentials are wrong. A connection refused means the daemon isn't running. + +- [ ] **Step 5: Commit** + +```bash +cd /Users/jingk/Documents/pliceclogs-ultra-yt-omega-999999-truth +git add rfid-daemon/index.js +git commit -m "feat: add /inventory-lookup SSH-tunnel endpoint to rfid-daemon" +``` + +--- + +## Task 3: Add settings UI to popup.html + +**Files:** +- Modify: `popup.html` + +Two changes: (A) inventory settings fields inside the Connect collapsible, and (B) a status/picker panel in the Discogs tab. + +- [ ] **Step 1: Add inventory settings fields in the Connect section** + +In `popup.html`, locate the line: +```html + +``` + +Insert the following block **immediately before** that line: + +```html + +
+
Inventory SKU Lookup
+ +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+``` + +- [ ] **Step 2: Add the inventory status and picker panel in the Discogs tab** + +In `popup.html`, locate the line: +```html + +``` + +Insert the following block **immediately after** that line: + +```html + + +``` + +- [ ] **Step 3: Verify HTML is valid — open the extension popup on any Discogs page** + +Load the extension in Chrome (`chrome://extensions` → Load unpacked). Open a Discogs release page, click the extension icon. The popup should open without errors in DevTools console. The Connect settings section should show the new Inventory SKU Lookup fields when expanded. + +- [ ] **Step 4: Commit** + +```bash +cd /Users/jingk/Documents/pliceclogs-ultra-yt-omega-999999-truth +git add popup.html +git commit -m "feat: add inventory SKU lookup settings and picker panel to popup" +``` + +--- + +## Task 4: Wire inventory settings save and load in popup.js + +**Files:** +- Modify: `popup.js` + +- [ ] **Step 1: Add loadInventorySettings function** + +Find the function `loadWpSettings` or `loadGoogleSettings` in `popup.js` (around line 460 or 736). Add the following new function in the same area (after either of those functions): + +```javascript +function loadInventorySettings() { + chrome.storage.local.get(['inventorySettings'], (result) => { + const s = result.inventorySettings || {}; + const el = (id) => document.getElementById(id); + if (el('inventorySkuEnabled')) el('inventorySkuEnabled').checked = !!s.enabled; + if (el('inventory-db-host')) el('inventory-db-host').value = s.dbHost || '100.123.123.64'; + if (el('inventory-db-name')) el('inventory-db-name').value = s.dbName || 'wp_rmp_disc_'; + if (el('inventory-db-user')) el('inventory-db-user').value = s.dbUser || ''; + if (el('inventory-db-pass')) el('inventory-db-pass').value = s.dbPass || ''; + if (el('inventory-ssh-key')) el('inventory-ssh-key').value = s.sshKeyPath || '~/.ssh/id_rsa'; + }); +} +``` + +- [ ] **Step 2: Call loadInventorySettings on popup init** + +Find the lines where `loadWpSettings()` and `loadGoogleSettings()` are called (around line 736-737). Add the new call immediately after them: + +```javascript + loadInventorySettings(); +``` + +- [ ] **Step 3: Add inventory settings save to the save-connect-settings handler** + +Find the end of the `save-connect-settings` click handler. It ends with: +```javascript + } else { + console.log('No Discogs token to save (field empty)'); + } + }); +``` + +Insert the following block **inside** the handler, immediately before the closing `});` of the handler (i.e., after the Discogs token save block): + +```javascript + // Save Inventory SKU Lookup settings + const inventorySettings = { + enabled: document.getElementById('inventorySkuEnabled').checked, + dbHost: document.getElementById('inventory-db-host').value.trim() || '100.123.123.64', + dbName: document.getElementById('inventory-db-name').value.trim() || 'wp_rmp_disc_', + dbUser: document.getElementById('inventory-db-user').value.trim(), + dbPass: document.getElementById('inventory-db-pass').value, + sshKeyPath: document.getElementById('inventory-ssh-key').value.trim() || '~/.ssh/id_rsa' + }; + chrome.storage.local.set({ inventorySettings }, () => { + if (chrome.runtime.lastError) { + console.error('Error saving inventory settings:', chrome.runtime.lastError); + } else { + console.log('Inventory settings saved.'); + } + }); +``` + +- [ ] **Step 4: Manual test — save and reload** + +1. Open the extension popup, go to Settings → Connect (expand it). +2. Fill in the Inventory SKU Lookup fields with test values and check the toggle. +3. Click Save Connect Settings. +4. Close and reopen the popup, go back to Settings → Connect. +5. The fields should be repopulated with the values you entered. + +- [ ] **Step 5: Commit** + +```bash +cd /Users/jingk/Documents/pliceclogs-ultra-yt-omega-999999-truth +git add popup.js +git commit -m "feat: save and load inventorySettings in Connect settings" +``` + +--- + +## Task 5: Auto-trigger inventory lookup on popup load + +**Files:** +- Modify: `popup.js` + +This task adds the `inventorySkuLookup(releaseId)` function and calls it automatically after `fetchAndDisplayReleaseData` completes, using `state.collectionBoxCount` (already populated by that point). + +- [ ] **Step 1: Add the inventorySkuLookup function** + +Add this function near `handleImportInventory` (around line 2092 in `popup.js`): + +```javascript +async function inventorySkuLookup(releaseId) { + const settings = await new Promise(resolve => + chrome.storage.local.get(['inventorySettings'], r => resolve(r.inventorySettings || {})) + ); + + if (!settings.enabled) return; + if (!settings.dbUser || !settings.dbPass || !settings.dbName) return; + + const panel = document.getElementById('inventory-sku-panel'); + const status = document.getElementById('inventory-sku-status'); + if (!panel || !status) return; + + panel.style.display = 'block'; + status.textContent = 'Looking up inventory SKUs…'; + status.style.color = '#888'; + + let rows; + try { + const params = new URLSearchParams({ + release_id: releaseId, + dbHost: settings.dbHost || '100.123.123.64', + dbName: settings.dbName || 'wp_rmp_disc_', + dbUser: settings.dbUser, + dbPass: settings.dbPass, + sshKeyPath: settings.sshKeyPath || '~/.ssh/id_rsa' + }); + const resp = await fetch(`http://localhost:7790/inventory-lookup?${params}`); + const data = await resp.json(); + if (data.error) throw new Error(data.error); + rows = data.rows || []; + } catch (e) { + status.textContent = `Inventory lookup failed: ${e.message}`; + status.style.color = '#c00'; + return; + } + + if (rows.length === 0) { + panel.style.display = 'none'; + return; + } + + const boxCount = state.collectionBoxCount || 1; + const lastBoxIdx = boxCount - 1; + + // ── Auto-fill cases ─────────────────────────────────────────────────────── + if (rows.length === 1) { + // Single row → write to last collection box silently + try { + await chrome.tabs.sendMessage(state.discogsTabId, { + action: 'updateDiscogsSku', + sku: rows[0].sku, + boxIndex: lastBoxIdx + }); + status.textContent = 'SKU filled'; + status.style.color = '#2a7'; + setTimeout(() => { panel.style.display = 'none'; }, 3000); + } catch (e) { + status.textContent = `Failed to fill SKU: ${e.message}`; + status.style.color = '#c00'; + } + return; + } + + if (rows.length === boxCount) { + // Matching counts → fill each box in order (earliest SKU first, already sorted ASC) + let ok = true; + for (let i = 0; i < rows.length; i++) { + try { + await chrome.tabs.sendMessage(state.discogsTabId, { + action: 'updateDiscogsSku', + sku: rows[i].sku, + boxIndex: i + }); + } catch (e) { + ok = false; + status.textContent = `Failed to fill box ${i + 1}: ${e.message}`; + status.style.color = '#c00'; + break; + } + } + if (ok) { + status.textContent = `${rows.length} SKUs filled`; + status.style.color = '#2a7'; + setTimeout(() => { panel.style.display = 'none'; }, 3000); + } + return; + } + + // ── Mismatch → show picker ──────────────────────────────────────────────── + status.textContent = `SKU mismatch: ${rows.length} DB rows, ${boxCount} collection box${boxCount !== 1 ? 'es' : ''}`; + status.style.color = '#b60'; + renderInventoryPicker(rows, boxCount); +} +``` + +- [ ] **Step 2: Call inventorySkuLookup at the end of fetchAndDisplayReleaseData** + +Find this line in `popup.js` (around line 1875): +```javascript + monsterBackgroundSync(releaseId); +``` + +Add the call immediately after it: +```javascript + inventorySkuLookup(releaseId); +``` + +- [ ] **Step 3: Manual test — auto-trigger fires** + +1. Enable the inventory lookup toggle in Settings → Connect and save. +2. Open a Discogs release page and click the extension icon. +3. The popup should briefly show "Looking up inventory SKUs…" in the Discogs tab. +4. If the daemon isn't running: shows "Inventory lookup failed: fetch failed" — expected. +5. If the daemon is running with valid creds: auto-fills or shows mismatch depending on data. + +- [ ] **Step 4: Commit** + +```bash +cd /Users/jingk/Documents/pliceclogs-ultra-yt-omega-999999-truth +git add popup.js +git commit -m "feat: auto-trigger inventory SKU lookup on popup load" +``` + +--- + +## Task 6: Mismatch picker rendering and interaction + +**Files:** +- Modify: `popup.js` + +- [ ] **Step 1: Add the renderInventoryPicker function** + +Add this function immediately after `inventorySkuLookup` in `popup.js`: + +```javascript +function renderInventoryPicker(rows, boxCount) { + const picker = document.getElementById('inventory-sku-picker'); + const cardsEl = document.getElementById('inventory-sku-cards'); + const boxButtonsEl = document.getElementById('inventory-sku-box-buttons'); + + if (!picker || !cardsEl || !boxButtonsEl) return; + + let selectedSku = null; + + // ── Render row cards ────────────────────────────────────────────────────── + cardsEl.innerHTML = ''; + rows.forEach((row) => { + const card = document.createElement('div'); + card.style.cssText = [ + 'padding:5px 8px', + 'border:1px solid #ccc', + 'border-radius:4px', + 'font-size:11px', + 'font-family:monospace', + 'cursor:pointer', + 'background:#fff', + 'display:flex', + 'gap:8px', + 'flex-wrap:wrap' + ].join(';'); + + const price = row.price ? `$${row.price}` : '—'; + const media = row.media_condition || '—'; + const sleeve = row.sleeve_condition || '—'; + card.textContent = `${row.sku} · ${price} · ${media} · ${sleeve}`; + card.dataset.sku = row.sku; + + card.addEventListener('click', () => { + // Deselect all + cardsEl.querySelectorAll('div').forEach(c => { + c.style.borderColor = '#ccc'; + c.style.background = '#fff'; + }); + // Select this card + card.style.borderColor = '#2a7'; + card.style.background = '#f0faf4'; + selectedSku = row.sku; + // Enable box buttons + boxButtonsEl.querySelectorAll('button').forEach(b => { + b.disabled = false; + b.style.opacity = '1'; + }); + }); + + cardsEl.appendChild(card); + }); + + // ── Render box number buttons ───────────────────────────────────────────── + boxButtonsEl.innerHTML = ''; + for (let i = 0; i < boxCount; i++) { + const btn = document.createElement('button'); + btn.textContent = String(i + 1); + btn.disabled = true; // enabled only when a card is selected + btn.style.cssText = [ + 'padding:3px 10px', + 'font-size:12px', + 'border-radius:4px', + 'border:1px solid #aaa', + 'cursor:pointer', + 'opacity:0.4' + ].join(';'); + btn.dataset.boxIndex = String(i); + + btn.addEventListener('click', async () => { + if (!selectedSku) return; + const boxIndex = parseInt(btn.dataset.boxIndex, 10); + + try { + await chrome.tabs.sendMessage(state.discogsTabId, { + action: 'updateDiscogsSku', + sku: selectedSku, + boxIndex + }); + // Visual confirmation on the card + const writtenCard = cardsEl.querySelector(`div[data-sku="${CSS.escape(selectedSku)}"]`); + if (writtenCard) { + writtenCard.style.borderColor = '#2a7'; + writtenCard.style.background = '#e8f8ef'; + writtenCard.textContent = '✓ ' + writtenCard.textContent.replace(/^✓ /, ''); + } + // Mark box button as done + btn.textContent = `✓${i + 1}`; + btn.style.background = '#e8f8ef'; + btn.style.borderColor = '#2a7'; + + // Reset selection so user must pick next card deliberately + selectedSku = null; + cardsEl.querySelectorAll('div').forEach(c => { + c.style.borderColor = '#ccc'; + c.style.background = '#fff'; + }); + boxButtonsEl.querySelectorAll('button').forEach(b => { + b.disabled = true; + b.style.opacity = '0.4'; + }); + } catch (e) { + document.getElementById('inventory-sku-status').textContent = `Write failed: ${e.message}`; + document.getElementById('inventory-sku-status').style.color = '#c00'; + } + }); + + boxButtonsEl.appendChild(btn); + } + + picker.style.display = 'block'; +} +``` + +- [ ] **Step 2: Manual test — mismatch picker** + +To test the picker without needing a real mismatch from the DB, temporarily add this call at the bottom of `inventorySkuLookup`, right before the `renderInventoryPicker` call, to force the mismatch branch: + +Trigger the mismatch branch by temporarily setting a release that has a different number of DB rows than collection boxes, or by editing the condition `rows.length === boxCount` to always be false for testing. Verify: + +1. The mismatch message appears: e.g. `SKU mismatch: 2 DB rows, 1 collection box` +2. Row cards are shown with SKU, price, media condition, sleeve condition +3. Box number buttons are grayed out initially +4. Clicking a card highlights it green and enables box buttons +5. Clicking a box number button writes the SKU (check Discogs page), marks the card with ✓, marks the button with ✓N +6. Buttons gray out again — user must select next card before writing to another box +7. Remove any temporary test overrides after confirming behaviour + +- [ ] **Step 3: End-to-end test with real data** + +1. Ensure rfid-daemon is running (`node rfid-daemon/index.js -q`) +2. Ensure inventory settings are saved with valid DB creds +3. Open a Discogs release page that **is** in your collection +4. Click the extension icon + + **Case A — matching counts:** SKUs should fill silently, `"N SKUs filled"` appears briefly then hides. + + **Case B — 1 row:** SKU fills into the last collection box silently. + + **Case C — mismatch:** Picker appears. Assign manually. + + **Case D — 0 rows:** Nothing shown (panel stays hidden). + +- [ ] **Step 4: Commit** + +```bash +cd /Users/jingk/Documents/pliceclogs-ultra-yt-omega-999999-truth +git add popup.js +git commit -m "feat: inventory SKU mismatch picker with card select and box-number assignment" +``` diff --git a/docs/superpowers/specs/2026-04-12-inventory-sku-lookup-design.md b/docs/superpowers/specs/2026-04-12-inventory-sku-lookup-design.md new file mode 100644 index 0000000..a5ab8bf --- /dev/null +++ b/docs/superpowers/specs/2026-04-12-inventory-sku-lookup-design.md @@ -0,0 +1,167 @@ +# Inventory SKU Lookup — Design Spec +**Date:** 2026-04-12 + +## Overview + +When the popup opens on a Discogs release page and the feature is enabled, it SSHes (via Tailscale) to the inventory MariaDB, looks up SKUs for the current `release_id`, and auto-fills the SKU custom collection field(s) on the Discogs page. If there is a row/box count mismatch, a picker UI lets the user manually assign each SKU to the correct collection box. + +--- + +## Database Schema + +Table: `wp_rmp_disc_inventory` (on MariaDB at `100.123.123.64`) + +| Column | Type | Notes | +|---|---|---| +| `sku` | varchar(255) PK | Timestamp-format integer e.g. `20250515100402` — lower = older | +| `release_id` | int(11) INDEX | Discogs release ID | +| `media_condition` | text nullable | | +| `sleeve_condition` | text nullable | | +| `price` | decimal(10,2) | May drift vs Discogs — display only, never written to Discogs | + +Query: +```sql +SELECT sku, price, media_condition, sleeve_condition +FROM wp_rmp_disc_inventory +WHERE release_id = ? +ORDER BY sku ASC +``` + +--- + +## Architecture + +``` +Discogs page (content.js) + ↕ sendMessage +Popup (popup.js) + ↕ fetch localhost:7790 +rfid-daemon (index.js) ──ssh2──▶ mrpadmin@100.123.123.64 + ──mysql2─▶ MariaDB 127.0.0.1:3306 (via tunnel) +``` + +The existing `updateDiscogsSku` message (`chrome.tabs.sendMessage`) already handles writing a SKU value to a specific collection box index — no changes needed to `content.js`. + +`state.collectionBoxCount` and `state.collectionBoxSkus` are already tracked in popup.js and populated when the popup loads on a Discogs release page. + +**Distinct from existing MONSTERWIKI inventory import (`handleImportInventory` / INV button):** that feature talks to the Python server on `100.91.239.7:5002` (PostgreSQL, different dataset) and is triggered manually. This new feature is auto-triggered on popup open, talks to the WordPress MariaDB at `100.123.123.64`, and only writes SKU (not price). + +--- + +## 1. Settings UI (Connect section, popup.html) + +Add a new collapsible sub-section "Inventory SKU Lookup" inside the existing Connect settings block. + +**Fields:** + +| Field | Element ID | Default | +|---|---|---| +| Enable toggle | `inventorySkuEnabled` (checkbox) | unchecked | +| DB Host | `inventory-db-host` | `100.123.123.64` | +| DB Name | `inventory-db-name` | `wp_rmp_disc_` | +| DB User | `inventory-db-user` | *(empty)* | +| DB Password | `inventory-db-pass` (type=password) | *(empty)* | +| SSH Key Path | `inventory-ssh-key` | `~/.ssh/id_rsa` | + +Saved and loaded by the existing "Save Connect Settings" button alongside Discogs token, Google settings, etc. Values stored in `chrome.storage.local` under key `inventorySettings`. + +--- + +## 2. rfid-daemon: `/inventory-lookup` endpoint + +### New npm dependencies +- `ssh2` — SSH tunnel +- `mysql2` — MariaDB client (promise API) + +### Endpoint + +``` +GET /inventory-lookup?release_id=&dbHost=&dbName=&dbUser=&dbPass=&sshKeyPath= +``` + +### Behaviour + +1. Read SSH private key from `sshKeyPath` on disk (resolved from `~` to `os.homedir()`) +2. Open SSH connection to `mrpadmin@dbHost` using the private key +3. Forward a random local port → `127.0.0.1:3306` on the remote host via `ssh2` `forwardOut` +4. Connect `mysql2` to `127.0.0.1:` with `dbUser`, `dbPass`, `dbName` +5. Execute query with `release_id` as the bound parameter +6. Close tunnel and DB connection +7. Return: +```json +{ "rows": [ { "sku": "20250515100402", "price": "12.00", "media_condition": "VG+", "sleeve_condition": "VG" } ] } +``` + +Errors return `{ "error": "" }` with HTTP 500. + +The tunnel is opened fresh per request (no persistent connection) — requests are infrequent (one per popup open). + +--- + +## 3. Popup logic (popup.js) + +### Trigger +Runs automatically when the popup finishes loading on a Discogs release page (`state.discogsTabId` is set and `state.releaseData.id` exists) and `inventorySettings.enabled` is `true`. + +### Flow + +``` +load inventorySettings from chrome.storage.local +if not enabled → stop + +GET /inventory-lookup?release_id=&...creds... +if error → show error message in popup, stop + +count rows = result.rows.length +count boxes = number of collection boxes on page (state.collectionBoxCount or equivalent) + +if rows == 0 → silent, stop +if rows == 1 → writeSkuToBox(rows[0].sku, state.collectionBoxCount - 1) [silent, last box] +if rows == boxes → for each i: writeSkuToBox(rows[i].sku, i) [silent, earliest SKU → first box] +else → show mismatch picker UI +``` + +### writeSkuToBox(sku, boxIndex) +Calls `chrome.tabs.sendMessage(state.discogsTabId, { action: 'updateDiscogsSku', sku, boxIndex })` — existing content.js handler, no changes needed. + +--- + +## 4. Mismatch Picker UI + +Rendered inside the popup when `rows ≠ boxes` (and not the 1-row case). + +**Layout:** + +``` +⚠ SKU mismatch: 2 DB rows, 3 collection boxes + +[ 20250515100402 · $12.00 · VG+ · VG ] ← clickable card +[ 20260101090000 · $18.50 · NM · NM ] ← clickable card + +Write selected to box: [1] [2] [3] +``` + +**Interaction:** +- Clicking a card selects it (highlighted border/background), deselects others +- The box number buttons are always visible (one per collection box, labelled 1-based) +- Clicking a box number button calls `writeSkuToBox(selectedSku, boxIndex)` for the selected card +- After writing, that card gets a small checkmark indicator; user can continue selecting and writing other rows +- No card selected + box button click → no-op (button visually disabled until a card is selected) + +--- + +## 5. Error / Status Display + +A small status line is added to the Discogs tab in the popup (below existing content) to show: +- Nothing (default) +- `"SKU mismatch: N rows, M boxes"` — triggers picker +- `"Inventory lookup failed: "` — SSH/DB error +- `"SKUs filled"` — after successful auto-fill (fades after 3s) + +--- + +## Out of Scope + +- Writing price to Discogs (price may drift — display only in picker) +- Caching DB results between popup opens +- Handling multiple Discogs tabs simultaneously diff --git a/fonts/NotoSans-Regular.ttf b/fonts/NotoSans-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..d55220958aa51eeeb85048d746eabe43d2cd9f14 GIT binary patch literal 569208 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.IN%>(p_~|wOn`C-PPH; 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

*akG6iL#jt$xbL%{HDIRBEp2t@jH9LI?&cAv7 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

+ `; + + // Add event listener for the settings button + document.getElementById('open-settings-btn').addEventListener('click', () => { + document.getElementById('settings-toggle-connect').click(); + }); + } +} + +function displayLimitedInterface() { + const container = document.querySelector('.container'); + if (container) { + container.innerHTML = ` +
+

🔧 Extension Ready

+

Your settings are configured! However, some features require being on a Discogs release page.

+
+

✅ Available Features:

+
    +
  • View and edit your settings
  • +
  • YouTube cookie management
  • +
+

📋 To use full features:

+
    +
  • Navigate to a Discogs release page
  • +
  • Click the extension icon
  • +
  • Use Print Label, Save JSON, and Update Sheet buttons
  • +
+
+
+ +
+
+ `; + + // Add event listener for the settings button + document.getElementById('open-settings-btn').addEventListener('click', () => { + document.getElementById('settings-toggle-connect').click(); + }); + } +} + +async function showMasterPageStatus(masterId, tabId) { + const container = document.querySelector('.container') || document.getElementById('discogs-tab'); + if (container) { + container.innerHTML = ` +
+
Master Release
+
Checking MONSTERWIKI sync…
+
`; + } + + const cfg = await getMonsterSettings(); + const statusEl = document.getElementById('master-status-msg'); + + if (!cfg.enabled) { + if (statusEl) statusEl.textContent = 'MONSTERWIKI sync off — enable in Settings → MONSTERWIKI'; + return; + } + + if (statusEl) statusEl.textContent = '⟳ Scraping reviews…'; + + // Inject directly into the master tab — no content script message timing issues + let reviews = []; + try { + const results = await chrome.scripting.executeScript({ + target: { tabId }, + func: async () => { + const sleep = (ms) => new Promise(r => setTimeout(r, ms)); + const isVisible = (el) => { + if (!el) return false; + const style = window.getComputedStyle(el); + if (style.display === 'none' || style.visibility === 'hidden' || style.opacity === '0') return false; + const rect = el.getBoundingClientRect(); + return rect.width > 0 && rect.height > 0; + }; + + const expandReplyButtons = async () => { + const re = /^see\s+\d+\s+repl/i; + for (let round = 0; round < 6; round++) { + const btns = [...document.querySelectorAll('button, a, div[role="button"]')] + .filter(isVisible) + .filter(el => re.test((el.textContent || '').trim())); + if (!btns.length) return; + for (const b of btns) { + try { b.scrollIntoView({ block: 'center', inline: 'center' }); } catch {} + try { b.click(); } catch {} + await sleep(200); + } + await sleep(600); + } + }; + + // ── 1. Try __NEXT_DATA__ (fast path) ─────────────────────────── + let ndReviews = null; + try { + const nd = document.getElementById('__NEXT_DATA__'); + if (nd) { + const d = JSON.parse(nd.textContent); + const pp = d?.props?.pageProps; + + // Deep-search for any array that looks like reviews + function findReviews(obj, depth = 0) { + if (!obj || typeof obj !== 'object' || depth > 6) return null; + if (Array.isArray(obj) && obj.length && + (obj[0]?.body || obj[0]?.text || obj[0]?.rating !== undefined) && + (obj[0]?.user || obj[0]?.username)) return obj; + for (const v of Object.values(obj)) { + const found = findReviews(v, depth + 1); + if (found) return found; + } + return null; + } + + const raw = pp?.reviews?.items + || (Array.isArray(pp?.reviews) ? pp.reviews : null) + || pp?.master?.reviews?.items + || pp?.initialState?.reviews?.items + || findReviews(pp) + || []; + + console.log('[MONSTER] __NEXT_DATA__ keys:', Object.keys(pp || {}), + '| reviews found via paths:', raw.length); + + if (raw.length) { + const mapped = raw.map(r => ({ + username: r.user?.username || r.username || null, + date: (r.submitted_at || r.submittedAt || r.date || '').split('T')[0] || null, + rating: r.rating ?? null, + text: (r.body || r.text || '').trim() || null, + helpful: r.helpful_count || r.helpfulCount || 0, + version_ref: r.version?.description || null, + version_id: r.version?.id || null, + replies: (r.replies || []).map(rep => ({ + username: rep.user?.username || rep.username || null, + date: (rep.submitted_at || rep.date || '').split('T')[0] || null, + text: (rep.body || rep.text || '').trim() || null, + })), + })).filter(r => r.text || r.rating); + // Discogs rarely embeds replies in __NEXT_DATA__ — only use as fast-path + // if replies are actually present; otherwise fall through for DOM scrape. + if (mapped.some(r => r.replies?.length > 0)) return mapped; + ndReviews = mapped; + } + } + } catch (e) { + console.warn('[MONSTER] __NEXT_DATA__ error:', e.message); + } + + // Expand only "See N reply/replies" buttons (no aggressive clicking) + await expandReplyButtons(); + + // ── 1b. Discogs-specific .review_luKwE scrape (reliable reply nesting) ── + const reviewEls = document.querySelectorAll('.review_luKwE:not(.replies_r6FWL .review_luKwE)'); + if (reviewEls.length) { + const classReviews = []; + reviewEls.forEach(reviewEl => { + const username = reviewEl.querySelector('.username_N7O6q')?.innerText?.trim() || null; + const date = reviewEl.querySelector('time')?.getAttribute('datetime')?.split('T')[0] || null; + const text = reviewEl.querySelector('.markup_Cngxi')?.innerText?.trim() || null; + const ratingLbl = reviewEl.querySelector('[class*="rating"]')?.getAttribute('aria-label') || ''; + const ratingM = ratingLbl.match(/(\d+)/); + const rating = ratingM ? parseInt(ratingM[1]) : null; + const helpful = parseInt([...reviewEl.querySelectorAll('button,a')] + .map(b => b.textContent || '') + .find(t => /helpful/i.test(t))?.match(/\d+/)?.[0]) || 0; + const replies = []; + const sib = reviewEl.nextElementSibling; + if (sib?.classList?.contains('replies_r6FWL')) { + sib.querySelectorAll('.review_luKwE').forEach(replyEl => { + const ru = replyEl.querySelector('.username_N7O6q')?.innerText?.trim() || null; + const rd = replyEl.querySelector('time')?.getAttribute('datetime')?.split('T')[0] || null; + const rt = replyEl.querySelector('.markup_Cngxi')?.innerText?.trim() || null; + if (ru && rt) replies.push({ username: ru, date: rd, text: rt }); + }); + } + if (username && (text || rating)) classReviews.push({ username, date, rating, text, helpful, version_ref: null, version_id: null, replies }); + }); + if (classReviews.length) { + console.log('[MONSTER] .review_luKwE scrape:', classReviews.length, 'reviews,', + classReviews.reduce((s,r) => s + r.replies.length, 0), 'replies'); + return classReviews; + } + } + + // ── 2. Scroll all scrollable containers + window ─────────────── + // Discogs sometimes uses a scrollable div, not window + document.querySelectorAll('main, [class*="content"], [class*="Content"], [class*="layout"], [class*="Layout"]') + .forEach(el => { try { el.scrollTop = el.scrollHeight; } catch(_){} }); + window.scrollTo(0, document.body.scrollHeight); + await new Promise(r => setTimeout(r, 3000)); + + // ── 3. Structural DOM scrape (class-name agnostic) ───────────── + // Find every element that has: a /user/ link + a

P!YA;<+82F2I23iWvirK>`61t0zA(s;Z$f60bm4zu}RKX@Ie@j!1w{2 zyu3$K_Q_q@XMf^rjbE3{%A=ECZ}_@A_A+rh>r$Q{N(bqomQ zU_`%#Um*Sr-ITLGXmAt?<1G7rQrwWd^bvf+gdVYvJtW-LjiJ<$+xey;st} zs0Du~4((=_ci#R@`&7d=GyyZWMC&#Cfa@zejA9?-7MQU|xJx+Qa7? z*)G}c;%(p&B1QB{ILJh4G!nL2IHka~VId{SiciUhTD*r&Mtt6A)a#3gLDrLr!%h~B zl$4-P^!zbA|0tj5SUQX=&|M+bO42QO*Mf;&ZZ5PintwI>^euRmRH;1u)0xkbY}to8 zPG1$DgX9bWV{Vh6|D+&(W^R+5PK7s=u@`~m@jOhKnkSGnP!C$GopEP88AsO9-uESE zM8g-~)!Kf-c|3NO&+XhCiVgPj_FxP3mFj5H?R3)*yEF4ZawhpccH0*nXCt_y9q%uj zt7ccvy#Ofu0YP}{MS4H`%v&!i@5lI&bN*Fij*-0%vGp{55#(l^n+Ye_a3q2i2!Y6+ zM^l*}$n@=tczw~R&l}19Wj7OxPMvO&7 z+EWS(fhPYa>@{i&tVFr3H|-*!n2Te`tigT6B6zA7R?b21Auqd|wPg4{WtnTmLDUb> z!nUw5*NQSViGvCZj0WEtLUu@|gjT{UtZTHHYeOgBy9vp$A1@aN*NnxxTDx$^-2aM$ z>=ypKcsfFUb^-y!?wce&EaLnY#8LPLk$EE+m_Y?AqZN>3Ze)tVx5UdzVlH1zaA>M;v~&uRt-W(Fdg+|{7pfe(7SqmqpR@+AjWz{P-MH94~ zq?VeU{64J);nJm)Rc18g=ae}e6v=LI8{H1O$&f{|#m!+iRskT=6$@m3PFX(W-Mx0d zdBWA`tE=tl*QIo|72zg*i*EEmB{lq`3Lu~~XB)6cRrPfYVulY#9G?Q*Aiu7 zM1|`KBMmD_p;L(15a@%&1QL=RO59KSfojH}(Mu{-9~^(MPc3c4zec-Bxt$st3?`G& z$uxqy%!LL+Y0wufiaPCuUbEL=GMH=*yAgGt;n35Dk@ApgAh-Z`Rbft5DOmofJfSOd?pvj1AVIl5@R zY2Nqr_TIE~Ux2~Q{YCmGoZ(^N)Zj%YMq21|JFJL_L46Gzk5KyaE`VQBngBKPa(g~$ z`{00dnyXb>u$wrs%i_H6$O;gbtpEx;z-*uY#}{D0 z;Sz=v!dzP6y+GwWy#^6OaMi;*L^g8D!y_+@FpcRFV(Y;8MKLZ8+u@T!6)T_Jha0V7 zn*&9H$(w@B<#O`=fa&G=Q>-)3>^#wMVfvSU*!xoH;bFz0B0gWgXXqE4*qZ~9%x~GQ z)$7-GXa1A=HI7)~66nE2uq<7kHn=#UHQMY^9E6#g;x`~EmGNpO5`qaJWx!FSR#y-+ ziIbiJa>HmmgT+?Gg$&+QHG_jVk!^_(8>AHok&wTe>Nq;rI1+W ztQ0irgri7_i`C+Q9`7qqd4{_-ohZDOh<=yp#AL^)8IYl+^0D8es56UU$$FRD75*qZW1GWQ;AcG${X3HUxuhke6BcX>3i! znbYjeY({LB3Hr9~)dco{s2jwZt-{=d zFgNu~l!YS%duyq97mE04SP5dORNw=PF5+Cw@`6fKj}X*Mr`~5`dWeO3hB3mi!>19` zhBY@M8Zo^jOv!IZF1-b_o4dnc$bDRJb2_!`eS8&QRp7R1$a8olR<`_JB%#o2;Q@+P zR)oV0!95lAmG$BBFwl#s+MvT`Ht}fU5DOJ5A}U3i$^>sfm@MB2&iS$>;L7AJ(!#II zi7#HZ?-tW_x9z<@*c#ct=|74FYZlbCNV1MKC|vTblc!fD*BXu=`Tl?C!ksniMq5iF zd6i4pVE6cFU-*-?$WbN!G=l|n5NpRKKu@7MGu)M^6_IcwSAmQ1DsbSpE~?Ci9a|bE z6H9|Ng&b@$+iT-m@!;XiGgDKa+*H45^WL*l4V$lL2Q&A<)b+?$HYCSp-m@t=eka}q zdl!6$9=r>6;B3|cl>LJV6ApHs2?@jx+I*z5#o4gc=CaejlC{l*5b{Z=PI|(iy9+aw_Iv9pf!Pi|KxOdeu zHxR4AUFsQ#^9lK=%H9MqCi?nVxIaZgBxdDth2!yDm41#bI|QC zWE<@%?|UC!bH$q`^N^hb)ex#BvcaPCg0J`_C|_YFC~a`bOz?fb>`W}31hid1 z%mtIc$r_I$51`l!RRX1OiL6v{dO5OE;D28JI8=gpa;}QCc-^g`&NUk+Eg|dX>rB;y zEhT1kp|)wYm6cdSwj0j2?);0naM)zsvG>3(N%af%!au&SUE9T^U;p{nqU!90nX8&< zZ_a5{L9AcO9JgULqO_z+LY+R9T&HjFBCWJIR*qT%Pb4-AQ#z`#)AFQ*I4n2C{97R> zkuPeAg93($J$W~%;3g`JMd?JaHAbU#25pewla+Nczk=r1Rw>_;rPc=VW@U8@FI-HS z^HWpok|}nRvLF_$9kwp>1X;ux6hZRG8l?fOlbGZYHOP&;2ihO}=K8Ug)Vhjgm zzJ)=d1=&H#b?GGQW{zay@r7&Q&CQ$N+`QZh_#=$@ue_3*d`u?If4BG@%)e2npl-ur zpi=LGT*42Z7&s-DgV8hxf&&ReoeW!PQZOY}@v6zp`=&(Crq6#~yk_<^V*Sp*naQ6$ zj(Rl*Kx_W&tSgz!FVo;WWt6Q=TzJv5xjR{Tx_Dq>B=ft??74x=?9=SqnFg@kdimMZ z?`P3(H|4Yy!j*@7ElBiGaxnq`PN)I2q1NoeUd$f^(#q_JrU_ehTFNYer<@;ue0|CE zbYesYCRcU0ZEu^JYCW9VeFOtzmev-hBl8HB(Z4&q+ctljMo4R^SMlv5x6O?ABOE{b zUi65>IWFGG0lhfh&~?gfiIML<*8@6usRPb@FTQA%9rjuO{nJn9y!Ef-T==u-g9BE; z0O$}DdehxXdYyc{Y6>Ng0yb@&GRS>^OMoKIPGN50$%IL0Cp_)stELoqw+m=eK^9cQ zUqh;kRhvZ49ex^|DJSynP>+WM%Lc^N|EsUUd+Ecq*xh>0#bNS!JS?oKw72u=kXTalxjf<|E@~#i%U03H_ zUq63c+LOB;m!E^@4T%@C&y%(-^Zk1I9?WP4fBh%ug#V@f8x{p6g-U_#o4jR(*wOnDCiC0D zU#T=>r(TwRcKyt>R^6}CoM7K68;Q-{D;^%6$h4qKkBJ*GR>pB9KL~qanQ)&hsoMRR zC^ZTQGw?Q*8ElN0-QuenTm`oyqbd24U}q%k6SZs@gwvnAVw72ODFp?DmutcC6{#84 z8Cr2IIT9`j_#mO0jIbn@v9fGXz)GcExnN2(0MG*4zw4yu&d#09jYl>&ZYwXJNsJF{ z+SKuWdr#}ujgzfciZ4wJzDKN^N_WmQTU}!=?_hU&P1lEG<@-i6_3Q=Nu!w^Qh*dXW z?zK=3;qL=(2;v?iOCCZjLXa} z2v);x>9AFQrM@AIKTDyM-Gx} z7kk10yYg1fOG8ALph*j!L6!ne5Ja1BR&gn@3gD^Rkh~2*4~130a@CYlA_4FTs}-p? z+%(*jDim)^wYBZ*`mdQsEJa9L2^eqM{+o)P{z-V*W3{2=#yUesUBkM1BYQOSZ~m0G zXpNf{XKdqp5|`S2-o9QwH$^?8AUWP?4IT0RVKD0Ud7N{4VrGPNo_$r zpO47lDzNiE&^Zl`f#RfdC4`YLbO}e(MO}z@O(2@65~l{l5e7U0Q9Xn_5jH4i9RxuK zF4JQa3eE}=h-H7Jbd+2ee$YuGZ`;y_4CB;SC8Du*&Tg2zv&a|E)9PW0i{tYG^cx`H z)Bmz4kHx2?+tccEvu{>!DDPMo@2hE^Xt-go*>5Vesof0`Ys6x%aVNXVt%acyAb}+I zw)SkQ7^-jBP}hE7b#h0YIAeFTCd+C=2-qEL-MSa&rNM7%iRul5T79^qEL3GtYt@_V z-j0@deZ=ml8)|DGuW~stB!p+om59KPh9Trc8g-R0mrN~!i>a-US1E~#vT4ZW3iGb| z6x|}Hl#>etF-r3>t(4rCZ3U1RNkt^fZw&1xU5IOxg$-@hMlo&;O8nL$I>jlyjNOvC zo&73vRcB8yJQ()WIqYr4>!*W`P+4%5*g3pv_8C=2YE`AqFrd?~Ple;;T@-~LymU3j zV}-SHZF;ppVc;+-qMCt{2ZYHb{U3)DS)-MpVY>~PORzV(95&?O7Z~&~d;z`+iLwY* zK~y-cPoBBMm#eho$|(>A#D>GA( zXc}KL(iLA*j;@0Cb}R_9`WfR z@)9*T+0eOnUv=Gqo&R+Cb|=$cw{OoCBlnDL#^xsZGcDf8c@L~gSxpUc9HtS*K1A1o zC^$Nml0-cE4?+*GR*TeWBeW+17m~wFvg?&gk2tS!TEhqT6>oVVsMXk`_a)TD&MMc=R zr9ywY2mVWDw-u6&K@w4;LPD;$3dPNF_~U3jMI@TRO68kY&WTo-D3G%(MuSkwO67ca znU%+rDFyXHs|M{TUWWWigd5X;>s_4(J74@+@3Fel>WRdAm}bM?{WH_`hw3W#8;#U*zxF>Ln%D$|U8O0nuIXUUWnO8$EMiI&XMT_MgFZoa{ubD2lur;< zRf-@zT};A}O#+Hz@ntY^l2FKmU51qb!C#l_J!PM3^)S$ZLDER%&vYI{mp0{g7O)3u zNOlr_CcyGhS%ILApuEcXB6Bg9QaU=j$T$&r4u(TBPYXmj!M_8Ge*;^+fF`%!K3I?? z%O48LUG-YCN!)D6Cr{sCY+@68Dodp6q8m{nF4YQ07S<;Is2&!-jkO8HD=>+O2saMs zD9pW~8Upr$9U4HH@ZhJyYEi4no{l9*&do?@ilZMyIg$K_BT&(2eZYyPxutD@YL?iV!=52w=9KGsI!fQaC6+hK9#CPtNjC6eVs@lqP7J%Bg>#0GFK)S!$_{P~gV%JiAv z^8r5Ps_ji}-8Oai?CxKV$ip)1KIp-?GR4gU(Ouiv*E983oMR0?k;g>i!K7b@@sMAn zK3(I6#RhpD@cV*el2>FumNGONIC_=nKDb2S3IUi3f;N4Xb-Y_7#M&XyqMv}7k%jLbx*`}9YX64x~(Hcabh=&^yQ5>L( z_KyI{8`pD+e9!pqWaqFIKeW%bfr68 z-qFxbbdlDA1+@F7P>fxK)25VZR2~y(hfcy-M!W`-F2b*YCBfr;d008|2HXy$5|7tv zbwolGa?icl3M)vZa`P<{R-IkO;^FWm(`^;5I!{x(*Ey7Vb%d6+OlFti6WeBgNuzLR zM}Jj5v)4Rk(4{&XzxT5E%}ia6*k8@AX7GR@cxD^bRRUHeTob}o8$}sWTcpE@A+AP% z{z^U?;AvxJ>Uj)52(Q!PFcl=kebT<=B9WSm5iY@HM<74`5RR;!N9Ivh8R<9;3^PGd z{icmm+qWx`{4915as6U!{rLF$&ntoaN94%<7@kMxd9Dwz^}C$h+E3nR;EHE83WfJj zgbZmpQ6Q|6s;eXqP|gbB5;D!MJ@Y99`*xM@z5n3xo!5@ux*(0<&awK9-+h3>rt-!g zpi?eT%#CVL#N~IxXa|84=NxdnXus1w1_wkh=nrDl0gWg31X2_19`kfq*rSbk;qvo@+Rrp@Wb((ITPuU(9$4`QJ$InFo1dN0O6<#GakGELzWUBlwrY;F*7(gb>s+Z z7Ax0{jjhW>N6?&~CCG*TKGF{TvQ(;tnMiK{BAO11hY*?-aYnAN4vvZJr9iP8eF6qr zI1u)EU4FNp(iXXq&4gWT1xN^mL%9fAf{fYN8w?(&(pZep2H}b7&<@>sVD}yCwXLnH z;dA>Aof}lKfn&$@?0dRPkDa(wovBivU;{ln&yS9r-_^74{*B}J?`7>bojiHd>=$mo z=9=5lb?gn)29+K~-(!dlr1SB(*pR&rsEPUO^&-?S@B&ETJipJ5v64R%t`R{e?!(%I zt68OnL4e$Tie7+I5Eu8PJ2YQo)P&au#zd*5^yc^brVj)#K?v5m}OMS z)!V&$>ZvW1uy@&@Xt-o|+rIRs!OJcab(#Mp=Q8h;8hyG3>!b*0{4p68f~H(8u;bwI zDjk{91=!x<70Rgwl$lP!f7D8S>g}4r*i6u^B>{h=7*VDG1c2{et0A;nu0C*ilY#>& z7$t8+*qgc0e6TXEl?GJWfsJNmSjwQ7yS&6&q%#C8?Hk#CK0KI4+-z@dc%U!%lT^xO z=L+Fp2QS(oz8MgE1n(Ra_#wrcs$9WHAoDc0?*h|Nd2#W+gvQuM^@`jLUilOWYu}G*Q zTu~B4Kp^5DKtVN$@!9%b9JP=zO&jXTM6ePaSz>H_m8H0_Am+ZcqB^vgmfJU6I-*ha zYIOIUY_4C9oP>3=QG5~Wn(BDM0`77^{V(#kfiFQJm3}7ngWw`1(>#V3!#x{Y^@u)A_TgFv@SO=(8xBHloK`h!4Y3PsQend;)@6N)i7OEI2>#5 zNw#DrZj4;&Kh&K+w)rZ}Y%j)9_p#!Z($ey#o@DD_S;& zGv9-BxLJnZFgUEJM}d{fXpbxZfP8>0PUsv2T}r|tne}+)84eiyQJB1bP)3ZnynIRwEj`>TF{1hv;nV`i(HiX~h*}QUhXCWznAA{)MSy1x}6HQ+Q(Pl+mshjRoo} zr;JxzLb72~x|zM?sIN7^lJCx~jC_eN#0fX=XG{qdKE$>RlRjjjY~#x2k1Jw&NZyDTI?$N~Wtk}M_cX7dL&8vWn7_swV|+skjT6}@@$-o59Zd+w><`BL+6 zdrRak8lN8jp9}-!Y_MfiRusz9pG2^3 zNI7${Z74J<#uki@?C%d8Kpyf8ADU%uWny;W#ZXH)+#+`$+_!7@(ay#Z)J6UW=ToYe z4`W=(q^BjJ7mY|7Q8@7sg$3|gvWqtuKo%CfOFG4rvMR`a1A;SY@=BzhPSVWz@3ZFq}`+Xjt zFOTY3N$?3A9&b+68$r@Sxc_)SQ@}*B-wt#Rjop6Y>cRZo1tZIQmdD0d#`_v7#`1k7 zhueTJ>+P6KRwYk$?mmz=>~OVrw1oS1G*;KS-C=)l9+SmdX)x~pz_>G{An8dqxQVRX zveTnP6#N86q7JOlLk3lSin|~y6R9J?tf1BJ^?A(+REJx!nda&h1s~DjS9$$ny`Y5H zQ}3P_>YCU&RyR9tElM(@*X1o9tli(!bEM_z=gwZ&C*LyD+u3I_b|smvT_5#`s;FgBDoJ!y>I9mBe%OgrIH633`N5DjX0$_!I{TM!)$1 zf@?b1mR8bq-w z&M;0~$Z&)em0y&|VVVHXgH{5uNgxUEfAXSYno`!*5BVOaJ7{$dQ@Fy478Qh51*l-1 zTCy{{n3z*1Vi&aG$z&vuZFZACD=Eouo>}|d@21<#nzU8#)YWBy^>m?0&o>|6|#s*si8 zz8(C7r`My{xd7e#;wr&D$xoXAhjM7~KO zbopvbn0TySWx#y1fM02Jk|K-K7uu{~xOAKeXbKgr-ra?vz3W!pF?*`|dIpE~F3z+kYcmh@AHVA1Ii0r0 zG~3TA=VwmsTYo@x_k4NvbtoQ)-yarfC2oHpkxJMxPy&H?O}{AnBL#XP>AK*0>=4fO zR6)rvay5fK!8s`Q14>4fy?{;5LoDUdy>Rh9*t!eWuUGZ}<2Ae^SRWU4h@sJ#pqc{5 z0M2%$ge?|RL@__6g=7^!j9l6T)Vd5IiLEk`Hbf{Sr{6tuw)^yn!tsLKnb7Jzy?Y1b zYX%1T&rMx_mnpg5WE%g_>fwiS1)Y|_*yJlr;5-6t73-#;PvZu#37zU(rSpJAaK_@V ze8WtnjzTw3o3G)CT%gTHNd6I?pio%{|D>$2K5x zu?i%_;?eMl$Y(|(H>zdr=o-7061B&|lk%{4EfhHdzI@gk?sK#I*Ka_?0&5JU%Xfh< zO8XHJJL*1;kb#_vBpVlUjnoh(btpLCI8w5rmX>ll zV)^|+*!_NvpAlPifKP!Nv|cyqg50eW9lPKDQO0h(sh}<6d1k6Q(GhvFq180|!PUC` z#qPYFr7LHh=&yYX+Sc9vkkRl@1Ci(K4t7IQQ}Xx?-A;S2&9ORtxRGc~UMTLvv`g?G z!hJ|*0I;AWq+E+$CNZy@A}9{~nnr9n`h zlyI8rLiSJ)%gI@-N~fA%`_{8#Gc$W%etdNP*&EJ+`j9>nTw~jBzi**J1%?Z94V?2i)gLUWhtk=!m@FaD!IwEDvey^1|v<_rde~ z`KxX)ceb#u*1W{op6NXwPXMM!X5?4wnWV<#*9Ha*O$lvF_O~kYZo2<;0Lj;U4Z(kI z?2{70d^chzmK5hu86i|%fLVH=%TP)b_Au^-klsub@)!Ae;)_)rvgDG8ia9g^z~b_A z3{pF)H&SLo04}Lpg1L38t@X>f8GyiOZL4l&=BLB0Tl%3J4X?4qtc?Cp?Qo$ZrQhtR zEh!D9*Ea>ShTFEZK3A(tK|%7R6JDE(dbf#|8EO?WqmEKs2(V<-`bNX690(VO6F5Db z1HA_KXwO{!CRD>)EPl9nEoO2#b0G&^W}EYkgx-J6AgwhRbGV(M1XoIBy*|%v&VZ-Q zQa?tr5Wdd<=#3sY;Hgi8qU2{W%Qu1kUa3O5CXBc&YG;wvqTnkqC8xT zwTo)fPJ)9$?38eN$=kt6;9yhDCu{1jY1$1}tU7&dWZ{~|_G`xnc4ul52X4JkJ5X#} zTUcJnn|#~moJdPsIhO1ww-&cfU06JLVW_@jaeePS_p^PuJ4W+sj-R~q+MeUB=zI4U z5T%pv?JVi=bBPRIL+BKg&FiP|C_@|w8KeBvCHEkNH-Wh!4R8_U#Ll5CH(9jc*>->Y zT|DL)jd&ur+2`T-<+Rqqe5fdQatqaKS4F2=Q6YCmRw|pCcU1UNXI58dGBeZCeOX2Q z{j8$7xT?nfuaSqVf5S@316fX2ChaW?{;9`YjFLN?N&X{hqyQjj9Dh6}%Li=dMe809 zBx4Zgw$9>Y^^sTB)>!`9TBTL4w^df!*1wJrtt^#p9GAP~cF4VKs+fRANnR_wh^oEu zXr%sa+8pq{mD#wvg)CohFeh#~xAd)&y9P&YKYG}ZFmtlL{^ZQ;iMmMJ`0UQHsj1m< zmc4p^=KVMIoST}wxu@ssi1?%>3Myo|&ifjI8UXzM*uNST(DukXOL7k@rZ~gk zW0X;BKaieIR(85KJtr$eR2IT6O^oJT2^hqvH->Wat-{v!+JVI;{*#s6c3n@nXZX%5 z@11#VqHl8Isyik|CeYt^b~-$4R3{Ghudb5E=z9(I^)+vGM&9deZET6gu2f$qxvqPa z{|^5Y#r}Y>Q39sa8Ez%shWsbL)d%_YGUfWs{JON^ldqFs!u>pFgbhjGQttP$xB2~~ zl{6NT%k<+Xi7h{ z6^lv-kZGtzOOz~KEuOWs@!uSiGNAn?Jxlvj2C+u(zyrP1Pn)g-w0D&~yuF|H#(&|H zeAR=od-h9rU3AZHa8FI#bM^rz_%k9({u!Ra1ucI2J$t1)FS-XODRaa<=O}wl+!NPV z9NU;>sL*>{8S@HyT=RED?~&A)nZ&ZyE}(iipjRUMJ={U(F60_MKv6!#Ex{Nhs3Go< zM79s7aexP(g1P~(H`SSF^ai}7zh^jeQgc$wMn@vlQll=4L4aan@8ycARiOQZv(~)V zSYGF>&sA#Y|Av0r($haOqk15t6DdaJWhvJ>)6!B?(+Fxn{CxkvX~{5p>h}Fr>XEL@ zareda1b+-k|495H*3@v0eV(r=bSUYSI2!I@f7wcB95E=~lHOOn3b~p}nImS%WE1>E zfYEh53sLpr4z>Xqm3@s5%C&=A`hE>7Os5E+_kR2IdRr;GfgTf9{^XH}M~C}U=iG1=H>NVJs~ z$=3CER+sS_jGf-|CBBwF#cOqjz0A6OjF3bBt)e^!MLubNDkt*q;<~zyU+3}(*Wcq~ zufvm0^ZFoQPAbbxdbQ|4+>d)SXnP!uS4DG$L_Tg52-#z)d*jtt-(W3Wf7|(iE+Fw^ ztVLWOUWWubgJ;N66@LE|^5y&>#P`L4WZ#6I(F_Tq6Q{*8RA5R2L%5mFN9u?Jm%dhg=C6JsT=Bo%ODEA1e>R;&vDYB@ z> zyE0hy=y2y8=uCL+UxZerW&aF1Gx{BVha9O!nhj5dPy#1ab3jj>BT<&MIZ(Ad2pz!h zfc;F)cvwjqwH8%{sF`0PBxT_7Z3Yl{6B=OM2YlI?yyapIt0AKT$^$~w!c*epa}JW} zYL9wpW47V8h{!Md_Lx^KNm+JVzBMJa!JXS;_v9e&WF0<>5s zTBwn)37*66Dl=%|1<#=~DXd^Q&*OHbSPYQ#EI$ogPF657(9t@Ma0$8HaV!p;kjH$O z<-fP0U1?ft&J4h$n|DkZf{W z-T6~pZ|gLjYOS|S-oO4(FF72riRndq=0 z9kpjc=_TOD_ShB7C&@!0oq@gke$+T3MnR(9RpUX`~3%2Joh@;eLr`pwP3hU%%R*}DFHjt_sh#Loeg4Vhgn1f0C+ z%xJ7$|FYb&V>DP>cDgO{?XnUbfha5MxDWJmqQ8*^IJ@YUNGaH8ZA6aq-e+jmX3jKN zb|3;P*#XJK1W*#FTOR@;)6Y5mKFXxCqWyHd3yInWVg+^T;iaMMa;wvvZ_6v$=e}*K zoZVM+xxKHjmWT^hIXa34m{4OweH%jma)egbm0;qB;%u%*9}+0X-#^OKM8M zV@ntthQ$vovNCZe2DUfuCjJqDH^V>R&*8nJtOB|@>gN)XEpJj6TihJvefLdu$*p_F z_y{YSx*{6(KiGYQ$%(e77$bGZpt?gdhw_a{6=h5it7M*GKHvugk@H2}A>zo2{f?z{ zAPqIDKta$uD+TRzF;7K#wH!Qutn*O#+_COM&37=Dt8Zka$Kh-!D+!0(si|%NP-L^D zv-h=JJAL+^meapa(5H=s7OuErp>iZ$t1St;j680*u_-o$^ zqyLcj0zf~MV}RgdF8PjW%0mNWW?MsDRb^>$UJwoQJXskI8%~E2Hj=nic*ZKX;CqVs z-L`I8&H@l~A!T!8?Ug8NtU~Oyn&E8sY)NZ_qqeHDC-=}yz?WRySKK*ei*4^zzVnlc zJq5){)~uYKV0CR;LwRL);7UV^dB~hz;Ip~iHd}5@VOx*Zon77Ot1XS&{4wE>UYTnv zc6KD&yjhOyOsh4owqO9UL3!gfoFgaL4E#9h!cGwNs}$MC%7LY>A>H9x;Z25efkMxL zq{LLGEhRBMDIEzq$*`E>P_|T?PGlGgHf@E~lw`9dnXG=ZE5Tq(vZvRUuv$`p@MrxE zwW>g+vS+d@BX<=cv6Skr-(@|J3t7^=f`82b9aK9FNM%DZ8)7VIDiC*xG7(f!8Sfw+ zm)t^Jh6#O-&L%~u#C?i$iNqY2EIb(?6|x+DG1Xqoc*{rA(=Yh_exDLK3wniO6cXy6 zQsyqQLhP)kJyDZBP?MZv!XamB8~2tV!PAsn;~E;CFAJ$uqbl{TK{i=duFmG*I9+*g$D!2*x8^j3JQm~}rRH0$RoR_`eM9a_x#17Don*}? zMz0tyo-3M}T0YY7n@B~oPSd6{^v<$SzURd0hX2u>*xhlkk$Hz5w#Dx5;T`WpUV@ZB zpaN@XhAqhBXAs{KdbCj(1i8v8#B!;YlsFr~k~2}s!q<`SSF}X&`Mh>3Icxowt=6Mi zRaUdW&;PA=Us-m^Naz8k?>N4^bFO@U>G+K|-g@)bA8$S3a_>k_9sO$C(2ll2yK^w_ z%H6vU&_1)m$M+T4#cTE851|oltJUMs-RNn#2u@O12iytfvP7%(G#6LvG0MH-^?K|p zU44#xlf`4s$%{O}MrI>VZHU6OiS}`YQ-+(^Pa`FdQYBge9oN|H7?(Vcafy1p?}}V( zTZS?`4``?lkl%*%+tjU>!9Qs4f`5CV<5CKDF7^c_8`305RAUyrYLE8F))e z%&5Xhxm1TSf)oroyg%H>N`Ce7%d#u{B66F6`@HcUI|Ds1C?T^6bysp4fd6-Qshl~{T2;?omrchZ}9dPR5Z4Qe9eKS!Mt97nzu2# zFqBc{%WLu9-8GorWwN1la=s(kUtiSLZ!tHTOnHF}ughc!))M~|L*J{xzAKj+ffN1l zu)WlTgtwApX!dI4QDmbZWGdj+z+_%5d#U=dNb9cwg8qKcqS={SM=zlvop?rPdQTUVv@*IAwy zy>&ukDd`nWg+n|4ynNW-AIvJ8?;qP)Ropqw3@iPig0>miJGa!HsZzOHD|xG(iFw{; zr>NMIn=&%+s8*GIt=+c6?u@*yDz7gn8tyJrt7|HX@_PqL`Fy^+r0jQ4pRl@OuhJxnDAU`};T7kB}u|JAqcX9hd zxry7Vm-@nVIJ=~nNmUiaH6=BL`2k->8nXXEc8yB%Fb}D&Xq-V7ThyZ^v>3D+jw5qi zRRY{Tn{>XeaK|YaCg+c}A8@mbJsnf?G19)*J2Koy*2+_Y#YBC? z^R0zLhZbP7tVM|mTFRVv`#{TF#M6H$9Db$%(@B1uiVhPbAEzX)$Z=OdN%9POB`qik zY6~wH;+ukyh_f#7jB?~#D>W;@&08q~&FM%-E75(+?JyW(58ZYrw)=j5yLyTIl!!Y* z+-2wIQ4jLGiu?*MkjDsxMX8+!4vQc=xLpty%5bzrOVptlPyKj`FYc;sgrd=rq)D4? z3{To}78)+*XX4`zb+s-pGROKGUHQ4?6;-7p1CQu0=3kInp|uUPMh=ejb%oZ*GF4gN zAxj5R7n(+aYjH&#cSWJKM}i~)7AFFF(GVrX9`}VHnNYFp2-e2Gd81klO4Hq--1eKp zd6&D7%rl%?^k|G45*1W-_`Gn?=6Z{KMHqcfnm@C?d1KqM+%nKSQ_4i58i<`pS$>x#HnL4v zkhiEo?m1XHCOIxe@GBQU>{6n7-t?y~Lv!0dt-mn{s*lgr+!#-Dk{8J;qIro_Cw*E_ z+!@EidR;!#N>H)292GK-m*YQ)tpIo$W%tl&;&__WB_c-*>+ukk0TvOvihH-Q^`-7d zAGxy9P*rJNS)I?Pa4QO%FH1lUPe$Cz&pv1kltcU1IahB@dTJ^1WlMf@DT+4iIr(|^ z9zjw2?n|(-qcokZtsl>+Lr=iogu;9_7Drnp=D>TzCjJTpK(!`>MiOkYbZIf1fMmV+ z{$c4*F?EbUUMR&8#x}J!q7XH2r|jACDVjmk2V3spxmr-atSK(a)r#vQM!3e5f*viY zjq4@$#y)fs>+73*;f1(vVv(1qm)Km(%uEZ$45LdK^FY{4;A_BbGpc09@lb`zYk{`L zy#oi3r^3C{zz-!24k^`&bF#DG9Jcata)b%8c+*jtKnYZo zMM_>Zn10k?Ng1(c%cmm60wj*R2PDSe=?|~KRwfXmD>raaF+~`#@e|?nz1(Ctng8<= z^C4qb176XgJ}-e%I@O>kT)8w6s!!(}!h;0(O=6VUO<{r0SyQM72r@k3Jm#^DsVVja zPsGda@US~^rwKRyC!TARTExTbV%`*e5L8j(-=TiDyGO^Wb$wlZed@?J z)qU^mIC}NfM|WI(bN$ibUyt|qk4ILQ#>STD?4h{pmmmkzarTr;A5v=n3~-n`cnJ|A zuZXKEzd+tm?OzU%ju3K%hl?~%wnV!UK3B@d;~_#iYQlxFo3O8=_uw>+{^yq4q5tFt zsq(qFFj$^j4u?b_GeEUIa0H?DncNY`QzVm}EFa-b;pHeTw4U~)_j|u?t zU8hd12;lJ-U!3~mNUPj3MF8aYw8*OfAHVJPTkqnqpmQ_9#Eb|0-?>nZEclG&8Os`umozFe(q z?@LHY=!P;roHyE*SW=(W(F%9FhZ-8ry2>ol%+y1|%n9 z5S$mVq9#)C9d;Z6{NZ2+}N2;S$^yPYMJR3l`1sf@XZBmN6;w*o?PMkF(3O8 zbrsNz!HGnG`2C1ID2(M}e6K~BkUK}W?MLp@quW8BOWeJ=AM>;G#eM`3O^{c=Vm~Ub zJ>hpGAx4?iVn3n`R`FqASHAxxS*3LjhnG&BUTz*rRVQ_fj7&W=+RoZ0yE;1W4!5P0 zT5?KnzwNd=OTFFe7s5+R-1GM zHeY_KC538A86pTlv5RyF?pC2&UM$gEk?2H>P<6E?o)Yql1$ivoZwq9epZbTu8?wBW zEX#qc$i66DSerkus-xChS)6$`^2fjXlK)r9>BbnDA|s1|%72d|6Q<+F9{4`|dN$}8 zm%{;oh~|1IldKj62LPQ?<8T0wUQMA9p3~+H{(O0VL;3y7H(j}_Cfr!Jf=0eW{dK*T z-~6PdytuT0;6w1Ff%84Ew=o6?Iv`!M3KQ`n{?iLl{jJ#pda8&i3%(|+Pd*|m));vJXMAas%?&$n? z2cCMDT_4$CYmx5k4tuo8Cf=WfJ^MdclM3o4l9y#hn9cxI7J@2P+s_>V7zecMXfTFK zSNsH);)H7ubz>qDqj*e1Ayu&oy-id)AXZ(X7b?d>W%v2qN!jM&Dyv~eotTLDpvsVx zsGgd;Fw>Wuf|Rl3MAh8vRI&{pSWP`sA4;q1emkK{r4F}vSs=NvEYFaTS6*z2{9JZL zep9xPk=+Em)WXP*3TB^S)O8NI(kOhpc?eFv#)pOf93AI-Fx-P zMM*iOciejGUBzylJIDA7`RA|i-o10Db=Q7KB$~56ZqC;|pPsDfM!c;!6eBD#)))9l zJlLw&M?-H32|P@N`7(BhN|N)Dh^0Oo|BcJuJRJrQP*Fj^2SR(WZRn2?<$Sg<+G&$L%8vVsKBJ{Go@iY)|Nj-QwNkZ2}0y4tJ zBE1<5%>zTJXrzgJ7&PMIp>ALnz>KF9Ewws1``dfezf&bd{>fdF%1X;vH&@>r5#kq!?MD&+FlZwi*%5jh7`{m_*?V zsE`XXj-C8Qf8UEewPXG6!aYr)nd%)odWO$mQ@1m3=j`~b;la+^8p5HLY){@;OWRJ1 z#x&n|;FR4qR5HqWVB>9!_uKN%xSer;vUCLQHf8BJaS-M30|*>&7`dC|L;-XGKX7TI z3km@gmM-FBaH2S{`2AcKh+A;{WM+6hWIUjJ)9OR$D5Jm`jkJ-V=I(%4ih)mU~-TM?3TVnSrtzzNg_W z2Y)-U79K)hpe%yR;2H2e%#Thi0MdfdQs8oU1|n$^r(;xw2b=+kd*<%y?r6y>u`+v2 z5P$~zdXC)u)U%UEYX;d*R;NbCOvYYg^3_+4oZRvF!+-omSN~IYTzwO0L;BDzEw@A^0=EI*^I{5!jjlnX==5oMEBH zL5)O+o774K0tga-7B|Gsx0Krp?Fp&XuJDfLmfoojqb6&#R{s14p+b*BU;W1~8|FJB zugk9avPv*0$v*5Y`IpFbPKAUX4iA7EIkaN}V25>rr4v~KGNcmVz(>DKnk6}IiLU`( zE%-VOz!~l=mnY4G$KbH0KTb~)T+Y}~ig80W-KL%(9A#1EpvgO?}ejFUr4^ywDS04kxEGrbp<9Q6M7P zEw>2eWqN~7e})FlWg|oclqsfPN=%UTdhi>vH5ITs- zr-w_T-y!*HKyT!|+g`Kn8zg4^KI9hV`HKC;*w}#ibl6P7gwjX=c_1+>>hjR&kN&5C zeUPIdnr%cTvr~|e&S$x@sds!lYwFFR_(Y>Odn?LO^_T6Df7w~vJQOKnKR^=EmOP`J z&c$yPWjcLDl|In51-$<%>MXO+qzjmQe%f>hn4_SUjtvPllf2#?HirWF=>}eScD_5G zkQk9?l@(|HiE4(Z1sH@~%UzV@2ZDQupVxmGoh}I!H)fqU{LH612kXl|Tzgw%&(csq zNp*EzRm%W_7+Hv~M=3@g_o|k7=e6IR{rz6t2Ha@gx zae8Ep_7>M`+3nDM9MW|{kuYN8NLJ+bBON?FjNdfT-xU87q0UGGXb77hx*p+V!lYBH zp%oGGKbH@54`th3d<##$#a1sNy1kP^6B4Dji4!a6P zPZ+fd^p+$+aeUQowWDVWaM-FsLCy-03|yCX+I1d#ylZ;otuup-JXQO|+Va<#`<0O% zo&XWP&|h+B@c5b9g9H0cXtXw528VX;92!LRrJy%zHC*uAQxEh_`$5!oI7M9t zrls5~KZv!-Caj)RBXGc6u;@3jdNAcBLSo^9f?HjiwpKPK$!!yrVmd$|ERjG^tTAp| z0(WvnrvhAh@vm zp9xS?ryXvMDPaI#F;`mA>DZeRvh0bW;84lFLnT863QSutIB4}qvKbQ^!tw+hP zNMR`gttZAm(ZeQ=ceZiP`kw^jFv*P^<8Na~Exa*<0BlG(whWu^r%nrl3Q$vR`ySn!8 zo7`nR10bO`+-S_n}eYG}fI=ag7#zgj2G!{NAkG>|9t_FtI!aSk=xLdII@< z$*pOj_=1u?s^WsC0`ffYsj{Z#<_c?O;?(M@uP`&qSYjP+uXUw)vkEc{tfHZ~GGsKO zcjIbx&qO8{{GAs7`4dC=m#2Dk>_P%+LULfeA$6J4KO| zkX~l=Gldrv@1^oNY0Bu@Y89m(9yBxBs#5}w2>CWF(h$?EDi)VRBk1)N)2X0Oz8QI! zj}P%b_7eB+wTE{g|CT}B``_`0z>{0>huo4I_(K-Iz#oGB5eMS49e*eg?9?ORm)Dn? zo*K@$-SW~utNXhOTQkyIircRUtN(Ay$ZDA-u{**1(Uz&Xl%#=VQ|Jg%#UVXZuvr%{ zPO7)8md=FJN=x$d{8_XobnwJ!HFofd4St2Fw&9^zpR|NMM!RS;YM|sU^4*4<9XK?^ zjd;st?wbyqgMrF&s*=q025nwFLY!83Ga)uegW{dc$YvLQ2L+V`iUCp%;h8~AowKqE zMRR1%t18)*t5xG!n#7L&{^O@l^bTItJ_vVB_2Hd|lWJH-xLeKqi9NHCAM3iBhI^RG zaQ%b1d7Yn4ZcdJT|Jao|!}-G<_Qaxu;UlOXwJl9ocQn1E)r1B{Ct>)4N)j+z-UA{5 zasWt$A-p?K$B2_b*;^J&6P7Yfnr7C6(Y#F|u9sz$icfvwTsKZ$;TBdl|>oiTgF#Eh`2 z=2nR0KVvDCKl`4ExfW+DwKrhwY$Jky?#0;Cr2Rt9qpK8-Olu;>PR`#x=$t*ky}%E) z<&zjnn*~Bl@Fip|Kax7rGNmYifRhVNJw`CeWRM2;>d>Z4C+*;eZfOB zW#fKPy;IZq$}w-?%H?S3Peu37m?qVZ)YKlUh1ch}gX#Ir4tos>bd(Yw2-*UQV^f_( zF=}J9>^dITu0vdV0J?$}V8=AC3Gmdfc-?o=v)Yxma1Qleli6A5n)qartDK9(d_&w6 z;&~CzYNa+0;lU~YlYg~-toN0kAN8UoWG?$L{l&9kk3j$(#+hk`Db)Zc5(@Ot2c6O| zMEc1A-d|f@pqF4rrJxlX${kZvQi-PxXd{CrM$qYCLd2kC35O1UMIwOL&i--gzO|iu z4!%mADG$7Mva#;0?E1-Y_u!<`p|WtHJoqAwWfb#PVf}!n&zyn-4QM*YlDO&zqluc$ zDpv@z8Tk;@la8V`;6O$7@Z#J=qy%099^i-ODqI3!KxB|YQ3O^S9z`y*;N@=R$%=G8 z$RKW~Hy3Q)&STk>5D;}C;MjoL9QPH(zY~z%k9OE_;!$@~YQHX$2rl;>a*4q{V^Xv^ z0AYaH;DmugMADXF8B`}Q>0qxtFtK8f{v7+3ZgDulM9h6 zqv|6;LSltxHBpaq2_`RGmUPMh#v2T z53KH*s_SSSp6wkL`8BdDucH0hvFjgduBmKYT4D2%&vmy?FEMxIo%y53=H`!3kcj-# zgxg5@Gx^eia3VbDlFbPJFLs%rKpJMj1wFO@;hKfe^C&kP4F|S<$PLPX=G#5Rciwi}?cMtp7mn;-G0)Fot`skLSI&X# zMHWXmceB@|m!a3BjL!*31$#n~1io0ONtH4ZPIl42Kv^Kpq9JyncTZ#b0P^TNcR1X} z85})iQzyOeMfr6_bBZ5{)H;p!z)M}SY8;te#ZRWv-g(VMlnsFij@Mn}J- z(V)GylDMhw% z@yWYIRpl9Wlcjs{x|_CDt5{PCii#{weR76Ql%~8^UYOnJV*MjSlWNtL`jk{ten(!B zTCM@8-p}L8QFv~f4`P<+3aA8*IrSO*L=6#^&Fz+Iy2FX6g7?*9A@@HDRf7T4AC?_>A-#dT>1p85pPEyeS-#=xKWdpEv?AD>m( zWA_I)aDHMuJ?P({#~hUL=(?oe^XLB?o}UE7m*_Z4Hm3Of4&WdCz1$FceyK)0|I4@^ z`3bT6i#KSG0bOn5{{ptJ0l0tLFpMY;NBXS_i_I~N00*uCj&kxQhLN&tHtkgzg|@uB z;=IWT_};s%6_xCv$l-+v8b3Y%AxQN4l2!fZ;N40uaK^YpAAzY`k2I%-gzq%jqdU>(-rw!lGSu|RczUB$JY5gA` zeU#l{FHKD?PJI|-;P2vNAdb*tP4OdkT@RYzI&hWtBU*qm#%E>rj8DNUQ@)G6!|&0u zp8B{uqR-&#ES~NERs6GQJ;n9ln{n6WZ^fS1*T3y~*pr}(@;%_gv6{HCj>o`n7x=@369j&Bq-|@^+H93_{{ira3PEVuk zg-Vakm9sCjFKw`UU;EzoUW>dGJbK~LN9BgjCpx~|$=-?lne#Y*H(xi>C9!UF%wjjw zYQ4_Kq3XF_Fp<9TVTDYcWyRscNv(w^) z=O3Uq3Hn$A7$rBtYvBP3gm|Kc$6t=EHI&t~99#JMi!C)bOz*ok+_p<@=;^EsC#VdK z%_F07!#hQV6Q7Q(?=CF=D)v<|>Oy}jw;@{`mBbF%lgFE>ot=CRW^=4-8V1K!4 z_v&#|QopO`?9{}~y}nKp6hK;MJ{C?#$OxiiQT%n{ZCr=w?_H(UXM+3r_sld0@j15O z)zUZOp11kEp1s?@M{_3`NAJ@a1JY;lQ>Jx8K1Blxh0PM7)I+3P z`Y77J8)=jnAIVGc-Qd5(eV5BiF{VC5`{H@D2f86>82ug_ zI*sosw7nO!74_YhqHUF0!MoSPO&O)Cw}*AU{rc;Zpy*dR|A6O|Y`iDiwS_;{i;Q z&aCi7v=sLcAJRQIvyR5m4189y;Z^1oBuvchv&zW;ha$}^IyH2~*1-XPsTl%kmCsSH zM+e9MWsYb}uT=40X0~^#U7nOuy(L+mym;b~TT((bjzmjUt$mXQT)tp_T)uoEy5@2s z-%r6X0dJ82SVcmEN>#~&1`sc}FNS4^b?3b>C@civVL5R!^1I1NW+P>gX(Imvu!}$7 zejFFoK;4Rw3^7MaLg#jieTqn6SLp!|%R#Cu2&CHXZ)th8rKQ}= zUNBWwnj+oia{f*{6S%LW4B{`N z?hNztv99Ai0WL#m96G~6>7ubpe(24hU38voh`jxnCn0Y3K*tedfsVw!v2~vCb^raw zvIOM?I&^N>59=B`1p#HCBSCj&Fe;%P(eWNrpmDhCVn{1IV!#Sh0ToXQ^v4WsDosVD zT(thvg$cYL&t_gu!!sBOX!t}NE%0=b$$#PR25vWCUN&*Ni5q3PN`^9KH`9@7RXQ~w zD4{}3qGu{8EBW&)Kl;h;&xTi6s+ix2|N8Faj6!|^kra%@GfwwbKB(2q~>ITQ_lvE$v(b^aUFZO_i+3k z=KD+;U#5iahkS&oDe=1ud0AUVo0)<96ft7mB}W{0;BFoJLOiEjJdG`E!)dp%%*U2N z62Jj`Dizq3>W-;&1GL5e;r*dCgqVY{aadA)IT{?T@%T2OZS<^=eUtq~B=U0e)sgQK zW%okLVKJQx6C?oh3fT{$^zE__dRf^feMuG*9m!t3Vw)_co(k{ro(d*tY-D37-YDp0 z--!P*MsTt*Q3wVu@UKlc&G3d zY<`!YiF{nx;%Byw3#W7G##^A}7%VCe{C$Y%L8F0m4EQrMuzdjL1}B=T54~?tl`Ns> z?Il#;U{QV?sbi^h6oa6ma!zxnl@wx>sRUINg^;^I`SH4(Qg3b${VNK)GXo{TfIre^ zwf-ruVRn)&+pNF$H_oA%1(w2FmQxly){S-+HcMr8P2fmpabG4I&pf%Sq$@4*bjB%8 zC(J`-1${3NeT}&QBGNyrV$U!Lz8D>euQ)BhSBJOJg81ss@V2#r7JjA+8@vc3q9TJQ zT~R#G3vv;f@G4GVVl^4CAE)SO=I}fUr z3XxE18$sDuQNfdl$UGqWt%+8QQiD9MuWvory^OgVY20a1LtFyIu|UQS-tZyp=1{$w{`9BzrRT6w1*> z-4>LiXeZZ2G*Os+jb1o8uz%mb^Ov%m@#Xz;!@;Sq#ok%Eagxie6lAc%6ALXe)(Zy7 zzLZ7MEzN`gsAGm3%>;qvwC%Go zTy{2_df2vkJsE${Zl7Z0j!o^1NqO)UegeM2O$<3CvZMPkKVqSYDyz@njRz5MfN=~t za2r2kl{zj;B#9kmn<*y_Co0uHad0^_l+(YnYDa5J*FfcTP06S?!`JC9tIw*>E9wY- ztY>F(@{q46zo5XG*3n+x?z5TN&6fNin$?>vx%H5de2jcO9uw>FW3e9MI-NDRPV12s zr`z!FnQ3m~bA*bnK78r#^|<4{2OiABItrRp(8_atJ(_zNV%I@AP17MIzz|djv8W#vJyrP6vt19lMymNiy-| zC5t72<_F&`PaG#_8~)0YEt5~ z!i4hxdIK6~zyKx381~$5%H;y_l#>?07!WVu_mKS1L?iY%Vq*b*a@r`wwAc``W`{*o z+E!IwoaV`m61StM@X8_$LrA{7(AVnJ$5T4;(BZoJ_PDuIY){N_Q2OAd=Lkus+yfnT zVJq!151I_Tme57K#oiBe)JH`*&i)jX_gWOlst(&9CVCaosLaLv;9 za1P(*Eq6L=GT8}=iu1mA@U}J})`sUgli}coO90jyF&xFRU_e_CTyt`LM1*BwvGb~Y z{(LK{Qvf7|7kSwQeUeIT)GseQG%=BoqSl%Wv*U9K7L9B$s^-QoEU^9VdZ(*4BLe4r zaULb#FL?AMe#EX5|KU3P96ji-6~}>_ z_i!E*-}Uc||1R;MxE@5vf%6Ccc^mULl0}(-1R9z@c~ePm;L`_K0;rl+5JH?&RpAVw zyPEgC4=n$~vx~Rfvh>_nSAP3j7G(BUUyZyGc}+Z%9t^D$u`q8KNk^pC#%PMqgik^* z=~Gh3#llob$puBN>?dED{>tK=h{#4h@v~Ria^#N;l)$|C^Ef^J5&sE#{1QK6*NGmu zPWy4&`OLq^X(7JnM~H9pdqfLyJ@{Q*2QOsepRZ!v2_%O}MTynYM9m4f2)KAhkPY8R zkP=cXDJ0n|s+b4PZsq}$dr9Oqc0XFJhHBW~ch^Qby7@c#v-un-NdR-;j@}LNPA&s* zopcOO+=^n3;(O#Trq9W@CG6d(1RyzG!Lp?j@=vgaCTXzu89$Cvj_JnJpYB1PH2T5P z8F?3#O>BO0$Cgh}qLhe6s)?pV*h4TfjLfJt#f%ItA5b!385d~w*8E!eCmh2b)w(Am zUt&8zzjmgT-ezCGI8rH_8T*s+_DQXm*sw2$gPq0d*mDByFnvo(0>KitR8m-2g1@-2 zTzXf2pAqI6dgbDb0rO1aGW9oHRgN5}4U&qot76d( zMIvKkcnI9ys8^;Q(G-&eck>u3ttpPzeLSBW)xct5>5wIi5D)r^^Z!{`A9BHSBHv+m zvy#E}LEd-{w8t~w$1{z{Mt}r{qmyglbS?@TjyG!r7D^I`3s72Hk_{kaI9r*KSAb!} zRER?2SFtQBEUfv9Gb8)2tvd6-{PfD6F6tx39O2dam4p3l?Sng58pgf^O#?mkV8tOG zWHoSiJUotgE2>>-|KgRH3F^BnR*QqTo3~bwzYi}Ymm_!0>ng15kN*K|^3k)esef_v zG;lrsfVbV1y|o1_|Wq0Ksw|oTe%*9;uRgYk<@W+!mg!e^zgi7ozUWYRK zOY{iMC;HPmR9aOj)Fbr$KUnc7!nacoVGemxemLmQFo7@->)cI0G&nGcRk`WRcL{S?x(ev0n<$U2D6E$!-8$sERx#mdcMSgaQ6@gZO z>7ZO*i^DpHY0=ps{vv#kbP>8SIbkyCw9`t6RU(aV0jGI@gR4+_N|3fSqCr@7=_tm4 zE|e>mybHSVICTm40( zB3ZfQ{V3$g^=4&Qs38+k!l=vMP6-sYRfI^KtDsuz{uhcob?X-&Cz?Ea%NIU=NvcHp z{(GP?@|V8f#|T4wLVe_L=Kc_D4G#>8`j|Hvel;K5ZbE5Wg6J$DfvsA?Iu@d5dZ9mG zjfRB4psGfHbXqX1jsOp*<)Q6z?c5pe$r>4~ z-S5lU({TK@FW2-`IURvgUrDXQ+@Ino9IhQ*^f>cMfk&Tao-n8E!#E2u&ST(NE6Es? zSIG>@C6!1yU)cJ3aW`V4&FMwI)|P`-VTt ze(9*Hazs36&!p+lCEy{{qf@>a@5zvA!`0~tvWDD4a5y6Q;0$EGUIzpfNwtR81$Y{G zkPGPyDZ}culblWfH(PnwnQS32Fcb<-BK{xMp{fsjdgke;j~t&_n44Lgx%#l2*|)UR zx0H0pf#;uITv=Lp_JzZ@CPJWM80c~RuKZn$#Ui=s1jEDhmqu0S|mj0xaZtj+Nz9UI3_W6o&EQf@)T65J{`iNWrFi z1)?E@)f820+gT257SyuQxoaAmt{e*VX5~04Ge>6j?9L9kX3}chyZ6kFWL7wHvU&qU zS2i`Co?8Q^$ifqc4m>iQYHzjJF5GYyc9PgAR2jgJ@F0~oqp&&4ndS5PAmk7ij*c7K z*iL>+Dh`N3=y)xU`pO*vtE0GSY<&N@8*jMbJ71lcT$)&rQ>z;Enoi5u?rZig?>^KQ z?&_l$HnH$;cOr(8ma(-e_ zzGfiuGL48%mguP9k;j-^7?T55%#Ls~tYyeT6wbk&DH#$p2Cg^-fZhspDxgEiNOso_ zq(U1)|G(_iY<$mQL0575lceL|5K&CF7{#Ea#0IuBbN|enZ}Opi>wY#NM)vK+#l@Z* z_}JX*zt|ib@$Kh;UEq)c`&n61gApf5dewt{G- zo&%514cxK7ilHtH z?D_EI+$RrA+}PE1!{j9Xy^-@WU!U*FFG1gNQ4G|M1C8~;D+b1eTDvAhN`j8?iZFdi zvY6xCJO&6i8lwjY*<5o2+BK_yI~2VlbW1ZVaB7a(cb@wB>76%3{>-j=qCl6XSD7qY zXf@wsRqGY3C-OZ1`_N%qdunn)KC~|4V(hQmF(wt~WJK!8YXEgly++CKT*C3R#h^4m z+$;Dt0bNTa=uYUr%$Nto;FP0`p{R78AUlEH=*O9>Sm)Gtywa*my{Cg+XqR7FuaI9F zbF?|0f8N#>dHlr}@dS)O{#Wp;6O~gw!W%Xxp}(aiQN~7sBU`7{YY8C)(RqpK5t2Yr zjL>*^+B9<9Gt%AJ>Anna3WDjdKZrzr_~EMv?g+*>?@ga2JDpw@@}Sxu#a_j-SMGRv z`029Qj+By~x^K%Z->K^^N$Hx6{Q3Vx9{WIPQ=Wz0WXf$SeH?#&RyS0ndB3vqeN9n+ z?JwEKUyHnMDJ?55vtsPD*Jv$`kW4PZF+;lmtR_4z=*mW1tt=-oG(>>Rm(<~qB!|lZ z+z$B1qE?F$XGU~kJ#mX_l0Cubx~?DJx~LuV?8441D;rzYFTVdi=@v;F*U6udzXPec z7&bU?U?Ud+87)eyI|wWJ9C_2CiWHSclbZv}OfVKWQMP=H4@k{aFG1nNsS5?t>IX2L z%}ffUpX=J(rAdsycaY*}g+E08#N0u%Q=c%MpmQY$QUal3o7-q~7}0$C({qf4%SUt9 z?~xA|E*D){GhLxm_oy{Z9XO{j2m3}F*9VM}7h^(3$`}oqx`4xASQJAcVTG(wT}ASW|Qz+FA{W7uE1#&T#?BmnS{`6TUJ^bO8DnVSPKXG@K&91Asi+vLK{3hG3J(yLSE}!Qn6_ z1)4FHBx8m-%WKo=od7ueyU0uO>7GX)sBE1t)oFS)y0UIx;Qp_n6%vhk38Y7#XzW>N zMRwSml;J{Z5XZNNUIufGvk~s5G#9cub>MK1icp*(VJl#_VF36q=tf=@`$)|0WFL?G zT9}?kVR%Lcak#x8clWQ~#9n~qxqdhIpO9YmFY?Q%^Fi(&)1lRxhE*cRM`kawN}l7R z=DHj1fqY2^LswA#C+hl*T7wFi^Js>P(Jpb-ntF^0*l%b>dAXSxlssQjlv|O9MkX1- z%%Ib5PPe2d=qQCgajSkr8U&i)@;A+0@9XWo?~1Dr zA3k;J*inZgBg5g$%zVO`k>SK&!_H40I{4Vm*~bqZdVJ@=htHqCaN+#<55JY3k&zz% z7es|G2sBV{V17Z}8*&LQX?4(&1b@pPRXqg!^)y2Blh6R-EOv~@aS!%3ItOfK)3%p}!SKs1e{1E;ZtQDhvuXj>5M%%P~qWe^9eV$0-jmV0{k*Je1oovyL|s*b8GPv>0Q$gz6j^8jf4L5#afx;5-VQJevovamkVfG3Yx zpr39j&@mMJL6lHS=-8qIMmpgRE|6AEM<JEDmMC-u$E%U#|%SRm+yaN zhSl$Z>E3olnhL2@43_KPVc?XPTAclJKJ}*_okJ$N?NVj zTFol%mMzP+Y(oqN458yd0wJMeY`z5k0TKuykN^Rk@Fk%HLTun8lmtFP(CB;Kb7zZ+ zg~RXnmqELlduQgJ_q^wA&s#?O2YV()x>`FT-tJ)LFz7S^J@{qFgD7SBg&lA_R9HQ7 zMqouyAObCiAXH^CESHM~xN5-VA||rEAfJ@5wh*tu-&^2KWyi1PqU_5nr`8Lz-s*+& z!4oUJ!-a*4W~Fzaw5znj(#?LKC%C%GytSWqc3W+MDE-#eWw$c~97*1{%Qoquk^uyPzDG*Ci7kGv}MPl87!vLi;O*K5`g zfJjW~v}jny6)DVVZ?*OM_oz_Cxrhh4*&COu@#bcXQK~doTFd!dHiLYiSTqts5hhKs zGU$XR*3^LW5GNl&wb|ixYwP(~OYZKf?9hPFOc36vz@iH3^updmR8vMN+K1V8~%DWp2(F=M!hkSiRPfiFNybEK4q?^ z(}Rc{^Zn`J`{Ne6s~wON;1`7)kA$vIIBfVS93exG>nMj`W$v0FzrrLVg z&3z**e-p=iuBmsV^?!@{|J~Z0Y14Z!h4C-iN^L`Oac+A0@}*p`T_NkjSZ#V12#Q}| z51pi+bU2_U-W>yn6^U=?n}$Tt`cRzBC&3b6*dW&mjH8A*XyyFMp;CYkU|>m{m38>~ zfsyhWhO6|SEgwEfocd>--Dq343?DJ=a;>iZEj|m+0GkTELcRuD9nV0REzJQ3&x+`A zD@P6p@+TmBj&UW4H%Q?e=oD+j8b|F7Jp+eRob?_6cJ9*h#0H8FnxpH77d;6>L)6yP zUOiPfa&qN&N~_%~taj>{LNOy(bdRjj)6~Alba&evwRiJpx{{Lp5_CxlUwbyZgSQDU z;k->1B4BQ+3E9crlITy9F68fV;1I*A{=j)DNz{l+Pp{M<)$x-zc#;!dwQ< z=Sh~>u4LzYP7%{<*qpOESrk!rmb3aZwdJ_k!JYx9cU+FIF#js^uS{?8df+NnCw4y> zT>!UBwwgi-dsV4?J+@AurTttwOT9B5*QLuveWtg2?Cg{3)|GwH! zKeG=FHx8_^hR>`WU`JtcZknI{w>+Tz=}&bRK6>k;x+_<7gypa+KfF>BFMt;uglt)u z62tPaCd!QFa2((WSei#jyyA>-YX=R$=nsb%>Y{_Hf;Q8X5L4N|!cMNN)Lu7Hb%b?r zKf1bQDuAU;6h5ilH8!f2k6|PT_t_NZ@!bK$jdoY(bm$WTq=e$md?pP=2~_h9%wS+^ zMjcoU!W~WUDei_|JN#LKK|u&6g3zY;kO1|}q(>v83hi29RB^$!Wm1Lh*SmINKWpA; zK-Io1S;5yhdbPh|?N`}NWB+v{$4>^kq$>U%*5ndGIA2rMai2j{siVjbAgzfWrRW!N zOowK?f_yi%XQ;bY8o-5u;sE^cqyo_)415VwcT#)|^>jt|Iz1$T6Dl9wG9?>|(6LQl z)r#NE7{Me9mzBuoP@Z(AErSz#7X1l1OU^FV?9a9CsXVF(-OCcUZAN0k}yXd=q<42Lh{hL0j8o9xDaeD?~=XLNs02(|z+B1SVgF=wpa7jbNVOhMG zD{dB_S={}d8@uA{v8mdBeCmeI_~nNoTc9`42jTPJ_Rn#@5RNzV$zCBQ=-PDH6_kgG-mCA)Pz4?)U1BDopz~hR1=iZ0Xo$l0qwZg0V?jmL8Z^nZQqZYJVD3l`QmS? z=6BqWgbKWaC=2xT#@_+xON1QMYYDuCpz_Yrb#UVbgnsPU>u)7e-+koC z^EV{+r>da#d#WGYB)5c}zE7lCK`)M-qAku#!%j)nUx%G0MvJ8`PkU=}JQ7IkZdo~< z8ZVVP99;uVdxOEbwu867F4LZ}+WbKWLTAQdvvqth+m^D~LLpl$<2B8iEVDRYyMUdx zqW_GNaa}6R!qyAoeEnvOGxghHoabM)^u!Y@hn9xN#zvM7F0n`Y=I8sSHAfHJa(HxL zVD#`UYe%(|5dz&B!LwmDBeYPCIshi!CS+bvB^=_Sk03z99-)*WDKLWoStQJaa4wRw z+w{o%U?JETn;n$$vT_kn31z?);WdAG43`>?mzOmwCt1LcJ zE|l%*nT||rb0Lv2wQ3iKD(n5}p~0y_>(pR2zkJ*7J(tdQWXA{N+0o2Eb2>AVO}1qn znIc$ov*%xltb&9F_ETJosI}Vx98@-0z{5|#nz{xE&0PnCHs>)>H|+PioS0dxhaXg8 zr8*Ewe$dV+(~H8OlJr0ngN068CFRK(oD)rR9&Nogi|6xn?*=E9v^!Td*{7X4z zt{dW>scUghvq_J4A(ZMeyQH)-yj!~i_oPA+dMq+kHqk}< zumKd~1K=>d82HJF2G?%u>GmwWW$EJ|e{?~wOV%T z5wVBVAMVGHRaTesd>1C=5M^9a37lx)LhlVDnhL~abeBa$?zjgVA zAK!EF$w!VHJ$mHGv124B_Tc${4IT`_v-@<_XvGLbm~#pr>h7tFmNbSODgI22UIfI2 z>y-AE;#29+6;q^6hlE^6OHT_Lz~h>8ulJd)%ViJlHOYfL2}qwWIah=!$(s< zNI^3N!y&|PW1+@yBZlAF5s0W)bsS?n;wbjw#;wsP2u8CJEql?teG_S= zrce^#i$^4I@E;C;z4rbm18TQMrt)Z7%Pe1_!@(Nn>;r!Hp!>CtKTcmQgGV8V`|AvD z@Gdyq3MBxz)mc$-xD_Zm``1^FK9Qd5cJ>V*=jW-e0bloA?QJiA+1t~_pq_P^D?NAM z&pZ1^RDY7o{fWAF^j+-h?|8@84dGxeglFH41@v-xQ^#3>V?sqCN(A6e2D|eXfU9({ zaeAb#t1uBqDAg!QVC`lmCX*362K2Y>-8 zWbxurxmSY6L-r7S7aRmKN*XCu4>DluDt~>`kEq`PEYBKC0c52JPdEyEJsCyLK6YOP z=H#JKvSkTl_3xcFSQHxBl1!~M=)*23E|YlCA=~WINSvaArBV)rRo4{>MDR09JEP6!tvl=)*bq=-7>kv>`S$wk3rjhsa9ZL zy!^t)NM2a+xzB+vX7JmMaMsifa8`84<>lV>sul@n#R07cWyz^6mSLj-01==2+4P>; z-%v_=)`k^T+O;t7qD>0l1J~@tPCr%Z_8Y{ly$!MW#p{b+s0gvd8{o2DybF9Dk2Y zHgm@xzYmj0LAM-Ru;(4MIrhO^Q|(4A5n$(ChdowlAgDP5Nbr1 z5l}}p%ogg)odWJU$eypCrxx+MJkt!BkrZu{a9xTHNw6-C6o+*WK)65v3W5!N zdGH344U!s7zaT-_Rfh?Xt_+9EjsyYrUFkSghZM69{QOR)K%XF2tsotzv(oVf|0Wtp`29(C*KxawTa|j zWn%L}&ZkdrR2HL&mBzlIP*=KXqVcw+rrnL+z)-rQ*Wa1Xj%R&`&e|-KX3tPZrZeyM zwM}=g9dx+*td9Ots@UlFw$0$H@vLFc^EuG7#H^C(;VLp6vbLEH!C*XdfT@*!q!%kF zO2yAUu8TLkUZuBQeMuv|b+eCl3=PzwI1vxu0H!Of$wWOgKST&drK4#r&MOjU>fe*y zzLy$~;3m9d9fbh`c__G(-o?w*vsB#Pf;NOqxkw$_F_~Ml@tfa6RuHg6I5)|7B!o7u z;0DY9((&mXaB&PckXD{+s3JoV8LQ}*L-ryEc(&ygMk6B$dNauZR?>I&p0eBiVCj1Y zzW2+cKU;c}!+ZM9j{U*NzDn2pn?^f^=6gG{1F7I{F)}t7$TfVU_G>1u)oMS$Sd5?i z%2bFAtXfSoCQrJsG8)e%5@z#o9Q!m1VY2}_7p3krCM9em9g`u&6I=yk96r!-o|gkM zapneq44}|jKeSv0a$}e4L~ih6@B~Hmp&Mxi9=eK@va{)>rN-6P6RD=79lMs6_$#s{ zw!c#F`+sox`F{_DM#71O`A>bkQt!kV8zaO?N8Kg1t#u^M_OQB20gL7wWvkwfMjD#Z_#@`#@O;tUslT-*?qTt7IR;) z?{?Tvui^WS3>{=Z;y^0oW+qc$$TRhw!}jAe90MEF>tDeE_4d2sx@1M+oJR#PLp)A1 zN05vLrCW!;Bze6la5yrK+3`@wW%kvlql<0()`!OIDWl163dPzx%Cn)RXP^%M)E(Zt z_T!;FO690rnaqE?uOn#xd$^t?Pwa@7d=<}YeGyz4k5})l3|yI;0XM>xNsD~;!|W5! zrt_AN$ezfi3%X;BQyK!1%(e(Kjme-$viU z_?$ZWwv8?Cc+VF0_R>DI`kOzG!ruUL>(eQ%b<8cwB0I2U*p4bHSsG z{u#k-Kln!6Y=7=trnC0GCFWZS2Ex-r5~v)|n--#tm{i=v{;p;*wZ|n$neR;x- zuqg2jzT3_Fvm;uxi6!Gq(Tr|fhis*)dVYN1-ATa)I2Gy5Xc1XAo0(NOL7UT-VaQ5B z1aoxH^sv9h)L@F*A`whT^DlI-tS@zREsiXShvvpKsv(6cotSnMboun!k=h@#;n9Kh z_1aG*o|YX4U2cvkr+zC;dFQ*f`1)#0dFL&3QiZimu)2CTVcH$?* zhzLIrd#c!Br(58Fco3&S_P?EKiM(!}i=~32pg>wO(w%N0Y03>WG%t5LQEe*(15S_A zV|7>^7W1~fj>b3ixOJ15QoM^rfXga}vrMpJlr@u)ejAzVySjUo5B-Jl++V8C_xJS3 zFNzUvrE`0IQZ+mBxaDnQZ?$~j1KK6dgIAt|+@~10gW`wqnib^O0Qm$ms*ovpz7S3Z zm-H}sP{P868p_~dYo`JA%MWaMxI=XZSH^vKijO!sLJln1 zgYhr0^7M&NtfpWL&bx*&ysa0EjVzSm;y9_t|8Cly~J5GM* zJ$}FFuaMkQA!g8qy>JNclwv33nxlsu{B&v;LjOX375^6;bqcOr4eG)Hx)vWMi~c%L zm&^VgKK*r|E^fHivzH)URL5AjQm3S!El79URtC~8w$067?c1|~;VZ(&cKY_UJkG2r zv?8XOfSjh8A?V!ixAU2plGg;sG!e^*R9(Tr69?vAZXd-;9)*86fwIkFKbSV6tg)o*Yh{O+;sEH?A$zU*o61=%}bI#JIw#9^pU8|*m|5F8LDbi)Dm0cExb%|&UZ z3N}Lx*fA9Zz0>d>J!HlU!$(~{zZ3_m;QJ5Y`!&dHr5*z);sHVns}djqn#CdCW)Zd>JAejmn5lqoHtI30 zQ!Z$jhOkw|H1uQU-{}+QMvS$ z>Dtru9bF*oZhVJMn3KN43!Dx%4O3jCdL)s`yGMb9D->fi&e^kdm0r5EeG8Bu9)R77 zRcldmLh&tl7nFU&yssa_jCAA+f1BlNU-|asOL#i$^Fe&a+bJK0p)U=s8Mes@Jdam6 zT6Mb6#|R)Yb``c0MY!CQ+K=FV3sj4fRy#@-{FoH)qOF*s`Y9(~llp_;GFAgnk6&4? z(lj^+O=3hziI;hmS}88N86B3Ylr>F6`aT+@LE*>;F!uOZZJ?JaYvF zwzv;5DxNc>RDOxCAN~V)%yr{EpSancPuy_N?No}rXXzs!fi*M!V|)c@Og>6G@(ymc z=i|S5&&OYM&nY99@A|ZDE6+isWAO7&2muG0b^xZkph5i0Af0l0am%10VG!w!| zbB6p`y4)5M>tR%N)$XrpkpmCJgjt@>!Qh3UO6Z+B0yv6@i0wDyEQ(^s^+jK=)l z>4U#BY6}?br>KSt41eX4_&)KA=m_F!Ke&I(OBr~RUx z5~UrGEC^|@oIUblAt0i_h(5w7V}EZ=+e!@{YqU*d!S1HYaL8yzx{UZLc_7wci1-u@ z$_Q#}9Vxp?Wl0ng@wToejkUGZU=4dTrtW!#wY$AR=ePNs+H|2gqEIz<^mw%fh!|%> z$52FnpV2gAwLkcZ{YTS`A>`KK(S%g*SNh#nm&&Y;r+h)XS{?U$CKgs2gVoMLSg!Y4 ztuA##wQTojbjhOMF`U;#(g~ML@3i@L?{W>?n{6&R70?zT@VZa@GF+80VX3-@=CBJL z?T}SIKqS!!Z#Wo+-lAS~GBEx{2z!*;DlYQgpz;e8xPaJ%+M|9xGUPl8vblgim+_AU z#-fR6T%|;%y+pBXQq~D>CH_YXZOToTC=IO#?x$lyP`i{f1cWanT7!*6zo)CK)oMv& zpx@}UQPbGkYL9iL)lZr7X-$ji7EDi+=^XJup=8nOV#Q{?J`z!5$W2FUEFWaQ(zJB9 zCmep@FG@?LVzQfZ-L9I_?p0?@_bK#|e55$vl-oDw(IpzAYO^P4)^yFx_!5KtahFqx zwTXi3%Kw#3KrWmU9u*#_-ZxuC;_Gd|3o>X%q+Va!FH@mXK)?uz18S8F^u%mOQK7jg zXq2Kxc>&Oks8nA-y_cva&Id-Kx&WCfs)P&p_)AdPq6}h06uB@Fk-dPEHFxpC-FF?^ z*t@c4_w*$3bUqQ)Dcu<-Cm~oC3<`W5HJmbHTH<4gZtx^=QDS7skotY}15~X?!pVat z8uPHYlM)_?{*?QGcN;}Y4@Lze!c7$CF^W!y@^eaGsKFI-njEEOQ$x_Fb~>~!hcR4g zciD4+KqBBx#&ssG$LfpwJeZ}O?M|e}N;+%XWJ@$*mg@{U3}`5?6wKMMJKhjd8J`$L zYFLve-h~Wuug%rd^^ewp;LE)}t=(_SH$wO-HEOTJ_20xXh_!P;F7U{04VCmiF12Qd&bYlo?9qc>Z0=4QDb&|P_z=tdl3LAX?XunZh07RBb+ zv>FIGyo_*krB&371AtL$&LH(vt5j((3R;CytGIyUfwI>N*iKaYU4WEB(Fisj2$Kvf z0GXy%9w$YM9fy6ijwZe`QXJEheZ4(hh30$~ZTNyNM+3FnT3`!$NG}R&@PJ!=*U1AX z1etc8Z(5Qw0sX4vAsXor(dKgN5=CG2?Y9}lFFDFiwbST9ORsFjZ}BoF^E;Xc(oXfl zaHOEqH#u7ip+twix!C{{b;2swCYln>;g;rLzBwvadi?68cu} z=5%&+y&yk)^ypo7>%7x7+uJiX@I2TKv~XT&VBZq|Kh(#*qUwdX0EQ?N(IZtB1Ra2f zVCrKd%z4dL=- ze*b)|9iNf(d05V%#QBe zcb1tOrmg0oYS(bjUrDqOA#(>1XLy_NNcEvv0JBf-o|}#;l=4-k)8Bdu+ipS6aZK$| z%Jp)k{-S^>;dkm)}6FhAW#P9Bzg{Kk~y|r#v?glQ_s^c!+N*b_KL8 zk(f8+(0MFMTPD`CJehVhwx{L6QpDaG?LNEeYbduTW8UaQHQk_42is?wOC8CMc5B;P zS5pH%k4LR;P&Xwjb17{+;mMBfO8P^3U9LrM%LTj!PsM9->P-p*I)d85YLio8Yl&)X zEnTUwL(!lPtUjO#i59D-SoOQ~6z| zdQC09`0Q||RLYEXq;%oDPNP?vMWxKvmu?y@S!A{thK$Y)HM(OaZMHjX);AWtK6iUL zHdhG*s0oNd(}1i7O~*pPUbJ|o58cscN}H>zF&W=efm zQdB8Ak?`^8GMq?xfQi~O7MP&QNhGq1;2g9P5%fy6{uos(;p2}%Bg-LjDAk?Z+G99- z#3lGaVtSKJ-twjgAGr6P+s_?5Fg@8{ZEMYC>TL1^dtxV>NO<}VHo?Y0EmyF)6{D=q z6_WU-3uJ$iD}eo_xly0tL6MNS}W4)jNiKXc}nG*+WUN} zEe=sRTQY6qJ+a- zMg!VVE)ufE^P%|O!v`~wcpluq-I~%ph)+SA=l9X6QYm$5Xj)A+ToP9o{HJ>%e2cDR6G&g#@HbW{C zQizKDOi>r8Rw8z%TpMsYLuzfH(ADcRLGu6pK zcr!V;*lsWekTJ|~N8#y3Xc$Nv@I{>;b_flC5L{-Iid2^Euwg8&O6Xxd>K$@I3hVGp zTT;ZWn~_=w0=smM=}adp*mZ7mVW%tDWiCJ*Zz}f&`2mkQeNJ2`GWOCOaI|-{7~7Ba|G4v^i{~=(2DN?a(6Q!N0!>eF z22j)e3t0lPcoJRNHiYBV4S>+Hv>!In0HPuL$2+xhrIu<_rxGBJ4z+y3++NK5I(T4pWADb|p3&jn?&drdxSLJz+a?j-mn@%6Jq!vG z5n=L>E#p*i!<2+D_sS$H(pivtG}WE#B>ZPGf$MfGqa+YAlOUuWuZ(oYyW@%7X>-sj z*U0;KWg1GWcT{sZc`n^?Xex6}Nlg6R%O}d>fy-|f58yi)$ynKb@W7i%!rqHfs~67S zJtfzuE&=EfUyodkZl+g29iymMrGa$S2`Y__>@y^G(;RTMpp~n&)H*?-r&Fa@3i@Sm z0k{Ij3esUAVZjqjc=Z!^-hSfP!S#Ksb29^dogLJk4o6HUyqUe3B&?J>C@I7U*}I!6 z60EVMA)`{<<$7&Ra`Ly(*7YhDNx5_3ES?F*8(d)*%zLv=?Qy7dE}cH#9BJO6B==k; zh1HH+tY@}A9a`+!sir%txogyPuCMnhHQnBJ`jp2mbGvm~eK;C&h$dC6*rSDl^$rbp z+l?kU{41kUrr00fOb|`80bh>(r z$Cinx{o{iUgWZ!#hvXV{DeRPTM&_$QWBJsiE1=+2T8;{YiLID^VGKqm`hba4$s`Eo$ zr^T$ts3;fYF$DMZf*OHZE~xERE}}imquAmg$s!{;f~t5D(bAN1a<15g)2|zwdGoE! z`_7Yrd-4iR3>ZD5Jf4&nl}OMtqf}&$Rwo-;CSvl zsqg>M`*$4G+Gkk@3Z++T@7g}Dpcg&IA45iHkO7;hMyXqZ8s+3j8b%OW6dpkr0a3gY zq(#GO)a@y_NGS5WP-cz;Y*?RUe^s8Ub+B*NurW0U`vJb?hc$coAgdk1`>@6I9q2rU zC#JRX&S!2LQi3Tl84HzA5cs|dRD$5^WQ*7)aSeqUGVz)P$HOofNhWc%iJ~MfmoUID zidY2B^*RDjclV#@IRpuH_v4TMd8}z({QRlap0(E6-(lIcFR_-|x6ReA6G;B0y7~p6 zG0!38)r;EIG4-%jG zvR5268vU0)=Ic#Ayl2ltX)*oK{O*U--@bq>W}?4>(;qdzypqI@NM2a@XDRZkqX94q zc#tURK$@u*-s0vX0!#6RF-5`BR};T21z85 zwyIQdHW}#t)~7$2*d4uaiQ^BlLSH}HP`~0e_x;6bJk#a3M?`P*^4mv?Z{L5Qjc7vW zoO+2WutrQu#3LhWBwTf&FOWvGx+Np;E?+r>p(@np8JIV(0lGF%Jz0`aRMhPqtGBV-H zNyeun5>%U?L&5`bR+_ercSc~fey4l6dFbqb!QXkLx4A1~a5cvxv1m?VO?s@6mT=zI zG?7ty%Tb@%+HQ~b6$7E7FE!PhhVSL`?Q6}8U^f*mAU<9mzih8IU zbOG=rTtVWdQT$3cX;%0;_FkMXR`dBtJZdm&;w^#1;J|RI_0)2!JEV3MvQg+tRQ9=x z<0tZ+;Rg8*e?6DXj&%D&ZMz%|`r>%rSJ~BPh$oz8zXFp(40fN{s2P#z^s;H4+bUW^ zvcQ4gVP#J|rVa0!AI{)IEk>;^6M%i1pE=T+i0h)2zAi-UohpA<*gx2lto^w+or$Wh zvJJgKN9(?>K2?ifZ%GDa9Y@xhw6T>VWeSTZf-#R-6KIp`8nOwM!`hrP%Cx&5fq;^H z1NlSHx95dwwR?1=u>rftCeN+5`sDb>t+)FgL>qCtmD?hFQ<3Rin?k1yLDX*(J)o10q; z7JVcZw5cs^y&k>0TJ=Oy?nE}JZ)hqtN0p{M_l$HeM*}E%w<%pC!Vd@!hjkvoSv$(MHD#l~Mo1>_nHz-rm!eQtE~-9$t7uIoF*iSsnY{c+xjKP*A&8 zP8>_N-gQeK_5%@4(E2Tq*CE(G1>uor(M}Y0pVUbujiGQdl}vsPhNpm-j2!*rZxE?bzBoSJK zK`ZHSI~S$Y87G;02vM_)eNpBrm@#CPPGq9O)8W|6dx zfeY!j7Wgv{z@PTOI(@im zG$RJ3Lh-E=Axo;Gre@b+IK(Qs5>7Odh}LnW*cnW^4C-3Wu_ z45c)msNYN=JMKlovJWZC*+vTTdz*YskXdkx(8bcD#hU6Rd6hC(QP?CWs$+MQKy##t z{NH-YK5L)3tABNQX5xX>Ng&de@uq#K_*u5I4eKeB3&HOvjo zAL-2;xZJwl*f(+K{papD)l=y0AAe}Hf14K6U(*JDg~x`aJ9BO#y1o_3^-dcnqQYH1x1Alu8}lDXb}LaKYOFTlb2AAW)saPfh&uN@nE!@2wJ zyyKp^dH(1v^V(b2>yN(c=<2&}J@tqCrr+@R%iqAd%iVqB4>fnf&%m5zzK7KB@>o?% zhFXaC7L<0+OIi$3uw#Jp8McP@4V@6{`xdBfy zyyDeM6XQ>G_uY9vdp+M3+6Ux@UHQM_L&(LU%<(8tDD+UspfDW%24Z`#L`Ap;aActm zATf}j4bU3WhTMFL;DFC~04Eeg^)B%iMyMh#YGD>i!N8f3LU#@)&BcN)Me%i%)e~RH z3Fn}S!};dwT%`X{wKS;ffB)~l-;vz)`vb4&uRYZ?*A<4=k!uv?NO!_z)9hXCfA~~i zCB<4VtB;gAI>aY0-_mpNbRpE4V64HuaL;7E6DfDnx_*HfnGwV(BA8dxL=m&5l+V@x z*BdKCi~s_Fj1Fihh(6xqM5ItuC}1&R1y1Iqu)+2UNH?iqHt^`X4BDuYh|mh0+*gI( zA@}cvQ|B7z@17n#@T#Yh!F+CiPLWv|^Oc-&EWw$vosXrPzS7?3aA{BNtKPrS)78^| z*!T&p$I)xGv684!d>CzdUuDV#la_e;vC(9gO(OVbobG5OGyf+VTJt6NWxi$ z9V1ubmyukdX|gle;11dB)-Rs@z`0uo_6~@%iFjkzNU>6IIf7oZ$$a^O=(_wu3qwwy z{K{$6h;BY_61`;>tGhiw!yRvHt58 z_Uk89nzB+IZ4w{2{H4(NK;x9HuZ#U08-vq9I5u+S?C`>=`>k7x${Mg2`HSMCj3QLR zB7O+emW7Y1@_KNy-ECLEQ9>GYYlZP4MzA62QAImtVaTG+fXw+-gR`M_<$qmJA-hPW zksWORT!TYz6)oC#44&2iHxYm0+r2L>T57*E#&t56SH(1!f1cXA7-3mGdbm!#V6Akv z@UtM}dgn5p(~svY39Hp54@M5)6ktXjrmHX|b?s2X7*}fHLt#b;%x$EqAV+Hh|I~2j zNh8cfBTUHWQi(_@S_-4HBJ6D>GS)kC`kB8Ts3l2E&bl>Psf1Ng89y0Ffx{7r^V5%` z!y~wK7r!X_yXLg=&X*m1|IypzGvYnElbv#f%S<&XUA1v=8=Ei&v?_T^P}9-ZC07@< zL!Gv=gBfdn_FYS~T>F{bud_60?^CHe+0(Tl8H+dioJm~&zAfWSq_9^E=SD!*-!Bm{ zLFOzbh;T=n36G%5Cv6rYRx&gVhL5|BbT!!=-h+aUxFZRl)fh`go8;lsGaBR%sg#cbW<@*`VTfA*SgQEpP_5&%sOG!~uOJHl z$Zxz6NvBv$M2N&NpN9Tul^E@T-GQ!0yR#_zCtkZQl4~;8J)@d&%aY}Dn$MfnIz?=M z-{_o7KCo0(t}U+ETE(@V)zzN)SSphl7&ZjVwGXmhzjqHRy?(*Zh6}Zlf6871*;^w0 zj!rRr1}x4$6eI$X7eNCwo8pe&rVOTV3(4S?rg$tIw3vhxOHoFpQ;O_YxF^Q<0J?_T z`(&ID(1xZ{08~+}4EOHO5-mQRPLpj=hr`OsV*~N9*4c4%Mx`~H{nNXmj=-+Hxz5Rq z+2bzc;#zMyYx2eHWrH@AQ1wlFLON$hN1>r1Wwm-UlTGP`_TRI1RZDtrVFE!P$_x7i z`zNdmeLHCa58`bK*k@wW39B0MXhcF`!Cb`B&!D7T65ulF8 zn9y3vXJei5PM;Uy2h#Odtrh+cxQ*K~>00{)(r7=pAim;tV$Lq`9u7!~+c z6K=GY=hqf}5p}E>h{cU|L!Tkq>5uO3NGJ1melgjf*V+`t-L2D>&WWY_!~LChb1-6W zZplUMmUl(UE$$grQ~z*xB3L^g$(q80eeD^;h$iStw>i9Rrm7(^7)f`8Q`OoVogHO^ zzIV*`+T`xB9D8+TcQ!H}N@a#-r#lS>b?u?tOv{^Po>Z~38V*waeC0|9`y}j@gfLzm zA*92phg^z-SC9-Ppu02yZHTTbQjpka zEug1h73sWGpz0}J#e0&J%Sx6VIo;cTb~HWd^17j(gV* z-Pd8(k7-O_Sl_T1e!n^dA4jGvRgn#iXWw(BLmYxEiwO@_jV=aH6QN4-waBYU^Dr|i z5YZSOhaUUQxWk3)Eg&M)$LTg?mDjz`gmCSRTlc^&kox<;P32i!;gH`;zFLC;Fo#lz zp@FruHN1|IVaQewYCWFuG(YBV`eQDBLdMLhygF$7o;zHnq*vDeIp|3x_By}EwEg!S_An` zQ7Hw6SyFDB0y&im<*^-axb8MIsKoc84J-8q;CfGIK(k-C?D&t*$gW`3TL(jF=YQLaU?d**XK8(*7Q5*LQ_A4<; zc7*_+o>oRaJ#5{Z`1H5k)ThTv>pnd{;n(~00Y5CUY$hF#`U`;qd0vo|KIS8z9v%yq zj*?H$xBX^bJ+Z-0N-LGlfkLG+pQ#L`^)mfX)vB;B=2r$M=G(gZhK-()!BK5!uv{E7 zD2zSXLa*PQv`<`qek$2KdU&7X`2NOZD&1emW{{LXF@4N66vJW!*|4a#z}|Op8c`1+ z_{>ldV&uhqW-R?CJ~OV~&}SxV)a$leEhdarinBQR%sc6@?KMkWzwI{vM{!q6OQof4 zzIQ@z8))k(Ee-GPv&tQNw9%oK;;>0!?600YT5aQtJG_s1_@Z&Bl`b4qBT+<(ePwpu30^rhCEX5P za^2m_)pQQ2)gV_>wva2NQ}Ik96ZAVB63PgrL9>dWH%xWC0lC2K2|6%b9B`3Xmyr}@ zk%4Yuj5!0v!VU+s9=JC{Ty24XaIPP%Q%s5QvcYGhmKC4#ksJ9{H4Br^Qt z)Y>oBZ;ekT{h9qO_oadd2g|z}^V5a7C6S#wdrSXuZ}d>-;I8Rit7Z1l!D{V!~JU0&!0y*1p<@@X+y9}f>Az(sz z)bI6J;V)2X0~;eD^9YXBosC`^F6~TG<{c@uO3_JbPla3_iU&B8b_`c3C6h++d9OS+ zl+!r>*l|E6*MEjZvJJLm$o9p|8q?o~)ERBB%5iMbnKVgyPg z9*ZQS2>C?Jc1zr(gTk&9OL%&&ox-H4?Fcttb)KUvA~9me$;rd#RQhh9}&^C~h4sL(!z=|m5@u zGwbdz44FAh%BP9*Yf0O>=d?!s#z!@R*fM>0|vL%S+tyE9ZnATbpU2=ocH`Tege{s69?AIdX>tAR)a<*lC^i;cCJMqHAIAi0Z z?E}8P6UAPWW4x)5Eva_*nKD+VKA^RsVSPuXy*=!Y#lyCQJ=^%``Kh}H=g0aEEv+2P z&6Lc0)-T`VvU;LkL_vW!T>%rk6TU$~xWB6RxsjYuAoqYK`jMHRfgdab4tkNwz<>%| z#CE`0LZT!p7BKVUIOhux6w}i&F6<@T&1QEu-SqdYr_j2()~*J(zo zpL);`y$JdS9r03KuwPj+ICWvK+The1eZ|qd&SStUdOu!qdHsdnqTXX*AC}3{={#t3 zne?W?_O5n>%(S&{%VZIo*>7-~ef@21y)r~P=q%7*_ktD`;i;+vw2&!M2F%4wLotbE zFcor#C91R_X%wClvhd;cV!$^AgtdCc3|bHdV=Bl^R3J>CP{8~%7)}^Ko14C8$L&g` zVNH6^a@A33Eft!ZXsDVcYKd545lh4fm%z$pg(}LG9;{~4fc1aWiB%~Q+a>Li1g`%h z`WmfOXY;Cx@~)i4vh(*PB>&oRLD8AD;=<x3~GN;dtRju z#;X0=(<)6UTJ6`pfO8M8MPSE4JL;brM89AIQi1KrI2F~+9hn7R zg2zyi#)NXIxxJ;GMh{TC9V?m~0A*Lua5RHt#*v@^e`6mvCm`_PK zaR1VB?dxpifwe=m?~Crybb2|P+qdybwV_q7oY~!tQRiW&6-{b5&BP6EBVKDAeSEp{vPMd~w3CHxXglyO)NSh7AhO-mc|!kR#~rn)KS*B6V`y zJvwmk0H;G^YVF8%L?9aI#RbqHE;I{wSFJP&(f}_Y3-(aKM8`-qN##UuKn6$v9taWE z!S7t#B)9Im0U^Lln|DGmMjK;hE4sW=AVjgV!pgbT(agNHdNY)dGcK9^#6e=P!EWtu zZX4=vO(#3LI0=-VRggfL^47kG0iKPja5NbF&vYc5=qi=FtnBvTz8#dPosR|zBkQ(s zI_<`>7KJSA*k@qJdSKyKszwX6KAZIWtOye`)X-BebsT1aPmADZM6>y?JC~mggJTTn z3gjde$>TWyC8K#US(Y?lvVx3MNgtAcPp}DWyIbu@6sFUz0Bf1Z8WCf8H@ZVAR8DKc zV6w5xK6C~#Mg~%unO%9W+U?Z^6yErI?P;6OQu}*{CDakmk30NGS46$$m9HR1X#<#$ z5n6@eDykoyb~!Dexd~ME4e+8teS5l*7E24&nALmTw~AYf zb?FD(?MmhLg1`MFGJyTDFS)bU58KV54(wO%%JX6armTkG=hKwu22>L=w9E2a&_YWs z6L64`96D)&A>m~rJP~2j#7D|#J#d#z$K!I!hjD=DT)|*vaIvsxzKKvSD2&GnLX@{nZH6OIJy)065jdi_11JZ#Tj&kf-gLt_MZk|Xw9ND|ZU>R$5)4)>mWxcAg>|IuLRmcjCLDm7J}nitvO+mH5j z)&5&KT>B(a1E*(3hgo~Mwe8iHR_^O-tF%?ju-~mK2g;`|jm{5^PqU3%4j(;s2x!wP&yZfA$Z`Ki)$Dm_&mJQfTd?MM1%Dd`J7d~UFq zEM?GoV*ej`|1s7%J^IF(VawM-wP(79m9_uwQe8S#KCr?a91yB4)f8=u9_+dF>QGy> z$80ONGuLW?wFi#Y{&wT=cvJ1mHa0yz#C>z3-G700G0tC2;5Jl?A<82|G)yH1rI>{Z zF$)!97MNXxY~Brn5-H7_jzojj$b%M&deEY!S&DL%ip{Mpt+{NvsS)Dk`dC*zY*W4g z&FaUB_^a;uk#hi6x*4U0PxU^0uJ>@jzn}Gtj44<~IXXNxtf)Pw9IJidhE(diZ{^af z+gd@L?=0-zy-?d&Tv%M#B#cP?$YpnOo!3IK0V+auAjee%^aqgv$3SF=05XPfFc339 zgXq!7O`T){1CBC@mShWII&^9Pa3HX`BWa6Hii&uEd%19YpwID|WX~s+6>j58msxJ| zboZq@yjiQ?ml&I!-WBV1hcDheb*l5hyEgi&KbW1EoSmGR(2m@{>(SS!RU`W2hxXs< zarUoVd_5YLUwlJv?>O&SerW$`NuHFidL`X@C{LkJVJb@0yIk`+@ z3TZ;JNqA7>X&ezc8e3~sUA0z9=WVN^omMG{HWKxCQXv#ki&~e;MPO?!9w#aFFOP3X8})*@vEw0mPgJt9{Trs9zOO z(1O2E%ZgfNrMQ8*4k@V-h9bA0>YC{^n+^q|;b1b944dO9!hz4NK>cy+CKg0bL4C8Z zm*h0y$z+>N%GkI1O+HgY(lIj7J36=Y=Le6qHZ>Lg_R!(>o}PtSrF=xCoEvy*YW#nT z?&+z@fYmfR!XE#4A>W+AbMwAWtSAPN0gmb7?2*hEryYG-v}kN5vEF2zNwjDZa6+En)KXiBXwsUS+WO zvNI*Vta4GQZt{h(*8;GUFJfIG^oe}4^t^WPl;EdKBZCex21F|n$i@Qky8Qar>x&G+ z4p1m%RNIWT$|)%k>jAik222vT7~Q&q+thR$B_>{V*K!ppibw$p(^OSED*lBK3lZER zEuPCG?pl#=C537*6PJ7o*`}l_vsZx-8bhdIV4>i*HUy0wLvS!=h#XU&ghSy#aud-* zCOR{pFVRMP1hmOQ=e$>SjWzkk2LKgid)}oKw(ggv8ploN{A|)%gbcOA_&AarkNux|VvJnY`87 z?K_BAXR7Py$QjHZ+9D=DLv|dbL!hS-mag8YMp`7Bq`pz`OF}p&CUAEK$)ip985X%=$QzOXC2m|sFYb7ps1jCu@)%imyMkjo8}poWxm z#Glvjy&lB&PgPB%N<=e<2u%Rg>fas!d&&_UrLPjnu*Op;P!ES_r34N6@JaA05jEPp zamQtTW+`Y;S1`zct|v&8>(5x09(hxVDl1Y5f%}5&f6X6~9-c2G-QF^uPEV#w>2#@_ zO15fm!5kb~%`jG0`&lM4o@<`WzB^rMPp8@uH6i(A#W_AI))3K|sy0~goYw8R851A! zg1mNc7+)B|I>c0X8w^JT-LWo6Fl4K4zqI5y*}q$ z^?=?oOkEOmu$~_IXeN%PYnuy#1IFY)4KC6~uc>4-HtiH20x2HUz@Mng>FnlhlupKv zqQHlraXEEj^L`v066=@)V!&JxbUcbu7A?kj*`T%ZhCK9^4qbI5X|xq1mR+?&NR`1c z-pVnDn~DHD`+_?dbmRXYSXo&rRqElgVWYx9;WCwb3FjMwsy)Gw=kizgZD2P)NTIT` ze}F(4b6$RaG}XA2$??724O)!vqy^OgNbCn%ps|F4U8JrC;<~hatZMLlM?l+A(^l6(;7K#L&kX&q9D7+Q@Yue(kT zCu|XhpdjaRu+cgMf>f_VL&U%Y$egBp8BhqXQ&?EGE-5Sw5sSqU0gEUNJ_rjEayvG( z-tLY3O-K&=_x>Mo-vK9CRpxuoy_IuLT{(7lb?&OJ&Rv~znx52?dvatLh5-g)0y3bW zz+wVa#1&W+b;*(pxUQ>2l~L4X72~?Q$|5Sb!c@QicWza8&(P!3-F?3|&{cKQxhH<- zi~o-n;#!QQm$ZD5FieJ#s?Nb@XgTt+qxE^ZGO1Md7)PM%fW^ZGUUWn(L+tm>c&j-7 z2k7}O6T?CTe&4sqra_wt)XU>EBBD$wdSM)uup84!#n~r|mc($;y=O0)QW6odK0$j( zI^ya-QdN)#5Lrync)Aa*MdO#=#+}5fDwA=7`m%vlgO(VYhmw<63O>A0DItivC~H%U zf~|ThrD|v~6fWg7!QH<$2=w15-~F z9%Q%wN7S$CQ>yA~o@MdE^6|VhRx>*$abRz@zeW9V9LU?T0bM|1* zaY560FpnfA@MuJct5SggR7_r(LY0xN7XGb!X(?h7lF}LeE5%Jabk0?%L9>U0BH)))0lt9G5-+VjXfxq4{HHTfhj-` z5yaSW@*znFr3stO#)Z^kRqU}8i=BRK`*rW#_V8DB+)()LHfCaadPm_mrwat*%*&e1N z;6u*X63*--TP0U%Snh?^>Ndx&!uQ0HQg6J*3UV!rJy8+*aG{-TIjcX87W=~^Y)8sP zj5oF%+K6Z=1rgAK3SU$lWrYIc2$1is1V7DT2cgx+PK7meo;ze%YGhWh*^pmD4QYFE zb}x1bh+GxDz*vHc0wth4!FPqTGqaIG zBF1I6MOLj*bX@$d)~%IQyIMvDAZ6w*FEVXwH3yGcEi3Hq$w957(z$Apds~hA<>v2T z8`*AzyrlAR5F~Ue2=-c5?&Hbs01dIi%g;rtyM4{ zpl$##;9Wo-AS%@?H-h3SZFP$m`Bp~Tm=k_m6k#Vj`)T!1qGQ`$>?@f`p%yJ+QXXz= zYaVQ@Y97i|wA5%NOLJ)2tFX5Js=4diFN`%cKJda=d-LD1o+_`msjRG6ceW9Aw+mAb z!?3YXbx0zpIaL2tx8l$d+POk8D~~C(P>WYM+PNGMi0aw_w}I;B&Z@3l%^!ElBa6Dp zwR(QMR3UUbs74O)WcyJcC!#L)Jz@jUF6R@eHv^R0875NF&!7@Tzu8Sxo%Q4~9lS)%QF_N z{+3#eXlV>LRk3tSsM1mMtC^K6R{8Dvkp61+ohoObI@hdk%ZHoexgKg4Lw>^Bm=Epx zbGZ~zVUV9W+`p-qOA#~p>=g?<2|!%Sd@DK5$XZ{XOVKx)Ph=d9_Fz@YoQOv2d_!%a zW{<;J?~Ns_sYtZOtFEonYwNTYFQUur27@Q+tEe{UDz$p2&1kn8^q#0(SKa(=!pkfT z`4#d0#Jfol`-w7w)_~NUA}>T9Lp=)#1dW?RwKuVaaB3rIun|hFMz^{bbd5Z@71kja zt{kq<8vGh<)Qmvoh6Zp_s$`yitLg$T};Y}A*CS|l)W|G)(X;o zr6sB=^R{#p-l}LshtAKV?pD;ZLHI)6vgluBgyS@EWwc#$uPLPpoGw${QRG^2{;^(@67HTAwt4e4Ca1 z_%LFevBjJ_+cWF#7NDRyk=)s=)!3r7LA6!e0vuPnRjIMqY>|qH#;QTTK*QlQXl)wY zrLBmM?ku1u-A4-%r*R)h)4{A%bcDbBd8(_&RYS^vm zini9jD|{*K^|ZDh_qru1rQt$56MiHfVRO>YvBFgky7jDq+bd)sdlD*(cv zMChv+eBUecDU%Vyixtbk?3hS=eKpt3(mX-osYE$O*q4q(vWOrhV;=Yw?$S@q!@JxO z_C}%UYnd*8TW7_}ikilQ-5Ykrdh4%etZVT4M15_zDie-&R3%moSNF9?cYsYr9Re7y zmr;juk~QLxHDchHF(V|TWD}ubWC%|L!VfkN=&9*}9i??yt(b@>BJo5yrLkuYHQ73s zD6MIijUnN3q`f%g9OG&U5gyH+emopsPfA0dxy1%du?r5br;yHQKH zTuTxq!UPw&g(xHqmaKVk^2@k_(-82$_Dkht019w^r*sk0-fdIpISbY-W%L9mM)qd{)-hmqfOCMfk6iH!R*N*(OiQ!@SD_ny$P%9_ zOTnc-s>W=!XPVq4(}h&z6Zj-af?K2+lB75Ym#g{nA9Gi^95udQnpEN0%=QZ|+dqAv z>Gj^x!JhJ=sze{F{oc1BnGdU!g&)+^UcCFj)l)ZoaMg-|NtW!0Rjq2`{b~bk`A?!P zLIV62Mwg9YNeSXLbd|!h$^~d6a9L%wDzHx747jCEc9?k!*RX#n{NhvM1>?a=Vri9z8(JZK)Kn-b3iQ&j+~#P$P*N! zyeU+R+6_ezdO?!+Ft7;F!v{89mgr1W4W*CoJA6e&Un(=)yrn%i7;BGb1_xdk86O^> zTHVtxo?bhX&ez+W*@60Xdv>g^2l9GwRZniTd@$RPXoy){olOndLV2dYKiAkF@egC% zYUfvq8mt>1+SHbBHbV2YRI`9pu3T8IEL$2|1e|aJy4=R%Tk;X>m1Bz9CR>b1V=<{8 zBqq{&D@&aU+9O))cCS8qxOVrd%PuJ#>z$tJ@1L6PWjhbwwe}xAck!KTp8EU;ZvLAO z-h4CZx;dr!VdxpQ*v~s$xts@?8i`DO#ZQi=M=>v)>l!GAH;;rosZn zrymQu6Z_3n-|CgEM>jWbsjA*xw`J9y&HV#w*AKL}t|+fc9vZsvfEXKEWm4$Y4tCBp zSzRk!-qD`kw$YJ}OiR=U5qCSy1K6-Z^PlH5A4ngNREY~hCt^9`2as}hqoPSpj8dd@ zbl7pP&I*!Ebcg_oiCV+hCzS|xgzW=_=+ye%yH`QR)rIxXFyU`U*-r|w$-iaa$&7pL z4d%iR&~IJ5-=2mK3goEs)9a#N4rU2CMWHsJ3TKgQawu7#3X3bK)LSyiZesQeu6qBm z+*~BSt9Ej3^+x}YtE!CcEd0W1ZDo&Ku>Ih1hkXWpG&wM;Q~KHT)C&@i#g^BK5#t-g zq5$0{PaMRVBHHQyPPfCMWIR+Au8OA;ahYy&lnUAA4E%-VNH<5xbh&b6gC}-48!fhK zcmIa0M^d?0T#H-4~wdd*3zF ztNNx=?cwyQ9Qql}VE>ABw}gJvyd}z=gkDM%Q{q|lyHTd!+gYM;oc*})Bk}U7zB8B8 zT$d16_=adN((f#xMAbR5kV#Wn9Goj8c4r!62ILWW z7811S*>wCJguHC<__g#>Gy>qg6ppFmntu)9=<*2b{ za!+ft{?M+`{jL4iU$bIm-((Vlyb=hsrM*?pX}S}06|#-jW3}+Tb#ZV&=u1>5m0X^@ zyBSd#WhTYAge~fq(s+rPqZ>ftD-?y_Sh^ag`j-;>syH+6xcTN>y6~IU*1zHQPW${N zY=ku+D+|n4XMQAT?-#^J&;01VEV;OGIpvt}8mpAlK*lUyXG^bp=8v&P)`;sDFMHjJ z^1J!wpnnybjzX^xwmB|1ERfit@Ypb@bmd*MXCX{`-5m|CV`waQ;p7AKp*>x6Jbnlt0Gn zkN#Wcc>)RS<Oc9qw6uLx|6%rs+<(iIZ)YwxB7R5izxiWw|IHs; z>^~M1UK5{|`%k{k9$j+X!-DX^d{OSdWv*LMemB34{#)j{4$rR=pOgD}^SdGy~h&wKHFKRr+VCtsJAwvXyRES{G8Z<+GRlD!9e zM^f`+%rrI9j!`-D@Xz|AG$?)t=YNFrDV*O$*EKI8L|Iv#{!x8iySzy6cr_5H=`XZUp;uE)ja@cd7U*Ebcf|GfDAKZ=B9 zD%YFdk9y<%KV+Zc*Mq2koL~Q0@p-xaKV;vRp9ev8p7p$3|9@uRDV2|%b7}eV^?zZH zE?oc9JFcfR-vt&F)#J2yAHUB$e^@b&*u@moD*>vBV4VMDp@XRfqc~mY5N!7|tmh8Q z*Zald58MU)jR4>&$YjXSL{b^q7I1bO@$s~;ACSNz5!M{6Ga9B*!cq=3Gub?3tZ{^2 z>_4=RIq%rEEqUasYmO95z3c#$yB6gl@h>kI)WC7-Rk>n9 z0syI7WAN+ScWD2vpP*Fs`jKm{I>JlE5*H@tx3V<)LodLW8GHn}CIZ2bAo{n_?nIT| zD^AFcWaN9JBqez9kELIJ`Th8JyR^H%@K7IRLZ&i3^IHY#W4%C#>)`&eOJfvaY8I4K zV;Q5CbN&lyj$u!BlTNev=ezEG@4N1m+lSc502>;5`xaiV1NO6b3De-0BKaU(Hn^0+ zgj0|$7=u4JZjxnP!cMRQ8!n}G+)@6C_Dhbw#<~k%{{8P!6AQ}N1s@-^0Kay)_{)WW z=~_|OQuF zDSAL8Jm~$DRk0D46s5T4FM64BGoBTdlhA?H)Ym2AUJvkigj}|+t-dW?5wA_uB2RM6 z8-rcZZFHka$a#-{c8Wlt)G$zM6Rt7ud z9lN{uqmV3}`FQb%ldT+MGlkEM6+SCQgW*UZfZP+M??NUNqB9}iJ&w+`foEQkx50of z08Q9r;f?CQc5>^p_${dNZsjh#O6lqV4I;IH6qyZ7<7pCy0q z!#}Sd922UNg$?K{&?VLj9l}(89NEU;7YnKiR|oY8fvMovBAy_q06yOZ5@bZ^mxk;B+10_q6`8Cz zIO9k~V`G)&HPN6qo8hOcL5q;Vr|=5GB+8*PvqEp;#oWmw5Bj7qBdig23Qy!84Ks}i zx=|>iM%J$r-9)8u35Qe z^{T0vshJhiW0PZ(6XPSp{k>fsEzR(92i`m)j-yx^UKelxY)%`X0FeX1YOf3u>CV7G zkVI~$11pLgu9VQ=^1ssR0;Un-0cD*yx)J0jnRCEvWkpGdwSJ~IkJRp9ruqNU4#bGmeqR=lY;y!OeRmib#sse^egWY7Z)1M)& zFFYcC@5}@2>xHjAQgs0oq#lPaBzWQQ?pH zRtlN<*D!qF#~CwrmJs+f!o`IZ8Ppzt128KT=>l-&k@9#BZt{n;FfK)l{{SNZI6aI6 z^{}$|ojB)PT|8zRT3TCM3g4$saUK8tE&iK-e5}2_Z61GZ#lN@O+p%+_j#<=Eb8a1r zj+M0KfpCEj5iSHsAPie`*rUjc|C~D7YU|u*}^OLP5${3KeL8^QXQ#& zZ=i04Gx(r?v>XESZ;L+mU+6>VjxYz|K%@fHEkcd}g9;i2y(4Fqc>ZEVY5R9LtPTgK z{)rfJaXV94m;k}UrE*~AoQMl=6nzgIt3K9stm@c<58|Wic-657{+W*01IKaxc-8R- zAH)Zz9YWzz=~wVgQxh+W_X@)pS`gJW_!5Q9=qC}Ynnqu3=lq${8Bx;vq+gx6vhW4( zn}6Dpd8qbO2DU8p`5%DS_L~KM16j1t0-XZU?ttb*rYAHSEE=&+YPAa394Zw+tmM6( z3GdwHm&6$?p{df6-%GdnrRQ01al?MKw1a=7_~Xsuw|FQRrmZ_1EPSQ3ftS7uUn~7W z!_lsD=R0h~aJ@m(5TdzsuG2(9%P@~h6P+Vy7AH|@@{}e`>3Eq5{`|tcDa~zpUV~p9 z5*`%3##$kRLk1R}5;XSWO=Y|U1sxsU$)#8v5j;fscS;tn~i{lBQ{Qa zuh!Ax_NL#X>bOY2VcF6sVZwSYVc z{-IQ3R36RPimpUl$T@XS04Hw28;q?{226mdk2phDCqo%5e(k1*srhi?rS(uTB>hw5wvig}p7j1-fR0Zc`%NBvd@of^PE3`PW&qa1_c0E0o`aMfaLGzp%f9?_K0M z$Srb#xNu4w;j&VRp*Uw#XKVS6{V(V2*k_)RH)>)hs1IQN8xl7P&#N-Bw_yGPWXPCZ zix|8ySUIoh>O@STRPPmyVqIKh#=DuBeb!-@?ACt-`>J9NS_lsPSWG9H+2}r|9>D^k zmDTm%D+eV|QQ|0yv7?y(jq1>PrRr$^`erSy4naCDEk^g3_s-H{$PcPij2@kQRxzeO z+sTW?(kS*8SLF~%9QEI(3)v4uiFmGDm<^^JfSQ>jlulvJut>2(-=0_#6PxV`Yu zJqD98WM$(qC@_(W?il1}vyz#Q2?!4`TaO7=yV7buhSaS}yX_c+Y=>ZT>;;X38@0P6g|d=X8W|L3it8MR}vHAu1ezt(G7En@c0>N*O9-goZHpbO9`6*{C0 zl$1K@*#Bst-uX&Wh8#NoD-BAW;h12Mlm_V-IEw%F40-2^X^oxxVnM6ao&qX*sloqS zZ$GP(X;of%PK)`A1t?>cdIk6->hEK~VSH!f1<|AwO~(W%luZBqMUsE_|JM60N~7hN z0QYPdwNz!I0DdL@+%sSM>Q|n8;J&*)^~pPK{m6$tc>Q~iU2*x*i!MZVlXSJe zrp)4mvk1u^Ck6Or z^&;b}hEpWh1*##IEF7rLJ~E5^E}jtunG$h7U8h_at_Jd|d*{H2D{$qG1`&dP!UL)T>4-Du>Ofat;Vd3RUqirkqG%UPFpI1;@wpP4r6td-Vmv; zx7eg$Dq+wA4KWe0rz1)e=DfQmr8fl1t8P4rSOVnfUY&EFtMy)&Rs8vKN5?Ynf zWKe~JQkl6tp>_65$x zY)#==)=*P;uJCnFFzA8aUtC}OQTTN6c5zeKUltCR`NL=a7AeMAwzlvL%hVK}DSQ)$ zCZG}c{XioqeHWfC-Ok5tQI7;U6oJaaG_Tnj;>tHe(S~V^vE#T*38+gkFQjJ+UpRB6 z^s7I;S$OoJOoqgUP4g$kF~}J(B z#Wko=F>RU*Ct`yY!=8i`08Iv&Xi1qt6EZ~!J*=CUt!G=VaYLsyWp3ShT)MR8z?Sv< zYm|z@g;LksPoXec1CT%d9&0KD{7Ps$5kt>_zsVgeq1zA?q}$-it)gxN^?+(4UX@5g z>H#t}#aW&=*3QkHU5k3*+5tl}8qWrHZ*HF}4@JisTDxpj$w=Jnj+J@iac^1d=VjJF zMWsKO?W&&M3-I;PLqqS+dvONcxDA(h zMGp%T4tvoqv*i6!t`YlDESbC~=JO>IK40vRdXv)X(Dr!h*iWhWWH4Bm)5lh=NoG&- z_gseccLkS^t-|2weH3_u)vOS%p+4cpY+2ufJ~>Pv?ywZmMHs%}4o{ZGlEr)W3q(M$ zE0>X2eGc{bT$U+b7+pd;9?9Oytsq{^4`Hzmh<%~PFTR{C=^PSFE|Zso8b6Yy+pfm1 z%ZhdX|E}|}s)^iiod>f*pNrV5MRO+W`-<;}UnrT194xS}=8D4Cx#EMHf|k*HAd#JW zYn;s_RzULsx{ZG7JXhyoFWtk6H!an7c=ArJ1`+^v4uuCwK=nBCDz6^Pqe|#NxhlN; zMZHIJp0K*1=}?{^Ko+Iq7_xf7ixwIWtZi<2Bj44k%2Yx|_auuO2SbZ;o+npwf8^{3 z^+Rzd!7*4Kn5;@CRIIzE#cR=MP31wS$Dp=o%|>4)**1u+*%b9BJ!ZSkXb!Y6Z@ew+ z&3U|ao^Z&lRl%-i2)Vnmu(Nq<9OY4`$!IkgqL{l(cmO(&ljrI@5CJFb!hAhT=YcQ_ zB3}I3d2}91?qkttWh1xTlKU-txt_iJHiCa>{_Pa*VlRnq?8qSj5jyBD?!2-CYlW{; zIGI>21Q}-uSwl!JYG!7Y?7&j$5l+m2cFJu_a8~5DD;8>8+0d}Ev2muMVWu(G9E~=| zVlB~V%Uw8`p_3Wh&>n4xEnK7ekPiPGyGcI2)LKGbpGtruDV2wmXKA_5HI@7s6Umu7 z&QZ0Hab!{5LLATcq>r&9u#14wlFtbuqa+H=h2C`*UxEmaTEtu+-Jb)yFj;FA5~W?0 zq4bc_kEnZ%NdDm*jy))fzi93Gq5ED)`*8 zkf;^=L91hg6>LYm5t6rIe+gnA9JMhe45;V@GOr^tMlp*%A$bx<9KA=OoQ79GJkCKG zmYUh!a>OMUE+9gHsh8nT{=@5Z_X`8z#zLxGl>c&#(g>8T&|w}}YgD+~IA z{=c{AquzxwRf4*zu@~A=HJ%-t>MEO_u~tCaiya5}9@Kf6 zy0Y`sPra0HG%j1m$x;(o*Ey9u5-LO0gMRSBa=+e$U2qQlr)HDF`{p-8yU4^x=Qnfh zA`?Iv5wqY0|C}hr^iXHh&UJwMgd=SnPAvF26@9|5f=~FBHU>J?%4M;{Hq>U05Gr=**z7yyvNhBgjRTB1>Ofd4`l30YnmBcx^3nm!kwx}SM zmqI}}T?7>@s_{wilhdMuVixh4h{;f?dKyyYiH23#*-39=AdzeB%hXKPtsm*%Qa{=^ zR#g$`>j;&z>nihhS5vgMEf8(BSb>t8bXd!q)4k*A!A!cd*6)i0p}htZ4R&DRYuqn{ z{D|PgLhS&^+u4f(g23XUAdok7q3jM)ngcS<6qXDH*DgC-ol8c2>F=Sqmv|9kf6o3E zF9oxc09R5de!o@x#><5<@IOC;ue3(MK86#FbA~jo0-Lnkxm5&0IjDs?HfE~xbesH| zO_yYkH?>>~-T(uKkI!Ha&?DX%i2}KY7CZ?58W%0M)F{D4%N@(9)AxF}dp`L|&vx&< z%wcA~D;Ujd%+Eecq8PezWd6T|--vf`UM&Fj37rck3Bso1vjnClhf`+OWYj*HSwx5c zPhA=N`U10tcJyc+R^_ISL?}c(!&YTaWD{#w$u|9p`DXUE_(u`GmC&;zK?{8swe2FU z2do*4H~SWJ?J2>^NO=#PJFg?`yTUz1If&w-checs&X>#@a-1{QpCfP`AnvrZqkJ0;Ym1jGFiF#@kh4?$(0Z$G@37c z!cW-{zypx9^g+y$2Ka+2`r8#7V-Zfr#F_s%y6UzT>`xso5>pl|_Horsnst^>jLfHB~kff8}5 z@Os)KsLf2Jg>xU=!P*oLZ+St}TO+U{4TlRv|Ugil_#~QjqiZ*ps%J2 zO2gpq)Yk=%5(5T4jV$1m@U#l~+ztgY>tZJ&U3mqR6$;MaP8HQsh8Yd!JYC47_MoN(P{Z7DPp}=L^mTr_Id9|HIT$tr6PnCm0}utRDWkj zd8#+xG0-_sTb*hzZx15vyw_ukSPX>b3}BK5@^66_6fiX@t2`=di0>+r;pLq%X9s(O zEH$#&l*@9%yUQL`TcOR&S(9pq8;Gr}r$cI}?}&BR+@v$B3cqFs zW#PY=&T!p(Cok;L7E~5v(r9EGcCFtF-DBHaZ~vZlcE6(Vc?Fvizj(QawK`Yw`B{(s z=^N+WpST|}0B+D?NaOYDO&Y(c+f%nkpLtJ96P$MdrY!tI`U?9Vs55+b$YbLaNDo|h zh)>=O!T`@5IA0Se5tLgBtm2XhokRu_p(4(g*UzTC?ugP^F8=%%t9q-e0x^S2>yCim zK@PY1Z!+?MmZ165JgkD6Lu^RfL98VF&7>b3d;x##)!?ry-+l`pyiMi8^K3I)iCqPC zBH59`ta8nQ6UNAsgY4dld_>E z)uPNPr+*?>JSR7UT{YZM;qs)~M+!GkGpIRe3Lm?3`l&Q}=j$gd7SdQ1Yr!@vr-v3_ z%vQFK$ZwMSiOMEk!Yg#-Td@i;3X*UFuCV9=+AyF;>X~KDRyGWQac#U3} z>=UBkIb^@|cJ#qNxPn2KBNTEiRsyYOb$)-KtSsR7Z!I+(LaxOhsS9C-wezBKI4oNSUeo$Wn zGYK8O7djqztqSRUIeI|mOwlnCxK@sa3Qk=xm<{lCmRnCkcJa-8yR)+x`?9aR+!sit zzEOB%HPf+2V+b0IC6X~_JJW>X@lTE$_!`y>e7*AlASn=356>A&0VtH@hSr1!<5ARY z5`RSr{fd76bci`FA0l}l4iTswAl-jsjsgns$G^GfzZdMgw8aSO_2{n3*N7Fn@_fXIGU*q408vDd!Y`{T`jA!sbzvPir`Z z7z6Wy3T-CO4GakH3&63$Wm~N!vC9S|XgKCNV*rD;x}7=p``W@A>()IbK0Q@8Wrty<2nmQZu_I|8cY+2HA}ym-Vo?)mnMLI*3XC+ZX|7Rf$}MfttCsp$ zd0Z_vGo{I84eM@NXjyF_ok?5W0QJS4$A}hR3pAE%R?BhX#AVwg-C$o=b3m?MA&p0Ttk1|ft9O-2N_6nDQ z+(P&Ls_lLGCZ|~|LDFMmHe}r$!CXa<5%hb=8leDJvWBDT(e|SdCV>M=|EwByFnzyD z=wqoE5)tLxgr2C*!DSVJK5$}fWVXKR`}?o&>%D$p;QHR`Z4C|Es;jp*G;C*qBbOaL za^&b`RTHb%OiZj69Op;EjUIb(nonh(L&0JaWZ@2HFlW(V9reF^P$EJlobE=3`{ za4E!0p8PLx@KE8oLvIl}EW9 zt#f`9cy`;6(q}8;RKG7vPiMZr;H#v<^*i}>DBI7yj`~j_{wo9YKBYiWWjF!-A(Y@` zED^Ur>|-JYCqdH+2oVxJxX08~{?6Os5p`87jSCcli1#|f%YeOw1`2yW9;dyZZ6RJ@ zs-*Ph0bXCs|NKtoD-7XjydS2E4A*)8SzS52v~HruZ0u2bDc;F!!WsS?q(9Vi3F^sS zj(W0CWjj}Re(}zqMu& ztzD{91$x@sdjhID$zDr+cN%R$qExiyYPl`&#f7$5khamN^TsT=RFb6z+#AL3Em*Vo zy_3b(Ech{7@|sNU{llZz zHD%t5d1i(mbUFKX==|UZ&D6r)`OD`mMV+6esN*=xSDNPLQr~I$Soa!hL^Ll`*P*re zmTti}sEj<9gYMb)elRe2U7% zH!4c!1?*{<$b4PG_Dzfcf~#<~qHwAHsft=Ki=`^z{q1;Ha$4j_b_TsI-9G6e_kkuYKY2agi<+YO_hIcZyRgP z<=VzOTYkL#k>0TfH*I-rWcV>&jt6ZHh@IG}5jSf_v@BEvpuI?V1GNg|VFf|p@f{^2 zPB^UrtJ9*=01Y3W@WeTgW&r#T$EhK8tP^`NO;Ar&!|ez>Lqeirq$m&E*HzP0C)R2)4_Z7M@u!i#l5h#;YDK+jL?3(<743X#OD$Vf}- zl91~VBMk=CiBh*x9kO7}h^=Aaip=Q7Dr82hsH{(K7;8v>k;PM&^t9$hf9#UldbOmf ztv?(KvhL2#%ac$OQe7|?gx{in)k`hMm;;+}6~o0HF*MLh7vqxKAKtg`VX>$4%%dIh z^DaF9%);|r<&Dj7VVD-4F9si<-1qRq`$R?OnGXIul*p1iCve7 zk;_5Xh$u(}uY?p^YA>{{EJ#d0LfS8jeiuvRNnFGLG%p0#zY5-u3u_Kx+vnxf;nv9*!vs!nt zKOKu`GZn4&rCnAp^`5>PvK2T4P84-da4D&$g-Gk~DBdfQfqu7eYs$$A>J9+}Yt!fXr6N^>N_Q_TC`+R`g^`WyshcOS3`=%YV>Iift zL@SR_FJiq`3O`}*Ch6col>}X?oph<$+)sAyY`gYaHh2B?k-PQx;8xrlz`Z|SdM{D~ zdIPYdoo*`&y4pD4p-DxVE3nXTq@qoo|b?Ps~=<$susNu_(5ah2Zf+;vz!;e z1g=?hV9#*E%a}4g$6Ij)N{t#+TXo@?e1%d$uJ3A`MFOs;enAp=y!)aAw1`@TH_JwA0w0!07fQoWFRLL z1z@DP1MU~}kFtLtDB1Eey7F+eN7wn!M?R(#j>GzC{PuFapenouxiXDaLSi{8RnRkhf zLjCkO``3cEdsiFQzia+}@$ca8G%TzT)}w3o<#$)WCS3`!Zf%E>0UOmyt&$;{P< zYF1QqPLvPTHm_-zo@|OH0dgPi^zW!OSaq6v6A^!BxXJBGM?C?5#pF>}TN2)7zJRmQ z@2+oeii}ofQx1E>SX=w5YL|1!?r6=H*F}-sY_xS?i(_V3!3IVpgLd0%i86gf!enY` z(io(U;n{ko>M9R{YKUZY11=%)gL+|9Ms6r0icA~fUJfnBrz>U#S7DVw0)SXfl$+ZP z<=fI-+#Gmq4qu!_manq_Z=ltjBCSJE^pxgHh+9E%`&9hS4Z z6SI2T#N2RmClZlpCO1{q*F_s#)>R{`ZR^Lvor#u#?U(!g$$&SSNY}6{tr3UM%DN{C zzmfJ1Ol_(iZ5h6xd#t%{&F<`~`p(Ii+cvdgWVB1GpRmtNvRmqN!9c9yU+kg!cwPR& zWO&`=DADd58aO1?BGwV{U3M#GzZedLSBo>_r*@NCBG>4h^zm zP1@?+)^4{&OP$cjZ5Kr2FsHeR1BiHh3PWu{6Po6CBNB<_zBIn`(1CWV&FyNhNL8fT zEf%l4{nYTOb*Ik!=S2A}7oNPwdvGUXI}d0~<0kb>KVs6$&t<;2=Gt)*ATXwL^S6s0 z)Hw>vc1E}(Z`Nx>Ep$?Pjh7)f0(vQeL9avg(ZUPS1UPLRGEy8rwBh<)uptU_M6^MV zbUNi`csv(%>^1ZVJ4H_@uKB+|fE>?NRdFzyRhg>B+Um;kSUR3Yt)h`|2s^(GR2B|g zM9t7CC9@CbvbnbdbxM@djAl#Z7AaAQ(qWFwZOCh){(M(=M{9XkVsap_*5vZ*R&Teogyx3#slHU4b0aAu^vnS>*Z@kZd* z5T<5Kn8=S(6T{G(13Ft0T}&xCseiySVb4O?J6~~_@qz$6JoFoJ>6Mf@AQMA@;J2)U3RlsZQL-48h(Jr))|?{bU-P6<@tQ*CcQ!h`Zfl*P}1AVcG{p@RC&@$B&sJj4KM?s z>^Tr~aLSDcRKPD$pWM6$i1dnKsdq9t9B%5qxi?ksolwN{HMLU_U-tO5`L&NvZ92Uz zJsik%+`YPH@2>LP6_?ewAK`|A;dx&6$c6@(X7;lRHM7( zyeOw}Px0xC%UJAo-p6EGVxOJbxT51JUqnA^sZZQ|>6+S$XLcW*84TyP&QxZT@wUeL z>86g6&iwkYetNiTZT#`jbZz&6iW^o|W_D~I+gK4_ksF>Fs!GK>64CaGcnxa~_cY~t zDhXYSVZ{m1lJrAE0jmi18!(@27b$KP0>b~HpW2Mp3W`bGY!NJu2&Lr2vIN);@fU#I zh9fm%Iiswpf8EKGE4NpTcd&}JBOU3TvxT2>IS!UX#8w~RJ|l#Gvs%{1d1x1#0}>Pg zFyM9KR`6nSPP#C$fZPTk%;CMMg&aBT&Kj<1gR{k#WC;P$Y=z)4ivL5VRQvn z9e^x;k=w&3*N?6-|{*u?Qhwdt6qZ&1bY2!P8@_ zFfc=zY=bNs*g!v&nA^%C`gJy=ETwGcWO|W#BBFiv(c&|ag{K#P{XPL3(+vwh*Q@oaBs^vq5CmJEKfPcQk&?|b`?{EON6mw38$d-s8hFWtNE zVjZok=84J4sZV_T<<=ef0~fdL%Sb`p9PlZXSNGN z`Fo)!1frXz(U?mNBgI zh@C~8P#?}YGOYxta`1BZDl{r?hg7%vt!)!XOm^0)g>du`r(f`5qWP;eoB=;|b(z8cz(PpxOnZEgNwF%v~HysS=)N zd@xN$KK;lF>PI$hV&7zs7cMQd(s+uHJA%?Z;{6CA50j4vnTHTliH$-WBYQF$E$tx%2NP#$ zZzWa_pd2owVE6l+VOQ8>5FCVMFJ~0b0iCKepq%Hk%j`6#7VMUHKNfx9lWfD?2M^q} zVf|ePul?vpuf6uxTgChL?7H{lbtL#?b^~IjJOu9zAH2#OHej-8pn3x0niV}@Cq;P-%oi6$b4C3C?8Gv`o+Q)_TECu^H;Z>|jZ8{95mH#~gDM%hD!8`~=b-o|P+(!Xxw zfG=ZnSkuWv>>$)718IrL(NQVVg>HMSNy`z0sl}y7^fV2`$~VfYwUl4-6N4KO^nWf_?`a%CcR2 zTJGY{7rXf64bf(IS*JglNLJN154Qwc{0>*f9}1+Zs@ng8zAkj^)a#lJW-lBvE%wT) z+O*!#pfftHE|m5hW)}IT}b#;tRDGc7Zieei28jLZB;ouX!wLRe+cTKAB0oQ*vAdy--8{27Vjj zl$b2sJUqE#pr@zC>Z@lx zrx$g*Xq6lFhFwr13&u5q(MWAD3gl=&bFm)k4e`{{Ct=#w=~aK`!N2lFm^bM5WCCQl z=q*Qpqm(epT+yXP*_HI|H*Qgtd#<+QRRcvGD1_ z`^Bfn=Y{bn?7g8tulrkko?yYxESV=2@I0aOq)vNS{0X{(Y{epE+&3gYe54YHjM|mo z?w3S^k&RK}V$~_IeFpII!U=LT)j@xxSBli@&<7d!n8}0RFpDpPFbDTjgD{;+Qi`8s zL#iPXT67*H^^xp82vI9R#1)a?)G6SA@Sn`i7Fk+|a9nFn`?;)EAk8WC-(o(u(xb^!=N ziLG4;eQ1$00b>ou1T1=yFTweUK*kjt^6c1jsvxvbq!@wkbt<~JGeGG8u+2sS+;pnh z)4#sv80)%h=Fmj#rt0;xI}Y`{T=?;xCkijKPdvw-YyW|?YfJZz78ady+GqN@d%K?< zeSEB)JP)g2ce@0<@D{B9<8Yk1LAXPBApiH-GM5?tsD6msZB3$HeZ#4%j$L`lnqiH> z_|XroQ!C5{sQXk3okFDpZ=z#5B|9PL)kd}6ctX&cO=hj>1UM6&QUladsDBa3$phfj z6gdc7D}&m&mjY_cT7!9yjhO_&G>b2j0Hy`V4AVE=c;qk>Zu{_!cieQx6_*}9e&qO} z3-|7xp6bcB=8#FWB9#aSN%0|UVO#9-6d+!$7!{TSYzPfB@g$2j*(OrbfR6HSQlYBx ztHE8|VP$nH`k9iu#mM$d3rRlaS}0zm$_-lOa;X~{a;Ye1^3^UN@?q7k85`&(|rB>DrrSlQ1HX1jW&3dy|#}s;1w89fM_yTsFR?^!|2Fb3MVh)W}$5=ye z)j$IzW|P?y(#3V*GIMlChg#=qIIUD^-PQ3_5(P+AbN{5ZYBV~V)=~yAkIOEON7mPU zDpO}LR#ff`gp?A(dM!x@lTb!$#4(%IRF;P;Jj$DtNM@va+f)LI5trFteS{28|??sQd#)ap>ByUdwr(C5}#Bdu}vC3}V2-`$$1=nUH$0+Q`+ z_8GAKe@3X_#jwnCb-dp)l?s z#WXSDN}%au`vbTIZGUQ*mVsFX5e*6C?06dTD>pjnX(!~Aio|a2FpM40$z(kzGw$yB zOwY~ldC$!R7=Li**2Cg;1(z5f8{2eX+Y$Ejb~Y;xtQ;Mox{(dzptu?9$t{Gj+X06| zjh$IQG?1hM;+CWW0Be;=QsS=dC1f;F!H71Y)h)=6JGMT=EmG5sEt2P$C!u*99cys;$Cbz;J@j+v9|<4o7%+Fuqyl`AB$$TP5de7Y(i+I*1FNUY<-1??0gcY2qBIjG8rbn z69DC*6opI${|!?4^LS}PS| z3s^;*3n%>`Ck#0&ZNJ!aKzU+NM#ON|`3Zm4YR?5y<>lp``siR=u+eF@S9|*_$}_p~ z_iWlUw>}S@!;b70OdqyQtI4WOWp1y}q;*$D>ySjcUTbXddQ7%-RbxiYwiJHL%!NCi z)zlj3m!(|wZS;j={`L7c6;3gP{da?~SGY{rlHYi6Zf3Y6mri)J3eXow=U7s-(*j9a z4>+nlh~mIR5EQfg2iPU(V@%L#3y2-R^vIrF>u1MD`+C}18tN)iVFWbTtwudOt0&lm zxwy&7N{)q3QhP7pIB~kk=_|)#~n%BX@Cp31AtP#y1e89_)Ga`eZ6R52cu#=#+N`%U&l+zp5 zRaI2PQ&noH=Iq=^M^!8B_wea0S=VXvm$?Jz{mJha$~w^OAVojorUgy{S-R|U5IL4S zu?~fbMwii0zOH=5^{K9ziul0p{uLXs;)0bvDPP{$Q*MVAsU}skCtJ5J;mX#9dYkGe zYvN_zNJU59t&cbPU7lo<+wBt%C8y@P{aIhr#^^wM?*%=%3pX~;^fok=xx;1f7^$ep zOwIJ@O}VzprmFJoP08V*;Z%M_-O6mkzPj|rO#6&w(>&nqt7)%_nhiY`?7@uqf8ayhhYb*U#XyL;&nV^#2kly# zV^Je$kj<5HEJh>{4$?QW8=k!S!T0xw7xWaW*^6f&#VwYnrFp0V;XZGHT0v{G+IWH1 z6iS4<080GKhd+OF5BnN6(VJ1=f3v*oVhta=7Bzf^eX6JMFdL;R{&&l?QkilcA9^3v zaVs5QD{}vVlP-=2JVgOEM@yHy%jAME9VnlsgYs!o5wv+(Uwx(HQ+M?Ah_|}sV%RIF z54^p2Icfp=XR<>rh6{^ZP(LIYqWTa8vQutXDvb!vf1K|6$HP6S(wUpZ3yS>(B^@tI zE5MUlOF>_pw(zDEYvf$05hdWUzWTGydp?dT-Qq5|*}Yw7rr3R`6Wkz+MR+fMJjZ{MBS*`CerY_jQ%07)=yA(AWv2)!sx2vS280s#yV2%=y>O1KE(6%hol ziWrouSG?Bi`?*}pz3N}d%>Vm)&N(x)DX>xR`@VtQnVs_V=U2YJcDvk8g>~VivQcV> zaCzD@zD6MFe68{8&`rZ4dHAMLq98Q*{+n&P$Jr|{bl-X_RtQpvGB1OW8ja(wHm(np zL)tQo8yCn+tt1?DNBiio?|!X)*Y2`-!ksU5-gc+F|1>7~KH?mK$IuELVMw*cD124E zi=X>i+goRr*{k~tufmS z$5*68v!Ku*T9W+tPcNU#7QNK-ji0f{rnRRRlA|$N-uk(zFR!{uNPgGHcvF>~9SlX> zqilUgw^|vTE;)e0NKEH~XJZ#XBXgJY;-E zAvc<)ES2)TJ;DHMJ0TB{Z|km~jy#HO{d(n_qCSY^Fm0=Nvp5~D+L?m?D?lNfDagV+ zJn_(TgP}JZno>%kGHl0_-yC}Js`A6^4}K~OQr{a|&tn;{9xW2FU^^cA;qWszlv#R@ z==WC^T*JE2D1)!-G48hm4WhmGf6$LRo@P_2${(3Y9-m6T4CGUNjQjoITRpVjot59S zsjS*0#+Opoa)x{(Q9In98D!mM@#e(Acf~BhiFY^fZS{;9>HZrb z0B~A&WC0-OB5ss&aV2m>QI~pT6qe4RwK@C`g%PFuwW3-S_ zmS7(0b1tud_CaHkD}5LFMoLSs{&KlYQYhN|9z68xZ5qi72~pV})hJOYXRT4bq|(yu zFYs0kr=r>GD;G45^>1odmT2@#?|iIWzODQid*$GAUOxRFHQpPZDVJ|7v$GFkyrIf3 zXuNe^hdh;fMZTev0rvwgN4k^?!Kb`*_($X8e(|^oH1HHZKXqP&`=meoKB-@aER%BR zPZ)Uzhj2@X{m<@$%f*!lxKYO-^GL{i6d_;d-O3s5%by zqMl1-b^B!LUB5Js7Rsmhyu=oriy=MsGptEnu0^Iv5DTtn9zk$Lv(p3+$lgUht~+;k zJ^fU9?}MGsuy1g}R+r;vDre>tIrG&Hwxx{p#BX=7^(-pSu`YLf_@2qsacTb##>Z1^ zif_7!_Pj0^d?+ttv}NlC+3DqSLcAIGE{pG~^w}WH@XqzT^&swCmQ7WDFLq*uF#;Mx zo%etEKDqk%UD7WfeB<$Q`Qjv7_xROl*}Zji`&ih6Y7O0E0MLe znxanH8pOd}9j}jzD|Zz4D`!O=kDl~>VpgQd;{1VA!|k|1y+)-msMjzV@OIdaJ8|Ov zTRiiDt}me_CUl_NW78odG(@L{?Re(u-0OFh#lEu(`ztN%0B?`xR+ph?#Pc2evSJI_ zjt6$NzrMT7Ub^e%!u~tCMvCV6dL3h%rTQrU>6&J=c@BHyqT>F_xlEBO|CVvq+uV0^ z3yssp20n#Gf5ifP?sV>FyswIw|Mtk8n;!{@qB+} zoG={r9u5-LOud80ioXEzc>RnrMs)Dm8vdfTbqx5++q3Q=`~{;L_y^!G7|nkj5r3I6 z9;5&;Sm=Zbz|`e5gRlrZokVUq5f;WN`p7-syr9f}S*|=P!+8yT68@sVp?`a);AARf+5mAre)|jC%XhJ53Jb#+3UvBmP-bft7C$erEi3c2^X>4mYA1tXW;| zoEe^02UXq~*!f6V6j5;ZkyPb-Ou^J>T=Jc!y5Eo$YOv#nf+`PwYw)!*u&}pBD;J$2 zgDUViRoXHV-Ip_9!3w0HnDyqcQ!=#G0I2MKYv67Wtyf?%y(bB!b#ygN7xPueXB1>v zhAW>lkYzxFWLf61uMd9dQ{}yg;fLEVNi&UY&TyP{AZ6FvgO347DLlp=j8>kyn??9A z(Wc5bXSTmQt2#L6>m9qsS?lZFyI5A4ugW`TikEVXlY?g8=)Ca@1fu-zjjo$XR+4G0 z%1aEw4EDDHYJ9!@t9(Nd5t&_j>0&*xzsA@$S!VKcu}G ztr;A^RqXPv4mMQ2g-vx=zRtd?w57`N$97KOh6tpV-`LmoblvtCK$BeNB{N^|=*~5O0GS_9*nae`F9k%1VFAu%;3-Qd#fZP(@1$B-y$JhW{ zb3lddc;x!wH?aYKs637KWK4zMFSSh>SDc|tgjNY%VLNVkc=+{)%IvA_m2GHt&mP(g zb(~KsSmlh`EY(N);0_w;61K1Mn4kT=@-fC+t+%UUpfhUMk*lr1XLj)wX!%3sdRl_N zFdaWS7%$zq8OugEFgP#of1~}L@#l&+)$nBXZhWL(0h0vjCGWr9e(6`r<^6?o#Q{i0 z|3>pu?>>)5qX_$tG)yU{7o*w#sq%BhM-{OMZK>n=NVy12D2AZd+duVBG@^^yPuF8e z5AgGGEbYiTHfFZ#0cz*wyVy$ym)|*^4$WvhSYW|yVMNq z9YqIr9|!gQor7Lc}nHE zC_DZxxh<9N&5&l-kNTsx4!ng+`IXAAQ|z9~3G7eP$EMh&NPYji-avMw_-zSwYS_k4zCvYMS$d5@;DlRf=6w#hFn-7vP}j)(c` zWd6DGa*EykT^T)~ajNp0f$ZoC9(`nypi%PWc5iC;^zT2stIXc3e50($1Jl}5?EFV< zPnB%BS)PxRo4ogyKP~d3)i6HJiwJ8c!2HM!Hb|`w63ywfvK{BY@z8x`cHO_1Sr#9!anwO2MlVxIN3W+dO%)!xUqcAzyDySRIQ<+makxTcM5W-^8Y&@bPC$}ig3 zyfXXu%GbNt)V4$BIaB$kR7d*mzm(>B-)C;<+J7f|?y&Zb1*cQc5?aBVcC_u@3z_A! zT~DeqOHtX=naM1AF0*X!ePLWI{5ZpUX<&8Uam+HyjeC2a1AbHaby{w!p{-+(SuiLW z!+HFg-nW3^gkME-3W&q^w9b=eY`Y;GN0C|X_-rr7ac=x?G^+qP^*JAd97H&dGSVlu zQ=8|oeQ(lGWgzEoYSU3~bI;9uoHmyFS87xSa`^m_2XyB0ih|{QukYS*wkcEjlh}n# zh97M0&VD!!Dk<{HpMKN_@wkj8-WNS!#s?bOn7O>7Xl3tzukWj$ptdT{%Mwd{JRd0^ z(1377As>9N_qNaT5&aK)>>Lc~COW&JYE{AbJ{*7XVJM2c^1Z%C??5~3B+zYvfX7v{&4^bo*^*$XNoy7!YI{U+W3$I_q$pyxwp8J{HZMb^m z0D!X{l^20sm&G-e|0*1Mzh^41)Iim5Y%4qiCi0!@+yAw)R;e*8PnoAr;q{C>r{O7etsX0wLKXa=A2alh6e~3zKexr8j5Ua z$G}@lidON}_B+P!{A%G2vXjaDtEF~NXT%R7@bU}GcHH|~$EThyi@M6KU+n_4O^8D0s&2;_cfpOlt`<0Gs_LbQ)m0!NtaV0BVfCd@zPpR1a zvEe+52E=ykd%Ekv+sb>NYQL{$vudrinVuOQh2!RvrKR0pYrhlHMCV;E7H<2D49@(m zawiw-=q8^1?Y(zH+w{sy^IMrkhi<`-`* zvw!|%`EHoYepV3nB6|Ymqk$U< zj6%pn0FxDE<`m#=hd>?DH4)4t)e_LNW_3NKg;Y0%Cfuca6PYgN11#M z?T!+#)Vr)=*tKpiY{BV8Oh=wUjurPwdecG}yCB*>DX{&bv6e49&$^WN7pd=ywfE7W z@_noe{EaaetPB#w(2}geW^jK)fig$n1GYpmp(WpVgejDIQqUZDxJ@cg>v7qf`3uI` zURsekV`Jm^0@g+Dn`f*T811dMj@S}p0Y$Q?!`21afcUy7-BF5)L%Y*sQPeK683220 zz4ArDoErBU8>^Tlfd-3|^@hya$o6pPUiZnfp=t5iJu+v$ve$cQMl>^8Z+Wk=-dL1_ ze^PSp{Hd06htBTt@R_6Bvhbjxj63WaDEcr+uEB#KP9kN3Ag-WjW<)PHX`Ap-3DLUb zhzjhW!KEIhW8b1|rk+?#+y_(gY_a9@ZcMEsC^HV;|CTN=7LWM1%m!#P1v2K*;^kvul3MVJIInxm~>>gfH{x|zOD z$9NtHBW^5`vb1~)j)DhAf**&`P=v~%L?BfkGM8gN4*A0*L4B;Zn}d!;Py zD<8bA;k$ZnlVYG52pwV+(>c8b90oaxiBoEdT!Pwi%PZ8--g0FCl&L-ru4~I_2XORJ zN~x9>3^YWdqS|%}ODZBDk;0&EDVJY)Mch~UL3vsmBsA~0X{mYmf_s*fF_we3l`-;L*&bw{|2c9CgoI`RxsgmrVZo4` z9)YAbLMWo9vm+dEA>XH3=ravrf=y!Uk?k9tWm3|Kg3yOVpjxf^2bD@o zO#2u`q)H{_Ll8}nXA~L5d~L0$M%mNWlTC+^_19_^qAY4KsKSUG0WMQhy^oi(L46ej zVxv%%oa+{$T!_)`lVh`gz2?-hS;z;xVD5^szFTsx6Rho#bIzEZJ#nnLt2vQwPDGo> z!@F}mvkfOK7+RD_jO2&rjLqtvh}=|M+_Nrq*6d`4ecaoXMAf}`q^t5uD0siOv#o;? z&%ytx`d8sEVg#HO6b@wxk^2CiJv?#7bQTL5B_bM&=iz}QhqORE4-akvkC43CRQ*nvwD?bt|_{{jh|405zp>V)vfa9DjweNPw?7` zga4^~cPl>k8S!DfwzxWnUPDY<7bLsyN(*t);yk9!gBPchAUjpIp@KRR@`8PbJy6*o zEd)Y}@BTnMUdSUCg(T$ocf*jV@H!7oBcD&Iu1ri+a!^evYQlv?s`=&OpZDwmkE&ja z?_b2fuNQiF3(ZJ5LsAi2#h)N=AN;k@%%KShmF6Tg2SS7!3ZX82;8J!X%+3Ewigb!rEQzVxJ!5442PW98ZZ*t-!|-rHeb zraloX$rBlw3dxwHQWB8GN#)AaOVerVLr|;Hf%J(~l1)=o3et%`pFbj(pyTKKN%nnV zKH_q9qK58A^=bUQi2tp9l>Vmo7x2IJ{QYO~_Y(R2$LRfgt3ATUt8X*hr|Nkh9FTRH z4-TlhOvC#Z9R5De=cCoEu)2!7BDC;%#<23lMpOj=vxYx1xC!TM$O249R1dHRM=G`Y zOgP!D8+&OCA3tJSq%lHQ#G91owx&ijw&kP5!ASnc+q%2f)>Gn3!c)={;BQ$zE+pDk zv;WiJXix$T3W1{m_2ywjNbp;JNqXY9Pt$nr7F&g_xI3sf%-gUcO_`i=)5X-o3yNIC zDba5(4zJVO)@>1|40FcK%TKl7`)^cZLO*JlSsK>{Gos*MfeXCCB;DN=RE&+vu+Z8l z`lyFee-!(v6rMlc|I>aX>nKEmeSDqns&)xe)$d@hU|gM^?S78pa%dj(e?8E%c!wvWI|aBsi2^UMZ6X(! z`GnOnLZ(Vn^UL$+m+v2*n85#Z=69gh);Z8u^_m^kZIzYsnXjx=^hs7-R)yC(WC5Gd z&-cBZlsu43o;p~~Aj#7(oJ_9@$05uF`3M9XQV}ROSg)pDKm`p1WS{SfnG8XD*Rp~4 z4M=OO>)Cnx=v-P?++nBiWMf}uoKvdcA@f*DPNme^q`pMz%ZQ4=jeXIHprTW zR-&3-SNT3^LinjGs#wc&t1D1}{b|q-@azxXm38wE-mTG(JE{?3TlKdn$pF6j!B>>` zzfybu{;FM|6Q&a`xrO%TiE3I{328&emS01E{{ZwUU;P1e|80Ws!FvjQdat%uOF@60 z;&)*|{apHp*oy3IES<=kd>#{rt*8`uE)+i69dG3 z9O(dKNXEJH9hUE)R z@%cI8E2Sb&i6;MkX{4(+80vm}zwo*05AgoNYNxyxY=6UEY^u%^c2&QH_m@VO!WJ#-s9xx?DzL z7SB%FC|YFzgH?8l-}yiD$b4NrOL$JWjopav>%N3@RcHmQtiQFAss7>aSv&FmVD(ku zRq>B_KgQ3Cn>V^0gTDYjjSW*Z(pM`lFJ`0SA3ykx)I}3K692%r;O&nrR5;%a>9!jA zhh7$6N|eGWRZ{qejY@ac_{WFcnQffl5M(E8#4QoPJ>)whQ=*19rr#NC7?^OW_*CUy z+?jWkJ0s%GgoPJD$0;9nT|yuyJMeRKz#D`di`vH1xH|S*0Yv}4p!WujX5|BTv^AYc%o&YN!2dz>)lxa);{oJghmf@k+;o;Vy;g%usN9wbomSK79FN>qXsB|)< zW_2~N(-=Kuf*OPfP(WPa@FPr1kqIdOITr|c#-0@4+iZ6B+`&jB5}q@JUlGZk>MVF| zwsdH30^dHE7{WL_Pxp?gXyrvT_ z*hl9ui@f9Sihsdp{&6%GiVn~A@-BP2T=`B}{0p5J8ZYkox0QQdP{wmDc)&%R2Y{l> zJV4z4L7fLY1Rk=k`U+&d37H2_szWc>^$}Ts=ZKQvnr9khK|PmF*ZouZqT#16qCv3g zd~rZ{4su6KSjO-292B@ib#)4?6c>9?)pDU0d0iGj9zk*LZasMET(SW87mH_q{l)387tB%g4ULM06Jk)Thiy zt%QT81xe8%eBGcEr!1%iZ#1mIgMl){8jLGaNm7@ZbIJBpyCq>s#3IOKOU0$B5;=qg zt1=PCVTx0>4&Hc4I#Fm77b;xgu*($+eN)%p87_5umAOSrT^>wpJAXGEmhSZh1Nay8 zoiR8O#%Uj#i?bfNL4B3xC{|aC>x4(8wYXEQ>I@rpK(vU+-wIgDq}Q3&m>Dv!>Ws)a zY%=L44OUTS(yj1$F~58^4NMAi0}RtjY9Y5uNvPfBvDLTg&?#YqAnP6B)p>zJhsW#G z6}8>1;X;SYHUk zhN=Hw40iMj4dd)&NIlxxp8fx5z`{qaEwaVFzGu(<_wU?!>n+z^d*u}uUv&1isV$Qm z*Q{Q#eDUJ>^T$R9`n$WD^ND!C@37;>>I7lW-aUICdHDW^?tkdP2X=pU=Y2cxyLZ<; zcYo&gTkg8`uA6SS_U7wu-hR~;pT6?bmww`+%P+qC{ByTmc=m;7oWA9(sk1(Q%Erx; zo7a78^@cSYPFT5o)rwV%mn~klbjkch^A{~#Fn4@(-q^fZL;bS{W|xXxecgTSt$Eb@ z%cSDDL@pBY#{w}Ff$=$frX~~W%3I7jqYfqDar9Bxd9iXw;8uv_WiYdQd|a#5CQCh( zM^3Li7L`Z!^~BNsMhhfTWt8`i`njXLulA$%3qO9PMJ}d!D!cAI^}YLly7}J9u23j+ zHhyl!Pv!Uc#bWgA3VL=iejR+eSKLrK_*MG*etKs_eW&tCdd5FZ-=hYop(i$%4)*q* zdddA_$GyF$o{FcZ_TFp48zDRWqJJIoLnt(%KDq8b{41(|ov1#kyDU*L7Gb&MMXY%@r(;=%%?y)2h$6B^aTNm(ygrGHmLij7Kt)TD)Xs-uNO0aj znl+?AEiG`D`u+a?lH2U;2#4F;lGhaU>*wfv0dvvfx7vKx0?8?Fi7SQKQWn`hFMirB z*8_ITiiL_v&WBkeAe8xt`am(%Vng6qS^*f4772FOz*eG})Z>|E1?(V#$7KsN1r&RT zK}Dvx^+N>&6?};E+ItlsQU(V&nm)A$QE>h4H0Zc%o z@p=i23OAYkZy=;Xh^m zLmzombQXZXpmKk2sfr4@mn} zS`I_IgHS140WOc%SK(pWXQ-p2wJ`djU#7C*c0tIbqo^*+w@Jm|4_h&m@sueTz^(8G%|&a-WDZ!1hcD{$uF`Rm*8jBXyTIL2{MPvEX|l0IRvCJ=tI(^yh~uj$T~NGJ6V?&$M6o{>>n~1tN3s*i zvZ0~tQ_cpX})rj)yh)2ZY5C-_oHCyF~N*fY0b%LzHT;W{dk?!!K1SvPNB^QO%M!vp%FW!?P# zQ#Wm)=i+JtME72k0jLEsGH6;x4n)<-gU)kkI*7Z z%hXjSI$OEDnqhZBx6lb4{63_xm!Rt)L6mLzaLuBI&;gx+UXehVn`dBX$ZUE{MC5r3-j|6}G)u8-nR;?g5AsOh}ozh=%W02hBW zufT_DyuydHr%=nV8vF@30Y~a<%z~~m0Z7Cxa5@!kQTq%ri=#F%8vd|v9|O10k^n_3 zS(G#B77yhX>=T?_Xnh~XE&_+L3*6O%-xs%5tK#p499vv@LRbQ4KQucF=;_4iTVb>X{O`K$0}yb3-Izma_!K1O_L9DWZk zN-4-?9w8yzCZDD}cFyEL)+Gz}RfI4>e~9uQkR#~rFm8>cU4v1>(2Zk2o;T8@9%+WP z(u&Y1++^`}QF{dj2!ojhMGoNo33E^V)2i$VmlVQ4A|Y?Whbp}GCK=hOnZz5+KuC`+ zOLHmU9yR08&F)~(?F@&1VGijx+Iu4{i-7GAz9YU&=ndgDebM8Srr7Z*o%#aSP^zAQ zxqrSk_j?-Vj>3F!35MyI=8iv5EQrt^77sfDZdy3J{+Z>g_MbG=vU$tem{@TadV?l+ zXE@yHHrcYx%@F?R%s0|#ct?On%OpCt;MU{?H{eHHxp?;I7=Gl>Zvh^BhxqGhG+If; zESJzkqtj_L+AH4izzxYy+$^qNG#fHQ)mx1Vzd>^`VT#YuY;OXQqEu+)Uquo%Wq@G9 zHZ+Aaw3^enI789|$M8iu&{67V`%yoDn%K@15FWcuv9zU%R2_q}U&vv(J{dhvDy;d2 zk&bvO)|qb(_=7R8C*L*LmF{bA_U78{v(IpP!k&=F8`8Cz23k7$d{JLM&DW0ndv+eO z7L-a5LvH}!>ikM7g7>8qe)TZtR|kI~E(J~dDX5sj+W{SuxsYrkBtES{PvRsbD3J^o zHo@jdI+Hrp7El9*VMR=p{;2EDXA9Z^&5}8rG9QRP?MNj%=Po^t)3&YPtve6lt%tMp z#<9YLky7^U-}t^&?iK^pVaX&ogf_l!3D`WL+cep5LS;5B+mC5$R-_Xu?#N(KA(t=3 zi7khG?SJeHxhzpvXJ4tUEtwJT?bZXc?&-)ch}z<^9{)~SqAwwhF>1F%fJHGnvk8hidF^1Hz|=PiPs2~mA@uS!Y2|wd zryh|Ohddx5cArdQH>~w2euPRt&=(xcp{wD@+^+~$dolp`BFN#1;&BVIrCFmr;W?}O z4dOkKNN=fWARHPYdG#64hvPsWa%^D*!EaDf7XAQf-kIote&9#GeYFf}+J|^~r?K zq6}7QAoKP5LvC*)`A;-_h80F;cNb>QE`;KVU@#GX*&PVDJ%Ipw2){g_kK+2FLSb;Q zP#EftheL@(C>+-W17UwK7{LGXBW5X8!{S=u=hB4W$Lu=P*|mk5Bt&&^;z*GlqISxp zBgZo;3PDd`aUo3(vUw&Q4Dk7NWIAGzKq`p&@p2G;<~P^2g7jN5#&iF5B-@vdtS(ak z97JY8w^ys^aUlEW=6k)KzI0)1c2B0y>+a1LW=9H@zjox^`A{sKWMUL$8d_W2E#lg? zSg3t=scXDB5osIkiIoz?xyeL663UDDNF+BWA=8sPa7VXF^Kq5{v2U6)8gH_gakWtA zLyjeHtW@gvsn-j|e8|;9&v_7Ju2M1JX!9n!9d>&m>2GT)h)ddP>(OA_nYpZ z^*jfV{>{=S)$_vp#KWIDt(ikqf?AUv|)LSqqTZabw5g@x-=9slvXgKsc) zdn4a+k2~;H^%ZHpvcuO*-)SWFBJ8CA-TV#io8l7;&v+b0typN)*VTIzZISJ(#HwPY zQmUsf(TCq9X6gaZ+MDRbAH9=!10|*KMyZr&cusw=iXEj{ep~&rFeZ%ix%X>u8&G!= z5`k_CdXH8M@eyc?b`tf?HZt7bi2$N-9rSx5!B|_oXDBR{^!cnW8i=-~vTXsE z-{bMSg00zPdo&pJg;Gx3_~7{L=15CRr159?q|U+P8(*O3tz!gwu}fr7LofhlR6P%E-N4&&socP2#Mz;{2-3)? zS}zkO!OOr4T)@gz`!$gYpwFPa_15FX0kr=4p1!%RS|0;yU+mx`ReNPp$b+&5_+9}V z<-DI=PvpLV#$D+v zf^^Vf$e>V13hanrk8cHng|4mw$kN^FGx2-zL2uXSNWnK4jScv^KsbGabY3;^Yd(d| zQTiqN-YMT$6cvH2fZq8N*!&2Xz<6i`^qa&j+ za_k7x0Nz)Gf7_eY-veuT54QU+64nCS{TCIiMXa1IoX+k*X*uFyGh5rt(MEr|I#Q`w zefF9B@^u{#8bwLx2J;lT*+7SSOjD@J3H3r+LywYhvIg-D zl5kusibSdDXiKaGMZQ6>!7w8%qG}3KjhP?=9}YdCKOojPWw{jU-+`IbocJ~Ey}j+> zv{}@}O$G_orELa>S1X#+-fS$AkH_QUmj1rJey26G*Mfp-L43evb49WlT^?q=ECOF? zE{|X?pM;H{w8t?%mtH&gq6XKTgi6Sz2*iNyM>Yq>Z4L~V6uKb{-_bCsd=7Uyt5*d~ zx6V^5ILHT$vV=t+IH5e3Qcpn?P3cHmUte1!ZITR;{G42bMk^g>_3Ld;WyGxO+*}LG zx3uP0V2lrn+k^|@A>qS0Ud_k2#Ee0;BP!7goNupX2@C)!oNG0M?e`lZ*?fKf$M%8=X0l`lZIZ+^y1U{O8r;ju6EDxVlAX#2P zaecTW(ox6;lWpP7NFZt(i)CF=M>Y|RBz#Q~XH!Jn#(I*?u3RRPgt;b{31!`S{b?6R zBc8A|9Q6nM=1AyssO3uY+k*Ij35+MIo+l5J1UE$kE+&-|7(cu$L|J4(7$)i~u2Dio zG;D<*CCmI#e>5C~hz_&ZJG@-%^9uh7V<3YrZOwrf_)Z)&il1k~RI0lu2WRLLm9X5XxFLKF@268WVrR zWyBlx=Xvpml7uS6Ax*oe;g1`);RPFBXpqtJkRLl#P;0%%7Fd_`_wdlY-fWNay z;Ek5tsU=``I7hhmGSrSI!V1*c%w%eknyXd;3U|SaO5m7_Vu&c}QX^$QO+aR~#J(@2&>j57cz zM5QP~MqO)rxjCUVq9L75YHe-S zn)u6!=J8JP7mk?G7;{|w&bf{hHqvXn_+ne!Y)U!LeFx*xz|OTr*d*P82*WHY@s0?a z`A)7402uUxZ|G2vS6XajdJ{u&VFTy@z66Set+k-Kr9`DH0gX~|HO}vJY(*r@gjqwq zrS8s_=2Rk_jby!UM-$9>8X?3&sv{d6&H9Q$+-RsEk5~_d4VH2Zicg~wWNU4W=tX-f znrQ7GY7Y8cs5EA8O|>We?r8HlR-?gcH5jcYSmY-bX(E}uE$VQ@67dwsSIA@1hxF!i zM6bu`h{j!e%|@fygn!B-)@2vgMe^}-4x2I zLIgYFRcKZWvg&m(eaLk<+Gb6=BA>JvjTZVj!Gayav@Fvv%-|uDfP8xw`;IUrZi9S# z1xV#?*_J5oR&9w@HI~q-+SfqNA?Y+4OF0F{ftRCTwTjn=OO{=rG!Q3JJw3Dq3InSL zwDSA=|3)8b9Hv>w^II4p%D@B|A3#AMnF;K$;E@`Ihg`sv&^hs^YOoyi@!wRl%*$gp zlr}-2)ulPAUpNR(qL19nHlu)$4j8(y?D*KQ(Vp;V~U@MAk zlh&TZnnSoJKI{-2AgJovYe{t{c!f)oULVZYJxfk%n{&}p-I(d~yH39C1lj50k3 zP`Tj-!XfBCdEx3ou)t3d<3nPM9)Z+4{R$2|0D(|1t}J2!U@d|}$tT1^k-RYl`OE$-|O>Vs_6LpZh^#u6dMc~DDAdCrBPC&IG zOaccQbK#MCbqScfwJ7Em0&pUg$RwI|dKnr69o5VFhMb|rOAa3>VOsDhkG6#(xnvO597JyfB-~>L*eGsY0f)W7?f&Apt^HMqT`~kd+{kla=3Rj^mtKe3B(jZBL zc?w$nW*r12$k?d!#Gf%F06eap}7#=;tJq5%7!g}B5Hf?R+l9_7XdP?ib8LZfr zGta=kGq=z`^!s_7)lHDA^D2g%gAS1eqokZTPH1Qj98xXU(zy2znGNCG5B517Ibs4i z0Kq}r-DE|goxEN-zcQiIdwBVEQaBYMQO?(+ir%?ivANstvH6<{rC^J#sU;A~%#8YY%4h`ncX?cc&vw&ZZ_5gSBBE&tv^QiS;w7=fMP;fsLZ# zh}bY337i@%9PJ&J%uZE)_<1NQD^~Q(Z{57Dhh3}g22?*@mNr)^$V$_x`FT1|GN=QNt&;)~ z!>!`h=f_uOMHXahC#k<{F^?P2pG)ZD=b+7LqN>g~1%UJUA)v=;X8;1P!{bFcUS&qu zeh`fmQKyeOKjjS79C3tU0i8BV964k;`QLO^xn3 ziX=u-SZ#Zbs;(VL+B$-4MQgeTbK8cw=~a{vGdsl73$Xzb4{1~4eNo9xp%#2X+j5s; zItTXe$7Bdo`bX+~(=H0#kpC5(?>XG_&A8`5mBLXht1_u$|U<(Y|)_S@OV53Am4z`|ZeoK(-~n z9eNvi7_j_sOWF*XMc`nxoIOV?z{4X6F&OBha7DwXB=u7SObT$-aiRJulK7cnRtKa6 zTdvB7B^h|901O;TWDn&02+;d+T_dC2e_ocmYF;Yoj`F)&8W=1__wQd;zo(*tH%xH6 zL9wMz#~M(ZQAHRaJRKEbI2>6pHW0uWAPXOgAbbQ~0NT9=`*IHGU;`En4`*hDX3eqa z>4+WTaLMq?J#8TONI=+;em~@g9n#SR|6MJ|qU#eNeyge+q;qg8Nw{6HCu@t>$oi*rVdVQcfohpRFiAXq!b568pE5r6X|*SK{yEQA3+(*;v+m&7Ao=nw!l$3c*Nujxr|Uun@;ZgjM{ zEf-HDV)?ebWC$h_!MN0%ZGmMz6v?+_^O`vEzb|49w*r%nBWiLEry>KnfE~`vBp884 z!3{}boIKV-{$*a0OfVtQo^1EHEoLFk;s|??FFik;eH|Dcd{MZ6J)~wXGIE;`9F%M# zj;uM?9144aHeKF;>{tN{Yi9Pi-|IKIQbCvB>vg#FesN1G<#Md=6_|?yoN*DK%cv1jw+_Q6I|Mig&VY&O4I;uK z4U%M7BNz0h(lOq?qCDG2V9_p=s+23&MaO$ zXR@Q`v{GsF=ooAc(!D1|hK8f*=OZV5d#>H>f@T4GGS>KUoKwPoluR2Gw+XW*#sT3I zA*q`IhYB3Rl!;$Xc;`pu;<%F@zaR zQP31Xlt6niN+V+i4FYKy^kM^|OAQ8LgI+XANE)*&5hpWYyd}{R3KF<1lPp{)ME_bE zk42v{dh%J)$xcfu0?EyVP>XRg+ERJfN%{QGif{+Bx>~)h?Gc0MNIT=Xbha61A`$c3 zH@&mkRxlWXMq?&-bKK>?C4&={8?oe=*9|xa*MfJMvErxGyq<9ZmY|{&IP=*YJY7ZL=|&uSj+(K`~Z(GL3SsVqZ(8d0g?wN$+$b^&*_Oo{7o3|r5Nv>7;gl(@B+RM)-V%w z+IR>IP^bD0#%XjI%Q-YG;c9sntMH)JZGg#0w+uPil#d8k9PKlF=&>leintvPx34yI z4~52H{BRn?2_sMllK|SC!&&!TvcMl|(uZ>qt;Ov~yIf{nBp22kjjzVq*1d%gabBFRLPKFbV1$(cb~Y&ME| zc&O-2n+3R#K}&R+NJmq8jD4qntaicYp>=bHar8rG%uo;3qYsU^Z812;?YS zZgwTYrU&L21#v$=zID7rDA1E?1&`Mb#p8{8aM2jQ_kU=Mj)JZGSa1g*x4S#giY>H6& zWjC;zPXjVlD9&_&L^vFa2fIgR6}xBQc{~>Co;9n`JtBTPmQI9%iSD89u2}=!(R4Bx zOm+Y*S9<$D6Y#$(h#lHSkpePX@49Xs| z6bAf*O{t{$G|Au`7;su#J$+u>JK?k9`CbydD2eq}EIjsrQ$p2dlA(FuhRgaZmZR8qnKz;6ULiKf|#OoGn6j{_L8 z2N+ffd#Tf{X?OSxwy?WYh_t%9lF9ShwX9#GEwn{?+iXqo67jI=LGjP*Ptu^MgD^&a z&qwURa}--g`M1yuz4k2Vcv(UwBHOt)(ce?}%&QXY;q3Uz+sbEt4By(R>J#|P)D0M0 zr6dkkKZ~3lPT?eys^t6@5gdF5(2r<868Zr!q1X;-Biv1x1lccy_o4M*p`ei+@~#{` z>Vyp~ozyC@qI}-yRB)l3m_+3^3CUeNp5TupudmY^6t{T&Aa5R@uMon0sq~Adz$W}- zj7#;ar$`Xah;Z`(Qd0t6+S3!v+%TZ4wNo+Eyyk|Gi4Y?!22Ly0ZD;?g{1nFQ-}g>DaJri zEXZq2k+%SakoG%~U2t4cXXsx&C)_hSOFAbK83~65no7O24j+i4@TPhY>%b*Z`Aqn+ z?9-0}uyGs*h}1rMtMMo(@5o1iOxXn>cuHzbzyz3Y0*eTDs%Ka>pJ&fC=W|Rvv!k2j8u{Bc`P};2&}p&E-{5lpm)A0Hbi|Hn_y2C^L zr9vtm2^tJ0pW9(JXmvKRv&{zS!IotfLBF^emvB*xMI$Wij)pfw3zNJ6#w54N>)z~g znkAFNZiL&V$*{SJ*#wJim7Wk)cuq(_nkq}8iVIR3a5%a$%) zv|#?k-0|}0>{-Ku1Mo2`c6W8Ox3=VSnRGG{gN=wAtnkYoSEO-RDr9>VfLLwA^Gw5Y zc9iFhpK1JVW1H_s`v<}kW09Vo@R<0GhCdGWH~b+68vk%M{Bf|S;g4wz{7=IhFRWdA z=EqmA+;o=m_*doe;Pc88Hl;lIo${!D(yIIo{!&?7`3ZYkYJ>LDBxe*G9U%u*1aq(} z4CEdGcFCi7-Hvqc0%p9SMhU{fF`*Z!_9vC?(jbzRq2a$WfMeC^j|D84%+{}5ez8raBb(gb94MPrrol}hk=(`w*d zrG=knU0xvDc_Yv(L%2*p;$>Ksxyc2Y&sF^PFp~=~#RjY~m+Xl|O9^M%Vzx%DskC&# zg<>Y|d#?JtB66V)CG)%;B82t$b_GL1!R z2$F;v1z*Sp+ez_gj!Dsce&u2ANaEH5hx#C4j(34=Un)HUbWe$Y54y-E!RY}aXR26s?zl^(go z9Z5R{q zcu+F46TB!7h>XC5%W>z9%kv|h?QPxL^G^oj(eMCvh!5!i94!HJLSPiDk6}y~VoXLz zHi|bY7KMy!I6<&`L$Fc3!8elOV>!c$*enJlv=ofYsB&}{2_YobcxrAXf%WZ$GxL|l z!sBxS3Gp`oSP!foL9ceuI9A<=e)mb^plgavFXnUV5fVstb}}5+LyJ>FD(rT{!_VPq^c@ruYR+JsLp8?qbBNdS|%rxe`Xh-{KuGW;G$%3kL1IQ%MA zLbNybUJt6&AwrVtD-~r(m^KE-Fy~75Mo0Uz^m`zaX~|@pGtJptURp1OI}=@lnsw{M za96y0P;=sWQgbHVB55f23=n(uI?(e6K+n^{I?nZub26ReVj5k78CjAcbK+vcYF^1CA&e4jI7zLZ zVU5?*Il$J7uX-HCo-up~>n4e>3in9ujr|d+hyH|KDH2=+YK|*L`E#+e3aHrlhT5MY z;o$w160(|+I>-ie&7J>BY6(8$4O5Wfo`VbQ(}rfG$a!Pxan z@Sz=4euV!m!!Gz+?t|#6L(>ERLrO_S7f=jbXBWHXk-Tv;cdDTr$zs$@(g6P>8V zx$wb{+1_L^$w5-Jtfz%(UKJqmlp;(uCk6{4n=NiTE}63XEX9v`TZ3@9i1$eowy4ek z-wH_@3UAdLWQPk{pX$GW)@=ff)vA$+v}iIG&3B)6gCUQt>MEy33=viL6!K?+ZgU@t zo6ydu(T+!rLAR3het7- zc+3^BNhh6f!Z}V?lWQJ&!P%LGo8?qf;YRl8BAsA`m_Uahk00cn~G%_hgSR z^>nl|VQ8Rdq%_jq)n4pC>_#FM4pQg>x6ik+wx;?d2?CKV75qZgqT3tii_HQJP>l96 zDHrHsV=!bZMEC&b{B8AZ}H zt&Qnm`C?!zu;EcMHbDcks!n6TGNCS$4sx4LCr;u%>%J&C*DZ7M9$F8@+&V2+8@ILc)mS*-j`Sr8;aSC4!Dj7<mR+<-&!HV2Fh+GnZL~KlA7TFAYmJ&+U!i})7#^S7>iTQsS z^G{;_duaBuYfO{siW-7wphH<16r#elByuR+l* zWOvYF<;a<)wH7+|(Vt#3>P-WAYRRYC)9n~oGMGuG(k3-^7L6`E@|tqdu&Bo| zlO>~4$zz07I-JVa77LbY$oyvAg0>4c$jc>eg>AZVnKHS#UboqAzV^VD+Cp)<@EmlT z&4@h;fc`76HRLRu2*i{kZ-kt2 z6Jd=StWdN3QF1r>h|jJW^)R8WHIs@(>aK#dP`0DH3i=2eulWNb2Mr?5y+`&Rv?mib zgT|`2BlEi}Xtw*rH;>>@*yHlRy9x$klSxc^BnbMf`j7E@R4K^OCv)U+AIg7 z=#Cs%4Jwh3>y8jmt##{8tbB*!1{;H^|95<+)Rm<;-f6V?@AjQieU9%J;@~)n_mmfs z4qF^2ah#m#jg+bh+6I;a+67b#f&xghf(Zu+NwSHyWLu_Hs|rMr4w114Bjr{d#ggkI z*V&9AuQ#}; zdtkud8f`C{EzFl~ih6@OllJ0tB9hIe18LY;e~ElHQSs+OmM!@T;RQ=7FL4@hH)z0F zpaD^!bBbRc{6DndqZ(L+;n<7n2Jno~>WEqBK=pJK1E_)?lLUIKh{qUwabm6U)}S96 ziV=Jl$Wtw3AN-I9>&v&5Q-4SZDH2GbZ`J1vWlQ7BStV^8;m*laZ!87s94K`5^z=j% z@pvYYlpbqxgx_uNw8b6qh(YU=;)A8)aHKV#Ye{8|ZCTvcharER&F_UG>yhOJmjZG$ zN)|&J!sXz`4l;FW;LDF-&x{&+2@3)@sL)a33=EHsVo?+=d0$(5uD2P$ku+|%*&PV; zysoD?a~A6Y&-nxTOh~tLyi95{gf$anQ(X$R!vgzEWA8NYaPBCsw>H-m}t z$RI___j#4{bC{|U$I^HT`*;E`1Utc9m5>*H43~L4gT0CF@IdcSHe?BVTy4GSWD5V1 zQr^)VF7yZB^3}`Id7H`CWD7mnl8htGe}de+un+sOCYNC!T&m37WHZCW1Zf|4gXc|v zzC#;Q3#xEA1FD08L}?Ou*eiFercFoyS}>b6OFB>9(s_J1mlF@_JO+)$qM84(Pi*om z!#=R;AJJzNeM%o)0|x*^5t}J)#TWT_e}(UELd;c@>Me)tO`;WJl>Js3Q~K4trUU@1!JYS;Qf$g6RHPf6b2y* z&V+yl$ci6R{u~R$y_2ZGa|D_6JdjMS7H*w`9Hw3}7ZnG2{4QxA1j+Y^KU19s z7&jj9fgycwKpy4ba&>l9%^W6BUPOin&04l zT?@-^@Vr(-@@dYmSAHX$hJ)!QcNyBE$mfi}c9-Z<1KWLS zPy?hk%$(17P~QY^Ih)QEcjXfr(VQ7(EY6rS?mg!~&KW?z-@|#>i1YBb_lqN-;6C+! z=N#IvG%>wnzR!=N?`_gJJmE*V6j7)QEgGDeQ#R*ps?5eEuR zDxSEUh;c;~TB{7>=A`znkgwb})YBe7nU;2t(0I%j)vsNJw3aR>Jlin;XF$^?G5=;2 zOGKQ%7`7tKtpvjcL3x0>!H{Iszrk}Y(}rlDX(ymA5@z9ASig@lS@Zg$;$%--AY*H4 z_C!ObpwFLh7V_S#!`hT|1On!;&lh)ydt-456Eiz)6jE-0!*3{}*N1fmo5g4~;{_jv zjd8z>aUUn02S0r!djs$r&^b;wB#pEk(lAbq2GM_*1-zEQqf~5N3oPR@BUB*0+he>8)*zbK zF~{hrz|jn1bO^UO8RIvq*c6IS;o?KoQS&3pv3hb)5eJc-4uk=!ClC8XFq^)3^1drC zdE|<##I3$Pq2L1;wfe=5Et{sxFpROlLQ4W|&i~jEaj_Lqy*L}fX-mkE zGzoz3Y;kEe=Rrc!V5<+3VF?AR-9A>Le3xpnjEsZ9|E~A!S&K3!8QE#0!C522pV%<8 zF3B#eywr8lSH{p{83%}RGJ#$H(wZ(dTlcHxC{qoHpxL*>j4vi){c-xbHjUYy;S zaKflJ6m;@|87Kt=&;og2avd22RSUuyOW-BK(E;&v5qKzcCH|r)o=)#blNkQl($Y20 zWzueshlHxb2G6w#Xlq5)G^7t+dZ;$wmKjYvnioO>`cl>N{9m2YhYxm_bsw_?algRKjkf&{VT<5*LxH za0{HQ1yq5c)ioiEhoDpK8B2_~5bSh@Nu&iWUN=xk_~GABKelEx2%ES73$hbAsZ0jH z(T`rqLT*M%0T_f`n3&#$jP6A9QuIhdz7O8mK;~ibX=YciU%fi?yYp;WW3V{5Y{)h^ zHv7ccFTz;JBzucb{N};lfBQG~ljfFWPkErNZ`qS~X4j^&tKg9)30;tEveE*<4v*44 z;WN)B!=k}R6AfUZE%<B_f|LW;h$W;B({Ivq^t?#%Y(`V#RNYKuEE&J0p-B9)3@XLic%!491} zS0rU?1f+in>F&82Nzv$B#N+`PY@~5HzCF4kH?eWBRJLp5G!Z9+Lyung;xUco<8b!qJUECJU!vuuxX&uctIn^^1fAUd!<3jv zt>g5HsGX|1YB2fjH%H;s*tL6y*Sl`@`Z#a*+|`2_C#>F*)_q23c60+1Puv)2Dm1xOL&W^+9PAGPMz~Wm2;Lu23*-N?(z3115VCEFo?Kv zVKavdoS`P}6(f4Y=xp)va7)Q6>_`u=2{OF2#mYpkVya888}2r7r8=siwvI+)#8wxe zZ`UIXr1VC&_PLq8KF_?>^An28OBT<~XdK)#KPfJwc}{c}e`0P|PIb1?6Z&#(Zc%x| z_Ej%2o^qQ@z<~ncZLCIj-E&FSrB#zs9pkj@YkD?ST)pdrminz*mIP;QsZN>DciZybFK#g(4Yk$v zmwxo|p4Fe8+qb$PXG?$YK(Z%!RnLYq1IER7+>kYY_T0_|JsoY+r?&Pucw1y{L!&ZR zeJq$!z%(?66JYFA_yXd0$K&9x9O(iH(Z(IqPrSA|G$AFyoq_vLdk9U&k|8ReDLI6% zgDp5VjLLoiYLxt|gAAswSu>_hZEJ4CHE*sQjZ(EntuvS^OC#8HtPf(*sW-$8Jc{bA z4w=tJAoJ{&<@x5EjP&Zft&eTk6QAz4JmsB5-qM13lQN1IHxHiFR$tUsye;%3$NxG@ zT6(T5O7H5Q**a^W*hoxITY6T*>9ft;&?DJxje%2cZtps^u4z_oR`1-#X(^tBqL%78 zYmMHS`&$zI)lF;Wm*XpK+Eh;3!T!|D@N{#v`3qH{`hq>BjJ+~AIYN}j2*B3UVCr$A zU4YWIikPjZG^h(bk3(37Dk;JzY=%D>)k}qeTSi8gt8;6&wQ~0Ap|w@iQ=*@O$Yfb% zTyy$`hYr=RsG8Q{+&4YBW5>sP7vH$^v=wE=OU;kmc+p30N=v>Y*lk}zJvV;M=XRg^ z+4VIGQ*o+jsOIo=<1OmmE_KgiKFP-)f;E}Cx3Ck_N@J)y;tQLsTU{wIrtVD*bu|+U zbFw%~-)^)^-SPO!62a*u28ml?cOeLOkmZhUSf$M>#1`POy6(!dQ>HChIpe$L#9bEnT5oP62d=}l!-fk`R;;vY`v?fPh1erIcGLv>E^rsdO?)@7&n zr)5v8FKejC&S~wNx^a7aVMBw@GslPB0(wCDD2sU_TXhF#OShm!L=jEju;dZ@HJWJX zCdvil9?d6YF)b1$OUiT<(yS_35M>+L(nPqw+ap{NA(nVtGm+^vZgYAew8_{Xy4H9q zbcu2Pv>)2IpEuWRTQc|PqgMyTrrd&;Pq+S#%`d*s!Q6J6ab=dJ&JL}fuHUpaYB5B==-XsVWp*LriA^R}yQUq?G4NIUyY?qPL>a;M z=+}_~Wo1eYxWCh>0A1vMUXEW5IbWCiONy(j4AtJ&Fr})cn$13(oZ}wX*-)r7Dn%%? zr*62kvzd@(_Z}?TJvY=^JZgI(&L}oAw(LK!rE_r}QtT?@aOl5`Qv25RjE-rc^HMyy zOBx5dXRq$*=`p4mlS02sy!^7uK02j1r8)IiznvZ0d6|7Ldv~yFen~^``VDDYPC0Gk zrtKc%lfp+3S;N!JN6l+gD+c6$wy*ohNcS-uGuZO0Gkj{Y5$}T-f)X1S6C3GkXF`kj z#c#z|4C=`twhj>;lj(RhFtqk2J53=a_2{(4?Z^5 z8`3H5ZHDTe+t%AYA3uCm<)!Y~SZ|zaHCm-pnuTcuY`sFUo8ncc-C18gVSbk}rKWVxp}4q=z&w9u>BQ_w6EZWZrqwQ*H_727aGj$0MP->qMVXmZ zQ|r=;{Gneo)^i3!4bX#MG;?u3^#^@M(6?(!p3?5|LE!H)47>#35t!d@)mxY$ryJEJY4;YZ>$7JDmLuB%@HhhnXW zZiY2^c3uT%OEQXT7A#n`V8Q$&zPKKbx3tk%(DT$&J)v(b7(j-;-Khg-mekZ>D{_)H z%|G3~xRz5@AkOpdh_~yD)8M3@o(7)d3X{l~yw<0lw@v^&w_kwN=%z zAlO^W=Z*3iH93V9xuqFLX1BD@5g~s5?A{6U%W4Ceg&7>EFv8DrU+ivk2z?D2iD7)$ z{D3;xheJ0D*H+xLkembxQjJs(HE54Q0eT6qKP@jIF*7BrU|Ri^9;?=}vL+a3gg!P| z?gP_!kMs{^wR0|Xw|W7tEN6n`Lt;WCW_et5g8OkSLh)$YynEWTO~!2E2ADTz&~F*4 zHQ2;~a4V7SLMMY#lGWT{a`3nf&y3Q0mQ`sjqPx*%Wt7_{h8bWfnwHV11-@8Uke6KG zODxT347MVQG+taf!E1GUy)*k}@hPDfC})zo9sDH8xhX!z?vb3HLf&9oM~FqP17`n- z%t4s&ZSK0|IXkHjq70|p#Q~bM}!RU z$1y$?&#_Z5{YOCr3wb}WJ$$@0i@$3GX zZ%lQ^iy^0o!vI=+S>WG-~ZN%t4{6cZw+>* z`4_C1)tsKY+<3XG#qaMcsti@Y-h|1&rS>8VFs!qPDx+ScL!S(!W8WYeKgexuKVh z&4bUK*4=sDnRQImdW~vaZI)1vJY}CHgg()bGxJ27_-cPxVA4KIsOcugb+K{vh9%AY zb?cY%CtS%{o2uHHN+adk3)&8CyY{@c1KW0P+O%`$`t^(pSr>Ql%>p$&*e=#0x#9zg z700oCKxJp@0|_{Sjq_@`z!9yZBvog=G0r~WnkCDw*);Q{qJpwjHHS{$y<^tKs2A4L`u2708_2a~CX;!7G0J=oIb8PsXXK$Eoed z5A##QD$PKcTyc2S>7gHr=FL1Tw+zYLV%5>FNvbAT>G(CmU{Cr|`dxgN*%pG45l+UP13rhn7=C4=1wCZKyx5g8pCIQ|H|C~Q_kUzzCe_F6@l-)k3II!UnAK+5iG41v_ zA`d6CcZm5?tKm8W`PH>MPuX_HtM?e!UVZJ1p4sL*p}GAF7OXbE)OYl~d#V~5N}&b> zbF-^7Eg+ z;i(hPcx~_AKU{hBjQ$?;-QV?Id&7d&#!q{Hcl2GmLV64}LPwS0B!C6%-}QjybU`qy>#b>!|6uB(YO1zoUmxgh9ONuoJUYv zK1foWRi>lq5%@DYe~WoVv2;MICTE4@cuBL%;X%U}nQr<29hv5ZhT54oWM2IM{{$R= z%z$8aPcw%?-(jNTpQ(x{KqesZJy9uoCT*^+r~o?=P@iE`8cc6KG5^L4E5Nlawas9o z67_S@X z&vVjIJhk~?wC#FvsTFP(n%nk_(yq*^%p{Iv6--IISt`E7-IBLil^CSkCR|jp<)I5C7WGPL89F=X77x;T-fFvMr4g zjoTRTt!;8H#P+R?uwf>8M!MF%Ioh*!Qc22z11ZI>V{NI+AF0bj!*v1S;usx+X$(O) z`_C4mT^Hsp=c}0Y4%aL4tG!v*#f%^J^KB-?Idw4-z2fHk!L*`;grYRt%XealKibJR zlB`-~++^-&Uju$7#Q70z^crQJze!{eG2D(<@i_hwo9Ffni_3qrDszScffa$b-wv!o zyOR30{FWj%Q|701nPtIZTYp6?<`Kegg-$mKyA?lndT*?}wB6U5Q`u}8pVEb`2&~dY zh5pQ2Y;KrI@NKW~Z4{|&vkSez1JNJC!bK-Q1P*90vBz$u*u}@u zYZotD71}nqYQmdp4XU1-GP27n0tqP-YBS{W4yFSU3ZvJvuxNL(aMx{|5XVVU!J5Je(WKDwPh08g#Voo`#zsE!@MFkElch}} z8;K2332iDKuT7|0Mzm?Ns-sO=fV7FDNV-iUnv^q6iz@Sj8JWA*L>A&RdLEvWm37AE zsY@pnt*zH9aO-bffhm*b_BqS$l8S<^^!lPjOVZPpq!rZa)i%Uzpzl}4{fs4_!gmSd z$ejsM*6G3H4(?(^*Vf`dvvL2L&=W?}8l!))F@@X{dH)denEk%J4RRu{qPEt%YVP}T zj<%H&jM7!BLVxGX3v$z+#J@FVq=HM<@$iUGI{G@UT$O`5rZ*>*GlkZ|Y{Tj;2xg9q z&c?&ENBkkmkSpaxmGW{s!pTgUOzC3zmyn><>$bAy6pO8i%JFi^;BmDsdRM|X}5yPQX|XErvdBQwkJuZ-s3$EP3+BqwxsZJN>G^JDRu;_K|}kY8p> zeB+FvImSJCQ~dt=y!%7ny(hmd&EJywzynzgfz;N*dyFpKR~_np^(?O6eac>iM0x$C z!$rHx*)X@$Gel>C0M)UjqhpKFIsZTB>oS&5#t~hH_>2;RTDf7J*2-!d4iJ&z9S6Ix z>vN@A^w9A`dYK8|*OLpxK4f6wnI-iiON9Z#jb{xik=)sDCJ6JKd; zQ121t^?&SlW5*x(jvK$l$*(m`{zH-cBjeAG+;Wi!7b+tb~%h0`R;jc zy!mUpo;W-4`Y(MUQcv^yc05XLum5rcQ3>w5f{JfhoUKM(T!u>H(h^&InY6MT^5 z^Pj99v)fJlFrF$jo=9bd!#}|b>BIP{(D;&c_PgEm5qPT*yh-`S55`Fce=+IN_^J>* z>h!Nf-XEC`K4a3O@mk>ruR8sm$otXwtq}a`^mpxa@OF{L|7LYPP12O&(8*O!{B1fO zN^$6<*N#UuCi#cyWMup>owPdnWf#I5MJFTUBXnZk1<$QCHY@Q^t9#z5&$UkcXLLM0 z@6;zxm%k;p{#L0If1A!fT>oe7_)+yA89!YAA36DB>pwC+Qh!gXrt>Yv75cjoI`^bG z<$P4fN9f#|q1&}3w!K!R6Cd5)A?Wb}wDuLo7D^F1MjRD9gww2OJPcDZUvtu<@i9!v zH$>8-+aIB05sRJoN2WV;9F-o8j|d%`9g+7(raN>zoIV0?5jw^fne+V-_>0i7d7+&S zi~NPg?>2R}#xEStrVryeC;omNAE5*D20Px^q2nWT91|a*1Mn{VahpRo5q=jFAE5(! zN%-A1<2GG>gbvKdoN{j0@ew*;UsULRoBD~4hvPZ*f5C~j$AeAxe%jlu`Q013{aHMB zTEg#MbMW<+)nfh<{(mZj62x)kOJ{=$FAM0;UJO@Gea-<)uB8~6U^j+eSda}4lcH+ehQ`eOK;h)(? zKU7d3h3CFgjC^&UibrpJ?|s^FUnI|9B+t$<^3YzZMB`zv?w6?f8eN?9v?zxhjWvX|V#$6j~nHZ2Md!(41Fxg0(ag^yt_CUtSs zqwzA#$0m-G4u0hO=5Ts6K8E=iJtXai&yGw7U;6z>`Ut!Y^RcDw`y=o-%*U4Lbg?yZ zow@rmggM2kovVqyWg_jveS|49K4YJ&~Uov%bMP8`Od*h^4rz{ zxBQrNjh7MWH#zT%yyxJBbTF^+@|I_0y2i_h^cSM!KL;+;+@6oasBkz4hzh}??5zJVJBI)0B(r?rCmJtMAF(h*89e0MEuK9WdFP_eE z(jB}+rEhZH?~cZcrzZ0L$aDuUQR#O^$qNy@c;F{CUgPd^%4a4A?~FI8zXx_ndLDSO z?D0ja(97fQd!Ezmc=*XMR%VdP?XN?2I(#KUFP5~y{jSU(m4?kk{|w^=Zs*|TBqx2VPIvLrBAm z3AzVdLy)MesGcYp=VL=07uOpn79etT8fB^Ei#t4iMz^fE!}98dqcYN-)j>aHNA{l* z_5KrPHN~=|4h$I|3H{Q@Sov-9(Zxr9dN}kSy3Y82e#>|UoYty&!8sY2V&QGwtYV|7 z8gn!DXxVweL`#<0)({;IV#N{xLoMuMFoWPW<_S4mdx1$VR)oGpS3}s&W$=zMx7T&7 zjw2mku`gn%i?Nw;>(rk3#PZOi)8i8IGqIe<-9biYSA1fj(Kg4En9qew@rjcXJEjGi ziq8E(YDIc3x4g`c_jR@tvFX3;2&>nF`8}u)zXg4yK>vkmaWI|RDvWe7kieZ2_h52X z&&G8?vWj+fkya!3%3*~7Dg~B&krdZ~3zr;}Pw^z?)?y38MdET0SN{>+O{G>RLe@Ux zw4w>tcPgLu=f7U{T+95H!Tg%a>-*vvAVFkIpYE-aY5=oZ8Fho?kXGd)|bim!Igq zN)BW4kA1hFVUDmnn1Vh~r6*&9&Ncwmtb!!)8*i#1=mlbN$=D@wi6hx*g_|18)+8>i zh)OnvE`-prdnhYQ7ea3iU@V(qYeTcN9?A;5@y6x{ugk8kO3RLC|34@F9u)fzhHf|V zDk?mlc~(YI=n*zjgvTHooX=X9~`hbCVu+3P`16);y+kaVCdjWo>vd7Mosue->dw^y7xTe z+@o#Am)cG#37u=4UwmqN$d*YaQP&w#S8L^nx>xAB`_uvXGWc@yRY*RzD-N7OKzw2N zZ^mqCyZ0IW3|@_;GN;A2#ID(mwNCtPQi4dkc0ZVzc6{ubJtm$x$jPsq{4$?K$-0of z{;pxiGv_$@dt?rdZ;4&AoAaIgGWSNU5scGiEkONabQGN8wc|gd^Xs)*7}G1GM%HRx zt#b;aUo%Q&t>*oe#)s^gthSPnh0o?KpZ_#G|4O}LTXU^F1hv!De$4ByCg6K6|z8mlJU#6ZKjyIo=Uh@#EoYSakrD7cvguvJ}dlEA6a3LI!1b>T`xC>#*4h~_D7}N zAIC`7{W5NPh3=ox-*?Ne(EW6*bm^~SrAxn!PIvpSLigXX(xo3qrAPXw!Y}<3oj#d) z^Z|{Z^FXN3>nAi`N5*^od!6wg8@~?`P3R*we!tA=W5gd6p>>S-vvQ;3rN5;+EtCj>yk=E4AYn#Ki9xbpZ8@E$5&!4rAlb z!XQQRcj|Jazob5lw`@CpR!scioapkUy>|Xf7L64z?ft@V`MN*t{8u>T>-y;NW5=H? zvPGo+ZuyKK%EzyF{OB|pJAA`Vje1vTTgsHN18&Dnuh2Ml%N~hm#!cz)cSquyF$1pM z_eSEi!Y}w9FHLanrj5iq;{?38X(Mr8;TPPyY5KhgJ{ccT@6Bdxv}xMGxPOicX#EA99fW8x2fYwY;5K5554LH?PR(3V}Fb3SLs|CIR7 zsQANo>UibVVDTc5UJ-y_ILH1S*h_aT0r4V4@>@0 z@q5*EW5hGIoiQ(S?{GQHrBiJ@#Ks@oI(Gb7v!mk$pLTsNQ5Q#jcR2ns^`efS$CxkH z^%sdl>i^)F@q5)3I({+r4Cwr#b(8#G95a5eIy^=^?d`GaIkFtu%h(gV#l|0WWR2MP zvnEI97kaa`fagpfJN~f4)9rEu4|e`bP-_f-*Nqom_Os!5O>cJoE27KS^d|A5hh^Zo z^*4py?D(Bde3!eqZDF80i|% z$4J-sK1RC6`!Uir{*RHa`(aeN+aHyF-5I5|U*p?NXWh7xwZx6shj8Ir zun-Ju7qoIPQd^i1VO#rRHD+)=qcmXL`08piw>Knq+q^1kTmwU0R4LediUo+aJ=@XG z>f9|sYgx428Oz903-bvK*AsuZ{0Hj~`jX=kQV(i7-xZnF*;6V*U!u%fsxj3pRmG|$ z*jR`^MPq>|Q7loaoX!fLh>h5lir)bYpz`x_u|VUVO;v0Z51&Nj7Mv(kCef*hqjs)U z60`QE#e-ebpS`Gc*0ddq7oR$9R_jI2&gdF6Uf8mH-M*Zzu95?5=WL%fYx|tF2THoS za`vrTzD3$9xH?K(eTutsK#(>J+tF`QH%#GN!wjr>uN;HWrxV3}2nL)@_>wbM)@)fd zxN=L)>dObOSYvE$S~u;MTc)jTy8piOjONhe=ibk_k-9$2c=CFFqC3%E3*LolBM&3o zZX8zsB$$=O;VJ_k6_%RaXeRkPjQAw?OzkxAtuKc%QVomKJ#xvRCjqBrX&mK>>+4s3 zf5MO)lv~=Lo?<2?#cxgynDOzw@u-M`l81Y>fn@~dDT^N z)6}Ac^Op834R%g#Z)vWdT-9COonM(>SzcORW0Eg#dCl_fIV*d6%y+VrCIzzn z9%$KDT3y=Uzb)~W!k@ovAzj#YSTZbl+TxMPe}thc2f!$0_B1ZLH>&m+P?_F~-coKv?f@cbOiTWSM2aURBNeoo*j#%jWc>#}zO z4Gd8qL)GKY4ophQ`0tI?m_Ey;&$9mi+h_lyVfNdReb&e@>-!(}nLW(<=6BX)eK3Dz zjYq#)gdQEyS<;&XB>)rSroqtsP z1}FY6G5LqaiQgpg$`gKG=XYtYU41^tWs&ZT-ohFCR($Zf6FPNuCiJ9{6MC{Up(i9T zBPS-tZ%*Nax}L|IB`Ibek9nEdd*oZIgC+LF-PAC-uByGdebjXA|B%zQoLbRyx3~%) z$(u({%EsdPt7?ieC#9xTeBk^$u)sJ!bf~e^>*8i^iuInd5lWnZ$&|q9(E9qt9_({;>4P z6s76&LrhW8_$(jE)J9K4(fItJIcF3;wNA_$G2Vw~n14Qe9tVBS8Hvx)lf*Ic88aV@ z#3wqyUugO~8Ji%@pZ&MpWAkUNW90m=8-K@-?0B2s4#(eq&2au{QTadpS>jnQwujq{ zA99YRL{$eX@cGJtK+Hxslfz#QkJ;uIOXVmcSxU<5WcNHyuVcpXx2bo~=lTmvr*@q% z^^!eReYnq_T0A&Er+ZHAoXWh6NAu@pmlP(acI;er)#a)F-o(_CS4e1s!ZJ>X?V zV!>I-x{_XbY$P8YJumH_v$Wd3D!sLNKKGNXN=rNc181kwuGMWuedrg{`m6TrpSQDP z#;(4bgx(@JcIPRLd&W91qWD|6Dl!5On!(6evJc~^BET)F>h|0~9nGd6BK>7Sk;Mt{V3x=UwIb(NQd1F8MiK&otCmS^rl*Rcj*QTGsGzsZSW@8j-#nBnF>^aDcxpEV)l(9_TTo2mKMQEDr)0A zZ)E%>abo&!Gav2v%#Nf(KfJuJru@jFuWu=A%U?8SaoL=Secf{wZpv7ebK2*hJZI?J z^TFXjIEc+fOw5DH&l+bw2_`x4&RCI*Z2mT78>y+||> zmRx3SEf9M>d|c({iNil=Zh|qvJA&rgE4h+UoHw!mVf$vt@EU0|PslD^(L8r$^4Dgs zUyo=0gsg<`Y=7*Ts)q^^X8N;Q=DpYUEi?D>s)d;;1xdesJ@m_mkl3jITV@})n~0Z- zcC|XVvI?I>$h4l8Op`60g&dpb#HmM|6LCb}^5Lu~P8(h>i8^VIDQsP>+;q~^P}^SD zj+3IAqMF?7RH;0-og_ufVjV5MSB?UEy|$YoZ5kaJ%6NXraEG;TqG|MBvb*Q(C4=kQ zmeg_+c*|5vGCvM6 zx!(neJ}H6r!wBR~7xXW94-zk=`i#9Z8gMBsM!+pChH9DFGIMI1T(8W%Hbn(_>1jy` zs@Z5xwp%WT@132Dh}o)Tha zGmNvYpR;`J&V%Xmf`&2U!19z;vubM_b|yA2om}0YmlKGO>x@rnsVrGKxn}k?*CtI! zG^cKuK5ONT7xpFx` z2p(_+4@a^M;)M)s*Vl4~pzEoovRKT)vnSX1_7X4egLw$BU1rFAzoO zI{kbD{JvIw(cTvc;I7d?t(3?O4#ij=%e`k3XGY?<%h)|FulGfV*!?t?3Mcez#^0I8 z(~H}1du$gmcr^poLu09J-fri_v4-RemV!TA)y8=a$K=)J*|{7O_F9EoUz|7i#Du+* zTN<>Ha)fexMsqYr1&M-IV^exbR%>ZWhA-D&p0{WqKGDcpm0ptFSe2XyOU+!cEIu*x zM)}r#vsQF#-nnbvq&Y>#28mhKrDJxVIce^s&>flvw9N_lDp!qaZ!obQ8py*Gv)wEI_|eR8Ub^K?%5`#-m^$ zNo0;zcIdGwkM1uj1!v20*}8PryxFs(ddV~&d+chrhgQrpPQLV_YcC!+)RmK++EqPo zg;9Uv&?(z~ct@Uie-ay-Hu!b6DuXhS-D;}}1DqRxK~Zn$no(xY}i&HX*Plpc237>$Dha6&dhk4(m)bQ3n_^W~>jE)GyxHFl|k1 zam(J0-JKI=wv<>yr_abNZa%ZIwr0;lt9)MT@-} z&F^H+Jg_yPW@<-4Reg4-aq5CVW>LaPJF15?eQ5hRV@dSAN^(mlD5o(a?xWs}G+~Ob z$;iD*Oe|mVs<}9Vim*=c8~ev$U3ucbf`9vVL=!H3E`0tL`dsGvwqP^9{yoN|fZV{s zITw!}#*?+>Lml*HSvBG>va+1)h=pAG$^9y>2#!BK&7-q(?7r40^koHHX64N?ruXfg zTi9MXV{$|NqA3HtovRua9Gc&}tf8YJqa^dlOP=ZbH@BU%GQVlk!Fj!dRdGhk+7(^9 zx=*>N%kz>^AJ@Ef$%e(LbGya)rW+(G;pMK`A@jJ7F=Ru7}c|MynsE14hmm zwdmt5t)@tSw!KR{UXqZAO9OpI^Rs40PbdkTOr-2Qvy&{^1DBjcksGF@3#1JC!q{ZN z_gii6Vp3GPCm!Eotr)&!l^1K%7l`GF6CMqnYE0SZ3;29#3C(8G(RbQ zmq;ByuIs#6w_yU$-`CIo?zYKH*3WzRu-t3$4(ANIp$(*3?GckZu$goa_*tb0$8FPh zGT3L4+SQ^$JQcA@nN%n~jIz=S0tNWO#w%$;ygrlU`v1{A6@3g1gNiI;=9>L8X6#?H z_RQ(i&s?`|#i~_n2L>koCBE;XRf8Ay^?hV;)kpdk?B8HD^9+5f+r|J}K}l{=5%flU1}05uE};ZDf)p*F)1QjS(9nB+e&Jcx==8zSKBxO8kXp z=h26aD{LHwBHuBu)8Dzw{jOQ2pD*W=mYnP}9)uRePh66$YZTX=BfnZWyNXZ-)E>7H zbjG#DEy7v62OnQa@wk%p_&gkz;$4eX5MJnzRN?>wm~EU8`hk%Vy4SeE_*+lUpXSXA zz1P#jCuzIWSJ0!#Ploh0x4L&w1KQ3{haQDXIZbyQwZzL|B=K-r3{8GxF!Yw$ar6=6 zub~vXT%nmqblYy$-w~R5Se{do^mm+R<`?|GLZo=26)&vzi9jgC`7SlE7Z$DB0W7n} zoUY6``F3l2r3hmsC6zgN*uimb)`UAgVO;ag>{)3S-(1mC_4ygEKiM(g_-58`j9%Kw zSBco5@_r%60nLZZPtk}e%ZwoVuMt&}W zRe4#_q}++Q6Z7+UF()Sw$O$CJ7s%mBxG}36=u_OZ!=AG$1DflwZVud{5)Fn>OsG4SBXdKIV4CC66b|HFHJ_GLFyJ>Jyfdr}8qe>B6gb zLi_~#?4%Z9v$a7N6_h7Vd>ZvT&K@kET{l=ayL@o(-s|Je+;{&2v-&0(>qDQO)Hmya z`}dt0cRe&CxLaY)1#kEqF3ZFeh#Adc%59n{TN}m6u4Q*3a#B?Qr;k1`h0`FdB9uv2 zPiSHjr#Z36jdE*dc1~8qzA4?a4h*c?-#Mp#-?Nk3aw`^fb}TB-ZL8}o-o1M9p`MRqj*NBYCV58mGm6aDq4xu0J_{l>U8F$Bj81G3+@`G4}e`Z>Z&laIR3Ht$T9Z!!MDL2UY@4`&5Cpr)8L zImU6ug6PG#X7kJxhRV)zmfWmayf))>)I9B$UUCN_%WY*Zx4T#SzZqP$DrKVo!7aaj z%2{hS&o=U!!9eJhKuOxq-wA!|p)uP*Wk+pYU$yc0uXv4z2p{&@vd};K^9Ri%vFW4c z30p>Ho^a-kfAF)6*Jybx_8BHPEDuHIJz1w9AN|ulk3VnQ?Hx{!owxtbKf_m$xy%ZY zGxYq0Q3(CSzR17gZF;p*S;IN=dx~MExpe%mc<{sc$A4J|_z}6&=i6(dkN8)71P_dV z>jKs^&iI0UF0{wjzv49>n7@r2s}BAnt5C21%7HT5OI#Tn=Fm~>{1;EIt&#jb|5f4B z(SqVv&bn9LaL1!#Q>pYA*o##)Z z@-QIzR(<4KSF4*xeQRVMum76e(r%|!v^zHa+IF38>Q;}DeqF|~)2|O6JNJ{b4K9Tn$`6}%?kIre=LFaX7KvnuR z4IEeA3ZaG3Ii+1A%B=816VdsGX(J{dv~gVdppoOs2dx|vg$UKaY!HRYmH7^XVSC;Fs}sJyx!$IR>W z9p&o&J(_vjMG%}4(qS3co{brI5N`J<(kgMO~2-y5$WNVq27|H_pkl#2s#bF6qA14O(WC) zOnP0^``7>I*y%TXc4Yd~yx(hqH>duexNl_oGo<%LrGN6PBhuO1fkcHio%e5kMW;u% ze}oKq%SahAY?lw7o%e6G%Xi<`e#n|-{+4v*OR5W>Dq|un5?Zy)-%fme_zWHYAo1Ce z`uO}ea;K!OQIrfCE2rKxT22kyc)2-JuTR-{u}fi|wPjA}cU$JXTK!aiXN1ft`X1dk zcAjh09UqVfK67!jb{{+a`aQ=^zhUuM>C%689dB0Gj#J0sJh!OP^0mx8 zkLb4ItcVeHH9nN|m+YRj`Phg&%&+UBa@aB%YXiZly*9WSD^khf%)q(~h#)EtWh{@% zF{%vknXl6$_>6u3y0?y>h<^d05u{yomTx}T3L zFLKGw5w(qsOS`V__mNBbjxQhmAN}QV%YzP%kx+KtvW|%>a1gJ&8f^gBj1nYi>zZ~bGm%PO10{pG9&BQAk z!}%ippxYVwHvKB=*yG5j*RjWuPp@Og&G$qEk9r+@9QpJ*cHDfGk@EC9b~s<8Uzlg3 zb-Lt;(&_5{VjZF)>j^tOX58vBqVhWHiDTrIzO~DB))U8-*I7>-M_&3@))T`yBmHaF z)%`yGE9;5l$fws6$B|F3C&tYu{VVNu))U8(Pp>D&%_se9m#5bg!}%ip3*R1JCoO%Z z_ktpPnG(=h$Mml*BPy@MmyeMb{5s`2eEGQYI(+#!@;ZEZIA^4P?Yg?(clh#gKWB->e z_q%e6wuw`;Wf*aaA->qIt08*#EbO`*qsj}lQRTVf6upELi~+eI&&fVI)9PRjM#-wW zvJ}@8dmf+{2b_`=3D`+1E&)9-#aHoR%i1`(t)MQqt-idbzBs44AgB6>@pwyT;f$%ZO+L#zqpf<{#H55<9+<*G zo2;rSW#wgQwbe(H{L~pUK+Z#*t$vSOGb1>an=p;ij5Hso4^)9Z=OB6XS%$Oq356kj zmf>8FShca1tH{hMEA#oe54N4V@Hoq5``*gV$>9oE?CzRfTj_3Pz0TY;DP_`y>VXZe?DiV_hfp*fZv( zdj#dJR&x$#12_`Z+N`fzIQ#4wv*OaQ?QgH1mNUKOxr4^MFZrt~lBa!SRp*YaEoZUA zQUH%`JISH3DzQ-ZZ}ETpI)E0g<4#c4iflxOu*%Sa{ojVt*;j{QY_cE>eQlnWkO zhb{H7AU=ax4oV1Q#-xh zS?#+pu{6~b>a-c3iy2t{b_AzQfPOibWKkK9M-%J?959IxELQI($jQp&lv`frq^wC& zzw%O_LxeGw_znSJSvGs&imIN;1&tZlH*TnJZfRbf(RjpYUAA=f(&oNOe@bF) z!NAvM&Ir!jH8k>_uRf~#>Pi_uQGNB%k$sh#%k`Zf&{wyQ>MKJn zQ;V)qmJ@^&xmbnk0n$Q<^`1yJc7W1aD8|*pvyE`WH1wk&w7|WKPqZEcpi03FJ zM$(>f%<1o}n!L!L7N72opLC?Ugj+Y#J;rp)D|Dl-w5}_O2`VUPv zSAG!PAk)n^ZdH$%6&Bw2`P%u+TFSWhe0wi(5^Ktb%?i$@VDU~rR+>TeJu?JvD+*2! zi+9GHm=0^3;XduZLQLH)j@@SHgV2>Yb25X;_a)vh?}z^o-h}pGBJbn((0QMDLth7v z$9sOc7t8BHe7cbQjWZf^>dY3L>(WsyvA}o^d?aIZ-gJ# z8=HozHrFcri-YeP>HFX$8K=fVKGQ2y$sGXv9FmqTEw3hnnaOt-QpYEC9run^N8<$QP$6~1uH_PSyRIvBGcMNg z*pKOWd;gcRjEi+y`|Yw!2k&xe&#<@N0#7XDHcXgP_>CRUSL<&% zxe@wc(f1;fZ`O{)+^!wM^>1C3BR!UU5aBYr)BzK>+Yv0Dyj=w3N#a@k4zd8K# zmn3}dkqbX_^qSD2#3LRoTkuqiR4DQC*E2c9zD82+(QA%gn|Q>D*NO7S{~2=?HRYe- zaUg}c@e``cyh!C?uhnVIQjO-bs#X0?bs2T43YchC!pl2UlaZ{djoHK{^UfJ6k+?=+ zHP8S|2C{%zKs!(eNV>c?ADAS+fvGy~K9y`;pr)JW($ve;khx#YG@mA{1AM@fJin-h zp!+H#5Wdemg}7ucyuY0A9l{jS*E``(;>uMs?gRID~KWDzi~dF;7$j#&4^Z# zd|UDlNIv6c(w^r~`^hSew8h5zd_P?!nE{nQ_rR3Ui$6Je2Vzu+I-^Ls5I zaWeqFTUC*9lzIvt!M%=qGknzeg2r(Z_cP}L0o|5e)aOd-1HS1$ zKk?`A1d4;m>UFmTKImay8xs_c36d77pvakbZ~)-4D_i%W2PYXyR$W=?CeH zXrQh^-9OS7(I9<6pPBopr{H}Iur{eFx-aMl=?fR=gD`!uknl<1ZyNt@KS*ChgV32g z(-+YoeIb3OLut2sKQ@F8_4mgMg+_%=r2Quo3XY_n9~25b%X{O6(7L%j{1h~=sB?m` zJp5PM`6#%?`*HX+LOKV-y0Ye-V3grG~Jirb5wX6{eGWnGZ}v}2Ar_d343Hr%D5OeWW4Gz6B`Q6 zNZ%c2C}UlZH|R_Etvlu!chF*mj6XNTFaLmXOZczmVY~l@-i7Aewz+jR?f}mM2Y`!J zmHIj%{80Uk@Vfxd+<04MUV^;w2<>3ZararGbtyb3iSS$?8R#W#VfcNQ&l!IO-=t}J zp>D$CE8%I@0`Lldvs%H`<2aI#F)8id#rXdf zym%AsT&R|rE5Rdi=2rR#p2JFcvZNb7A&xxeGV)74p&9mJ%{_KL;}z0n41E-ywo1)2 zw~_A^eoJ}3Bz~DnH(ytatx3!i3&Zc}c*#$?#Oe0ENL`^f?xdcn@oMvri9)aVbu_H+ zkS2My6YhpzN;_pdo=7Njg1q}x<(0CmmC)ltRe|B>W&!=qBa|Vya&V~M7d$a`c_&fI zw90HeNgngx)Dlk$PB{YnzF);#YY5K=4ycKqLc()Zw&n?gYML1Ye_sI?-6}(m?>FFk zuc%_$GN2(qIGY2IuMnOMNZWT4I&+Eftjg51_)EqI^8j@kpbz@2^VNWL8Na`wSo{$# z<2!Gt3D#VG*Mnc-B{Kf`w(%!$F7t{#2mMXPxYdU=a3*=lL%B9DlRnF24Bk)K&RB>I zg*K!<#+%F`FWX?;6b`8`t7HxDp;6&C_c_{d8}qfIAC>B04(YdY)O^n;@hk8$bJ-_= zHpW03;a{0+&JTAPAE(~73{Z?*ypZ2H&}NqzuiC8l)kcd|gU~5Fs>$k9ML+;31<=EW zA7ZXb1SSH7Kpyo}BK1T<(HOi3+zEYj5TDHN&jDKi=O6j21q4sh7NHG2UpqYB=vPy% zG-%@_cv&*z<_>6CXiMlx@J`=aH>f--i~jmF_&ul+tQ(<=KY(A(_3~YhbvyZme?A4h z9#&rKNuHPTynwpD!Z*t(_g%(-pYI4w9O6A0cTVVeM9uW{@cmZOuTkwD?pn1jQPU&e zy#Rc_#(P8f-BCyX9eCOjdcB5koTzf3mjviY=AZ#HUF9&B$D1++vZ(tdjE6#doM>9T zh4{(jlkp|=x?QC(&J)ZBpxa%vQFzhSyjM^7f*SA?(Uy%ob2^-H(Jtdi&xLi+<1;E# z(-5*vB;1F5RRtYypv+&8{#~`i+@bnpoUuNVP|q#kr@;IqvWF82uhZk1F~v9-G8?Gd zPx-xodI=BM!SkDh*Aq%vGH$Np`LEEs%zH6&w#&n%FLgiu9{H(-aqonYZ^1t_UgoP( z<1fmu`(656`d>m@rfhfn&JBe>$QTuVqQ`V>=+u$^7?N=-d_|9Kw}1A7rwZ`hr!372 zPE?)rU%Pb?^7aLck4qT`)$sNMs?^Mb$6*0vt!13QO*z+rgLj<%cnmyW1)lp=tMPkP zYyJqF!4G2b5%ZiL^E_JSiNWWn{4QR{4=cd;qzL|F@=2e;!#bRBQ3TH}zDI`DSOlZ-A zCoZd>^1i6c*76qfYCUs=ti39Xt>JgHJQW<4t9Y+m<0HtpWhtxki9Ey@0NNP`B|xD$ zoi&_{3+6Zjdosr20RC6bGiw14b3AL6xMb$edx4qI?gVJl4-P!=jRbzb2b>B%TwW{d z1Y~u$FJt>;+~*itjEwCk83WPs^C^5gd$|0_cbu^uT~}A;w(jN~;Ulih8}lvtXsPBO z4*ep7KS~>Jr*E|E?S8`zk#h%;d(#|wcg3hS&7x0^AeV{kVaxWyU)#-FS@*8cYhhb9 zb?f1L*DZg%(4|jyvV5%T28;{gWyo^^8viceM*gHtiCTuB&y9!J6u6&t@nz80Go&GF zlCF7XWDOB^@Vt}vZYGZ-Hy{@+)%ZV=HL5M+6q^~)jP!|s@LNFhrB%?CtVd3S)+Mcz zXXXv#{qRv}d8yE|0CbLQjPITxc0LDHoUs9|H+}>4oOGvJ%G@nL-th1BJ0e3dr&^l; zKY9dYE9#gU1q1vZFxF7!8u)EJ`2kyo3jdxu3H$~4IO8N+kCpATaXo#sRV{Vb?eKVI zz=QR=VIp{At}y<>8tiUlqq|kU4v~R%{~#wKA5WGxiX2GUx62%Be3f|G?!IF^M1J1! z#FOuBmByMrjd@cbRnK#4c^BJyobn8qr-xq?5SdCq-4%Woc}Lduvd&0k54YV2D<8Ns zT$xSFa3afno}CB4C|2=6rZE9o%7zTW6m=WC7`=yp{w?bp=NbLNd;#@s(g4FxIW83O zyO21nBGg@cza2iY3VdXtd$@x&==e~D99yO3%3BBp7C0c^m35VXtf@p#G?6e0Oh5Cz zKsI$!q02SS!K*9ZnyK{P50K?IL4WW)Gm*J}g<1)e8ULYHYJQeMxR&vz2p>d8^(5)r zfrI2tgb!|jR**RX%eqgspo5vF(?~boB3~-{5`gluC|BsW!ph*C?bP*o`s_#aiHtAd zop(cz@4^%2Kr^?JHWR(YooW`4f($haniHrrp5omX)GYNZyQ^ObKTbc-G6v9{Eh2ow zf%nOCKRo18p05Q?rq7?D&g<#h9rVWz@v$67sS3rXGE&#`-y9K*s$V z6-Rs`c$IM|^Qt{=(7{=JOV*|Ei7J~9=rkGQg7;?QF2=LSqoQY%InCDPx%{Zzc%7T) zWzBXed1VdtTkr%Apx+kjzPgHWI+Z%CR+BVNW^oVrZ&jimZ-UE@qX)eUUq!zo{22xe z0(XTUW(~ragbx(hIMw+2c=&blw;MNUe3co$W-eunkpFcDw?4j+Xn*}^ z@RsAoGdBt!eT=zr0^ysE?6T06VIpBNx3>Jb3?|4N3Rjw z(4Bupz7rac4P_oZnfV`mvtFCDqd!H*1($aIg*jdruI0Td_}Y2Ghk2H`I^c>3u$D&t zt29KnEc)Z&w9EPJ!WFE|Gk{DWpm~t+8{sE17wlrJbwI-%@M84*ddzm91M5=D&084T z9n5tdD#Lmde%gT?LYkJ%Hu3Fp*3-~9af|t0wuSE7d=8o50c7b;){Ym!e;L25e;c5k zM3EiLWaJ6q8KVDZ?CbuKHLd7Jt{{~8-^G{6HLSy}$5^9J0ax$yUKX_ZGx9Jm8_VEF zt?-qtz{$WG;16n^2H7KV;cLVTh;C5ktM8(hPeFD7n4iv~?tdplqN7d!!MalD_lIgN zk5e3IA#7ouQC2l;yb9#zCgl4oXyb0^%UP>ie`YP;q6K4sU*x{>-xf2~1h(ZT!GxXFGG{=X7@BtSnesdeUZ@(LuQhnb|->A2nS zS*a@~KFlp)^XIf{8*Aym0jC0`%-hST6YG2Pw|sMmIcEX-rv1>$DfB}f{aqaXta*{v z`)&}Oi|`-aHzIq(E8$~RBEKUeiJowXkl*OwCxrjtz?X@$_#Gx(XQwl#Pf$HhzW4au zVFP;<6T-h{o+=cuKF^wobqDgpboyd4W1&^gOW%c_k(tp+$^0a;49!%5@5$_8VAX`&kU{!l{kFZ{BwQ|Y(HP(Yms9O7yRsiwmaoq6D zaL5!$LFa{y+L$npw0ZD6CxmbGMS<{<=;yhS=g;uo5>-D628kbJ><}8I?DJ`${iVoS zj0flWMet4 z^rFhLu0oH@O~CM6y%!|!$4!Mt$=(M%+jF(5@HD6e@Hj6zq$INh_?6luA-c^Z^tnTx zBsC;FSoB2Zv*B0c4w3f(;K#HTo(5Q&AIa}0kxd2A8_8OkeqLhylKtWH;ZL_y-xHW4 z8yRDB;XMl(OBvL8D|1z+T7hkqK|iLm?~!5tow!etE_&{LjQ=+Y*)L(d)>_Y~V(VM% ziT#?qzhkZOGHa*3jBg453JCv_y%6C!^8TLiFFjXK=5q3jPIDb=d+KVP2Cti~?lB%= zen2N}d=ngA#lDzgK4UJj+ZNuY+Xw$JKL*G=$=)P=VITt(p?A)u%p|i6UKL_rVje2_ z687X?3crtRk_5hotdn?_K9>1lKYJ7sm&muSwEF~}C~`#wa(5Xz?;+-zHu*j_ZH3m< z@cW(%c>h1(iwWU37(0#V!yEM&nuA>bS6~nxHyGY!PJ*{4khYz5)``e8PiVO&*PI)^ z2i_-pKLgaMjrl8;dASxjaWY{Cc}s;aqA#8T&zz24#|I0<17UM_eWS)Prua9vONMzth9#(ud~~9+3QcEyS9WF*LmHlr^fXiDa#L z4srP(94KM#X)~^* z?@DNAHhTK0^mje$BNhTN~0s^mJ{0c z6~p^eBKz8VR3Zc0^6>v&zI#-;wFMbDkFZbWGRFl(M#HwQoH=iz)j*h~%02LPkLZrh zg$~bEt5`oS26Dkerg0|o?U3eIIq0D}X!F%pA^5wFeYqLX%A5528|q5#qe(UIR`c15 zYO!V#*TFs{dv1)OR=(Au<=ffFxvgr8@h!^z7CP?r(A=Bq5YXwsVO?IO`W!S-&F^nn zExP>ANmqy)0z=edd-?)!DZj-w5 z-eNP3@66EsC4DAPW-2vXe&{qUJu>2- zPT#@2RKpmW2klLQH~fmd@e*h;1^utc<08LzsP$%;wcQZo@LA->bjI`<=%^k=&%BI& z7TAxj%K7b$XTEWMi+pdMs`8QLyY+9eT{snbxr@Gfl(BsSe0x2z?C<&3OjQ(j0(^Ko z;}<;+^PrD?vV7>Kj(3L4FRK%f3G_Zbb)M?+h5v$V9MEfyxvEaR6~2nSk44d7oXh%Y zB5j$-IGM=YFp=^A;!6lC012y{-xb8C^IJgjOPC=c@!5p(ZmAQ>bEQ+hr+(N7u#qUi7!5Z24ZfguoO)erq6Jw~Oc4Ft#3($RqWYu+Rx7MU@*V zle7}zrEXFWx1KsAUh3f1CGrmOQsyimI+WkB^^kXZVuAOYiHnry{wBVF-=l!|=)6)l z{Y?C1e%Hi6EzcwCA?yER!T9>_W9h;rt)F@5YI7s}a3Nz?;Q>OiCQ%`ztk5_4eLjFe zd{|CbZUvZ)Ls^83jqh zexq-Ze<4=>x-NV#d<*a;K)$sIm;=B$be-I9&gWU`R0K2vl8^d@K0&w(V0Tl0&wXFY zxDj{=kalbWr2Go!nKp$#4M@2H@;!7a;m=a$O@vN*yGkEWFz!82o6EFQNA=(MuFQkR5uDy={QtT;d%3h9$qGe;EL`+5?KTS<01qp9UWJ7uv_~zY~&2{<%2T_@2Qt z{Smqq-Nh&1>r2gEbq02?PqT)QxN|i0tBcK6^;u-Ioy_$gQ9nfHLPyEF;9b)?=L}fC zt57R26`=m1&)eyt_rdwoJTD}azP}&16?hB~{OtwK1MUVk0V{#a0EtHnrrT~A7wNi7 zd!GP43dryK0Kw0CU;(fb5c~-UZ3vFQS?CYWGjuFIWi%eYLHHK%5+MC5X@cJ$13w48 z2nY>41V~?h0+96k&{4IpMwo(}{cGgh2IJ!J3*fHMd^!9AGJdj4 zr^Vi*-g9(xOyn;RT@!G-)+>pVLKhUe+u%Ftm%G48Jo#-QTPE_x0wgR zKWC3D0a>Au_t-Nb%~|6}nbdWK0DGE4z-H=E7umBY=ljnyA7#N~f5twR?BTwR{Ev+U zu*Ccta@Ir09S0oPN+|FJKx`kL1hBc(Yc(iKhadFL!{q-7?|;OB(+C0czW}k@JY>gv zI#r?u>^D3D-WvW&_$Dw3z(y23f*;6|dPtd` z76*z50qYt-Y(*&#y<4L7J%IMJW=^yu9X+`0&kI;Hcx2?D)mqUTngS*L24 zODJ$Ta0NIJ+y1{ptI(^al|P05ZZ72}qb0Pdg!)Qo+tO*fPSL-RSKHc1sC61&rJQe* z_e=*i6AFADxSKTUX@EOdPs^IO{T~hN)!25nPGqMF*ZB{3&U2Yuz$_%kwM1pMfs|?*mV0eT?X2#sjej77$zD4-Z}L zJFF|Z{!zf1cct+c`u_xUC}IzAIqP28%m0ABr~R)v@E5|ru!sFT@QU8cw!>fW`_E4N zpV^<#HqUOGbhs6~90Ls5hep>Uq2O44vzC?f77gf+?nZ|(V4er;LVw5Jl(mL6#^+gc zfOGwx@NV?-=!0ZkCi*vzxkK!*(dGSu_%wI|x@h+G`^uS;AP0%1Z*r&+%J>ElaicYbc{T#atThDAsx(m7t(xndaU9F!! zN+@;u2SY?>K2nz+(W~qB3l9DPpmC~o?5-~UxI)p>YtVQT{Eq{oKi3e2YZvDqCX~MW zM}gH0ul_J_5WC(F19z$h_LPqsoIVl!#z*65EE@es)22Hf92)H*oEJ;4{|LHt%N(Z9 z@XPE6y#)N(fu{+dAwAvBBfr`AEDgU4Jg9M38h&~_x^(0JMW4{}hoDW#t8J^Wt1?*S zVlO0i6jS84dXu?Xo<(2Exk+`Ws#JHP1H=Yhapnk}Wpxb5Y5#@B<-~uPP~ZxF3%Ji> zUl#?YoLhHmUww5>f6KLbid_%!!29hcgxdd-Qd*eO2Tg`)@Ax1YXubz ztj!g(lffFw1gxJSksjf;!YW`l@c%fwAGo^b|Kb17_v_F5|Hy<8YlINOFoe)(#9|?Y zX6>J4%a#ctgb;=hLM+UL5JJcnLdXmugfN5~p!k-|PC_ez)tg+ueDe*X#Lw zzMk**Id#sd)BEuH$z|KEL}HscFAKB5YY#sYts+4g21UX;{w6jbypD>=A2R_>{5`A> zwiAC-zaDkgCqAiDWCO-FAa5+OV|zKR32SXwA(EVoQnZO|lmf;!Vx5iCQ3HD3gs~Lr zrquHX?>VSKpU7qtK&{QGwK;V+?-ofVE|r+nYB0A&j1rM83q{7|g0Zw7k@3{rDph3b zgcgx>u5W{F1>|pM&>)gQe#RiD-Dwrsp;%-`>hH*SCTnKa@=>yBAaAENyd9+gt3-B5 zL8C|(F>6(e?8@A(#O%iUyXRpkZ&~RO*&|bAPx{)6`g@ItOq>Yj_bx?~$Uf<)6WKQj z)XwI5HkbR&My>FpanRTPt3?i=R*sKheq`S)a&RFkK`#e)Vo)TP`CQ_1ThImaCdJ4C z@so(3MEoS;ClP;01sc$S0g*!uGLVm2k-P#BlSfP*F?qyHCT4P#$YD)rM=w~1m-KRY z3Ro+@2CS3ch90n1{wN8`LbJW(hS*h$%^oQ?q1LWLhJ? z`kjqBG@~2Tolf29)GaL%nZbH9DnQH(VrF!Jm>FwCW)d@#wPzAHvmCW(LKpfmA~GvR zmdNZ(P-9Lu=xGi;&1pm%`Y(C=3+=>kpX#& z$Xir^*{DVXTG5R@tQI+ooU>T(tbUMt)~HA&bt{`d?AhsHzs@G^>;VjmoI?-il!7(S zrN?tqM5+vuLC$$JbzTkX(Sj~e|GW{A^J8#%0c%!giCidP{-RQT{F;V#k(yLwid<3z z`ni;Pm*s)$wYi{=%gaFjR}^DNsOI?RS9ZDu4av^YelYM z{F)pTfZEqEckOJj)^%K7S0{3PA)3)9Qa=H?Ant}3^moHzksGOfV~fa5^mWrxkp^-a zN>Kq~8+y=>AyE6~YECl3{4LDi!rZMBQHx=b#&QsITbao1$s%{eXaIGa=)Y+VCz&Gt z&JK`!SFXqs1Lm3q>`U{A$lcVxyB*#9kz^9mkOk`BQ;o%F0>NT4JE%HPMsMk)t_AC^G_1arR zo@D+>E}!E1)BPeHT_Vr)iabm0=NRiu0X=jww>(p%t4!p@QjwQBM7onuEAle)FVo*E zx&Lq8@I~I}!64X|Ue@fT&)z(+U%iaKxm08&*H;dUyw!v*tQLMv4B}VO&)Y>{>>YY} zm;U>jMczwCqsaRcz#1Pg*Pq6jLJB!cNUq4o)EZ#TPYjaLCh}=MMnyiO=4S&~BQi+c z&spp9UXd^AM80I~t1^+VS?8Npk)a$=|JyW?@2NXX%nz*bV+xjv{4^1LJaO$8`8gX6 zBEM9M{7U?COH_5KjB{l@@L@ruBje-?nazfw?xA%1q85B^GAYIq0J1b*_6 z%{yZG3s+OY2b310jT5KD;4fZz9_YA(;&>(K6~`ymCpSn&qc|ZkVT(8s;}PRgJAXjj z$q6`m#941hob^Y=NupL#w>TTH-q<3Hh_hjbILS@oY*c_%oZfvRxV{PXHfa|>~s5Oq9apaEc z!>~AMf+S2pKFU!G)=%rgYH`LBGd>;E8D9eGjPDVL=Z?-+IVi%YI9oS~lb(wKakeQ$ zr#RbA1U+ucTHAGqlR@70b>i$m-VTiINd3$Tadt{Uw>UeOU`U)@O0i0uta>zyvnzAE zCnFQAvHNUPi!*^<_VmTs%ZM|P*uCjvU+kAA&i;Mk9KiSi>Eh(X;vCp3&Ou$``Sfu_5;DX&k~OAeiBmuiN74Jy4dN6|5a$@SkF7&HSnoJ` zDq>BZ`#43+7v-Z=oa5O(K|pUOt`VmgC*c(4O1e2s8S71Ft?Ah)26d)4paZKwY$@}l z)G4KADS4$;s7H%9GfKpnS%^w3MjLv>nbj}O>=AM1q#z4dvhfr>sky(|a)>&b(o9=2wVQPFy+TXVi+bfEo+9Tu9A@tW`nWnXANE z#5#*|#5v0cbt=g_oAuAh1-+h|E>2Y@hQv9KUd|`xf?})@r<$BpzH8mk&9xGU*CXMtiq5uH_*=w8OTSeI5$od=cdKt zG*pRmGkx4LB2HtCIJc2|JJ;`^k2@R1xr^8(?dS(F&Fm+St80m4lf_xd_DXWzY7=Kwk2r6$?mNx=U?pFiKK7%plOIyk>-$xx6X%00 z&_{o_I3KdkN7VQj1F6VFjX0kW|7ncH;(SKlU^Z5X!{em$MUyyRmZA%ceKi3?;_#U1 zd_&xjL7O<=mWcBmb-rs6=lf)^Kf_!O4~z3dvp7H2it`g|j?m)>b3bQ*I=@tl^J_lH zTSNYuE^&TK0@r^pMwvK&lwu8kP*f+*pJ`ydKYKXQM+N7hOcN!UsOH^Ry}UcC2=$_L zqbS3+O%~<$hzdj$kBcg95;bN})cU!ik_JSLWq#~ZQ5zPbT~so88+C}{DCjfcPzm-;($(2StrDNCEwi zs{*m(y0KbRnvV?RfxNT^QRAsGzD(3s zb|Pn|4pBSP+s;iG5w%O3s4T8$RbrK>T_>Pf)NTf~qIRdB-HDk%?jEeO=R~mnUTp8x zAZjA>6N%fK%f0ilRMbAn7!qVGxcatLvUG-8b?es-er1XZFYv(DrZQHRxuI-I@^r$#=x`5mH;Xc2W} zlc*`g7qHe*#iEYR5;c|mn#x=uW5*PVI<^3PqK?bKsHmcDQO9SaN7M=Fs1kJ|aVHLl zDlWr_sFPYnot%VrQKzgHRYKl0YMz>m4pGzdK;Nar&CC!ri@4dVIGI+esJYZED;0Hm zwWxWlIX_=iIq_%2obbq?Qq)3X&ZO3vwW1a=epV*BMO8KnZ*&lKZiT2SoYy1je8w)I zPBr^+;RI0^QS0J-Q8kQR!q_FloQjz`m!*iRZ4q@jb*_xDT2x)1sH?bsb(^Sbh+E9% zwT+^#s}ps7u_zw5RDG|g8wNz(*d*#E#v6)6-E2hNBH;S1Wgw<89qjvUt)gyct=n1i zc52_zDXOVZ)SYSQ7j;*Ts3qhssprS36{7CW!>FixR*Sl~3ado%+D|QI?7n>Ti(1Ay z_fx+mMi!{o!n!RrAhx9q1EL&)P988 zk9MLD!=l=Jq#+-y(MEn7_1lba%!wd0yS1Jx1to}uONQ~`76j@F)FHyp1UT1n67dV z(?v`dF)z@|OXPQx`*NSCSLo>#>c5hQGSr|EZRo)usQGF#GLeg7RG>~&Po=2WsQdb2 zQE$+9uL0}#PC!0bznArUS-+RK-hPbm2aPGnLLtgP{+mnDi9QUATInMVthtgkSF+|x z)?C^8ueXv#y;TXu-s%>$Y67^<>s<9Vy}Vr`>K!iED(A9V)VqsC^--7Cy{d0e)O+cm z_IsnE-skdziC815f3>I&S??o30Y*f9OwK^3s887bjJ!eSJ}(jVMGERgeaYqON>N`C z|8=&gZ#V`+#C)4DAnH5jz9a5?diWs|)uMjv5jE0@UQxd`idsXBHLaq4Blq_tFh06i z)SopV_b=-H)h3GfHLAZmMN0-oMLV%*mB6;{5p9xD46fTO@E1gOjcB(J?HCg6rJ))F zqJ05zehC=!SBnm^F&j-779Hk-?U0&LF9t-%-J-`3yFTkB`Jy)vu+CU|*sxS|GCgd> z*v72SjnSezqvbi0CaF(FSVpIIejd*W-xgF6LoeP5dHuQHKKRn za+d}$pOu4A(Yq4AYbH8H@75%G_aV^}xZI-})Z3Hzy>diPWZx$)6}>mxdpC;Sr%?31 z28?AFi{3949JBq&+rLxv0ac=N($EZQ9#|s!AZi@cCHmlO42aIH6+I~*YeXNy+@UF; zx4a3U#$;+vE*59(A5)spj(&`YE@0h)YBZo#^ilM8REp@MsdY5tQ>#!Xx^OnAUARW{ zF^nJEDf&3pIc`{VQH$sksCQzS=wj-fBq$Mm@pP~Ohm8fOBzI9ngjOd zGUhI0td@Q*XYBF;(O1-RQbzWZPK2t*WnCEc#m3x-MPx^<367 zR?qwmnaD-4=o{(d#x~J6)uS8KzG;o<25L5Bfc1E+*A3;MenS)5McZ87NcHsWum&)eC)eF9kXcGkST z3xlHXVD64oWKeraK8Rbw+!Fd( z(g|XgjEZh9LM7<$?h??$-R+zlD-&$r(oiE&AzH)Qj%$!Ftamf%s=9h<>gBYeaXlZs(Bb=UIC>y{?Esovv)r zFXUjA=og87iSd_OM0b~?Q}oM>@jOHG+(N&yRP?L0Ag_noJ=A+W8LgswQ^5S2NupQg zfqHMz%Ui^}P3+tB^EQ3FQz80Y=KF|$Z!xI#UKfaeZ&36HX`=hn}3UCi=^A42xb({jW+;Df(;jzit&hR0QU} zD-iv?piJ~|qv#*V<+Zr}F-P=IwP+AMLa#iw>z`TomtxVp7T3S7#v0MT4~hPR{6DHe zz0pFf!l39sThIZn|H<{gsPk7Bxc>LB7^jnW>kWx9{bJlaF9JaXq7q$3xls6jKj zFes+nARW0VMGczKg+VcA7^EW?rKmwOx-ckafk8TQQHmNgqYM3DKNhAU8^x$XBRbHJ zQ85+iC`Ox@Gh?t{XSRd6MS0*DE@~BX7W;ozg_z1UV$NobbI3V2p;yd#rB8*E=YAm+Ms5Pv=ET;DIIz6A7f18d(i+vc)tJduO4TCCNx!wt+g$ zxnk~4LK#NI+*1X{@2wZJ)JG|}eqXzoW%=j;z3_8lbAJqu!~J#W64Sz3Evc9whS%`s zfmLE2q_+pluoz8fMK7rN5cvz0#idmj7hS%Jts}M^;zb{b##dJ{T#Wpc76<|aRkB8=!ZZSP|U>{y9 z67xFqulIm@Z_q<8b1SL)R*RTbd1Btqz(g_c&!yie}?12rVFHlr={eqhHLQtodg(y2SiN&R^vG)h_1m7;OJd z-M@##%0yJ7Tdb3eVl-n!teTB>v6@fR(FJJ2YO#hKQ-^-BHWO9o73=chd@i-zQL$bs zve6*cPeK{U@u?e>phs*-ov=}CWKfQNv2iYzVo>auEL5OV?0N!n)@S{sLd-@bsF~D+ zHgtm;NyB0{pymcC$ON$)EEPMJ8e?n4ZkUF|CB1FPIKMlv8+K#0*km8nPo`!vJ#3VY zDo}Id5_EtyHpv5PrVyW!0j{SMVK!^J#34XKXz6w(`Yp%k}Np=j~F_ zh9R*T>_f&Xu{%(6he9yEBkSzQI+@I6R-*&`Vt3;DPOQ0e3i3d`T|{iwY}A9fUFmz* zY~+jGjhNlJ+@1X0S&QEd*a>UI?!o*X%~&mVPuARXRP0`5s1ZA{RP5g5?M)y16o5;9 zu3`5b5u45W+4Z2-e#Gsc0b=`}=e z@2CN>N7sv;nh9d2_KGc}eqkfn?_;QQtidX=$1zrv4|0yD<_Wpz7kgrx*ka;N;`+(- zw^jj{?8C{OVoym$A?m>Ol41;totA`3bcsEc?Nf`;Ep~c3szL2i)+=SKbX4pN)|f$$ zGiuQQdYI86b|$rXzGr#9XJ?h5SM2Npv8QE&_2#l4WlP1L?t>oY5jT(g`I%@I%X2wf z&OFcC>>1QquvqLuK{*D+R&c$dPwbi0Jd^bnad}pX*h=c3jdNy;J(s#wk z>FNA3u@^9ZL95v6G<1o*a3U%|-HV93m~}3$!idZWnt`H9E!KYs4;1Ln}ta-j|I+(8GQ7b07Kl zk#`?`-be0zqhgmOBNN2(+{-R21+mMT(S<>=_Zy@m7p15|JzCI(evF81i9uWowOR^M zh8i@Y4LumdsMrURk%@c|_dp$5(1Rhd55~wuE{aisIy9pLt3cdC2B{$Sp==bQ3^iy( z8+tH^QL(MbAhtCZ#i&3Xn$e9Ru@4)hVgm9}iYnBj1zqUJh}cJxLEIySs6aj1unHq$ zAB~X->O5M8I<%k%Lt@)vq$3xs(^i9KbYW2JV+QHSMltB)u|{;DAERO)PenHJ!SyE^ z#kO;wdXn)c*{7$te>~NI4zTW1{b22YPK zL2L)H9mIAJ+p${gGlCRkArB>}#9}N(Cy0G!SnRVt(l8N4Anw@)w4)De#6FjTi6}xP z8o-**bz=Z)#C9ej134hBvmCW(LOXh~TI}PP+w4e)vV!Mg! zPDd_EQG;f5VNmSL2I(jT$Muy0EXJtVS7Wg~onl{Sythm&zdN%lCxV!jvr!F>A-_Mf zE4wiuc2$-$#5OY_T6UiT#*IGv>tkX*W*uHv*nvEZi2a1QPm{4&>}S*;#OH+|{tMRplJ!>8^Xe+pp%E=&zasx@ zL66vPvOz6g3)mrQ4N+sL9o?X(q19r)tp#g;yHxCVg596>d^vXd2M1x`jLnq75j6HRAeF>`6xyis!)eUw4eh$ z=*NiIUt-YzFWD$W8EQa0uXXG%#QrjfQL(=g`)evPLHw`zC`K8oP=`jepaVVV#}G!v zu8EO~Ok^V;#VA7+>d=T5bf5?Q7{aL7-(sX96WPc|G0ISdIy9mM9q2(nhA=Aj_ZX?j zL^krl@%_CD9N*tt(1m_*Z2lnrk8}|G2gl}*GSr|E9GgFSFo;pHqshobE{aisIy9pL zt1u+?PlHrUKt4)Qg?hB03;h@o`&W!~WTOyes6ivz(1Rh2iv64W_usi7?(Yh4|NpxK z1LBH72KY;TDMKAv(1Rgyofw(OM>#lyq{EpzoKEzKs|3ueB2NMnmJl%i} z^kY<9lZtEaaA z>o zhAiZRHOAMW1-yS!WW8o5MN(uYUvEkpWHj;TM9$^wZNyim5s@7nK1+?u#Q(bDJHzZad)bb*tBHhnz2V>ALNR&zChKillkW-h<|O7zb@E^^oP&v}2ga{JefYhwOdw{2uS??1U#VsG1Z zs_&Kd_C&$ z+q|`X^0^@1J?pkPm#EjeZkx}F@RqOJ9xI!9{8nyl{D!Qx?wIqFx(x64b>ka}?{Bqk zdt?4!c!!x~^B2sSm$vZi(@&jWRye1kY|gw{X$O{7%vdmQTE&coX_M2Y%_~hiEN$le z1!)!QrV}I6%F5EFPb*JbIHRJ1l!XUQpFU$=#f;LlLl?}LF*j}M!E@$UOiP zjmN}A?Dfucvpv^#TDyl6*KRG~|9jA9V)Rh{pEy?kT;mgP$(gWrCYS#w_N!v;nme&Z z8e54D5=U<*X42#gj=>pguNCqCt@!t!z4`y&+d1T>t*uhQv75#bo*}1mxj^PJK7Z|c z|L0rmh_ziLZi}y-!xq>prpz|IS+bZ)bY= z_x`vu{m!S8T^OCgp6#;sSSN1LUH(6^PiHQ1d;I4p{99omV`s7#iTg|8+IvLeNFTB` zK5@^O%GOL`&RTo46UXnL+oFui>1+2PalcO-g)>bLfZdTXNi4D>{a3`{M5Dg^nd#M=j$QywV1f~@!1(%PUinx zae2_%>xpZLK8|C&kVly*oVTrT?ezosDm$8(Be_0VCauk#!blq56{awnyEbF;+U-Q$ zDePzBd&QAFKBe&|?~~WYBx=u~tACD8;yBHaN{&q8zOaygiFUA zB#z?@{{6ok*EDXuf2#iHHd(m#wwO-!nV3%1#8>XTwcnejt-VJj`b>PSETE6XvHZ_> zlSGG!$i%Ik=q@o^!AJ#{iKCmCPux!v-vbwLJ@MTo@fCJ9V`r}2voncF?8iS}v5AiU zxi|fLulVoxxBve2u#k=uw`@79F67uGdMo2Hv5&L3|0j-oK6_TSb|le38Zl?n>#2;C zar-5DPIUiIZ;9{ciLcB=zll9b+!BfV#lL%c7~B6I!~dH7pQAC2DrLlRHeEVPteE(^ zOdOZQDhs(MOy^(XD?YJ8;`klPiiz7a@%?Km_oBoROdQL^x}{|NyO;m<`}=X^{O6IY zaP9G%$NjOA+{E|A#Mjh6k81yJ{nz{>)~-K?+vD`L_o~Egc+lD-Q~EzI|E>4$OyWK= zooT<+{EKi z;`k(vNaFT5gKlT=$W+Mx6MLFV#l*ch(bL&H^HbozzZ-dU`ak@)UNg@jm7{sKVfdY) zE1vigaBjs&__S`GAFeM+JgXcl8%nZlBpb^nJVWI?$g;Vla%LFL+)GE}`986=q{}v( z9ArEC+g^5%9r6K2z4`vVuVl-9oSfqT$>APw5c`?S zZFLCymd8EpFupJ3^Qdto_t^qDiti><*~4S_E_j?2@qOb2KHa8RPLh-56e;0sk4BbA z4QJ|nMsAeVa;aP`SITX2pENsGu5et=uX?@XIlf%w1X3$2i8jr``MJKH$hI@>uJ&i2j@&W=u|vy-#4vx}4E?CR|1>@L4M6P!JqJ)OOriO$~6 zKF+>QwzHqJzjJ_-;~eN5#F@cAa}IWLok`9i&Y@18Gub)JIo!#2j&P22rZ@%8QPL_8 zJ4ZWHokHgr=UC@Br^q?pIl(!RKdl~>LHXP%c206mc203hoN3Of&UB~Lnc>WIW;wH+ zInHU$T&K)A-I?dicgmeJr^@CIp;eUNS}P- zRLcj_FCX#>xzM@Dx!9?3E^#h(E^}&~%bhEnE1f#$D(7nF8fUR{t#h4oy;JYp z;N0lkn=onM?^oi)yH&hO42&ZzUJ^Oy6t z66GkRv@*&nS9!`;f#QswDpq6EdTM=@q&84v)rKlrZKO6Jt?bQxyN0lj$$fIf}wX;0V=goJiU8GGOlNaP7SuU5!{qmy9 zQoG8t@|@aDI@Ip+tD2zpPczA9Vor}kF|s2p{mI!GO?a@8bth&oi| zsmbavb-2n`N2nv!6jh*(Qb(()s!$!Hj#bC0B6YkvL7k|I)k*4Pb&4uc)6}VIx++yO z)J!!?%~o^NX=<)2Q>UwWYQ8F0XQ%~gp{h`4szvH7RjJNa=csd4l{!zIuP#v4>Oysq zx>(hyOVp+6GF7WCS68SjRh_y@U9GNBi`BL2I(5COS2w5|)lI5F-K=g=x2i^Uo4Q@y zp_MpfJHLJVTJ?dVyRNbeRsryxndO$s>9#XC9VfBc5RJEzc)Z^+2)vlgYPpPL> zhk8amtDaMx>Up(Xtx#R+1@)qONp-82)hp^%)uUchud6pyuXTUIodRO(S z_tg991J$oSR3E92)qwg$eX2fFgX(kjh5AyhR$r;F)i-KLeXG7x->YHugZfeZq(;=w z>KFB^TBCkbzpFpgsQOd=rT*rdxTBTU+Gwj??P*^JI@FPl^%%XLUSB8a4fI&Op-$Et z>5cU!Iz?})H`ANzRK11XQjgPVdc59BZ>`hyHhNpVozBqP>mBrtI#chYch7(^jU8s-I$LiyBkv?9Zpik7r`Xqg_K1G-4Y5G(>U6<+^dZwPGXX`ooG(A_B z>C^Q*JztmWGxP$zP*>nrq?x=vrEuh!S-#rj%(oxWbz>l^fq`X=3=Z`QZyTXmzpP2aBX&`tVIeV1OMoAurL z9(}J~s_)aw^!>U;KcFAf59wC@uzo~8s@wEq`f>e)Zr4xhr}WdhLqDUR)z9fp{k&eT zSLiPNf__oIq`URY`W5}E?$NL5*Yz8^SHG!O>bLYN{kDEbzpMN7d-{F-f$rBI>W}ot zdO&}oKh>Y#y|J`Wro@zt!LA@Aa_$LI0?K(j)q3{fqupuhGBh-}N7Q zRR5{}(tq<~BF8ABjWO1^#xuSNOlTq#n=xiRv%X0(83CYU|Uo@OsI z(d=#ZG5hjX+x^V`<^Ypp4m1augH5iPWDYThnmjYv9A*wT`Q`|7q?uw0%u(iOGu0HD zW6ZJUI8$VfHz$}AO|d!2oNP`pC1#pA)l4^~W`>z*W|`S$jycWDHD%^>Gmkf;mh*bParor57ZZWr-Msu6Foi{=@nLEv0W{GJwcbj|6y=JMo&nz?d z^R~qY%!B43(`p_zkC;bIn|aJUZk{mh=1KFEdD?WCXUwzaIn!yLH_Ocm(`8;TFPfK3 zw|UvTVqP^p<~8%WdBgOYH_b}(mRV)qHt(2sO`mzsyl*}*{pLgSk@?sRm`}{7<})*B zJ~v;OFU@N6mHFCy!&}7vFq9OZIa!szb|1U1&9?j5 z{p|rZ#~x@8vIpB-JINkm54CxAvOUZmZu9LC_DDO$7TBZg(RQjWw8z+E?Qyoq9&b;u zC)#3rl0Dg;VoU5ad#asoOYICh)6TN9?HqfWoombN>2{u-Z_Di&c7a`JE9{wekv+>+ z+OzFB_FP+K&$H*-3v9K$&|YLOwl($=d#Sz5*4oSM74}M7XRoqX+iUD%d#%0BUT^E| z4faNRlWnj!+gt3dw$a{ZZ?|{YCVQv7%Pz6a_HKKRz1J?a_t|Cke%oRnun*dYY^#0P zK4KrWZT2zyxP8L5+b8W)_G#N;pRv!{=WM5a-Y&N*Y?pn(zGz>v-S%bsihb4g*w^gq z_6^%>-?S_3TXvOw+rDGpwSD$I`@a3a_S+BbNA_boU_Y^++RyBu{oH5p6*`mM0am@A9r6j+uhII-#x(1 zaSwD4au0TM-AV2t?xAj;JJ~(VJ>1QAk8qE4r?>^~QSQ<1RJYJQ#y!?O&Mk6}cTaFn zbc@}S+>_l?+!A-1d#XF#Ep=zOGu>J4Y+xo(wvo_oG~fm`if=w9Sr?AExKxR<(@xwY=)?iKEpZk>CTd$n}R^X@h7 zV)t72I`?|F-o3%S(Y?uSaBp^Rac^}S-P_#T-8)P?{k;A z_q#3b1MY+FLvE}4u=|MnsN3c~=05H|;kLU^x=*=JyB+Q`?z8T5Zm0XayWCyjcDXOO zFS;+e-R{foEAFdqkNcYYy8DLP>%Qr(bl-AUxo^AgxbM1s?tAY0?gwta`=R@h`>{LV ze&T-We&!CkpSxeUU%IQ^uiUTQZ`>jGTlYKndw1CV!Tr(w$sKWjc7Jhyb=SDRxxc%A zxTEf${4D%k_is-;$5Wp6jAuR9^E}@RywHoh*c;=m=dJH0c^i0Ry$!u&ZzFGGZxb)Y z+tl04+uTd_w(z#}#(8PpcyB9jYcJi~#@p80&dcz&_jd4h^fJAjyq&#Wyew~5Z#Qpu zZ-Tdnx2Lz4H__YM+sE72%l7v3_V*6(a=Zh*gS>;iTyK(hhZB=2PJ6tBda=AG(I_e#AP-b`I?EQtv)*nRma};yvI!=so1MdJlV#c#nE*-ecb5-Vxy=J?C|L&wI2LlGp9M?7iZ>>h*Z9d9QnKc)i}6-b(K+ZE^1k)H^S<|n zy&t?Ey`Q`h?`Q89?^kb)_nY^-_lGy?{ptPX{q1w&VLm2P`^LAv>wCWM2Y%>Be(aC& z*Ynr+ll%?*vHpgBvcHkPvA>C*;&1A2=5Ow&`dj#0`s4gGf4skyzqOz4Z{u(4Z|7(D z+xt8CJNlXaPX5mRE`FB3tG}DSyFbC-!{5{2%b)1)?eF97>u3A>`TP3^_&NT8{z3l1 zey%^sKg2)O&+{kyhxv#5`Ti09k^U6Fz(2}A+Mntd`p5Xk`p5Z2{_*|^{)v9Ef0BQ) ze~Mq?PxDXpr~9S;41cCS%b)Gf@lW&T`epv<{ycxaU+$mbFYp)o753P{R{nz{EPh>{}TUF|1!VUzudpVztXSsukx?+keM@*YES+^WXPB@caD_{g3>Q{Q>_I|5N`nf6)Kj z|HA*$U+sV8f9-$c5BcBv-}&GB!~PHckN!{oi2t+yi~p;?#{bR#-T%WM_5bw$^8XI_ z;J-ixIxv9^+`tR`APB-B3gTc)uwJl!kQ8hXj14vnl7o$cje|{slwi|fvtaWeHP|B9 zG8h-61>=LQf~|w}V4GmuV7nkA*gn`H*fGcqb_#Y5b_ueAU4z|%-Gd3i9>Jc$Uctm* z?_i%`-yl2KFW5ggAjk<03=Rqo4swG@!6Ct+L0&L9I4n3k$PbPPjtr&*1;J6l(ZST9 zFgPYSHaIRQ3XTs>2u=)&gOh@jgHwW%U|Mi$Fg+*@W&|^XS;6dJPHRd8N#esDoh9b6b(6kHtC1eXMt2A2i3!R5gf z!IeQ>a8+=1a80l{xHh;hxIU;4ZU}A+ZVDQLn}b_|TZ6{nw&3>Qj-V;HGq@{Q5;O;Q z2loW`21|qcf@Q(|K}+yJ@L=#z&>B1(JQ6$_v;~g^j|Wc#?ZK15Q^C_gNAOJWZ17yr z89W~>4^{+S!3)8Q!An7R@N)1<@M_Q#ycWD3yb<&UZw4!aw}Mr{+rc}*yFp*@UhsbK zLC_z37g~tZX9kBri7b@n}wT)so@skmf^TCEgTc4-huehPhTDZ1;r8JU;f`TuxKp@u zxJ#H7?i%hE?jBAE_Xzh4_X;P5dx!gk`-a)!e&PP%0bx#fV0ch?aF`oT3J(bn4fDdu z;bGz7VSac-cw{&wEC`PZj}E7Xh2b&bvEgxHQFwfKLU>|W9G(=O9G()Egww)P!|7pZ zI3t`H&I)ITbHdZYxnWs&dN?nfAC`w_gbTujVMTamxF|d;tPIZ%&k4^BtHSfb^TP|m z>hQwwqVVFdCcGrPG`uXV4KEL`2(Jw5!mGlo!)wCD;kDs);q_sCctdz&cvILA-W=W% z-WoQBw}rQdcZ5yho#9>KlCU|vJG>{nH(VOt7cL9$4_m?q!Uw~L!q)KN@R9J*uq}Kn zd^~(2Y!9Cdp9-H2JHlteXT#^h&hYtgdAK6%3SS6c3||Vn!Xh|EF26!55EY%3|EI=gIG{u2Hgt_gn&e-Hl%N5enEzrw#GiJVA9Ix>-s+{lak zD2T!+isEQYv|hA+loV|cjg2;plB12HjiXJXlxWjvvuN`uHQFNDG8z}9MdPEbqOGI! zXq#x;XuBvQ+CJJL+A+$Ec8Ye6c8Rj0U8CKi-J=Q79?_oBUeUy8?`WTB-zYoUFWNsk zAj*jjj1Gzpj&h?((IL^HQC>7TIxIRo%8!nSj*O;61<_H_(b3eXFghkWHaadUijI#? zh)#@(qm!bOqf?@iXj*h?G(9SfW<)ciS<&ohPIOu{H!6!xkLE@5qw?sCXhF0vs)){v z7DZ=8mC@PJInlXMRdil-esn=p9bFh*6kQzEM3+RDMwdmk(dE$<(UnnMbX9b9bWOB4 zx;DBlx<0CpZisG-Zi*VBo1Mlx1v?i+tEAGyHQ{CUi5zSLDV087=09d91TRD zM4v{VMT61j(HGH|(dy`{=os%z2b@S-tj*1zHxTEU%Y>OK%5gF7#|cL9OuT9;zQy?nI=(QzD84wZi7$yS zjW3I9>4el31Iek1OU-;7trZ^f(Px8rx> zcjLbJz4-n3gSbEbF#ah1I39>Ui9d}$iwEP+<1gYbHXkuxVqP@M zreRi0)2y17xoXzTHPbdPnd@fVY?w{cF*nRd&6e3VJ7(A1G`GxcbH}`FzSMk~`Ev6y z^KtVD^A+YR%_q%QnNOLoHeX{tZNAprHJ>qGXTIKigZZraM)OVPo6WbFZ#Ca$zTJF> z`A+j)=DW@JnC~^;XTIP3fcc#HLGwfAhs}?eA2mN_e%$n15;hmH9pMug$+P|JM9F^Y6`nF#pl~C-a}p@0<4MuO2`EEo?ag2`YiFhLL;3=Rc{gCoJw z;8^fL@L=$!;Gy8*;LXAD;4Q%y1#b=B7EA{xg0}}V!6U(=!DGQYf_DaA96TPJ3}%B< z!Rg>#K`{se8TH+V95UvMU<1yN8B;vfmq;B4?za4vX% za6WiC_(1SXa3Q!DJR4jJo(nDqSAq`)&j*XaQt(3Xq2R;8M}jX2UJRClMz9hzgVmrF zTn*NOYe74BDYzc22OGg=&Xvg4@BJ;N{>;gD(rdJos4f@!%7| zR|H=fd@}f|;8Vd@2VWC>I{4b)Zt$7l>w>Qjz9IN*@QuMY1>YQeOYp71w*}uGd`Iw| z!FL7U9ehvly}|bd-yi%y@VVdzgC7chIQWs^M}r>=emwYz;3tEh3Vu5Hnc!!Gp9_9I z=mvYiz2KGL7lL05eku6n;Pb&3f?o-Kb?BKZPd`0azcjkL*)A4qMTYTs=VohbyV==l zX-Z@nmKatTE{xVT8qKZF=4eC1k=n{u>t<`DA;D;^v)0*cT_0^|I9YGDx0<^fSJzv& zC!2YEqP~hlU2@QCqS=d%#LWg!kF07CgHB^-G$Fwj2_{OgCBa0}t3A=`MMo1hqov_U zq8M8eOrFgfGP#z=C(iZ|Osw^y((%yhfP}U*`BYwG@>(7rdTOPyHFOPsM$YZD*H>F3 zZ3#xtvHfkf|D3kJtpj$BEp2N!c<%j!?UyFspW~f;DUWMgN>zq)Q`gsUMs9N*$LQM4 zk*6EY-JRCRx&$l|F|3a~twXRb!O+v_-_Sb#j69>YHoaP9o$at(9eGA;ZR)^nHg0sb zceXk=uC)#%n`;MJn`@&N*u4(BcR{5Im8pCMhvR2-aVCb@&pdB|sS9F4Qb%L(22fOUS z745;U1jAQwsBvw0*ZnnD{Pvq&9~!;FiQLt2^7*`7lefJ1k{7>|$46e!9=uv9j72{J`$uGrNO}Z7fY`!QjRAflJpq!_T$XHW~*mH+DzangbWF zwGY(s@8Wh_$LcwB!Zc5GMkv#OFfEcJ(0P<(jJ zb#8dIwZ79BC9a{Dk#WFf?nu`hvf=B}wRP#5HZrOYZtf1=ZjW}fe+RbExozp(4mwA| z2X3HaP5eVUhC6P=ryRblJqP>RH$`MRUCb0AKv?#RbB;QOiYTQsrWu=?TMB!%)RkIV9bXbVJe&NjD_jkaR=R4M{g7T{4Jr zNV*~EhB4`pen|S3^eyRA7L+aNThh0rZ%N;hz9oH2`j-8+q;E;zlD;K6b~rO!{TgFOz9h;R!Fx(x)t`D!lPUv-3sYeNVh_|71FJcZiVzJ zq_@ESE`%e`uWdD;+}zUOdEuiYwg<|?(T)s=Pg z(Oqy*r!#GBw^m0s+M7;jZ?~GA&DHVN?Iw0QN@?A>bZEW3)fl#hP$nl$ zQkjf2O=Xf0>f#7fog5oUdYI^9MJVONMB9Z>7mZCz!xye~w(w_x2)xh z-MOft`ta1@nxd^LVgw>257h{!+ zagOxoNPmv>=SW}YsaV!|LP+{LUw}z}ZUF)rLSUDNfVM*20%Ms~Eq#u!fo%HLZ zUuXa8q+cifI_cL*zfSsf(yx<#o%HLZUuXa8q+cifI_bxxACrDe`Z4Lpq#u)hO!_hD z$D|*VeoXo?>BpoWlYUJ4G3h6ypOAh+`U&YLq@R#}Li!2mC#0W{enR>Q=_jP0kbXk? z3F(uIl~dABNk1k1l=M^5Pf0%|{gm`m(oac0C4J?Z#WJ~OIVFANs>KSqUWHt;qTCzl zO20x?uA(yvgJtB|W!ib}sy)c#kf(p9L^RjATcRGx*2 z?oWg=J_u!e5K8+H%J?9Z@j)o1Wfw6KLL}z?oYs^ulo})>FfRkO!}Gh(*22a(%1bNCb~ZnlD_Uwz@)GH6ENxP z{sc_=x<3JvzV1)Jq_6uEF#E6j6EOR)`!h^*e;44H@z?zcnB%Ye6EMeL_a|VE zzwS@K9Dm)PfZ2cDpJAf=6CwMr`x7wxulo})`>*>GF#E6j6EOR)`x7wxulo})`>*>G zF#E6jGfZ@UB4mGcKLTcdbw2`Tf76AbRoLhvyh5r9AytKt!ZW1s3@JRrdFfO!oYzes z&P%5N>!u6mrBi_ChvS__TXaJ}y5&QP*pMPNq=*eEVnd49kXmiHAVXRV7fKUiU#~ZC z>rxxMP#JgDub)EFl(!+}ZAf_=Qr?D?w;|Dl-iDN~A?0gG`5IEbhLo=%M>Ye@MTQoe?@Wa^6A+g{@-R6`2YkU}-2Pz@++#64Jk~a zlQW&`I;o7DRfpV~1k6=Y7E+Xg2Qyu^Y7sn%u!>UbQNk)pLW)e=S$Z)ny%?5W3`;MDr5D4}i(%=- zu=HYBdNC}$7?xfPOD~3{7sJwvVd=%N^kP_gF)Y0pmR<}?FNUQT!_tdk>BX@0Vpw`F zEWH<&-V00bg{Akx(tBa)y|DCN*mCjE+4as2*czOfH<}F?-G|ot5_H7r&#?4oSo$+8 z{TY`23`>88r9Z>cpJD0Gu=HnG`ZFy38J7MGOB2)5uVLxeu=HzK`ZX;58kT+yOTUJt zU&GR`Vd>AX^kZ21F)U42OVia-9$CsGOVicTbhR{HElpQT)74fNCY|SSyS3H6+FI4I zqWNlRzFL~Ew#rpU^VQOPwKQKX%~wnF)zW;mG+!;vS4;EN(tNdZBFKw&PPv1fQ|@5r zlsnitWnQJL?EoH8y%(axcmNM5;=2{xImWHjR)U}klmQvSJ>RL)& zOQ~xqbuFc?T_9JXp=)XAS{k~RhOVWdYbkgw1+S&xwG_OTg4a^;S_)oE!E0&gS{k~R zg4j|JTMA-JL2N0AEd{ZqAhs05mV($)5L*gjOF?XD=vo@OmWHmSp=&9VEoHK$OtzHC zmNMB=CR@s6OPOpblPzVkr7X6T#g?+zQWjgvVoOfsB>m^kkc z(UnfAYbkXtrLLvawUoM+QrA-IT1s6@scR{9Ev2rd)U}kNmQvJGidsrhODSq;l3JRi zmL{pCNor}5TFOyNIcjN=TFOyNlhjg3)HOe2Zj!Y+H(HycZNj|j&1f9n&0Nx1%E65+=J#2Z0%(eAXT{czB`@oM zJ-B@XuIJ62o1J#EwYuKey0f{~YH)y6NkBcdr(#!{Kz-raSrP@?)QgUQ!TE?mmps+{;glgKw`ZWW}FuSZ@ zGXR$+8agyRROQNKw#f1{wndcyRAXDpwXv3)Y!nQ^;TLdUHvC-Eh)fG^lqoi(bz-)`^3NQ`S;Ez>T0L&ew zx&mNMyvl#TB7YHbv{nAYwBUYK`452!2!2!;ua1!6HfwpJM!vy63(eW13@fOqZ7Sr(-)A1J5@fOqZ7Sr(-)A1J5@fOqZ7H5t( zb%esCReA{}NupLC(&_k7s}C?8KWg;>Rw0t8)dyJjS)x`SVBH^yT76-nRv$uL5Q$oS zfJtAiKES#l61DmO>w-x1+cscb5Q)l9z`7t3m7johK_qGw0@ekYPyi$p0Et?KFyTpG ztwO-0uT~*o(pRexFzKsR2$=NMDg;dWY83(|eaeMItwOjAls_bD6#`cNkWeHf6bT7M zLPC*{P$VR39ikrTt91yN^vV4ba{q+fKT+E+Ow{&6$o{JB2bldO+fT^$6Se)2PkL(m z0nX@gzSZ^%6Y~0mygpIe59u6lwfz8-KKXk>{+_7qhkTB=e$xg_`sC{g`Ff%@A@Vui zY7>SD`Fuh?pODWd{7>=?_9# zPY9(y2-AtH?X_K~y*S?GSUUVx!kQ4uRNJC%MT9an2#HF!B4DD@tq4DtY&C>T*QEnL zm#{R1#G_LTm`&0t228p-#qf)_|1x@*}=iG4V+)t zf!e9LDxi=n8v`M+tIz=~3lbq)rNRX;TcyGU-Z)ZMLliKnt6%|4{3<};ozqr_%5dR@ zQ~aSib>NND`k`)IODDdqsM%=iy5SHi-MVf#z*?`a8xFA2t?PyZEE^7?2pELgzdC25 z&e^DQHtL*>x^666*NugcbaZ0@CLPXBT{jl2PN7$u>xDuWu+T*)s{o;_0)(=f5XyKU zlvRUJ#=ADBf(4=UyEdmA4I%OAMgvTIy3tY!B!p5Ap{x>wr7@g1J>6K}39|@n6-_A} zbcY2>#Ss6h_%}}&hf(&yE+41W_T>xgmRPYu4{L=U)(SnW6&(`f%a9S9zoaP`Hj!}#}NTmGuCm8eCHB_Qd@*!T#=bZ)@9@;*#?HYL&?Oo_Auq0mRjsaA#om{Y3^qBf^886oSb3aGGz(z=TPv!3#-+MJ3Ngk0r1q*%4W6%ev%YBvBTeiawBIpui> zSx(jN+MIGTgd9@kW`H@QwVLUf$xd(AUa10&Qt_nwPDdkXi z{Sr=|6aO0HaBDP$Uxp4xa0slJ+v|H325i ziA&GVP>ezxGD35BP@jMv;}+l;yZWLVDh!1rPUG_#)edZH z9&k$@LULneQP}#znh;VNs9F!0Tv~Mpz+@?^zGLfixvAO?n0T~pfJsNya=_eA>XgBj zXMI(}0kgiU-GEtN)oj45uWB{+JL{`72F&`ZHUnmTRg(d;zN*F8_pGl{7%=;)a#{DJ#hr7d7?GnKZ0$rn`G0_Hwf^%XE#XU3}4KLLKiZL9tWz-*VQq2McQ zx9U*f420E;2h4F$cRpZ_gK9Zo2gH}w#96GH< znQfq+T*#Z0JftprKIb9T9?WY%8BaLK`#3$AmnAZIy#3;KQ}##D7Iu+?!Z9-NXglW< zS=!-t#vQVhBkdkf$dZD#aDoh+Xup(25Au3W4l4u5;6QKlWZ-zO;!*E@PL?~=IKAB* zZ;<05Mt;`}8hOJ}WU6-@U&@n9H79tt3W*ch2yQpWv-D#D*I!si9Xt z5FJ`^e=wlU@n)|rP5JhYG~CB(t+vy4^+ ziOZE1kzz}Tn*1J@tLAzz>aJ)Z47|HrF0YM0CHDpZnmYD#uaxY&xFIBRZ z54T?eJi!$u(M+0vL^fSRu2A5u9)LsFU1@2534)?Iw2nXHdZSBX*?_VPBu;bGUE`8W zx!;4>(1!c7>C*ICm&Ep0Emx5^f(u-d*K1S9ft}uB(OXyWAvuwZ`f$gsq@f%5Gq&T7Xglbm?vIk94m`lA=ekQVIjAGF>_87bczw0-x;kTt=JXcFx$oH4nACN;D18oCK^=$1>7vpU zGx4b2lG>bpGek&ns+J32iet540H;nfbLB-CIApad&53H+n)v0OSG#$Kxhi3+<#}`E zI$Q^CP2RYM$2fwW2pP zns=PCEfTTOymNSIce}aX!6B0M_Rh|FONwrgsySeSXb`PtEUIm5N1`hD()(OI4jSwdz83oYb3lCNAK9-!_Hg!CsDlygag4x|S z^>W7{n|jQ0KJ@^+sfX6no3uMqcf6_Rtj!(1bKkThC7*TxJq)im?Wx(>H|?w0w70Tp zZ)MZo@uqdE<4=3%ji#NWLuIi_WwAo1tJ1e5C8quv4(PoV(k0RQx5#3x7ZPM2RE23>1(G3>S z#*OF>i)iacbc;o_c_X^VBHF$Y-DDAM;E3+Bh_-MA+IHLP3qHP?hKLP%DU1>%A zQ~_95LQy|e0M?aI)K3+Fb)^@%iRX0lLU^l<8>#=I7SZO8=$nhw_Qp9U5%xHsQR&G7 z04gQM!RO4|5UEOf?jyHU$+w{J^iLM}OKRIWN|!OeDt zP-uX}s3YM*M*-ou5^%%?zeF5*SH@v?WfZxKDQ;ItP`g5cdHw2$LyW-TUB3#|7Pm1G z85OK9bV!l!a3Wt(BBB^kKoG89oe+GYM$2X`s=$YTOgDW|1wUYARz+0+0CP%J5dh37 zRi`}Q1s&+s&CZ4lv_xEUU4#SeqB_tTbB&gAuGvyf8!l08x)hYgOH7)-30JMqkcgw< zBBbG>N<(9ghLm$Oq@2=_sM3&vLc_(BiE(L#D*5n{hRjp90AMmV-2#Bg+_(io-C9T| zGu5qyBjC!+i@G%dE0ZpgITy)1i^^J%&v{W+furLpEcg{0NBcMrx<&92M(2%R`Eevr znQx+BCIBn5#l1-BC%>u#FSjK7$x{VL=hkFDaeP+Sjj|}vV}Hohd71$AROs;Z1Ij70 z=V=DCL+d4a>H%9=`&BF_0hT(6 zbOD&%Q4Wn}Wy4GS*%wXakSMSDyb}yqmjMq$0M_Z_VGqD6d-?4N)5Gba%rEj=Uy;j* zhbhnw?GF!KVA_dCB@2d=bf^pP&;sytTUNpV`=Ec=id>CJ_92(5MNyr#sLol*W{;`? zuR`O%Xn4eZ9d-);?hSVi%&F*Rdw1I%SZw3E`O5m?>y4Xtt~c77uyt@{e7$pPT2ovl zjmZH`ufVt_qv)Z$DB6yMgWGu1=Q`|x4xYAfSKYTe>+RLuZR7&^)DC{XZ5q4+{A&r?W1^=XcJ0|T4U{-IASTws#fKv zO`eUxcyKwWehaRqyCtCt#WO5etz5m?II60L^lVqD3dA!m_>j$A&hKeFV}lRvT=iUr zJad9}aQd@duZjmgtY_2BWzXG@GbmH&zuPibo!h|(u;p&<1DaZa+XG{vSpsBPfrGBM zV1-KNL4sK}9}{pG`K&w-`WB{6jnJvMY7)_2e!z8E%F<9k>9+F)TxX7CSK&X?;^i_7y0eG$Zy~HmaF_i z4}IZVy>5V_9_GS#93A+gdbN?Se5I&|zW|ecMmRj-l+n}M+kCDdBxejcN1-ZVP;+%H zz^)O}VaD0jUdGy>8k})*wXu+%v8rrMvT5q@hdNDjf@>tCqzEZt!gBfH?Op5)H&3xx z`_Juc?KZEU-e}9}N6Qprs3)RveMl*Vd}smRy0yi6f(_-hMIm{1Nahq$wuJiW2Q8~l z-GFOWeryrM6$v?7NKO}0Fok6NAvtcSpT1$WlqPSr;Npc=-`L)EIEpq-5{(K*|%lC0R*vIXct@hz|u#elp{pEe!F5k!P z=gs%wcCe4z!9H#W_t*Dv&v|1o*N5A|K5hs5xE<`{c5sHs;)xna+wr8+k-=+EW9qhNwFYC{jE9cKw2KSfuar^VtPuHI>$#ZS@+U?I*mhavGUkEw%w+z$5J?O-3bgEQRz7)Ts>8SV_uaA$CaJA*Ua8SLZs>$-mWxEASemmI5 z?O?y(4)$?7IK%C?Q{u?WaA$CaJA*Ua8JywHU>~<%*Pky})}OBo_Hq03mF4@m{jzQh z{dPOpr|sbW@_xHrem2IAmiy=96Z%{WS-y|YrTK01ak=sKaXHv;n}dB^4))vT;0(8m zXSgK(I&g+N%g=CUaE3dBecXOsf4*EC%lh->%KGz_!Tsg^cFTNG zCcE-}o%U~b3%x7PIHh-?X`{$3jgMEAs_VGDb{ZDhMAl2qnK|(01970i$ z5b~^sT8Dr|HQ(mrmp1VOeE?@F`cj-#nK%93J zf(WId2!#N`+PHj4^lC^`kRz4~Lg^Ah=@LTeQn936LMUBANDA5|z{JColqH^|Eb$~| zi6<#bJV{yNt-q2w%~78%RVO%L(&tIb5>Hx|c+#?D?G$Xxl@@H!yfZv*S>kcalB)Q{ zl3FDQWj+zgd?J+jL`dTNqES-o2I=g)dIgFlH8&Bm^SsDjQZEM5If!aP0G9QHkW;4$ zIAGFO1syQyt62}2omcZ8$FyZVA>`nz(+M!~t6v!~`=`1)VD?X)SAaRWyq;cC9UfLH z@vHL-F#D(855SyUbv6O!a#E)nVAAFJw30fZkj{Sb99v2Kz)0t~s&!W^sg;OO=;GB0 z!G}=#hgTQaqYmukGaRLia|@y(lt?H{XKqCi5h%Y_(U{TDoOjQMfpq zt-I0Kx{j(cLNO0E$7wvaB6o!Gom?*qH}8zEUCWYI85w`Mm-KR$cfH{l0_wG#r%56k zS!7cqqa7yP$SUDH0L$V@Y^k)9W#K7ZNg2oYT*jIi)p7UGuH;T`Uu$M@+|z(pOp+(y zcVVs3tX*v;Os>Av+PbOb4)@M4>|Q4ke4^Ia*qvRC9LzpA6VpLGkl;R43$dw{_F4}( zmKF9B-5{rQj$*sW_ChGz0ikR=guX4_1*17L0+J`ol3iKw`q%F!4|C8(g?}Q z)PG+r>vt1`nqJoLCV-X2m9sDEJpNhbr>-i`xm0-!w94b3RUZGW^7vxJk=0fHOEQ~CQ&uPVcMl0r<0wvz| ziusIJ%xAn}KI0YhZGw_I;J}K>(s=?j=CfWgp972eQcy{c)1!RGO37OJ+*i!!zGA*% zP~xqzm~S7Hc-t)I%SR>NCX4y(SIjpMN_q?zbSU!lJON;e1iX!KML#GjBbiIaYJBr$ ztdT{|Ws!CkxspY88JT##0qfSf(;pgPD_6uIpgR3vEx^t#C@SP9u z2)MWJU6}`WwqGxK!ktoGZ*6bmpwUb2+lj_;?N(mWXF~9j_J<%2o$ApW_Z}G2CSSsp zS;i;sbaog$+}_?@QFk6w9%%1tS6)sYJ;;$f=o874kLU?TVco2I$o0Wbn1r{!~L~L_lN*7roYTB5%WXV^-frNV%NlO9nOIL>X_L+BKIpl9(6$dvK805y zt|{qB_d*2YN4B(-a6`?WU<)w}ldc8ss|?~((mDdNF;X=n@TjipSShbBr)oMNU3H&S z4FSN)SW;eJPN}1$)KOCEFe!DIlsZewYnCamS*E;Znev)t%4?P>uUV$NW|{JuWy)*L zsTvG;^Gk#hLS=ZV8VrDy5vJ7XQtFPW3N^eD#(t_$1I+rW^8;pmWw3yip`?62G3EP- zDRsh>*EdsM-%NRZGv$5!ly@*v-p5ask>kxV;#FG!ZF7dJ=Ng>vmMkm zQ|g*2byl3nqJ~@!`$$^wl4x}|vQbMfH(~VW9Q{Xwc`8>LiM{9XB%A;PjI8ROTXxfX`^Rf#$ ziG`fRLQY~KC$ZpF%SkNcBo=ZKXj%SqI75;aFcH77l(S1j?3 zz)~jh`6ghAZvvJwNzPZ0N_+*W#8;3?d`+mt*MmxYHK@c_gGziQsKi%-N_r9)$M^Jt zm^({|)t?^}1%T7rIPJ$Ay--B}8fBgXMKT9sAJ7|QtmD&(eQdFhE%sXwYYWIx)p|_T z+XRlOR&2@#B~m^pk@7)_ln+Xzd{81)l@hNMsBfRFin2q2~PozmJ)X?>@B2{+|M{FE2*Q(nYRc@aP5 zMf{W(@l#&JPk9kPrFS7!?+%s~`>oy`z-k4j>fHgXDsHOY9l#tnRrS$+!c?hKdKFTd zODWBzlqz(}mvd9~?tmkczM3q6NuLi?q-wH&j;h$HniAmH95=p-IQL5lwOLI-ieeC+oXKhCgsC6DIc~;`LIo@H{&2NxbFCJbgGOA zZ&+!1tm_fZ8k#iJBw}h1v0XR{o>VMFynK#>xTRw8b<)DVG$`hj(9^UoPt-$5F~bkaj>trAYIeBlx)` zfwo;RCf838k>6dC-%kSI+;-kQg{Je&_26D1|M!?2TZN%(G1v?%)&zgEtCjQi;-QU<+Fa%- zhqmLcqH24Sylj$}t>n}yIkieot&&r#k*#I9Pv;l^Rh`!ILQeo zIpHKHoaEzM&8t=OYSp}2?=me^#Js)LyuH=D4b>d)T=rc6V+Lc6W0vM+)4VxpPA$zz z)bf_q@|M-|vb7vT&8wETtd>)&GfC*R!^xWtEFPv~p$KFKeM{jxqo^OiTz0Tff8A|Q!J_Gtr}v`;0_s(pHaBp&jV z14(eFbs)*zHu7N^Yu8EU%Pe`YjJF5N3iedwvEBf5rHUK9==?!zytho9fqe^EmG{J#F{PR{9zPU4jp#l(mE z=0j8zKfkYkqO5rNqOtgJUw=e*@$yB1@!>xDqRROBee^}C@$>uEgQz!NzUVkU+&7-0 z?Rfdh`||M)2zNkwcebJeG zxNp2gd-C)9`X_pnpWip$qEUJIqE`8EUwcKt^72K?^5H&yA^Mh|-#31ud3pJwe)(`8 zK2gN{{62i5lKJ_4^C8NamoFNc2aB5K!+rHdVe|4uYxCj0`4Roi&+nTb(d7L6zWEWI z&dZ;3ik%NT?aqTm#q;4l{wT_xpWoMBQTzP-zWEmg(90Js(1-i*i9YD(_w`>iLqET- z|Dq#$`JyQLu+tVjSX4$I?pq(CJo@>4?NLo5-;bh8dgWEy@bdfctH$Bw_pKk*I=uY8 z@m0;k^8bw935BlRo34tnX=eq1tj`;(-1 z`;szM)kB}@tA5h`?aDM)uT-YK`bpFc{iOSGiCGK%&M$R;9~bWLW2W5t74Pq3rsjI3 zGF{hCy1!kS*6WqZR9`>o{yt_(uwP16=Dt2=>abtx{yt`kv0v)`K4vPiloG#RoE`V! z*Wj2w|CnEiV}3P`vy-BH>^ZI$r+Pm_kKOE$!OzLh>IAgJSZ3B7%Dj+Sf_e}zn3)-l zA`IUr@OCS><&Hl!o7D6n0nGox+BTriSB_%mo9y1 z5rvQ6U7YS-yojVTOUI|X^DZ{Ov^2e^rO~2yB8kv+x9IYVuH>s17pE~AcN^2)iHnQN zNSStd6E0SDvFh^i<)x*i;~1^(RK3|PTw3fF&bz`V03Sc!eXEPT^?c*=hYC$s;`76W zm8GTC#!`3S(&6r@F(l)5&yq=+OrHG+Mv7*d3jTx??jDW&l-|PjyFR zxG@sbt9zp>(X`8S-94_&cYnL%%Sp34{P+oE)~D}I-vzC`;_#ywp=TGDFCK4PT3Vc0 zIGl(Pj$y< zr(J6UbZe-vf+A?|ndK!{WI2}BPR!mL4+`}pdi+Fh;Y`l%Ur1AmW#A;5P)FC7r<1!g z4L7MW*oEV6Lb}t((a5ZonA({}tR&1ERPR25TBzLXnqMh!>whMC#Y`0rB$%S(GbffF z$09yByEizPbXObksqUd!bYXhBd$9g~*E2*gL)}9Tx&-Ku%-3NcIwXTKjWKAV;oZaa z<>|Z2)7`@uwo~0Bv*#}_?hUQROOJF-Yv%T;?$O!v&n}*SP7{xxK>AThKQ_BpI8wi| zxOe18y*to|x`$7?Er+EQ?HzP~4&hIC;6cpAfk!Vc?zw%4;fn5JhC%kw<0ocNEsJA4 zxO`UyJK5zfp(kh2{) z-!!{7;KGM6@Gg9KcJF`--#oiFn6 z9rgQn0{xptyWWoexo`&kbKxWCp9>#F|6KSO`sc!TpnooWC;I2YFGl}d_&ECK!qc(UDk z{sQD{p%6bgGrw0Jc)<0wit#`PUboINc1>gcRCjLn^qZbI)t&!86~zi~qWA))sPN#U z)2FA;I^KYxJ$Lu+*_pH8MT?MtV80Me^8*799K#5|8%*rM?we3-2z>QXDYiFNh`N*Y zldZd_XQrp0xC@-`*wBqZIU^lSzba&Y?mov{UzA`jDJbnC?p~r^byc9W>I|1$u z`e?ySy4)SXZ13N<*jfW8RXh#Vmse-H!;r4vdPDWbam1IGz$p6bG|)5%f|;~2e|!cM zQuGsnPyxQzA%ccD-aLX$jL8_rf`cgOYY8wmoY-=WIDo%osW~kymM5~Ym_`eRALCfe zJb__)Z!fDm0Uk0voz9$fMBOYtndM1mbfmk5%ZsO{pMYd{tsm4xAni>>cjQq(=aAJ? zVssMkUwO+joGpleQ{DGv)MWHIUCU0>>F;tj#b>}jPPAm8> zG3?vgzT8X4FYe2Y_T^@EeSG~j>a*QTm7=~|L>Oc+1FcO|1Yc9jkn`t zPt438KjE#H6H9F8Suo&tpUg((DM0TzdBV+^8yEJbHw5P}1P|!8hnj*Ne)M#=ie3Kx zH%LDZbOXnZcIQy$>DlfAf)BV+OfcNjDWq{WTF=b71>OAshWWzmy+R>HI!^0%0Ah{_c4J4-^VrTihn|*uJ~7==97x=D>dp0d{U#Xz*nK{`+E33C6M6z zYK^+$U!zf1{L`rUKE?O78g&KkYSb0@%Cu8pk> zesClmd-sSPdSrBbf?3}<@`;ffBdx-Rhn^WZGgKWsIV@R+qT1x!&%E`_o6kJ->I1JH zel>V?>ecZxh4I29>OG9i!kPR2cbQ)(9DwxSdt~6#&%(g?^rC}T new Promise(resolve => setTimeout(resolve, ms)); + +async function saveDebug(data) { + try { + await new Promise(resolve => chrome.storage.local.set({ geminiDebugLast: { ...data, at: new Date().toISOString() } }, resolve)); + } catch {} +} + +function normMarker(v) { + return String(v || '') + .trim() + .replace(/^"+|"+$/g, '') + .replace(/[\s_]+/g, '') + .toUpperCase(); +} + +function isVisible(el) { + if (!el) return false; + const style = window.getComputedStyle(el); + if (style.display === 'none' || style.visibility === 'hidden' || style.opacity === '0') return false; + const rect = el.getBoundingClientRect(); + return rect.width > 0 && rect.height > 0; +} + +async function waitForSelectorAny(selectors, timeoutMs) { + const start = Date.now(); + while (Date.now() - start < timeoutMs) { + for (const sel of selectors) { + const el = document.querySelector(sel); + if (isVisible(el)) return el; + } + await sleep(250); + } + return null; +} + +async function waitForInputEl(timeoutMs) { + const start = Date.now(); + while (Date.now() - start < timeoutMs) { + const els = [ + ...document.querySelectorAll('textarea'), + ...document.querySelectorAll('div[contenteditable="true"]'), + ].filter(isVisible); + const best = els.find(e => (e.getAttribute('aria-label') || '').toLowerCase().includes('prompt')) + || els.find(e => (e.getAttribute('aria-label') || '').toLowerCase().includes('message')) + || els[0]; + if (best) return best; + await sleep(250); + } + return null; +} + +function setInputText(el, text) { + el.focus(); + if (el.tagName === 'TEXTAREA' || el.tagName === 'INPUT') { + const proto = el.tagName === 'TEXTAREA' + ? HTMLTextAreaElement.prototype + : HTMLInputElement.prototype; + const desc = Object.getOwnPropertyDescriptor(proto, 'value'); + if (desc && desc.set) desc.set.call(el, text); + else el.value = text; + try { + el.dispatchEvent(new InputEvent('beforeinput', { bubbles: true, cancelable: true, inputType: 'insertFromPaste', data: text })); + } catch {} + try { + el.dispatchEvent(new InputEvent('input', { bubbles: true, inputType: 'insertFromPaste', data: text })); + } catch { + el.dispatchEvent(new Event('input', { bubbles: true })); + } + el.dispatchEvent(new Event('change', { bubbles: true })); + return; + } + const editable = el.getAttribute('contenteditable') === 'true'; + if (editable) { + el.focus(); + const sel = window.getSelection && window.getSelection(); + if (sel) { + const range = document.createRange(); + range.selectNodeContents(el); + sel.removeAllRanges(); + sel.addRange(range); + } + try { + document.execCommand('insertText', false, text); + } catch { + el.textContent = text; + } + } else { + el.textContent = text; + } + try { + el.dispatchEvent(new InputEvent('input', { bubbles: true, inputType: 'insertFromPaste', data: text })); + } catch { + el.dispatchEvent(new Event('input', { bubbles: true })); + } +} + +function findSendButton() { + const selectors = [ + 'button[type="submit"]', + 'button[aria-label="Send message"]', + 'button[aria-label="Send"]', + 'button[aria-label*="Send"]', + 'button[aria-label*="send"]', + 'button[aria-label*="Submit"]', + 'button[aria-label*="submit"]', + 'button[data-testid*="send"]', + 'button.send-button', + 'button.submit', + ]; + for (const sel of selectors) { + const btns = [...document.querySelectorAll(sel)]; + for (const btn of btns) { + if (isVisible(btn)) return btn; + } + } + const btns = [...document.querySelectorAll('button')].filter(isVisible); + const labeled = btns.filter(b => { + const label = `${b.getAttribute('aria-label') || ''} ${b.getAttribute('title') || ''} ${b.textContent || ''}`.toLowerCase(); + return label.includes('send message') || label === 'send' || label.includes(' send ') || label.includes('submit'); + }); + if (labeled.length) return labeled[labeled.length - 1]; + return null; +} + +function triggerEnter(el) { + const down = new KeyboardEvent('keydown', { bubbles: true, cancelable: true, key: 'Enter', code: 'Enter' }); + const up = new KeyboardEvent('keyup', { bubbles: true, cancelable: true, key: 'Enter', code: 'Enter' }); + el.dispatchEvent(down); + el.dispatchEvent(up); +} + +function isAriaDisabled(el) { + const v = (el?.getAttribute('aria-disabled') || '').toLowerCase(); + return v === 'true'; +} + +function clickLikeAUser(el) { + if (!el) return; + const r = el.getBoundingClientRect ? el.getBoundingClientRect() : null; + const clientX = r ? Math.round(r.left + r.width / 2) : 1; + const clientY = r ? Math.round(r.top + r.height / 2) : 1; + try { el.dispatchEvent(new PointerEvent('pointerdown', { bubbles: true, clientX, clientY, pointerType: 'mouse', isPrimary: true })); } catch {} + try { el.dispatchEvent(new MouseEvent('mousedown', { bubbles: true, clientX, clientY })); } catch {} + try { el.dispatchEvent(new PointerEvent('pointerup', { bubbles: true, clientX, clientY, pointerType: 'mouse', isPrimary: true })); } catch {} + try { el.dispatchEvent(new MouseEvent('mouseup', { bubbles: true, clientX, clientY })); } catch {} + try { el.dispatchEvent(new MouseEvent('click', { bubbles: true, clientX, clientY })); } catch {} + try { el.click(); } catch {} +} + +function findSendButtonNear(inputEl) { + const containers = []; + const form = inputEl?.closest && inputEl.closest('form'); + if (form) containers.push(form); + let p = inputEl; + for (let i = 0; i < 6 && p; i++) { + if (p.parentElement) containers.push(p.parentElement); + p = p.parentElement; + } + + const selectors = [ + 'button[aria-label="Send message"]', + 'button.send-button', + 'button.submit', + 'button[type="submit"]', + ]; + + for (const c of containers) { + for (const sel of selectors) { + const btns = [...c.querySelectorAll(sel)].filter(isVisible); + if (btns.length) return btns[btns.length - 1]; + } + } + return findSendButton(); +} + +async function waitForSendEnabled(inputEl, timeoutMs) { + const start = Date.now(); + while (Date.now() - start < timeoutMs) { + const btn = findSendButtonNear(inputEl); + if (btn && isVisible(btn) && !btn.disabled && !isAriaDisabled(btn)) return btn; + await sleep(250); + } + return findSendButtonNear(inputEl); +} + +async function sendMessageNow(inputEl) { + for (let i = 0; i < 3; i++) { + const sendBtn = await waitForSendEnabled(inputEl, 4000); + await saveDebug({ + attempt: i + 1, + hasSendBtn: !!sendBtn, + sendBtnDisabled: !!sendBtn?.disabled, + sendBtnAriaDisabled: (sendBtn?.getAttribute && sendBtn.getAttribute('aria-disabled')) || null, + sendBtnLabel: (sendBtn?.getAttribute && sendBtn.getAttribute('aria-label')) || null, + }); + if (sendBtn && !sendBtn.disabled && !isAriaDisabled(sendBtn)) { + try { sendBtn.scrollIntoView({ block: 'center', inline: 'center' }); } catch {} + clickLikeAUser(sendBtn); + await sleep(600); + if (isGenerating()) return true; + const form = sendBtn.closest && sendBtn.closest('form'); + if (form && form.requestSubmit) { + try { form.requestSubmit(); } catch {} + await sleep(600); + if (isGenerating()) return true; + } + } + triggerEnter(inputEl); + await sleep(600); + if (isGenerating()) return true; + try { + inputEl.dispatchEvent(new Event('input', { bubbles: true })); + } catch {} + await sleep(250); + } + return false; +} + +function isGenerating() { + const stopBtn = document.querySelector('button[aria-label*="Stop"], button[aria-label*="stop"]'); + if (isVisible(stopBtn)) return true; + const progress = document.querySelector('[role="progressbar"]'); + if (isVisible(progress)) return true; + return false; +} + +function extractJsonObjects(text, maxObjects = 20) { + if (!text) return []; + const s = String(text); + const out = []; + let i = 0; + while (i < s.length && out.length < maxObjects) { + const start = s.indexOf('{', i); + if (start === -1) break; + let depth = 0; + let inStr = false; + let esc = false; + for (let j = start; j < s.length; j++) { + const ch = s[j]; + if (inStr) { + if (esc) esc = false; + else if (ch === '\\\\') esc = true; + else if (ch === '"') inStr = false; + continue; + } + if (ch === '"') { inStr = true; continue; } + if (ch === '{') depth++; + else if (ch === '}') { + depth--; + if (depth === 0) { + out.push(s.slice(start, j + 1)); + i = j + 1; + break; + } + } + if (j === s.length - 1) i = s.length; + } + if (i === start) i = start + 1; + } + return out; +} + +function chooseBestJsonFromText(text, marker) { + const markerNorm = normMarker(marker); + const candidates = extractJsonObjects(text, 25); + const expectedKeys = [ + 'summary', + 'store_description', + 'features', + 'sound_profile', + 'highlight_tracks', + 'production', + 'market_insight', + 'sales_angles', + 'embedding', + ]; + + let best = null; + let bestScore = -Infinity; + for (const cand of candidates) { + let parsed; + try { parsed = JSON.parse(cand); } catch { continue; } + if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) continue; + + let score = 0; + const eomNorm = normMarker(parsed.eom); + if (markerNorm && eomNorm === markerNorm) score += 200; + + for (const k of expectedKeys) if (Object.prototype.hasOwnProperty.call(parsed, k)) score += 10; + + const placeholderSummary = 'Short factual description (1-2 sentences)'; + const placeholderStore = 'Punchy, slightly opinionated record store blurb (max 80 words, human tone, not generic AI)'; + if (parsed.summary === placeholderSummary) score -= 50; + if (parsed.store_description === placeholderStore) score -= 50; + + if (parsed.embedding && typeof parsed.embedding === 'object') score += 5; + if (parsed.embedding?.description && typeof parsed.embedding.description === 'string') score += 5; + if (parsed.embedding?.vibe && typeof parsed.embedding.vibe === 'string') score += 5; + if (parsed.embedding?.sales && typeof parsed.embedding.sales === 'string') score += 5; + + if (cand.length > 2000) score += 5; + + if (score > bestScore) { + bestScore = score; + best = parsed; + } + } + return best; +} + +function extractLastResponseText() { + const selectors = [ + 'main div[class*="markdown"]', + 'main div[class*="response"]', + 'main div[class*="model"]', + 'main [role="article"]', + 'main article', + ]; + const seen = new Set(); + const nodes = []; + for (const sel of selectors) { + for (const el of document.querySelectorAll(sel)) { + if (!isVisible(el)) continue; + const txt = (el.innerText || '').trim(); + if (txt.length < 40) continue; + if (seen.has(txt)) continue; + seen.add(txt); + nodes.push({ el, txt }); + } + } + if (!nodes.length) { + const main = document.querySelector('main'); + const txt = (main?.innerText || '').trim(); + return txt.length ? txt : null; + } + const scored = nodes.map(n => { + const t = n.txt; + let s = t.length / 1000; + if (t.includes('__PLICE_EOM__')) s += 50; + if (t.trimStart().startsWith('{')) s += 10; + if (t.includes('You said')) s -= 20; + if (t.includes('INPUT JSON:')) s -= 10; + if (t.includes('OUTPUT SCHEMA:')) s -= 10; + if (t.includes('Gemini is AI and can make mistakes')) s -= 5; + return { ...n, score: s }; + }).sort((a, b) => b.score - a.score); + return scored[0].txt; +} + +async function waitForStableResponse(timeoutMs) { + const start = Date.now(); + let last = null; + let stable = 0; + while (Date.now() - start < timeoutMs) { + const txt = extractLastResponseText(); + const gen = isGenerating(); + if (txt && txt === last) stable += 1; + else stable = 0; + last = txt; + if (txt && txt.includes('__PLICE_EOM__') && !gen && stable >= 2) return txt; + if (txt && !gen && stable >= 6) return txt; + await sleep(500); + } + return extractLastResponseText(); +} + +function parseJsonMaybe(text) { + if (!text) return null; + const trimmed = text.trim(); + const start = trimmed.indexOf('{'); + const end = trimmed.lastIndexOf('}'); + if (start === -1 || end === -1 || end <= start) return null; + const candidate = trimmed.slice(start, end + 1); + try { return JSON.parse(candidate); } catch { return null; } +} + +function findJsonWithMarker(text, marker) { + if (!text || !marker) return null; + const i = text.indexOf(marker); + if (i === -1) return null; + const before = text.lastIndexOf('{', i); + const after = text.indexOf('}', i); + if (before === -1 || after === -1 || after <= before) return null; + const candidate = text.slice(before, after + 1); + try { return JSON.parse(candidate); } catch { return null; } +} + +async function waitForJsonAndText(marker, timeoutMs) { + const start = Date.now(); + const want = normMarker(marker); + while (Date.now() - start < timeoutMs) { + const txt = extractLastResponseText() || ''; + if (txt) { + const parsed = chooseBestJsonFromText(txt, marker); + if (parsed) { + const got = normMarker(parsed?.eom); + if (!want || got === want) return { text: txt, json: parsed }; + } + if (marker && txt.includes(marker) && !isGenerating()) return { text: txt, json: parsed || chooseBestJsonFromText(txt, marker) || parseJsonMaybe(txt) }; + } + await sleep(500); + } + const finalTxt = extractLastResponseText(); + return { text: finalTxt, json: chooseBestJsonFromText(finalTxt, marker) || parseJsonMaybe(finalTxt) }; +} + +async function sendToBackground(message) { + return await new Promise(resolve => { + try { + chrome.runtime.sendMessage(message, (resp) => { + const err = chrome.runtime?.lastError?.message; + if (err) resolve({ ok: false, error: err }); + else resolve(resp || { ok: false, error: 'No response' }); + }); + } catch (e) { + resolve({ ok: false, error: e.message || 'sendMessage failed' }); + } + }); +} + +async function run() { + const job = await new Promise(resolve => chrome.storage.local.get(['geminiJob'], r => resolve(r.geminiJob || null))); + if (!job || !job.prompt || (job.status !== 'pending' && job.status !== 'running')) return; + + // If the job is older than 15 minutes and still pending/running, it's stale — abandon it + // so it doesn't re-inject text into Gemini on every page load. + const jobAge = job.created_at ? (Date.now() - new Date(job.created_at).getTime()) : Infinity; + if (jobAge > 15 * 60 * 1000) { + await new Promise(resolve => chrome.storage.local.set({ + geminiJob: { ...job, status: 'error', error: 'Job abandoned (stale — older than 15 minutes)', failed_at: new Date().toISOString() } + }, resolve)); + return; + } + + if (job.status === 'pending') { + await new Promise(resolve => chrome.storage.local.set({ geminiJob: { ...job, status: 'running', started_at: new Date().toISOString() } }, resolve)); + } + + const inputEl = await waitForInputEl(45000); + if (!inputEl) { + await new Promise(resolve => chrome.storage.local.set({ geminiJob: { ...job, status: 'error', error: 'Gemini input box not found.', failed_at: new Date().toISOString() } }, resolve)); + return; + } + + setInputText(inputEl, job.prompt); + await sleep(500); + const sent = await sendMessageNow(inputEl); + if (!sent) { + await new Promise(resolve => chrome.storage.local.set({ geminiJob: { ...job, status: 'error', error: 'Failed to trigger Gemini send.', failed_at: new Date().toISOString() } }, resolve)); + return; + } + + const marker = '__PLICE_EOM__'; + const { text: responseText, json: parsedFromWait } = await waitForJsonAndText(marker, 300000); + if (!responseText) { + await new Promise(resolve => chrome.storage.local.set({ geminiJob: { ...job, status: 'error', error: 'No Gemini response detected.', failed_at: new Date().toISOString() } }, resolve)); + return; + } + + let outputJson = parsedFromWait || parseJsonMaybe(responseText); + if (!outputJson) outputJson = findJsonWithMarker(responseText, marker); + + await saveDebug({ + stage: 'captured', + response_chars: responseText.length, + has_json: !!outputJson, + has_marker_text: responseText.includes(marker), + eom_value: outputJson ? outputJson.eom : null, + }); + + const result = { + job_id: job.job_id, + model: job.model || 'gemini-web', + release_id: job.release_id || null, + discogs_url: job.discogs_url || null, + gemini_url: location.href, + created_at: job.created_at, + prompt: job.prompt, + input_json: job.input_json || null, + output_text: responseText, + output_json: outputJson, + }; + + try { + await navigator.clipboard.writeText(job.prompt + '\n\n' + responseText); + } catch {} + + await new Promise(resolve => chrome.storage.local.set({ geminiJob: { ...job, status: 'posting', posting_at: new Date().toISOString() } }, resolve)); + const postResp = await sendToBackground({ action: 'postGeminiResult', result }); + await saveDebug({ stage: 'posted', postResp }); + + if (!postResp || !postResp.ok) { + const err = postResp?.error || 'Post failed.'; + await new Promise(resolve => chrome.storage.local.set({ geminiJob: { ...job, status: 'error', error: err, failed_at: new Date().toISOString() }, geminiLastExchange: result }, resolve)); + return; + } + + await new Promise(resolve => chrome.storage.local.set({ geminiJob: { ...job, status: 'done', done_at: new Date().toISOString() }, geminiLastExchange: result }, resolve)); + + const closeOnSuccess = await new Promise(resolve => + chrome.storage.local.get(['geminiCloseTabOnSuccess'], r => resolve(r.geminiCloseTabOnSuccess !== false)) + ); + if (closeOnSuccess) { + await sendToBackground({ action: 'closeSenderTab' }); + } +} + +if (document.readyState === 'complete' || document.readyState === 'interactive') { + run(); +} else { + window.addEventListener('DOMContentLoaded', () => run(), { once: true }); +} diff --git a/label.css b/label.css new file mode 100644 index 0000000..cb3775d --- /dev/null +++ b/label.css @@ -0,0 +1,92 @@ +.label-field { + position: absolute; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + box-sizing: border-box; +} + +.print-logo img, +.print-logo-large img { + width: 100%; + height: 100%; + object-fit: contain; + image-rendering: -webkit-optimize-contrast; +} + +.print-barcode img, +.print-barcode-large img { + width: 100%; + height: 100%; + object-fit: contain; +} + +.print-title, +.print-genre, +.print-style, +.print-description, +.print-bottom-info, +.print-title-large, +.print-genre-large, +.print-style-large, +.print-description-large, +.print-bottom-info-large { + display: flex; + align-items: flex-end; +} + +/* Buffer genre/style away from the QR code on the right */ +.print-genre, .print-genre-large, +.print-style, .print-style-large { + padding-right: 1.5mm; + box-sizing: border-box; +} + +/* Bottom info: pipe separators via CSS */ +.print-bottom-info .country::before, +.print-bottom-info .label::before, +.print-bottom-info-large .country::before, +.print-bottom-info-large .label::before { + content: ' | '; + white-space: pre; +} + +/* Bottom info: year is fixed-width when present */ +.print-bottom-info .year, +.print-bottom-info-large .year { + flex-shrink: 0; +} + +/* Bottom info: country and label auto-fit */ +.print-bottom-info .country, +.print-bottom-info-large .country { + flex-shrink: 0; +} + +.print-bottom-info .label, +.print-bottom-info-large .label { + flex: 1; + min-width: 0; +} + +/* When no year: hide year span and remove country's leading pipe */ +.print-bottom-info.no-year .year, +.print-bottom-info-large.no-year .year { + display: none; +} + +.print-bottom-info.no-year .country::before, +.print-bottom-info-large.no-year .country::before { + content: none; +} + +.print-price, +.print-condition, +.print-barcode, +.print-price-large, +.print-condition-large, +.print-barcode-large { + display: flex; + align-items: center; + justify-content: right; +} \ No newline at end of file diff --git a/large.css b/large.css new file mode 100644 index 0000000..d146665 --- /dev/null +++ b/large.css @@ -0,0 +1,1152 @@ +/* Large Label Preview */ +.label-preview-large { + font-family: "MS Gothic", "Hiragino Kaku Gothic Pro", Arial, sans-serif; + width: 54mm; + height: 24mm; + position: relative; + background: white; + overflow: hidden; + margin: 0; + padding: 0; + border: 0.1mm solid black; +} + +.print-label-large { + font-family: "MS Gothic", "Hiragino Kaku Gothic Pro", Arial, sans-serif; + width: 54mm !important; + height: 24mm; + position: absolute; + background: white; + overflow: hidden; + top: 3mm; + margin-left: 2mm !important; + padding: 0 !important; + border: 0; + display: block !important; + box-sizing: border-box !important; + transform: none !important; + float: none !important; + -webkit-print-color-adjust: exact; + print-color-adjust: exact; + +} + +/* Large Label Field Positions */ +.print-artist-large { + left: 0mm; + top: 0mm; + width: 40mm; + height: 4mm; + font-size: 8pt; +} + +.print-title-large { + left: 0mm; + top: 4mm; + width: 40mm; + height: 4mm; + font-size: 8pt; +} + +.print-genre-large { + left: 0mm; + top: 8mm; + width: 40mm; + height: 4mm; + font-size: 8pt; +} + +.print-style-large { + left: 0mm; + top: 12mm; + width: 40mm; + height: 4mm; + font-size: 9pt; + font-weight: bold; +} + +.print-description-large { + left: 0mm; + top: 16mm; + width: 40mm; + height: 3mm; + font-size: 6pt; +} + +.print-bottom-info-large { + left: 0mm; + top: 19mm; + width: 40mm; + height: 3mm; + gap: 0; + /* Remove gap between elements */ +} + +/* Add specific styles for the child elements */ +.print-bottom-info-large .year { + width: auto; + font-size: 7pt !important; + margin: 0; + padding: 0; +} + +.print-bottom-info-large .country { + width: auto; + min-width: 4mm; + line-height: 1; + margin: 0; + padding: 0; +} + +.print-bottom-info-large .label { + flex: 1; + text-align: left; + margin: 0; + padding: 0; +} + +.print-logo-large { + position: absolute; + left: 40mm; + top: 0mm; + width: 11mm; + height: 2.5mm; + display: block; +} + +.print-price-large { + position: absolute; + left: 40mm; + top: 2.5mm; + width: 11mm; + height: 5.5mm; + font-size: 13pt; + font-weight: bold; +} + +.print-condition-large { + position: absolute; + left: 40mm; + top: 8mm; + width: 11mm; + height: 2.5mm; + font-size: 6pt; + line-height: 1; +} + + +.print-barcode-large { + position: absolute; + left: 40mm; + top: 10.5mm; + width: 11mm; + height: 11mm; +} + +/* Comment and Notes — no room on large label by default; adjust positions to fit your redesign */ +.print-comment-large { + left: 0mm; + top: 22mm; + width: 40mm; + height: 2mm; + font-size: 5pt; + overflow: hidden; +} + +.print-notes-large { + left: 0mm; + top: 24mm; + width: 40mm; + height: 1.5mm; + font-size: 4.5pt; + overflow: hidden; +} + +/* Large Label Print Settings */ +@media print { + .print-label-large { + width: 54mm !important; + height: 24mm !important; + + } +} + +@page large-label { + size: 54mm 24mm; + margin: 0; + padding: 0; +} + +/* Tab Styles */ +.tab-container { + width: 100%; + margin-bottom: 10px; +} + +.tab-nav { + display: flex; + border-bottom: 2px solid #ddd; + background: #f5f5f5; +} + +.tab-button { + flex: 1; + padding: 12px 16px; + border: none; + background: #f5f5f5; + cursor: pointer; + font-size: 14px; + font-weight: 500; + color: #666; + border-bottom: 3px solid transparent; + transition: all 0.3s ease; +} + +.tab-button:hover { + background: #e9e9e9; + color: #333; +} + +.tab-button.active { + background: white; + color: #007cba; + border-bottom-color: #007cba; +} + +.tab-content { + display: none; + padding: 20px; + background: white; + min-height: 400px; +} + +.tab-content.active { + display: block; +} + +/* Layout Styles - Ultra Compact */ +.container { + display: flex; + gap: 4px; + max-width: 700px; + width: 100%; + padding: 2px; +} + +.left-column { + flex: 1; + min-width: 260px; +} + +.right-column-combined { + flex: 1; + min-width: 260px; +} + +/* Enhanced Button Styling */ +.primary-buttons { + display: flex; + flex-direction: column; + gap: 3px; + margin-bottom: 4px; +} + +.primary-buttons-large { + display: flex; + gap: 3px; +} + +.primary-buttons-small { + display: flex; + gap: 3px; +} + +.action-button-small { + padding: 2px 8px !important; + font-size: 10px !important; + flex: 1; +} + +.action-button { + background: linear-gradient(135deg, #2196F3, #1976D2); + color: white; + border: none; + padding: 6px 8px; + font-size: 11px; + font-weight: 600; + border-radius: 4px; + cursor: pointer; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); + transition: all 0.3s ease; + flex: 1; + min-width: 50px; + text-transform: uppercase; +} + +.action-button:hover { + background: linear-gradient(135deg, #1976D2, #1565C0); + transform: translateY(-1px); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3); +} + +/* Special styling for ALL button */ +.all-button { + background: linear-gradient(135deg, #4CAF50, #45a049); +} + +.all-button:hover { + background: linear-gradient(135deg, #45a049, #3d8b40); +} + +/* General Interface Styling - Ultra Compact */ +body { + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); + margin: 0; + padding: 0; + font-size: 12px; +} + +.input-group { + margin-bottom: 2px; + padding: 2px; + background: white; + border-radius: 4px; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} + +.input-group label { + font-weight: 600; + color: #333; + margin-bottom: 0px; + display: block; + font-size: 10px; +} + +.release-info { + background: white; + padding: 4px; + border-radius: 4px; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + margin-bottom: 4px; +} + +.release-info h3 { + color: #2c3e50; + margin-top: 0; + margin-bottom: 2px; + font-size: 11px; + border-bottom: 1px solid #3498db; + padding-bottom: 1px; + font-weight: 600; +} + +.info-field { + margin-bottom: 1px; + padding: 1px 3px; + background: #f8f9fa; + border-radius: 1px; + border-left: 1px solid #3498db; + font-size: 9px; + line-height: 1.1; +} + +.info-field strong { + color: #2c3e50; +} + +/* Price Options Styling - Ultra Snug Grid */ +.price-options { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(32px, 1fr)); + gap: 1px; + margin-top: 0px; +} + +.price-options label { + display: flex; + align-items: center; + justify-content: center; + padding: 1px; + background: #e3f2fd; + border-radius: 1px; + cursor: pointer; + transition: all 0.3s ease; + border: 1px solid transparent; + font-size: 9px; + font-weight: 600; + min-height: 18px; +} + +.price-options label:hover { + background: #bbdefb; + border-color: #2196F3; +} + +.price-options input[type="checkbox"]:checked+.price-label { + background: #2196F3; + color: white; +} + +/* Ultra compact input styling */ +input[type="text"], +input[type="number"], +select, +textarea { + font-size: 9px; + padding: 1px; + border-radius: 2px; + border: 1px solid #ddd; + margin-bottom: 1px; +} + +/* Price input field */ +input[type="text"] { + width: 100%; + margin-bottom: 1px; +} + +/* YouTube Cookie Textarea - Compact */ +#cookieOutput { + width: 100%; + height: 100px; + min-height: 100px; + padding: 6px; + border: 1px solid #ddd; + border-radius: 4px; + font-family: 'Courier New', monospace; + font-size: 10px; + background: #f8f9fa; + resize: vertical; + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); +} + +.youtube-cookie-container { + background: white; + padding: 8px; + border-radius: 6px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); +} + +.youtube-cookie-container h3 { + color: #2c3e50; + margin-top: 0; + margin-bottom: 8px; + font-size: 14px; + text-align: center; + border-bottom: 2px solid #e74c3c; + padding-bottom: 4px; +} + +.youtube-extract-btn { + background: linear-gradient(135deg, #e74c3c, #c0392b); + color: white; + border: none; + padding: 6px 12px; + font-size: 12px; + font-weight: 600; + border-radius: 4px; + cursor: pointer; + margin-bottom: 6px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); + transition: all 0.3s ease; + width: 100%; +} + +.youtube-extract-btn:hover { + background: linear-gradient(135deg, #c0392b, #a93226); + transform: translateY(-1px); + box-shadow: 0 3px 6px rgba(0, 0, 0, 0.3); +} + +/* Settings Styling - Ultra Compact */ +.settings-container { + background: white; + margin-bottom: 8px; + border-radius: 4px; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + overflow: hidden; +} + +.settings-container button { + width: 100%; + padding: 8px 10px; + background: linear-gradient(135deg, #9b59b6, #8e44ad); + color: white; + border: none; + font-size: 12px; + font-weight: 600; + cursor: pointer; + transition: all 0.3s ease; +} + +.settings-container button:hover { + background: linear-gradient(135deg, #8e44ad, #7d3c98); +} + +/* Toggle Switch Styling - Tiny */ +.switch { + position: relative; + display: inline-block; + width: 40px; + height: 22px; + margin-right: 6px; +} + +.switch input { + opacity: 0; + width: 0; + height: 0; +} + +.slider { + position: absolute; + cursor: pointer; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: #ccc; + transition: .4s; + border-radius: 22px; +} + +.slider:before { + position: absolute; + content: ""; + height: 16px; + width: 16px; + left: 3px; + bottom: 3px; + background-color: white; + transition: .4s; + border-radius: 50%; +} + +input:checked+.slider { + background-color: #2196F3; +} + +input:checked+.slider:before { + transform: translateX(18px); +} + +/* Ultra compact popup sizing */ +.tab-content { + max-height: 550px; + overflow-y: auto; + padding: 2px; +} + +/* Market info and other sections ultra compact */ +h3, +h4 { + margin: 4px 0; + font-size: 13px; +} + +p, +div { + margin: 2px 0; + line-height: 1.2; +} + +/* Remove extra spacing from specific elements */ +.primary-buttons, +.secondary-buttons { + margin: 0; +} + +/* Compact the label preview and other right column content */ +.right-column-combined>* { + margin-bottom: 4px; +} + +/* Make dropdowns more compact */ +select { + padding: 1px; + font-size: 9px; + margin-bottom: 1px; + height: 20px; +} + +/* Compact status messages */ +.status-message { + padding: 4px; + margin: 2px 0; + font-size: 11px; +} + +/* Mapping tab styles */ +.mapping-grid { + display: grid; + grid-template-columns: repeat(5, 1fr); + gap: 4px; + margin: 8px 0; +} + +.mapping-item { + display: flex; + flex-direction: column; + align-items: center; + padding: 4px; + border: 1px solid #ddd; + border-radius: 3px; + background: #f9f9f9; +} + +.mapping-item label { + font-size: 8px; + font-weight: bold; + margin-bottom: 2px; + text-align: center; + line-height: 1.1; +} + +.mapping-item .column-letter { + font-size: 10px; + color: #666; + margin-bottom: 2px; +} + +.mapping-item select { + width: 100%; + font-size: 8px; + padding: 1px; + height: 18px; + border: 1px solid #ccc; +} + +.mapping-actions { + display: flex; + gap: 8px; + margin-bottom: 8px; + justify-content: center; +} + +.mapping-actions button { + padding: 6px 12px; + margin-right: 8px; + background: #007cba; + color: white; + border: none; + border-radius: 3px; + cursor: pointer; + font-size: 12px; +} + +.mapping-actions button:hover { + background: #005a87; +} + +.sheet-info { + margin: 15px 0; + padding: 10px; + background: #f9f9f9; + border-radius: 4px; + border: 1px solid #ddd; +} + +.info-row { + display: flex; + align-items: center; + margin-bottom: 8px; +} + +.info-row:last-child { + margin-bottom: 0; +} + +.info-row label { + font-weight: bold; + min-width: 100px; + margin-right: 10px; +} + +.info-row span { + color: #666; + margin-right: 10px; +} + +.info-row input { + padding: 4px 8px; + border: 1px solid #ccc; + border-radius: 3px; + margin-right: 8px; + width: 80px; +} + +/* ================================================================ + PROMPT button in Discogs action row + ================================================================ */ +.rfid-quick-button { + background: linear-gradient(135deg, #ff6f00, #e65100); +} +.rfid-quick-button:hover { + background: linear-gradient(135deg, #e65100, #bf360c); +} + +/* Settings — compact check grid */ +.settings-section-label { + font-size: 11px; + font-weight: 700; + text-transform: uppercase; + letter-spacing: .5px; + color: #555; + margin-bottom: 8px; +} +.settings-check-grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 5px 8px; +} +.settings-check-item { + display: flex; + align-items: center; + gap: 6px; + font-size: 13px; + cursor: pointer; + white-space: nowrap; +} +.settings-check-item input[type="checkbox"] { + width: 15px; + height: 15px; + cursor: pointer; + flex-shrink: 0; +} + +/* Per-field label style grid */ +.lfs-grid { + margin-top: 8px; + display: grid; + grid-template-columns: 1fr; + gap: 2px; +} +.lfs-header, .lfs-row { + display: grid; + grid-template-columns: 1fr 18px 18px 18px; + align-items: center; + gap: 2px; +} +.lfs-header { + font-size: 10px; + font-weight: 700; + color: #888; + text-align: center; + padding-bottom: 2px; + border-bottom: 1px solid #e0e0e0; + margin-bottom: 2px; +} +.lfs-header span:first-child { text-align: left; } +.lfs-row span { + font-size: 11px; + color: #444; + white-space: nowrap; +} +.lfs-row input[type="checkbox"] { + width: 14px; + height: 14px; + cursor: pointer; + justify-self: center; +} + +/* ================================================================ + Research Tab + ================================================================ */ +.research-container { + padding: 6px 8px; +} + +.research-header h3 { + color: #1a1a2e; + font-size: 13px; + margin: 0 0 3px; + padding-bottom: 5px; + border-bottom: 2px solid #9b59b6; + letter-spacing: 0.3px; +} + +.research-desc { + color: #888; + font-size: 10px; + font-style: italic; + margin: 3px 0 8px; + line-height: 1.4; +} + +/* Release card */ +.research-release-card { + display: flex; + gap: 10px; + align-items: flex-start; + background: linear-gradient(135deg, #1a1a2e 0%, #16213e 60%, #0f3460 100%); + border-radius: 8px; + padding: 10px 12px; + margin-bottom: 8px; + box-shadow: 0 3px 12px rgba(0,0,0,0.3); +} + +.research-cover-wrap { + position: relative; + width: 58px; + height: 58px; + flex-shrink: 0; + border-radius: 5px; + overflow: hidden; + background: #0f3460; + box-shadow: 0 2px 8px rgba(0,0,0,0.5); +} + +.research-cover { + width: 100%; + height: 100%; + object-fit: cover; + display: block; +} + +.research-cover-placeholder { + position: absolute; + inset: 0; + display: flex; + align-items: center; + justify-content: center; + font-size: 22px; + color: rgba(155,89,182,0.6); + background: linear-gradient(135deg, #0f3460, #1a1a2e); +} + +.research-release-meta { + flex: 1; + min-width: 0; +} + +.research-artist { + font-size: 9px; + color: #c084fc; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.8px; + margin-bottom: 2px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.research-title { + font-size: 13px; + font-weight: 700; + color: #fff; + margin-bottom: 3px; + line-height: 1.2; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.research-meta-row { + font-size: 9px; + color: #94a3b8; + margin-bottom: 3px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.research-format-row { + color: #64748b; +} + +.research-sep { + margin: 0 3px; + color: #475569; +} + +.research-tags { + display: flex; + flex-wrap: wrap; + gap: 3px; + margin-top: 4px; +} + +.research-tag { + font-size: 8px; + padding: 1px 6px; + border-radius: 10px; + font-weight: 600; + letter-spacing: 0.2px; +} + +.research-tag-genre { + background: rgba(59,130,246,0.2); + border: 1px solid rgba(59,130,246,0.4); + color: #93c5fd; +} + +.research-tag-style { + background: rgba(155,89,182,0.2); + border: 1px solid rgba(155,89,182,0.4); + color: #c084fc; +} + +/* Market stats grid */ +.research-market { + display: grid; + grid-template-columns: repeat(5, 1fr); + gap: 4px; + margin-bottom: 8px; +} + +.research-stat { + background: #f8f9fa; + border: 1px solid #e2e8f0; + border-radius: 6px; + padding: 5px 3px 4px; + text-align: center; +} + +.rstat-label { + display: block; + font-size: 8px; + color: #94a3b8; + text-transform: uppercase; + letter-spacing: 0.4px; + margin-bottom: 2px; +} + +.rstat-value { + display: block; + font-size: 11px; + font-weight: 700; + color: #1e293b; + line-height: 1.1; +} + +.rstat-value.rstat-small { + font-size: 8px; + font-weight: 600; +} + +.rstat-value.rstat-accent { + color: #e74c3c; +} + +.rstat-value.rstat-median { + color: #059669; +} + +.rstat-sub { + display: block; + font-size: 7px; + color: #94a3b8; + margin-top: 1px; +} + +/* Tracklist preview */ +.research-tracklist-wrap { + margin-bottom: 8px; + background: #f8f9fa; + border-radius: 6px; + border: 1px solid #e2e8f0; + overflow: hidden; +} + +.research-section-label { + font-size: 9px; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.5px; + color: #64748b; + padding: 4px 8px; + background: #e2e8f0; +} + +.research-tracklist { + padding: 4px 6px; +} + +.research-track { + display: flex; + align-items: baseline; + gap: 6px; + padding: 2px 0; + border-bottom: 1px solid #f1f5f9; + font-size: 9px; + line-height: 1.3; +} + +.research-track:last-child { + border-bottom: none; +} + +.research-track-pos { + color: #9b59b6; + font-weight: 700; + min-width: 14px; + flex-shrink: 0; + font-size: 8px; +} + +.research-track-title { + flex: 1; + color: #1e293b; + font-weight: 500; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.research-track-extra { + color: #94a3b8; + font-size: 8px; + flex-shrink: 0; + font-style: italic; + max-width: 90px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.research-track-dur { + color: #64748b; + font-size: 8px; + flex-shrink: 0; + font-variant-numeric: tabular-nums; +} + +/* Export action buttons */ +.research-actions { + display: flex; + gap: 6px; + margin-bottom: 6px; +} + +.research-btn { + flex: 1; + padding: 8px 6px; + border: none; + border-radius: 6px; + font-size: 11px; + font-weight: 700; + cursor: pointer; + transition: all 0.2s ease; + box-shadow: 0 2px 4px rgba(0,0,0,0.15); + letter-spacing: 0.2px; +} + +.research-btn:hover { + transform: translateY(-1px); + box-shadow: 0 4px 8px rgba(0,0,0,0.2); +} + +.research-btn:active { + transform: translateY(0); + box-shadow: 0 1px 2px rgba(0,0,0,0.15); +} + +.research-btn-icon { + margin-right: 3px; + font-style: normal; +} + +.research-btn-download { + background: linear-gradient(135deg, #9b59b6, #8e44ad); + color: white; +} + +.research-btn-download:hover { + background: linear-gradient(135deg, #8e44ad, #7d3c98); +} + +.research-btn-copy { + background: linear-gradient(135deg, #1e293b, #0f172a); + color: white; +} + +.research-btn-copy:hover { + background: linear-gradient(135deg, #0f172a, #020617); +} + +.research-btn-gemini { + background: linear-gradient(135deg, #10b981, #0ea5e9); + color: white; +} + +.research-btn-gemini:hover { + background: linear-gradient(135deg, #059669, #0284c7); +} + +.research-btn-drive { + background: linear-gradient(135deg, #4285F4, #1a73e8); + color: white; + flex: 0 0 auto; + padding: 8px 12px; +} + +.research-btn-drive:hover { + background: linear-gradient(135deg, #1a73e8, #1557b0); +} + +/* Status line */ +.research-status { + font-size: 10px; + min-height: 14px; + margin-bottom: 5px; + font-weight: 600; + padding: 0 2px; +} + +.research-status.ok { color: #059669; } +.research-status.err { color: #e74c3c; } +.research-status.inf { color: #9b59b6; } + +/* Collapsible JSON preview */ +.research-preview-toggle { + width: 100%; + background: #e2e8f0; + border: none; + border-radius: 6px; + padding: 5px 8px; + font-size: 9px; + font-weight: 700; + color: #475569; + cursor: pointer; + text-align: left; + text-transform: uppercase; + letter-spacing: 0.4px; + transition: background 0.2s; + margin-bottom: 3px; +} + +.research-preview-toggle:hover { + background: #cbd5e1; +} + +.research-preview { + font-size: 8px; + font-family: 'Courier New', 'SF Mono', monospace; + padding: 8px; + margin: 0 0 4px; + white-space: pre-wrap; + word-break: break-word; + max-height: 180px; + overflow-y: auto; + color: #1e293b; + background: #f8fafc; + border: 1px solid #e2e8f0; + border-radius: 6px; + line-height: 1.4; +} + +/* ================================================================ + End Research Tab + ================================================================ */ + +.info-row button { + padding: 4px 8px; + background: #666; + color: white; + border: none; + border-radius: 3px; + cursor: pointer; + font-size: 11px; +} diff --git a/logo.svg b/logo.svg new file mode 100644 index 0000000..e8a594d --- /dev/null +++ b/logo.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..7c656e6 --- /dev/null +++ b/manifest.json @@ -0,0 +1,106 @@ +{ + "manifest_version": 3, + "name": "PliceCogs X YT", + "version": "10.1", + "description": "Discogs pricing tool and YT cookie blagginate crossover", + "permissions": [ + "activeTab", + "alarms", + "cookies", + "downloads", + "scripting", + "storage", + "tabs" + ], + "host_permissions": [ + "*://*.priceclogs.com/*", + "*://*.youtube.com/*", + "*://*.discogs.com/*", + "*://*.beatport.com/*", + "*://gemini.google.com/*", + "*://chat.deepseek.com/*", + "*://localhost/*", + "*://*.localhost/*", + "http://100.91.239.7:5002/*" + ], + "externally_connectable": { + "matches": [ + "*://localhost/*", + "*://*.localhost/*", + "*://*.local/*", + "*://*.test/*", + "*://*.dev/*" + ] + }, + "action": { + "default_popup": "popup.html" + }, + "content_security_policy": { + "extension_pages": "script-src 'self'; object-src 'self'; img-src 'self' https://api.qrserver.com/;" + }, + "content_scripts": [ + { + "matches": [ + "*://*.discogs.com/*" + ], + "js": [ + "content.js" + ] + }, + { + "matches": [ + "*://www.discogs.com/master/*" + ], + "js": [ + "monster_master.js" + ], + "run_at": "document_idle" + }, + { + "matches": [ + "*://gemini.google.com/*" + ], + "js": [ + "gemini.js" + ], + "run_at": "document_idle" + }, + { + "matches": [ + "*://chat.deepseek.com/*" + ], + "js": [ + "deepseek.js" + ], + "run_at": "document_idle" + }, + { + "matches": [ + "*://localhost/*/wowplatter-admin-blagginate*", + "*://*.localhost/wp-admin/*" + ], + "js": [ + "blagginate-bridge.js" + ] + } + ], + "web_accessible_resources": [ + { + "resources": [ + "print.js", + "utils.js", + "small.css", + "large.css", + "xlarge.css", + "label.css", + "logo.svg" + ], + "matches": [ + "" + ] + } + ], + "background": { + "service_worker": "background.js" + } +} \ No newline at end of file diff --git a/monster_capture.js b/monster_capture.js new file mode 100644 index 0000000..c46b697 --- /dev/null +++ b/monster_capture.js @@ -0,0 +1,262 @@ +// Shared MONSTERWIKI capture helpers — pure functions, no DOM / popup deps. +// Loaded by popup.html ( + + + + + + + + + diff --git a/popup.js b/popup.js new file mode 100644 index 0000000..6bc068b --- /dev/null +++ b/popup.js @@ -0,0 +1,4930 @@ +// Create placeholder functions for missing API functions +async function getStoredDiscogsToken() { + return new Promise((resolve) => { + if (!chrome || !chrome.storage) { + resolve(null); + return; + } + chrome.storage.local.get('discogsToken', (data) => { + resolve((data.discogsToken || '').trim() || null); + }); + }); +} + +async function getReleaseData(releaseId) { + const token = await getStoredDiscogsToken(); + if (!token) return null; + const idMatch = String(releaseId || '').match(/\d+/); + const id = idMatch ? idMatch[0] : null; + if (!id) return null; + + // Retry up to 3 times — Discogs occasionally rate-limits or drops the first + // request on a freshly-loaded page, which would otherwise crash the popup. + for (let attempt = 0; attempt < 3; attempt++) { + try { + const response = await fetch(`https://api.discogs.com/releases/${id}`, { + headers: { + 'Authorization': `Discogs token=${token}`, + 'User-Agent': 'PriceClogs/1.0' + } + }); + if (response.status === 429) { + // Rate limited — back off and retry + await new Promise(r => setTimeout(r, 1500 * (attempt + 1))); + continue; + } + const data = await response.json(); + if (data && data.artists) return data; // success + // API returned an error envelope (e.g. { message: "..." }) — retry + if (attempt < 2) await new Promise(r => setTimeout(r, 1000)); + } catch (_) { + if (attempt < 2) await new Promise(r => setTimeout(r, 1000)); + } + } + return null; +} + +async function getPriceSuggestions(releaseId) { + try { + const token = await getStoredDiscogsToken(); + if (!token) { + throw new Error('Discogs token not configured'); + } + const idMatch = String(releaseId || '').match(/\d+/); + const id = idMatch ? idMatch[0] : null; + if (!id) { + throw new Error('Invalid release ID'); + } + const response = await fetch(`https://api.discogs.com/marketplace/price_suggestions/${id}`, { + headers: { + 'Authorization': `Discogs token=${token}`, + 'User-Agent': 'PriceClogs/1.0' + } + }); + return await response.json(); + } catch (error) { + // console.error('Error fetching price suggestions:', error); + return null; + } +} + +const state = { + releaseData: null, + originalReleaseData: null, + lastFetchTimestamp: 0, + sku: null, // 14-digit SKU generated at popup open (e.g. 20260313084637) + sheetTimestamp: null, // Full ISO timestamp matching the SKU, used for sheet column A + discogsTabId: null, // Tab ID of the Discogs page, captured at popup open + fetchCooldown: 1000, + collectionBoxIndex: 0, // currently selected collection box index + collectionBoxSkus: [], // SKUs for each box (empty string = no SKU) + collectionBoxCount: 1, // total number of collection boxes on page + // MONSTERWIKI background sync results (populated silently at popup open) + monsterSalesHistory: null, + monsterCurrentListings: null, + geminiAutoTriggered: false, +}; + +// ================================================================ +// MONSTERWIKI — background sync helpers +// ================================================================ + +// parseSalesHistoryHtml + parseListingsHtml moved to monster_capture.js +// (loaded before popup.js in popup.html) so background.js can share them. + +async function getMonsterSettings() { + return new Promise(resolve => + chrome.storage.local.get(['monsterSettings'], r => + resolve(r.monsterSettings || { enabled: false, preferLocalhost: false, serverUrl: 'http://100.91.239.7:5002' }) + ) + ); +} + +function monsterSetIndicator(msg, color, fadeAfterMs = 0) { + const el = document.getElementById('monster-sync-indicator'); + if (!el) return; + el.textContent = msg; + el.style.color = color; + el.style.opacity = '1'; + el.style.display = 'block'; + if (fadeAfterMs) { + setTimeout(() => { + el.style.transition = 'opacity 1.5s'; + el.style.opacity = '0'; + setTimeout(() => { el.style.display = 'none'; }, 1600); + }, fadeAfterMs); + } +} + +function geminiSetIndicator(msg, color, fadeAfterMs = 0) { + const el = document.getElementById('gemini-sync-indicator'); + if (!el) return; + el.textContent = msg; + el.style.color = color; + el.style.opacity = '1'; + el.style.display = 'block'; + if (fadeAfterMs) { + setTimeout(() => { + el.style.transition = 'opacity 1.5s'; + el.style.opacity = '0'; + setTimeout(() => { el.style.display = 'none'; }, 1600); + }, fadeAfterMs); + } +} + +async function monsterResolveBase(cfg) { + // If we're ON ultra, localhost:5002 will answer immediately — use it directly. + // Otherwise fall back to the configured Tailscale URL. + try { + const r = await fetch('http://localhost:5002/plice/health', + { signal: AbortSignal.timeout(400) }); + if (r.ok) return 'http://localhost:5002'; + } catch (_) {} + return (cfg.serverUrl || 'http://100.91.239.7:5002').replace(/\/$/, ''); +} + +async function monsterBackgroundSync(releaseId) { + const cfg = await getMonsterSettings(); + if (!cfg.enabled || !releaseId) return; + + const base = await monsterResolveBase(cfg); + monsterSetIndicator('⟳ MONSTER syncing…', '#888'); + + const [histHtml, listHtml] = await Promise.all([ + fetch(`https://www.discogs.com/sell/history/${releaseId}`) + .then(r => r.ok ? r.text() : null).catch(() => null), + fetch(`https://www.discogs.com/sell/list?release_id=${releaseId}`) + .then(r => r.ok ? r.text() : null).catch(() => null), + ]); + + state.monsterSalesHistory = histHtml ? parseSalesHistoryHtml(histHtml) : null; + state.monsterCurrentListings = listHtml ? parseListingsHtml(listHtml) : null; + + if (!state.releaseData) return; + + // Scroll to bottom of page so reviews lazy-load, wait 2s, then scrape + let liveReviews = state.releaseData.reviews || []; + if (state.discogsTabId) { + try { + const results = await chrome.scripting.executeScript({ + target: { tabId: state.discogsTabId }, + func: async () => { + window.scrollTo(0, document.body.scrollHeight); + await new Promise(r => setTimeout(r, 2000)); + const reviews = []; + document.querySelectorAll('#release-reviews [data-username], #release-reviews [class*="review_card"]') + .forEach(card => { + const username = card.getAttribute('data-username') + || card.querySelector('[class*="username"]')?.textContent?.trim() || null; + const dateEl = card.querySelector('time'); + const date = dateEl?.getAttribute('datetime')?.split('T')[0] + || dateEl?.textContent?.trim() || null; + const text = card.querySelector('[class*="review_body"], [class*="reviewBody"]') + ?.textContent?.trim() || null; + const rating = card.querySelectorAll('[class*="star_full"],[class*="starFull"],[class*="filled"]').length || null; + const helpful = parseInt(card.querySelector('[class*="helpful"]')?.textContent?.match(/\d+/)?.[0]) || 0; + if (username && (text || rating)) + reviews.push({ username, date, rating: rating||null, text, helpful, replies: [] }); + }); + return reviews; + } + }); + if (results?.[0]?.result?.length) liveReviews = results[0].result; + } catch (_) {} + } + + // Merge live DOM reviews into releaseData for the POST + const postData = { ...state.releaseData, reviews: liveReviews }; + + try { + const resp = await fetch(`${base}/plice`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + ...buildResearchJson(postData), + sales_history: state.monsterSalesHistory, + current_listings: state.monsterCurrentListings, + }), + signal: AbortSignal.timeout(12000), + }); + if (resp.ok) { + const d = await resp.json(); + const sales = d.sale_rows || 0; + const listings = d.listing_rows || 0; + const reviews = d.review_rows || 0; + monsterSetIndicator( + `✓ MONSTER — ${sales} sales · ${listings} listings · ${reviews} reviews`, + '#2a7a2a', 4000 + ); + } else { + monsterSetIndicator(`✗ MONSTER ${resp.status}`, '#b00', 4000); + } + } catch (e) { + monsterSetIndicator( + e.name === 'TimeoutError' ? '✗ MONSTER timeout' : '✗ MONSTER unreachable', + '#b00', 4000 + ); + } +} + +// YouTube Cookie Management Functions +function extractCookies() { + const button = document.getElementById('getCookies'); + const textarea = document.getElementById('cookieOutput'); + + if (!button || !textarea) return; // Elements don't exist on this page + + // Check if chrome runtime is available + if (typeof chrome === 'undefined' || !chrome.runtime) { + textarea.value = 'Extension functionality not available in preview mode.\nInstall as Chrome extension to use YouTube cookie extraction.'; + return; + } + + // Show loading state + button.disabled = true; + button.textContent = 'Extracting...'; + textarea.value = 'Extracting cookies...'; + + chrome.runtime.sendMessage({ action: "getCookies" }, async function (response) { + if (response && response.success && response.cookieText) { + textarea.value = response.cookieText; + + // Try to copy to clipboard + let copied = false; + try { + await navigator.clipboard.writeText(response.cookieText); + copied = true; + } catch (err) { + // console.error('Failed to copy:', err); + } + + button.textContent = copied ? 'Cookies Saved & Copied!' : 'Cookies Saved!'; + button.style.backgroundColor = '#45a049'; + + // Reset button after delay + setTimeout(() => { + button.textContent = 'Extract Cookies'; + button.style.backgroundColor = '#4CAF50'; + button.disabled = false; + }, 2000); + } else { + // Handle error + console.error('Error response:', response); + textarea.value = response?.error || 'Failed to extract cookies'; + button.textContent = 'Error - Try Again'; + button.style.backgroundColor = '#f44336'; + button.disabled = false; + + setTimeout(() => { + button.textContent = 'Extract Cookies'; + button.style.backgroundColor = '#4CAF50'; + }, 3000); + } + }); +} + +function initializeYouTubeCookieUI() { + const toggle = document.getElementById('autoUpdate'); + const blagginateToggle = document.getElementById('blagginateBridge'); + const textarea = document.getElementById('cookieOutput'); + const button = document.getElementById('getCookies'); + const container = document.querySelector('.youtube-cookie-container'); + + if (!toggle || !blagginateToggle || !textarea || !button || !container) return; // Elements don't exist + + // Check if chrome.storage is available (extension context) + if (typeof chrome !== 'undefined' && chrome.storage) { + // Load initial state + chrome.storage.local.get(['autoUpdate', 'blagginateBridge', 'lastCookie', 'lastUpdate'], function (data) { + // Set toggle states + toggle.checked = data.autoUpdate === true; + blagginateToggle.checked = data.blagginateBridge !== false; // Default to true + + // Show last saved cookie if available + if (data.lastCookie) { + const lastUpdateTime = new Date(data.lastUpdate).toLocaleString(); + textarea.value = `Last saved on ${lastUpdateTime}:\n\n${data.lastCookie}`; + } else { + textarea.value = 'No cookies saved yet. Click "Extract Cookies" to get YouTube cookies.'; + } + + // If auto-update is enabled, get fresh cookies + if (data.autoUpdate === true) { + extractCookies(); + } + }); + + // Handle auto-update toggle changes + toggle.addEventListener('change', function (e) { + const isEnabled = e.target.checked; + chrome.storage.local.set({ autoUpdate: isEnabled }, function () { + if (isEnabled) { + extractCookies(); + } + }); + }); + + // Handle BLAGGINATE bridge toggle changes + blagginateToggle.addEventListener('change', function (e) { + const isEnabled = e.target.checked; + chrome.storage.local.set({ blagginateBridge: isEnabled }, function () { + // Send message to background script to enable/disable bridge + chrome.runtime.sendMessage({ + type: 'toggle_blagginate_bridge', + enabled: isEnabled + }); + + console.log('BLAGGINATE bridge', isEnabled ? 'enabled' : 'disabled'); + }); + }); + } else { + // Fallback for non-extension context (preview mode) + textarea.value = 'Extension functionality not available in preview mode.\nInstall as Chrome extension to use YouTube cookie extraction.'; + toggle.disabled = true; + blagginateToggle.disabled = true; + button.disabled = true; + } + + // Handle button click + button.addEventListener('click', extractCookies); + + // JDownloader 2 button: pull fresh YT cookies as Cookie-Editor JSON and copy to clipboard. + const jdBtn = document.getElementById('getCookiesJd2'); + if (jdBtn) { + jdBtn.addEventListener('click', () => { + const orig = jdBtn.textContent; + jdBtn.disabled = true; + jdBtn.textContent = 'Fetching...'; + chrome.runtime.sendMessage({ action: 'getCookiesJson' }, async (response) => { + if (response && response.success && response.cookieJson) { + try { + await navigator.clipboard.writeText(response.cookieJson); + textarea.value = response.cookieJson; + jdBtn.textContent = 'Copied! Paste into JD2 password field'; + jdBtn.style.background = '#45a049'; + } catch (err) { + textarea.value = response.cookieJson; + jdBtn.textContent = 'Shown below — copy manually'; + jdBtn.style.background = '#f39c12'; + } + } else { + jdBtn.textContent = 'Failed: ' + ((response && response.error) || 'unknown'); + jdBtn.style.background = '#f44336'; + } + setTimeout(() => { + jdBtn.textContent = orig; + jdBtn.style.background = '#2196F3'; + jdBtn.disabled = false; + }, 2500); + }); + }); + } +} + +// Tab switching functionality +function initializeTabs() { + const tabButtons = document.querySelectorAll('.tab-button'); + const tabContents = document.querySelectorAll('.tab-content'); + + tabButtons.forEach(button => { + button.addEventListener('click', () => { + const targetTab = button.getAttribute('data-tab'); + + // Remove active class from all buttons and contents + tabButtons.forEach(btn => btn.classList.remove('active')); + tabContents.forEach(content => content.classList.remove('active')); + + // Add active class to clicked button and corresponding content + button.classList.add('active'); + document.getElementById(`${targetTab}-tab`).classList.add('active'); + }); + }); +} + +// Save functions - defined before DOMContentLoaded to ensure availability +function saveDiscogsToken() { + if (!chrome || !chrome.storage) { + alert('Chrome storage not available in preview mode'); + return; + } + + const token = document.getElementById('discogs-token').value.trim(); + console.log('Saving Discogs token:', { hasToken: !!token }); + + if (token) { + chrome.storage.local.set({ discogsToken: token }, () => { + console.log('Discogs token saved successfully to chrome.storage.local'); + if (chrome.runtime.lastError) { + console.error('Error saving Discogs token:', chrome.runtime.lastError); + alert('Error saving Discogs token: ' + chrome.runtime.lastError.message); + } + }); + } else { + console.log('No Discogs token to save (field empty)'); + } +} + +function saveGoogleSettings() { + if (!chrome || !chrome.storage) { + alert('Chrome storage not available in preview mode'); + return; + } + + const spreadsheetId = document.getElementById('spreadsheet-id').value; + const serviceAccountJson = document.getElementById('google-service-account-json').value; + + console.log('Saving Google settings:', { spreadsheetId, hasServiceAccount: !!serviceAccountJson }); + + let googleSettings = {}; + + if (spreadsheetId) { + googleSettings.spreadsheetId = spreadsheetId; + } + + if (serviceAccountJson) { + try { + const serviceAccount = JSON.parse(serviceAccountJson); + if (serviceAccount.client_email && serviceAccount.private_key) { + googleSettings.clientEmail = serviceAccount.client_email; + googleSettings.privateKey = serviceAccount.private_key; + } + } catch (error) { + console.error('Invalid JSON in service account field:', error); + alert('Invalid JSON format in Service Account JSON field'); + return; + } + } + + if (Object.keys(googleSettings).length > 0) { + chrome.storage.local.set({ googleSettings: googleSettings }, () => { + console.log('Google settings saved successfully to chrome.storage.local'); + if (chrome.runtime.lastError) { + console.error('Error saving Google settings:', chrome.runtime.lastError); + alert('Error saving Google settings: ' + chrome.runtime.lastError.message); + } + }); + } else { + console.log('No Google settings to save (all fields empty)'); + } +} + +document.addEventListener('DOMContentLoaded', function () { + // Initialize tab functionality first + initializeTabs(); + + // Initialize mapping tab + initializeMappingTab(); + + // Initialize YouTube cookie functionality + initializeYouTubeCookieUI(); + + // Load auto-update Discogs price setting + const autoUpdatePriceCheckbox = document.getElementById('autoUpdateDiscogsPrice'); + if (autoUpdatePriceCheckbox && chrome && chrome.storage) { + chrome.storage.local.get(['autoUpdateDiscogsPrice'], (result) => { + // Default to true if not set + autoUpdatePriceCheckbox.checked = result.autoUpdateDiscogsPrice !== false; + }); + + // Save setting when changed + autoUpdatePriceCheckbox.addEventListener('change', () => { + chrome.storage.local.set({ autoUpdateDiscogsPrice: autoUpdatePriceCheckbox.checked }); + console.log('Auto-update Discogs price setting saved:', autoUpdatePriceCheckbox.checked); + }); + } + + // Load and persist QR SKU toggle; show indicator on Discogs tab + const qrUseSkuCheckbox = document.getElementById('qr-use-sku'); + const skuIndicator = document.getElementById('sku-mode-indicator'); + const skuIndicatorStatus = document.getElementById('sku-mode-status'); + function updateSkuIndicator(on) { + if (!skuIndicator) return; + skuIndicator.style.display = 'block'; + skuIndicatorStatus.textContent = on ? 'ON' : 'OFF'; + skuIndicatorStatus.style.color = on ? '#28a745' : '#dc3545'; + } + if (qrUseSkuCheckbox && chrome && chrome.storage) { + chrome.storage.local.get(['qrUseSku'], (result) => { + qrUseSkuCheckbox.checked = result.qrUseSku === true; + updateSkuIndicator(result.qrUseSku === true); + }); + qrUseSkuCheckbox.addEventListener('change', () => { + chrome.storage.local.set({ qrUseSku: qrUseSkuCheckbox.checked }); + updateSkuIndicator(qrUseSkuCheckbox.checked); + }); + } + + // Load enable JSON download setting + const enableJsonDownloadCheckbox = document.getElementById('enableJsonDownload'); + if (enableJsonDownloadCheckbox && chrome && chrome.storage) { + chrome.storage.local.get(['enableJsonDownload'], (result) => { + // Default to true if not set + enableJsonDownloadCheckbox.checked = result.enableJsonDownload !== false; + }); + + // Save setting when changed + enableJsonDownloadCheckbox.addEventListener('change', () => { + chrome.storage.local.set({ enableJsonDownload: enableJsonDownloadCheckbox.checked }); + console.log('Enable JSON download setting saved:', enableJsonDownloadCheckbox.checked); + }); + } + + // ── Settings: ALL config + RFID + visibility ───────────────────────────── + const settingsConfig = [ + // [storageKey, elementId, defaultValue] + ['allDoesLabel', 'allDoesLabel', true], + ['allDoesSheet', 'allDoesSheet', true], + ['allDoesRfid', 'allDoesRfid', true], + ['allDoesJson', 'allDoesJson', true], + ['allDoesPrice', 'allDoesPrice', true], + ['qrUseSku', 'qrUseSku', false], + ['rfidIncludeReleaseId', 'rfidIncludeReleaseId', false], + ['rfidAppendR', 'rfidAppendR', false], + ['btnShowLabel', 'btnShowLabel', true], + ['btnShowRfid', 'btnShowRfid', true], + ['btnShowSheet', 'btnShowSheet', true], + ['btnShowJson', 'btnShowJson', true], + ['btnShowInventory', 'btnShowInventory', true], + ['btnShowLabel203', 'btnShowLabel203', false], + ['enableJsonDownload', 'enableJsonDownload', true], + ['stripSkuSuffix', 'stripSkuSuffix', false], + ]; + const allKeys = settingsConfig.map(c => c[0]); + chrome.storage.local.get(allKeys, (stored) => { + for (const [key, id, def] of settingsConfig) { + const el = document.getElementById(id); + if (!el) continue; + el.checked = stored[key] !== undefined ? stored[key] : def; + el.addEventListener('change', () => { + chrome.storage.local.set({ [key]: el.checked }); + if (id.startsWith('btnShow')) applyButtonVisibility(stored); + if (id === 'stripSkuSuffix') { + window.stripSkuSuffix = el.checked; + if (state.releaseData) updatePreview(state.releaseData); + } + }); + } + window.stripSkuSuffix = stored.stripSkuSuffix === true; + applyButtonVisibility(stored); + }); + + function applyButtonVisibility(stored) { + // Re-read live from checkboxes (they may have just changed) + const showLabel = document.getElementById('btnShowLabel')?.checked ?? true; + const showRfid = document.getElementById('btnShowRfid')?.checked ?? true; + const showSheet = document.getElementById('btnShowSheet')?.checked ?? true; + const showJson = document.getElementById('btnShowJson')?.checked ?? true; + const showInventory = document.getElementById('btnShowInventory')?.checked ?? true; + const showLabel203 = document.getElementById('btnShowLabel203')?.checked ?? false; + + const setVis = (id, show) => { + const el = document.getElementById(id); + if (el) el.style.display = show ? '' : 'none'; + }; + setVis('printLabel', showLabel); + setVis('printLabel203', showLabel203); + setVis('rfidQuickWrite', showRfid); + setVis('updateSheet', showSheet); + setVis('writeJSON', showJson); + setVis('importWordPress', showInventory); + + // Hide small row entirely if all buttons hidden + const smallRow = document.getElementById('buttons-small-row'); + if (smallRow) smallRow.style.display = (showSheet || showJson || showInventory) ? '' : 'none'; + } + + function applyLabelPreviewVisibility() { + const size = document.getElementById('labelSize')?.value || 'large'; + const previewSmall = document.querySelector('.label-preview'); + const previewLarge = document.querySelector('.label-preview-large'); + const previewXLarge = document.querySelector('.label-preview-xlarge'); + if (previewSmall) previewSmall.style.display = size === 'small' ? '' : 'none'; + if (previewLarge) previewLarge.style.display = size === 'large' ? '' : 'none'; + if (previewXLarge) previewXLarge.style.display = size === 'xlarge' ? '' : 'none'; + } + + // ── Label settings (font/bold/italic/size + per-field styles) ──────────── + const LFS_FIELDS = ['artist','title','genre','style','format','info','price','condition','comment','notes']; + + function applyLabelFieldStyles(lfs) { + window.labelFieldStyles = lfs || {}; + LFS_FIELDS.forEach(f => { + const s = (lfs || {})[f] || {}; + const bEl = document.getElementById(`lfs-${f}-b`); + const iEl = document.getElementById(`lfs-${f}-i`); + const eEl = document.getElementById(`lfs-${f}-e`); + if (bEl) bEl.checked = !!s.b; + if (iEl) iEl.checked = !!s.i; + if (eEl) eEl.checked = !!s.e; + }); + } + + function readLabelFieldStyles() { + const lfs = {}; + LFS_FIELDS.forEach(f => { + lfs[f] = { + b: !!(document.getElementById(`lfs-${f}-b`)?.checked), + i: !!(document.getElementById(`lfs-${f}-i`)?.checked), + e: !!(document.getElementById(`lfs-${f}-e`)?.checked), + }; + }); + return lfs; + } + + chrome.storage.local.get(['labelFont', 'labelBold', 'labelItalic', 'labelSize', 'labelFieldStyles'], (ls) => { + const fontSel = document.getElementById('label-font-select'); + const boldCb = document.getElementById('label-bold-toggle'); + const italicCb = document.getElementById('label-italic-toggle'); + const sizeSel = document.getElementById('labelSize'); + if (fontSel && ls.labelFont) fontSel.value = ls.labelFont; + if (boldCb) boldCb.checked = ls.labelBold === true; + if (italicCb) italicCb.checked = ls.labelItalic === true; + if (sizeSel && ls.labelSize) sizeSel.value = ls.labelSize; + applyLabelPreviewVisibility(); + applyLabelFieldStyles(ls.labelFieldStyles); + + const onLabelChange = () => { + const lfs = readLabelFieldStyles(); + window.labelFieldStyles = lfs; + chrome.storage.local.set({ + labelFont: fontSel?.value, + labelBold: boldCb?.checked, + labelItalic: italicCb?.checked, + labelSize: sizeSel?.value, + labelFieldStyles: lfs, + }); + if (state.releaseData) updatePreview(state.releaseData); + }; + fontSel?.addEventListener('change', onLabelChange); + boldCb?.addEventListener('change', onLabelChange); + italicCb?.addEventListener('change', onLabelChange); + sizeSel?.addEventListener('change', onLabelChange); + + // Wire per-field checkboxes + LFS_FIELDS.forEach(f => { + ['b','i','e'].forEach(prop => { + document.getElementById(`lfs-${f}-${prop}`)?.addEventListener('change', onLabelChange); + }); + }); + }); + + // Check if chrome.tabs is available (extension context) + if (typeof chrome !== 'undefined' && chrome.tabs) { + chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) { + if (!tabs || !tabs[0] || !tabs[0].url) { + console.error('No active tab or URL found'); + return; + } + + const url = tabs[0].url; + const releaseMatch = url.match(/\/release\/(\d+)/); + const masterMatch = url.match(/\/master\/(\d+)/); + const styleMatch = url.match(/\/style\/([^\/]+)/); + const isYouTube = url.includes('youtube.com'); + + // Determine which tab to show based on the current page + if (isYouTube) { + document.querySelector('.tab-button[data-tab="youtube"]').click(); + } else if (releaseMatch || styleMatch || masterMatch) { + document.querySelector('.tab-button[data-tab="discogs"]').click(); + } else { + document.querySelector('.tab-button[data-tab="settings"]').click(); + } + + if (styleMatch) { + document.getElementById('stylePageContainer').style.display = 'block'; + } else if (releaseMatch) { + fetchAndDisplayReleaseData(releaseMatch[1]); + } else if (masterMatch) { + showMasterPageStatus(masterMatch[1], tabs[0].id); + } + }); + + loadWpSettings(); + loadGoogleSettings(); + loadInventorySettings(); + loadDiscogsToken(); + (function () { var el = document.getElementById('extension-id-display'); if (el) { if (typeof chrome !== 'undefined' && chrome.runtime && chrome.runtime.id) { el.textContent = chrome.runtime.id; } } })(); + // Copy Extension ID button + (function () { + var btn = document.getElementById('copy-extension-id'); + if (btn) { + btn.addEventListener('click', async function () { + var id = (typeof chrome !== 'undefined' && chrome.runtime && chrome.runtime.id) ? chrome.runtime.id : (document.getElementById('extension-id-display').textContent || '').trim(); + try { + await navigator.clipboard.writeText(id); + var status = document.getElementById('copy-extension-id-status'); + if (status) { + status.textContent = 'Copied!'; + status.style.display = 'inline'; + setTimeout(function () { status.style.display = 'none'; }, 1500); + } + } catch (e) { + try { + var temp = document.createElement('textarea'); + temp.value = id; + document.body.appendChild(temp); + temp.select(); + document.execCommand('copy'); + document.body.removeChild(temp); + var status2 = document.getElementById('copy-extension-id-status'); + if (status2) { + status2.textContent = 'Copied!'; + status2.style.display = 'inline'; + setTimeout(function () { status2.style.display = 'none'; }, 1500); + } + } catch (err2) { + console.error('Clipboard copy failed:', err2); + alert('Could not copy extension ID. Please copy manually.'); + } + } + }); + } + })(); + } + + // Add all event listeners inside DOMContentLoaded to ensure DOM elements exist + document.getElementById('settings-toggle-connect').addEventListener('click', () => { + document.getElementById('settings-content-connect').style.display = document.getElementById('settings-content-connect').style.display === 'none' ? 'block' : 'none'; + }); + + document.getElementById('save-connect-settings').addEventListener('click', () => { + console.log('Save Connect Settings button clicked!'); + + // Save Google Settings + if (!chrome || !chrome.storage) { + alert('Chrome storage not available in preview mode'); + return; + } + + const spreadsheetId = document.getElementById('spreadsheet-id').value; + const serviceAccountJson = document.getElementById('google-service-account-json').value; + + console.log('Saving Google settings:', { spreadsheetId, hasServiceAccount: !!serviceAccountJson }); + + let googleSettings = {}; + + if (spreadsheetId) { + googleSettings.spreadsheetId = spreadsheetId; + } + + if (serviceAccountJson) { + try { + const serviceAccount = JSON.parse(serviceAccountJson); + if (serviceAccount.client_email && serviceAccount.private_key) { + googleSettings.clientEmail = serviceAccount.client_email; + googleSettings.privateKey = serviceAccount.private_key; + } + } catch (error) { + console.error('Invalid JSON in service account field:', error); + alert('Invalid JSON format in Service Account JSON field'); + return; + } + } + + if (Object.keys(googleSettings).length > 0) { + chrome.storage.local.set({ googleSettings: googleSettings }, () => { + console.log('Google settings saved successfully to chrome.storage.local'); + if (chrome.runtime.lastError) { + console.error('Error saving Google settings:', chrome.runtime.lastError); + alert('Error saving Google settings: ' + chrome.runtime.lastError.message); + } else { + alert('Google settings saved successfully!'); + } + }); + } else { + console.log('No Google settings to save (all fields empty)'); + } + + // Save Discogs Token + const discogsToken = document.getElementById('discogs-token').value.trim(); + if (discogsToken) { + chrome.storage.local.set({ discogsToken: discogsToken }, () => { + console.log('Discogs token saved successfully to chrome.storage.local'); + if (chrome.runtime.lastError) { + console.error('Error saving Discogs token:', chrome.runtime.lastError); + alert('Error saving Discogs token: ' + chrome.runtime.lastError.message); + } + }); + } else { + console.log('No Discogs token to save (field empty)'); + } + + // Save Inventory SKU Lookup settings + const inventorySettings = { + enabled: document.getElementById('inventorySkuEnabled').checked, + dbHost: document.getElementById('inventory-db-host').value.trim() || '100.123.123.64', + dbName: document.getElementById('inventory-db-name').value.trim() || 'wp_rmp_disc_', + dbUser: document.getElementById('inventory-db-user').value.trim(), + dbPass: document.getElementById('inventory-db-pass').value.trim(), + sshKeyPath: document.getElementById('inventory-ssh-key').value.trim() || '~/.ssh/id_rsa' + }; + chrome.storage.local.set({ inventorySettings }, () => { + if (chrome.runtime.lastError) { + console.error('Error saving inventory settings:', chrome.runtime.lastError); + alert('Error saving inventory settings: ' + chrome.runtime.lastError.message); + } else { + console.log('Inventory settings saved successfully.'); + } + }); + }); + + // MONSTERWIKI settings handlers + document.getElementById('settings-toggle-monster').addEventListener('click', () => { + const el = document.getElementById('settings-content-monster'); + el.style.display = el.style.display === 'none' ? 'block' : 'none'; + }); + + document.getElementById('save-monster-settings').addEventListener('click', () => { + const enabled = document.getElementById('monster-enabled').checked; + const autoCapture = document.getElementById('monster-autocapture')?.checked === true; + const preferLocalhost = document.getElementById('monster-prefer-localhost')?.checked === true; + const serverUrl = document.getElementById('monster-server-url').value.trim() + || 'http://100.91.239.7:5002'; + chrome.storage.local.set({ monsterSettings: { enabled, autoCapture, preferLocalhost, serverUrl } }, () => { + document.getElementById('monster-status').textContent = 'Saved.'; + setTimeout(() => { document.getElementById('monster-status').textContent = ''; }, 2000); + }); + }); + + document.getElementById('test-monster-connection').addEventListener('click', async () => { + const statusEl = document.getElementById('monster-status'); + statusEl.textContent = 'Testing…'; + const cfg = await getMonsterSettings(); + const base = (cfg.serverUrl || 'http://100.91.239.7:5002').replace(/\/$/, ''); + try { + const r = await fetch(`${base}/plice/health`, { signal: AbortSignal.timeout(5000) }); + statusEl.textContent = r.ok ? '✓ Connected' : `✗ HTTP ${r.status}`; + } catch (e) { + statusEl.textContent = `✗ ${e.message.includes('abort') ? 'Timeout' : 'Unreachable'}`; + } + }); + + // Load saved MONSTERWIKI settings into fields + chrome.storage.local.get(['monsterSettings'], r => { + const cfg = r.monsterSettings || {}; + if (document.getElementById('monster-enabled')) + document.getElementById('monster-enabled').checked = cfg.enabled === true; + if (document.getElementById('monster-autocapture')) + document.getElementById('monster-autocapture').checked = cfg.autoCapture === true; + if (document.getElementById('monster-prefer-localhost')) + document.getElementById('monster-prefer-localhost').checked = cfg.preferLocalhost === true; + if (document.getElementById('monster-server-url')) + document.getElementById('monster-server-url').value = cfg.serverUrl || 'http://100.91.239.7:5002'; + }); + + const geminiToggle = document.getElementById('settings-toggle-gemini'); + if (geminiToggle) { + geminiToggle.addEventListener('click', () => { + const el = document.getElementById('settings-content-gemini'); + el.style.display = el.style.display === 'none' ? 'block' : 'none'; + }); + } + + const geminiTemplateEl = document.getElementById('gemini-prompt-template'); + const geminiStatusEl = document.getElementById('gemini-prompt-status'); + const geminiCloseTabEl = document.getElementById('gemini-close-tab'); + const geminiAutoRunEl = document.getElementById('gemini-auto-run'); + const aiProviderEl = document.getElementById('ai-provider'); + + chrome.storage.local.get(['geminiPromptTemplate', 'geminiCloseTabOnSuccess', 'geminiAutoRunOnPopup', 'aiProvider'], r => { + if (!geminiTemplateEl) return; + geminiTemplateEl.value = (r.geminiPromptTemplate && typeof r.geminiPromptTemplate === 'string') + ? r.geminiPromptTemplate + : defaultGeminiPromptTemplate(); + if (geminiCloseTabEl) geminiCloseTabEl.checked = r.geminiCloseTabOnSuccess !== false; + if (geminiAutoRunEl) geminiAutoRunEl.checked = r.geminiAutoRunOnPopup === true; + if (aiProviderEl) aiProviderEl.value = (r.aiProvider === 'deepseek') ? 'deepseek' : 'gemini'; + }); + + if (geminiCloseTabEl) { + geminiCloseTabEl.addEventListener('change', () => { + chrome.storage.local.set({ geminiCloseTabOnSuccess: geminiCloseTabEl.checked === true }); + }); + } + + if (geminiAutoRunEl) { + geminiAutoRunEl.addEventListener('change', () => { + chrome.storage.local.set({ geminiAutoRunOnPopup: geminiAutoRunEl.checked === true }, () => { + if (geminiStatusEl) geminiStatusEl.textContent = geminiAutoRunEl.checked ? 'Auto-run enabled.' : 'Auto-run disabled.'; + setTimeout(() => { if (geminiStatusEl) geminiStatusEl.textContent = ''; }, 1500); + }); + }); + } + + if (aiProviderEl) { + aiProviderEl.addEventListener('change', () => { + const v = aiProviderEl.value === 'deepseek' ? 'deepseek' : 'gemini'; + chrome.storage.local.set({ aiProvider: v }, () => { + if (geminiStatusEl) geminiStatusEl.textContent = `Provider: ${v}`; + setTimeout(() => { if (geminiStatusEl) geminiStatusEl.textContent = ''; }, 1500); + }); + }); + } + + const saveGeminiBtn = document.getElementById('save-gemini-prompt'); + if (saveGeminiBtn) { + saveGeminiBtn.addEventListener('click', () => { + if (!geminiTemplateEl) return; + const tpl = geminiTemplateEl.value || ''; + const closeOnSuccess = geminiCloseTabEl ? geminiCloseTabEl.checked === true : true; + const autoRun = geminiAutoRunEl ? geminiAutoRunEl.checked === true : false; + chrome.storage.local.set({ geminiPromptTemplate: tpl, geminiCloseTabOnSuccess: closeOnSuccess, geminiAutoRunOnPopup: autoRun }, () => { + if (geminiStatusEl) geminiStatusEl.textContent = 'Saved.'; + setTimeout(() => { if (geminiStatusEl) geminiStatusEl.textContent = ''; }, 2000); + }); + }); + } + + const resetGeminiBtn = document.getElementById('reset-gemini-prompt'); + if (resetGeminiBtn) { + resetGeminiBtn.addEventListener('click', () => { + if (!geminiTemplateEl) return; + geminiTemplateEl.value = defaultGeminiPromptTemplate(); + const closeOnSuccess = geminiCloseTabEl ? geminiCloseTabEl.checked === true : true; + const autoRun = geminiAutoRunEl ? geminiAutoRunEl.checked === true : false; + chrome.storage.local.set({ geminiPromptTemplate: geminiTemplateEl.value, geminiCloseTabOnSuccess: closeOnSuccess, geminiAutoRunOnPopup: autoRun }, () => { + if (geminiStatusEl) geminiStatusEl.textContent = 'Reset.'; + setTimeout(() => { if (geminiStatusEl) geminiStatusEl.textContent = ''; }, 2000); + }); + }); + } + + chrome.storage.onChanged.addListener((changes, areaName) => { + if (areaName !== 'local') return; + if (!changes.geminiJob) return; + const job = changes.geminiJob.newValue; + if (!job) return; + if (state.releaseData?.id && job.release_id && job.release_id !== state.releaseData.id) return; + const prov = job.provider === 'deepseek' ? 'DeepSeek' : 'Gemini'; + + if (job.status === 'posting') { + geminiSetIndicator(`${prov} saving…`, '#888'); + } else if (job.status === 'done') { + geminiSetIndicator(`✓ ${prov} done`, '#28a745', 2500); + } else if (job.status === 'error') { + geminiSetIndicator(`✗ ${prov}: ${job.error || 'error'}`, '#dc3545'); + } + }); + + document.getElementById('settings-toggle-wowplatter').addEventListener('click', () => { + document.getElementById('settings-content-wowplatter').style.display = document.getElementById('settings-content-wowplatter').style.display === 'none' ? 'block' : 'none'; + }); + + document.getElementById('save-wp-settings').addEventListener('click', () => { + saveWpSettings(); + // Note: saveWpSettings() already shows an alert, so we don't need another one + }); + + document.getElementById('test-wp-connection').addEventListener('click', testWpConnection); + + // Keep the old save-google-settings for backward compatibility (if needed) + document.getElementById('save-google-settings')?.addEventListener('click', () => { + if (!chrome || !chrome.storage) { + alert('Chrome storage not available in preview mode'); + return; + } + + const spreadsheetId = document.getElementById('spreadsheet-id').value; + const jsonText = document.getElementById('google-service-account-json').value; + try { + const serviceAccount = JSON.parse(jsonText); + chrome.storage.local.set({ + googleSettings: { + spreadsheetId, + clientEmail: serviceAccount.client_email, + privateKey: serviceAccount.private_key + } + }, () => alert('Google settings saved!')); + } catch (error) { + alert(`Error parsing service account JSON: ${error.message}`); + } + }); + + // Mapping tab event listeners + document.getElementById('save-mappings')?.addEventListener('click', saveMappings); + document.getElementById('load-mappings')?.addEventListener('click', loadMappings); + document.getElementById('reset-mappings')?.addEventListener('click', resetMappings); + document.getElementById('detect-sheet')?.addEventListener('click', detectSheetStructureUI); + document.getElementById('auto-map-headers')?.addEventListener('click', autoMapHeaders); + document.getElementById('toggle-manual-range')?.addEventListener('click', toggleManualRange); +}); + +function loadGoogleSettings() { + if (!chrome || !chrome.storage) { + console.log('Chrome storage not available in preview mode'); + return; + } + + chrome.storage.local.get('googleSettings', (data) => { + console.log('Loading Google settings:', data.googleSettings); + if (data.googleSettings) { + document.getElementById('spreadsheet-id').value = data.googleSettings.spreadsheetId || ''; + const serviceAccount = { + client_email: data.googleSettings.clientEmail, + private_key: data.googleSettings.privateKey + }; + if (data.googleSettings.clientEmail && data.googleSettings.privateKey) { + document.getElementById('google-service-account-json').value = JSON.stringify(serviceAccount, null, 2); + } + console.log('Google settings loaded successfully'); + } else { + console.log('No Google settings found in storage'); + } + }); +} + +function loadDiscogsToken() { + if (!chrome || !chrome.storage) { + console.log('Chrome storage not available in preview mode'); + return; + } + + chrome.storage.local.get('discogsToken', (data) => { + console.log('Loading Discogs token:', { hasToken: !!data.discogsToken }); + if (data.discogsToken) { + document.getElementById('discogs-token').value = (data.discogsToken || '').trim(); + console.log('Discogs token loaded successfully'); + } else { + console.log('No Discogs token found in storage'); + } + }); +} + +function loadInventorySettings() { + if (!chrome || !chrome.storage) { + console.log('Chrome storage not available in preview mode'); + return; + } + chrome.storage.local.get(['inventorySettings'], (result) => { + const s = result.inventorySettings || {}; + const el = (id) => document.getElementById(id); + if (el('inventorySkuEnabled')) el('inventorySkuEnabled').checked = !!s.enabled; + if (el('inventory-db-host')) el('inventory-db-host').value = s.dbHost || '100.123.123.64'; + if (el('inventory-db-name')) el('inventory-db-name').value = s.dbName || 'wp_rmp_disc_'; + if (el('inventory-db-user')) el('inventory-db-user').value = s.dbUser || ''; + if (el('inventory-db-pass')) el('inventory-db-pass').value = s.dbPass || ''; + if (el('inventory-ssh-key')) el('inventory-ssh-key').value = s.sshKeyPath || '~/.ssh/id_rsa'; + console.log('Inventory settings loaded successfully'); + }); +} + +function makeEditable(field) { + const valueElement = field.querySelector('.value'); + if (valueElement && valueElement.getAttribute('contenteditable') === 'true') { + valueElement.addEventListener('input', () => { + const fieldName = field.dataset.field; + if (state.releaseData) { + state.releaseData[fieldName] = valueElement.textContent; + updatePreview(state.releaseData); + } + }); + } +} + +function setupEventListeners() { + const elements = { + priceInput: document.getElementById('price'), + priceCheckboxes: document.querySelectorAll('.price-checkbox'), + sleeveCondition: document.getElementById('sleeveCondition'), + mediaCondition: document.getElementById('mediaCondition'), + commentInput: document.getElementById('commentInput'), + labelSize: document.getElementById('labelSize'), + }; + + const updateState = (key, value) => { + if (state.releaseData) { + state.releaseData[key] = value; + updatePreview(state.releaseData); + } + }; + + elements.priceInput.addEventListener('input', () => { + document.querySelectorAll('.price-checkbox').forEach(cb => cb.checked = false); + updateState('price', elements.priceInput.value); + }); + + // Also update on focus/blur/keyup/paste to ensure we catch all changes + elements.priceInput.addEventListener('focus', () => { + updateState('price', elements.priceInput.value); + }); + + elements.priceInput.addEventListener('blur', () => { + updateState('price', elements.priceInput.value); + }); + + elements.priceInput.addEventListener('keyup', () => { + updateState('price', elements.priceInput.value); + }); + + elements.priceInput.addEventListener('paste', () => { + setTimeout(() => updateState('price', elements.priceInput.value), 10); + }); + + elements.priceCheckboxes.forEach(checkbox => { + checkbox.addEventListener('change', () => { + if (checkbox.checked) { + elements.priceCheckboxes.forEach(cb => { if (cb !== checkbox) cb.checked = false; }); + elements.priceInput.value = checkbox.value; + updateState('price', checkbox.value); + } + }); + }); + + elements.mediaCondition.addEventListener('change', () => updateState('mediaCondition', elements.mediaCondition.value)); + elements.sleeveCondition.addEventListener('change', () => updateState('sleeveCondition', elements.sleeveCondition.value)); + // Update comment on input, focus, blur, keyup and paste to ensure we catch all changes + elements.commentInput.addEventListener('input', () => updateState('comment', elements.commentInput.textContent)); + elements.commentInput.addEventListener('focus', () => updateState('comment', elements.commentInput.textContent)); + elements.commentInput.addEventListener('blur', () => updateState('comment', elements.commentInput.textContent)); + elements.commentInput.addEventListener('keyup', () => updateState('comment', elements.commentInput.textContent)); + elements.commentInput.addEventListener('paste', () => { + setTimeout(() => updateState('comment', elements.commentInput.textContent), 10); + }); + elements.labelSize.addEventListener('change', () => { applyLabelPreviewVisibility(); updatePreview(state.releaseData); }); + + // QR SKU toggle: switch between release_id and SKU for preview + const qrSkuToggle = document.getElementById('qr-use-sku'); + if (qrSkuToggle) { + qrSkuToggle.addEventListener('change', () => { + if (!state.releaseData) return; + if (qrSkuToggle.checked) { + // Prefer existing Discogs SKU (reprint), else use the one generated at popup open + state.releaseData.sku = state.releaseData.collectionSku || state.sku; + } else { + delete state.releaseData.sku; + } + updatePreview(state.releaseData); + }); + } + + document.querySelectorAll('.info-field').forEach(makeEditable); + + document.getElementById('printLabel').addEventListener('click', () => generateLabel(state.releaseData)); + document.getElementById('printLabel203').addEventListener('click', () => generateLabel203dpi()); + document.getElementById('writeJSON').addEventListener('click', async (e) => { + if (e.shiftKey) { + // Shift+click = upload JSON and merge into state + const data = await uploadJSON(); + if (data) { + state.releaseData = { ...state.releaseData, ...data }; + displayReleaseInfo(state.releaseData); + updatePreview(state.releaseData); + updateResearchTab(); + showStatusMessage('allStatus', 'JSON loaded from file', true); + } + } else { + writeJSON(state.releaseData); + } + }); + + // BP JSON button — copy current Beatport token JSON to clipboard + const bpJsonBtn = document.getElementById('copyBeatportJson'); + if (bpJsonBtn) { + bpJsonBtn.addEventListener('click', () => { + chrome.storage.local.get(['beatportToken'], (result) => { + const tokenJson = result.beatportToken; + if (!tokenJson) { + showStatusMessage('allStatus', 'No Beatport token saved — fetch it in Settings first', false); + return; + } + navigator.clipboard.writeText(tokenJson).then(() => { + const orig = bpJsonBtn.textContent; + bpJsonBtn.textContent = 'Copied!'; + setTimeout(() => { bpJsonBtn.textContent = orig; }, 1500); + }).catch(() => { + showStatusMessage('allStatus', 'Clipboard write failed', false); + }); + }); + }); + } + document.getElementById('updateSheet').addEventListener('click', async () => { + // console.log('=== GOOGLE SHEETS BUTTON CLICKED ==='); + // console.log('Current state.releaseData:', state.releaseData); + + if (state.releaseData) { + const result = await updateSheetOnly(state.releaseData); + showStatusMessage('sheetStatus', result.message, result.success); + } + }); + document.getElementById('bothActions').addEventListener('click', async () => await handleAllActions(state.releaseData)); + + // RFID quick-READ from Discogs tab — shows what's currently on the tag without writing + const rfidReadBtn = document.getElementById('rfidQuickRead'); + if (rfidReadBtn) { + rfidReadBtn.addEventListener('click', async () => { + const rfidEl = document.getElementById('rfidStatus'); + if (rfidEl) { + rfidEl.style.color = '#888'; + rfidEl.style.whiteSpace = 'pre-line'; + rfidEl.style.fontSize = '11px'; + rfidEl.style.lineHeight = '1.4'; + rfidEl.textContent = 'Reading tag…'; + } + rfidReadBtn.disabled = true; + const orig = rfidReadBtn.textContent; + rfidReadBtn.textContent = '…'; + const tag = await readRfidTagOnce(); + rfidReadBtn.disabled = false; + rfidReadBtn.textContent = orig; + if (rfidEl) { + if (!tag) { + rfidEl.textContent = '✗ No tag in field (or daemon not running)'; + rfidEl.style.color = '#dc3545'; + } else { + // Compare against the current Discogs page if available + const expectedSku = (state.releaseData?.collectionSku || state.sku || '').replace(/-[AR]$/i, ''); + const expectedRel = state.releaseData?.id || null; + const matchSku = expectedSku && tag.sku === expectedSku; + const matchRel = expectedRel && tag.releaseId == expectedRel; + let line2 = ''; + if (expectedSku) { + line2 = `\nexpect: ${expectedSku}${expectedRel ? ' + rel ' + expectedRel : ''}`; + if (matchSku && matchRel) line2 += ' ✓ MATCH'; + else if (matchSku) line2 += ' ⚠ sku ok, rel mismatch'; + else line2 += ' ✗ DIFFERENT'; + } + rfidEl.textContent = `tag: ${formatTag(tag)}${line2}`; + rfidEl.style.color = (matchSku && matchRel) ? '#28a745' : (matchSku ? '#d29922' : '#888'); + } + } + }); + } + + // RFID quick-write from Discogs tab + const rfidQuickBtn = document.getElementById('rfidQuickWrite'); + if (rfidQuickBtn) { + rfidQuickBtn.addEventListener('click', async () => { + const rawSku = (state.releaseData?.collectionSku) || state.sku; + if (!rawSku) { + showStatusMessage('allStatus', 'No SKU — open a Discogs release first', false); + return; + } + const sku = rawSku ? rawSku.replace(/-[AR]$/i, '') : rawSku; + rfidQuickBtn.disabled = true; + const orig = rfidQuickBtn.textContent; + rfidQuickBtn.textContent = '…'; + const releaseId = state.releaseData?.id || null; + const rfidEl = document.getElementById('rfidStatus'); + if (rfidEl) { rfidEl.style.color = '#888'; rfidEl.style.whiteSpace = 'pre-line'; rfidEl.style.fontSize = '11px'; rfidEl.style.lineHeight = '1.4'; } + + // 1. PRE-SCAN — what's on the tag right now? + if (rfidEl) rfidEl.textContent = 'Reading current tag…'; + const before = await readRfidTagOnce(); + if (rfidEl && before) { + rfidEl.textContent = `pre: ${formatTag(before)}\nwriting…`; + } + + // 2. WRITE + const result = await writeRfidTag(sku, releaseId); + + // 3. POST-SCAN — confirm what's on the tag now + const after = result?.ok ? await readRfidTagOnce() : null; + + rfidQuickBtn.disabled = false; + rfidQuickBtn.textContent = orig; + if (rfidEl) { + if (!result) { + rfidEl.textContent = `pre: ${before ? formatTag(before) : '?'}\n✗ RFID: daemon not running`; + rfidEl.style.color = '#dc3545'; + } else if (result.ok) { + rfidEl.textContent = `pre: ${before ? formatTag(before) : '?'}\n✓ wrote ${sku}${releaseId ? ' + rel ' + releaseId : ''}\npost: ${after ? formatTag(after) : '?'}`; + rfidEl.style.color = '#28a745'; + } else { + rfidEl.textContent = `pre: ${before ? formatTag(before) : '?'}\n✗ RFID: ${result.error}`; + rfidEl.style.color = '#dc3545'; + } + } + if (result?.ok) { + const appendR = await new Promise(resolve => chrome.storage.local.get(['rfidAppendR'], r => resolve(r.rfidAppendR === true))); + if (appendR && state.discogsTabId) { + try { + await chrome.tabs.sendMessage(state.discogsTabId, { action: 'updateDiscogsSku', sku: sku + '-R', boxIndex: state.collectionBoxIndex }); + } catch (e) { console.warn('[RFID] -R SKU update failed:', e.message); } + } + } + }); + } + + // Website Inventory Sync + const importBtn = document.getElementById('importWordPress'); + if (importBtn) { + importBtn.addEventListener('click', handleImportInventory); + } +} + +// Function to update button states based on available settings +async function updateButtonStates() { + if (!chrome || !chrome.storage) { + return; // Skip in preview mode + } + + return new Promise((resolve) => { + chrome.storage.local.get(['discogsToken', 'googleSettings', 'wpSettings'], (result) => { + const hasDiscogsToken = result.discogsToken && result.discogsToken.trim() !== ''; + const hasGoogleSettings = result.googleSettings && + result.googleSettings.spreadsheetId && + result.googleSettings.clientEmail && + result.googleSettings.privateKey; + const hasWpSettings = result.wpSettings && + result.wpSettings.endpoint && result.wpSettings.endpoint.trim() !== '' && + result.wpSettings.key && result.wpSettings.key.trim() !== '' && + result.wpSettings.secret && result.wpSettings.secret.trim() !== ''; + + // Update Google Sheets button + const sheetButton = document.getElementById('updateSheet'); + const bothButton = document.getElementById('bothActions'); + + if (sheetButton) { + if (hasGoogleSettings) { + sheetButton.disabled = false; + sheetButton.style.opacity = '1'; + sheetButton.title = 'Update Google Sheets'; + } else { + sheetButton.disabled = true; + sheetButton.style.opacity = '0.5'; + sheetButton.title = 'Google Sheets not configured - go to Settings tab'; + } + } + + // Update "Both Actions" button behavior + if (bothButton) { + if (hasGoogleSettings) { + bothButton.title = 'Print Label + Update Google Sheets'; + } else { + bothButton.title = 'Print Label + Save JSON (Google Sheets not configured)'; + } + } + + // console.log('Button states updated:', { hasDiscogsToken, hasGoogleSettings, hasWpSettings }); + resolve(); + }); + }); +} + +// Settings validation functions +async function checkSettingsConfigured() { + // Check if we're in an extension context + if (!chrome || !chrome.storage) { + // console.log('Not in extension context, assuming settings not configured'); + return false; + } + + return new Promise((resolve) => { + chrome.storage.local.get(['discogsToken', 'googleSettings', 'wpSettings'], (result) => { + // console.log('=== DETAILED SETTINGS DEBUG ==='); + // console.log('Raw storage result:', result); + // console.log('discogsToken value:', result.discogsToken); + // console.log('googleSettings value:', result.googleSettings); + // console.log('wpSettings value:', result.wpSettings); + + const hasDiscogsToken = result.discogsToken && result.discogsToken.trim() !== ''; + // console.log('hasDiscogsToken check:', hasDiscogsToken); + + const hasGoogleSettings = result.googleSettings && + result.googleSettings.spreadsheetId && + result.googleSettings.clientEmail && + result.googleSettings.privateKey; + // console.log('hasGoogleSettings check:', hasGoogleSettings); + if (result.googleSettings) { + // console.log('Google settings breakdown:', { + // spreadsheetId: result.googleSettings.spreadsheetId, + // clientEmail: result.googleSettings.clientEmail, + // privateKey: result.googleSettings.privateKey ? 'PRESENT' : 'MISSING' + // }); + } + + const hasWpSettings = result.wpSettings && + result.wpSettings.endpoint && result.wpSettings.endpoint.trim() !== '' && + result.wpSettings.key && result.wpSettings.key.trim() !== '' && + result.wpSettings.secret && result.wpSettings.secret.trim() !== ''; + // console.log('hasWpSettings check:', hasWpSettings); + + // Discogs token is essential - that's the minimum requirement + // Google Sheets and WordPress are optional enhancements + const hasValidSettings = hasDiscogsToken; + // console.log('Final validation result:', { hasDiscogsToken, hasGoogleSettings, hasWpSettings, hasValidSettings }); + // console.log('Settings validation: Discogs token is the only requirement'); + // console.log('=== END SETTINGS DEBUG ==='); + resolve(hasValidSettings); + }); + }); +} + +function displayStaticInterface() { + const container = document.querySelector('.container'); + if (container) { + container.innerHTML = ` +