{"id":18414,"date":"2022-10-31T17:39:41","date_gmt":"2022-10-31T16:39:41","guid":{"rendered":"https:\/\/cmm.imgw.pl\/?page_id=18414"},"modified":"2026-04-13T14:25:28","modified_gmt":"2026-04-13T12:25:28","slug":"zestawienia-danych-synop","status":"publish","type":"page","link":"https:\/\/cmm.imgw.pl\/?page_id=18414","title":{"rendered":"Zestawienia danych SYNOP"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"18414\" class=\"elementor elementor-18414\">\n\t\t\t\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-c426f89 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"c426f89\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-5f99e89\" data-id=\"5f99e89\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-element elementor-element-bd18b8e elementor-widget elementor-widget-html\" data-id=\"bd18b8e\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<div id=\"summary-switcher-app\" class=\"summary-switcher-app\">\n  <div class=\"switcher-toolbar\" role=\"tablist\" aria-label=\"Wyb\u00f3r zestawienia\">\n    <button class=\"switcher-tab active\" data-view=\"current\" type=\"button\" role=\"tab\" aria-selected=\"true\">Podsumowanie bie\u017c\u0105cego miesi\u0105ca<\/button>\n    <button class=\"switcher-tab\" data-view=\"climate\" type=\"button\" role=\"tab\" aria-selected=\"false\">Statystyka 30-letnia<\/button>\n    <button class=\"switcher-tab\" data-view=\"monthly\" type=\"button\" role=\"tab\" aria-selected=\"false\">Zestawienie miesi\u0119czne<\/button>\n  <\/div>\n\n  <div class=\"switcher-panels\">\n    <div class=\"switcher-panel active\" data-panel=\"current\" role=\"tabpanel\">\n      <iframe class=\"panel-frame\" title=\"biez_podsumowanie\" loading=\"eager\" tabindex=\"-1\"><\/iframe>\n    <\/div>\n    <div class=\"switcher-panel\" data-panel=\"monthly\" role=\"tabpanel\" hidden>\n      <iframe class=\"panel-frame\" title=\"zestawienie_mies\" loading=\"lazy\" tabindex=\"-1\"><\/iframe>\n    <\/div>\n    <div class=\"switcher-panel\" data-panel=\"climate\" role=\"tabpanel\" hidden>\n      <iframe class=\"panel-frame\" title=\"statystyka_30lat\" loading=\"lazy\" tabindex=\"-1\"><\/iframe>\n    <\/div>\n  <\/div>\n\n  <textarea id=\"template-current\" class=\"embedded-template\" hidden>\n&lt;div id=\"forecast-app\" class=\"forecast-app current-month-app\"&gt;\n\t&lt;div class=\"layout-container\"&gt;\n\t\t&lt;div class=\"left-column\"&gt;\n\t\t\t&lt;div class=\"section\"&gt;\n\t\t\t\t&lt;h3&gt;Podsumowanie:&lt;\/h3&gt;\n\t\t\t\t&lt;div id=\"modeButtons\" class=\"buttons mode-buttons\"&gt;&lt;\/div&gt;\n\t\t\t&lt;\/div&gt;\n\n\t\t\t&lt;div class=\"section\"&gt;\n\t\t\t\t&lt;h3&gt;Charakterystyka:&lt;\/h3&gt;\n\t\t\t\t&lt;div id=\"paramButtons\" class=\"buttons params-buttons\"&gt;&lt;\/div&gt;\n\t\t\t&lt;\/div&gt;\n\n\t\t\t&lt;div class=\"keyboard-info\"&gt;\n\t\t\t\t&lt;strong&gt;\ud83d\udca1 Skr\u00f3ty klawiszowe:&lt;\/strong&gt;&lt;br&gt;\n\t\t\t\t1-2 wyb\u00f3r widoku&lt;br&gt;\n\t\t\t\t\u2191, \u2193 zmiana charakterystyki&lt;br&gt;\n\t\t\t\t&amp;lt; &amp;gt; zmiana karty g\u0142\u00f3wnej\n\t\t\t&lt;\/div&gt;\n\t\t&lt;\/div&gt;\n\n\t\t&lt;div class=\"right-column\"&gt;\n\t\t\t&lt;div class=\"section images\"&gt;\n\t\t\t\t&lt;div id=\"loader\" class=\"loader-container\" style=\"display: none;\"&gt;\n\t\t\t\t\t&lt;div class=\"loader\"&gt;&lt;\/div&gt;\n\t\t\t\t&lt;\/div&gt;\n\n\t\t\t\t&lt;div id=\"images\" class=\"images-grid\"&gt;&lt;\/div&gt;\n\t\t\t\t&lt;div id=\"noData\" class=\"date-warning\"&gt;Brak dost\u0119pnej mapy dla wybranego zestawu.&lt;\/div&gt;\n\t\t\t&lt;\/div&gt;\n\t\t&lt;\/div&gt;\n\t&lt;\/div&gt;\n&lt;\/div&gt;\n\n&lt;style&gt;\n\t.forecast-app {\n\t\tfont-family: Arial, sans-serif;\n\t\tmax-width: 1200px;\n\t\tmargin: 0 auto;\n\t}\n\n\t.layout-container {\n\t\tdisplay: flex;\n\t\tflex-wrap: wrap;\n\t\tgap: 10px;\n\t}\n\n\t.left-column {\n\t\tflex: 1;\n\t\tmin-width: 260px;\n\t\tmax-width: 300px;\n\t}\n\n\t.right-column {\n\t\tflex: 2;\n\t\tmin-width: 400px;\n\t}\n\n\t.section {\n\t\tmargin-bottom: 12px;\n\t\tbackground: #f9f9f9;\n\t\tpadding: 10px;\n\t\tborder-radius: 8px;\n\t\tbox-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n\t}\n\n\t.section h3 {\n\t\tmargin-top: 0;\n\t\tmargin-bottom: 6px;\n\t\tborder-bottom: 1px solid #ddd;\n\t\tpadding-bottom: 5px;\n\t\tcolor: #333;\n\t}\n\n\t.buttons {\n\t\tdisplay: flex;\n\t\tflex-wrap: wrap;\n\t\tgap: 6px;\n\t\tmargin-top: 4px;\n\t}\n\n\t.buttons button {\n\t\tpadding: 8px 10px;\n\t\tmin-width: 45px;\n\t\tborder: 1px solid #666;\n\t\tborder-radius: 8px;\n\t\tbackground: #f5f5f5;\n\t\tcursor: pointer;\n\t\ttransition: all 0.2s;\n\t\tfont-size: 0.9em;\n\t\tfont-weight: 600;\n\t}\n\n\t.buttons button:hover {\n\t\tbackground: #e3f5f3;\n\t\tborder-color: rgba(86, 221, 208, 1);\n\t}\n\n\t.buttons button.active {\n\t\tbackground: rgba(86, 221, 208, 1);\n\t\tborder-color: rgba(56, 191, 178, 1);\n\t\tcolor: #fff;\n\t}\n\n\t.mode-buttons,\n\t.params-buttons {\n\t\tdisplay: grid;\n\t\tgrid-template-columns: 1fr;\n\t\tgap: 8px;\n\t}\n\n\t.mode-buttons button,\n\t.params-buttons button {\n\t\twidth: 100%;\n\t\ttext-align: center;\n\t}\n\n\t.images-grid {\n\t\tdisplay: grid;\n\t\tgrid-template-columns: 1fr;\n\t\tgap: 14px;\n\t\tmin-height: 420px;\n\t}\n\n\t.image-card {\n\t\tmargin: 0;\n\t\tborder: 1px solid #ddd;\n\t\tborder-radius: 8px;\n\t\tpadding: 8px;\n\t\tbackground: #fff;\n\t\tbox-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);\n\t}\n\n\t.image-card img {\n\t\twidth: 100%;\n\t\theight: auto;\n\t\tdisplay: block;\n\t\tborder-radius: 5px;\n\t}\n\n\t.loader-container {\n\t\tdisplay: flex;\n\t\tjustify-content: center;\n\t\talign-items: center;\n\t\tflex-direction: column;\n\t\twidth: 100%;\n\t\theight: 300px;\n\t\tz-index: 100;\n\t\tposition: relative;\n\t\tbackground-color: rgba(245, 245, 245, 0.7);\n\t\tborder-radius: 8px;\n\t\tmargin-bottom: 10px;\n\t}\n\n\t.loader {\n\t\tborder: 12px solid #f3f3f3;\n\t\tborder-radius: 50%;\n\t\tborder-top: 12px solid rgba(86, 221, 208, 1);\n\t\twidth: 90px;\n\t\theight: 90px;\n\t\tanimation: spin 0.8s linear infinite;\n\t\tbox-shadow: 0 0 20px rgba(86, 221, 208, 0.7);\n\t}\n\n\t@keyframes spin {\n\t\t0% { transform: rotate(0deg); }\n\t\t100% { transform: rotate(360deg); }\n\t}\n\n\t.date-warning {\n\t\tdisplay: none;\n\t\ttext-align: center;\n\t\tpadding: 8px 15px;\n\t\tbackground: rgba(255, 152, 0, 0.1);\n\t\tborder: 1px solid rgba(255, 152, 0, 0.3);\n\t\tborder-radius: 6px;\n\t\tfont-size: 13px;\n\t\tcolor: #e65100;\n\t\tmargin: 10px 0;\n\t\tfont-weight: 500;\n\t}\n\n\t.keyboard-info {\n\t\tfont-size: 11px;\n\t\tcolor: #555;\n\t\tmargin-top: 20px;\n\t\tpadding: 10px;\n\t\tline-height: 1.6;\n\t\tbackground-color: #f0f8ff;\n\t\tborder-left: 3px solid rgba(86, 221, 208, 1);\n\t\tborder-radius: 4px;\n\t}\n\n\t.keyboard-info strong {\n\t\tcolor: rgba(86, 221, 208, 1);\n\t\tfont-size: 12px;\n\t}\n\n\t@media (max-width: 768px) {\n\t\t.layout-container {\n\t\t\tflex-direction: column;\n\t\t}\n\n\t\t.left-column,\n\t\t.right-column {\n\t\t\tmax-width: 100%;\n\t\t\twidth: 100%;\n\t\t\tmin-width: 0;\n\t\t}\n\n\t\t.keyboard-info {\n\t\t\tdisplay: none;\n\t\t}\n\t}\n&lt;\/style&gt;\n\n&lt;script&gt;\n\tconst modeConfig = {\n\t\tsummary: {\n\t\t\tid: \"summary\",\n\t\t\tlabel: \"Podsumowanie miesi\u0105ca\",\n\t\t\tfolder: \"aktu_mies\",\n\t\t\tparameters: [\n\t\t\t\t{ id: \"TAVE\", label: \"Temperatura \u015brednia\", file: \"TAVE.png\" },\n\t\t\t\t{ id: \"TAVE_ANOM\", label: \"Anomalia temperatury\", file: \"TAVE_anom.png\" },\n\t\t\t\t{ id: \"TMAX\", label: \"Temperatura maksymalna\", file: \"TMAX.png\" },\n\t\t\t\t{ id: \"TMIN\", label: \"Temperatura minimalna\", file: \"TMIN.png\" },\n\t\t\t\t{ id: \"RRR_ACU\", label: \"Suma opadu\", file: \"RRR_acu.png\" },\n\t\t\t\t{ id: \"RRR_ANOM\", label: \"Anomalia opadu\", file: \"RRR_anom.png\" },\n\t\t\t\t{ id: \"SSS_ACU\", label: \"Us\u0142onecznienie\", file: \"SSS_acu.png\" },\n\t\t\t\t{ id: \"SSS_ANOM\", label: \"Anomalia us\u0142onecznienia\", file: \"SSS_anom.png\" }\n\t\t\t]\n\t\t},\n\t\tdaily: {\n\t\t\tid: \"daily\",\n\t\t\tlabel: \"Zestawienie dni\",\n\t\t\tfolder: \"aktu_mies_kazdy_dzien\",\n\t\t\tparameters: [\n\t\t\t\t{ id: \"TAVE\", label: \"Temperatura \u015brednia\", file: \"TAVE.png\" },\n\t\t\t\t{ id: \"TMAX\", label: \"Temperatura maksymalna\", file: \"TMAX.png\" },\n\t\t\t\t{ id: \"TMIN\", label: \"Temperatura minimalna\", file: \"TMIN.png\" },\n\t\t\t\t{ id: \"RR\", label: \"Opad\", file: \"RR.png\" }\n\t\t\t]\n\t\t}\n\t};\n\n\tconst orderedModes = [\"summary\", \"daily\"];\n\n\tconst state = {\n\t\tmode: \"summary\",\n\t\tparam: \"TAVE\"\n\t};\n\n\tconst bridge = window.__switcherBridge;\n\tconst initialState = bridge ? bridge.getInitialState(\"current\") : null;\n\n\tif (initialState) {\n\t\tif (typeof initialState.mode === \"string\" &amp;&amp; orderedModes.includes(initialState.mode)) {\n\t\t\tstate.mode = initialState.mode;\n\t\t}\n\n\t\tif (typeof initialState.param === \"string\") {\n\t\t\tstate.param = initialState.param;\n\t\t}\n\t}\n\n\tconst modeButtonsEl = document.getElementById(\"modeButtons\");\n\tconst paramButtonsEl = document.getElementById(\"paramButtons\");\n\tconst imagesEl = document.getElementById(\"images\");\n\tconst noDataEl = document.getElementById(\"noData\");\n\tconst loaderEl = document.getElementById(\"loader\");\n\tconst pageCacheToken = String(Date.now());\n\tconst imageAvailabilityCache = new Map();\n\tconst imagePreloadPromises = new Map();\n\n\tlet renderToken = 0;\n\n\tfunction syncUrlState() {\n\t\tif (!bridge) {\n\t\t\treturn;\n\t\t}\n\n\t\tbridge.updateState(\"current\", {\n\t\t\tmode: state.mode,\n\t\t\tparam: state.param\n\t\t});\n\t}\n\n\tfunction getCurrentParameters() {\n\t\treturn modeConfig[state.mode].parameters;\n\t}\n\n\tfunction ensureActiveParameter() {\n\t\tconst params = getCurrentParameters();\n\t\tif (!params.some((item) =&gt; item.id === state.param)) {\n\t\t\tstate.param = params[0].id;\n\t\t}\n\t}\n\n\tfunction getSelectedParameter() {\n\t\tconst params = getCurrentParameters();\n\t\treturn params.find((item) =&gt; item.id === state.param) || params[0];\n\t}\n\n\tfunction setLoading(isLoading) {\n\t\tloaderEl.style.display = isLoading ? \"flex\" : \"none\";\n\t}\n\n\tfunction setActiveModeButton() {\n\t\tmodeButtonsEl.querySelectorAll(\"button\").forEach((button) =&gt; {\n\t\t\tbutton.classList.toggle(\"active\", button.dataset.mode === state.mode);\n\t\t});\n\t}\n\n\tfunction setActiveParamButton() {\n\t\tparamButtonsEl.querySelectorAll(\"button\").forEach((button) =&gt; {\n\t\t\tbutton.classList.toggle(\"active\", button.dataset.param === state.param);\n\t\t});\n\t}\n\n\tfunction buildImagePathFor(modeId, paramFile) {\n\t\treturn `\/cmm\/wp-content\/uploads\/production\/analizy_meteo\/${modeConfig[modeId].folder}\/${paramFile}?v=${pageCacheToken}`;\n\t}\n\n\tfunction buildImagePath() {\n\t\tconst selectedParam = getSelectedParameter();\n\t\treturn buildImagePathFor(state.mode, selectedParam.file);\n\t}\n\n\tfunction preloadImage(src) {\n\t\tif (imageAvailabilityCache.has(src)) {\n\t\t\treturn Promise.resolve(imageAvailabilityCache.get(src));\n\t\t}\n\n\t\tif (imagePreloadPromises.has(src)) {\n\t\t\treturn imagePreloadPromises.get(src);\n\t\t}\n\n\t\tconst preloadPromise = new Promise((resolve) =&gt; {\n\t\t\tconst img = new Image();\n\n\t\t\timg.onload = () =&gt; {\n\t\t\t\timageAvailabilityCache.set(src, true);\n\t\t\t\timagePreloadPromises.delete(src);\n\t\t\t\tresolve(true);\n\t\t\t};\n\n\t\t\timg.onerror = () =&gt; {\n\t\t\t\timageAvailabilityCache.set(src, false);\n\t\t\t\timagePreloadPromises.delete(src);\n\t\t\t\tresolve(false);\n\t\t\t};\n\n\t\t\timg.src = src;\n\t\t});\n\n\t\timagePreloadPromises.set(src, preloadPromise);\n\t\treturn preloadPromise;\n\t}\n\n\tfunction preloadModeImages(modeId) {\n\t\tconst params = modeConfig[modeId].parameters;\n\t\tparams.forEach((param) =&gt; {\n\t\t\tconst src = buildImagePathFor(modeId, param.file);\n\t\t\tvoid preloadImage(src);\n\t\t});\n\t}\n\n\tfunction checkImageExists(src) {\n\t\treturn preloadImage(src);\n\t}\n\n\tfunction renderModeButtons() {\n\t\tmodeButtonsEl.innerHTML = \"\";\n\n\t\torderedModes.forEach((modeId) =&gt; {\n\t\t\tconst button = document.createElement(\"button\");\n\t\t\tbutton.type = \"button\";\n\t\t\tbutton.dataset.mode = modeId;\n\t\t\tbutton.textContent = modeConfig[modeId].label;\n\t\t\tbutton.addEventListener(\"click\", () =&gt; {\n\t\t\t\tstate.mode = modeId;\n\t\t\t\tensureActiveParameter();\n\t\t\t\tpreloadModeImages(state.mode);\n\t\t\t\tsetActiveModeButton();\n\t\t\t\trenderParamButtons();\n\t\t\t\trenderImage();\n\t\t\t});\n\t\t\tmodeButtonsEl.appendChild(button);\n\t\t});\n\n\t\tsetActiveModeButton();\n\t}\n\n\tfunction renderParamButtons() {\n\t\tparamButtonsEl.innerHTML = \"\";\n\n\t\tgetCurrentParameters().forEach((param) =&gt; {\n\t\t\tconst button = document.createElement(\"button\");\n\t\t\tbutton.type = \"button\";\n\t\t\tbutton.dataset.param = param.id;\n\t\t\tbutton.textContent = param.label;\n\t\t\tbutton.addEventListener(\"click\", () =&gt; {\n\t\t\t\tstate.param = param.id;\n\t\t\t\tsetActiveParamButton();\n\t\t\t\trenderImage();\n\t\t\t});\n\t\t\tparamButtonsEl.appendChild(button);\n\t\t});\n\n\t\tsetActiveParamButton();\n\t}\n\n\tfunction appendImageCard(imagePath) {\n\t\tconst figure = document.createElement(\"figure\");\n\t\tfigure.className = \"image-card\";\n\n\t\tconst link = document.createElement(\"a\");\n\t\tlink.href = imagePath;\n\t\tlink.target = \"_blank\";\n\t\tlink.rel = \"noopener\";\n\n\t\tconst image = document.createElement(\"img\");\n\t\timage.src = imagePath;\n\t\timage.alt = \"Mapa aktualnego miesi\u0105ca\";\n\n\t\tlink.appendChild(image);\n\t\tfigure.appendChild(link);\n\t\timagesEl.appendChild(figure);\n\t}\n\n\tasync function renderImage() {\n\t\timagesEl.innerHTML = \"\";\n\t\tnoDataEl.style.display = \"none\";\n\t\tsetLoading(true);\n\t\tsyncUrlState();\n\n\t\tconst token = ++renderToken;\n\t\tconst imagePath = buildImagePath();\n\t\tconst exists = await checkImageExists(imagePath);\n\n\t\tif (token !== renderToken) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (exists) {\n\t\t\tappendImageCard(imagePath);\n\t\t} else {\n\t\t\tnoDataEl.style.display = \"block\";\n\t\t}\n\n\t\tsetLoading(false);\n\t}\n\n\tfunction selectModeByIndex(index) {\n\t\tconst modeId = orderedModes[index];\n\t\tif (!modeId) {\n\t\t\treturn;\n\t\t}\n\n\t\tstate.mode = modeId;\n\t\tensureActiveParameter();\n\t\tsetActiveModeButton();\n\t\trenderParamButtons();\n\t\trenderImage();\n\t}\n\n\tfunction selectNextParam(step) {\n\t\tconst params = getCurrentParameters();\n\t\tconst currentIndex = params.findIndex((item) =&gt; item.id === state.param);\n\t\tif (currentIndex === -1) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst nextIndex = (currentIndex + step + params.length) % params.length;\n\t\tstate.param = params[nextIndex].id;\n\t\tsetActiveParamButton();\n\t\trenderImage();\n\t}\n\n\tfunction shouldIgnoreKeyboardEvent(event) {\n\t\tconst target = event.target;\n\t\tif (!target) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst tag = target.tagName ? target.tagName.toLowerCase() : \"\";\n\t\treturn tag === \"input\" || tag === \"textarea\" || tag === \"select\" || target.isContentEditable;\n\t}\n\n\tdocument.addEventListener(\"keydown\", (event) =&gt; {\n\t\tif (shouldIgnoreKeyboardEvent(event)) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"1\") {\n\t\t\tevent.preventDefault();\n\t\t\tselectModeByIndex(0);\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"2\") {\n\t\t\tevent.preventDefault();\n\t\t\tselectModeByIndex(1);\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"ArrowUp\") {\n\t\t\tevent.preventDefault();\n\t\t\tselectNextParam(-1);\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"ArrowDown\") {\n\t\t\tevent.preventDefault();\n\t\t\tselectNextParam(1);\n\t\t}\n\t});\n\n\trenderModeButtons();\n\tensureActiveParameter();\n\torderedModes.forEach((modeId) =&gt; preloadModeImages(modeId));\n\trenderParamButtons();\n\trenderImage();\nconsole.log(\"Autor Bart\u0142omiej Sobczyk 2026\");\n&lt;\/script&gt;\n  <\/textarea>\n\n  <textarea id=\"template-monthly\" class=\"embedded-template\" hidden>\n&lt;div id=\"forecast-app\" class=\"forecast-app monthly-summary-app\"&gt;\n\t&lt;div class=\"layout-container\"&gt;\n\t\t&lt;div class=\"left-column\"&gt;\n\t\t\t&lt;div class=\"section\"&gt;\n\t\t\t\t&lt;h3&gt;Rocznik:&lt;\/h3&gt;\n\t\t\t\t&lt;div id=\"yearButtons\" class=\"buttons year-buttons\"&gt;&lt;\/div&gt;\n\t\t\t&lt;\/div&gt;\n\n\t\t\t&lt;div class=\"section\"&gt;\n\t\t\t\t&lt;h3&gt;Miesi\u0105c:&lt;\/h3&gt;\n\t\t\t\t&lt;div class=\"month-slider-wrap\"&gt;\n\t\t\t\t\t&lt;div id=\"monthValue\" class=\"month-value\"&gt;Stycze\u0144&lt;\/div&gt;\n\t\t\t\t\t&lt;input type=\"range\" id=\"monthSlider\" class=\"horizontal-slider\" min=\"1\" max=\"12\" step=\"1\" value=\"1\" aria-label=\"Wybierz miesi\u0105c\"&gt;\n\t\t\t\t\t&lt;div class=\"month-labels\"&gt;\n\t\t\t\t\t\t&lt;span&gt;01&lt;\/span&gt;&lt;span&gt;02&lt;\/span&gt;&lt;span&gt;03&lt;\/span&gt;&lt;span&gt;04&lt;\/span&gt;&lt;span&gt;05&lt;\/span&gt;&lt;span&gt;06&lt;\/span&gt;\n\t\t\t\t\t\t&lt;span&gt;07&lt;\/span&gt;&lt;span&gt;08&lt;\/span&gt;&lt;span&gt;09&lt;\/span&gt;&lt;span&gt;10&lt;\/span&gt;&lt;span&gt;11&lt;\/span&gt;&lt;span&gt;12&lt;\/span&gt;\n\t\t\t\t\t&lt;\/div&gt;\n\t\t\t\t&lt;\/div&gt;\n\t\t\t&lt;\/div&gt;\n\n\t\t\t&lt;div class=\"section\"&gt;\n\t\t\t\t&lt;h3&gt;Charakterystyka:&lt;\/h3&gt;\n\t\t\t\t&lt;div class=\"buttons params-buttons tab\" id=\"paramTabs\"&gt;\n\t\t\t\t\t&lt;button class=\"tablinks\" data-param=\"TEMPSR\" id=\"defaultOpen\" onclick=\"wrf(event, 'TEMPSR')\"&gt;Temperatura \u015brednia&lt;\/button&gt;\n\t\t\t\t\t&lt;button class=\"tablinks\" data-param=\"TEMPMAX\" onclick=\"wrf(event, 'TEMPMAX')\"&gt;Temperatura maksymalna&lt;\/button&gt;\n\t\t\t\t\t&lt;button class=\"tablinks\" data-param=\"TEMPMIN\" onclick=\"wrf(event, 'TEMPMIN')\"&gt;Temperatura minimalna&lt;\/button&gt;\n\t\t\t\t\t&lt;button class=\"tablinks\" data-param=\"OPAD\" onclick=\"wrf(event, 'OPAD')\"&gt;Opad&lt;\/button&gt;\n\t\t\t\t&lt;\/div&gt;\n\t\t\t&lt;\/div&gt;\n\n\t\t\t&lt;div class=\"keyboard-info\"&gt;\n\t\t\t\t&lt;strong&gt;\ud83d\udca1 Skr\u00f3ty klawiszowe:&lt;\/strong&gt;&lt;br&gt;\n\t\t\t\t\u2191, \u2193 Zmiana rocznika&lt;br&gt;\n\t\t\t\t\u2190, \u2192 Zmiana miesi\u0105ca&lt;br&gt;\n\t\t\t\t1-4 Wyb\u00f3r charakterystyki&lt;br&gt;\n\t\t\t\tA   Wszystkie miesi\u0105ce&lt;br&gt;\n\t\t\t\tS   Ten sam miesi\u0105c w latach&lt;br&gt;\n\t\t\t\t&amp;lt; &amp;gt; zmiana karty g\u0142\u00f3wnej\n\t\t\t&lt;\/div&gt;\n\t\t&lt;\/div&gt;\n\n\t\t&lt;div class=\"right-column\"&gt;\n\t\t\t&lt;div class=\"section images\"&gt;\n\t\t\t\t&lt;div class=\"image-header\"&gt;\n\t\t\t\t\t&lt;h3 id=\"imageTitle\"&gt;Temperatura \u015brednia | Stycze\u0144 2026&lt;\/h3&gt;\n\t\t\t\t\t&lt;div class=\"header-actions\"&gt;\n\t\t\t\t\t\t&lt;button id=\"showAllBtn\" class=\"control-btn\" type=\"button\"&gt;Poka\u017c wszystkie miesi\u0105ce w roku&lt;\/button&gt;\n\t\t\t\t\t\t&lt;button id=\"showAllYearsBtn\" class=\"control-btn\" type=\"button\"&gt;Poka\u017c ten sam miesi\u0105c w latach&lt;\/button&gt;\n\t\t\t\t\t&lt;\/div&gt;\n\t\t\t\t&lt;\/div&gt;\n\t\t\t\t&lt;div id=\"loader\" class=\"loader-container\" style=\"display: none;\"&gt;\n\t\t\t\t\t&lt;div class=\"loader\"&gt;&lt;\/div&gt;\n\t\t\t\t&lt;\/div&gt;\n\t\t\t\t&lt;div id=\"images\" class=\"images-grid\"&gt;&lt;\/div&gt;\n\t\t\t\t&lt;div id=\"noData\" class=\"date-warning\"&gt;Brak dost\u0119pnych map dla wybranego zestawu.&lt;\/div&gt;\n\t\t\t&lt;\/div&gt;\n\t\t&lt;\/div&gt;\n\t&lt;\/div&gt;\n&lt;\/div&gt;\n\n&lt;style&gt;\n\t.forecast-app {\n\t\tfont-family: Arial, sans-serif;\n\t\tmax-width: 1200px;\n\t\tmargin: 0 auto;\n\t}\n\n\t.layout-container {\n\t\tdisplay: flex;\n\t\tflex-wrap: wrap;\n\t\tgap: 10px;\n\t}\n\n\t.left-column {\n\t\tflex: 1;\n\t\tmin-width: 230px;\n\t\tmax-width: 230px;\n\t}\n\n\t.right-column {\n\t\tflex: 2;\n\t\tmin-width: 400px;\n\t}\n\n\t.section {\n\t\tmargin-bottom: 12px;\n\t\tbackground: #f9f9f9;\n\t\tpadding: 10px;\n\t\tborder-radius: 8px;\n\t\tbox-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n\t}\n\n\t.section h3 {\n\t\tmargin-top: 0;\n\t\tmargin-bottom: 6px;\n\t\tborder-bottom: 1px solid #ddd;\n\t\tpadding-bottom: 5px;\n\t\tcolor: #333;\n\t}\n\n\t.buttons {\n\t\tdisplay: flex;\n\t\tflex-wrap: wrap;\n\t\tgap: 5px;\n\t\tmargin-top: 3px;\n\t}\n\n\t.buttons button {\n\t\tpadding: 6px 10px;\n\t\tmin-width: 45px;\n\t\tborder: 1px solid #666;\n\t\tborder-radius: 6px;\n\t\tbackground: #f5f5f5;\n\t\tcursor: pointer;\n\t\ttransition: all 0.2s;\n\t\tfont-size: 0.9em;\n\t}\n\n\t.buttons button:hover {\n\t\tbackground: #e3f5f3;\n\t\tborder-color: rgba(86, 221, 208, 1);\n\t}\n\n\t.buttons button.active,\n\t.tablinks.active {\n\t\tbackground: rgba(86, 221, 208, 1);\n\t\tborder-color: rgba(56, 191, 178, 1);\n\t\tcolor: #fff;\n\t}\n\n\t.year-buttons {\n\t\tdisplay: grid;\n\t\tgrid-template-columns: repeat(3, minmax(0, 1fr));\n\t\tgap: 6px;\n\t}\n\n\t.year-buttons button {\n\t\twidth: 100%;\n\t\tmin-width: 0;\n\t\tfont-variant-numeric: tabular-nums;\n\t}\n\n\t.params-buttons {\n\t\tdisplay: grid;\n\t\tgrid-template-columns: 1fr;\n\t\tgap: 6px;\n\t}\n\n\t.params-buttons button {\n\t\twidth: 100%;\n\t\ttext-align: center;\n\t}\n\n\t.month-slider-wrap {\n\t\tmargin-top: 4px;\n\t}\n\n\t.month-value {\n\t\tfont-size: 1.1em;\n\t\tfont-weight: bold;\n\t\tcolor: rgba(86, 221, 208, 1);\n\t\tmargin-bottom: 6px;\n\t}\n\n\t.horizontal-slider {\n\t\t-webkit-appearance: none;\n\t\tappearance: none;\n\t\twidth: 100%;\n\t\theight: 10px;\n\t\tborder-radius: 5px;\n\t\tbackground: #e0e0e0;\n\t\toutline: none;\n\t\tmargin: 4px 0 8px;\n\t}\n\n\t.horizontal-slider::-webkit-slider-thumb {\n\t\t-webkit-appearance: none;\n\t\tappearance: none;\n\t\twidth: 22px;\n\t\theight: 22px;\n\t\tborder-radius: 50%;\n\t\tbackground: rgba(86, 221, 208, 1);\n\t\tcursor: pointer;\n\t\tborder: 2px solid #fff;\n\t\tbox-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n\t}\n\n\t.horizontal-slider::-moz-range-thumb {\n\t\twidth: 22px;\n\t\theight: 22px;\n\t\tborder-radius: 50%;\n\t\tbackground: rgba(86, 221, 208, 1);\n\t\tcursor: pointer;\n\t\tborder: 2px solid #fff;\n\t\tbox-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n\t}\n\n\t.month-labels {\n\t\tdisplay: grid;\n\t\tgrid-template-columns: repeat(12, minmax(0, 1fr));\n\t\tgap: 2px;\n\t\tfont-size: 10px;\n\t\tcolor: #777;\n\t\ttext-align: center;\n\t}\n\n\t.image-header {\n\t\tdisplay: flex;\n\t\talign-items: center;\n\t\tgap: 10px;\n\t\tjustify-content: space-between;\n\t\tmargin-bottom: 10px;\n\t}\n\n\t.image-header h3 {\n\t\tmargin: 0;\n\t\tpadding: 0;\n\t\tborder: none;\n\t}\n\n\t.header-actions {\n\t\tdisplay: flex;\n\t\tgap: 8px;\n\t\tflex-wrap: wrap;\n\t\tjustify-content: flex-end;\n\t}\n\n\t.control-btn {\n\t\tbackground: rgba(86, 221, 208, 0.1);\n\t\tborder: 2px solid rgba(86, 221, 208, 1);\n\t\tcolor: rgba(56, 191, 178, 1);\n\t\tborder-radius: 8px;\n\t\tcursor: pointer;\n\t\ttransition: all 0.2s;\n\t\tpadding: 7px 10px;\n\t\tfont-size: 0.85em;\n\t\tfont-weight: bold;\n\t\twhite-space: nowrap;\n\t}\n\n\t.control-btn:hover {\n\t\tbackground: rgba(86, 221, 208, 0.2);\n\t}\n\n\t.control-btn.active {\n\t\tbackground: rgba(86, 221, 208, 1);\n\t\tcolor: #fff;\n\t}\n\n\t.images-grid {\n\t\tdisplay: grid;\n\t\tgrid-template-columns: repeat(auto-fit, minmax(320px, 1fr));\n\t\tgap: 14px;\n\t\tmin-height: 420px;\n\t}\n\n\t.image-card {\n\t\tmargin: 0;\n\t\tborder: 1px solid #ddd;\n\t\tborder-radius: 8px;\n\t\tpadding: 8px;\n\t\tbackground: #fff;\n\t\tbox-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);\n\t}\n\n\t.image-card img {\n\t\twidth: 100%;\n\t\theight: auto;\n\t\tdisplay: block;\n\t\tborder-radius: 5px;\n\t}\n\n\t.loader-container {\n\t\tdisplay: flex;\n\t\tjustify-content: center;\n\t\talign-items: center;\n\t\tflex-direction: column;\n\t\twidth: 100%;\n\t\theight: 300px;\n\t\tz-index: 100;\n\t\tposition: relative;\n\t\tbackground-color: rgba(245, 245, 245, 0.7);\n\t\tborder-radius: 8px;\n\t\tmargin-bottom: 10px;\n\t}\n\n\t.loader {\n\t\tborder: 12px solid #f3f3f3;\n\t\tborder-radius: 50%;\n\t\tborder-top: 12px solid rgba(86, 221, 208, 1);\n\t\twidth: 90px;\n\t\theight: 90px;\n\t\tanimation: spin 0.8s linear infinite;\n\t\tbox-shadow: 0 0 20px rgba(86, 221, 208, 0.7);\n\t}\n\n\t@keyframes spin {\n\t\t0% {\n\t\t\ttransform: rotate(0deg);\n\t\t}\n\t\t100% {\n\t\t\ttransform: rotate(360deg);\n\t\t}\n\t}\n\n\t.date-warning {\n\t\tdisplay: none;\n\t\ttext-align: center;\n\t\tpadding: 8px 15px;\n\t\tbackground: rgba(255, 152, 0, 0.1);\n\t\tborder: 1px solid rgba(255, 152, 0, 0.3);\n\t\tborder-radius: 6px;\n\t\tfont-size: 13px;\n\t\tcolor: #e65100;\n\t\tmargin: 10px 0;\n\t\tfont-weight: 500;\n\t}\n\n\t.keyboard-info {\n\t\tfont-size: 11px;\n\t\tcolor: #555;\n\t\tmargin-top: 20px;\n\t\tpadding: 10px;\n\t\tline-height: 1.6;\n\t\tbackground-color: #f0f8ff;\n\t\tborder-left: 3px solid rgba(86, 221, 208, 1);\n\t\tborder-radius: 4px;\n\t}\n\n\t.keyboard-info strong {\n\t\tcolor: rgba(86, 221, 208, 1);\n\t\tfont-size: 12px;\n\t}\n\n\t@media (max-width: 768px) {\n\t\t.layout-container {\n\t\t\tflex-direction: column;\n\t\t}\n\n\t\t.left-column,\n\t\t.right-column {\n\t\t\tmax-width: 100%;\n\t\t\twidth: 100%;\n\t\t\tmin-width: 0;\n\t\t}\n\n\t\t.images-grid {\n\t\t\tgrid-template-columns: 1fr;\n\t\t}\n\n\t\t.image-header {\n\t\t\tflex-direction: column;\n\t\t\talign-items: flex-start;\n\t\t}\n\n\t\t.header-actions {\n\t\t\tjustify-content: flex-start;\n\t\t}\n\t}\n&lt;\/style&gt;\n\n&lt;script&gt;\n\tconst months = [\n\t\t{ value: 1, label: \"Stycze\u0144\" },\n\t\t{ value: 2, label: \"Luty\" },\n\t\t{ value: 3, label: \"Marzec\" },\n\t\t{ value: 4, label: \"Kwiecie\u0144\" },\n\t\t{ value: 5, label: \"Maj\" },\n\t\t{ value: 6, label: \"Czerwiec\" },\n\t\t{ value: 7, label: \"Lipiec\" },\n\t\t{ value: 8, label: \"Sierpie\u0144\" },\n\t\t{ value: 9, label: \"Wrzesie\u0144\" },\n\t\t{ value: 10, label: \"Pa\u017adziernik\" },\n\t\t{ value: 11, label: \"Listopad\" },\n\t\t{ value: 12, label: \"Grudzie\u0144\" }\n\t];\n\n\tconst paramsConfig = {\n\t\tTEMPSR: { label: \"Temperatura \u015brednia\", suffix: \"TAVE\" },\n\t\tTEMPMAX: { label: \"Temperatura maksymalna\", suffix: \"TMAX\" },\n\t\tTEMPMIN: { label: \"Temperatura minimalna\", suffix: \"TMIN\" },\n\t\tOPAD: { label: \"Opad\", suffix: \"RR\" }\n\t};\n\n\tconst firstYear = 2013;\n\tconst now = new Date();\n\tconst currentYear = now.getFullYear();\n\tconst currentMonth = now.getMonth() + 1;\n\tconst defaultMonthDate = new Date(currentYear, currentMonth - 2, 1);\n\tconst defaultYear = defaultMonthDate.getFullYear();\n\tconst defaultMonth = defaultMonthDate.getMonth() + 1;\n\tconst latestYear = Math.max(firstYear, currentYear);\n\tconst years = Array.from({ length: latestYear - firstYear + 1 }, (_, i) =&gt; latestYear - i);\n\tconst state = {\n\t\tyear: defaultYear,\n\t\tmonth: defaultMonth,\n\t\tparam: \"TEMPSR\",\n\t\tviewMode: \"single\"\n\t};\n\n\tconst bridge = window.__switcherBridge;\n\tconst initialState = bridge ? bridge.getInitialState(\"monthly\") : null;\n\n\tif (initialState) {\n\t\tif (Number.isInteger(initialState.year) &amp;&amp; years.includes(initialState.year)) {\n\t\t\tstate.year = initialState.year;\n\t\t}\n\n\t\tif (Number.isInteger(initialState.month) &amp;&amp; initialState.month &gt;= 1 &amp;&amp; initialState.month &lt;= 12) {\n\t\t\tstate.month = initialState.month;\n\t\t}\n\n\t\tif (typeof initialState.param === \"string\" &amp;&amp; paramsConfig[initialState.param]) {\n\t\t\tstate.param = initialState.param;\n\t\t}\n\n\t\tif (\n\t\t\ttypeof initialState.viewMode === \"string\" &amp;&amp;\n\t\t\t[\"single\", \"allMonths\", \"allYears\"].includes(initialState.viewMode)\n\t\t) {\n\t\t\tstate.viewMode = initialState.viewMode;\n\t\t}\n\t}\n\n\tconst hasPinnedPeriodFromUrl = Boolean(initialState &amp;&amp; initialState.periodPinned === true);\n\n\tconst yearButtonsEl = document.getElementById(\"yearButtons\");\n\tconst monthSliderEl = document.getElementById(\"monthSlider\");\n\tconst monthValueEl = document.getElementById(\"monthValue\");\n\tconst imageTitleEl = document.getElementById(\"imageTitle\");\n\tconst imagesEl = document.getElementById(\"images\");\n\tconst noDataEl = document.getElementById(\"noData\");\n\tconst showAllBtnEl = document.getElementById(\"showAllBtn\");\n\tconst showAllYearsBtnEl = document.getElementById(\"showAllYearsBtn\");\n\tconst loaderEl = document.getElementById(\"loader\");\n\tconst imageAvailabilityCache = new Map();\n\tconst imagePreloadPromises = new Map();\n\tlet renderToken = 0;\n\n\tfunction syncUrlState() {\n\t\tif (!bridge) {\n\t\t\treturn;\n\t\t}\n\n\t\tbridge.updateState(\"monthly\", {\n\t\t\tyear: state.year,\n\t\t\tmonth: state.month,\n\t\t\tparam: state.param,\n\t\t\tviewMode: state.viewMode\n\t\t});\n\t}\n\n\tfunction getMonthMeta(monthNumber) {\n\t\treturn months.find((m) =&gt; m.value === monthNumber) || months[0];\n\t}\n\n\tfunction createImagePath(year, month, suffix) {\n\t\treturn `\/cmm\/wp-content\/uploads\/production\/analizy_meteo\/miesieczne\/${year}_${month}_${suffix}.png`;\n\t}\n\n\tfunction checkImageExists(src) {\n\t\treturn preloadImage(src);\n\t}\n\n\tasync function findLatestAvailableYearMonth(paramId) {\n\t\tconst suffix = paramsConfig[paramId].suffix;\n\n\t\tfor (const year of years) {\n\t\t\tconst monthsDesc = Array.from({ length: 12 }, (_, i) =&gt; 12 - i);\n\t\t\tconst checks = await Promise.all(\n\t\t\t\tmonthsDesc.map(async (month) =&gt; {\n\t\t\t\t\tconst path = createImagePath(year, month, suffix);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tmonth: month,\n\t\t\t\t\t\tok: await checkImageExists(path)\n\t\t\t\t\t};\n\t\t\t\t})\n\t\t\t);\n\n\t\t\tconst found = checks.find((item) =&gt; item.ok);\n\t\t\tif (found) {\n\t\t\t\treturn {\n\t\t\t\t\tyear: year,\n\t\t\t\t\tmonth: found.month\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tfunction createYearButtons() {\n\t\tyearButtonsEl.innerHTML = \"\";\n\t\tyears.forEach((year) =&gt; {\n\t\t\tconst btn = document.createElement(\"button\");\n\t\t\tbtn.type = \"button\";\n\t\t\tbtn.textContent = year;\n\t\t\tbtn.dataset.year = String(year);\n\t\t\tif (year === state.year) {\n\t\t\t\tbtn.classList.add(\"active\");\n\t\t\t}\n\n\t\t\tbtn.addEventListener(\"click\", () =&gt; {\n\t\t\t\tstate.year = year;\n\t\t\t\tyearButtonsEl.querySelectorAll(\"button\").forEach((b) =&gt; b.classList.remove(\"active\"));\n\t\t\t\tbtn.classList.add(\"active\");\n\t\t\t\trenderImages();\n\t\t\t});\n\n\t\t\tyearButtonsEl.appendChild(btn);\n\t\t});\n\t}\n\n\tfunction setLoading(isLoading) {\n\t\tloaderEl.style.display = isLoading ? \"flex\" : \"none\";\n\t}\n\n\tasync function initializeDefaultSelection() {\n\t\tsetLoading(true);\n\n\t\ttry {\n\t\t\tconst preferredPeriod = hasPinnedPeriodFromUrl\n\t\t\t\t? { year: state.year, month: state.month }\n\t\t\t\t: { year: defaultYear, month: defaultMonth };\n\n\t\t\tstate.year = preferredPeriod.year;\n\t\t\tstate.month = preferredPeriod.month;\n\n\t\t\tif (!years.includes(state.year)) {\n\t\t\t\tstate.year = years[0];\n\t\t\t}\n\n\t\t\tmonthSliderEl.value = String(state.month);\n\t\t\tupdateActiveYearButton();\n\t\t\tsetActiveParamButton(state.param);\n\t\t\tawait renderImages();\n\t\t} finally {\n\t\t\tsetLoading(false);\n\t\t}\n\t}\n\n\tfunction updateMonthLabel() {\n\t\tconst monthMeta = getMonthMeta(state.month);\n\t\tmonthValueEl.textContent = monthMeta.label;\n\t}\n\n\tfunction syncViewModeButtons() {\n\t\tconst allMonthsActive = state.viewMode === \"allMonths\";\n\t\tconst allYearsActive = state.viewMode === \"allYears\";\n\n\t\tshowAllBtnEl.classList.toggle(\"active\", allMonthsActive);\n\t\tshowAllYearsBtnEl.classList.toggle(\"active\", allYearsActive);\n\n\t\tshowAllBtnEl.textContent = allMonthsActive ? \"Wr\u00f3\u0107 do jednego miesi\u0105ca\" : \"Poka\u017c wszystkie miesi\u0105ce\";\n\t\tshowAllYearsBtnEl.textContent = allYearsActive ? \"Wr\u00f3\u0107 do jednego roku\" : \"Poka\u017c ten sam miesi\u0105c w latach\";\n\t}\n\n\tfunction updateTitle() {\n\t\tconst monthMeta = getMonthMeta(state.month);\n\t\tconst paramLabel = paramsConfig[state.param].label;\n\t\tconst period = state.viewMode === \"allMonths\"\n\t\t\t? `${state.year} (wszystkie miesi\u0105ce)`\n\t\t\t: state.viewMode === \"allYears\"\n\t\t\t\t? `${monthMeta.label} (r\u00f3\u017cne lata)`\n\t\t\t\t: `${monthMeta.label} ${state.year}`;\n\t\timageTitleEl.textContent = `${paramLabel} | ${period}`;\n\t}\n\n\tfunction setActiveParamButton(activeParam) {\n\t\tdocument.querySelectorAll(\".tablinks\").forEach((button) =&gt; {\n\t\t\tbutton.classList.toggle(\"active\", button.dataset.param === activeParam);\n\t\t});\n\t}\n\n\tfunction preloadImage(src) {\n\t\tif (imageAvailabilityCache.has(src)) {\n\t\t\treturn Promise.resolve(imageAvailabilityCache.get(src));\n\t\t}\n\n\t\tif (imagePreloadPromises.has(src)) {\n\t\t\treturn imagePreloadPromises.get(src);\n\t\t}\n\n\t\tconst preloadPromise = new Promise((resolve) =&gt; {\n\t\t\tconst img = new Image();\n\n\t\t\timg.onload = () =&gt; {\n\t\t\t\timageAvailabilityCache.set(src, true);\n\t\t\t\timagePreloadPromises.delete(src);\n\t\t\t\tresolve(true);\n\t\t\t};\n\n\t\t\timg.onerror = () =&gt; {\n\t\t\t\timageAvailabilityCache.set(src, false);\n\t\t\t\timagePreloadPromises.delete(src);\n\t\t\t\tresolve(false);\n\t\t\t};\n\n\t\t\timg.src = src;\n\t\t});\n\n\t\timagePreloadPromises.set(src, preloadPromise);\n\t\treturn preloadPromise;\n\t}\n\n\tfunction appendImageCard(src) {\n\t\tconst figure = document.createElement(\"figure\");\n\t\tfigure.className = \"image-card\";\n\n\t\tconst link = document.createElement(\"a\");\n\t\tlink.href = src;\n\t\tlink.target = \"_blank\";\n\t\tlink.rel = \"noopener\";\n\n\t\tconst img = document.createElement(\"img\");\n\t\timg.src = src;\n\t\timg.alt = \"Mapa\";\n\n\t\tlink.appendChild(img);\n\t\tfigure.appendChild(link);\n\t\timagesEl.appendChild(figure);\n\t}\n\n\tfunction updateActiveYearButton() {\n\t\tyearButtonsEl.querySelectorAll(\"button\").forEach((button) =&gt; {\n\t\t\tbutton.classList.toggle(\"active\", Number(button.dataset.year) === state.year);\n\t\t});\n\t}\n\n\tfunction toggleShowAll() {\n\t\tstate.viewMode = state.viewMode === \"allMonths\" ? \"single\" : \"allMonths\";\n\t\tsyncViewModeButtons();\n\t\trenderImages();\n\t}\n\n\tfunction toggleShowAllYears() {\n\t\tstate.viewMode = state.viewMode === \"allYears\" ? \"single\" : \"allYears\";\n\t\tsyncViewModeButtons();\n\t\trenderImages();\n\t}\n\n\tfunction changeYearByOffset(offset) {\n\t\tconst currentIndex = years.indexOf(state.year);\n\t\tif (currentIndex === -1) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst nextIndex = Math.max(0, Math.min(years.length - 1, currentIndex + offset));\n\t\tif (nextIndex === currentIndex) {\n\t\t\treturn;\n\t\t}\n\n\t\tstate.year = years[nextIndex];\n\t\tupdateActiveYearButton();\n\t\trenderImages();\n\t}\n\n\tfunction changeMonthByOffset(offset) {\n\t\tconst nextMonth = Math.max(1, Math.min(12, state.month + offset));\n\t\tif (nextMonth === state.month) {\n\t\t\treturn;\n\t\t}\n\n\t\tstate.month = nextMonth;\n\t\tmonthSliderEl.value = String(nextMonth);\n\t\trenderImages();\n\t}\n\n\tfunction selectParamByIndex(index) {\n\t\tconst orderedParams = [\"TEMPSR\", \"TEMPMAX\", \"TEMPMIN\", \"OPAD\"];\n\t\tconst paramId = orderedParams[index];\n\t\tif (!paramId) {\n\t\t\treturn;\n\t\t}\n\n\t\tstate.param = paramId;\n\t\tsetActiveParamButton(paramId);\n\t\trenderImages();\n\t}\n\n\tfunction shouldIgnoreKeyboardEvent(event) {\n\t\tconst target = event.target;\n\t\tif (!target) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst tag = target.tagName ? target.tagName.toLowerCase() : \"\";\n\t\treturn tag === \"input\" || tag === \"textarea\" || tag === \"select\" || target.isContentEditable;\n\t}\n\n\tasync function renderImages() {\n\t\timagesEl.innerHTML = \"\";\n\t\tnoDataEl.style.display = \"none\";\n\t\tconst token = ++renderToken;\n\t\tsetLoading(true);\n\t\tsyncUrlState();\n\n\t\tupdateMonthLabel();\n\t\tupdateTitle();\n\n\t\tconst renderTargets = state.viewMode === \"allMonths\"\n\t\t\t? months.map((monthMeta) =&gt; ({ year: state.year, month: monthMeta.value }))\n\t\t\t: state.viewMode === \"allYears\"\n\t\t\t\t? years.map((year) =&gt; ({ year: year, month: state.month }))\n\t\t\t\t: [{ year: state.year, month: state.month }];\n\t\tconst suffix = paramsConfig[state.param].suffix;\n\n\t\ttry {\n\t\t\tconst checks = await Promise.all(\n\t\t\t\trenderTargets.map(async (target) =&gt; {\n\t\t\t\t\tconst filePath = createImagePath(target.year, target.month, suffix);\n\t\t\t\t\tconst ok = await preloadImage(filePath);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tok: ok,\n\t\t\t\t\t\tfilePath: filePath\n\t\t\t\t\t};\n\t\t\t\t})\n\t\t\t);\n\n\t\t\tif (token !== renderToken) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tchecks.forEach((item) =&gt; {\n\t\t\t\tif (item.ok) {\n\t\t\t\t\tappendImageCard(item.filePath);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tif (!checks.some((item) =&gt; item.ok)) {\n\t\t\t\tnoDataEl.style.display = \"block\";\n\t\t\t}\n\t\t} finally {\n\t\t\tif (token === renderToken) {\n\t\t\t\tsetLoading(false);\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction wrf(evt, paramId) {\n\t\tstate.param = paramId;\n\t\tsetActiveParamButton(paramId);\n\t\trenderImages();\n\n\t\tif (evt &amp;&amp; evt.currentTarget) {\n\t\t\tevt.preventDefault();\n\t\t}\n\t}\n\n\tmonthSliderEl.addEventListener(\"input\", (event) =&gt; {\n\t\tstate.month = Number(event.target.value);\n\t\trenderImages();\n\t});\n\n\tshowAllBtnEl.addEventListener(\"click\", toggleShowAll);\n\tshowAllYearsBtnEl.addEventListener(\"click\", toggleShowAllYears);\n\n\tdocument.addEventListener(\"keydown\", (event) =&gt; {\n\t\tif (shouldIgnoreKeyboardEvent(event)) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"ArrowLeft\") {\n\t\t\tevent.preventDefault();\n\t\t\tchangeMonthByOffset(-1);\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"ArrowRight\") {\n\t\t\tevent.preventDefault();\n\t\t\tchangeMonthByOffset(1);\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"ArrowUp\") {\n\t\t\tevent.preventDefault();\n\t\t\tchangeYearByOffset(-1);\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"ArrowDown\") {\n\t\t\tevent.preventDefault();\n\t\t\tchangeYearByOffset(1);\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"1\") {\n\t\t\tselectParamByIndex(0);\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"2\") {\n\t\t\tselectParamByIndex(1);\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"3\") {\n\t\t\tselectParamByIndex(2);\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"4\") {\n\t\t\tselectParamByIndex(3);\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"a\" || event.key === \"A\") {\n\t\t\tevent.preventDefault();\n\t\t\ttoggleShowAll();\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"s\" || event.key === \"S\") {\n\t\t\tevent.preventDefault();\n\t\t\ttoggleShowAllYears();\n\t\t}\n\t});\n\n\tcreateYearButtons();\n\tsyncViewModeButtons();\n\tinitializeDefaultSelection();\nconsole.log(\"Autor Bart\u0142omiej Sobczyk 2026\");\n&lt;\/script&gt;\n  <\/textarea>\n\n  <textarea id=\"template-climate\" class=\"embedded-template\" hidden>\n&lt;div id=\"forecast-app\" class=\"forecast-app climate-stats-app\"&gt;\n\t&lt;div class=\"layout-container\"&gt;\n\t\t&lt;div class=\"left-column\"&gt;\n\t\t\t&lt;div class=\"section\"&gt;\n\t\t\t\t&lt;h3&gt;Zakres statystyki:&lt;\/h3&gt;\n\t\t\t\t&lt;div id=\"modeButtons\" class=\"buttons mode-buttons\"&gt;&lt;\/div&gt;\n\t\t\t&lt;\/div&gt;\n\n\t\t\t&lt;div class=\"section\"&gt;\n\t\t\t\t&lt;h3 id=\"paramTitle\"&gt;Charakterystyka:&lt;\/h3&gt;\n\t\t\t\t&lt;div id=\"paramButtons\" class=\"buttons params-buttons\"&gt;&lt;\/div&gt;\n\t\t\t&lt;\/div&gt;\n\n\t\t\t&lt;div class=\"keyboard-info\"&gt;\n\t\t\t\t&lt;strong&gt;\ud83d\udca1 Skr\u00f3ty klawiszowe:&lt;\/strong&gt;&lt;br&gt;\n\t\t\t\t1-3 zmiana zakresu statystyki\n\t\t\t\t&lt;br&gt;\u2191, \u2193 zmiana charakterystyki\n\t\t\t\t&lt;br&gt;&amp;lt; &amp;gt; zmiana karty g\u0142\u00f3wnej\n\t\t\t&lt;\/div&gt;\n\t\t&lt;\/div&gt;\n\n\t\t&lt;div class=\"right-column\"&gt;\n\t\t\t&lt;div class=\"section images\"&gt;\n\t\t\t\t&lt;div id=\"loader\" class=\"loader-container\" style=\"display: none;\"&gt;\n\t\t\t\t\t&lt;div class=\"loader\"&gt;&lt;\/div&gt;\n\t\t\t\t&lt;\/div&gt;\n\n\t\t\t\t&lt;div id=\"images\" class=\"images-grid\"&gt;&lt;\/div&gt;\n\t\t\t\t&lt;div id=\"noData\" class=\"date-warning\"&gt;Brak dost\u0119pnej mapy dla wybranego zestawu.&lt;\/div&gt;\n\t\t\t&lt;\/div&gt;\n\t\t&lt;\/div&gt;\n\t&lt;\/div&gt;\n&lt;\/div&gt;\n\n&lt;style&gt;\n\t.forecast-app {\n\t\tfont-family: Arial, sans-serif;\n\t\tmax-width: 1200px;\n\t\tmargin: 0 auto;\n\t}\n\n\t.layout-container {\n\t\tdisplay: flex;\n\t\tflex-wrap: wrap;\n\t\tgap: 10px;\n\t}\n\n\t.left-column {\n\t\tflex: 1;\n\t\tmin-width: 280px;\n\t\tmax-width: 320px;\n\t}\n\n\t.right-column {\n\t\tflex: 2;\n\t\tmin-width: 400px;\n\t}\n\n\t.section {\n\t\tmargin-bottom: 12px;\n\t\tbackground: #f9f9f9;\n\t\tpadding: 10px;\n\t\tborder-radius: 8px;\n\t\tbox-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n\t}\n\n\t.section h3 {\n\t\tmargin-top: 0;\n\t\tmargin-bottom: 6px;\n\t\tborder-bottom: 1px solid #ddd;\n\t\tpadding-bottom: 5px;\n\t\tcolor: #333;\n\t}\n\n\t.buttons {\n\t\tdisplay: flex;\n\t\tflex-wrap: wrap;\n\t\tgap: 6px;\n\t\tmargin-top: 4px;\n\t}\n\n\t.buttons button {\n\t\tpadding: 8px 10px;\n\t\tmin-width: 45px;\n\t\tborder: 1px solid #666;\n\t\tborder-radius: 8px;\n\t\tbackground: #f5f5f5;\n\t\tcursor: pointer;\n\t\ttransition: all 0.2s;\n\t\tfont-size: 0.9em;\n\t\tfont-weight: 600;\n\t}\n\n\t.buttons button:hover {\n\t\tbackground: #e3f5f3;\n\t\tborder-color: rgba(86, 221, 208, 1);\n\t}\n\n\t.buttons button.active {\n\t\tbackground: rgba(86, 221, 208, 1);\n\t\tborder-color: rgba(56, 191, 178, 1);\n\t\tcolor: #fff;\n\t}\n\n\t.mode-buttons {\n\t\tdisplay: grid;\n\t\tgrid-template-columns: 1fr;\n\t\tgap: 8px;\n\t}\n\n\t.mode-buttons button {\n\t\twidth: 100%;\n\t\ttext-align: center;\n\t}\n\n\t.params-buttons {\n\t\tdisplay: grid;\n\t\tgrid-template-columns: 1fr;\n\t\tgap: 8px;\n\t}\n\n\t.params-buttons button {\n\t\twidth: 100%;\n\t\ttext-align: center;\n\t}\n\n\t.param-select-wrap {\n\t\tposition: relative;\n\t\twidth: 100%;\n\t\tmin-height: 44px;\n\t}\n\n\t.param-select {\n\t\tposition: absolute;\n\t\tinset: 0;\n\t\twidth: 100%;\n\t\theight: 100%;\n\t\topacity: 0;\n\t\tcursor: pointer;\n\t}\n\n\t.param-select-display {\n\t\tmin-height: 44px;\n\t\tpadding: 10px 40px 10px 12px;\n\t\tborder: 1px solid #666;\n\t\tborder-radius: 8px;\n\t\tbackground: #fff;\n\t\tfont-size: 16px;\n\t\tline-height: 1.35;\n\t\tfont-weight: 500;\n\t\twhite-space: normal;\n\t\tword-break: break-word;\n\t\tposition: relative;\n\t\tpointer-events: none;\n\t}\n\n\t.param-select-display::after {\n\t\tcontent: \"\";\n\t\tposition: absolute;\n\t\tright: 14px;\n\t\ttop: 50%;\n\t\tmargin-top: -3px;\n\t\twidth: 0;\n\t\theight: 0;\n\t\tborder-left: 6px solid transparent;\n\t\tborder-right: 6px solid transparent;\n\t\tborder-top: 7px solid #666;\n\t}\n\n\t.param-select-wrap:focus-within .param-select-display {\n\t\toutline: 2px solid rgba(86, 221, 208, 0.35);\n\t\tborder-color: rgba(86, 221, 208, 1);\n\t}\n\n\t.images-grid {\n\t\tdisplay: grid;\n\t\tgrid-template-columns: 1fr;\n\t\tgap: 14px;\n\t\tmin-height: 420px;\n\t}\n\n\t.image-card {\n\t\tmargin: 0;\n\t\tborder: 1px solid #ddd;\n\t\tborder-radius: 8px;\n\t\tpadding: 8px;\n\t\tbackground: #fff;\n\t\tbox-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);\n\t}\n\n\t.image-card img {\n\t\twidth: 100%;\n\t\theight: auto;\n\t\tdisplay: block;\n\t\tborder-radius: 5px;\n\t}\n\n\t.loader-container {\n\t\tdisplay: flex;\n\t\tjustify-content: center;\n\t\talign-items: center;\n\t\tflex-direction: column;\n\t\twidth: 100%;\n\t\theight: 300px;\n\t\tz-index: 100;\n\t\tposition: relative;\n\t\tbackground-color: rgba(245, 245, 245, 0.7);\n\t\tborder-radius: 8px;\n\t\tmargin-bottom: 10px;\n\t}\n\n\t.loader {\n\t\tborder: 12px solid #f3f3f3;\n\t\tborder-radius: 50%;\n\t\tborder-top: 12px solid rgba(86, 221, 208, 1);\n\t\twidth: 90px;\n\t\theight: 90px;\n\t\tanimation: spin 0.8s linear infinite;\n\t\tbox-shadow: 0 0 20px rgba(86, 221, 208, 0.7);\n\t}\n\n\t@keyframes spin {\n\t\t0% { transform: rotate(0deg); }\n\t\t100% { transform: rotate(360deg); }\n\t}\n\n\t.date-warning {\n\t\tdisplay: none;\n\t\ttext-align: center;\n\t\tpadding: 8px 15px;\n\t\tbackground: rgba(255, 152, 0, 0.1);\n\t\tborder: 1px solid rgba(255, 152, 0, 0.3);\n\t\tborder-radius: 6px;\n\t\tfont-size: 13px;\n\t\tcolor: #e65100;\n\t\tmargin: 10px 0;\n\t\tfont-weight: 500;\n\t}\n\n\t.keyboard-info {\n\t\tfont-size: 11px;\n\t\tcolor: #555;\n\t\tmargin-top: 20px;\n\t\tpadding: 10px;\n\t\tline-height: 1.6;\n\t\tbackground-color: #f0f8ff;\n\t\tborder-left: 3px solid rgba(86, 221, 208, 1);\n\t\tborder-radius: 4px;\n\t}\n\n\t.keyboard-info strong {\n\t\tcolor: rgba(86, 221, 208, 1);\n\t\tfont-size: 12px;\n\t}\n\n\t@media (max-width: 768px) {\n\t\t.layout-container {\n\t\t\tflex-direction: column;\n\t\t}\n\n\t\t.left-column,\n\t\t.right-column {\n\t\t\tmax-width: 100%;\n\t\t\twidth: 100%;\n\t\t\tmin-width: 0;\n\t\t}\n\n\t\t.params-buttons {\n\t\t\tgrid-template-columns: 1fr;\n\t\t}\n\n\t\t.keyboard-info {\n\t\t\tdisplay: none;\n\t\t}\n\t}\n&lt;\/style&gt;\n\n&lt;script&gt;\n\tconst monthNamesUpperGen = [\n\t\t\"stycznia\", \"lutego\", \"marca\", \"kwietnia\", \"maja\", \"czerwca\",\n\t\t\"lipca\", \"sierpnia\", \"wrze\u015bnia\", \"pa\u017adziernika\", \"listopada\", \"grudnia\"\n\t];\n\n\tconst monthNamesUpperNom = [\n\t\t\"stycze\u0144\", \"luty\", \"marzec\", \"kwiecie\u0144\", \"maj\", \"czerwiec\",\n\t\t\"lipiec\", \"sierpie\u0144\", \"wrzesie\u0144\", \"pa\u017adziernik\", \"listopad\", \"grudzie\u0144\"\n\t];\n\n\tconst modeConfig = {\n\t\tday: {\n\t\t\tid: \"day\",\n\t\t\ttitlePrefix: \"Zestawienie na dzie\u0144\",\n\t\t\tsectionTitle: \"Charakterystyka:\",\n\t\t\tfolders: [\"dobowe_30lat\"]\n\t\t},\n\t\tperiod: {\n\t\t\tid: \"period\",\n\t\t\ttitlePrefix: \"Zestawienie\",\n\t\t\tsectionTitle: \"Charakterystyka:\",\n\t\t\tfolders: [\"15dni_30lat\"]\n\t\t},\n\t\tmonth: {\n\t\t\tid: \"month\",\n\t\t\ttitlePrefix: \"Zestawienie za\",\n\t\t\tsectionTitle: \"Charakterystyka:\",\n\t\t\tfolders: [\"miesieczne_30lat\"]\n\t\t}\n\t};\n\n\tconst orderedModes = [\"day\", \"period\", \"month\"];\n\n\tconst dayParameters = [\n\t\t{ id: \"TEMPSR\", label: \"Temperatura \u015brednia\", code: \"TAVE\" },\n\t\t{ id: \"TEMPMAX\", label: \"Temperatura maksymalna\", code: \"TMAX\" },\n\t\t{ id: \"TEMPMIN\", label: \"Temperatura minimalna\", code: \"TMIN\" },\n\t\t{ id: \"OPAD\", label: \"Opad\", code: \"RR\" },\n\t\t{ id: \"WIATR\", label: \"Wiatr\", code: \"WIATR\" },\n\t\t{ id: \"PKSN\", label: \"Pokrywa \u015bnie\u017cna\", code: \"PKSN\" }\n\t];\n\n\tconst periodMonthParameters = [\n\t\t{ id: \"LD_OPAD_01\", label: \"Liczba dni z opadem &gt;= 0.1mm\", code: \"LD_OPAD_01\" },\n\t\t{ id: \"LD_PKSN\", label: \"Liczba dni z pokryw\u0105 \u015bnie\u017cn\u0105 &gt;= 1cm\", code: \"LD_PKSN\" },\n\t\t{ id: \"LD_PORYWY_55\", label: \"Liczba dni z porywem wiatru &gt;= 55km\/h\", code: \"LD_PORYWY_55\" },\n\t\t{ id: \"LD_TMAX_25\", label: \"Liczba dni z temperatur\u0105 &gt;= 25\u00b0C\", code: \"LD_TMAX_25\" },\n\t\t{ id: \"LD_TMAX_30\", label: \"Liczba dni z temperatur\u0105 &gt;= 30\u00b0C\", code: \"LD_TMAX_30\" },\n\t\t{ id: \"LD_TMIN_PON_0\", label: \"Liczba dni z temperatur\u0105 &lt; 0\u00b0C\", code: \"LD_TMIN_PON_0\" },\n\t\t{ id: \"LD_TMIN_PON_10\", label: \"Liczba dni z temperatur\u0105 &lt;= -10\u00b0C\", code: \"LD_TMIN_PON_10\" },\n\t\t{ id: \"LD_TMIN_PON_15\", label: \"Liczba dni z temperatur\u0105 &lt;= -15\u00b0C\", code: \"LD_TMIN_PON_15\" },\n\t\t{ id: \"LD_TMIN_PON_20\", label: \"Liczba dni z temperatur\u0105 &lt;= -20\u00b0C\", code: \"LD_TMIN_PON_20\" },\n\t\t{ id: \"LD_TMIN_PON_25\", label: \"Liczba dni z temperatur\u0105 &lt;= -25\u00b0C\", code: \"LD_TMIN_PON_25\" },\n\t\t{ id: \"PKSN\", label: \"Maksymalna grubo\u015b\u0107 pokrywy \u015bnie\u017cnej (cm)\", code: \"PKSN\" },\n\t\t{ id: \"PKSN_AVE\", label: \"\u015arednia grubo\u015b\u0107 pokrywy \u015bnie\u017cnej (cm)\", code: \"PKSN_AVE\" },\n\t\t{ id: \"RR_ANOM\", label: \"Anomalia sumy opadu (%) wzgl\u0119dem lat 1991-2020\", code: \"RR_anom\" },\n\t\t{ id: \"RR\", label: \"Suma opadu (mm)\", code: \"RR\" },\n\t\t{ id: \"SMBD\", label: \"Maksymalny dobowy opad (mm)\", code: \"SMBD\" },\n\t\t{ id: \"TAVE_ANOM\", label: \"Anomalia \u015bredniej temperatury (\u00b0C) wzgl\u0119dem lat 1991-2020\", code: \"TAVE_anom\" },\n\t\t{ id: \"TAVE\", label: \"\u015arednia temperatura (\u00b0C)\", code: \"TAVE\" },\n\t\t{ id: \"TMAX_AVE\", label: \"\u015arednia maksymalna temperatura (\u00b0C)\", code: \"TMAX_AVE\" },\n\t\t{ id: \"TMAX\", label: \"Maksymalna temperatura (\u00b0C)\", code: \"TMAX\" },\n\t\t{ id: \"TMIN_AVE\", label: \"\u015arednia minimalna temperatura (\u00b0C)\", code: \"TMIN_AVE\" },\n\t\t{ id: \"TMIN\", label: \"Minimalna temperatura (\u00b0C)\", code: \"TMIN\" },\n\t\t{ id: \"WIATR_AVG\", label: \"\u015arednia pr\u0119dko\u015b\u0107 wiatru (km\/h)\", code: \"Wiatr\" }\n\t];\n\n\tconst modeButtonsEl = document.getElementById(\"modeButtons\");\n\tconst paramButtonsEl = document.getElementById(\"paramButtons\");\n\tconst paramTitleEl = document.getElementById(\"paramTitle\");\n\tconst imagesEl = document.getElementById(\"images\");\n\tconst noDataEl = document.getElementById(\"noData\");\n\tconst loaderEl = document.getElementById(\"loader\");\n\n\tconst now = new Date();\n\tconst dayDate = new Date(now.getFullYear(), now.getMonth(), now.getDate());\n\tconst periodStartDate = new Date(now.getFullYear(), now.getMonth(), now.getDate());\n\tperiodStartDate.setDate(periodStartDate.getDate() - 7);\n\tconst periodEndDate = new Date(now.getFullYear(), now.getMonth(), now.getDate());\n\tperiodEndDate.setDate(periodEndDate.getDate() + 7);\n\tconst monthDate = new Date(now.getFullYear(), now.getMonth(), 1);\n\n\tconst state = {\n\t\tmode: \"day\",\n\t\tparam: \"TEMPSR\"\n\t};\n\n\tconst bridge = window.__switcherBridge;\n\tconst initialState = bridge ? bridge.getInitialState(\"climate\") : null;\n\n\tif (initialState) {\n\t\tif (typeof initialState.mode === \"string\" &amp;&amp; orderedModes.includes(initialState.mode)) {\n\t\t\tstate.mode = initialState.mode;\n\t\t}\n\n\t\tif (typeof initialState.param === \"string\") {\n\t\t\tstate.param = initialState.param;\n\t\t}\n\t}\n\n\tlet renderToken = 0;\n\tconst imageAvailabilityCache = new Map();\n\tconst imagePreloadPromises = new Map();\n\n\tfunction syncUrlState() {\n\t\tif (!bridge) {\n\t\t\treturn;\n\t\t}\n\n\t\tbridge.updateState(\"climate\", {\n\t\t\tmode: state.mode,\n\t\t\tparam: state.param\n\t\t});\n\t}\n\n\tfunction isDropdownMode(modeId) {\n\t\treturn modeId === \"period\" || modeId === \"month\";\n\t}\n\n\tfunction getParametersForMode(modeId) {\n\t\tif (modeId === \"day\") {\n\t\t\treturn dayParameters;\n\t\t}\n\t\treturn periodMonthParameters;\n\t}\n\n\tfunction ensureActiveParameterForMode() {\n\t\tconst modeParams = getParametersForMode(state.mode);\n\t\tif (!modeParams.some((item) =&gt; item.id === state.param)) {\n\t\t\tstate.param = modeParams[0].id;\n\t\t}\n\t}\n\n\tfunction formatDayLabel(date) {\n\t\treturn `${date.getDate()} ${monthNamesUpperGen[date.getMonth()]}`;\n\t}\n\n\tfunction formatMonthLabel(date) {\n\t\treturn monthNamesUpperNom[date.getMonth()];\n\t}\n\n\tfunction formatPeriodLabel(startDate, endDate) {\n\t\tconst startPart = `${startDate.getDate()} ${monthNamesUpperGen[startDate.getMonth()]}`;\n\t\tconst endPart = `${endDate.getDate()} ${monthNamesUpperGen[endDate.getMonth()]}`;\n\t\treturn `${startPart} - ${endPart}`;\n\t}\n\n\tfunction getModeButtonText(modeId) {\n\t\tif (modeId === \"day\") {\n\t\t\treturn `${modeConfig.day.titlePrefix} ${formatDayLabel(dayDate)}`;\n\t\t}\n\t\tif (modeId === \"period\") {\n\t\t\treturn `${modeConfig.period.titlePrefix} ${formatPeriodLabel(periodStartDate, periodEndDate)}`;\n\t\t}\n\t\treturn `${modeConfig.month.titlePrefix} ${formatMonthLabel(monthDate)}`;\n\t}\n\n\tfunction getModeDisplayPeriod(modeId) {\n\t\tif (modeId === \"day\") {\n\t\t\treturn formatDayLabel(dayDate);\n\t\t}\n\t\tif (modeId === \"period\") {\n\t\t\treturn formatPeriodLabel(periodStartDate, periodEndDate);\n\t\t}\n\t\treturn formatMonthLabel(monthDate);\n\t}\n\n\tfunction setLoading(isLoading) {\n\t\tloaderEl.style.display = isLoading ? \"flex\" : \"none\";\n\t}\n\n\tfunction setActiveModeButton() {\n\t\tmodeButtonsEl.querySelectorAll(\"button\").forEach((button) =&gt; {\n\t\t\tbutton.classList.toggle(\"active\", button.dataset.mode === state.mode);\n\t\t});\n\t}\n\n\tfunction setActiveParamButton() {\n\t\tconst select = paramButtonsEl.querySelector(\"select\");\n\t\tif (select) {\n\t\t\tconst modeParams = getParametersForMode(state.mode);\n\t\t\tconst selected = modeParams.find((item) =&gt; item.id === state.param) || modeParams[0];\n\t\t\tselect.value = selected.id;\n\t\t\tselect.title = selected.label;\n\n\t\t\tconst display = paramButtonsEl.querySelector(\".param-select-display\");\n\t\t\tif (display) {\n\t\t\t\tdisplay.textContent = selected.label;\n\t\t\t}\n\t\t}\n\n\t\tparamButtonsEl.querySelectorAll(\"button\").forEach((button) =&gt; {\n\t\t\tbutton.classList.toggle(\"active\", button.dataset.param === state.param);\n\t\t});\n\n\t}\n\n\tfunction getFileCandidates(paramCode, modeId) {\n\t\tif (modeId === \"day\" &amp;&amp; paramCode === \"WIATR\") {\n\t\t\treturn [\"WIATR.png\", \"Wiatr.png\"];\n\t\t}\n\t\treturn [`${paramCode}.png`];\n\t}\n\n\tfunction buildImageCandidates(paramCode, modeId) {\n\t\tconst folders = modeConfig[modeId].folders;\n\t\tconst fileCandidates = getFileCandidates(paramCode, modeId);\n\n\t\tconst urls = [];\n\t\tfolders.forEach((folder) =&gt; {\n\t\t\tfileCandidates.forEach((fileName) =&gt; {\n\t\t\t\turls.push(`\/cmm\/wp-content\/uploads\/production\/analizy_meteo\/${folder}\/${fileName}`);\n\t\t\t});\n\t\t});\n\n\t\treturn urls;\n\t}\n\n\tfunction preloadImage(src) {\n\t\tif (imageAvailabilityCache.has(src)) {\n\t\t\treturn Promise.resolve(imageAvailabilityCache.get(src));\n\t\t}\n\n\t\tif (imagePreloadPromises.has(src)) {\n\t\t\treturn imagePreloadPromises.get(src);\n\t\t}\n\n\t\tconst preloadPromise = new Promise((resolve) =&gt; {\n\t\t\tconst img = new Image();\n\n\t\t\timg.onload = () =&gt; {\n\t\t\t\timageAvailabilityCache.set(src, true);\n\t\t\t\timagePreloadPromises.delete(src);\n\t\t\t\tresolve(true);\n\t\t\t};\n\n\t\t\timg.onerror = () =&gt; {\n\t\t\t\timageAvailabilityCache.set(src, false);\n\t\t\t\timagePreloadPromises.delete(src);\n\t\t\t\tresolve(false);\n\t\t\t};\n\n\t\t\timg.src = src;\n\t\t});\n\n\t\timagePreloadPromises.set(src, preloadPromise);\n\t\treturn preloadPromise;\n\t}\n\n\tfunction preloadModeImages(modeId) {\n\t\tconst modeParams = getParametersForMode(modeId);\n\t\tmodeParams.forEach((param) =&gt; {\n\t\t\tconst candidates = buildImageCandidates(param.code, modeId);\n\t\t\tcandidates.forEach((src) =&gt; {\n\t\t\t\tvoid preloadImage(src);\n\t\t\t});\n\t\t});\n\t}\n\n\tfunction checkImageExists(src) {\n\t\treturn preloadImage(src);\n\t}\n\n\tasync function findFirstAvailableImagePath(paramCode, modeId) {\n\t\tconst candidates = buildImageCandidates(paramCode, modeId);\n\t\tfor (const candidate of candidates) {\n\t\t\tconst exists = await checkImageExists(candidate);\n\t\t\tif (exists) {\n\t\t\t\treturn candidate;\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\n\tfunction renderModeButtons() {\n\t\tmodeButtonsEl.innerHTML = \"\";\n\n\t\torderedModes.forEach((modeId) =&gt; {\n\t\t\tconst button = document.createElement(\"button\");\n\t\t\tbutton.type = \"button\";\n\t\t\tbutton.dataset.mode = modeId;\n\t\t\tbutton.textContent = getModeButtonText(modeId);\n\t\t\tbutton.addEventListener(\"click\", () =&gt; {\n\t\t\t\tstate.mode = modeId;\n\t\t\t\tensureActiveParameterForMode();\n\t\t\t\tpreloadModeImages(state.mode);\n\t\t\t\tparamTitleEl.textContent = modeConfig[modeId].sectionTitle;\n\t\t\t\tsetActiveModeButton();\n\t\t\t\trenderParamButtons();\n\t\t\t\trenderImage();\n\t\t\t});\n\t\t\tmodeButtonsEl.appendChild(button);\n\t\t});\n\n\t\tsetActiveModeButton();\n\t}\n\n\tfunction selectNextMode(step) {\n\t\tconst currentIndex = orderedModes.indexOf(state.mode);\n\t\tif (currentIndex === -1) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst nextIndex = (currentIndex + step + orderedModes.length) % orderedModes.length;\n\t\tstate.mode = orderedModes[nextIndex];\n\t\tensureActiveParameterForMode();\n\t\tparamTitleEl.textContent = modeConfig[state.mode].sectionTitle;\n\t\tsetActiveModeButton();\n\t\trenderParamButtons();\n\t\trenderImage();\n\t}\n\n\tfunction selectModeByIndex(index) {\n\t\tconst modeId = orderedModes[index];\n\t\tif (!modeId) {\n\t\t\treturn;\n\t\t}\n\n\t\tstate.mode = modeId;\n\t\tensureActiveParameterForMode();\n\t\tparamTitleEl.textContent = modeConfig[state.mode].sectionTitle;\n\t\tsetActiveModeButton();\n\t\trenderParamButtons();\n\t\trenderImage();\n\t}\n\n\tfunction renderParamButtons() {\n\t\tparamButtonsEl.innerHTML = \"\";\n\t\tconst modeParams = getParametersForMode(state.mode);\n\n\t\tif (isDropdownMode(state.mode)) {\n\t\t\tconst wrap = document.createElement(\"div\");\n\t\t\twrap.className = \"param-select-wrap\";\n\n\t\t\tconst select = document.createElement(\"select\");\n\t\t\tselect.className = \"param-select\";\n\t\t\tselect.setAttribute(\"aria-label\", \"Wybierz charakterystyk\u0119\");\n\n\t\t\tmodeParams.forEach((param) =&gt; {\n\t\t\t\tconst option = document.createElement(\"option\");\n\t\t\t\toption.value = param.id;\n\t\t\t\toption.textContent = param.label;\n\t\t\t\tselect.appendChild(option);\n\t\t\t});\n\n\t\t\tselect.addEventListener(\"change\", (event) =&gt; {\n\t\t\t\tstate.param = event.target.value;\n\t\t\t\tsetActiveParamButton();\n\t\t\t\trenderImage();\n\t\t\t});\n\n\t\t\tconst display = document.createElement(\"div\");\n\t\t\tdisplay.className = \"param-select-display\";\n\n\t\t\twrap.appendChild(select);\n\t\t\twrap.appendChild(display);\n\t\t\tparamButtonsEl.appendChild(wrap);\n\n\t\t\tsetActiveParamButton();\n\t\t\treturn;\n\t\t}\n\n\t\tmodeParams.forEach((param) =&gt; {\n\t\t\tconst button = document.createElement(\"button\");\n\t\t\tbutton.type = \"button\";\n\t\t\tbutton.dataset.param = param.id;\n\t\t\tbutton.textContent = param.label;\n\t\t\tbutton.addEventListener(\"click\", () =&gt; {\n\t\t\t\tstate.param = param.id;\n\t\t\t\tsetActiveParamButton();\n\t\t\t\trenderImage();\n\t\t\t});\n\t\t\tparamButtonsEl.appendChild(button);\n\t\t});\n\n\t\tsetActiveParamButton();\n\t}\n\n\tfunction appendImageCard(imagePath) {\n\t\tconst figure = document.createElement(\"figure\");\n\t\tfigure.className = \"image-card\";\n\n\t\tconst link = document.createElement(\"a\");\n\t\tlink.href = imagePath;\n\t\tlink.target = \"_blank\";\n\t\tlink.rel = \"noopener\";\n\n\t\tconst image = document.createElement(\"img\");\n\t\timage.src = imagePath;\n\t\timage.alt = \"Mapa statystyki 30-letniej\";\n\n\t\tlink.appendChild(image);\n\t\tfigure.appendChild(link);\n\t\timagesEl.appendChild(figure);\n\t}\n\n\tasync function renderImage() {\n\t\timagesEl.innerHTML = \"\";\n\t\tnoDataEl.style.display = \"none\";\n\t\tsetLoading(true);\n\t\tsyncUrlState();\n\t\tconst token = ++renderToken;\n\n\t\tconst modeParams = getParametersForMode(state.mode);\n\t\tconst selectedParam = modeParams.find((item) =&gt; item.id === state.param) || modeParams[0];\n\t\tconst imagePath = await findFirstAvailableImagePath(selectedParam.code, state.mode);\n\n\t\tif (token !== renderToken) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (imagePath) {\n\t\t\tappendImageCard(imagePath);\n\t\t} else {\n\t\t\tnoDataEl.style.display = \"block\";\n\t\t}\n\n\t\tsetLoading(false);\n\t}\n\n\tfunction selectNextParam(step) {\n\t\tconst modeParams = getParametersForMode(state.mode);\n\t\tconst currentIndex = modeParams.findIndex((item) =&gt; item.id === state.param);\n\t\tif (currentIndex === -1) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst nextIndex = (currentIndex + step + modeParams.length) % modeParams.length;\n\t\tstate.param = modeParams[nextIndex].id;\n\t\tsetActiveParamButton();\n\t\trenderImage();\n\t}\n\n\tfunction shouldIgnoreKeyboardEvent(event) {\n\t\tconst target = event.target;\n\t\tif (!target) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst tag = target.tagName ? target.tagName.toLowerCase() : \"\";\n\t\treturn tag === \"input\" || tag === \"textarea\" || tag === \"select\" || target.isContentEditable;\n\t}\n\n\tdocument.addEventListener(\"keydown\", (event) =&gt; {\n\t\tif (shouldIgnoreKeyboardEvent(event)) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"1\") {\n\t\t\tevent.preventDefault();\n\t\t\tselectModeByIndex(0);\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"2\") {\n\t\t\tevent.preventDefault();\n\t\t\tselectModeByIndex(1);\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"3\") {\n\t\t\tevent.preventDefault();\n\t\t\tselectModeByIndex(2);\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"ArrowUp\") {\n\t\t\tevent.preventDefault();\n\t\t\tselectNextParam(-1);\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === \"ArrowDown\") {\n\t\t\tevent.preventDefault();\n\t\t\tselectNextParam(1);\n\t\t}\n\t});\n\n\trenderModeButtons();\n\tensureActiveParameterForMode();\n\torderedModes.forEach((modeId) =&gt; preloadModeImages(modeId));\n\trenderParamButtons();\n\tparamTitleEl.textContent = modeConfig[state.mode].sectionTitle;\n\trenderImage();\nconsole.log(\"Autor Bart\u0142omiej Sobczyk 2026\");\n&lt;\/script&gt;\n  <\/textarea>\n<\/div>\n\n<style>\n  .summary-switcher-app {\n    font-family: Arial, sans-serif;\n    max-width: 1280px;\n    margin: 0 auto;\n  }\n\n  .switcher-toolbar {\n    display: grid;\n    grid-template-columns: repeat(3, minmax(0, 1fr));\n    gap: 8px;\n    margin-bottom: 10px;\n  }\n\n  .switcher-tab {\n    padding: 10px 12px;\n    border: 1px solid #666;\n    border-radius: 8px;\n    background: #f5f5f5;\n    color: #333;\n    cursor: pointer;\n    font-size: 0.95em;\n    font-weight: 500;\n    transition: all 0.2s;\n  }\n\n  .switcher-tab:hover {\n    background: #e3f5f3;\n    border-color: rgba(86, 221, 208, 1);\n  }\n\n  .switcher-tab.active {\n    background: rgba(86, 221, 208, 1);\n    border-color: rgba(56, 191, 178, 1);\n    color: #fff;\n  }\n\n  .switcher-panels {\n    background: #f9f9f9;\n    border-radius: 10px;\n    padding: 8px;\n    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.12);\n  }\n\n  .switcher-panel {\n    display: none;\n  }\n\n  .switcher-panel.active {\n    display: block;\n  }\n\n  .panel-frame {\n    width: 100%;\n    min-height: 980px;\n    border: none;\n    border-radius: 8px;\n    background: #fff;\n  }\n\n  .embedded-template {\n    display: none;\n  }\n\n  @media (max-width: 900px) {\n    .switcher-toolbar {\n      grid-template-columns: 1fr;\n    }\n\n    .panel-frame {\n      min-height: 860px;\n    }\n  }\n<\/style>\n\n<script>\n  const tabs = Array.from(document.querySelectorAll(\".switcher-tab\"));\n  const panels = Array.from(document.querySelectorAll(\".switcher-panel\"));\n\tconst allowedViews = [\"current\", \"monthly\", \"climate\"];\n  const templateByView = {\n    current: document.getElementById(\"template-current\"),\n    monthly: document.getElementById(\"template-monthly\"),\n    climate: document.getElementById(\"template-climate\")\n  };\n\n\tfunction parseIntegerParam(value) {\n\t\tif (value === null || value === \"\") {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst parsed = Number.parseInt(value, 10);\n\t\treturn Number.isNaN(parsed) ? null : parsed;\n\t}\n\n\tfunction readInitialUrlState() {\n\t\tconst params = new URLSearchParams(window.location.search);\n\t\tconst view = params.get(\"view\");\n\t\tconst now = new Date();\n\t\tconst defaultMonthlyDate = new Date(now.getFullYear(), now.getMonth() - 1, 1);\n\n\t\treturn {\n\t\t\tview: allowedViews.includes(view) ? view : \"current\",\n\t\t\tcurrent: {\n\t\t\t\tmode: params.get(\"c_mode\") || \"summary\",\n\t\t\t\tparam: params.get(\"c_param\") || \"TAVE\"\n\t\t\t},\n\t\t\tmonthly: {\n\t\t\t\tyear: parseIntegerParam(params.get(\"m_year\")) || defaultMonthlyDate.getFullYear(),\n\t\t\t\tmonth: parseIntegerParam(params.get(\"m_month\")) || defaultMonthlyDate.getMonth() + 1,\n\t\t\t\tparam: params.get(\"m_param\") || \"TEMPSR\",\n\t\t\t\tviewMode: params.get(\"m_view\") || \"single\",\n\t\t\t\tperiodPinned: params.has(\"m_year\") || params.has(\"m_month\")\n\t\t\t},\n\t\t\tclimate: {\n\t\t\t\tmode: params.get(\"cl_mode\") || \"day\",\n\t\t\t\tparam: params.get(\"cl_param\") || \"TEMPSR\"\n\t\t\t}\n\t\t};\n\t}\n\n\tconst urlState = readInitialUrlState();\n\twriteUrlState();\n\n\tfunction writeUrlState() {\n\t\tconst params = new URLSearchParams(window.location.search);\n\t\tconst managedKeys = [\n\t\t\t\"view\",\n\t\t\t\"c_mode\", \"c_param\",\n\t\t\t\"m_year\", \"m_month\", \"m_param\", \"m_view\",\n\t\t\t\"cl_mode\", \"cl_param\"\n\t\t];\n\t\tmanagedKeys.forEach((key) => params.delete(key));\n\n\t\tconst setOrDelete = (key, value) => {\n\t\t\tif (value === null || value === undefined || value === \"\") {\n\t\t\t\tparams.delete(key);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tparams.set(key, String(value));\n\t\t};\n\n\t\tsetOrDelete(\"view\", urlState.view);\n\n\t\tif (urlState.view === \"current\") {\n\t\t\tsetOrDelete(\"c_mode\", urlState.current.mode);\n\t\t\tsetOrDelete(\"c_param\", urlState.current.param);\n\t\t}\n\n\t\tif (urlState.view === \"monthly\") {\n\t\t\tsetOrDelete(\"m_year\", urlState.monthly.year);\n\t\t\tsetOrDelete(\"m_month\", urlState.monthly.month);\n\t\t\tsetOrDelete(\"m_param\", urlState.monthly.param);\n\t\t\tsetOrDelete(\"m_view\", urlState.monthly.viewMode);\n\t\t}\n\n\t\tif (urlState.view === \"climate\") {\n\t\t\tsetOrDelete(\"cl_mode\", urlState.climate.mode);\n\t\t\tsetOrDelete(\"cl_param\", urlState.climate.param);\n\t\t}\n\n\t\tconst query = params.toString();\n\t\tconst nextUrl = `${window.location.pathname}${query ? `?${query}` : \"\"}${window.location.hash}`;\n\t\twindow.history.replaceState(null, \"\", nextUrl);\n\t}\n\n\twindow.__summarySwitcherBridge = {\n\t\tgetInitialState(viewId) {\n\t\t\treturn urlState[viewId] ? { ...urlState[viewId] } : null;\n\t\t},\n\t\tupdateState(viewId, patch) {\n\t\t\tif (!urlState[viewId] || !patch || typeof patch !== \"object\") {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\turlState[viewId] = {\n\t\t\t\t...urlState[viewId],\n\t\t\t\t...patch\n\t\t\t};\n\t\t\twriteUrlState();\n\t\t}\n\t};\n\n\tfunction getInitialView() {\n\t\treturn allowedViews.includes(urlState.view) ? urlState.view : \"current\";\n\t}\n\n\tfunction syncMainViewInUrl(viewId) {\n\t\tif (!allowedViews.includes(viewId)) {\n\t\t\treturn;\n\t\t}\n\n\t\turlState.view = viewId;\n\t\twriteUrlState();\n\t}\n\n  function buildSrcdoc(viewId) {\n    const source = templateByView[viewId];\n    if (!source) {\n      return \"\";\n    }\n\t\treturn `<!doctype html><html><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><style>body{margin:0}#forecast-app .section h3,#forecast-app .image-header h3{font-weight:400!important}#forecast-app .buttons button,#forecast-app .tablinks,#forecast-app .control-btn{font-weight:400!important}#forecast-app{font-synthesis-weight:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}<\/style><\/head><body><script>window.__switcherBridge=window.parent&&window.parent.__summarySwitcherBridge?window.parent.__summarySwitcherBridge:null;<\\\/script>${source.value}<\/body><\/html>`;\n  }\n\n  function isEditableTarget(target) {\n    if (!target) {\n      return false;\n    }\n\n    const tag = target.tagName ? target.tagName.toLowerCase() : \"\";\n    return tag === \"input\" || tag === \"textarea\" || tag === \"select\" || target.isContentEditable;\n  }\n\n  function switchTabByOffset(offset) {\n    const activeIndex = tabs.findIndex((tab) => tab.classList.contains(\"active\"));\n    if (activeIndex === -1) {\n      return;\n    }\n\n    const nextIndex = (activeIndex + offset + tabs.length) % tabs.length;\n    setActiveView(tabs[nextIndex].dataset.view);\n  }\n\n  function handleMainTabShortcuts(event) {\n    if (isEditableTarget(event.target)) {\n      return;\n    }\n\n    if (event.key === \"<\" || event.key === \",\") {\n      event.preventDefault();\n      switchTabByOffset(-1);\n      return;\n    }\n\n    if (event.key === \">\" || event.key === \".\") {\n      event.preventDefault();\n      switchTabByOffset(1);\n    }\n  }\n\n  function bindFrameShortcutBridge(frame) {\n    if (!frame || frame.dataset.shortcutBridgeBound === \"1\") {\n      return;\n    }\n\n    frame.addEventListener(\"load\", () => {\n      try {\n        const doc = frame.contentDocument;\n        if (!doc || doc.documentElement.dataset.mainTabShortcutsBound === \"1\") {\n          return;\n        }\n\n        doc.addEventListener(\"keydown\", handleMainTabShortcuts);\n        doc.documentElement.dataset.mainTabShortcutsBound = \"1\";\n      } catch (error) {\n        console.warn(\"Nie udalo sie podpiac skrotow dla iframe\", error);\n      }\n    });\n\n    frame.dataset.shortcutBridgeBound = \"1\";\n  }\n\n  function ensureFrameLoaded(panel) {\n    const frame = panel.querySelector(\".panel-frame\");\n    if (!frame) {\n      return;\n    }\n\n    bindFrameShortcutBridge(frame);\n\n    if (frame.dataset.loaded === \"1\") {\n      return;\n    }\n\n    const viewId = panel.dataset.panel;\n    frame.srcdoc = buildSrcdoc(viewId);\n    frame.dataset.loaded = \"1\";\n  }\n\n  function setActiveView(viewId) {\n\t\tif (!allowedViews.includes(viewId)) {\n\t\t\treturn;\n\t\t}\n\n    let activeFrame = null;\n\n    tabs.forEach((tab) => {\n      const isActive = tab.dataset.view === viewId;\n      tab.classList.toggle(\"active\", isActive);\n      tab.setAttribute(\"aria-selected\", isActive ? \"true\" : \"false\");\n    });\n\n    panels.forEach((panel) => {\n      const isActive = panel.dataset.panel === viewId;\n      panel.classList.toggle(\"active\", isActive);\n      panel.hidden = !isActive;\n      if (isActive) {\n        ensureFrameLoaded(panel);\n        activeFrame = panel.querySelector(\".panel-frame\");\n      }\n    });\n\n    if (activeFrame) {\n      activeFrame.focus();\n    }\n\n\t\tsyncMainViewInUrl(viewId);\n  }\n\n  tabs.forEach((tab) => {\n    tab.addEventListener(\"click\", () => setActiveView(tab.dataset.view));\n  });\n\n  document.addEventListener(\"keydown\", handleMainTabShortcuts);\n\n\tsetActiveView(getInitialView());\n  console.log(\"Autor Bart\u0142omiej Sobczyk 2026\");\n<\/script>\n\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-c1d4600 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"c1d4600\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-0ca756d\" data-id=\"0ca756d\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-element elementor-element-d7d8b01 elementor-widget-divider--view-line_text elementor-widget-divider--element-align-center elementor-widget elementor-widget-divider\" data-id=\"d7d8b01\" data-element_type=\"widget\" data-widget_type=\"divider.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<style>\/*! elementor - v3.12.1 - 02-04-2023 *\/\n.elementor-widget-divider{--divider-border-style:none;--divider-border-width:1px;--divider-color:#0c0d0e;--divider-icon-size:20px;--divider-element-spacing:10px;--divider-pattern-height:24px;--divider-pattern-size:20px;--divider-pattern-url:none;--divider-pattern-repeat:repeat-x}.elementor-widget-divider .elementor-divider{display:flex}.elementor-widget-divider .elementor-divider__text{font-size:15px;line-height:1;max-width:95%}.elementor-widget-divider .elementor-divider__element{margin:0 var(--divider-element-spacing);flex-shrink:0}.elementor-widget-divider .elementor-icon{font-size:var(--divider-icon-size)}.elementor-widget-divider .elementor-divider-separator{display:flex;margin:0;direction:ltr}.elementor-widget-divider--view-line_icon .elementor-divider-separator,.elementor-widget-divider--view-line_text .elementor-divider-separator{align-items:center}.elementor-widget-divider--view-line_icon .elementor-divider-separator:after,.elementor-widget-divider--view-line_icon .elementor-divider-separator:before,.elementor-widget-divider--view-line_text .elementor-divider-separator:after,.elementor-widget-divider--view-line_text .elementor-divider-separator:before{display:block;content:\"\";border-bottom:0;flex-grow:1;border-top:var(--divider-border-width) var(--divider-border-style) var(--divider-color)}.elementor-widget-divider--element-align-left .elementor-divider .elementor-divider-separator>.elementor-divider__svg:first-of-type{flex-grow:0;flex-shrink:100}.elementor-widget-divider--element-align-left .elementor-divider-separator:before{content:none}.elementor-widget-divider--element-align-left .elementor-divider__element{margin-left:0}.elementor-widget-divider--element-align-right .elementor-divider .elementor-divider-separator>.elementor-divider__svg:last-of-type{flex-grow:0;flex-shrink:100}.elementor-widget-divider--element-align-right .elementor-divider-separator:after{content:none}.elementor-widget-divider--element-align-right .elementor-divider__element{margin-right:0}.elementor-widget-divider:not(.elementor-widget-divider--view-line_text):not(.elementor-widget-divider--view-line_icon) .elementor-divider-separator{border-top:var(--divider-border-width) var(--divider-border-style) var(--divider-color)}.elementor-widget-divider--separator-type-pattern{--divider-border-style:none}.elementor-widget-divider--separator-type-pattern.elementor-widget-divider--view-line .elementor-divider-separator,.elementor-widget-divider--separator-type-pattern:not(.elementor-widget-divider--view-line) .elementor-divider-separator:after,.elementor-widget-divider--separator-type-pattern:not(.elementor-widget-divider--view-line) .elementor-divider-separator:before,.elementor-widget-divider--separator-type-pattern:not([class*=elementor-widget-divider--view]) .elementor-divider-separator{width:100%;min-height:var(--divider-pattern-height);-webkit-mask-size:var(--divider-pattern-size) 100%;mask-size:var(--divider-pattern-size) 100%;-webkit-mask-repeat:var(--divider-pattern-repeat);mask-repeat:var(--divider-pattern-repeat);background-color:var(--divider-color);-webkit-mask-image:var(--divider-pattern-url);mask-image:var(--divider-pattern-url)}.elementor-widget-divider--no-spacing{--divider-pattern-size:auto}.elementor-widget-divider--bg-round{--divider-pattern-repeat:round}.rtl .elementor-widget-divider .elementor-divider__text{direction:rtl}.e-con-inner>.elementor-widget-divider,.e-con>.elementor-widget-divider{width:var(--container-widget-width,100%);--flex-grow:var(--container-widget-flex-grow)}<\/style>\t\t<div class=\"elementor-divider\">\n\t\t\t<span class=\"elementor-divider-separator\">\n\t\t\t\t\t\t\t<h2 class=\"elementor-divider__text elementor-divider__element\">\n\t\t\t\tUDOST\u0118PNIJ STRON\u0118\t\t\t\t<\/h2>\n\t\t\t\t\t\t<\/span>\n\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Podsumowanie bie\u017c\u0105cego miesi\u0105ca Statystyka 30-letnia Zestawienie miesi\u0119czne &lt;br \/&gt; &lt;div id=&#8221;forecast-app&#8221;&gt;&lt;br \/&gt; &lt;div&gt;&lt;br \/&gt; &lt;div&gt;&lt;br \/&gt; &lt;div&gt;&lt;br \/&gt; &lt;h3&gt;Podsumowanie:&lt;\/h3&gt;&lt;br \/&gt; &lt;div id=&#8221;modeButtons&#8221;&gt;&lt;\/div&gt;&lt;br \/&gt; &lt;\/div&gt;&lt;br \/&gt; &lt;div&gt;&lt;br \/&gt; &lt;h3&gt;Charakterystyka:&lt;\/h3&gt;&lt;br \/&gt; &lt;div id=&#8221;paramButtons&#8221;&gt;&lt;\/div&gt;&lt;br \/&gt; &lt;\/div&gt;&lt;br \/&gt; &lt;div&gt;&lt;br \/&gt; &lt;strong&gt;\ud83d\udca1 Skr\u00f3ty klawiszowe:&lt;\/strong&gt;&lt;br&gt;&lt;br \/&gt; 1-2 wyb\u00f3r widoku&lt;br&gt;&lt;br \/&gt; \u2191, \u2193 zmiana charakterystyki&lt;br&gt;&lt;br \/&gt; &amp;lt; &amp;gt; zmiana karty g\u0142\u00f3wnej&lt;br \/&gt; [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_header_footer","meta":{"ocean_post_layout":"","ocean_both_sidebars_style":"","ocean_both_sidebars_content_width":0,"ocean_both_sidebars_sidebars_width":0,"ocean_sidebar":"0","ocean_second_sidebar":"0","ocean_disable_margins":"enable","ocean_add_body_class":"","ocean_shortcode_before_top_bar":"","ocean_shortcode_after_top_bar":"","ocean_shortcode_before_header":"","ocean_shortcode_after_header":"","ocean_has_shortcode":"","ocean_shortcode_after_title":"","ocean_shortcode_before_footer_widgets":"","ocean_shortcode_after_footer_widgets":"","ocean_shortcode_before_footer_bottom":"","ocean_shortcode_after_footer_bottom":"","ocean_display_top_bar":"off","ocean_display_header":"off","ocean_header_style":"custom","ocean_center_header_left_menu":"0","ocean_custom_header_template":"2993","ocean_custom_logo":0,"ocean_custom_retina_logo":0,"ocean_custom_logo_max_width":0,"ocean_custom_logo_tablet_max_width":0,"ocean_custom_logo_mobile_max_width":0,"ocean_custom_logo_max_height":0,"ocean_custom_logo_tablet_max_height":0,"ocean_custom_logo_mobile_max_height":0,"ocean_header_custom_menu":"0","ocean_menu_typo_font_family":"0","ocean_menu_typo_font_subset":"","ocean_menu_typo_font_size":0,"ocean_menu_typo_font_size_tablet":0,"ocean_menu_typo_font_size_mobile":0,"ocean_menu_typo_font_size_unit":"px","ocean_menu_typo_font_weight":"","ocean_menu_typo_font_weight_tablet":"","ocean_menu_typo_font_weight_mobile":"","ocean_menu_typo_transform":"","ocean_menu_typo_transform_tablet":"","ocean_menu_typo_transform_mobile":"","ocean_menu_typo_line_height":0,"ocean_menu_typo_line_height_tablet":0,"ocean_menu_typo_line_height_mobile":0,"ocean_menu_typo_line_height_unit":"","ocean_menu_typo_spacing":0,"ocean_menu_typo_spacing_tablet":0,"ocean_menu_typo_spacing_mobile":0,"ocean_menu_typo_spacing_unit":"","ocean_menu_link_color":"","ocean_menu_link_color_hover":"","ocean_menu_link_color_active":"","ocean_menu_link_background":"","ocean_menu_link_hover_background":"","ocean_menu_link_active_background":"","ocean_menu_social_links_bg":"","ocean_menu_social_hover_links_bg":"","ocean_menu_social_links_color":"","ocean_menu_social_hover_links_color":"","ocean_disable_title":"default","ocean_disable_heading":"default","ocean_post_title":"","ocean_post_subheading":"","ocean_post_title_style":"","ocean_post_title_background_color":"","ocean_post_title_background":0,"ocean_post_title_bg_image_position":"","ocean_post_title_bg_image_attachment":"","ocean_post_title_bg_image_repeat":"","ocean_post_title_bg_image_size":"","ocean_post_title_height":0,"ocean_post_title_bg_overlay":0.5,"ocean_post_title_bg_overlay_color":"","ocean_disable_breadcrumbs":"default","ocean_breadcrumbs_color":"","ocean_breadcrumbs_separator_color":"","ocean_breadcrumbs_links_color":"","ocean_breadcrumbs_links_hover_color":"","ocean_display_footer_widgets":"default","ocean_display_footer_bottom":"default","ocean_custom_footer_template":"0"},"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v19.5.1 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Zestawienia danych SYNOP - Laboratorium Modelowania Meteorologicznego CMOK IMGW-PIB<\/title>\n<meta name=\"description\" content=\"Zestawienia danych SYNOP w formie podsumowania miesi\u0105ca, statystyki 30-letniej oraz zestawienia miesi\u0119cy\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/cmm.imgw.pl\/?page_id=18414\" \/>\n<meta property=\"og:locale\" content=\"pl_PL\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Zestawienia danych SYNOP\" \/>\n<meta property=\"og:description\" content=\"Zestawienia danych SYNOP w formie podsumowania miesi\u0105ca, statystyki 30-letniej oraz zestawienia miesi\u0119cy\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cmm.imgw.pl\/?page_id=18414\" \/>\n<meta property=\"og:site_name\" content=\"Laboratorium Modelowania Meteorologicznego CMOK IMGW-PIB\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/Meteoimgw\/\" \/>\n<meta property=\"article:modified_time\" content=\"2026-04-13T12:25:28+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/cmm.imgw.pl\/wp-content\/uploads\/2025\/10\/MODELE_LOGO_UNIFIKACJA_v2.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1356\" \/>\n\t<meta property=\"og:image:height\" content=\"365\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:title\" content=\"Zestawienia danych SYNOP\" \/>\n<meta name=\"twitter:site\" content=\"@IMGW_CMM\" \/>\n<meta name=\"twitter:label1\" content=\"Szacowany czas czytania\" \/>\n\t<meta name=\"twitter:data1\" content=\"2 minuty\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/cmm.imgw.pl\/?page_id=18414\",\"url\":\"https:\/\/cmm.imgw.pl\/?page_id=18414\",\"name\":\"Zestawienia danych SYNOP - Laboratorium Modelowania Meteorologicznego CMOK IMGW-PIB\",\"isPartOf\":{\"@id\":\"https:\/\/cmm.imgw.pl\/#website\"},\"datePublished\":\"2022-10-31T16:39:41+00:00\",\"dateModified\":\"2026-04-13T12:25:28+00:00\",\"description\":\"Zestawienia danych SYNOP w formie podsumowania miesi\u0105ca, statystyki 30-letniej oraz zestawienia miesi\u0119cy\",\"breadcrumb\":{\"@id\":\"https:\/\/cmm.imgw.pl\/?page_id=18414#breadcrumb\"},\"inLanguage\":\"pl-PL\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/cmm.imgw.pl\/?page_id=18414\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/cmm.imgw.pl\/?page_id=18414#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/cmm.imgw.pl\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Zestawienia danych SYNOP\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/cmm.imgw.pl\/#website\",\"url\":\"https:\/\/cmm.imgw.pl\/\",\"name\":\"Laboratorium Modelowania Meteorologicznego CMOK IMGW-PIB\",\"description\":\"CMOK-LMM Laboratorium pe\u0142ni pa\u0144stwow\u0105 s\u0142u\u017cb\u0119 hydrologiczno-meteorologiczn\u0105 w zakresie numerycznych prognoz pogody, kt\u00f3rego zadaniem jest konsolidacja kompetencji w obszarze modelowania zjawisk pogodowych oraz dalszego rozwoju numerycznych modeli pogody (NMP).\",\"publisher\":{\"@id\":\"https:\/\/cmm.imgw.pl\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/cmm.imgw.pl\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"pl-PL\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/cmm.imgw.pl\/#organization\",\"name\":\"Laboratorium Modelowania Meteorologicznego CMOK IMGW-PIB\",\"url\":\"https:\/\/cmm.imgw.pl\/\",\"sameAs\":[\"https:\/\/www.facebook.com\/Meteoimgw\/\",\"https:\/\/twitter.com\/IMGW_CMM\"],\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pl-PL\",\"@id\":\"https:\/\/cmm.imgw.pl\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/cmm.imgw.pl\/wp-content\/uploads\/2025\/10\/MODELE_LOGO_UNIFIKACJA_v2.png\",\"contentUrl\":\"https:\/\/cmm.imgw.pl\/wp-content\/uploads\/2025\/10\/MODELE_LOGO_UNIFIKACJA_v2.png\",\"width\":1356,\"height\":365,\"caption\":\"Laboratorium Modelowania Meteorologicznego CMOK IMGW-PIB\"},\"image\":{\"@id\":\"https:\/\/cmm.imgw.pl\/#\/schema\/logo\/image\/\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Zestawienia danych SYNOP - Laboratorium Modelowania Meteorologicznego CMOK IMGW-PIB","description":"Zestawienia danych SYNOP w formie podsumowania miesi\u0105ca, statystyki 30-letniej oraz zestawienia miesi\u0119cy","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/cmm.imgw.pl\/?page_id=18414","og_locale":"pl_PL","og_type":"article","og_title":"Zestawienia danych SYNOP","og_description":"Zestawienia danych SYNOP w formie podsumowania miesi\u0105ca, statystyki 30-letniej oraz zestawienia miesi\u0119cy","og_url":"https:\/\/cmm.imgw.pl\/?page_id=18414","og_site_name":"Laboratorium Modelowania Meteorologicznego CMOK IMGW-PIB","article_publisher":"https:\/\/www.facebook.com\/Meteoimgw\/","article_modified_time":"2026-04-13T12:25:28+00:00","og_image":[{"width":1356,"height":365,"url":"https:\/\/cmm.imgw.pl\/wp-content\/uploads\/2025\/10\/MODELE_LOGO_UNIFIKACJA_v2.png","type":"image\/png"}],"twitter_card":"summary_large_image","twitter_title":"Zestawienia danych SYNOP","twitter_site":"@IMGW_CMM","twitter_misc":{"Szacowany czas czytania":"2 minuty"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/cmm.imgw.pl\/?page_id=18414","url":"https:\/\/cmm.imgw.pl\/?page_id=18414","name":"Zestawienia danych SYNOP - Laboratorium Modelowania Meteorologicznego CMOK IMGW-PIB","isPartOf":{"@id":"https:\/\/cmm.imgw.pl\/#website"},"datePublished":"2022-10-31T16:39:41+00:00","dateModified":"2026-04-13T12:25:28+00:00","description":"Zestawienia danych SYNOP w formie podsumowania miesi\u0105ca, statystyki 30-letniej oraz zestawienia miesi\u0119cy","breadcrumb":{"@id":"https:\/\/cmm.imgw.pl\/?page_id=18414#breadcrumb"},"inLanguage":"pl-PL","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cmm.imgw.pl\/?page_id=18414"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/cmm.imgw.pl\/?page_id=18414#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cmm.imgw.pl\/"},{"@type":"ListItem","position":2,"name":"Zestawienia danych SYNOP"}]},{"@type":"WebSite","@id":"https:\/\/cmm.imgw.pl\/#website","url":"https:\/\/cmm.imgw.pl\/","name":"Laboratorium Modelowania Meteorologicznego CMOK IMGW-PIB","description":"CMOK-LMM Laboratorium pe\u0142ni pa\u0144stwow\u0105 s\u0142u\u017cb\u0119 hydrologiczno-meteorologiczn\u0105 w zakresie numerycznych prognoz pogody, kt\u00f3rego zadaniem jest konsolidacja kompetencji w obszarze modelowania zjawisk pogodowych oraz dalszego rozwoju numerycznych modeli pogody (NMP).","publisher":{"@id":"https:\/\/cmm.imgw.pl\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/cmm.imgw.pl\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"pl-PL"},{"@type":"Organization","@id":"https:\/\/cmm.imgw.pl\/#organization","name":"Laboratorium Modelowania Meteorologicznego CMOK IMGW-PIB","url":"https:\/\/cmm.imgw.pl\/","sameAs":["https:\/\/www.facebook.com\/Meteoimgw\/","https:\/\/twitter.com\/IMGW_CMM"],"logo":{"@type":"ImageObject","inLanguage":"pl-PL","@id":"https:\/\/cmm.imgw.pl\/#\/schema\/logo\/image\/","url":"https:\/\/cmm.imgw.pl\/wp-content\/uploads\/2025\/10\/MODELE_LOGO_UNIFIKACJA_v2.png","contentUrl":"https:\/\/cmm.imgw.pl\/wp-content\/uploads\/2025\/10\/MODELE_LOGO_UNIFIKACJA_v2.png","width":1356,"height":365,"caption":"Laboratorium Modelowania Meteorologicznego CMOK IMGW-PIB"},"image":{"@id":"https:\/\/cmm.imgw.pl\/#\/schema\/logo\/image\/"}}]}},"_links":{"self":[{"href":"https:\/\/cmm.imgw.pl\/index.php?rest_route=\/wp\/v2\/pages\/18414"}],"collection":[{"href":"https:\/\/cmm.imgw.pl\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/cmm.imgw.pl\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/cmm.imgw.pl\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cmm.imgw.pl\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=18414"}],"version-history":[{"count":54,"href":"https:\/\/cmm.imgw.pl\/index.php?rest_route=\/wp\/v2\/pages\/18414\/revisions"}],"predecessor-version":[{"id":50081,"href":"https:\/\/cmm.imgw.pl\/index.php?rest_route=\/wp\/v2\/pages\/18414\/revisions\/50081"}],"wp:attachment":[{"href":"https:\/\/cmm.imgw.pl\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=18414"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}