PagesStructures['id1779690236526'] = {"structures":[{"type":"page","id":"id1779690236526","elementProperties":{"tagName":"DIV","behaviours":null,"isLocked":true,"name":"Precision Art Grid","baseName":"Home","templateID":null,"templateName":null,"order":0,"customStates":null,"isElementWasEditedInMode":true,"showHoverEffects":true,"skinInformation":{"categoryId":245},"isSupportsMobile":false,"isVisibleInMode":true,"isFixed":false,"topZIndex":0,"elementOpacity":1,"staticMargin":{"horizontalMargin":0,"verticalMargin":0},"sizeAndPosition":{"width":0,"height":1068,"top":0,"left":0},"lastResizingSize":{"width":0,"height":1068,"top":0,"left":0},"isVisibleInLastSection":true,"isVisibleInLastDataItem":true,"attributes":null,"metaProps":null,"metaItemType":null,"metaTitle":null,"styleBindingId":null,"styleBindingFields":null,"shadow":{"top":0,"left":0,"spread":0,"blur":0,"color":"black"},"glow":{"spread":0,"blur":0,"color":"black"},"isParallaxBackground":false,"parallaxBackgroundSpeed":0.5,"isParallaxElement":{"isActive":false,"speed":1,"delay":0},"effectsOptions":{"isParallax":false,"oneTimeAnimation":false,"duration":1200,"startDistance":200,"startVisibility":0.8,"distance":300,"measureDistanceType":3,"delay":0,"distanceDelay":0,"runInLoop":false,"flyDirection":2,"direction":"horizontal","movementDistanceHorizontally":200,"movementDistanceVertically":0,"autoStartDistanceSettings":true,"autoDistanceSettings":true},"effects":null,"binding":null,"verticalAlign":"center","horizontalAlign":"center","horizontalContentAlign":"center","basicUserCanEdit":true,"overflow":false,"isGrowable":{"bottom":false,"right":false},"rowsItems":null,"childrenAnchor":"center","backgroundColor":{"mainColor":0,"variation":0,"opacity":1,"brightness":0},"imageUrl":"","imageLayout":"fitWhenBigger","imagePosition":{"horizontal":"center","vertical":"center"},"origImage":"","imageOpacity":1,"backgroundOverlay":"transparent","gridLines":[],"fixedBackground":false,"statesGroups":null},"metaData":{"position":{"left":-581.9921875,"top":0},"size":{"width":1164,"height":757}},"childElements":[{"type":"SectionElement","id":"id1779690236527","elementProperties":{"tagName":"SECTION","behaviours":null,"isLocked":false,"name":"Section 4","baseName":null,"templateID":null,"templateName":null,"order":3,"customStates":null,"isElementWasEditedInMode":false,"showHoverEffects":true,"skinInformation":{},"isSupportsMobile":false,"isVisibleInMode":true,"isFixed":false,"topZIndex":0,"elementOpacity":1,"staticMargin":{"horizontalMargin":0,"verticalMargin":0},"sizeAndPosition":{"height":642,"left":0,"width":1164,"top":0},"lastResizingSize":{"width":1164,"height":642},"isVisibleInLastSection":true,"isVisibleInLastDataItem":true,"attributes":null,"metaProps":null,"metaItemType":null,"metaTitle":null,"styleBindingId":null,"styleBindingFields":null,"shadow":{"top":0,"left":0,"spread":0,"blur":0,"color":"black"},"glow":{"spread":0,"blur":0,"color":"black"},"isParallaxBackground":false,"parallaxBackgroundSpeed":0.5,"isParallaxElement":{"isActive":false,"speed":1,"delay":0},"effectsOptions":{"isParallax":false,"oneTimeAnimation":false,"duration":1200,"startDistance":200,"startVisibility":0.8,"distance":300,"measureDistanceType":3,"delay":0,"distanceDelay":0,"runInLoop":false,"flyDirection":2,"direction":"horizontal","movementDistanceHorizontally":200,"movementDistanceVertically":0,"autoStartDistanceSettings":true,"autoDistanceSettings":true},"effects":null,"binding":null,"innerGlow":{"spread":0,"blur":0,"color":"black"},"innerShadow":{"top":0,"left":0,"spread":0,"blur":0,"color":"black"},"padding":{"top":0,"left":0,"bottom":0,"right":0},"basicUserCanEdit":true,"backgroundColor":{"mainColor":1,"variation":4,"opacity":1,"brightness":0},"imageUrl":"","imageLayout":"stretchedToFill","imagePosition":{"vertical":"center","horizontal":"center"},"origImage":"","imageOpacity":1,"backgroundOverlay":"transparent","verticalLayout":"normal","horizontalLayout":"normal","fillLayout":{"fillVertical":false,"fillHorizontal":false},"margin":{"top":0,"left":0,"bottom":0,"right":0},"overflow":false,"isGrowable":{"bottom":false,"right":false},"rowsItems":null,"childrenAnchor":"center","resizingGripPosiotion":"s","sectionName":"Section A","pageContentType":1,"borderWidth":{"top":0,"left":0,"bottom":0,"right":0},"roundness":{"topLeft":0,"bottomLeft":0,"topRight":0,"bottomRight":0},"borderColor":{"top":{"mainColor":1,"variation":4,"opacity":1,"brightness":0},"left":{"mainColor":1,"variation":4,"opacity":1,"brightness":0},"right":{"mainColor":1,"variation":4,"opacity":1,"brightness":0},"bottom":{"mainColor":1,"variation":4,"opacity":1,"brightness":0}},"borderStyle":{"top":"solid","left":"solid","bottom":"solid","right":"solid"}},"metaData":{"position":{"left":-581.9921875,"top":115},"size":{"width":1164,"height":642}},"childElements":[{"type":"ExternalAppembed_html_app1","id":"id1779690697013","elementProperties":{"tagName":"DIV","behaviours":null,"isLocked":false,"name":"Embed Html 1","baseName":null,"templateID":"templateid1779690697014","templateName":null,"order":32,"customStates":null,"isElementWasEditedInMode":false,"showHoverEffects":true,"skinInformation":{},"isSupportsMobile":false,"isVisibleInMode":true,"isFixed":false,"topZIndex":0,"elementOpacity":1,"staticMargin":{"horizontalMargin":0,"verticalMargin":0},"sizeAndPosition":{"width":960,"height":600,"left":-480,"top":6},"lastResizingSize":{"width":960,"height":600,"left":-480,"top":6},"isVisibleInLastSection":true,"isVisibleInLastDataItem":true,"attributes":null,"metaProps":null,"metaItemType":null,"metaTitle":null,"styleBindingId":null,"styleBindingFields":null,"shadow":{"top":0,"left":0,"spread":0,"blur":0,"color":"black"},"glow":{"spread":0,"blur":0,"color":"black"},"isParallaxBackground":false,"parallaxBackgroundSpeed":0.5,"isParallaxElement":{"isActive":false,"speed":1,"delay":0},"effectsOptions":{"isParallax":false,"oneTimeAnimation":false,"duration":1200,"startDistance":200,"startVisibility":0.8,"distance":300,"measureDistanceType":3,"delay":0,"distanceDelay":0,"runInLoop":false,"flyDirection":2,"direction":"horizontal","movementDistanceHorizontally":200,"movementDistanceVertically":0,"autoStartDistanceSettings":true,"autoDistanceSettings":true},"effects":null,"binding":null,"innerGlow":{"spread":0,"blur":0,"color":"black"},"innerShadow":{"top":0,"left":0,"spread":0,"blur":0,"color":"black"},"basicUserCanEdit":true,"backgroundColor":"transparent","padding":{"top":0,"left":0,"bottom":0,"right":0},"imageUrl":"","imageLayout":"stretchedToFill","imagePosition":{"vertical":"center","horizontal":"center"},"origImage":"","imageOpacity":1,"backgroundOverlay":"transparent","verticalLayout":"normal","horizontalLayout":"normal","fillLayout":{"fillHorizontal":false,"fillVertical":false},"margin":{"top":0,"left":0,"bottom":0,"right":0},"isVisible":true,"borderWidth":{"top":0,"left":0,"bottom":0,"right":0},"roundness":{"topLeft":0,"bottomLeft":0,"topRight":0,"bottomRight":0},"borderColor":{"top":"Black","left":"Black","bottom":"Black","right":"Black"},"borderStyle":{"top":"solid","left":"solid","bottom":"solid","right":"solid"},"rotationAngle":0,"display":"fixed","cellItem":null,"cellHorizontalAlignment":"none","verticalAlign":"center","horizontalAlign":"center","horizontalContentAlign":"center","embed_html_app1html":"<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>Master Studio Pro | Ray Naso Art</title>\n    <style>\n        :root { --accent: #d4af37; --bg: #0a0a0a; --panel: #1e1e1e; --text: #d0d0d0; --blue-gray: #3a4b5c; --lock: #c0392b; }\n        \n        body { \n            font-family: 'Segoe UI', system-ui, sans-serif; \n            background: var(--bg); \n            color: var(--text); \n            display: flex; \n            height: 100vh; \n            margin: 0; \n            overflow: hidden; \n            width: 100%;\n            box-sizing: border-box;\n        }\n        \n        .sidebar { \n            width: 280px; \n            background: var(--panel); \n            border-right: 1px solid #333; \n            display: flex; \n            flex-direction: column; \n            padding: 15px; \n            gap: 16px; \n            font-size: 11px; \n            overflow-y: auto; \n            overflow-x: hidden; \n            box-sizing: border-box; \n            flex-shrink: 0; \n            transition: width 0.25s ease, padding 0.25s ease, opacity 0.25s ease; \n            height: 100%; \n            opacity: 1;\n            -webkit-overflow-scrolling: touch; \n        }\n        \n        body.fullscreen .sidebar { width: 0; padding: 0; border: none; opacity: 0; pointer-events: none; }\n\n        #fsToast {\n            position: fixed;\n            bottom: 20px;\n            left: 50%;\n            transform: translateX(-50%);\n            background: rgba(0, 0, 0, 0.85);\n            color: var(--accent);\n            padding: 8px 16px;\n            border-radius: 20px;\n            font-size: 10px;\n            font-weight: bold;\n            letter-spacing: 1px;\n            z-index: 4000;\n            pointer-events: none;\n            border: 1px solid var(--accent);\n            opacity: 0;\n            transition: opacity 0.3s ease;\n            text-transform: uppercase;\n        }\n        body.fullscreen #fsToast { opacity: 1; }\n\n        #exitFS { position: fixed; top: 15px; right: 15px; z-index: 4000; padding: 8px 16px; background: var(--accent); color: #000; border: none; border-radius: 4px; font-weight: bold; cursor: pointer; box-shadow: 0 4px 15px rgba(0,0,0,0.5); font-size: 11px; text-transform: uppercase; display: none; }\n        body.fullscreen #exitFS { display: block; }\n\n        .studio-header { cursor: pointer; border-bottom: 1px solid #333; padding-bottom: 8px; margin-bottom: 5px; flex-shrink: 0; }\n        h2 { font-size: 0.95rem; margin: 0; color: var(--accent); text-transform: uppercase; letter-spacing: 1px; outline: none; }\n        \n        .section { display: flex; flex-direction: column; gap: 6px; border-bottom: 1px solid #2a2a2a; padding-bottom: 12px; flex-shrink: 0; }\n        label { text-transform: uppercase; font-weight: bold; color: #777; font-size: 9px; margin-top: 2px; display: block; }\n        \n        input, button { background: #2a2a2a; border: 1px solid #444; color: white; padding: 7px; border-radius: 3px; font-size: 11px; outline: none; box-sizing: border-box; width: 100%; height: auto; }\n        \n        input[type=\"range\"] { accent-color: var(--accent); cursor: pointer; height: 18px; touch-action: none; display: block; }\n\n        .stats-box { background: rgba(0,0,0,0.4); padding: 8px; border-radius: 4px; border: 1px solid #333; margin-top: 5px; font-family: monospace; color: var(--accent); text-align: center; box-sizing: border-box; }\n\n        .btn { cursor: pointer; font-weight: bold; text-transform: uppercase; border: none; transition: 0.2s; box-sizing: border-box; }\n        .btn-main { background: var(--accent); color: #000; padding: 12px; margin-top: 10px; flex-shrink: 0; }\n        .btn-sub { background: var(--blue-gray); color: #fff; padding: 7px; flex: 1; }\n        .btn-sub.active { background: var(--accent); color: #000; }\n        .btn-lock.active { background: var(--accent); color: #000; border: 1px solid #fff; }\n        \n        .btn-zoom {\n            background-color: #2a2a2a;\n            border: 1px solid #555;\n            color: #fff;\n            padding: 10px;\n            font-size: 12px;\n            font-weight: 700;\n            letter-spacing: 0.5px;\n            margin-top: 5px;\n            border-radius: 4px;\n        }\n        .btn-zoom:active { background-color: var(--accent); color: #000; border-color: var(--accent); }\n\n        #welcomeModal, #zoomModal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.85); z-index: 5000; display: flex; justify-content: center; align-items: center; }\n        #zoomModal { display: none; z-index: 6000; }\n        \n        .modal-content { background: var(--panel); padding: 30px; border: 1px solid var(--accent); border-radius: 8px; text-align: center; max-width: 400px; width: 85%; }\n        .zoom-modal-content { background: var(--panel); padding: 25px; border: 1px solid var(--accent); border-radius: 8px; text-align: center; max-width: 500px; width: 90%; }\n\n        #viewport { \n            flex-grow: 1; \n            display: flex; \n            justify-content: center; \n            align-items: center; \n            background: #111; \n            position: relative; \n            overflow: auto; \n            cursor: crosshair; \n            height: 100%;\n            touch-action: none; \n            -webkit-overflow-scrolling: auto;\n        }\n        \n        canvas { \n            background: #fff; \n            box-shadow: 0 0 60px rgba(0,0,0,0.8); \n            margin: auto; \n            max-width: 95%; \n            max-height: 95%;\n            object-fit: contain;\n            will-change: filter;\n        }\n\n        #zoomCanvas { background: #fff; border: 1px solid #444; max-width: 100%; }\n\n        @media (max-width: 1024px) {\n            .sidebar { width: 290px; gap: 14px; }\n            input[type=\"number\"], button, .btn-sub { padding: 9px 6px; }\n        }\n    </style>\n</head>\n<body>\n\n<button id=\"exitFS\" onclick=\"toggleFullScreen()\">Minimize Menu</button>\n<div id=\"fsToast\">Double Tap Canvas to return Menu</div>\n\n<div id=\"welcomeModal\">\n    <div class=\"modal-content\">\n        <h1 style=\"color:var(--accent); font-size: 1.2rem; margin-top:0;\">RAY NASO PRECISION ART GRID</h1>\n        <p style=\"font-size: 13px; color: #bbb; line-height: 1.5;\">Studio Edition Ready.<br><br>Click \"Maximize View\" to fill the screen instantly. Double-tap to exit.</p>\n        <button class=\"btn btn-main\" style=\"width:100%\" onclick=\"closeWelcomeModal()\">Enter Studio</button>\n    </div>\n</div>\n\n<div id=\"zoomModal\">\n    <div class=\"zoom-modal-content\">\n        <h2 id=\"zoomTitle\" style=\"margin-top: 0; margin-bottom: 15px;\">Detailed View</h2>\n        <canvas id=\"zoomCanvas\" width=\"450\" height=\"450\"></canvas>\n        <div style=\"display: flex; gap: 10px; justify-content: center; align-items: center; margin-top: 15px;\">\n            <label style=\"font-size: 10px;\">Sub-grid divisions</label>\n            <input type=\"number\" id=\"subGridDivs\" value=\"5\" min=\"2\" max=\"10\" style=\"width: 50px; text-align: center;\" onchange=\"updateZoomedGrid()\">\n            <button class=\"btn btn-sub\" onclick=\"closeZoomModal()\" style=\"padding: 6px 15px;\">Close View</button>\n        </div>\n    </div>\n</div>\n\n<div class=\"sidebar\">\n    <div class=\"studio-header\">\n        <h2 id=\"displayTitle\" contenteditable=\"true\" spellcheck=\"false\" oninput=\"saveAppState()\">Ray Naso Precision Art Grid</h2>\n        <span style=\"font-size:8px; color:#555;\">CLICK TO EDIT TITLE</span>\n    </div>\n    \n    <div class=\"section\">\n        <label>1. Image Source</label>\n        <input type=\"file\" id=\"upload\" accept=\"image/*\">\n    </div>\n\n    <div class=\"section\">\n        <label>2. Canvas Setup</label>\n        <div style=\"display:grid; grid-template-columns: 1fr 1fr 1fr; gap:8px;\">\n            <div><label style=\"font-size:8px;\">WIDTH</label><input type=\"number\" id=\"canvW\" value=\"20\" oninput=\"appSettingChanged()\"></div>\n            <div><label style=\"font-size:8px;\">HEIGHT</label><input type=\"number\" id=\"canvH\" value=\"16\" oninput=\"appSettingChanged()\"></div>\n            <div><label style=\"font-size:8px;\">COLUMNS</label><input type=\"number\" id=\"cols\" value=\"10\" oninput=\"appSettingChanged()\"></div>\n        </div>\n        <div class=\"stats-box\" id=\"gridReadout\">GRID: -- x --</div>\n    </div>\n\n    <div class=\"section\">\n        <label>3. Appearance</label>\n        <label>Thickness</label>\n        <input type=\"range\" id=\"thickness\" min=\"1\" max=\"5\" step=\"1\" value=\"1\" oninput=\"appSettingChanged()\">\n        <label>Grid Color</label>\n        <input type=\"color\" id=\"gridColor\" value=\"#000000\" oninput=\"appSettingChanged()\" style=\"height:32px; padding:0; cursor:pointer; border:none;\">\n    </div>\n\n    <div class=\"section\">\n        <label>4. Zoom & Panning</label>\n        <input type=\"range\" id=\"zoom\" min=\"0.1\" max=\"4\" step=\"0.01\" value=\"1\" oninput=\"appSettingChanged()\">\n        <div style=\"display:flex; flex-direction:column; gap:6px; margin-top:5px;\">\n            <div style=\"display:flex; gap:6px;\">\n                <button class=\"btn btn-sub\" style=\"background: var(--blue-gray);\" onclick=\"autoCenterAndFit(); saveAppState();\">Auto Fit</button>\n                <button id=\"lockBtn\" class=\"btn btn-sub\" onclick=\"toggleLock()\">Lock Pan</button>\n                <button class=\"btn btn-sub\" onclick=\"resetAll(); saveAppState();\">Reset</button>\n            </div>\n            <button id=\"mobileZoomBtn\" class=\"btn-zoom btn\" onclick=\"toggleFullScreen()\">Maximize View</button>\n        </div>\n    </div>\n\n    <div class=\"section\">\n        <label>5. Artistic Filters</label>\n        <div style=\"display:flex; gap:5px;\">\n            <button id=\"bwBtn\" class=\"btn btn-sub\" onclick=\"toggleFilter('grayscale')\">B&W</button>\n            <button id=\"thirdsBtn\" class=\"btn btn-sub\" onclick=\"toggleFilter('thirds')\">3rds</button>\n        </div>\n        <label>The Squint (Blur)</label>\n        <input type=\"range\" id=\"blur\" min=\"0\" max=\"15\" value=\"0\" oninput=\"appSettingChanged()\">\n        <div style=\"display:flex; gap:5px;\">\n            <button class=\"btn btn-sub\" onclick=\"toggleFlip('h')\">Flip H</button>\n            <button class=\"btn btn-sub\" onclick=\"toggleFlip('v')\">Flip V</button>\n        </div>\n    </div>\n\n    <button class=\"btn btn-main\" onclick=\"downloadImage()\">Save Reference</button>\n</div>\n\n<div id=\"viewport\">\n    <canvas id=\"mainCanvas\"></canvas>\n</div>\n\n<script>\n    const canvas = document.getElementById('mainCanvas');\n    const ctx = canvas.getContext('2d');\n    let img = new Image();\n    let moveX = 0, moveY = 0, flipH = 1, flipV = 1, isLocked = false;\n    let isDragging = false, startX, startY;\n    let filters = { grayscale: false, thirds: false };\n    let activeCol = 0, activeRow = 0;\n\n    window.addEventListener('DOMContentLoaded', () => {\n        img.crossOrigin = \"anonymous\";\n        \n        const savedImage = localStorage.getItem('precision_img_src');\n        if (savedImage) {\n            img.src = savedImage;\n        } else {\n            img.src = \"https://storage.googleapis.com/production-homestead-v1-0-0/170/2018170/S9EXuCtN/e078bfaf032240608319f111a5c9d078\";\n        }\n\n        const returningUser = localStorage.getItem('precision_returning_session');\n        if (returningUser) {\n            document.getElementById('welcomeModal').style.display = 'none';\n        }\n    });\n\n    img.onload = function() {\n        if (!localStorage.getItem('precision_app_state')) {\n            resetAll();\n            autoCenterAndFit();\n        } else {\n            loadAppState();\n        }\n    };\n\n    function closeWelcomeModal() {\n        document.getElementById('welcomeModal').style.display = 'none';\n        localStorage.setItem('precision_returning_session', 'true');\n    }\n\n    function saveAppState() {\n        const state = {\n            title: document.getElementById('displayTitle').innerText,\n            canvW: document.getElementById('canvW').value,\n            canvH: document.getElementById('canvH').value,\n            cols: document.getElementById('cols').value,\n            thickness: document.getElementById('thickness').value,\n            gridColor: document.getElementById('gridColor').value,\n            zoom: document.getElementById('zoom').value,\n            blur: document.getElementById('blur').value,\n            moveX: moveX,\n            moveY: moveY,\n            flipH: flipH,\n            flipV: flipV,\n            grayscale: filters.grayscale,\n            thirds: filters.thirds\n        };\n        localStorage.setItem('precision_app_state', JSON.stringify(state));\n    }\n\n    function loadAppState() {\n        const savedState = localStorage.getItem('precision_app_state');\n        if (!savedState) { drawAll(); return; }\n        \n        const state = JSON.parse(savedState);\n        \n        document.getElementById('displayTitle').innerText = state.title || \"Ray Naso Precision Art Grid\";\n        document.getElementById('canvW').value = state.canvW;\n        document.getElementById('canvH').value = state.canvH;\n        document.getElementById('cols').value = state.cols;\n        document.getElementById('thickness').value = state.thickness;\n        document.getElementById('gridColor').value = state.gridColor;\n        document.getElementById('zoom').value = state.zoom;\n        document.getElementById('blur').value = state.blur;\n        \n        moveX = state.moveX || 0;\n        moveY = state.moveY || 0;\n        flipH = state.flipH || 1;\n        flipV = state.flipV || 1;\n        \n        filters.grayscale = state.grayscale || false;\n        filters.thirds = state.thirds || false;\n\n        document.getElementById('bwBtn').classList.toggle('active', filters.grayscale);\n        document.getElementById('thirdsBtn').classList.toggle('active', filters.thirds);\n        \n        drawAll();\n    }\n\n    function appSettingChanged() {\n        drawAll();\n        saveAppState();\n    }\n\n    function toggleFullScreen() {\n        document.body.classList.toggle('fullscreen');\n        setTimeout(drawAll, 260);\n    }\n\n    function toggleLock() {\n        isLocked = !isLocked;\n        document.getElementById('lockBtn').classList.toggle('active');\n        document.getElementById('viewport').style.cursor = isLocked ? \"not-allowed\" : \"crosshair\";\n    }\n\n    document.getElementById('upload').addEventListener('change', (e) => {\n        const reader = new FileReader();\n        reader.onload = (ev) => {\n            img = new Image();\n            img.onload = () => { \n                resetAll(); \n                autoCenterAndFit(); \n                try {\n                    localStorage.setItem('precision_img_src', ev.target.result);\n                } catch(err) {\n                    console.log(\"Image exceeds local storage limits.\");\n                }\n                saveAppState();\n            };\n            img.src = ev.target.result;\n        };\n        reader.readAsDataURL(e.target.files[0]);\n    });\n\n    const vp = document.getElementById('viewport');\n    function startDrag(clientX, clientY) { if(isLocked) return; isDragging = true; startX = clientX - moveX; startY = clientY - moveY; }\n    function moveDrag(clientX, clientY) { if(!isDragging || isLocked) return; moveX = clientX - startX; moveY = clientY - startY; drawAll(); }\n    \n    vp.addEventListener('mousedown', (e) => startDrag(e.clientX, e.clientY));\n    window.addEventListener('mousemove', (e) => moveDrag(e.clientX, e.clientY));\n    window.addEventListener('mouseup', () => { if(isDragging) { isDragging = false; saveAppState(); } });\n\n    vp.addEventListener('touchstart', (e) => {\n        if (e.touches.length === 1) {\n            if(!isLocked) e.preventDefault(); \n            startDrag(e.touches[0].clientX, e.touches[0].clientY);\n        }\n    }, { passive: false });\n\n    vp.addEventListener('touchmove', (e) => {\n        if (e.touches.length === 1) {\n            if(!isLocked) e.preventDefault();\n            moveDrag(e.touches[0].clientX, e.touches[0].clientY);\n        }\n    }, { passive: false });\n\n    vp.addEventListener('touchend', () => { if(isDragging) { isDragging = false; saveAppState(); } });\n\n    let lastTap = 0;\n    vp.addEventListener('touchend', (e) => {\n        const currentTime = new Date().getTime();\n        const tapLength = currentTime - lastTap;\n        \n        if (tapLength < 280 && tapLength > 0) {\n            e.preventDefault();\n            \n            if (document.body.classList.contains('fullscreen')) {\n                toggleFullScreen();\n            } else {\n                const rect = canvas.getBoundingClientRect();\n                const x = e.changedTouches[0].clientX - rect.left;\n                const y = e.changedTouches[0].clientY - rect.top;\n                const padVal = document.body.classList.contains('fullscreen') ? 40 : 60;\n                \n                const cw = parseFloat(document.getElementById('canvW').value) || 1;\n                const ch = parseFloat(document.getElementById('canvH').value) || 1;\n                const colInput = document.getElementById('cols').value;\n                const cols = (colInput === \"\" || parseInt(colInput) === 0) ? 0 : parseInt(colInput);\n                \n                if (cols === 0) return; \n\n                const scale = Math.min((vp.offsetWidth - padVal * 2.2) / cw, (vp.offsetHeight - padVal * 2.2) / ch);\n                const dW = cw * scale, dH = ch * scale;\n                const step = dW / cols;\n\n                if (x >= padVal && x <= padVal + dW && y >= padVal && y <= padVal + dH) {\n                    activeCol = Math.floor((x - padVal) / step);\n                    activeRow = Math.floor((y - padVal) / step);\n                    showZoomedGrid();\n                }\n            }\n        }\n        lastTap = currentTime;\n    });\n\n    vp.addEventListener('dblclick', (e) => {\n        if (document.body.classList.contains('fullscreen')) {\n            toggleFullScreen();\n            return;\n        }\n        const rect = canvas.getBoundingClientRect();\n        const x = e.clientX - rect.left;\n        const y = e.clientY - rect.top;\n        const padVal = 60;\n        const cw = parseFloat(document.getElementById('canvW').value) || 1;\n        const ch = parseFloat(document.getElementById('canvH').value) || 1;\n        const colInput = document.getElementById('cols').value;\n        const cols = (colInput === \"\" || parseInt(colInput) === 0) ? 0 : parseInt(colInput);\n        \n        if (cols === 0) return; \n\n        const scale = Math.min((vp.offsetWidth - padVal * 2.2) / cw, (vp.offsetHeight - padVal * 2.2) / ch);\n        const dW = cw * scale, dH = ch * scale;\n        const step = dW / cols;\n\n        if (x >= padVal && x <= padVal + dW && y >= padVal && y <= padVal + dH) {\n            activeCol = Math.floor((x - padVal) / step);\n            activeRow = Math.floor((y - padVal) / step);\n            showZoomedGrid();\n        }\n    });\n\n    function showZoomedGrid() {\n        const letter = String.fromCharCode(65 + activeCol);\n        document.getElementById('zoomTitle').innerText = `Detailed View: Square ${letter}${activeRow + 1}`;\n        document.getElementById('zoomModal').style.display = 'flex';\n        drawZoomedCanvas();\n    }\n\n    function closeZoomModal() { document.getElementById('zoomModal').style.display = 'none'; }\n    function updateZoomedGrid() { drawZoomedCanvas(); }\n\n    function drawZoomedCanvas() {\n        const zoomCanvas = document.getElementById('zoomCanvas');\n        const zCtx = zoomCanvas.getContext('2d');\n        const padVal = document.body.classList.contains('fullscreen') ? 40 : 60;\n        \n        const cw = parseFloat(document.getElementById('canvW').value) || 1;\n        const ch = parseFloat(document.getElementById('canvH').value) || 1;\n        const colInput = document.getElementById('cols').value;\n        const cols = (colInput === \"\" || parseInt(colInput) === 0) ? 0 : parseInt(colInput);\n        \n        if (cols === 0) return;\n\n        const scale = Math.min((vp.offsetWidth - padVal * 2.2) / cw, (vp.offsetHeight - padVal * 2.2) / ch);\n        const dW = cw * scale, dH = ch * scale;\n        const step = dW / cols;\n\n        const tempCanvas = document.createElement('canvas');\n        tempCanvas.width = canvas.width;\n        tempCanvas.height = canvas.height;\n        const tempCtx = tempCanvas.getContext('2d');\n\n        tempCtx.fillStyle = \"#111\"; tempCtx.fillRect(0, 0, tempCanvas.width, tempCanvas.height);\n        tempCtx.save();\n        tempCtx.beginPath(); tempCtx.rect(padVal, padVal, dW, dH); tempCtx.clip();\n\n        const centerX = padVal + (dW / 2) + moveX, centerY = padVal + (dH / 2) + moveY;\n        tempCtx.translate(centerX, centerY); tempCtx.scale(flipH, flipV); tempCtx.translate(-centerX, -centerY);\n\n        const imgRatio = img.width / img.height, canvasRatio = cw / ch;\n        let iW = (imgRatio > canvasRatio) ? dW : dH * imgRatio, iH = (imgRatio > canvasRatio) ? dW / imgRatio : dH;\n        const zoomVal = parseFloat(document.getElementById('zoom').value);\n\n        tempCtx.drawImage(img, centerX - (iW * zoomVal)/2, centerY - (iH * zoomVal)/2, iW * zoomVal, iH * zoomVal);\n        \n        if (filters.grayscale) {\n            try {\n                let imgData = tempCtx.getImageData(padVal, padVal, dW, dH);\n                for (let i = 0; i < imgData.data.length; i += 4) {\n                    let gray = 0.3 * imgData.data[i] + 0.59 * imgData.data[i + 1] + 0.11 * imgData.data[i + 2];\n                    imgData.data[i] = imgData.data[i + 1] = imgData.data[i + 2] = gray;\n                }\n                tempCtx.putImageData(imgData, padVal, padVal);\n            } catch(e) {}\n        }\n        tempCtx.restore();\n\n        const sX = padVal + activeCol * step;\n        const sY = padVal + activeRow * step;\n\n        zCtx.fillStyle = \"#fff\"; zCtx.fillRect(0, 0, zoomCanvas.width, zoomCanvas.height);\n        zCtx.drawImage(tempCanvas, sX, sY, step, step, 0, 0, zoomCanvas.width, zoomCanvas.height);\n\n        const divisions = parseInt(document.getElementById('subGridDivs').value) || 5;\n        const zStep = zoomCanvas.width / divisions;\n        zCtx.strokeStyle = document.getElementById('gridColor').value;\n        zCtx.lineWidth = document.getElementById('thickness').value || 1;\n\n        for (let i = 0; i <= divisions; i++) {\n            let pos = i * zStep;\n            zCtx.beginPath(); zCtx.moveTo(pos, 0); zCtx.lineTo(pos, zoomCanvas.height); zCtx.stroke();\n            zCtx.beginPath(); zCtx.moveTo(0, pos); zCtx.lineTo(zoomCanvas.width, pos); zCtx.stroke();\n        }\n    }\n\n    function drawAll() {\n        if (!img.src) return;\n        \n        const colInput = document.getElementById('cols').value;\n        const cols = (colInput === \"\" || parseInt(colInput) === 0) ? 0 : parseInt(colInput);\n        \n        const cw = parseFloat(document.getElementById('canvW').value) || 20;\n        const ch = parseFloat(document.getElementById('canvH').value) || 16;\n        const zoom = parseFloat(document.getElementById('zoom').value);\n        const pad = document.body.classList.contains('fullscreen') ? 40 : 60;\n        const rowCount = cols > 0 ? Math.ceil(ch / (cw / cols)) : 0;\n        \n        if (cols === 0) {\n            document.getElementById('gridReadout').innerText = `GRID: OFF`;\n        } else {\n            document.getElementById('gridReadout').innerText = `GRID: ${cols} x ${rowCount}`;\n        }\n\n        let vw = vp.offsetWidth || 800;\n        let vh = vp.offsetHeight || 600;\n        const scale = Math.min((vw - pad * 2.2) / cw, (vh - pad * 2.2) / ch);\n        const dW = cw * scale, dH = ch * scale;\n\n        canvas.width = dW + pad * 2; canvas.height = dH + pad * 2;\n\n        ctx.fillStyle = \"#111\"; ctx.fillRect(0, 0, canvas.width, canvas.height);\n        \n        const blur = document.getElementById('blur').value;\n        canvas.style.filter = blur > 0 ? `blur(${blur}px)` : 'none';\n        canvas.style.webkitFilter = blur > 0 ? `blur(${blur}px)` : 'none';\n\n        ctx.save();\n        ctx.beginPath(); ctx.rect(pad, pad, dW, dH); ctx.clip();\n\n        const cX = pad + dW / 2 + moveX, cY = pad + dH / 2 + moveY;\n        ctx.translate(cX, cY); ctx.scale(flipH, flipV); ctx.translate(-cX, -cY);\n\n        const ratio = img.width / img.height, cRatio = cw / ch;\n        let iW = (ratio > cRatio) ? dW : dH * ratio, iH = (ratio > cRatio) ? dW / ratio : dH;\n        ctx.drawImage(img, cX - (iW * zoom) / 2, cY - (iH * zoom) / 2, iW * zoom, iH * zoom);\n\n        if (filters.grayscale) {\n            try {\n                let d = ctx.getImageData(pad, pad, dW, dH);\n                for (let i = 0; i < d.data.length; i += 4) {\n                    let g = 0.3 * d.data[i] + 0.59 * d.data[i+1] + 0.11 * d.data[i+2];\n                    d.data[i] = d.data[i+1] = d.data[i+2] = g;\n                }\n                ctx.putImageData(d, pad, pad);\n            } catch(e) {}\n        }\n        ctx.restore();\n\n        if (cols > 0) {\n            const step = dW / cols;\n            ctx.strokeStyle = document.getElementById('gridColor').value;\n            ctx.lineWidth = document.getElementById('thickness').value;\n            \n            for (let i = 0; i <= cols; i++) {\n                let x = pad + i * step;\n                ctx.beginPath(); ctx.moveTo(x, pad); ctx.lineTo(x, pad + dH); ctx.stroke();\n            }\n            for (let j = 0; j <= rowCount; j++) {\n                let y = pad + j * step;\n                if (y <= pad + dH + 1) {\n                    ctx.beginPath(); ctx.moveTo(pad, y); ctx.lineTo(pad + dW, y); ctx.stroke();\n                }\n            }\n\n            ctx.fillStyle = \"#fff\"; ctx.font = \"bold 14px sans-serif\"; ctx.textAlign = \"center\";\n            for (let i = 0; i < cols; i++) ctx.fillText(String.fromCharCode(65+i), pad + i*step + step/2, pad - 12);\n            ctx.textAlign = \"right\"; ctx.textBaseline = \"middle\";\n            for (let j = 0; j < rowCount; j++) ctx.fillText(j+1, pad - 12, pad + j*step + step/2);\n        }\n\n        if (filters.thirds) {\n            ctx.strokeStyle = \"red\"; ctx.lineWidth = 1; ctx.setLineDash([5, 5]);\n            for(let t=1; t<=2; t++) {\n                ctx.beginPath(); ctx.moveTo(pad + (dW/3)*t, pad); ctx.lineTo(pad + (dW/3)*t, pad+dH); ctx.stroke();\n                ctx.beginPath(); ctx.moveTo(pad, pad + (dH/3)*t); ctx.lineTo(pad+dW, pad + (dH/3)*t); ctx.stroke();\n            }\n            ctx.setLineDash([]);\n        }\n    }\n\n    function toggleFlip(dir) { \n        if(dir === 'h') flipH *= -1; else flipV *= -1; \n        appSettingChanged(); \n    }\n    \n    function toggleFilter(f) { \n        filters[f] = !filters[f]; \n        document.getElementById(f === 'grayscale' ? 'bwBtn' : 'thirdsBtn').classList.toggle('active');\n        appSettingChanged(); \n    }\n    \n    function resetAll() { \n        moveX = 0; moveY = 0; flipH = 1; flipV = 1; filters.grayscale = false; filters.thirds = false;\n        document.getElementById('zoom').value = 1; document.getElementById('blur').value = 0;\n        document.querySelectorAll('.active').forEach(b => b.classList.remove('active'));\n        drawAll(); \n    }\n    \n    function autoCenterAndFit() {\n        const cw = parseFloat(document.getElementById('canvW').value), ch = parseFloat(document.getElementById('canvH').value);\n        if(!img.width) return;\n        const r = (img.width/img.height) / (cw/ch);\n        document.getElementById('zoom').value = r > 1 ? r : 1/r;\n        drawAll();\n    }\n    \n    function downloadImage() {\n        const link = document.createElement('a');\n        link.download = 'RayNaso_Reference.jpg';\n        link.href = canvas.toDataURL('image/jpeg', 0.9);\n        link.click();\n    }\n    \n    window.addEventListener('resize', drawAll);\n</script>\n</body>\n</html>","embed_html_app1headerHtml":""},"metaData":{"position":{"left":-480,"top":120.99609375},"size":{"width":960,"height":600}}},{"type":"image","id":"id1779724153421","elementProperties":{"tagName":"DIV","behaviours":null,"isLocked":false,"name":"Image 6","baseName":null,"templateID":"templateid1779724153422","templateName":null,"order":33,"customStates":null,"isElementWasEditedInMode":false,"showHoverEffects":true,"skinInformation":{},"isSupportsMobile":false,"isVisibleInMode":true,"isFixed":false,"topZIndex":0,"elementOpacity":1,"staticMargin":{"horizontalMargin":0,"verticalMargin":0},"sizeAndPosition":{"width":102,"height":143,"left":-185,"top":652},"lastResizingSize":{"width":102,"height":143},"isVisibleInLastSection":true,"isVisibleInLastDataItem":true,"attributes":null,"metaProps":null,"metaItemType":null,"metaTitle":null,"styleBindingId":null,"styleBindingFields":null,"shadow":{"top":0,"left":0,"spread":0,"blur":0,"color":"black"},"glow":{"spread":0,"blur":0,"color":"black"},"isParallaxBackground":false,"parallaxBackgroundSpeed":0.5,"isParallaxElement":{"isActive":false,"speed":1,"delay":0},"effectsOptions":{"isParallax":false,"oneTimeAnimation":false,"duration":1200,"startDistance":200,"startVisibility":0.8,"distance":300,"measureDistanceType":3,"delay":0,"distanceDelay":0,"runInLoop":false,"flyDirection":2,"direction":"horizontal","movementDistanceHorizontally":200,"movementDistanceVertically":0,"autoStartDistanceSettings":true,"autoDistanceSettings":true},"effects":null,"binding":null,"innerGlow":{"spread":0,"blur":0,"color":"black"},"innerShadow":{"top":0,"left":0,"spread":0,"blur":0,"color":"black"},"display":"fixed","cellItem":null,"cellHorizontalAlignment":"none","basicUserCanEdit":true,"isVisible":true,"backgroundColor":"transparent","verticalLayout":"normal","horizontalLayout":"normal","fillLayout":{"fillVertical":false,"fillHorizontal":false},"margin":{"top":0,"left":0,"bottom":0,"right":0},"startSelected":false,"urlAddress":null,"openInNewTab":false,"openInTopWindow":false,"shouldUnderlineChildren":false,"templateOpener":false,"popupType":"DefaultPopup","imageUrl":{"id":154969090,"imagePath":"https://storage.googleapis.com/production-homestead-v1-0-0/170/2018170/S9EXuCtN/e078bfaf032240608319f111a5c9d078","storageServer":0,"imageWidth":928,"imageHeight":1152},"imageLayout":"stretchedToFill","imagePosition":{"vertical":"center","horizontal":"center"},"origImage":"","imageOpacity":1,"borderWidth":{"top":0,"left":0,"bottom":0,"right":0},"roundness":{"topLeft":0,"bottomLeft":0,"topRight":0,"bottomRight":0},"borderColor":{"top":"black","left":"black","bottom":"black","right":"black"},"borderStyle":{"top":"solid","left":"solid","bottom":"solid","right":"solid"},"rotationAngle":0,"backgroundOverlay":"transparent","dataBinding":null,"imageLoadingOverlay":{"background":"rgba(255,255,255,0.7)","imageInfo":{}},"imageLoadingSettings":{"hideImage":false,"showOverlay":false,"overlayBackground":"rgba(255,255,255,0.7)"},"alt":null},"metaData":{"position":{"left":-185,"top":766.9921875},"size":{"width":102,"height":143}}}]}],"offset":{"left":230.99609375,"top":63.984375}}],"connections":{"targetConnections":{},"sourceConnections":{}},"customStatesProperties":{},"pageId":"id1779690236526","version":17.004,"id":"id1779832397820","relativePoint":{"left":230.99609375,"top":63.984375}}