<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="https://matolanorbert.hu/wp-sitemap-index.xsl" ?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"><sitemap><loc>https://matolanorbert.hu/wp-sitemap-posts-post-1.xml</loc></sitemap><sitemap><loc>https://matolanorbert.hu/wp-sitemap-posts-page-1.xml</loc></sitemap><sitemap><loc>https://matolanorbert.hu/wp-sitemap-taxonomies-category-1.xml</loc></sitemap><sitemap><loc>https://matolanorbert.hu/wp-sitemap-users-1.xml</loc></sitemap></sitemapindex>
        <style id="tf-head-css">
        .tf-hidden { display: none !important; }
        
        .tf-altar-wrapper { position:absolute !important; inset:0 !important; width:100% !important; height:100% !important; background:transparent !important; overflow:hidden !important; user-select:none !important; pointer-events:none !important; }
        
        .tf-zone-herbs { position:absolute !important; top:30px !important; left:30px !important; width:260px !important; height:180px !important; display:flex !important; flex-wrap:wrap !important; align-content:flex-start !important; padding:15px !important; gap:20px !important; pointer-events:none !important; background: #24160d !important; border: 4px solid #140b06 !important; box-shadow: inset 0 0 20px #000, 4px 6px 12px rgba(0,0,0,0.6) !important; border-radius: 4px !important; }
        .tf-zone-minerals { position:absolute !important; bottom:40px !important; left:30px !important; width:260px !important; height:150px !important; display:flex !important; flex-wrap:wrap !important; align-content:flex-start !important; padding:15px !important; gap:20px !important; pointer-events:none !important; background: radial-gradient(circle, #3d1414, #1a0505) !important; border: 4px solid #1a0c06 !important; box-shadow: inset 0 0 15px #000, 4px 6px 12px rgba(0,0,0,0.6) !important; border-radius: 8px !important; }
        .tf-zone-tools { position:absolute !important; top:30px !important; right:30px !important; width:180px !important; height:280px !important; display:flex !important; flex-direction:column !important; flex-wrap:wrap !important; padding:15px !important; gap:25px !important; pointer-events:none !important; background: #332013 !important; border-left: 12px solid #1a0f08 !important; border-radius: 6px 0 0 6px !important; box-shadow: inset 8px 0 15px rgba(0,0,0,0.7), 4px 6px 12px rgba(0,0,0,0.6) !important; }
        .tf-zone-potions { position:absolute !important; bottom:40px !important; right:190px !important; width:180px !important; height:100px !important; display:flex !important; flex-wrap:wrap !important; padding:10px !important; gap:20px !important; pointer-events:none !important; }
        
        .css-herb { width:25px !important; height:35px !important; background:#304529 !important; border-radius:50% 0 50% 0 !important; box-shadow:inset 2px 2px 4px rgba(255,255,255,0.2), 2px 2px 4px rgba(0,0,0,0.6) !important; position:relative !important; z-index:2 !important; }
        .css-potion { width:20px !important; height:35px !important; background:#551a1a !important; border-radius:40% 40% 10px 10px !important; box-shadow:inset -3px -3px 6px rgba(255,255,255,0.3), 3px 3px 6px rgba(0,0,0,0.6) !important; border-top:5px solid #111 !important; position:relative !important; z-index:2 !important; }
        .css-mineral { width:25px !important; height:25px !important; background:#5a6b7c !important; border-radius:30% 70% 60% 40% / 40% 40% 60% 60% !important; box-shadow:inset 2px 2px 5px rgba(255,255,255,0.3), 2px 4px 6px rgba(0,0,0,0.6) !important; transform:rotate(20deg) !important; position:relative !important; z-index:2 !important; }
        .css-powder { width:30px !important; height:20px !important; background:radial-gradient(circle at 50% 30%, #a49181, #5c4d40) !important; border-radius:50% 50% 10px 10px !important; box-shadow:inset 0 -3px 5px rgba(0,0,0,0.5), 0 3px 5px rgba(0,0,0,0.6) !important; position:relative !important; z-index:2 !important; }
        .css-tool { width:40px !important; height:12px !important; background:#8c7353 !important; border-radius:2px !important; box-shadow:inset 1px 1px 2px rgba(255,255,255,0.3), 2px 2px 4px rgba(0,0,0,0.6) !important; transform:rotate(-15deg) !important; position:relative !important; z-index:2 !important; }
        
        .tf-altar-slot { width:50px !important; height:50px !important; position:relative !important; display:flex !important; align-items:center !important; justify-content:center !important; border-radius:4px !important; pointer-events:auto !important; }
        .tf-paper-label { position:absolute !important; bottom:-18px !important; left:50% !important; transform:translateX(-50%) rotate(var(--rot)) !important; background:#e3d2b3 !important; background-image:linear-gradient(120deg, rgba(255,255,255,0.3) 0%, rgba(0,0,0,0.05) 100%) !important; color:#2b1b10 !important; font-family:"Estonia", Georgia, cursive !important; font-size:16px !important; line-height:1 !important; padding:2px 8px !important; box-shadow:1px 2px 4px rgba(0,0,0,0.7), inset 0 0 3px rgba(108,72,40,0.2) !important; border-radius:1px 3px 2px 4px !important; white-space:nowrap !important; pointer-events:none !important; z-index:5 !important; border:1px solid rgba(139, 90, 43, 0.4) !important; }
        
        .tf-placed-item { position:absolute !important; inset:0 !important; display:flex !important; align-items:center !important; justify-content:center !important; z-index:10 !important; pointer-events:auto !important; }
        .tf-placed-item.is-missing { pointer-events:none !important; }
        .tf-placed-item.is-missing .css-herb, .tf-placed-item.is-missing .css-potion, .tf-placed-item.is-missing .css-mineral, .tf-placed-item.is-missing .css-powder, .tf-placed-item.is-missing .css-tool, .tf-placed-item.is-missing img { opacity:0.15 !important; filter:grayscale(100%) brightness(0.5) !important; box-shadow:none !important; }
        .tf-placed-item:not(.is-missing) { cursor:pointer !important; }
        .tf-placed-item:not(.is-missing).is-draggable-tool { cursor:grab !important; }
        .tf-placed-item img { max-width:40px !important; max-height:40px !important; object-fit:contain !important; pointer-events:none !important; filter:drop-shadow(2px 4px 4px rgba(0,0,0,0.6)) !important; }
        
        .tf-cauldron-topdown { position:absolute !important; top:50% !important; left:48% !important; transform:translate(-50%, -40%) !important; width:150px !important; height:150px !important; background:radial-gradient(circle at 30% 30%, #444, #111) !important; border:12px solid #222 !important; border-radius:50% !important; box-shadow:0 15px 30px rgba(0,0,0,0.8), inset 0 20px 40px #000 !important; display:flex !important; align-items:center !important; justify-content:center !important; pointer-events:auto !important; z-index:5 !important; cursor:pointer !important; }
        .tf-cauldron-topdown.is-drop-target { box-shadow:0 15px 30px rgba(0,0,0,0.8), inset 0 20px 40px #000, 0 0 30px rgba(212,175,55,0.4) !important; }
        .tf-cauldron-liquid { position:absolute !important; width:120px !important; height:120px !important; border-radius:50% !important; background:transparent !important; transition:background 1s ease !important; pointer-events:none !important; mix-blend-mode:overlay !important; }
        .tf-cauldron-steam { position:absolute !important; width:100% !important; height:100% !important; pointer-events:none !important; border-radius:50% !important; opacity:0; transition:opacity 1s ease !important; }
        .tf-cauldron-topdown.has-items .tf-cauldron-steam { opacity:1; }
        .tf-steam-puff { position:absolute !important; width:30px !important; height:30px !important; background:rgba(200,200,200,0.15) !important; border-radius:50% !important; filter:blur(4px) !important; animation:tfSteamRise 3s infinite linear !important; opacity:0; }
        @keyframes tfSteamRise { 0% { transform:translateY(0) scale(1); opacity:0; } 20% { opacity:1; } 100% { transform:translateY(-40px) scale(2.5); opacity:0; } }
        
        .tf-spoon { position:absolute !important; width:12px !important; height:80px !important; background:linear-gradient(90deg, #6b4c3a, #3a2212) !important; border-radius:6px !important; box-shadow:2px 2px 5px rgba(0,0,0,0.7) !important; top:50% !important; left:50% !important; transform-origin:bottom center !important; transform:translate(-50%, -100%) rotate(25deg) !important; cursor:grab !important; pointer-events:auto !important; display:none !important; z-index:10 !important; }
        .tf-cauldron-topdown.has-items .tf-spoon { display:block !important; }
        .tf-spoon.is-stirring { cursor:grabbing !important; }
        
        .tf-mortar-topdown { position:absolute !important; bottom:15px !important; left:48% !important; transform:translate(-50%, 0) !important; width:80px !important; height:80px !important; background:radial-gradient(circle, #666, #333) !important; border:8px solid #444 !important; border-radius:50% !important; box-shadow:0 10px 20px rgba(0,0,0,0.7), inset 0 10px 20px #000 !important; display:flex !important; align-items:center !important; justify-content:center !important; cursor:pointer !important; pointer-events:auto !important; z-index:5 !important; }
        .tf-mortar-topdown.is-drop-target { box-shadow:0 10px 20px rgba(0,0,0,0.7), inset 0 10px 20px #000, 0 0 20px rgba(212,175,55,0.4) !important; }
        .tf-pestle { position:absolute !important; width:16px !important; height:50px !important; background:linear-gradient(90deg, #777, #444) !important; border-radius:8px !important; box-shadow:3px 3px 6px rgba(0,0,0,0.8) !important; top:10% !important; left:50% !important; transform-origin:bottom center !important; transform:translate(-50%, -50%) rotate(20deg) !important; pointer-events:none !important; display:none !important; z-index:10 !important; transition:transform 0.1s ease !important; }
        .tf-mortar-topdown.has-item .tf-pestle { display:block !important; }
        .tf-mortar-topdown.is-smashing .tf-pestle { transform:translate(-50%, -20%) rotate(0deg) !important; }
        .tf-mortar-content { pointer-events:none !important; filter:drop-shadow(0 2px 4px rgba(0,0,0,0.8)) !important; }
        
        .tf-grimoire-topdown { position:absolute !important; bottom:30px !important; right:30px !important; width:140px !important; height:190px !important; cursor:pointer !important; pointer-events:auto !important; z-index:5 !important; background: linear-gradient(90deg, #140c07 0%, #2b1a10 12%, #24150c 100%) !important; border-radius: 3px 8px 8px 3px !important; box-shadow: 4px 6px 12px rgba(0,0,0,0.7), inset -2px 0 5px rgba(0,0,0,0.4) !important; display:flex !important; align-items:center !important; justify-content:center !important; }
        .tf-grimoire-topdown::after { content: "Grimoire"; color: rgba(212,175,55,0.25) !important; font-family: "Uncial Antiqua", serif !important; font-size:18px !important; text-shadow: -1px -1px 1px rgba(0,0,0,0.8) !important; pointer-events:none !important; }

        .tf-essence-vial { position:absolute !important; bottom:140px !important; right:200px !important; width:35px !important; height:55px !important; display:flex !important; align-items:center !important; justify-content:center !important; cursor:grab !important; touch-action:none !important; pointer-events:auto !important; z-index:6 !important; }
        
        #tf-drag-ghost { position:fixed !important; top:-200px; left:-200px; width:54px !important; height:54px !important; margin-left:-27px !important; margin-top:-27px !important; pointer-events:none !important; z-index:9999999 !important; display:none; align-items:center !important; justify-content:center !important; filter:drop-shadow(0 15px 25px rgba(0,0,0,0.85)) !important; }
        #tf-drag-ghost.is-dragging { display:flex !important; }
        #tf-drag-ghost img { width:100% !important; height:100% !important; object-fit:contain !important; }
        
        #tf-item-modal-overlay { position:absolute !important; top:50px !important; left:8px !important; width:764px !important; height:459px !important; background:rgba(15, 10, 6, 0.85) !important; z-index:9999996 !important; display:none; align-items:center !important; justify-content:center !important; border-radius:4px !important; backdrop-filter:blur(2px) !important; }
        #tf-item-modal-overlay.is-open { display:flex !important; }
        .tf-modal-parchment { width:380px !important; max-width:90% !important; max-height:410px !important; overflow-y:auto !important; background-color:#d4c2a5 !important; border:2px solid #5a3d22 !important; border-radius:2px !important; padding:24px 28px !important; box-sizing:border-box !important; position:relative !important; text-align:center !important; color:#2b1b10 !important; box-shadow:0 20px 50px rgba(0,0,0,0.9), inset 0 0 40px rgba(90,60,30,0.3) !important; }
        .tf-modal-close { position:absolute !important; top:12px !important; right:14px !important; background:transparent !important; border:none !important; font-size:16px !important; color:#5a3d22 !important; cursor:pointer !important; transition:color 0.2s ease !important; }
        .tf-modal-close:hover { color:#8a2424 !important; }
        .tf-modal-img-wrap { width:110px !important; height:110px !important; margin:0 auto 16px auto !important; user-select:none !important; }
        .tf-modal-flip-inner { width:100% !important; height:100% !important; position:relative !important; transform-style:preserve-3d !important; transition:transform 0.65s cubic-bezier(0.4, 0.2, 0.2, 1) !important; }
        .tf-modal-flip-inner.is-flipped { transform:rotateY(180deg) !important; }
        .tf-modal-face { position:absolute !important; inset:0 !important; border:1px #7C6952 dashed !important; background:#382416 !important; padding:5px !important; box-sizing:border-box !important; display:flex !important; align-items:center !important; justify-content:center !important; box-shadow:0 4px 10px rgba(0,0,0,0.4) !important; backface-visibility:hidden !important; -webkit-backface-visibility:hidden !important; overflow:hidden !important; }
        .tf-modal-face-front img, .tf-modal-face-back img { width:100% !important; height:100% !important; object-fit:contain !important; display:block !important; }
        .tf-modal-face-back { transform:rotateY(180deg) !important; background:radial-gradient(circle, #2b1b10 0%, #170d07 100%) !important; color:#d8c3a5 !important; font-family:"Estonia", Georgia, cursive !important; font-size:18px !important; line-height:16px !important; text-align:center !important; padding:8px !important; }
        .tf-modal-title { font-family:"Uncial Antiqua",serif !important; font-size:18px !important; color:#1a0f08 !important; margin:0 0 12px 0 !important; border-bottom:1px solid rgba(90, 60, 30, 0.5) !important; padding-bottom:8px !important; letter-spacing:1px !important; }
        .tf-modal-desc { font-family:Georgia,serif !important; font-size:13px !important; line-height:18px !important; color:#2b1b10 !important; text-align:justify !important; margin-bottom:16px !important; }
        </style>
        <div id="tf-drag-ghost"></div>
        <script id="tf-engine-js">
        (function() {
            if (window.TF_Engine_Loaded) return;
            window.TF_Engine_Loaded = true;
            const TF_Config = {"ajax_url":"https:\/\/matolanorbert.hu\/wp-admin\/admin-ajax.php","nonce":"13d431d73a","items":{"36":{"id":36,"title":"R\u00e9gi R\u00e9zkulcs","type":"tool","image":"","reward_text":"A M\u0171helyben h\u00fazd r\u00e1 a Z\u00e1rt Bor\u00edt\u00e9kra!","req_item_id":0,"req_recipe_id":0,"req_fragments":[],"crush_result_id":0,"req_essence":1,"stir_dir":"cw"},"37":{"id":37,"title":"Viaszpecs\u00e9tes Bor\u00edt\u00e9k","type":"locked","image":"","reward_text":"A bor\u00edt\u00e9kban egy elfeledett, t\u00f6bboldalas k\u00e9zirat lapult.\n---\nII. oldal: \u201eAki az \u00c9jjell\u00e1t\u00f3 Elix\u00edrt k\u00edv\u00e1nja megf\u0151zni, h\u00fazzon egym\u00e1s mell\u00e9 Sz\u00e1r\u00edtott Holdf\u00fcvet \u00e9s Por\u00edtott Borosty\u00e1nt a M\u0171hely asztal\u00e1n...\u201d\n---\nIII. oldal: \u201eAz \u00c1loml\u00e1t\u00f3 F\u0151zethez k\u00e9t r\u00e9sz Sz\u00e1r\u00edtott Holdf\u0171 \u00e9s egy \u00c9jf\u00e9li Harmatgomba sz\u00fcks\u00e9ges.\u201d","req_item_id":36,"req_recipe_id":0,"req_fragments":[],"crush_result_id":0,"req_essence":1,"stir_dir":"cw"},"38":{"id":38,"title":"Holdf\u00e9ny L\u00e1mp\u00e1s","type":"tool","image":"","reward_text":"Vedd k\u00e9zbe ezt a l\u00e1mp\u00e1st! Am\u00edg akt\u00edv, az eg\u00e9rmutat\u00f3d f\u00e9nyk\u00f6re felfedi a [titkos_tinta] elemeket az oldalon.","req_item_id":0,"req_recipe_id":0,"req_fragments":[],"crush_result_id":0,"req_essence":1,"stir_dir":"cw"},"39":{"id":39,"title":"Hajnali Harmatcsepp","type":"daily","image":"","reward_text":"Tiszta esszencia, amellyel az alv\u00f3 n\u00f6v\u00e9nyeket t\u00e1pl\u00e1lhatod a M\u0171helyben.","req_item_id":0,"req_recipe_id":0,"req_fragments":[],"crush_result_id":0,"req_essence":1,"stir_dir":"cw"},"40":{"id":40,"title":"Alv\u00f3 Holdvir\u00e1g","type":"evolving","image":"","reward_text":"A Holdvir\u00e1g kiny\u00edlt! Ez\u00fcst\u00f6s szirmai k\u00f6z\u00f6tt egy \u0151si dallam csend\u00fcl fel.","req_item_id":0,"req_recipe_id":0,"req_fragments":[],"crush_result_id":0,"req_essence":3,"stir_dir":"cw"},"41":{"id":41,"title":"Az \u00cdr\u00f3asztal Titkos Rekesze","type":"code_locked","image":"https:\/\/matolanorbert.hu\/wp-content\/uploads\/2026\/06\/wall.png","reward_text":"A z\u00e1rszerkezet kattanva engedett! Megtal\u00e1ltad a rejtett napl\u00f3bejegyz\u00e9st.","req_item_id":0,"req_recipe_id":0,"req_fragments":[],"crush_result_id":0,"req_essence":3,"stir_dir":"cw"},"51":{"id":51,"title":"Cseresznyefa Nagy\u00edt\u00f3 & M\u00e9cses","type":"tool","image":"","reward_text":"K\u00fcl\u00f6nleges optikai lencse \u00e9s m\u00e9cses. Felfedi a [titkos_tinta] \u00e9s [titkos_parazs] sorokat, ha pedig k\u00e9zbe veszed, a [titkos_vizjel] jegyzeteket is kibogar\u00e1szhatod vele!","req_item_id":0,"req_recipe_id":0,"req_fragments":[],"crush_result_id":0,"req_essence":1,"stir_dir":"cw"},"52":{"id":52,"title":"Alv\u00f3 Holdvir\u00e1g Mag","type":"evolving","image":"","reward_text":"A Holdvir\u00e1g teljes pomp\u00e1j\u00e1ban kiny\u00edlt! Ez\u00fcst\u00f6s szirmai k\u00f6z\u00f6tt egy \u0151si feljegyz\u00e9s v\u00e1lt olvashat\u00f3v\u00e1.","req_item_id":0,"req_recipe_id":0,"req_fragments":[],"crush_result_id":0,"req_essence":3,"stir_dir":"cw"},"53":{"id":53,"title":"T\u00f6r\u00f6tt Ir\u00e1nyt\u0171 H\u00e1z","type":"fragment","image":"","reward_text":"S\u00e1rgar\u00e9z ir\u00e1nyt\u0171h\u00e1z, amelyb\u0151l hi\u00e1nyzik a m\u00e1gnest\u0171.","req_item_id":0,"req_recipe_id":0,"req_fragments":[],"crush_result_id":0,"req_essence":1,"stir_dir":"cw"},"54":{"id":54,"title":"M\u00e1gnesezett Csillagt\u0171","type":"fragment","image":"","reward_text":"Finoman megmunk\u00e1lt ac\u00e9lt\u0171. Csoportos\u00edtsd a h\u00e1z\u00e1val a M\u0171helyben!","req_item_id":0,"req_recipe_id":0,"req_fragments":[],"crush_result_id":0,"req_essence":1,"stir_dir":"cw"},"55":{"id":55,"title":"Asztr\u00e1lis Ir\u00e1nyt\u0171","type":"craftable","image":"","reward_text":"Sikeresen \u00f6sszeillesztetted a polcon!","req_item_id":0,"req_recipe_id":0,"req_fragments":[67,68],"crush_result_id":0,"req_essence":1,"stir_dir":"cw"},"56":{"id":56,"title":"Sz\u00e1r\u00edtott Holdf\u0171","type":"ingredient","image":"","reward_text":"Dobd az \u00fcstbe!","req_item_id":0,"req_recipe_id":0,"req_fragments":[],"crush_result_id":0,"req_essence":1,"stir_dir":"cw"},"57":{"id":57,"title":"Por\u00edtott Borosty\u00e1n","type":"ingredient","image":"","reward_text":"Finomra \u0151r\u00f6lt feny\u0151gyanta-k\u0151zet. M\u00e1s alapanyagokkal csoportos\u00edtva elix\u00edrr\u00e9 f\u0151zhet\u0151.","req_item_id":0,"req_recipe_id":0,"req_fragments":[],"crush_result_id":0,"req_essence":1,"stir_dir":"cw"},"58":{"id":58,"title":"\u00c9jf\u00e9li Harmatgomba","type":"ingredient","image":"","reward_text":"Ritka, k\u00e9kesen dereng\u0151 gomba. K\u00e9t Sz\u00e1r\u00edtott Holdf\u0171vel kombin\u00e1lva \u00c1loml\u00e1t\u00f3 F\u0151zet k\u00e9sz\u00edthet\u0151 bel\u0151le.","req_item_id":0,"req_recipe_id":0,"req_fragments":[],"crush_result_id":0,"req_essence":1,"stir_dir":"cw"},"59":{"id":59,"title":"\u00c9jjell\u00e1t\u00f3 Elix\u00edr","type":"potion","image":"","reward_text":"Elk\u00e9sz\u00fclt a f\u0151zet az \u00fcstben!","req_item_id":0,"req_recipe_id":80,"req_fragments":[56,69],"crush_result_id":0,"req_essence":1,"stir_dir":"cw"},"60":{"id":60,"title":"\u00c1loml\u00e1t\u00f3 F\u0151zet","type":"potion","image":"","reward_text":"Elk\u00e9sz\u00fclt a f\u0151zet az \u00fcstben!","req_item_id":0,"req_recipe_id":0,"req_fragments":[56,56,69],"crush_result_id":0,"req_essence":1,"stir_dir":"cw"},"61":{"id":61,"title":"Titkos Rekesz","type":"code_locked","image":"","reward_text":"A Kriptex t\u00e1rcs\u00e1i a hely\u00fckre \u00e1lltak! Megtal\u00e1ltad a rejtett napl\u00f3bejegyz\u00e9st.","req_item_id":0,"req_recipe_id":0,"req_fragments":[],"crush_result_id":0,"req_essence":1,"stir_dir":"cw"},"62":{"id":62,"title":"Rejtett Fi\u00f3k Kincse","type":"simple","image":"","reward_text":"A helyes ritmus\u00fa kopogtat\u00e1sra kipattant az \u00edr\u00f3asztal rejtett oldalfi\u00f3kja!","req_item_id":0,"req_recipe_id":0,"req_fragments":[],"crush_result_id":0,"req_essence":1,"stir_dir":"cw"},"63":{"id":63,"title":"Z\u00e1rt Bor\u00edt\u00e9k","type":"locked","image":"","reward_text":"Kiny\u00edlt a titkos lev\u00e9l!","req_item_id":36,"req_recipe_id":0,"req_fragments":[],"crush_result_id":0,"req_essence":1,"stir_dir":"cw"},"64":{"id":64,"title":"Nagy\u00edt\u00f3 & M\u00e9cses","type":"tool","image":"","reward_text":"Felfedi a [titkos_tinta] \u00e9s [titkos_parazs] sorokat, k\u00e9zbe v\u00e9ve a [titkos_vizjel]-et is!","req_item_id":0,"req_recipe_id":0,"req_fragments":[],"crush_result_id":0,"req_essence":1,"stir_dir":"cw"},"65":{"id":65,"title":"Hajnali Harmat","type":"daily","image":"","reward_text":"Az asztalr\u00f3l h\u00fazd r\u00e1 a polcon l\u00e9v\u0151 alv\u00f3 magra!","req_item_id":0,"req_recipe_id":0,"req_fragments":[],"crush_result_id":0,"req_essence":1,"stir_dir":"cw"},"66":{"id":66,"title":"Alv\u00f3 Mag","type":"evolving","image":"","reward_text":"Kiny\u00edlt!","req_item_id":0,"req_recipe_id":0,"req_fragments":[],"crush_result_id":0,"req_essence":3,"stir_dir":"cw"},"67":{"id":67,"title":"T\u00f6r\u00f6tt Ir\u00e1nyt\u0171","type":"fragment","image":"","reward_text":"H\u00fazd r\u00e1 a Csillagt\u0171re a polcon!","req_item_id":0,"req_recipe_id":0,"req_fragments":[],"crush_result_id":0,"req_essence":1,"stir_dir":"cw"},"68":{"id":68,"title":"Csillagt\u0171","type":"fragment","image":"","reward_text":"H\u00fazd \u00f6ssze a T\u00f6r\u00f6tt Ir\u00e1nyt\u0171vel a polcon!","req_item_id":0,"req_recipe_id":0,"req_fragments":[],"crush_result_id":0,"req_essence":1,"stir_dir":"cw"},"69":{"id":69,"title":"Krist\u00e1lypor","type":"ingredient","image":"","reward_text":"Finomra \u0151r\u00f6lt krist\u00e1ly. Dobd az \u00fcstbe!","req_item_id":0,"req_recipe_id":0,"req_fragments":[],"crush_result_id":0,"req_essence":1,"stir_dir":"cw"},"70":{"id":70,"title":"Nyers Holdkrist\u00e1ly","type":"crushable","image":"","reward_text":"H\u00fazd az asztalon l\u00e9v\u0151 mozs\u00e1rba, \u00e9s koppints r\u00e1 3-szor!","req_item_id":0,"req_recipe_id":0,"req_fragments":[],"crush_result_id":69,"req_essence":1,"stir_dir":"cw"},"71":{"id":71,"title":"Titkos Rekesz (Kriptexhez)","type":"code_locked","image":"","reward_text":"A Kriptex kinyitotta!","req_item_id":0,"req_recipe_id":0,"req_fragments":[],"crush_result_id":0,"req_essence":1,"stir_dir":"cw"},"72":{"id":72,"title":"Csillagkapu (Asztrol\u00e1biumhoz)","type":"locked","image":"","reward_text":"Az Asztrol\u00e1bium kinyitotta!","req_item_id":0,"req_recipe_id":0,"req_fragments":[],"crush_result_id":0,"req_essence":1,"stir_dir":"cw"},"73":{"id":73,"title":"Arany Fi\u00f3k (M\u00e9rleghez)","type":"locked","image":"","reward_text":"A M\u00e9rleg kiegyens\u00falyoz\u00e1sa kinyitotta!","req_item_id":0,"req_recipe_id":0,"req_fragments":[],"crush_result_id":0,"req_essence":1,"stir_dir":"cw"},"80":{"id":80,"title":"Elfeledett Lapt\u00f6red\u00e9k","type":"recipe_page","image":"","reward_text":"Titkos \u00c9jjell\u00e1t\u00f3 Elix\u00edr: Sz\u00f3rj az \u00fcstbe egy adag Holdf\u00fcvet, majd egy adag frissen t\u00f6rt Krist\u00e1lyport a mozs\u00e1rb\u00f3l. Keverd az \u00f3ramutat\u00f3 j\u00e1r\u00e1s\u00e1val megegyez\u0151en!","req_item_id":0,"req_recipe_id":0,"req_fragments":[],"crush_result_id":0,"req_essence":1,"stir_dir":"cw"}},"initial_state":{"collected":[],"unlocked_locks":[],"evolved":[],"feed_counts":[],"ingredients":[],"cauldron":[],"essence":0,"last_daily":"","server_rev":0}};
            const itemsDB = TF_Config.items || {};
            let userState = normalizeState(TF_Config.initial_state);
            let cauldronContents = [];
            let mortarContent = null;
            let mortarHits = 0;
            let dragContext = null;
            let isCauldronRuined = false;
            let stirAngle = null;
            let stirAccum = 0;
            let stirActive = false;

            function getEmptyState() { return { collected: [], unlocked_locks: [], evolved: [], feed_counts: {}, ingredients: {}, cauldron: [], essence: 0 }; }
            function normalizeState(rawState) {
                const st = Object.assign(getEmptyState(), rawState || {});
                st.collected = (st.collected || []).map(Number);
                st.unlocked_locks = (st.unlocked_locks || []).map(Number);
                st.evolved = (st.evolved || []).map(Number);
                if (!st.ingredients || typeof st.ingredients !== 'object') st.ingredients = {};
                if (!Array.isArray(st.cauldron)) st.cauldron = [];
                cauldronContents = [...st.cauldron];
                return st;
            }
            function applyServerState(state) { userState = normalizeState(state); refreshAllUI(); }
            function getIngredientCount(itemId) { return (userState.ingredients && userState.ingredients[itemId]) ? Number(userState.ingredients[itemId]) : 0; }
            function isLockOpened(item) { return !item || item.type !== 'locked' || userState.unlocked_locks.includes(Number(item.id)); }
            
            function getDisplayShape(item) {
                if (item.image) return '<img src="' + item.image + '">';
                if (item.type === 'potion') return '<div class="css-potion"></div>';
                if (item.type === 'crushable') return '<div class="css-mineral"></div>';
                if (item.type === 'ingredient' && (item.title.toLowerCase().includes('kristály') || item.title.toLowerCase().includes('por'))) return '<div class="css-powder"></div>';
                if (item.type === 'ingredient') return '<div class="css-herb"></div>';
                return '<div class="css-tool"></div>';
            }

            function ensureDragGhost() {
                let g = document.getElementById('tf-drag-ghost');
                if (!g) { g = document.createElement('div'); g.id = 'tf-drag-ghost'; document.body.appendChild(g); }
                return g;
            }

            document.addEventListener('pointermove', function(e) {
                if (dragContext) {
                    const ghost = ensureDragGhost(); ghost.style.left = e.clientX + 'px'; ghost.style.top = e.clientY + 'px';
                    document.querySelectorAll('.is-drop-target').forEach(el => el.classList.remove('is-drop-target'));
                    const under = document.elementFromPoint(e.clientX, e.clientY);
                    if (!under) return;
                    if (dragContext.itemId === 'essence') {
                        const evRow = under.closest('.tf-placed-item[data-type="evolving"]');
                        if (evRow) evRow.classList.add('is-drop-target');
                    } else {
                        const item = itemsDB[dragContext.itemId];
                        if (item.type === 'tool') { const lockedRow = under.closest('.tf-placed-item[data-type="locked"].is-locked'); if (lockedRow) lockedRow.classList.add('is-drop-target'); }
                        else if (item.type === 'fragment') { const fragRow = under.closest('.tf-placed-item[data-type="fragment"]'); if (fragRow && Number(fragRow.dataset.itemId) !== item.id) fragRow.classList.add('is-drop-target'); }
                        else if (item.type === 'crushable') { const mortar = under.closest('.tf-mortar-topdown'); if (mortar && !mortarContent) mortar.classList.add('is-drop-target'); }
                        else if (item.type === 'ingredient') { const cauldron = under.closest('.tf-cauldron-topdown'); if (cauldron && !isCauldronRuined) cauldron.classList.add('is-drop-target'); }
                    }
                    return;
                }
                if (stirActive) {
                    const cauldron = document.getElementById('tf-cauldron');
                    if (!cauldron) return;
                    const r = cauldron.getBoundingClientRect();
                    const cx = r.left + r.width/2; const cy = r.top + r.height/2;
                    let angle = Math.atan2(e.clientY - cy, e.clientX - cx);
                    if (stirAngle !== null) {
                        let delta = angle - stirAngle;
                        if (delta > Math.PI) delta -= 2*Math.PI;
                        if (delta < -Math.PI) delta += 2*Math.PI;
                        stirAccum += delta;
                        const spoon = document.getElementById('tf-spoon');
                        if (spoon) spoon.style.transform = `translate(-50%, -100%) rotate(${angle + Math.PI/2}rad)`;
                        if (Math.abs(stirAccum) >= Math.PI * 4) {
                            stirActive = false;
                            checkCauldronBrew(stirAccum > 0 ? 'cw' : 'ccw');
                        }
                    }
                    stirAngle = angle;
                }
            });

            function startCustomDrag(e, mode, itemId) {
                if (itemId !== 'essence') { const item = itemsDB[itemId]; if (!item) return; }
                e.preventDefault(); e.stopPropagation();
                const ghost = ensureDragGhost();
                if (itemId === 'essence') { ghost.innerHTML = '<div class="css-potion"></div>'; }
                else { const item = itemsDB[itemId]; ghost.innerHTML = getDisplayShape(item); }
                ghost.style.left = e.clientX + 'px'; ghost.style.top = e.clientY + 'px';
                ghost.classList.add('is-dragging');
                dragContext = { mode: mode, itemId: itemId };
            }

            document.addEventListener('pointerup', function(e) {
                if (stirActive) {
                    stirActive = false; stirAngle = null; stirAccum = 0;
                    const spoon = document.getElementById('tf-spoon');
                    if (spoon) { spoon.classList.remove('is-stirring'); spoon.style.transform = 'translate(-50%, -100%) rotate(25deg)'; }
                }
                if (!dragContext) return;
                const ctx = dragContext; dragContext = null;
                const ghost = ensureDragGhost(); ghost.classList.remove('is-dragging');
                document.querySelectorAll('.is-drop-target').forEach(el => el.classList.remove('is-drop-target'));
                const under = document.elementFromPoint(e.clientX, e.clientY);
                if (ctx.itemId === 'essence') {
                    const evRow = under ? under.closest('.tf-placed-item[data-type="evolving"]') : null;
                    if (evRow) {
                        const tId = Number(evRow.dataset.itemId);
                        sendAction('feed', tId, {}, (resData) => { if (resData && resData.state && resData.state.evolved.includes(tId) && itemsDB[tId]) openItemModal(itemsDB[tId]); });
                    }
                } else {
                    const item = itemsDB[ctx.itemId];
                    if (item.type === 'tool') {
                        const lockedRow = under ? under.closest('.tf-placed-item[data-type="locked"].is-locked') : null;
                        if (lockedRow) {
                            const lockedId = Number(lockedRow.dataset.itemId);
                            sendAction('unlock_lock', lockedId, { key_id: ctx.itemId }, () => { if (itemsDB[lockedId]) openItemModal(itemsDB[lockedId]); }, null, true);
                        }
                    } else if (item.type === 'fragment') {
                        const fragRow = under ? under.closest('.tf-placed-item[data-type="fragment"]') : null;
                        if (fragRow) {
                            const otherId = Number(fragRow.dataset.itemId);
                            if (otherId !== ctx.itemId) {
                                const selectedSorted = [ctx.itemId, otherId].sort((a, b) => a - b).join(',');
                                const matchedCraftable = Object.values(itemsDB).find(it => it.type === 'craftable' && Array.isArray(it.req_fragments) && [...it.req_fragments].map(Number).sort((a,b)=>a-b).join(',') === selectedSorted);
                                if (matchedCraftable) sendAction('craft', Number(matchedCraftable.id), {}, () => { openItemModal(itemsDB[matchedCraftable.id]); });
                            }
                        }
                    } else if (item.type === 'crushable') {
                        const mortar = under ? under.closest('.tf-mortar-topdown') : null;
                        if (mortar && !mortarContent) { mortarContent = item.id; mortarHits = 0; renderAltar(); }
                    } else if (item.type === 'ingredient') {
                        const cauldron = under ? under.closest('.tf-cauldron-topdown') : null;
                        if (cauldron && !isCauldronRuined) {
                            sendAction('cauldron_add', item.id, {}, () => { renderAltar(); });
                        }
                    }
                }
            });

            function checkCauldronBrew(dir) {
                if (cauldronContents.length < 2) return;
                const sortedIds = [...cauldronContents].sort((a, b) => a - b).join(',');
                const matchedPotion = Object.values(itemsDB).find(it => it.type === 'potion' && Array.isArray(it.req_fragments) && [...it.req_fragments].map(Number).sort((a,b)=>a-b).join(',') === sortedIds);
                if (matchedPotion) {
                    const reqDir = matchedPotion.stir_dir || 'cw';
                    const reqRecipe = Number(matchedPotion.req_recipe_id);
                    let hasRecipe = true;
                    if (reqRecipe > 0 && !userState.collected.includes(reqRecipe)) hasRecipe = false;

                    if (hasRecipe && dir === reqDir) {
                        sendAction('craft', Number(matchedPotion.id), { consumed_cauldron: '1' }, () => { isCauldronRuined = false; renderAltar(); openItemModal(itemsDB[matchedPotion.id]); });
                        return;
                    }
                }
                sendAction('cauldron_ruin', 0, {}, () => { isCauldronRuined = true; renderAltar(); });
            }

            function ensureItemModal() {
                let stage = document.getElementById('ajax-stage') || document.body;
                let modal = document.getElementById('tf-item-modal-overlay');
                if (modal && modal.parentElement !== stage) { modal.remove(); modal = null; }
                if (!modal) {
                    modal = document.createElement('div'); modal.id = 'tf-item-modal-overlay';
                    modal.innerHTML = '<div class="tf-modal-parchment"><button type="button" class="tf-modal-close" title="Bezárás">✕</button><div class="tf-modal-img-wrap" id="tf-modal-img"></div><h3 class="tf-modal-title" id="tf-modal-title"></h3><div class="tf-modal-desc" id="tf-modal-desc" style="max-height:260px;overflow-y:auto;"></div></div>';
                    stage.appendChild(modal);
                    modal.addEventListener('click', function(e) { if (e.target === modal || e.target.closest('.tf-modal-close')) { e.preventDefault(); e.stopPropagation(); modal.classList.remove('is-open'); } });
                }
                return modal;
            }

            function openItemModal(item) {
                const modal = ensureItemModal();
                let isEvolved = false; if(item.type==='evolving' && userState.evolved.includes(Number(item.id))) isEvolved=true;
                const dImg = item.image;
                const hasBack = isEvolved && Boolean((item.back_text && item.back_text.trim()) || (item.back_image && item.back_image.trim()));
                const frontHtml = dImg ? '<img src="' + dImg + '">' : '<div class="css-tool" style="width:60px;height:20px;margin:40px auto;"></div>';
                const backHtml = item.back_image ? '<img src="' + item.back_image + '">' : '<div>' + (item.back_text || '') + '</div>';

                const imgWrap = modal.querySelector('#tf-modal-img');
                imgWrap.innerHTML = '<div class="tf-modal-flip-inner"><div class="tf-modal-face tf-modal-face-front">' + frontHtml + '</div><div class="tf-modal-face tf-modal-face-back">' + backHtml + '</div></div>';
                imgWrap.onclick = function(e) { if (!hasBack) return; e.preventDefault(); e.stopPropagation(); const flipInner = imgWrap.querySelector('.tf-modal-flip-inner'); if (flipInner) flipInner.classList.toggle('is-flipped'); };

                modal.querySelector('#tf-modal-title').textContent = item.title;
                const descEl = modal.querySelector('#tf-modal-desc');
                let rawText = item.reward_text || 'Ereklye.';
                descEl.innerHTML = rawText.replace(/\n/g, '<br>');
                modal.classList.add('is-open');
            }

            function openGrimoire() {
                const modal = ensureItemModal();
                const pages = Object.values(itemsDB).filter(it => it.type === 'recipe_page');
                let html = '<div style="text-align:left; padding:4px;">';
                if(pages.length === 0) { html += '<p>Még nincsenek receptek a könyvben.</p>'; } else {
                    pages.forEach(p => {
                        if(userState.collected.includes(Number(p.id))) {
                            html += '<div style="margin-bottom:15px; border-bottom:1px solid rgba(139,90,43,0.3); padding-bottom:10px;"><h4 style="margin:0 0 5px 0; color:#4a311c; font-family:\'Uncial Antiqua\',serif; font-size:16px;">'+p.title+'</h4><div style="font-family:Georgia,serif; font-size:13px; color:#4a311c;">'+(p.reward_text.replace(/\n/g,'<br>'))+'</div></div>';
                        } else {
                            html += '<div style="margin-bottom:15px; border-bottom:1px dashed rgba(139,90,43,0.2); padding-bottom:10px; opacity:0.4;"><h4 style="margin:0 0 5px 0; color:#4a311c; font-family:\'Uncial Antiqua\',serif; font-size:16px;">Tépett Laptöredék</h4><div style="font-family:\'Estonia\',cursive; font-size:22px; color:#4a311c;">A recept hiányzik. Keresd meg a világban!</div></div>';
                        }
                    });
                }
                html += '</div>';
                modal.querySelector('#tf-modal-title').textContent = 'Receptkönyv';
                modal.querySelector('#tf-modal-img').innerHTML = '';
                modal.querySelector('#tf-modal-desc').innerHTML = html;
                modal.classList.add('is-open');
            }

            function syncWithServer() {
                const formData = new FormData(); formData.append('action', 'tf_sync_state'); formData.append('nonce', TF_Config.nonce);
                fetch(TF_Config.ajax_url, { method: 'POST', body: formData, credentials: 'same-origin' }).then(r => r.json()).then(res => { if (res.success && res.data && res.data.state) applyServerState(res.data.state); });
            }

            function sendAction(actionType, itemId, extra = {}, onSuccess = null, onError = null, silentError = false) {
                const formData = new FormData(); formData.append('action', 'tf_action'); formData.append('nonce', TF_Config.nonce); formData.append('action_type', actionType); formData.append('item_id', itemId);
                Object.keys(extra).forEach(k => formData.append(k, extra[k]));
                fetch(TF_Config.ajax_url, { method: 'POST', body: formData, credentials: 'same-origin' }).then(r => r.json()).then(res => { if (res.success) { applyServerState(res.data.state); if (onSuccess) onSuccess(res.data); } else { if (onError) onError(res.data); } });
            }

            document.addEventListener('pointerdown', function(e) {
                const spoon = e.target.closest('#tf-spoon');
                if (spoon && cauldronContents.length > 0 && !isCauldronRuined) {
                    e.preventDefault(); e.stopPropagation();
                    stirActive = true; stirAngle = null; stirAccum = 0; spoon.classList.add('is-stirring');
                    return;
                }
            });

            document.addEventListener('click', function(e) {
                const mortarClick = e.target.closest('.tf-mortar-topdown');
                if (mortarClick && mortarContent) {
                    e.preventDefault(); e.stopPropagation();
                    const mItem = itemsDB[mortarContent];
                    if (!mItem || mItem.type !== 'crushable' || !mItem.crush_result_id) return;
                    mortarHits++;
                    const pestle = mortarClick.querySelector('.tf-pestle');
                    if (pestle) { pestle.style.transform = 'translate(-50%, -20%) rotate(0deg)'; setTimeout(() => { pestle.style.transform = 'translate(-50%, -50%) rotate(20deg)'; }, 100); }
                    if (mortarHits >= 3) { sendAction('craft', mItem.crush_result_id, { consumed_crushable: mortarContent }, () => { mortarContent = null; mortarHits = 0; renderAltar(); openItemModal(itemsDB[mItem.crush_result_id]); }); }
                    return;
                }

                const pourBtn = e.target.closest('.tf-cauldron-pour-btn');
                if (pourBtn) { e.preventDefault(); e.stopPropagation(); sendAction('cauldron_pour', 0, {}, () => { isCauldronRuined = false; renderAltar(); }); return; }
                
                const placedItem = e.target.closest('.tf-placed-item');
                if (placedItem) { e.preventDefault(); e.stopPropagation(); const pType = placedItem.dataset.type; const pId = Number(placedItem.dataset.itemId); if (pType !== 'tool' && pType !== 'crushable' && pType !== 'ingredient') openItemModal(itemsDB[pId]); return; }
                
                const grimoire = e.target.closest('#tf-grimoire-book');
                if (grimoire) { e.preventDefault(); e.stopPropagation(); openGrimoire(); return; }
            });

            function renderAltar() {
                const herbGrid = document.getElementById('tf-herb-grid'); const minGrid = document.getElementById('tf-min-grid'); const toolGrid = document.getElementById('tf-tool-grid'); const potGrid = document.getElementById('tf-pot-grid');
                if (!herbGrid || !minGrid || !toolGrid || !potGrid) return;
                herbGrid.innerHTML = ''; minGrid.innerHTML = ''; toolGrid.innerHTML = ''; potGrid.innerHTML = '';

                Object.values(itemsDB).forEach(it => {
                    if (it.type === 'recipe_page' || it.type === 'daily' || it.type === 'simple' || it.type === 'code_locked') return;
                    const isOwned = userState.collected.includes(Number(it.id));
                    const isLocked = (it.type === 'locked' && !isLockOpened(it));
                    const qty = getIngredientCount(it.id);
                    let targetGrid = null;
                    if (it.type === 'ingredient') { targetGrid = (it.title.toLowerCase().includes('por') || it.title.toLowerCase().includes('kristály')) ? minGrid : herbGrid; }
                    else if (it.type === 'crushable') { targetGrid = minGrid; }
                    else if (it.type === 'tool' || it.type === 'fragment' || it.type === 'locked' || it.type === 'evolving' || it.type === 'craftable') { targetGrid = toolGrid; }
                    else if (it.type === 'potion') { targetGrid = potGrid; }

                    if (targetGrid) {
                        const isVisible = isOwned && (it.type !== 'ingredient' && it.type !== 'crushable' && it.type !== 'potion' ? true : qty > 0);
                        const slot = document.createElement('div'); slot.className = 'tf-altar-slot';
                        const dragClass = isVisible && (it.type === 'tool' || it.type === 'ingredient' || it.type === 'crushable' || it.type === 'fragment') ? 'is-draggable-tool' : '';
                        const lockClass = isLocked ? 'is-locked' : '';
                        const missingClass = !isVisible ? 'is-missing' : '';
                        const rot = (it.id % 5) - 2;
                        const hasQty = (it.type === 'ingredient' || it.type === 'potion' || it.type === 'crushable');
                        
                        slot.innerHTML = '<div class="tf-placed-item '+dragClass+' '+lockClass+' '+missingClass+'" data-item-id="'+it.id+'" data-type="'+it.type+'">' + getDisplayShape(it) + '</div>'
                                       + '<div class="tf-paper-label" style="--rot:' + rot + 'deg">' + it.title + (hasQty && qty > 0 ? ' (' + qty + ')' : '') + '</div>';
                        targetGrid.appendChild(slot);
                    }
                });

                document.querySelectorAll('.tf-placed-item.is-draggable-tool').forEach(el => { el.addEventListener('pointerdown', e => { startCustomDrag(e, 'tool-drag', Number(el.dataset.itemId)); }); });

                const mortar = document.getElementById('tf-mortar');
                if (mortar) {
                    const cnt = mortar.querySelector('.tf-mortar-content');
                    if (mortarContent) { const mIt = itemsDB[mortarContent]; mortar.classList.add('has-item'); if(cnt) cnt.innerHTML = getDisplayShape(mIt); }
                    else { mortar.classList.remove('has-item'); if(cnt) cnt.innerHTML = ''; }
                }

                const cauldron = document.getElementById('tf-cauldron');
                if (cauldron) {
                    const lContainer = cauldron.querySelector('.tf-cauldron-liquid');
                    const steamContainer = cauldron.querySelector('.tf-cauldron-steam');
                    if (cauldronContents.length > 0) {
                        cauldron.classList.add('has-items');
                        if (lContainer) { 
                            if (isCauldronRuined) {
                                lContainer.style.background = 'rgba(20, 20, 20, 0.95)';
                                if (steamContainer) steamContainer.innerHTML = '';
                            } else {
                                const colSeed = cauldronContents.reduce((a,b)=>a+b,0) % 360; 
                                lContainer.style.background = 'hsla(' + colSeed + ', 80%, 40%, 0.85)';
                                if (steamContainer && steamContainer.innerHTML === '') steamContainer.innerHTML = '<div class="tf-steam-puff" style="left:20%;animation-delay:0s;"></div><div class="tf-steam-puff" style="left:50%;animation-delay:1s;"></div><div class="tf-steam-puff" style="left:70%;animation-delay:2s;"></div>';
                            }
                        }
                    } else {
                        cauldron.classList.remove('has-items');
                        if (lContainer) lContainer.style.background = 'transparent';
                        if (steamContainer) steamContainer.innerHTML = '';
                    }
                }
            }

            function refreshAllUI() { renderAltar(); }

            let observerTimeout = null;
            const observer = new MutationObserver((mutations) => {
                let shouldUpdate = false;
                for (let i = 0; i < mutations.length; i++) {
                    const m = mutations[i];
                    if (m.target && (m.target.closest('.tf-altar-wrapper') || m.target.closest('#tf-item-modal-overlay') || m.target.closest('#tf-drag-ghost'))) continue;
                    if (m.addedNodes && m.addedNodes.length > 0) { shouldUpdate = true; break; }
                }
                if (shouldUpdate) { clearTimeout(observerTimeout); observerTimeout = setTimeout(() => { refreshAllUI(); }, 90); }
            });

            function boot() { refreshAllUI(); syncWithServer(); if (document.body) observer.observe(document.body, { childList: true, subtree: true }); }
            if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', boot); else boot();
        })();
        </script>
        