<?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-album-css">
        /* ============================================================
         * TITKOS FIOK — V41 / SCRAPBOOK CODEX
         * A magazin mChustomScrollbar szerkezetet tartjuk meg,
         * de a Kódex saját, feszesebb viewporttal működik.
         * ============================================================ */

        .tf-hidden { display:none !important; }

        /* ---- A világban megjelenő gyűjthető elemek ---- */
        .tf-world-item { display:inline-flex; align-items:center; justify-content:center; position:relative; margin:4px 6px; padding:0; user-select:none; transition:transform .18s ease, opacity .35s ease; z-index:25; pointer-events:auto; overflow:visible; cursor:pointer; }
        .tf-world-item.tf-collected-hide { display:none !important; }
        .tf-world-item-inner { display:inline-flex; align-items:center; justify-content:center; position:relative; pointer-events:none; }
        .tf-world-emoji { font-size:28px; line-height:1; display:inline-block; padding:6px; }
        .tf-world-img { max-width:120px; max-height:120px; object-fit:contain; display:block; }

        /* ---- Gombok: egyszerű, tintaszerű ---- */
        .tf-vintage-btn {
            appearance:none; border:0; background:#3b2719; color:#efe2c6;
            font-family:"Uncial Antiqua", Georgia, serif; font-size:11px;
            letter-spacing:.8px; text-transform:uppercase; padding:7px 14px;
            cursor:default; box-shadow:1px 1px 0 rgba(35,20,10,.35);
        }
        .tf-vintage-btn:hover:not(:disabled) { background:#512e1e; color:#fff7e5; }
        .tf-vintage-btn:disabled { opacity:.45; }

        /* ---- A két Kódex-lap ---- */
        .tf-codex-page,
        .tf-details-page {
            box-sizing:border-box !important;
            padding:7px 8px !important;
            overflow:hidden !important;
            justify-content:flex-start !important;
            color:#27170d;
            background:
                radial-gradient(circle at 30% 15%, rgba(255,252,235,.78), transparent 34%),
                radial-gradient(circle at 78% 78%, rgba(128,91,46,.09), transparent 42%),
                linear-gradient(120deg,#eee2c7 0%,#e5d5b6 48%,#ede1c6 100%);
        }
        .tf-codex-page::before,
        .tf-details-page::before {
            content:""; position:absolute; inset:5px; pointer-events:none;
            background:linear-gradient(115deg,rgba(255,255,255,.18),transparent 32%,rgba(83,53,28,.05));
            mix-blend-mode:multiply;
        }

        /* ---- Bal felső scrapbook-jegyzet ---- */
        .tf-scrapbook-heading {
            position:relative; flex:0 0 44px; height:44px; margin:0 6px 3px;
            display:flex; flex-direction:column; justify-content:center;
            transform:rotate(-.7deg);
            z-index:2;
        }
        .tf-scrapbook-heading::after {
            content:""; position:absolute; left:-3px; right:7px; bottom:1px; height:1px;
            background:rgba(95,61,31,.17); transform:rotate(.5deg);
        }
        .tf-scrapbook-paperclip {
            position:absolute; left:26px; top:-12px; width:9px; height:24px;
            border:2px solid #6f6b63; border-bottom:0; border-radius:7px 7px 0 0;
            box-shadow:1px 1px 0 rgba(0,0,0,.25); transform:rotate(3deg); opacity:.92;
        }
        .tf-scrapbook-label {
            width:max-content; max-width:170px; padding:6px 17px 5px 12px;
            background:rgba(248,241,221,.92); color:#1c120a;
            font-family:"Uncial Antiqua", Georgia, serif; font-size:18px; letter-spacing:.2px;
            box-shadow:0 2px 6px rgba(45,29,15,.16);
        }
        .tf-scrapbook-kicker {
            margin:1px 0 0 13px; font-family:Georgia,serif; font-size:8.5px;
            color:#71553a; font-style:italic; letter-spacing:.35px;
        }

        .tf-album-stats {
            flex:0 0 18px; height:18px; display:flex; align-items:center; justify-content:space-between;
            margin:0 9px; padding:0; font-family:Georgia,serif; font-size:9.5px; color:#5b4027;
        }
        .tf-album-stats strong { color:#8a2d25; font-weight:700; }

        /* ---- Kategória-sor: kéziratos jelek, nem UI-kártyák ---- */
        .tf-album-filters {
            flex:0 0 31px; height:31px; display:flex; align-items:flex-start; justify-content:space-between;
            margin:1px 7px 4px; padding:0; position:relative; z-index:3;
        }
        .tf-album-filter {
            width:38px; height:31px; padding:0; border:0; outline:0; background:transparent;
            display:flex; flex-direction:column; align-items:center; justify-content:flex-start;
            opacity:.43; filter:sepia(.65) saturate(.7); transform-origin:center top;
            cursor:default; transition:opacity .15s ease, transform .15s ease;
        }
        .tf-album-filter:hover { opacity:.72; transform:translateY(-1px); }
        .tf-album-filter.is-active { opacity:1; filter:none; transform:translateY(-1px); }
        .tf-album-filter img { width:25px; height:25px; object-fit:contain; display:block; }
        .tf-album-filter span {
            font-family:Georgia,serif; font-size:7.5px; line-height:8px; color:#62472e;
            margin-top:0; font-variant:small-caps; letter-spacing:.3px;
        }
        .tf-album-filter.is-active span { color:#8a2d25; font-weight:700; }

        /* ---- Magazin-szerű, FIX Kódex viewport ---- */
        .tf-codex-body {
            width:284px !important; height:196px !important; flex:0 0 196px !important;
            margin:2px auto 0 !important; padding:0 !important; position:relative !important;
            overflow:hidden !important; box-sizing:border-box !important; z-index:2;
        }
        .tf-codex-page #mcs_tf_inventory {
            position:relative !important; width:284px !important; height:196px !important;
            margin:0 !important; padding:0 !important; overflow:visible !important; box-sizing:border-box !important;
        }
        .tf-codex-page #mcs_tf_inventory .customScrollBox {
            position:relative !important; width:284px !important; height:196px !important;
            overflow:hidden !important; margin:0 !important; box-sizing:border-box !important;
        }
        .tf-codex-page #mcs_tf_inventory .customScrollBox .container {
            position:relative !important; width:268px !important; min-height:0 !important;
            height:auto !important; top:0; left:0 !important; float:left !important;
            margin:0 !important; padding:0 !important; box-sizing:border-box !important;
        }
        .tf-codex-page #mcs_tf_inventory .customScrollBox .content {
            clear:both !important; width:100% !important; height:auto !important; min-height:0 !important;
            margin:0 !important; padding:2px 0 8px !important; box-sizing:border-box !important;
            overflow:visible !important;
        }
        .tf-codex-page #mcs_tf_inventory .dragger_container {
            position:relative !important; width:6px !important; height:194px !important;
            float:right !important; margin:0 2px 0 0 !important; padding:0 !important;
            background:rgba(69,49,32,.16) !important; border:0 !important; border-radius:1px !important;
            box-sizing:border-box !important;
        }
        .tf-codex-page #mcs_tf_inventory .dragger {
            position:absolute !important; top:0; left:1px !important; width:4px !important;
            height:23px !important; min-height:23px !important; margin:0 !important; padding:0 !important;
            background:#4b3724 !important; border:0 !important; border-radius:1px !important; box-shadow:none !important;
        }
        .tf-codex-page #mcs_tf_inventory .dragger_pressed {
            width:4px !important; height:23px !important; background:#3b2819 !important;
        }

        /* ---- Kódex-bejegyzések: scrapbook-kártyák, nem rács ---- */
        .tf-codex-grid {
            display:flex !important; flex-direction:column !important; gap:5px !important;
            width:100% !important; min-height:0 !important; margin:0 !important; padding:0 !important;
            box-sizing:border-box !important;
        }
        .tf-codex-entry {
            box-sizing:border-box !important; width:100% !important; min-height:45px !important;
            margin:0 !important; padding:4px 26px 4px 7px !important;
            display:flex !important; align-items:center !important; justify-content:flex-start !important;
            position:relative !important; background:rgba(250,244,227,.46) !important;
            border:1px solid rgba(116,83,48,.23) !important; border-radius:1px !important;
            box-shadow:0 1px 4px rgba(62,41,21,.06) !important;
            transform:none !important; cursor:default !important;
            transition:background .16s ease, opacity .16s ease;
        }
        .tf-codex-entry:hover { background:rgba(255,249,231,.70) !important; transform:none !important; }
        .tf-codex-entry.is-silhouette { opacity:.56; }
        .tf-codex-entry.is-silhouette:hover { opacity:.67; }
        .tf-codex-entry::before {
            content:""; width:4px; height:4px; flex:0 0 4px; margin-right:7px;
            border-radius:50%; background:rgba(138,45,37,.58);
        }
        .tf-codex-entry img,
        .tf-codex-entry .tf-emoji-icon {
            width:36px !important; height:36px !important; max-width:36px !important; max-height:36px !important;
            object-fit:contain !important; display:block !important; flex:0 0 36px;
            pointer-events:none !important;
            filter:sepia(.16) saturate(.86);
        }
        .tf-codex-entry .tf-emoji-icon { font-size:30px !important; line-height:1 !important; }
        .tf-codex-entry.is-silhouette img,
        .tf-codex-entry.is-silhouette .tf-emoji-icon { filter:grayscale(1) brightness(.18) opacity(.34) !important; }
        .tf-codex-entry.is-active-selection { background:rgba(138,45,37,.075) !important; box-shadow:inset 3px 0 0 #8a2d25, 0 1px 4px rgba(62,41,21,.06) !important; }
        .tf-codex-entry.is-drop-target { background:rgba(212,175,55,.13) !important; box-shadow:inset 3px 0 0 #b28b2e !important; }
        .tf-album-qty {
            position:absolute; top:3px; right:6px; padding:0; margin:0; background:transparent;
            color:#8a2d25; font:700 10px/1 Georgia,serif;
        }
        .tf-album-lock {
            position:absolute; right:6px; bottom:4px; left:auto; top:auto; color:#8a2d25;
            font-size:11px; line-height:1; opacity:.8;
        }

        /* ---- Jobb lap: tanúsítvány / leletlap ---- */
        .tf-details-topline {
            flex:0 0 18px; height:18px; display:flex; align-items:center; justify-content:space-between;
            margin:0 8px 2px; font:8px/1 Georgia,serif; color:#806346; letter-spacing:1px; text-transform:uppercase;
        }
        .tf-details-topline span:last-child { color:#8a2d25; letter-spacing:.5px; }
        .tf-details-body {
            width:280px !important; height:296px !important; flex:0 0 296px !important;
            margin:2px auto 0 !important; padding:0 !important; position:relative !important;
            overflow:hidden !important; box-sizing:border-box !important;
        }
        .tf-details-page #mcs_tf_details { position:relative !important; width:280px !important; height:296px !important; margin:0 !important; padding:0 !important; }
        .tf-details-page #mcs_tf_details .customScrollBox { position:relative !important; width:280px !important; height:296px !important; overflow:hidden !important; }
        .tf-details-page #mcs_tf_details .customScrollBox .container {
            width:262px !important; position:relative !important; top:0; left:0 !important; float:left !important;
            height:auto !important; min-height:0 !important; margin:0 !important; padding:0 !important;
            box-sizing:border-box !important;
        }
        .tf-details-page #mcs_tf_details .customScrollBox .content {
            clear:both !important; width:100% !important; height:auto !important; min-height:0 !important;
            margin:0 !important; padding:4px 4px 12px !important; overflow:visible !important; box-sizing:border-box !important;
        }
        .tf-details-page #mcs_tf_details .dragger_container {
            position:relative !important; width:6px !important; height:294px !important; float:right !important;
            margin:0 2px 0 0 !important; padding:0 !important; background:rgba(69,49,32,.16) !important; border:0 !important;
            border-radius:1px !important; box-sizing:border-box !important;
        }
        .tf-details-page #mcs_tf_details .dragger {
            position:absolute !important; top:0; left:1px !important; width:4px !important;
            height:23px !important; min-height:23px !important; margin:0 !important; padding:0 !important;
            background:#4b3724 !important; border:0 !important; border-radius:1px !important;
        }
        .tf-details-empty {
            min-height:280px; display:flex; flex-direction:column; align-items:center; justify-content:center;
            gap:8px; padding:20px; box-sizing:border-box; text-align:center;
            color:#806346; font:italic 13px/1.5 Georgia,serif;
        }
        .tf-details-empty-mark { color:#8a2d25; font-size:22px; }
        .tf-details-content { display:none; text-align:center; padding:0 7px 4px; }
        .tf-details-ornament { color:#8a2d25; font:13px/1 Georgia,serif; letter-spacing:5px; margin:1px 0 8px 5px; opacity:.72; }
        .tf-details-eyebrow { color:#7e6245; font:8px/1 Georgia,serif; letter-spacing:1.25px; text-transform:uppercase; margin-bottom:5px; }
        #tf-details-title {
            font-family:"Uncial Antiqua", Georgia, serif !important; font-size:24px !important; line-height:1.08 !important;
            font-weight:400 !important; color:#1d120a !important; margin:0 4px 12px !important;
        }
        .tf-details-img-wrap {
            width:92px; height:92px; margin:0 auto 8px; display:flex; align-items:center; justify-content:center;
            background:radial-gradient(circle,rgba(255,252,238,.95) 0 56%,rgba(178,149,102,.12) 57% 68%,transparent 69%);
            box-shadow:0 1px 5px rgba(62,41,21,.09); position:relative;
        }
        .tf-details-img-wrap::before,
        .tf-details-img-wrap::after {
            content:""; position:absolute; width:22px; height:22px; border-color:rgba(93,65,39,.25); border-style:solid;
        }
        .tf-details-img-wrap::before { left:0; top:0; border-width:1px 0 0 1px; }
        .tf-details-img-wrap::after { right:0; bottom:0; border-width:0 1px 1px 0; }
        #tf-details-img-wrap img { max-width:74px; max-height:74px; object-fit:contain; }
        #tf-details-img-wrap .tf-emoji-icon { font-size:52px; color:#5a3d22; }
        .tf-details-meta {
            font:italic 9.5px/1.4 Georgia,serif; color:#8a2d25; margin:0 6px 12px; padding:0 0 6px;
            border-bottom:1px dotted rgba(104,75,46,.26); text-align:center;
        }
        .tf-details-desc {
            font:12px/1.45 Georgia,serif; color:#2b1b10; text-align:justify; padding:0 7px;
        }
        .tf-details-desc strong { color:#8a2d25; }
        .tf-details-actions { margin:17px 5px 0; text-align:center; }
        .tf-details-signature { margin:18px 0 0; text-align:center; font:italic 9px Georgia,serif; color:#82694d; }

        /* ---- Jelszó: kézzel húzott vonal ---- */
        .tf-secret-input {
            width:210px; max-width:100%; box-sizing:border-box; background:transparent; border:0;
            border-bottom:1px solid rgba(90,61,34,.55); outline:0; padding:5px 2px 4px;
            color:#3e2615; font:16px "Uncial Antiqua",Georgia,serif; text-align:center; margin:2px auto 11px;
        }
        .tf-secret-input:focus { border-bottom-color:#8a2d25; }

        .tf-details-footer,
        .tf-scrapbook-footer {
            flex:0 0 20px; height:20px; margin:3px 7px 0; display:flex; align-items:center; justify-content:space-between;
            color:#806346; font:8px/1 Georgia,serif; letter-spacing:.5px; text-transform:uppercase;
        }
        .tf-scrapbook-footer span:nth-child(2), .tf-details-footer span:nth-child(2) { color:#8a2d25; }


        /* ============================================================
         * V40 – TISZTA KÓDEX LAYOUT
         * A scrollbar DOM-ja pontosan a Magaziné:
         * customScrollBox > container > content + dragger_container > dragger
         * A moving container NINCS top/left !important-tal lezárva.
         * ============================================================ */
        .tf-codex-page,
        .tf-details-page {
            width:50% !important;
            height:100% !important;
            flex:0 0 50% !important;
            min-width:0 !important;
            min-height:0 !important;
            float:none !important;
            display:flex !important;
            flex-direction:column !important;
            box-sizing:border-box !important;
        }

        .tf-codex-grid {
            display:grid !important;
            grid-template-columns:repeat(4,minmax(0,1fr)) !important;
            grid-auto-rows:58px !important;
            gap:7px !important;
            align-content:start !important;
            width:268px !important;
            min-width:268px !important;
            height:auto !important;
            min-height:0 !important;
            margin:0 !important;
            padding:2px 1px 4px 0 !important;
            box-sizing:border-box !important;
        }

        .tf-codex-entry {
            width:100% !important;
            height:58px !important;
            min-height:58px !important;
            padding:4px !important;
            margin:0 !important;
            display:flex !important;
            align-items:center !important;
            justify-content:center !important;
            border:1px solid rgba(106,76,43,.24) !important;
            background:rgba(248,239,216,.34) !important;
            user-select:none !important;
            -webkit-user-drag:none !important;
            box-shadow:none !important;
            border-radius:0 !important;
            cursor:default !important;
        }
        .tf-codex-entry::before { display:none !important; }
        .tf-codex-entry:hover { background:rgba(255,248,229,.56) !important; }
        .tf-codex-entry.is-active-selection { border-color:rgba(138,45,37,.58) !important; box-shadow:inset 0 0 0 1px rgba(138,45,37,.18) !important; }

        .tf-codex-page .tf-codex-body {
            width:284px !important;
            height:196px !important;
            flex:0 0 196px !important;
            min-height:196px !important;
            margin:2px auto 0 !important;
            position:relative !important;
            overflow:hidden !important;
        }
        .tf-codex-page #mcs_tf_inventory {
            width:284px !important;
            height:196px !important;
            margin:0 !important;
            padding:0 !important;
            position:relative !important;
        }
        .tf-codex-page #mcs_tf_inventory .customScrollBox {
            width:284px !important;
            height:196px !important;
            overflow:hidden !important;
            position:relative !important;
        }
        .tf-codex-page #mcs_tf_inventory .customScrollBox .container {
            width:268px !important;
            position:relative !important;
            float:left !important;
            margin:0 !important;
            padding:0 !important;
            /* A saját scrollbar JS a transform értékét kezeli. */
            left:0 !important;
            height:auto !important;
            min-height:0 !important;
            box-sizing:border-box !important;
        }
        .tf-codex-page #mcs_tf_inventory .customScrollBox .content {
            clear:both !important;
            width:100% !important;
            height:auto !important;
            min-height:0 !important;
            margin:0 !important;
            padding:2px 0 4px 0 !important;
            overflow:visible !important;
            box-sizing:border-box !important;
        }
        .tf-codex-page #mcs_tf_inventory .dragger_container {
            position:relative !important;
            width:6px !important;
            height:194px !important;
            float:right !important;
            margin:0 2px 0 0 !important;
            padding:0 !important;
            background:rgba(74,55,35,.25) !important;
            border:1px solid #5c442c !important;
            border-radius:1px !important;
            box-sizing:border-box !important;
        }
        .tf-codex-page #mcs_tf_inventory .dragger {
            position:absolute !important;
            left:0 !important;
            width:4px !important;
            min-width:4px !important;
            height:23px !important;
            min-height:23px !important;
            margin:0 !important;
            padding:0 !important;
            background:#3d2d1e !important;
            border:0 !important;
            border-radius:1px !important;
            box-shadow:none !important;
        }

        .tf-details-body {
            width:280px !important;
            height:296px !important;
            flex:0 0 296px !important;
            min-height:296px !important;
            margin:2px auto 0 !important;
            position:relative !important;
            overflow:hidden !important;
        }
        .tf-details-page #mcs_tf_details {
            width:280px !important;
            height:296px !important;
            margin:0 !important;
            padding:0 !important;
            position:relative !important;
        }
        .tf-details-page #mcs_tf_details .customScrollBox {
            width:280px !important;
            height:296px !important;
            overflow:hidden !important;
            position:relative !important;
        }
        .tf-details-page #mcs_tf_details .customScrollBox .container {
            width:262px !important;
            position:relative !important;
            float:left !important;
            margin:0 !important;
            padding:0 !important;
            left:0 !important;
            height:auto !important;
            min-height:0 !important;
            box-sizing:border-box !important;
        }
        .tf-details-page #mcs_tf_details .customScrollBox .content {
            clear:both !important;
            width:100% !important;
            height:auto !important;
            min-height:0 !important;
            margin:0 !important;
            padding:2px 4px 12px !important;
            overflow:visible !important;
            box-sizing:border-box !important;
        }
        .tf-details-page #mcs_tf_details .dragger_container {
            position:relative !important;
            width:6px !important;
            height:294px !important;
            float:right !important;
            margin:0 2px 0 0 !important;
            padding:0 !important;
            background:rgba(74,55,35,.25) !important;
            border:1px solid #5c442c !important;
            border-radius:1px !important;
            box-sizing:border-box !important;
        }
        .tf-details-page #mcs_tf_details .dragger {
            position:absolute !important;
            left:0 !important;
            width:4px !important;
            height:23px !important;
            min-height:23px !important;
            margin:0 !important;
            padding:0 !important;
            background:#3d2d1e !important;
            border:0 !important;
            border-radius:1px !important;
            box-shadow:none !important;
        }

        /* A plugin saját eseménykezelése marad érvényben; a footer és a lap nem takarja. */
        .tf-codex-page .tf-codex-body,
        .tf-details-page .tf-details-body { z-index:2 !important; }

        /* A sötét takarás és a könyvgeometria a Magazinéval azonos. */
        #altar-modal-overlay .modal-dark-bg,
        #altar-modal-overlay .modal-book-mask {
            top:50px !important;
            left:8px !important;
            width:765px !important;
            height:460px !important;
            box-sizing:border-box !important;
        }
        #altar-modal-overlay .news-spread-book {
            width:648px !important;
            height:382px !important;
            box-sizing:border-box !important;
        }

        /* ---- Drag ghost ---- */
        #tf-drag-ghost {
            position:fixed; top:-200px; left:-200px; width:50px; height:50px; margin-left:-25px; margin-top:-25px;
            pointer-events:none; z-index:9999999; display:none; align-items:center; justify-content:center;
            filter:drop-shadow(0 8px 12px rgba(0,0,0,.4));
        }
        #tf-drag-ghost.is-dragging { display:flex; }
        #tf-drag-ghost img { max-width:100%; max-height:100%; object-fit:contain; }
        #tf-drag-ghost span { font-size:38px; line-height:1; }
        </style>

        <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":"9452a750bc","items":{"36":{"id":36,"title":"R\u00e9gi R\u00e9zkulcs","type":"tool","emoji":"&#128273;","image":"","hint":"Valahol egy poros sarokban lapul...","reward_text":"H\u00fazd r\u00e1 a Z\u00e1rt Bor\u00edt\u00e9kra!","req_item_id":0,"ink_clue":""},"37":{"id":37,"title":"Viaszpecs\u00e9tes Bor\u00edt\u00e9k","type":"locked","emoji":"\u2709","image":"","hint":"Z\u00e1rt bor\u00edt\u00e9k. H\u00fazd r\u00e1 a megfelel\u0151 kulcsot a K\u00f3dexben!","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,"ink_clue":""},"38":{"id":38,"title":"Holdf\u00e9ny L\u00e1mp\u00e1s","type":"tool","emoji":"\ud83c\udfee","image":"","hint":"F\u00e9nye l\u00e1that\u00f3v\u00e1 teszi a l\u00e1thatatlan tint\u00e1t.","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,"ink_clue":""},"39":{"id":39,"title":"Hajnali Harmatcsepp","type":"daily","emoji":"\u2727","image":"","hint":"Minden nap \u00fajragy\u0171jthet\u0151 esszencia.","reward_text":"Tiszta esszencia, amellyel az alv\u00f3 n\u00f6v\u00e9nyeket t\u00e1pl\u00e1lhatod a M\u0171helyben.","req_item_id":0,"ink_clue":""},"40":{"id":40,"title":"Alv\u00f3 Holdvir\u00e1g","type":"evolving","emoji":"\ud83c\udf31","image":"","hint":"3 csepp Hajnali Harmatra van sz\u00fcks\u00e9ge, hogy kivir\u00e1gozzon.","reward_text":"A Holdvir\u00e1g kiny\u00edlt! Ez\u00fcst\u00f6s szirmai k\u00f6z\u00f6tt egy \u0151si dallam csend\u00fcl fel.","req_item_id":0,"ink_clue":""},"41":{"id":41,"title":"Az \u00cdr\u00f3asztal Titkos Rekesze","type":"code_locked","emoji":"\ud83d\udcdc","image":"https:\/\/matolanorbert.hu\/wp-content\/uploads\/2026\/06\/wall.png","hint":"\u00cdrd be a helyes jelsz\u00f3t (BAGOLY) a fi\u00f3kod \u00cdr\u00f3g\u00e9p\u00e9be!","reward_text":"A z\u00e1rszerkezet kattanva engedett! Megtal\u00e1ltad a rejtett napl\u00f3bejegyz\u00e9st.","req_item_id":0,"ink_clue":"BAGOLY"},"51":{"id":51,"title":"Cseresznyefa Nagy\u00edt\u00f3 & M\u00e9cses","type":"tool","emoji":"\ud83d\udd0d","image":"","hint":"F\u00e9nye \u00e9s lencs\u00e9je l\u00e1that\u00f3v\u00e1 teszi a rejtett sorokat.","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,"ink_clue":""},"52":{"id":52,"title":"Alv\u00f3 Holdvir\u00e1g Mag","type":"evolving","emoji":"\ud83c\udf30","image":"","hint":"H\u00e1rom csepp Hajnali Harmatra van sz\u00fcks\u00e9ge.","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,"ink_clue":""},"53":{"id":53,"title":"T\u00f6r\u00f6tt Ir\u00e1nyt\u0171 H\u00e1z","type":"fragment","emoji":"\u2699","image":"","hint":"Egy r\u00e9gi m\u0171szer egyik fele.","reward_text":"S\u00e1rgar\u00e9z ir\u00e1nyt\u0171h\u00e1z, amelyb\u0151l hi\u00e1nyzik a m\u00e1gnest\u0171.","req_item_id":0,"ink_clue":""},"54":{"id":54,"title":"M\u00e1gnesezett Csillagt\u0171","type":"fragment","emoji":"\ud83e\udded","image":"","hint":"Egy r\u00e9gi m\u0171szer m\u00e1sik fele.","reward_text":"Finoman megmunk\u00e1lt ac\u00e9lt\u0171. Csoportos\u00edtsd a h\u00e1z\u00e1val a M\u0171helyben!","req_item_id":0,"ink_clue":""},"55":{"id":55,"title":"Asztr\u00e1lis Ir\u00e1nyt\u0171","type":"craftable","emoji":"\u2638","image":"","hint":"A M\u0171helyben \u00e1ll\u00edthat\u00f3 \u00f6ssze k\u00e9t t\u00f6red\u00e9kb\u0151l.","reward_text":"Sikeresen \u00f6sszeillesztetted a polcon!","req_item_id":0,"ink_clue":""},"56":{"id":56,"title":"Sz\u00e1r\u00edtott Holdf\u0171","type":"ingredient","emoji":"&#127807;","image":"","hint":"Ez\u00fcst\u00f6sen csillog\u00f3 gy\u00f3gyn\u00f6v\u00e9ny.","reward_text":"Holdf\u0171.","req_item_id":0,"ink_clue":""},"57":{"id":57,"title":"Por\u00edtott Borosty\u00e1n","type":"ingredient","emoji":"\u26b1","image":"","hint":"Aranyl\u00f3 \u00e1sv\u00e1nyi \u0151rlem\u00e9ny.","reward_text":"Finomra \u0151r\u00f6lt feny\u0151gyanta-k\u0151zet. M\u00e1s alapanyagokkal csoportos\u00edtva elix\u00edrr\u00e9 f\u0151zhet\u0151.","req_item_id":0,"ink_clue":""},"58":{"id":58,"title":"\u00c9jf\u00e9li Harmatgomba","type":"ingredient","emoji":"\ud83c\udf44","image":"","hint":"S\u00f6t\u00e9tben dereng\u0151 apr\u00f3 kalapos gomba.","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,"ink_clue":""},"59":{"id":59,"title":"\u00c9jjell\u00e1t\u00f3 Elix\u00edr","type":"potion","emoji":"&#129514;","image":"","hint":"A M\u0171helyben f\u0151zhet\u0151 b\u00e1jital (Sz\u00e1r\u00edtott Holdf\u0171 + Por\u00edtott Borosty\u00e1n).","reward_text":"K\u00e9sz.","req_item_id":0,"ink_clue":""},"60":{"id":60,"title":"\u00c1loml\u00e1t\u00f3 F\u0151zet","type":"potion","emoji":"\u2697","image":"","hint":"A M\u0171helyben f\u0151zhet\u0151 elix\u00edr (2x Sz\u00e1r\u00edtott Holdf\u0171 + 1x \u00c9jf\u00e9li Harmatgomba).","reward_text":"Elk\u00e9sz\u00fclt a f\u0151zet az \u00fcstben!","req_item_id":0,"ink_clue":""},"61":{"id":61,"title":"Titkos Rekesz","type":"code_locked","emoji":"&#128220;","image":"","hint":"BAGOLY","reward_text":"A Kriptex kinyitotta!","req_item_id":0,"ink_clue":"TITOK"},"62":{"id":62,"title":"Rejtett Fi\u00f3k Kincse","type":"simple","emoji":"\ud83c\udffa","image":"","hint":"A titkos kopogtat\u00e1s jutalma.","reward_text":"A helyes ritmus\u00fa kopogtat\u00e1sra kipattant az \u00edr\u00f3asztal rejtett oldalfi\u00f3kja!","req_item_id":0,"ink_clue":""},"63":{"id":63,"title":"Z\u00e1rt Bor\u00edt\u00e9k","type":"locked","emoji":"&#9993;","image":"","hint":"","reward_text":"Kiny\u00edlt a titkos lev\u00e9l!","req_item_id":36,"ink_clue":""},"64":{"id":64,"title":"Nagy\u00edt\u00f3 & M\u00e9cses","type":"tool","emoji":"\ud83d\udd0d","image":"","hint":"","reward_text":"Felfedi a [titkos_tinta] \u00e9s [titkos_parazs] sorokat, k\u00e9zbe v\u00e9ve a [titkos_vizjel]-et is!","req_item_id":0,"ink_clue":""},"65":{"id":65,"title":"Hajnali Harmat","type":"daily","emoji":"\u2727","image":"","hint":"","reward_text":"Az asztalr\u00f3l h\u00fazd r\u00e1 a polcon l\u00e9v\u0151 alv\u00f3 magra!","req_item_id":0,"ink_clue":""},"66":{"id":66,"title":"Alv\u00f3 Mag","type":"evolving","emoji":"\ud83c\udf30","image":"","hint":"","reward_text":"Kiny\u00edlt!","req_item_id":0,"ink_clue":""},"67":{"id":67,"title":"T\u00f6r\u00f6tt Ir\u00e1nyt\u0171","type":"fragment","emoji":"\u2699","image":"","hint":"","reward_text":"H\u00fazd r\u00e1 a Csillagt\u0171re a polcon!","req_item_id":0,"ink_clue":""},"68":{"id":68,"title":"Csillagt\u0171","type":"fragment","emoji":"\ud83e\udded","image":"","hint":"","reward_text":"H\u00fazd \u00f6ssze a T\u00f6r\u00f6tt Ir\u00e1nyt\u0171vel a polcon!","req_item_id":0,"ink_clue":""},"69":{"id":69,"title":"Krist\u00e1lypor","type":"ingredient","emoji":"&#10024;","image":"","hint":"","reward_text":"Por.","req_item_id":0,"ink_clue":""},"70":{"id":70,"title":"Nyers Holdkrist\u00e1ly","type":"crushable","emoji":"&#128142;","image":"","hint":"","reward_text":"Krist\u00e1ly.","req_item_id":0,"ink_clue":""},"71":{"id":71,"title":"Titkos Rekesz (Kriptexhez)","type":"code_locked","emoji":"\ud83d\udcdc","image":"","hint":"","reward_text":"A Kriptex kinyitotta!","req_item_id":0,"ink_clue":"BAGOLY"},"72":{"id":72,"title":"Csillagkapu (Asztrol\u00e1biumhoz)","type":"locked","emoji":"\ud83c\udf0c","image":"","hint":"","reward_text":"Az Asztrol\u00e1bium kinyitotta!","req_item_id":0,"ink_clue":""},"73":{"id":73,"title":"Arany Fi\u00f3k (M\u00e9rleghez)","type":"locked","emoji":"\ud83c\udffa","image":"","hint":"","reward_text":"A M\u00e9rleg kiegyens\u00falyoz\u00e1sa kinyitotta!","req_item_id":0,"ink_clue":""},"80":{"id":80,"title":"Elfeledett Lapt\u00f6red\u00e9k","type":"recipe_page","emoji":"&#128196;","image":"","hint":"","reward_text":"\u00c9jjell\u00e1t\u00f3 Elix\u00edr: Tiszt\u00edtott V\u00edz, Sz\u00e1r\u00edtott Holdf\u0171, Krist\u00e1lypor. H\u0151: 3.","req_item_id":0,"ink_clue":""},"84":{"id":84,"title":"Tiszt\u00edtott V\u00edz","type":"ingredient","emoji":"&#128167;","image":"","hint":"","reward_text":"V\u00edz.","req_item_id":0,"ink_clue":""}},"initial_state":{"collected":[],"unlocked_locks":[],"evolved":[],"feed_counts":[],"ingredients":[],"essence":0,"last_daily":"","server_rev":0},"server_today":"2026-10-04"};
            const itemsDB = TF_Config.items || {};
            let userState = normalizeState(TF_Config.initial_state);
            
            let collectionFilter = 'all';
            let activeItemId = null;
            let dragContext = null;

            function getEmptyState() { return { collected: [], unlocked_locks: [], evolved: [], feed_counts: {}, ingredients: {}, essence: 0 }; }
            function normalizeState(rawState) {
                const st = Object.assign(getEmptyState(), rawState || {});
                const cleanIds = (value) => Array.from(new Set((Array.isArray(value) ? value : []).map(Number).filter(v => Number.isInteger(v) && v > 0)));
                st.collected = cleanIds(st.collected);
                st.unlocked_locks = cleanIds(st.unlocked_locks);
                if (!st.ingredients || typeof st.ingredients !== 'object') st.ingredients = {};
                const cleanIngredients = {};
                Object.keys(st.ingredients).forEach(k => { const id = Number(k); const qty = Math.floor(Number(st.ingredients[k]) || 0); if (id > 0 && qty > 0) cleanIngredients[id] = qty; });
                st.ingredients = cleanIngredients;
                st.essence = Math.max(0, Math.floor(Number(st.essence) || 0));
                return st;
            }
            function stableState(st) {
                return JSON.stringify({ collected:st.collected||[], unlocked_locks:st.unlocked_locks||[], evolved:st.evolved||[], feed_counts:st.feed_counts||{}, ingredients:st.ingredients||{}, essence:st.essence||0, last_daily:st.last_daily||'' });
            }
            function applyServerState(state) {
                const next = normalizeState(state);
                if (stableState(userState) === stableState(next)) return;
                userState = next;
                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 getDisplayImage(item) { return item.image; }
            function getDisplayEmoji(item) { return item.emoji; }

            // Drag and Drop (csak a zárakhoz)
            function ensureDragGhost() { let g = document.getElementById('tf-drag-ghost'); return g; }
            function startCustomDrag(e, itemId) {
                // A Kódex matricái nem húzhatók.
                return false;
            }

            // Nincs drag-and-drop a Kódex matricáin.
            // A pointermove/pointerup globális drag-kezelők szándékosan nincsenek regisztrálva.

            // Kattintások kezelése
            document.addEventListener('click', function(e) {
                const filterBtn = e.target.closest('.tf-album-filter');
                if (filterBtn) {
                    e.preventDefault();
                    collectionFilter = filterBtn.dataset.filter || 'all';
                    document.querySelectorAll('.tf-album-filter').forEach(b => b.classList.toggle('is-active', b === filterBtn));
                    // Kategória/lap váltásakor mindig a kategória első tárgya nyíljon meg.
                    const firstItem = getFirstCodexItem();
                    activeItemId = firstItem ? Number(firstItem.id) : null;
                    renderScrapbook();
                    if (firstItem) showItemDetails(firstItem);
                    else {
                        const empty = document.getElementById('tf-details-empty');
                        const content = document.getElementById('tf-details-content');
                        if (empty) empty.style.display = 'flex';
                        if (content) content.style.display = 'none';
                    }
                    updateCodexScrollbars();
                    return;
                }
                const entrySq = e.target.closest('.tf-codex-entry');
                if (entrySq) {
                    e.preventDefault();
                    const pId = Number(entrySq.dataset.itemId);
                    if (!pId || !itemsDB[pId]) return;
                    activeItemId = pId;
                    document.querySelectorAll('.tf-codex-entry.is-active-selection').forEach(el => el.classList.remove('is-active-selection'));
                    entrySq.classList.add('is-active-selection');
                    showItemDetails(itemsDB[pId]);
                    return;
                }

                const secretBtn = e.target.closest('#tf-secret-btn');
                if (secretBtn) {
                    e.preventDefault();
                    const inputEl = document.getElementById('tf-secret-input');
                    const codeVal = inputEl ? inputEl.value.trim() : '';
                    if (!codeVal) return;
                    sendAction('unlock_code', 0, { code: codeVal }, (resData) => {
                        if (resData && resData.unlocked_id && itemsDB[resData.unlocked_id]) { 
                            activeItemId = resData.unlocked_id;
                            renderScrapbook();
                            showItemDetails(itemsDB[resData.unlocked_id]); 
                        } else {
                            inputEl.style.borderColor = '#8a2d25';
                            inputEl.value = '';
                            inputEl.placeholder = 'Hibás jelszó!';
                        }
                    }, () => {
                        if(inputEl) { inputEl.style.borderColor = '#8a2d25'; inputEl.value = ''; inputEl.placeholder = 'Hibás jelszó!'; }
                    });
                }
            });

            function codexCategoryName(type) {
                if (['ingredient','crushable'].includes(type)) return 'Alapanyag';
                if (type === 'potion') return 'Főzet';
                if (['tool','fragment'].includes(type)) return 'Eszköz';
                if (['locked','code_locked','evolving','craftable'].includes(type)) return 'Titok';
                return 'Kincs';
            }
            
            function codexCategory(item) {
                if (['ingredient','crushable'].includes(item.type)) return 'ingredient';
                if (item.type === 'potion') return 'potion';
                if (['tool','fragment'].includes(item.type)) return 'tool';
                if (['locked','code_locked','evolving','craftable'].includes(item.type)) return 'secret';
                return 'relic';
            }

            // Jobb oldali panel frissítése
            function showItemDetails(item) {
                document.getElementById('tf-details-empty').style.display = 'none';
                const contentDiv = document.getElementById('tf-details-content');
                contentDiv.style.display = 'block';

                const dImg = getDisplayImage(item); 
                const dEmoji = getDisplayEmoji(item);
                const isCol = userState.collected.includes(Number(item.id));
                const isLockOpen = isLockOpened(item);

                const imgWrap = document.getElementById('tf-details-img-wrap');
                const titleEl = document.getElementById('tf-details-title');
                const descEl  = document.getElementById('tf-details-desc');
                const actEl   = document.getElementById('tf-details-actions');
                const metaEl  = document.getElementById('tf-details-meta');
                
                actEl.innerHTML = '';
                const catName = codexCategoryName(item.type);

                let metaText = 'Típus: ' + catName;
                if (isCol) {
                    if (['ingredient', 'potion', 'crushable'].includes(item.type)) {
                        metaText += ' &nbsp;|&nbsp; Birtokodban: ' + getIngredientCount(item.id) + ' db';
                    } else {
                        metaText += ' &nbsp;|&nbsp; Birtokodban: 1 db';
                    }
                } else {
                    metaText += ' &nbsp;|&nbsp; Birtokodban: 0 db';
                }
                metaEl.innerHTML = metaText;

                if (isCol && (item.type !== 'locked' || isLockOpen)) {
                    // Tárgy megvan
                    imgWrap.style.filter = 'none';
                    imgWrap.style.border = 'none';
                    imgWrap.style.background = 'transparent';
                    imgWrap.innerHTML = dImg ? '<img src="' + dImg + '">' : '<span class="tf-emoji-icon">' + dEmoji + '</span>';
                    titleEl.textContent = item.title;
                    
                    let rawText = item.reward_text || 'Ereklye a gyűjteményedből.';
                    descEl.innerHTML = rawText.replace(/\n/g, '<br>');
                } else {
                    // Sziluett vagy Zárt
                    imgWrap.style.filter = 'grayscale(1) brightness(0.15) opacity(0.3)';
                    imgWrap.style.border = '1px dashed #846635';
                    imgWrap.style.background = 'rgba(56,36,22,0.05)';
                    imgWrap.innerHTML = dImg ? '<img src="' + dImg + '">' : '<span class="tf-emoji-icon">' + dEmoji + '</span>';
                    titleEl.textContent = 'Ismeretlen ' + catName;
                    
                    let rawText = item.hint ? ('<strong>Nyom:</strong> ' + item.hint) : 'A sors még nem hozta utadba ezt a rejtélyt.';
                    
                    if (item.type === 'locked') {
                        rawText += '<br><br><span style="color:#8a2d25; font-weight:bold;">ZÁRT TÁRGY</span><br>Ez a tárgy kulcsra van zárva. Keress a gyűjteményedben egy megfelelő eszközt, és húzd rá a bal oldali rácsban lévő matricára a kinyitáshoz!';
                    }
                    
                    descEl.innerHTML = rawText.replace(/\n/g, '<br>');

                    // Jelszómező
                    if (item.type === 'code_locked' && !isCol) {
                        actEl.innerHTML = '<div style="margin-top:10px;">'
                                        + '<p style="font-family:Georgia, serif; font-size:12px; font-style:italic; color:#6f5438;">Írd be a megfelelő szót vagy kódot:</p>'
                                        + '<input type="text" id="tf-secret-input" class="tf-secret-input" placeholder="Titkos jelszó..."><br>'
                                        + '<button type="button" id="tf-secret-btn" class="tf-vintage-btn">Feloldás</button>'
                                        + '</div>';
                    }
                }

                // Scroll újrakalkulálás
                requestAnimationFrame(() => updateCodexScrollbars());
            }

            // Bal oldali Rács Kirajzolása (Mindent egyszerre, nincs lapozás)
            function renderScrapbook() {
                const leftGrid = document.getElementById('tf-grid-left');
                if (!leftGrid) return;
                const filteredItems = getFilteredCodexItems();
                const fragment = document.createDocumentFragment();
                const totalKnown = filteredItems.filter(it => userState.collected.includes(Number(it.id))).length;
                const progressEl = document.querySelector('.tf-collection-progress');
                if (progressEl) progressEl.textContent = totalKnown + ' / ' + filteredItems.length;
                filteredItems.forEach((it) => {
                    const isCol = userState.collected.includes(Number(it.id));
                    const qty = getIngredientCount(it.id);
                    const sq = document.createElement('div');
                    sq.className = 'tf-codex-entry ' + (isCol ? 'is-known' : 'is-silhouette');
                    if (isCol && it.type === 'locked' && !isLockOpened(it)) sq.classList.add('is-locked');
                    if (activeItemId === Number(it.id)) sq.classList.add('is-active-selection');
                    sq.dataset.itemId = it.id;
                    sq.draggable = false;
                    sq.style.userSelect = 'none';
                    sq.style.webkitUserDrag = 'none';
                    const visual = getDisplayImage(it) ? '<img src="'+getDisplayImage(it)+'" alt="" draggable="false">' : '<span class="tf-emoji-icon">'+getDisplayEmoji(it)+'</span>';
                    sq.innerHTML = visual;
                    if (isCol && it.type === 'locked' && !isLockOpened(it)) sq.innerHTML += '<span class="tf-album-lock">&#128274;</span>';
                    if (isCol && ['ingredient','potion','crushable'].includes(it.type) && qty > 0) sq.innerHTML += '<span class="tf-album-qty">'+qty+'</span>';
                    fragment.appendChild(sq);
                });
                leftGrid.replaceChildren(fragment);
                updateCodexScrollbars();
            }

            // Saját scrollbar JS: kizárólag a Magazin megjelenését utánozza.
            const nativeCodexScroll = new WeakMap();
            function initOneCodexScrollbar(sel) {
                const root=document.querySelector(sel); if(!root)return;
                const box=root.querySelector('.customScrollBox'), container=root.querySelector('.customScrollBox .container'), content=root.querySelector('.customScrollBox .content'), track=root.querySelector('.dragger_container'), thumb=root.querySelector('.dragger');
                if(!box||!container||!content||!track||!thumb)return;
                let st=nativeCodexScroll.get(root);
                if(!st){
                    st={y:0,max:0,dragging:false,startPointer:0,startY:0,touchActive:false,touchStart:0,touchY:0}; nativeCodexScroll.set(root,st);
                    const clamp=(v,a,b)=>Math.max(a,Math.min(b,v));
                    st.setY=(y)=>{st.y=clamp(y,0,st.max);container.style.transform='translate3d(0,'+(-st.y)+'px,0)';const travel=Math.max(0,track.clientHeight-23);thumb.style.top=Math.round(st.max?st.y/st.max*travel:0)+'px';};
                    root.addEventListener('wheel',e=>{if(st.max<=0)return;const d=e.deltaY||0;if(!d)return;e.preventDefault();st.setY(st.y+d);},{passive:false});
                    track.addEventListener('pointerdown',e=>{if(e.target===thumb||thumb.contains(e.target)||st.max<=0)return;e.preventDefault();const r=track.getBoundingClientRect(),travel=Math.max(1,r.height-23),pos=clamp(e.clientY-r.top-11.5,0,travel);st.setY(st.max*pos/travel);});
                    thumb.addEventListener('pointerdown',e=>{e.preventDefault();e.stopPropagation();st.dragging=true;st.startPointer=e.clientY;st.startY=st.y;try{thumb.setPointerCapture(e.pointerId);}catch(_) {}});
                    thumb.addEventListener('pointermove',e=>{if(!st.dragging)return;const travel=Math.max(1,track.clientHeight-23);st.setY(st.startY+(e.clientY-st.startPointer)*(st.max/travel));});
                    const stop=()=>{st.dragging=false;}; thumb.addEventListener('pointerup',stop); thumb.addEventListener('pointercancel',stop);
                    box.addEventListener('touchstart',e=>{if(e.touches.length!==1||st.max<=0||e.target.closest('.dragger_container'))return;st.touchActive=true;st.touchStart=e.touches[0].clientY;st.touchY=st.y;},{passive:true});
                    box.addEventListener('touchmove',e=>{if(!st.touchActive||e.touches.length!==1||st.max<=0)return;const dy=e.touches[0].clientY-st.touchStart;if(Math.abs(dy)<2)return;e.preventDefault();st.setY(st.touchY-dy);},{passive:false});
                    box.addEventListener('touchend',()=>{st.touchActive=false;},{passive:true}); box.addEventListener('touchcancel',()=>{st.touchActive=false;},{passive:true});
                }
                const viewportH=box.clientHeight, contentH=Math.max(content.scrollHeight,container.scrollHeight); st.max=Math.max(0,contentH-viewportH); track.style.display=st.max>0?'block':'none'; thumb.style.height='23px'; thumb.style.minHeight='23px'; thumb.style.left='0px'; st.setY(st.max?Math.min(st.y,st.max):0);
            }
            let codexScrollFrame=0;
            function updateCodexScrollbars(){if(codexScrollFrame)return;codexScrollFrame=requestAnimationFrame(()=>{codexScrollFrame=0;initOneCodexScrollbar('#mcs_tf_inventory');initOneCodexScrollbar('#mcs_tf_details');});}

            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) {
                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); } }).catch(err => console.error(err));
            }

            function getFilteredCodexItems() {
                return Object.values(itemsDB).filter(it => {
                    if (it.type === 'recipe_page' || it.type === 'daily') return false;
                    const isCol = userState.collected.includes(Number(it.id));
                    const qty = getIngredientCount(it.id);
                    const category = codexCategory(it);
                    if (collectionFilter !== 'all' && category !== collectionFilter) return false;
                    if (it.type === 'ingredient' && qty <= 0 && !isCol) return false;
                    return true;
                });
            }

            function getFirstCodexItem() {
                return getFilteredCodexItems()[0] || null;
            }

            function syncScrapbookEntries() {
                const leftGrid = document.getElementById('tf-grid-left');
                if (!leftGrid) return;
                const filteredItems = getFilteredCodexItems();
                const currentIds = Array.from(leftGrid.querySelectorAll('.tf-codex-entry')).map(el => Number(el.dataset.itemId));
                const nextIds = filteredItems.map(it => Number(it.id));
                if (currentIds.length !== nextIds.length || currentIds.some((id,i) => id !== nextIds[i])) {
                    renderScrapbook();
                    return;
                }

                const totalKnown = filteredItems.filter(it => userState.collected.includes(Number(it.id))).length;
                const progressEl = document.querySelector('.tf-collection-progress');
                if (progressEl) progressEl.textContent = totalKnown + ' / ' + filteredItems.length;

                filteredItems.forEach((it, index) => {
                    const el = leftGrid.children[index];
                    if (!el) return;
                    const isCol = userState.collected.includes(Number(it.id));
                    const qty = getIngredientCount(it.id);
                    el.classList.toggle('is-known', isCol);
                    el.classList.toggle('is-silhouette', !isCol);
                    el.classList.toggle('is-active-selection', activeItemId === Number(it.id));
                    el.classList.toggle('is-locked', isCol && it.type === 'locked' && !isLockOpened(it));

                    let lockBadge = el.querySelector('.tf-album-lock');
                    const needsLock = isCol && it.type === 'locked' && !isLockOpened(it);
                    if (needsLock && !lockBadge) {
                        lockBadge = document.createElement('span');
                        lockBadge.className = 'tf-album-lock';
                        lockBadge.textContent = '🔒';
                        el.appendChild(lockBadge);
                    } else if (!needsLock && lockBadge) {
                        lockBadge.remove();
                    }

                    let qtyBadge = el.querySelector('.tf-album-qty');
                    const needsQty = isCol && ['ingredient','potion','crushable'].includes(it.type) && qty > 0;
                    if (needsQty) {
                        if (!qtyBadge) { qtyBadge = document.createElement('span'); qtyBadge.className = 'tf-album-qty'; el.appendChild(qtyBadge); }
                        qtyBadge.textContent = qty;
                    } else if (qtyBadge) {
                        qtyBadge.remove();
                    }
                });
                updateCodexScrollbars();
            }

            function refreshAllUI() {
                const essenceEl=document.querySelector('.tf-essence-count'); if(essenceEl) essenceEl.textContent=userState.essence;
                const today=TF_Config.server_today;
                document.querySelectorAll('.tf-world-item').forEach(el=>{const id=Number(el.dataset.itemId),item=itemsDB[id];if(!item)return;if(item.type==='daily'){if(userState.last_daily===today)el.classList.add('tf-collected-hide');else el.classList.remove('tf-collected-hide');}else if(userState.collected.includes(id))el.classList.add('tf-collected-hide');else el.classList.remove('tf-collected-hide');});
                const visible=getFilteredCodexItems();
                if(!activeItemId||!visible.some(it=>Number(it.id)===Number(activeItemId))){const first=visible[0]||null;activeItemId=first?Number(first.id):null;}
                syncScrapbookEntries(); if(activeItemId&&itemsDB[activeItemId])showItemDetails(itemsDB[activeItemId]);
                else{const empty=document.getElementById('tf-details-empty'),content=document.getElementById('tf-details-content');if(empty)empty.style.display='flex';if(content)content.style.display='none';}
            }
            function selectFirstCodexItem(){
                const first=getFirstCodexItem(); activeItemId=first?Number(first.id):null; renderScrapbook(); if(first)showItemDetails(first);
                else{const empty=document.getElementById('tf-details-empty'),content=document.getElementById('tf-details-content');if(empty)empty.style.display='flex';if(content)content.style.display='none';}
            }
            function boot(){
                refreshAllUI(); syncWithServer();
                document.addEventListener('tf:altar-closed',()=>{collectionFilter='all';document.querySelectorAll('.tf-album-filter').forEach(b=>b.classList.toggle('is-active',(b.dataset.filter||'all')==='all'));selectFirstCodexItem();});
                setTimeout(updateCodexScrollbars,100); window.addEventListener('resize',updateCodexScrollbars);
            }
            if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', boot); else boot();
        })();
        </script>
        