{"id":6,"date":"2025-09-21T09:23:10","date_gmt":"2025-09-21T08:23:10","guid":{"rendered":"http:\/\/localhost\/?page_id=6"},"modified":"2026-03-12T07:55:55","modified_gmt":"2026-03-12T07:55:55","slug":"frostland","status":"publish","type":"page","link":"https:\/\/frostland.se\/","title":{"rendered":""},"content":{"rendered":"\n<!-- START OF AI IMAGE GENERATOR WIDGET -->\n<div id=\"ai-widget-wrapper\" class=\"relative w-full rounded-xl overflow-hidden\" style=\"min-height: 600px; background-color: #000;\">\n\n    <!-- Load Tailwind (Scoped usage) -->\n    <script src=\"https:\/\/cdn.tailwindcss.com\"><\/script>\n\n    <style>\n        \/* Scoped styles for the widget only *\/\n        #ai-widget-wrapper {\n            font-family: sans-serif;\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n        }\n        \n        \/* Smooth fade transition *\/\n        .ai-fade-in {\n            animation: fadeIn 1.5s ease-in-out;\n        }\n        @keyframes fadeIn {\n            from { opacity: 0; }\n            to { opacity: 1; }\n        }\n\n        \/* Scrollbar styling for this specific container *\/\n        #ai-image-container {\n            width: 100%;\n            height: 100%;\n            overflow-y: auto;\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n            padding: 20px 0;\n            gap: 1rem;\n        }\n        \n        \/* Ensure images don't overflow *\/\n        #ai-image-container img {\n            max-width: 95%;\n            border-radius: 8px;\n            box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.5);\n            border: 1px solid #333;\n        }\n    <\/style>\n\n    <!-- Container for images -->\n    <div id=\"ai-image-container\">\n        <!-- New images will appear here -->\n    <\/div>\n\n    <!-- Minimal Spinner (Absolute position within wrapper) -->\n    <div id=\"ai-loader\" class=\"absolute inset-0 flex items-center justify-center bg-black z-10\">\n        <div class=\"w-10 h-10 border-2 border-gray-800 border-t-purple-500 rounded-full animate-spin\"><\/div>\n    <\/div>\n\n    <script>\n        (function() {\n            \/\/ --- Configuration ---\n            const REFRESH_INTERVAL = 20000; \/\/ 60 seconds\n            \n            \/\/ PLACEHOLDER SETTINGS\n            const PLACEHOLDER_PATH = 'https:\/\/frostland.se\/temp\/aiimg\/';\n\n            \/\/ --- Random Data ---\n            const subjects = [\n                \"cyberpunk city\", \"magical forest\", \"astronaut\", \"steampunk robot\", \n                \"underwater kingdom\", \"neon detective\", \"space station\", \n                \"mystical dragon\", \"japanese garden\", \"abstract shapes\", \n                \"floating island\", \"crystal cave\", \"nebula explosion\", \n                \"ancient ruins\", \"futuristic vehicle\"\n            ];\n            \n            const styles = [\n                \"digital art\", \"oil painting\", \"hyper-realistic\", \"synthwave\", \n                \"watercolor\", \"studio ghibli\", \"cinematic\", \"sci-fi\", \"noir\",\n                \"isometric\", \"pencil sketch\", \"pop art\"\n            ];\n\n            const adjectives = [\n                \"glowing\", \"detailed\", \"moody\", \"vibrant\", \"ethereal\", \n                \"dark\", \"colorful\", \"foggy\", \"futuristic\", \"vintage\"\n            ];\n\n            \/\/ Use specific IDs to avoid conflict with other WP plugins\n            const container = document.getElementById('ai-image-container');\n            const loader = document.getElementById('ai-loader');\n\n            function getRandomItem(arr) {\n                return arr[Math.floor(Math.random() * arr.length)];\n            }\n\n            \/\/ Function to fetch directory listing and pick random image\n            async function showInitialPlaceholder() {\n                try {\n                    \/\/ Fetch the directory HTML\n                    const response = await fetch(PLACEHOLDER_PATH);\n                    if (!response.ok) throw new Error(\"Could not access folder\");\n                    \n                    const text = await response.text();\n                    \n                    \/\/ Use Regex to find all href=\"...jpg\" links in the HTML\n                    \/\/ This matches standard Apache\/Nginx directory listings\n                    const regex = \/href=[\"']([^\"']+\\.jpg)[\"']\/gi;\n                    let matches;\n                    const foundImages = [];\n\n                    while ((matches = regex.exec(text)) !== null) {\n                        \/\/ Avoid query parameters or sorting links if any\n                        if (!matches[1].includes('?')) {\n                            foundImages.push(matches[1]);\n                        }\n                    }\n\n                    if (foundImages.length === 0) {\n                        console.warn(\"No .jpg images found in directory listing.\");\n                        return; \n                    }\n\n                    \/\/ Pick random image from the found list\n                    const randomImageName = getRandomItem(foundImages);\n                    const imgUrl = PLACEHOLDER_PATH + randomImageName;\n\n                    \/\/ Display it\n                    const placeholderImg = document.createElement('img');\n                    placeholderImg.src = imgUrl;\n                    placeholderImg.alt = \"Initial Preview\";\n                    placeholderImg.className = \"ai-fade-in\";\n                    \n                    placeholderImg.onload = function() {\n                        if (loader) loader.style.display = 'none';\n                    };\n                    \n                    placeholderImg.onerror = function() {\n                        console.log(\"Failed to load image: \" + imgUrl);\n                    };\n\n                    container.appendChild(placeholderImg);\n\n                } catch (error) {\n                    console.error(\"Error fetching image list:\", error);\n                    \/\/ Fallback or leave loader spinning until AI image arrives\n                }\n            }\n\n            function generateImage() {\n                \/\/ Construct prompt\n                const prompt = `Frosty environment, ${getRandomItem(adjectives)} ${getRandomItem(subjects)}, ${getRandomItem(styles)}, 8k, detailed, wallpaper`;\n                const seed = Math.floor(Math.random() * 1000000);\n                \n                \/\/ Request high res image (1920x1080)\n                const url = `https:\/\/image.pollinations.ai\/prompt\/${encodeURIComponent(prompt)}?width=1920&height=1080&seed=${seed}&nologo=true`;\n\n                \/\/ Load in background first\n                const tempImg = new Image();\n                tempImg.onload = function() {\n                    \/\/ Create new actual DOM element\n                    const newImgDisplay = document.createElement('img');\n                    newImgDisplay.src = url;\n                    newImgDisplay.alt = prompt;\n                    newImgDisplay.className = \"ai-fade-in\"; \n                    \n                    \/\/ Insert at the top (pushing placeholder down)\n                    container.prepend(newImgDisplay);\n                    \n                    \/\/ Ensure loader is hidden (in case placeholder failed)\n                    if (loader && loader.style.display !== 'none') {\n                        loader.style.display = 'none'; \n                    }\n                };\n                tempImg.src = url;\n            }\n\n            \/\/ 1. Show local placeholder immediately (via scanning)\n            showInitialPlaceholder();\n\n            \/\/ 2. Start generating AI image (will appear at top when done)\n            \/\/ generateImage();\n            \n            \/\/ 3. Set interval for future images\n            \/\/ setInterval(generateImage, REFRESH_INTERVAL);\n        })();\n    <\/script>\n<\/div>\n<!-- END OF AI IMAGE GENERATOR WIDGET -->\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-6","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/frostland.se\/index.php\/wp-json\/wp\/v2\/pages\/6","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/frostland.se\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/frostland.se\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/frostland.se\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/frostland.se\/index.php\/wp-json\/wp\/v2\/comments?post=6"}],"version-history":[{"count":12,"href":"https:\/\/frostland.se\/index.php\/wp-json\/wp\/v2\/pages\/6\/revisions"}],"predecessor-version":[{"id":36,"href":"https:\/\/frostland.se\/index.php\/wp-json\/wp\/v2\/pages\/6\/revisions\/36"}],"wp:attachment":[{"href":"https:\/\/frostland.se\/index.php\/wp-json\/wp\/v2\/media?parent=6"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}