{"id":224,"date":"2026-06-04T03:04:48","date_gmt":"2026-06-04T03:04:48","guid":{"rendered":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/?p=224"},"modified":"2026-06-05T01:56:49","modified_gmt":"2026-06-05T01:56:49","slug":"materials-production-tree","status":"publish","type":"post","link":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/materials-production-tree\/","title":{"rendered":"EVE Frontier Materials Production Tree"},"content":{"rendered":"\r\n<div id=\"evefrontier-material-tree\" data-json=\"https:\/\/gamingwithdaopa.ellatha.com\/media\/evefrontier\/blueprints.json\">\r\n  <style>\r\n    \/* === EVE-INSPIRED THEME (same as before) === *\/\r\n    :root{\r\n      --bg:#0a0c10; --panel:#12141b; --panel-2:#171a22; --ink:#e6edf3; --muted:#9aa4b2;\r\n      --accent:#39d0ff; --accent-2:#00ffa8; --warn:#ffbe55; --red:#ff5555; --grid:#1f2430;\r\n      --chip:#222635; --shadow:0 10px 30px rgba(0,0,0,.35), inset 0 1px 0 rgba(255,255,white,.03);\r\n      --radius:14px;\r\n    }\r\n    #evefrontier-material-tree{\r\n      color:var(--ink); font:14px\/1.5 Inter, system-ui, -apple-system, Segoe UI, Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", \"Liberation Sans\", sans-serif;\r\n      background:radial-gradient(1200px 600px at 70% -20%,rgba(57,208,255,.05),transparent 60%), var(--bg);\r\n      padding:18px; border-radius:var(--radius); box-shadow:var(--shadow); position:relative; overflow:hidden;\r\n    }\r\n    #evefrontier-material-tree::after{\r\n      content:\"\"; position:absolute; inset:-2px;\r\n      background:radial-gradient(800px 400px at 110% 20%,rgba(0,255,168,.06),transparent 60%);\r\n      pointer-events:none; filter:blur(2px);\r\n    }\r\n    h1,h2,h3{ letter-spacing:.08em; text-transform:uppercase; margin:6px 0 10px }\r\n    h1{ font-size:22px } h2{ font-size:16px; color:#fff }\r\n    p.lede{ color:var(--muted); margin:8px 0 16px }\r\n    .shell{ display:grid; grid-template-columns: 300px 1fr; gap:16px; min-height:520px; }\r\n    @media (max-width: 900px){ .shell{ grid-template-columns:1fr } }\r\n    .sidebar{ display:flex; flex-direction:column; background:linear-gradient(180deg,var(--panel),var(--panel-2));\r\n      border:1px solid #202531; border-radius:var(--radius); overflow:hidden; min-height:480px; }\r\n    .toolbar{ display:grid; gap:8px; grid-template-columns:auto 1fr 36px 36px; padding:10px;\r\n      border-bottom:1px solid var(--grid); background:linear-gradient(180deg,rgba(57,208,255,.04),transparent);\r\n      position:sticky; top:0; z-index:2; }\r\n    .search{ width:100%; background:#0e1118; border:1px solid #1e2430; color:#fff; border-radius:10px; padding:8px 12px; outline:none; }\r\n    .search::placeholder{ color:var(--muted); }\r\n    .search-icon{ color:#7d8798; display:flex; align-items:center; justify-content:center; }\r\n    .sort, .filter-raw{ border:1px solid #1e2430; background:#0e1118; color:var(--ink);\r\n      border-radius:10px; cursor:pointer; }\r\n    .list{ overflow:auto; flex:1; scrollbar-width:thin; scrollbar-color:#2b3242 transparent; }\r\n    .group{ border-bottom:1px solid rgba(255,255,white,.04); }\r\n    .group-title{ width:100%; text-align:left; display:flex; align-items:center; justify-content:space-between;\r\n      gap:8px; padding:8px 10px; cursor:pointer; background:linear-gradient(180deg,#151924,#121622);\r\n      border-bottom:1px solid rgba(255,255,white,.03); font-weight:600; }\r\n    .group-title .left{ display:flex; align-items:center; gap:8px }\r\n    .group-title .count{ color:var(--muted); font-weight:500; font-size:12px }\r\n    .group-items{ display:none }\r\n    .group[data-open=\"true\"] .group-items{ display:block }\r\n    .group-title .caret{ transition:transform .15s ease }\r\n    .group[data-open=\"true\"] .group-title .caret{ transform:rotate(180deg) }\r\n    .item{ display:grid; grid-template-columns:42px 1fr auto; gap:12px; align-items:center; padding:10px 12px;\r\n      border-bottom:1px solid rgba(255,255,white,.03); background:transparent; color:var(--ink); cursor:pointer;\r\n      transition:background .15s ease, transform .04s ease; }\r\n    .item:hover{ background:rgba(57,208,255,.06) }\r\n    .item.active{ background:linear-gradient(90deg,rgba(57,208,255,.12),transparent 60%);\r\n      outline:1px solid rgba(57,208,255,.35); }\r\n    .item .name{ font-weight:600 }\r\n    .badge{ display:inline-flex; gap:6px; align-items:center; background:var(--chip); border:1px solid #2a3144;\r\n      color:#b8c0cc; padding:3px 8px; border-radius:999px; font-size:11px; }\r\n    .badge.raw{ background:#1a3a2a; border-color:#00ffa8; color:#00ffa8; }\r\n    .bp-icon, .bp-icon-large { border-radius:6px; border:1px solid #2a3144; background:#0e1118; object-fit:contain;\r\n      box-shadow:0 2px 8px rgba(0,0,0,.35); flex-shrink:0; image-rendering: crisp-edges; }\r\n    .bp-icon { width:36px; height:36px; }\r\n    .bp-icon-large { width:96px; height:96px; border-width:2px; border-color:#39d0ff;\r\n      box-shadow:0 0 18px rgba(57,208,255,.4), 0 6px 22px rgba(0,0,0,.5); }\r\n    .icon-frame { width:120px; height:120px; background:linear-gradient(145deg, #12141b, #0a0c10);\r\n      border:1px solid #263042; border-radius:12px; display:flex; align-items:center; justify-content:center;\r\n      overflow:hidden; box-shadow: inset 0 0 0 1px rgba(255,255,white,.03), 0 6px 24px rgba(0,0,0,.45); position:relative; }\r\n    .icon-frame::after { content:''; position:absolute; inset:0;\r\n      background:radial-gradient(circle at 30% 25%, rgba(57,208,255,.12), transparent 60%); pointer-events:none; }\r\n    .placeholder { display:flex; align-items:center; justify-content:center; color:#4a5468; background:#0e1118; width:100%; height:100%; }\r\n    .panel{ background:linear-gradient(180deg,var(--panel),var(--panel-2)); border:1px solid #202531;\r\n      border-radius:var(--radius); padding:16px; min-height:480px; position:relative; overflow:hidden; }\r\n    .holo{ display:grid; grid-template-columns:140px 1fr auto; gap:14px; align-items:center; padding:12px;\r\n      border:1px solid #263042; border-radius:12px; background:linear-gradient(180deg,rgba(0,255,168,.06),rgba(57,208,255,.04));\r\n      box-shadow:inset 0 0 0 1px rgba(255,255,white,.02); }\r\n    .title{ display:flex; flex-direction:column; gap:4px }\r\n    .title h2{ margin:0; font-size:18px; letter-spacing:.12em }\r\n    .sub{ color:var(--muted); font-size:12px }\r\n    .chips{ display:flex; gap:8px; flex-wrap:wrap }\r\n    .tree-wrap{ margin-top:16px; padding:14px; background:#0f131b; border:1px solid #1e2431; border-radius:12px; }\r\n    .tree-view{ max-height:520px; overflow:auto; padding:4px 0; }\r\n    .tree-root{ font-size:15px; font-weight:600; padding:8px 12px; background:rgba(57,208,255,.08);\r\n      border:1px solid #263042; border-radius:10px; margin-bottom:10px; }\r\n    .tree-node{ margin:6px 0 6px 20px; position:relative; }\r\n    .tree-node::before{ content:\"\"; position:absolute; left:-12px; top:0; bottom:0; width:1px; background:var(--muted); opacity:.25; }\r\n    .usage-header{ display:flex; flex-wrap:wrap; align-items:flex-start; gap:8px; padding:10px 12px; }\r\n    .usage-header > div:first-child { flex:1 1 auto; min-width:0; display:flex; flex-wrap:wrap; align-items:center; gap:8px; }\r\n    .usage-header .faint[style*=\"consumes\"] { white-space:normal; flex:1 1 100%; font-size:12.5px; line-height:1.35; margin-top:2px; }\r\n    @media (max-width: 600px) {\r\n      .usage-header { padding:10px 8px; }\r\n    }\r\n    .tree-sub{ margin-left:12px; padding-left:12px; border-left:1px dashed #2a3144; display:none; }\r\n    .tree-leaf{ padding:4px 8px; font-size:12.5px; display:flex; align-items:center; gap:8px; }\r\n    .tree-summary{ margin-top:12px; padding:10px; background:#0a0c10; border-radius:8px; font-size:12px; color:var(--muted); }\r\n    .mono{ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", monospace }\r\n    .faint{ color:var(--muted) }\r\n    .sep{ opacity:.35; margin:0 8px }\r\n    .btn-mini{ display:inline-flex; align-items:center; gap:6px; background:#0e1118; border:1px solid #1e2431;\r\n      color:#d7deea; border-radius:999px; padding:6px 12px; cursor:pointer; font-size:12px; }\r\n    .btn-mini:hover{ border-color:#2b3850; color:#fff }\r\n\r\n    \/* === VISUAL TREE MODAL === *\/\r\n    #visual-tree-modal {\r\n      position: fixed; inset: 0; background: rgba(0,0,0,0.85);\r\n      z-index: 99999; display: none; align-items: center; justify-content: center; padding: 20px;\r\n    }\r\n    #visual-tree-modal.show { display: flex; }\r\n    .visual-tree-content {\r\n      background: linear-gradient(180deg, #12141b, #0a0c10);\r\n      border: 1px solid #39d0ff; border-radius: 16px; width: 100%; max-width: 1100px;\r\n      max-height: 90vh; overflow: hidden; box-shadow: 0 0 40px rgba(57,208,255,0.2);\r\n      display: flex; flex-direction: column;\r\n    }\r\n    .visual-tree-header {\r\n      padding: 16px 24px; border-bottom: 1px solid #263042;\r\n      display: flex; align-items: center; justify-content: space-between;\r\n      background: rgba(57,208,255,0.05);\r\n    }\r\n    .visual-tree-header h2 { margin: 0; font-size: 20px; }\r\n    .visual-tree-close {\r\n      background: transparent; border: 1px solid #39d0ff; color: #39d0ff;\r\n      width: 36px; height: 36px; border-radius: 50%; cursor: pointer;\r\n      font-size: 20px; display: flex; align-items: center; justify-content: center;\r\n    }\r\n    .visual-tree-body {\r\n      padding: 24px; overflow: auto; flex: 1;\r\n    }\r\n    .visual-node {\r\n      background: #171a22; border: 1px solid #2a3144; border-radius: 12px;\r\n      padding: 14px 18px; margin-bottom: 12px; display: flex; align-items: center; gap: 16px;\r\n      transition: all 0.2s ease; box-shadow: 0 4px 12px rgba(0,0,0,0.3);\r\n    }\r\n    .visual-node:hover {\r\n      border-color: #39d0ff; box-shadow: 0 0 20px rgba(57,208,255,0.15);\r\n      transform: translateY(-1px);\r\n    }\r\n    .visual-node.root {\r\n      border-color: #39d0ff; background: rgba(57,208,255,0.08);\r\n      box-shadow: 0 0 25px rgba(57,208,255,0.2);\r\n    }\r\n    .visual-node .icon { flex-shrink: 0; }\r\n    .visual-node .info { flex: 1; min-width: 0; }\r\n    .visual-node .name { font-weight: 600; font-size: 15px; }\r\n    .visual-node .meta { font-size: 12px; color: #9aa4b2; margin-top: 2px; }\r\n    .visual-children {\r\n      margin-left: 40px; padding-left: 20px; border-left: 2px dashed #39d0ff; position: relative;\r\n    }\r\n    .visual-children::before {\r\n      content: ''; position: absolute; left: -2px; top: 0;\r\n      width: 2px; height: 100%; background: linear-gradient(to bottom, #39d0ff, transparent);\r\n    }\r\n    #toast { visibility:hidden; min-width:220px; background:rgba(20,20,20,0.9); color:var(--accent);\r\n      text-align:center; border:1px solid var(--accent); border-radius:6px; padding:12px; position:fixed;\r\n      z-index:9999; right:20px; bottom:20px; font-size:14px; opacity:0; transform:translateY(20px);\r\n      transition:all .5s ease; box-shadow:0 0 12px rgba(0,170,255,0.6); }\r\n    #toast.show { visibility:visible; opacity:1; transform:translateY(0); }\r\n  <\/style>\r\n\r\n  <p class=\"lede\">Trace every industrial chain in EVE Frontier Cycle 5. Start from any material and see the complete recursive tree of everything that material can help you build \u2014 blueprints, components, ships, and end-game items.<\/p>\r\n\r\n  <div class=\"shell\">\r\n    <!-- SIDEBAR -->\r\n    <aside class=\"sidebar\" id=\"material-sidebar\">\r\n      <div class=\"toolbar\">\r\n        <i class=\"fa fa-search search-icon\" aria-hidden=\"true\"><\/i>\r\n        <input class=\"search\" id=\"searchBox\" type=\"search\" placeholder=\"Search material name or typeID\u2026\" \/>\r\n        <button class=\"filter-raw\" id=\"filterRawBtn\" title=\"Toggle Raw Materials only\">\r\n          <i class=\"fa fa-leaf\" aria-hidden=\"true\"><\/i>\r\n        <\/button>\r\n        <button class=\"sort\" id=\"sortBtn\" title=\"Toggle sort A\u21c4Z\">\r\n          <i class=\"fa fa-sort-alpha-asc\" aria-hidden=\"true\"><\/i>\r\n        <\/button>\r\n      <\/div>\r\n      <div class=\"list\" id=\"material-list\"><\/div>\r\n    <\/aside>\r\n\r\n    <!-- DETAIL + TREE -->\r\n    <section class=\"panel\" id=\"material-detail\">\r\n      <div id=\"detail\">\r\n        <div class=\"holo\" aria-live=\"polite\">\r\n          <div class=\"icon-frame\">\r\n            <div class=\"bp-icon-large placeholder\" style=\"width:96px;height:96px;font-size:42px;\">\r\n              <i class=\"fa fa-sitemap\"><\/i>\r\n            <\/div>\r\n          <\/div>\r\n          <div class=\"title\">\r\n            <h2>Material Production Tree<\/h2>\r\n            <div class=\"sub\">Select any material on the left to see the full recursive chain of what it can make.<\/div>\r\n            <div class=\"chips\">\r\n              <span class=\"badge\"><i class=\"fa fa-industry\"><\/i> Recursive Chains<\/span>\r\n              <span class=\"badge\"><i class=\"fa fa-link\"><\/i> Cycle-Safe<\/span>\r\n            <\/div>\r\n          <\/div>\r\n          <div class=\"tag\"><i class=\"fa fa-database\"><\/i> Live: blueprints.json<\/div>\r\n        <\/div>\r\n      <\/div>\r\n\r\n      <!-- THE TREE -->\r\n      <div id=\"treeWrap\" class=\"tree-wrap\" style=\"display:none;\">\r\n        <div style=\"display:flex; align-items:center; justify-content:space-between; margin-bottom:8px; flex-wrap:wrap; gap:8px;\">\r\n          <h3 style=\"margin:0;\"><i class=\"fa fa-sitemap\"><\/i> What this material can make<\/h3>\r\n          <div style=\"display:flex; gap:8px; flex-wrap:wrap;\">\r\n            <button class=\"btn-mini\" id=\"expandAllBtn\"><i class=\"fa fa-plus-square\"><\/i> Expand All<\/button>\r\n            <button class=\"btn-mini\" id=\"collapseAllBtn\"><i class=\"fa fa-minus-square\"><\/i> Collapse All<\/button>\r\n            <button class=\"btn-mini\" id=\"exportJSONBtn\"><i class=\"fa fa-download\"><\/i> JSON<\/button>\r\n            <button class=\"btn-mini\" id=\"exportCSVBtn\"><i class=\"fa fa-file-excel-o\"><\/i> CSV<\/button>\r\n          <\/div>\r\n        <\/div>\r\n        <div class=\"tree-view\" id=\"materialTree\"><\/div>\r\n        <div class=\"tree-summary\" id=\"treeSummary\"><\/div>\r\n      <\/div>\r\n\r\n      <div class=\"status\">\r\n        <span id=\"statusText\">Fetching data\u2026<\/span>\r\n        <span><span class=\"sep\">\u2022<\/span> <span id=\"matCount\">0<\/span> materials tracked<\/span>\r\n      <\/div>\r\n    <\/section>\r\n  <\/div>\r\n\r\n  <!-- VISUAL TREE MODAL -->\r\n  <div id=\"visual-tree-modal\">\r\n    <div class=\"visual-tree-content\">\r\n      <div class=\"visual-tree-header\">\r\n        <h2 id=\"visual-tree-title\"><i class=\"fa fa-sitemap\"><\/i> Visual Production Tree<\/h2>\r\n        <button class=\"visual-tree-close\" onclick=\"document.getElementById('visual-tree-modal').classList.remove('show')\">&times;<\/button>\r\n      <\/div>\r\n      <div class=\"visual-tree-body\" id=\"visual-tree-body\"><\/div>\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <div id=\"toast\"><\/div>\r\n\r\n  <script>\r\n  (async function() {\r\n    const root = document.getElementById('evefrontier-material-tree');\r\n    const JSON_URL = root.getAttribute('data-json');\r\n    const els = {\r\n      list: document.getElementById('material-list'),\r\n      detail: document.getElementById('detail'),\r\n      search: document.getElementById('searchBox'),\r\n      sortBtn: document.getElementById('sortBtn'),\r\n      filterRawBtn: document.getElementById('filterRawBtn'),\r\n      status: document.getElementById('statusText'),\r\n      matCount: document.getElementById('matCount'),\r\n      treeWrap: document.getElementById('treeWrap'),\r\n      materialTree: document.getElementById('materialTree'),\r\n      treeSummary: document.getElementById('treeSummary'),\r\n      expandAllBtn: document.getElementById('expandAllBtn'),\r\n      collapseAllBtn: document.getElementById('collapseAllBtn'),\r\n      exportJSONBtn: document.getElementById('exportJSONBtn'),\r\n      exportCSVBtn: document.getElementById('exportCSVBtn'),\r\n    };\r\n\r\n    const secsToHMS = (s) => {\r\n      if (!Number.isFinite(+s)) return \"\u2014\";\r\n      const d = Math.floor(s\/86400), h = Math.floor((s%86400)\/3600), m = Math.floor((s%3600)\/60), sec = s % 60;\r\n      const parts = []; if (d) parts.push(`${d}d`); if (h) parts.push(`${h}h`); if (m) parts.push(`${m}m`);\r\n      if (sec || (!d && !h && !m)) parts.push(`${sec}s`); return parts.join(\" \");\r\n    };\r\n\r\n    const ICON_BASE = 'https:\/\/gamingwithdaopa.ellatha.com\/media\/evefrontier\/icons\/';\r\n\r\n    function getIconHTML(bp, size = 'small') {\r\n      const cls = size === 'large' ? 'bp-icon-large' : 'bp-icon';\r\n      if (!bp) {\r\n        const ph = size === 'large' ? 'width:96px;height:96px;font-size:42px;' : 'width:36px;height:36px;';\r\n        return `<div class=\"${cls} placeholder\" style=\"${ph}\"><i class=\"fa fa-drafting-compass\"><\/i><\/div>`;\r\n      }\r\n      let iconFile = bp.iconID ? `${bp.iconID}.png` : (bp.graphicID ? `g${bp.graphicID}.png` : null);\r\n      if (iconFile) {\r\n        const safe = (bp.name || 'Item').replace(\/\"\/g, '&quot;');\r\n        return `<img decoding=\"async\" class=\"${cls}\" src=\"${ICON_BASE}${iconFile}\" alt=\"${safe}\" loading=\"lazy\"\r\n                 onerror=\"this.outerHTML='<div class=\\\\'${cls} placeholder\\\\' style=\\\\'${size === 'large' ? 'width:96px;height:96px;font-size:42px;' : 'width:36px;height:36px;'}\\\\'> <i class=\\\\'fa fa-drafting-compass\\\\'><\/i><\/div>'\" \/>`;\r\n      }\r\n      const ph = size === 'large' ? 'width:96px;height:96px;font-size:42px;' : 'width:36px;height:36px;';\r\n      return `<div class=\"${cls} placeholder\" style=\"${ph}\"><i class=\"fa fa-drafting-compass\"><\/i><\/div>`;\r\n    }\r\n\r\n    function getItemIconHTML(typeID, size = 'small') {\r\n      const cls = size === 'large' ? 'bp-icon-large' : 'bp-icon';\r\n      const phStyle = size === 'large' ? 'width:96px;height:96px;font-size:42px;' : 'width:36px;height:36px;';\r\n\r\n      if (itemIcons.has(typeID)) {\r\n        return `<img decoding=\"async\" class=\"${cls}\" src=\"${ICON_BASE}${itemIcons.get(typeID)}\" style=\"object-fit:contain;\" loading=\"lazy\"\r\n                 onerror=\"this.outerHTML='<div class=\\\\'${cls} placeholder\\\\' style=\\\\'${phStyle}\\\\'> <i class=\\\\'fa fa-cube\\\\'><\/i><\/div>'\" \/>`;\r\n      }\r\n\r\n      const producers = producedBy.get(typeID) || [];\r\n      if (producers.length > 0) {\r\n        let bestBp = null;\r\n        const itemName = (itemMap.get(typeID) || \"\").toLowerCase();\r\n        for (const prod of producers) {\r\n          const bp = bpMap.get(prod.recipeKey);\r\n          if (!bp) continue;\r\n          const bpName = bp.name.toLowerCase();\r\n          if (bpName.includes(itemName) || itemName.includes(bpName.replace(\" blueprint\", \"\"))) {\r\n            bestBp = bp;\r\n            break;\r\n          }\r\n          if (!bestBp) bestBp = bp;\r\n        }\r\n        if (bestBp) return getIconHTML(bestBp, size);\r\n      }\r\n      return `<div class=\"${cls} placeholder\" style=\"${phStyle}\"><i class=\"fa fa-cube\"><\/i><\/div>`;\r\n    }\r\n\r\n    let blueprints = [];\r\n    let bpMap = new Map();\r\n    let recipesByTypeID = new Map();\r\n    let itemMap = new Map();\r\n    let producedBy = new Map();\r\n    let materialUsages = new Map();\r\n    let allMaterials = new Map();\r\n    let itemIcons = new Map();\r\n    let sortAsc = true;\r\n    let showOnlyRaw = false;\r\n    let activeTypeID = null;\r\n\r\n    async function load() {\r\n      try {\r\n        els.status.textContent = 'Fetching data\u2026';\r\n        const res = await fetch(JSON_URL, {mode:'cors'});\r\n        if (!res.ok) throw new Error(`HTTP ${res.status}`);\r\n        const data = await res.json();\r\n        if (!data || !Array.isArray(data.blueprints)) throw new Error('Invalid JSON');\r\n        blueprints = data.blueprints;\r\n\r\n        blueprints.forEach((bp, idx) => {\r\n          bp._recipeKey = `${bp.typeID}_${idx}`;\r\n          bpMap.set(bp._recipeKey, bp);\r\n          if (!recipesByTypeID.has(bp.typeID)) recipesByTypeID.set(bp.typeID, []);\r\n          recipesByTypeID.get(bp.typeID).push(bp);\r\n        });\r\n\r\n        for (const bp of blueprints) {\r\n          const build = bp.build || {};\r\n          const act = build.activities?.manufacturing || {};\r\n          const products = act.products || (build.manufactures ? [build.manufactures] : []);\r\n          let iconFile = bp.iconID ? `${bp.iconID}.png` : (bp.graphicID ? `g${bp.graphicID}.png` : null);\r\n\r\n          if (iconFile && !itemIcons.has(bp.typeID)) itemIcons.set(bp.typeID, iconFile);\r\n\r\n          for (const p of products) {\r\n            if (p.name) itemMap.set(p.typeID, p.name);\r\n            if (!producedBy.has(p.typeID)) producedBy.set(p.typeID, []);\r\n            producedBy.get(p.typeID).push({recipeKey: bp._recipeKey, yield: p.quantity || 1, time: act.time || build.time || 0});\r\n\r\n            if (iconFile) {\r\n              const current = itemIcons.get(p.typeID);\r\n              const bpName = bp.name.toLowerCase();\r\n              const prodName = (p.name || \"\").toLowerCase();\r\n              const isGoodMatch = bpName.includes(prodName) || prodName.includes(bpName.replace(\" blueprint\", \"\"));\r\n              if (!current || isGoodMatch) itemIcons.set(p.typeID, iconFile);\r\n            }\r\n          }\r\n\r\n          const materials = act.materials || build.materials || [];\r\n          for (const m of materials) {\r\n            if (m.name) itemMap.set(m.typeID, m.name);\r\n          }\r\n        }\r\n\r\n        materialUsages.clear();\r\n        for (const bp of blueprints) {\r\n          const build = bp.build || {};\r\n          const act = build.activities?.manufacturing || {};\r\n          const mats = act.materials || build.materials || [];\r\n          const prods = act.products || (build.manufactures ? [build.manufactures] : []);\r\n          const time = act.time || build.time || 0;\r\n          for (const m of mats) {\r\n            if (!materialUsages.has(m.typeID)) materialUsages.set(m.typeID, []);\r\n            materialUsages.get(m.typeID).push({\r\n              recipeKey: bp._recipeKey,\r\n              bpName: bp.name || 'Unnamed Blueprint',\r\n              group: bp.group || 'Other',\r\n              inputQty: m.quantity || 1,\r\n              products: prods.map(p => ({ typeID: p.typeID, name: p.name || p.typeID, quantity: p.quantity || 1 })),\r\n              time: time\r\n            });\r\n          }\r\n        }\r\n\r\n        allMaterials.clear();\r\n        for (const [typeID, usages] of materialUsages.entries()) {\r\n          const name = itemMap.get(typeID) || `Item #${typeID}`;\r\n          const isRaw = !producedBy.has(typeID) || producedBy.get(typeID).length === 0;\r\n          allMaterials.set(typeID, { name, isRaw, usageCount: usages.length });\r\n        }\r\n\r\n        \/\/ MANUAL ICON FEEDER\r\n        const manualIconFeed = {\r\n          \"Catalytic Dust\": \"27004.png\", \"Eclipsite\": \"25395.png\", \"Feral Echo\": \"27012.png\",\r\n          \"Fine Old Crude Matter\": \"25786.png\", \"Fine Young Crude Matter\": \"25785.png\",\r\n          \"Fossilized Exotronics\": \"3335.png\", \"Gravionite\": \"25397.png\",\r\n          \"Luminalis\": \"25396.png\", \"Radiantium\": \"25398.png\",\r\n          \"Rough Old Crude Matter\": \"25786.png\", \"Rough Young Crude Matter\": \"25785.png\",\r\n          \"Stack Slice\": \"26204.png\"\r\n        };\r\n\r\n        for (const [typeID, meta] of allMaterials.entries()) {\r\n          const name = (meta.name || itemMap.get(typeID) || \"\").toLowerCase();\r\n          for (const [key, iconFile] of Object.entries(manualIconFeed)) {\r\n            const keyLower = key.toLowerCase();\r\n            const isMatch = name === keyLower || (keyLower.includes(\"stack slice\") && name.startsWith(\"stack slice\"));\r\n            if (isMatch && !itemIcons.has(typeID)) {\r\n              itemIcons.set(typeID, iconFile);\r\n              break;\r\n            }\r\n          }\r\n        }\r\n\r\n        els.matCount.textContent = allMaterials.size;\r\n        els.status.textContent = 'Ready';\r\n        renderMaterialList();\r\n        els.filterRawBtn.style.borderColor = '#1e2430';\r\n        els.filterRawBtn.style.color = 'var(--ink)';\r\n        showDashboard();\r\n      } catch (err) {\r\n        console.error(err);\r\n        els.status.innerHTML = `Could not load <span class=\"mono\">blueprints.json<\/span>`;\r\n        els.list.innerHTML = `<div style=\"padding:12px;color:#ff9a9a\">Error: ${err.message}<\/div>`;\r\n      }\r\n    }\r\n\r\n    function renderMaterialList() { \/* unchanged for brevity - same as previous version *\/ \r\n      \/\/ ... (keeping the same renderMaterialList function as last version)\r\n      const q = (els.search.value || '').trim().toLowerCase();\r\n      let filtered = Array.from(allMaterials.entries())\r\n        .filter(([typeID, meta]) => {\r\n          if (showOnlyRaw && !meta.isRaw) return false;\r\n          return meta.name.toLowerCase().includes(q) || String(typeID).includes(q);\r\n        })\r\n        .sort((a, b) => {\r\n          const A = a[1].name.toLowerCase();\r\n          const B = b[1].name.toLowerCase();\r\n          return sortAsc ? A.localeCompare(B) : B.localeCompare(A);\r\n        });\r\n\r\n      els.list.innerHTML = '';\r\n      if (filtered.length === 0) {\r\n        els.list.innerHTML = `<div style=\"padding:20px;color:#9aa4b2\">No materials found.<\/div>`;\r\n        return;\r\n      }\r\n\r\n      const section = document.createElement('div');\r\n      section.className = 'group';\r\n      section.dataset.open = 'true';\r\n\r\n      const title = document.createElement('button');\r\n      title.className = 'group-title';\r\n      title.innerHTML = `\r\n        <span class=\"left\">\r\n          <i class=\"fa fa-folder-open-o\"><\/i>\r\n          ${showOnlyRaw ? 'Raw Materials' : 'All Materials'}\r\n          <span class=\"count\">${filtered.length}<\/span>\r\n        <\/span>\r\n        <i class=\"fa fa-caret-down caret\"><\/i>\r\n      `;\r\n      title.addEventListener('click', () => {\r\n        section.dataset.open = section.dataset.open === 'true' ? 'false' : 'true';\r\n        title.querySelector('.left i').className = section.dataset.open === 'true' ? 'fa fa-folder-open-o' : 'fa fa-folder-o';\r\n      });\r\n\r\n      const itemsContainer = document.createElement('div');\r\n      itemsContainer.className = 'group-items';\r\n\r\n      for (const [typeID, meta] of filtered) {\r\n        const item = document.createElement('div');\r\n        item.className = 'item' + (typeID === activeTypeID ? ' active' : '');\r\n        item.dataset.typeId = typeID;\r\n        const iconHTML = getItemIconHTML(typeID);\r\n        item.innerHTML = `\r\n          ${iconHTML}\r\n          <div>\r\n            <div class=\"name\">${meta.name}<\/div>\r\n            <div class=\"chips\" style=\"margin-top:4px\">\r\n              ${meta.isRaw ? `<span class=\"badge raw\"><i class=\"fa fa-leaf\"><\/i> RAW<\/span>` : ''}\r\n              <span class=\"badge\"><i class=\"fa fa-link\"><\/i> ${meta.usageCount} bp${meta.usageCount === 1 ? '' : 's'}<\/span>\r\n            <\/div>\r\n          <\/div>\r\n          <div class=\"actions\"><span class=\"tag\">Explore<\/span><\/div>\r\n        `;\r\n        item.addEventListener('click', () => selectMaterial(typeID));\r\n        itemsContainer.appendChild(item);\r\n      }\r\n\r\n      section.appendChild(title);\r\n      section.appendChild(itemsContainer);\r\n      els.list.appendChild(section);\r\n    }\r\n\r\n    function showDashboard() { \/* same as previous *\/ \r\n      const total = allMaterials.size;\r\n      const rawCount = Array.from(allMaterials.values()).filter(m => m.isRaw).length;\r\n      els.detail.innerHTML = `\r\n        <div class=\"holo\">\r\n          <div class=\"icon-frame\">\r\n            <div class=\"bp-icon-large placeholder\" style=\"width:96px;height:96px;font-size:42px;\">\r\n              <i class=\"fa fa-sitemap\"><\/i>\r\n            <\/div>\r\n          <\/div>\r\n          <div class=\"title\">\r\n            <h2>Material Production Tree<\/h2>\r\n            <div class=\"sub\">Explore ${total} materials \u2022 ${rawCount} raw materials<\/div>\r\n            <div class=\"chips\">\r\n              <span class=\"badge\"><i class=\"fa fa-industry\"><\/i> Full Chains<\/span>\r\n              <span class=\"badge\"><i class=\"fa fa-link\"><\/i> Cycle Protected<\/span>\r\n            <\/div>\r\n          <\/div>\r\n          <div style=\"text-align:right\">\r\n            <button class=\"btn-mini\" id=\"randomRawBtn\"><i class=\"fa fa-random\"><\/i> Pick Random Raw<\/button>\r\n          <\/div>\r\n        <\/div>\r\n        <div style=\"margin-top:16px; padding:12px; background:#0f131b; border-radius:10px; font-size:13px; color:#9aa4b2;\">\r\n          <strong>How to use:<\/strong> Use the leaf button to filter to Raw Materials only if desired. Click any material to explore its full production chain.\r\n        <\/div>\r\n      `;\r\n      document.getElementById('randomRawBtn')?.addEventListener('click', () => {\r\n        const raws = Array.from(allMaterials.entries()).filter(([_,m]) => m.isRaw);\r\n        if (raws.length) {\r\n          const random = raws[Math.floor(Math.random()*raws.length)];\r\n          selectMaterial(random[0]);\r\n        }\r\n      });\r\n    }\r\n\r\n    function selectMaterial(typeID) {\r\n      activeTypeID = typeID;\r\n      const meta = allMaterials.get(typeID);\r\n      if (!meta) return;\r\n      const iconHTML = getItemIconHTML(typeID, 'large');\r\n      const isRaw = meta.isRaw;\r\n      const usages = materialUsages.get(typeID) || [];\r\n      els.detail.innerHTML = `\r\n        <div class=\"holo\">\r\n          <div class=\"icon-frame\">${iconHTML}<\/div>\r\n          <div class=\"title\">\r\n            <h2>${meta.name}<\/h2>\r\n            <div class=\"sub\">typeID: <span class=\"mono\">${typeID}<\/span> ${isRaw ? '\u2022 <span style=\"color:#00ffa8\">RAW MATERIAL<\/span>' : ''}<\/div>\r\n            <div class=\"chips\">\r\n              ${isRaw ? `<span class=\"badge raw\"><i class=\"fa fa-leaf\"><\/i> Raw Material<\/span>` : ''}\r\n              <span class=\"badge\"><i class=\"fa fa-link\"><\/i> Used in ${usages.length} blueprint${usages.length===1?'':'s'}<\/span>\r\n            <\/div>\r\n          <\/div>\r\n          <div style=\"display:flex; flex-direction:column; gap:6px; align-items:flex-end\">\r\n            <div class=\"tag\"><i class=\"fa fa-id-badge\"><\/i> typeID: <span class=\"mono\">${typeID}<\/span><\/div>\r\n          <\/div>\r\n        <\/div>\r\n      `;\r\n      els.treeWrap.style.display = 'block';\r\n      renderProductionTree(typeID);\r\n      document.querySelectorAll('#material-list .item').forEach(el => {\r\n        el.classList.toggle('active', el.dataset.typeId == typeID);\r\n      });\r\n    }\r\n\r\n    function renderProductionTree(rootTypeID) {\r\n      const container = els.materialTree;\r\n      container.innerHTML = '';\r\n      els.treeSummary.innerHTML = '';\r\n      const meta = allMaterials.get(rootTypeID);\r\n      if (!meta) return;\r\n\r\n      const root = document.createElement('div');\r\n      root.className = 'tree-root';\r\n      root.style.border = '2px solid #39d0ff';\r\n      root.style.background = 'rgba(57,208,255,.15)';\r\n\r\n      const rootIcon = getItemIconHTML(rootTypeID, 'small');\r\n\r\n      root.innerHTML = `\r\n        <div style=\"display:flex; align-items:center; gap:12px; flex-wrap:wrap;\">\r\n          ${rootIcon}\r\n          <div style=\"flex:1; min-width:0;\">\r\n            <strong>${meta.name}<\/strong>\r\n            <span class=\"faint\">(typeID ${rootTypeID})<\/span>\r\n            ${meta.isRaw ? '<span class=\"badge raw\" style=\"margin-left:8px\">RAW<\/span>' : ''}\r\n          <\/div>\r\n          <button class=\"btn-mini\" id=\"visual-tree-btn\" style=\"margin-left:auto; white-space:nowrap;\">\r\n            <i class=\"fa fa-sitemap\"><\/i> Visual Tree\r\n          <\/button>\r\n        <\/div>\r\n      `;\r\n      container.appendChild(root);\r\n\r\n      setTimeout(() => {\r\n        const visualBtn = document.getElementById('visual-tree-btn');\r\n        if (visualBtn) visualBtn.onclick = () => showVisualTreeModal(rootTypeID);\r\n      }, 50);\r\n\r\n      \/\/ ... rest of renderUsages logic (same as last working version)\r\n      let totalBps = 0;\r\n      let maxDepthReached = 0;\r\n\r\n      function renderUsages(matTypeID, parentEl, depth = 0, path = new Set()) {\r\n        if (depth > 7) { \/* truncated note *\/ return; }\r\n        if (path.has(matTypeID)) { \/* cycle note *\/ return; }\r\n        path.add(matTypeID);\r\n\r\n        const usages = materialUsages.get(matTypeID) || [];\r\n        totalBps += usages.length;\r\n        if (depth > maxDepthReached) maxDepthReached = depth;\r\n\r\n        if (usages.length === 0) {\r\n          const leaf = document.createElement('div');\r\n          leaf.style.marginLeft = `${depth * 18}px`;\r\n          leaf.className = 'tree-leaf faint';\r\n          leaf.textContent = 'No further production steps in Cycle 5 data.';\r\n          parentEl.appendChild(leaf);\r\n          path.delete(matTypeID);\r\n          return;\r\n        }\r\n\r\n        usages.forEach(usage => {\r\n          const node = document.createElement('div');\r\n          node.className = 'tree-node';\r\n          const header = document.createElement('div');\r\n          header.className = 'usage-header';\r\n          const prodText = usage.products.map(p => `${p.name}\u00d7${p.quantity}`).join(', ');\r\n\r\n          header.innerHTML = `\r\n            <div>\r\n              <div style=\"display:flex; align-items:center; gap:8px; flex-wrap:wrap;\">\r\n                <span style=\"flex:1 1 auto; min-width:0; font-weight:600;\">\r\n                  <i class=\"fa fa-industry\"><\/i> ${usage.bpName} <span class=\"faint\">(${usage.group})<\/span>\r\n                <\/span>\r\n              <\/div>\r\n              <div style=\"margin-top:4px; font-size:12.5px; color:#9aa4b2;\">\r\n                consumes ${usage.inputQty} \u2192 produces ${prodText}\r\n              <\/div>\r\n            <\/div>\r\n            <div style=\"display:flex; align-items:center; gap:8px; margin-left:auto; flex-shrink:0;\">\r\n              <span class=\"badge\"><i class=\"fa fa-clock-o\"><\/i> ${secsToHMS(usage.time)}<\/span>\r\n              <button class=\"btn-mini recipe-btn\" style=\"padding:5px 11px; font-size:11px;\">Recipe<\/button>\r\n              <i class=\"fa fa-caret-down caret\"><\/i>\r\n            <\/div>\r\n          `;\r\n\r\n          node.appendChild(header);\r\n          const sub = document.createElement('div');\r\n          sub.className = 'tree-sub';\r\n          node.appendChild(sub);\r\n\r\n          let rendered = false;\r\n\r\n          header.addEventListener('click', (e) => {\r\n            if (e.target.classList.contains('recipe-btn')) return;\r\n            const open = sub.style.display === 'block';\r\n            sub.style.display = open ? 'none' : 'block';\r\n            header.classList.toggle('open', !open);\r\n            if (!open && !rendered) {\r\n              usage.products.forEach(prod => {\r\n                if (!prod.typeID) return;\r\n                const isRoot = prod.typeID == rootTypeID;\r\n                const prodRow = document.createElement('div');\r\n                prodRow.style.cssText = `margin-left:8px; padding:5px 0; display:flex; align-items:center; gap:8px; flex-wrap:wrap; ${isRoot ? 'background:rgba(57,208,255,.12); padding:5px 8px; border-radius:6px;' : ''}`;\r\n                const iconHTML = getItemIconHTML(prod.typeID, 'small');\r\n                prodRow.innerHTML = `${iconHTML} <span style=\"font-size:13px;\"><span class=\"faint\">Output:<\/span> <strong>${prod.name}<\/strong> \u00d7${prod.quantity}<\/span> ${isRoot ? '<span class=\"badge raw\" style=\"margin-left:6px; font-size:10px;\">SELECTED<\/span>' : ''}`;\r\n                sub.appendChild(prodRow);\r\n                const next = document.createElement('div');\r\n                sub.appendChild(next);\r\n                renderUsages(prod.typeID, next, depth + 1, new Set(path));\r\n              });\r\n              rendered = true;\r\n            }\r\n          });\r\n\r\n          const recipeBtnEl = header.querySelector('.recipe-btn');\r\n          recipeBtnEl.addEventListener('click', (e) => {\r\n            e.stopImmediatePropagation();\r\n            \/\/ Recipe details logic (same as before)\r\n            let recipeDiv = node.querySelector('.recipe-details');\r\n            if (recipeDiv) { recipeDiv.style.display = recipeDiv.style.display === 'none' ? 'block' : 'none'; return; }\r\n            const bp = bpMap.get(usage.recipeKey);\r\n            const mats = (bp?.build?.activities?.manufacturing?.materials) || [];\r\n            recipeDiv = document.createElement('div');\r\n            recipeDiv.className = 'recipe-details';\r\n            recipeDiv.style.cssText = 'margin:8px 0 8px 8px; padding:10px 12px; background:#0a0c10; border:1px solid #2a3144; border-radius:8px; font-size:12.5px;';\r\n            let html = `<div style=\"font-weight:600; margin-bottom:6px; color:#39d0ff;\"><i class=\"fa fa-list\"><\/i> Full Recipe Requirements<\/div>`;\r\n            if (mats.length === 0) {\r\n              html += `<div class=\"faint\">No material list available.<\/div>`;\r\n            } else {\r\n              html += `<div style=\"display:grid; gap:5px;\">`;\r\n              mats.forEach(m => {\r\n                html += `<div style=\"display:flex; align-items:center; gap:8px;\">${getItemIconHTML(m.typeID,'small')} <span><strong>${m.name || m.typeID}<\/strong> \u00d7${m.quantity || 1}<\/span><\/div>`;\r\n              });\r\n              html += `<\/div>`;\r\n            }\r\n            recipeDiv.innerHTML = html;\r\n            node.appendChild(recipeDiv);\r\n          });\r\n\r\n          parentEl.appendChild(node);\r\n        });\r\n        path.delete(matTypeID);\r\n      }\r\n\r\n      const firstLevel = document.createElement('div');\r\n      container.appendChild(firstLevel);\r\n      renderUsages(rootTypeID, firstLevel, 0, new Set());\r\n\r\n      els.treeSummary.innerHTML = `<strong>Chain summary:<\/strong> ${totalBps} blueprint steps \u2022 max depth: ${maxDepthReached}`;\r\n    }\r\n\r\n    \/\/ === FIXED VISUAL TREE POPUP ===\r\n    function showVisualTreeModal(rootTypeID) {\r\n      const modal = document.getElementById('visual-tree-modal');\r\n      const body = document.getElementById('visual-tree-body');\r\n      const titleEl = document.getElementById('visual-tree-title');\r\n\r\n      const meta = allMaterials.get(rootTypeID);\r\n      if (!meta) return;\r\n\r\n      titleEl.innerHTML = `<i class=\"fa fa-sitemap\"><\/i> Visual Production Tree \u2014 ${meta.name}`;\r\n      body.innerHTML = '';\r\n\r\n      const treeData = collectTreeData(rootTypeID);\r\n\r\n      function renderVisualNode(nodeData, container, isRoot = false) {\r\n        if (!nodeData) return;\r\n\r\n        const nodeEl = document.createElement('div');\r\n        nodeEl.className = `visual-node ${isRoot ? 'root' : ''}`;\r\n\r\n        const iconHTML = getItemIconHTML(nodeData.typeID, 'small');\r\n\r\n        nodeEl.innerHTML = `\r\n          <div class=\"icon\">${iconHTML}<\/div>\r\n          <div class=\"info\">\r\n            <div class=\"name\">${nodeData.name}<\/div>\r\n            <div class=\"meta\">\r\n              typeID: ${nodeData.typeID} \r\n              ${nodeData.isRaw ? '\u2022 <span style=\"color:#00ffa8\">RAW<\/span>' : ''}\r\n              ${nodeData.depth > 0 ? `\u2022 Depth ${nodeData.depth}` : ''}\r\n            <\/div>\r\n          <\/div>\r\n        `;\r\n        container.appendChild(nodeEl);\r\n\r\n        if (nodeData.usages && nodeData.usages.length > 0) {\r\n          const childrenContainer = document.createElement('div');\r\n          childrenContainer.className = 'visual-children';\r\n\r\n          nodeData.usages.forEach(usage => {\r\n            usage.products.forEach(prod => {\r\n              if (prod.typeID) {\r\n                const childData = collectTreeData(prod.typeID, nodeData.depth + 1);\r\n                if (childData) {\r\n                  renderVisualNode(childData, childrenContainer);\r\n                }\r\n              }\r\n            });\r\n          });\r\n\r\n          if (childrenContainer.children.length > 0) {\r\n            container.appendChild(childrenContainer);\r\n          }\r\n        }\r\n      }\r\n\r\n      renderVisualNode(treeData, body, true);\r\n      modal.classList.add('show');\r\n    }\r\n\r\n    \/\/ IMPROVED collectTreeData - now checks itemMap as fallback\r\n    function collectTreeData(typeID, depth = 0, path = new Set()) {\r\n      if (path.has(typeID) || depth > 7) return null;\r\n      path.add(typeID);\r\n\r\n      const meta = allMaterials.get(typeID);\r\n      const nameFromMap = itemMap.get(typeID);\r\n      const name = meta?.name || nameFromMap || `Item #${typeID}`;\r\n\r\n      const usages = materialUsages.get(typeID) || [];\r\n      const node = {\r\n        typeID,\r\n        name: name,\r\n        isRaw: meta?.isRaw || false,\r\n        depth,\r\n        usages: []\r\n      };\r\n\r\n      for (const usage of usages) {\r\n        const usageNode = {\r\n          blueprint: usage.bpName,\r\n          group: usage.group,\r\n          inputQty: usage.inputQty,\r\n          time: usage.time,\r\n          products: usage.products,\r\n          children: []\r\n        };\r\n        for (const prod of usage.products) {\r\n          if (prod.typeID) {\r\n            const child = collectTreeData(prod.typeID, depth + 1, new Set(path));\r\n            if (child) usageNode.children.push(child);\r\n          }\r\n        }\r\n        node.usages.push(usageNode);\r\n      }\r\n      path.delete(typeID);\r\n      return node;\r\n    }\r\n\r\n    \/\/ Export functions (unchanged)\r\n    function exportAsJSON(rootTypeID) { \/* same as before *\/ }\r\n    function exportAsCSV(rootTypeID) { \/* same as before *\/ }\r\n    function showToast(msg) {\r\n      const t = document.getElementById('toast');\r\n      t.textContent = msg;\r\n      t.className = 'show';\r\n      setTimeout(() => t.className = '', 2400);\r\n    }\r\n\r\n    \/\/ Event listeners\r\n    els.search.addEventListener('input', renderMaterialList);\r\n    els.sortBtn.addEventListener('click', () => {\r\n      sortAsc = !sortAsc;\r\n      els.sortBtn.innerHTML = sortAsc ? '<i class=\"fa fa-sort-alpha-asc\"><\/i>' : '<i class=\"fa fa-sort-alpha-desc\"><\/i>';\r\n      renderMaterialList();\r\n    });\r\n    els.filterRawBtn.addEventListener('click', () => {\r\n      showOnlyRaw = !showOnlyRaw;\r\n      els.filterRawBtn.style.borderColor = showOnlyRaw ? '#00ffa8' : '#1e2430';\r\n      els.filterRawBtn.style.color = showOnlyRaw ? '#00ffa8' : 'var(--ink)';\r\n      renderMaterialList();\r\n    });\r\n\r\n    load();\r\n  })();\r\n  <\/script>\r\n<\/div>\r\n","protected":false},"excerpt":{"rendered":"<p>Trace every industrial chain in EVE Frontier Cycle 5. Start from any material and see the complete recursive tree of everything that material can help you build \u2014 blueprints, components, ships, and end-game items. Material Production Tree Select any material on the left to see the full recursive chain of what it can make. Recursive [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":228,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[],"class_list":["post-224","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tools"],"yoast_head":"<!-- Meta Tags -->\r\n<title>EVE Frontier Materials Production Tree<\/title>\r\n<meta name=\"description\" content=\"Trace every industrial chain in EVE Frontier Cycle 5. Start from any material and see the complete recursive tree of everything that material can help you\" \/>\r\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\r\n<link rel=\"canonical\" href=\"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/materials-production-tree\/\" \/>\r\n<meta property=\"og:locale\" content=\"en_US\" \/>\r\n<meta property=\"og:type\" content=\"article\" \/>\r\n<meta property=\"og:title\" content=\"EVE Frontier Materials Production Tree\" \/>\r\n<meta property=\"og:description\" content=\"Trace every industrial chain in EVE Frontier Cycle 5. Start from any material and see the complete recursive tree of everything that material can help you\" \/>\r\n<meta property=\"og:url\" content=\"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/materials-production-tree\/\" \/>\r\n<meta property=\"og:site_name\" content=\"EVE Frontier\" \/>\r\n<meta property=\"article:publisher\" content=\"facebook.com\/gamingwithdaopa\/\" \/>\r\n<meta property=\"article:author\" content=\"facebook.com\/gamingwithdaopa\/\" \/>\r\n<meta property=\"article:published_time\" content=\"2026-06-04T03:04:48+00:00\" \/>\r\n<meta property=\"article:modified_time\" content=\"2026-06-05T01:56:49+00:00\" \/>\r\n<meta property=\"og:image\" content=\"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/wp-content\/uploads\/sites\/40\/2026\/06\/eve-frontier-materials-production-tree.jpg\" \/>\r\n\t<meta property=\"og:image:width\" content=\"400\" \/>\r\n\t<meta property=\"og:image:height\" content=\"263\" \/>\r\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\r\n<meta name=\"author\" content=\"daopa\" \/>\r\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\r\n<meta name=\"twitter:creator\" content=\"@gamingwithdaopa\" \/>\r\n<meta name=\"twitter:site\" content=\"@gamingwithdaopa\" \/>\r\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"daopa\" \/>\r\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/materials-production-tree\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/materials-production-tree\/\"},\"author\":{\"name\":\"daopa\",\"@id\":\"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/#\/schema\/person\/fb03a927907d90f409fac550ba375638\"},\"headline\":\"EVE Frontier Materials Production Tree\",\"datePublished\":\"2026-06-04T03:04:48+00:00\",\"dateModified\":\"2026-06-05T01:56:49+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/materials-production-tree\/\"},\"wordCount\":82,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/#\/schema\/person\/fb03a927907d90f409fac550ba375638\"},\"image\":{\"@id\":\"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/materials-production-tree\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/wp-content\/uploads\/sites\/40\/2026\/06\/eve-frontier-materials-production-tree.jpg\",\"articleSection\":[\"Tools\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/materials-production-tree\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/materials-production-tree\/\",\"url\":\"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/materials-production-tree\/\",\"name\":\"EVE Frontier Materials Production Tree\",\"isPartOf\":{\"@id\":\"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/materials-production-tree\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/materials-production-tree\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/wp-content\/uploads\/sites\/40\/2026\/06\/eve-frontier-materials-production-tree.jpg\",\"datePublished\":\"2026-06-04T03:04:48+00:00\",\"dateModified\":\"2026-06-05T01:56:49+00:00\",\"description\":\"Trace every industrial chain in EVE Frontier Cycle 5. Start from any material and see the complete recursive tree of everything that material can help you\",\"breadcrumb\":{\"@id\":\"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/materials-production-tree\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/materials-production-tree\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/materials-production-tree\/#primaryimage\",\"url\":\"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/wp-content\/uploads\/sites\/40\/2026\/06\/eve-frontier-materials-production-tree.jpg\",\"contentUrl\":\"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/wp-content\/uploads\/sites\/40\/2026\/06\/eve-frontier-materials-production-tree.jpg\",\"width\":400,\"height\":263,\"caption\":\"eve frontier materials production tree\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/materials-production-tree\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"EVE Frontier Materials Production Tree\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/#website\",\"url\":\"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/\",\"name\":\"EVE Frontier\",\"description\":\"DaOpa&#039;s EVE Frontier Fansite - Guides, tools, databases, and lists to empower the EVE Frontier community in exploring the stars.\",\"publisher\":{\"@id\":\"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/#\/schema\/person\/fb03a927907d90f409fac550ba375638\"},\"alternateName\":\"evefrontier\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/#\/schema\/person\/fb03a927907d90f409fac550ba375638\",\"name\":\"daopa\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/wp-content\/uploads\/sites\/40\/2025\/08\/90-90-Logo.png\",\"contentUrl\":\"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/wp-content\/uploads\/sites\/40\/2025\/08\/90-90-Logo.png\",\"width\":90,\"height\":90,\"caption\":\"daopa\"},\"logo\":{\"@id\":\"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/#\/schema\/person\/image\/\"},\"description\":\"DaOpa has been variety streamer since 2009 with game focuses on primarily MMOs, Sandbox, RPG and FPS genres. For inquires comment in the comments sections. This channel is syndicated across various micro niche gaming related blogs operated by DaOpa. He creates fansites, guides, tools for gamers\",\"sameAs\":[\"https:\/\/gamingwithdaopa.ellatha.com\",\"facebook.com\/gamingwithdaopa\/\",\"https:\/\/x.com\/gamingwithdaopa\",\"youtube.com\/@daopa\"],\"url\":\"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/author\/daopa\/\"}]}<\/script>","yoast_head_json":{"title":"EVE Frontier Materials Production Tree","description":"Trace every industrial chain in EVE Frontier Cycle 5. Start from any material and see the complete recursive tree of everything that material can help you","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/materials-production-tree\/","og_locale":"en_US","og_type":"article","og_title":"EVE Frontier Materials Production Tree","og_description":"Trace every industrial chain in EVE Frontier Cycle 5. Start from any material and see the complete recursive tree of everything that material can help you","og_url":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/materials-production-tree\/","og_site_name":"EVE Frontier","article_publisher":"facebook.com\/gamingwithdaopa\/","article_author":"facebook.com\/gamingwithdaopa\/","article_published_time":"2026-06-04T03:04:48+00:00","article_modified_time":"2026-06-05T01:56:49+00:00","og_image":[{"width":400,"height":263,"url":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/wp-content\/uploads\/sites\/40\/2026\/06\/eve-frontier-materials-production-tree.jpg","type":"image\/jpeg"}],"author":"daopa","twitter_card":"summary_large_image","twitter_creator":"@gamingwithdaopa","twitter_site":"@gamingwithdaopa","twitter_misc":{"Written by":"daopa"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/materials-production-tree\/#article","isPartOf":{"@id":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/materials-production-tree\/"},"author":{"name":"daopa","@id":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/#\/schema\/person\/fb03a927907d90f409fac550ba375638"},"headline":"EVE Frontier Materials Production Tree","datePublished":"2026-06-04T03:04:48+00:00","dateModified":"2026-06-05T01:56:49+00:00","mainEntityOfPage":{"@id":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/materials-production-tree\/"},"wordCount":82,"commentCount":0,"publisher":{"@id":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/#\/schema\/person\/fb03a927907d90f409fac550ba375638"},"image":{"@id":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/materials-production-tree\/#primaryimage"},"thumbnailUrl":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/wp-content\/uploads\/sites\/40\/2026\/06\/eve-frontier-materials-production-tree.jpg","articleSection":["Tools"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/materials-production-tree\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/materials-production-tree\/","url":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/materials-production-tree\/","name":"EVE Frontier Materials Production Tree","isPartOf":{"@id":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/#website"},"primaryImageOfPage":{"@id":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/materials-production-tree\/#primaryimage"},"image":{"@id":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/materials-production-tree\/#primaryimage"},"thumbnailUrl":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/wp-content\/uploads\/sites\/40\/2026\/06\/eve-frontier-materials-production-tree.jpg","datePublished":"2026-06-04T03:04:48+00:00","dateModified":"2026-06-05T01:56:49+00:00","description":"Trace every industrial chain in EVE Frontier Cycle 5. Start from any material and see the complete recursive tree of everything that material can help you","breadcrumb":{"@id":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/materials-production-tree\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/materials-production-tree\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/materials-production-tree\/#primaryimage","url":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/wp-content\/uploads\/sites\/40\/2026\/06\/eve-frontier-materials-production-tree.jpg","contentUrl":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/wp-content\/uploads\/sites\/40\/2026\/06\/eve-frontier-materials-production-tree.jpg","width":400,"height":263,"caption":"eve frontier materials production tree"},{"@type":"BreadcrumbList","@id":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/materials-production-tree\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/"},{"@type":"ListItem","position":2,"name":"EVE Frontier Materials Production Tree"}]},{"@type":"WebSite","@id":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/#website","url":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/","name":"EVE Frontier","description":"DaOpa&#039;s EVE Frontier Fansite - Guides, tools, databases, and lists to empower the EVE Frontier community in exploring the stars.","publisher":{"@id":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/#\/schema\/person\/fb03a927907d90f409fac550ba375638"},"alternateName":"evefrontier","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/#\/schema\/person\/fb03a927907d90f409fac550ba375638","name":"daopa","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/#\/schema\/person\/image\/","url":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/wp-content\/uploads\/sites\/40\/2025\/08\/90-90-Logo.png","contentUrl":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/wp-content\/uploads\/sites\/40\/2025\/08\/90-90-Logo.png","width":90,"height":90,"caption":"daopa"},"logo":{"@id":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/#\/schema\/person\/image\/"},"description":"DaOpa has been variety streamer since 2009 with game focuses on primarily MMOs, Sandbox, RPG and FPS genres. For inquires comment in the comments sections. This channel is syndicated across various micro niche gaming related blogs operated by DaOpa. He creates fansites, guides, tools for gamers","sameAs":["https:\/\/gamingwithdaopa.ellatha.com","facebook.com\/gamingwithdaopa\/","https:\/\/x.com\/gamingwithdaopa","youtube.com\/@daopa"],"url":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/author\/daopa\/"}]}},"_links":{"self":[{"href":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/wp-json\/wp\/v2\/posts\/224","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/wp-json\/wp\/v2\/comments?post=224"}],"version-history":[{"count":4,"href":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/wp-json\/wp\/v2\/posts\/224\/revisions"}],"predecessor-version":[{"id":264,"href":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/wp-json\/wp\/v2\/posts\/224\/revisions\/264"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/wp-json\/wp\/v2\/media\/228"}],"wp:attachment":[{"href":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/wp-json\/wp\/v2\/media?parent=224"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/wp-json\/wp\/v2\/categories?post=224"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/gamingwithdaopa.ellatha.com\/evefrontier\/wp-json\/wp\/v2\/tags?post=224"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}