OOKNET                             [ /  search the index  ]  
──────────────────────────────────────────────────────────────────────────────────────
══════════════════════════════════════════════════════════════════════════════════════
OOKNET   [ /  search  ]  
────────────────────────────────────────────────
════════════════════════════════════════════════
 
HASH      6a7d77a78083
DATE      2025-07-27
SUBJECT   web: loadout ui draft
FILES     2 CHANGED
HASH      6a7d77a78083
DATE      2025-07-27
SUBJECT   web: loadout ui draft
FILES     2 CHANGED
 

diff --git a/web/src/components/ItemDatabase.astro b/web/src/components/ItemDataba
se.astro
index 27c8110..37de99f 100644
--- a/web/src/components/ItemDatabase.astro
+++ b/web/src/components/ItemDatabase.astro
@@ -93,49 +93,76 @@ window.ItemDatabase = {
     return `https://www.wowhead.com/mop-classic/item=${itemId}`;
   },
 
-  // Format equipment item with all details
+  // Format equipment item with all details - uses enriched data from backend
   formatEquipmentItem: (item) => {
     if (!item || !item.id) return null;
     
-    const itemName = `Item ${item.id}`; // TODO: Replace with actual item names
+    // Use enriched name if available, otherwise fallback to ID
+    const itemName = item.name || `Item ${item.id}`;
     const wowheadUrl = window.ItemDatabase.getWowheadUrl(item.id);
+    const iconUrl = item.icon ? `https://wow.zamimg.com/images/wow/icons/large/${
item.icon}.jpg` : null;
     
-    // Build details array
+    // Build details array from enriched data
     const details = [];
     
-    // Reforging
-    if (item.reforging) {
+    // Item stats from scalingOptions
+    if (item.stats) {
+      const stats = [];
+      if (item.stats.ilvl) stats.push(`Item Level: ${item.stats.ilvl}`);
+      if (item.stats.weaponDamageMin && item.stats.weaponDamageMax) {
+        stats.push(`Damage: ${item.stats.weaponDamageMin}-${item.stats.weaponDama
geMax}`);
+      }
+      if (stats.length > 0) details.push(...stats);
+    }
+    
+    // Enriched reforging information
+    if (item.reforging && item.reforging.description) {
+      details.push(`Reforge: ${item.reforging.description}`);
+    } else if (item.reforging && typeof item.reforging === 'number') {
+      // Fallback to manual reforge lookup if not enriched
       const reforge = reforgeData[item.reforging.toString()];
       if (reforge) {
         const fromStat = statNames[reforge.s1] || reforge.s1;
         const toStat = statNames[reforge.s2] || reforge.s2;
-        details.push(`${fromStat} ? ${toStat}`);
+        details.push(`Reforge: ${fromStat} ? ${toStat}`);
       }
     }
     
-    // Gems
+    // Enriched gems information
     if (item.gems && item.gems.length > 0) {
-      const activeGems = item.gems.filter(g => g && g !== 0);
-      activeGems.forEach(gemId => {
-        details.push(`Gem ${gemId}`); // TODO: Replace with actual gem names and 
stats
+      item.gems.forEach(gem => {
+        if (gem && gem.description) {
+          // Use enriched gem description (includes name and stats)
+          details.push(gem.description);
+        } else if (gem && gem.name) {
+          // Use enriched gem name if available
+          details.push(gem.name);
+        } else if (gem && typeof gem === 'number') {
+          // Fallback for non-enriched gem IDs
+          details.push(`Gem ${gem}`);
+        }
       });
     }
     
-    // Enchant
-    if (item.enchant) {
-      details.push(`Enchant ${item.enchant}`); // TODO: Replace with actual encha
nt names
+    // Enriched enchant information
+    if (item.enchant && item.enchant.name) {
+      details.push(`Enchant: ${item.enchant.name}`);
+    } else if (item.enchant && typeof item.enchant === 'number') {
+      details.push(`Enchant ${item.enchant}`);
     }
     
-    // Tinker
+    // Tinker (not enriched yet, but prepared for future)
     if (item.tinker) {
-      details.push(`Tinker ${item.tinker}`); // TODO: Replace with actual tinker 
names
+      details.push(`Tinker ${item.tinker}`);
     }
     
     return {
       itemId: item.id,
       itemName: itemName,
       itemDetails: details,
-      wowheadUrl: wowheadUrl
+      wowheadUrl: wowheadUrl,
+      iconUrl: iconUrl,
+      quality: item.quality || null
     };
   },
 

diff --git a/web/src/components/ItemDatabase
.astro b/web/src/components/ItemDatabase.ast
ro
index 27c8110..37de99f 100644
--- a/web/src/components/ItemDatabase.astro
+++ b/web/src/components/ItemDatabase.astro
@@ -93,49 +93,76 @@ window.ItemDatabase = {
     return `https://www.wowhead.com/mop-cla
ssic/item=${itemId}`;
   },
 
-  // Format equipment item with all details
+  // Format equipment item with all details
 - uses enriched data from backend
   formatEquipmentItem: (item) => {
     if (!item || !item.id) return null;
     
-    const itemName = `Item ${item.id}`; // 
TODO: Replace with actual item names
+    // Use enriched name if available, othe
rwise fallback to ID
+    const itemName = item.name || `Item ${i
tem.id}`;
     const wowheadUrl = window.ItemDatabase.
getWowheadUrl(item.id);
+    const iconUrl = item.icon ? `https://wo
w.zamimg.com/images/wow/icons/large/${item.i
con}.jpg` : null;
     
-    // Build details array
+    // Build details array from enriched da
ta
     const details = [];
     
-    // Reforging
-    if (item.reforging) {
+    // Item stats from scalingOptions
+    if (item.stats) {
+      const stats = [];
+      if (item.stats.ilvl) stats.push(`Item
 Level: ${item.stats.ilvl}`);
+      if (item.stats.weaponDamageMin && ite
m.stats.weaponDamageMax) {
+        stats.push(`Damage: ${item.stats.we
aponDamageMin}-${item.stats.weaponDamageMax}
`);
+      }
+      if (stats.length > 0) details.push(..
.stats);
+    }
+    
+    // Enriched reforging information
+    if (item.reforging && item.reforging.de
scription) {
+      details.push(`Reforge: ${item.reforgi
ng.description}`);
+    } else if (item.reforging && typeof ite
m.reforging === 'number') {
+      // Fallback to manual reforge lookup 
if not enriched
       const reforge = reforgeData[item.refo
rging.toString()];
       if (reforge) {
         const fromStat = statNames[reforge.
s1] || reforge.s1;
         const toStat = statNames[reforge.s2
] || reforge.s2;
-        details.push(`${fromStat} ? ${toSta
t}`);
+        details.push(`Reforge: ${fromStat} 
? ${toStat}`);
       }
     }
     
-    // Gems
+    // Enriched gems information
     if (item.gems && item.gems.length > 0) 
{
-      const activeGems = item.gems.filter(g
 => g && g !== 0);
-      activeGems.forEach(gemId => {
-        details.push(`Gem ${gemId}`); // TO
DO: Replace with actual gem names and stats
+      item.gems.forEach(gem => {
+        if (gem && gem.description) {
+          // Use enriched gem description (
includes name and stats)
+          details.push(gem.description);
+        } else if (gem && gem.name) {
+          // Use enriched gem name if avail
able
+          details.push(gem.name);
+        } else if (gem && typeof gem === 'n
umber') {
+          // Fallback for non-enriched gem 
IDs
+          details.push(`Gem ${gem}`);
+        }
       });
     }
     
-    // Enchant
-    if (item.enchant) {
-      details.push(`Enchant ${item.enchant}
`); // TODO: Replace with actual enchant nam
es
+    // Enriched enchant information
+    if (item.enchant && item.enchant.name) 
{
+      details.push(`Enchant: ${item.enchant
.name}`);
+    } else if (item.enchant && typeof item.
enchant === 'number') {
+      details.push(`Enchant ${item.enchant}
`);
     }
     
-    // Tinker
+    // Tinker (not enriched yet, but prepar
ed for future)
     if (item.tinker) {
-      details.push(`Tinker ${item.tinker}`)
; // TODO: Replace with actual tinker names
+      details.push(`Tinker ${item.tinker}`)
;
     }
     
     return {
       itemId: item.id,
       itemName: itemName,
       itemDetails: details,
-      wowheadUrl: wowheadUrl
+      wowheadUrl: wowheadUrl,
+      iconUrl: iconUrl,
+      quality: item.quality || null
     };
   },
 
 

diff --git a/web/src/layouts/ChartLayout.astro b/web/src/layouts/ChartLayout.astro
index 4c148bf..4164ef0 100644
--- a/web/src/layouts/ChartLayout.astro
+++ b/web/src/layouts/ChartLayout.astro
@@ -498,6 +498,91 @@ const isFixedClassSpec = fixedClass && fixedSpec;
         text-align: right;
         font-family: 'Courier New', monospace;
       }
+
+      /* Item icons and quality styles */
+      .equipment-icon,
+      .consumable-icon {
+        width: 24px;
+        height: 24px;
+        border-radius: 3px;
+        margin-right: 8px;
+        vertical-align: middle;
+        border: 1px solid rgba(255,255,255,0.2);
+      }
+
+      .equipment-item-header,
+      .consumable-item-header {
+        display: flex;
+        align-items: center;
+        gap: 8px;
+      }
+
+      /* WoW item quality colors */
+      .quality-0 { color: #9d9d9d; } /* Poor (Gray) */
+      .quality-1 { color: #ffffff; } /* Common (White) */
+      .quality-2 { color: #1eff00; } /* Uncommon (Green) */
+      .quality-3 { color: #0070dd; } /* Rare (Blue) */
+      .quality-4 { color: #a335ee; } /* Epic (Purple) */
+      .quality-5 { color: #ff8000; } /* Legendary (Orange) */
+      .quality-6 { color: #e6cc80; } /* Artifact (Light Orange) */
+      .quality-7 { color: #00ccff; } /* Heirloom (Light Blue) */
+
+      .equipment-item-link.quality-0,
+      .equipment-item-link.quality-1,
+      .equipment-item-link.quality-2,
+      .equipment-item-link.quality-3,
+      .equipment-item-link.quality-4,
+      .equipment-item-link.quality-5,
+      .equipment-item-link.quality-6,
+      .equipment-item-link.quality-7 {
+        text-decoration: none;
+        transition: all 0.2s ease;
+      }
+
+      .equipment-item-link.quality-0:hover,
+      .equipment-item-link.quality-1:hover,
+      .equipment-item-link.quality-2:hover,
+      .equipment-item-link.quality-3:hover,
+      .equipment-item-link.quality-4:hover,
+      .equipment-item-link.quality-5:hover,
+      .equipment-item-link.quality-6:hover,
+      .equipment-item-link.quality-7:hover {
+        text-shadow: 0 0 4px currentColor;
+        transform: translateY(-1px);
+      }
+
+      /* Glyph-specific styling */
+      .consumable-item-header img {
+        flex-shrink: 0;
+      }
+
+      /* Better spacing for talents and glyphs section */
+      .loadout-section .loadout-grid {
+        gap: 16px;
+      }
+
+      .loadout-section .loadout-item {
+        padding: 8px;
+        background-color: rgba(255,255,255,0.02);
+        border-radius: 4px;
+        border: 1px solid rgba(255,255,255,0.05);
+      }
+
+      /* Loadout notice styling */
+      .loadout-notice {
+        background-color: rgba(255, 193, 7, 0.1);
+        border: 1px solid rgba(255, 193, 7, 0.3);
+        border-radius: 4px;
+        padding: 12px;
+        margin-bottom: 16px;
+        color: #ffc107;
+        font-size: 0.9em;
+        line-height: 1.4;
+      }
+
+      .loadout-notice strong {
+        color: #ffca28;
+      }
     </style>
   </head>
   <body>
@@ -684,8 +769,11 @@ const formatLoadout = (loadout) => {
       items.push({ label: 'Talents', value: loadout.talentsString, isSpecial: 'ta
lents' });
     }
     if (loadout.glyphs) {
-      const glyphText = formatGlyphs(loadout.glyphs);
-      if (glyphText) items.push({ label: 'Glyphs', value: glyphText });
+      const glyphItems = formatGlyphs(loadout.glyphs);
+      if (glyphItems && glyphItems.length > 0) {
+        // Add glyphs as structured items instead of text
+        items.push(...glyphItems);
+      }
     }
     sections.push({ title: 'Talents & Glyphs', items });
   }
@@ -716,11 +804,32 @@ const formatClass = (className) => {
 };
 
 const formatGlyphs = (glyphs) => {
-  const glyphList = [];
+  const glyphItems = [];
   ['major1', 'major2', 'major3', 'minor1', 'minor2', 'minor3'].forEach(slot => {
-    if (glyphs[slot]) glyphList.push(`${slot}: ${glyphs[slot]}`);
+    if (glyphs[slot]) {
+      const glyphName = glyphs[`${slot}Name`] || `Glyph ${glyphs[slot]}`;
+      const iconUrl = glyphs[`${slot}Icon`] 
+        ? `https://wow.zamimg.com/images/wow/icons/large/${glyphs[`${slot}Icon`]}
.jpg`
+        : null;
+      const quality = glyphs[`${slot}Quality`];
+      const spellId = glyphs[`${slot}SpellId`];
+      
+      // Use spellId for wowhead link if available, otherwise fall back to item l
ookup
+      const wowheadUrl = spellId 
+        ? `https://www.wowhead.com/mop-classic/spell=${spellId}`
+        : `https://www.wowhead.com/mop-classic/item=${glyphs[slot]}`;
+      
+      glyphItems.push({
+        label: slot.charAt(0).toUpperCase() + slot.slice(1), // Capitalize slot n
ame
+        value: glyphName,
+        iconUrl: iconUrl,
+        quality: quality,
+        wowheadUrl: wowheadUrl,
+        isGlyph: true
+      });
+    }
   });
-  return glyphList.length > 0 ? glyphList.join(', ') : null;
+  return glyphItems;
 };
 
 const formatConsumables = (consumables) => {
@@ -728,32 +837,40 @@ const formatConsumables = (consumables) => {
   if (consumables.flaskId) {
     items.push({ 
       label: 'Flask', 
-      value: consumables.flaskId,
+      value: consumables.flaskName || `Item ${consumables.flaskId}`,
       wowheadUrl: `https://www.wowhead.com/mop-classic/item=${consumables.flaskId
}`,
+      iconUrl: consumables.flaskIcon ? `https://wow.zamimg.com/images/wow/icons/l
arge/${consumables.flaskIcon}.jpg` : null,
+      quality: consumables.flaskQuality,
       isItem: true
     });
   }
   if (consumables.foodId) {
     items.push({ 
       label: 'Food', 
-      value: consumables.foodId,
+      value: consumables.foodName || `Item ${consumables.foodId}`,
       wowheadUrl: `https://www.wowhead.com/mop-classic/item=${consumables.foodId}
`,
+      iconUrl: consumables.foodIcon ? `https://wow.zamimg.com/images/wow/icons/la
rge/${consumables.foodIcon}.jpg` : null,
+      quality: consumables.foodQuality,
       isItem: true
     });
   }
   if (consumables.potId) {
     items.push({ 
       label: 'Potion', 
-      value: consumables.potId,
+      value: consumables.potName || `Item ${consumables.potId}`,
       wowheadUrl: `https://www.wowhead.com/mop-classic/item=${consumables.potId}`
,
+      iconUrl: consumables.potIcon ? `https://wow.zamimg.com/images/wow/icons/lar
ge/${consumables.potIcon}.jpg` : null,
+      quality: consumables.potQuality,
       isItem: true
     });
   }
   if (consumables.prepotId) {
     items.push({ 
       label: 'Pre-Potion', 
-      value: consumables.prepotId,
+      value: consumables.prepotName || `Item ${consumables.prepotId}`,
       wowheadUrl: `https://www.wowhead.com/mop-classic/item=${consumables.prepotI
d}`,
+      iconUrl: consumables.prepotIcon ? `https://wow.zamimg.com/images/wow/icons/
large/${consumables.prepotIcon}.jpg` : null,
+      quality: consumables.prepotQuality,
       isItem: true
     });
   }
@@ -808,11 +925,20 @@ const generateLoadoutDropdown = (loadout, chartData) => {
           ? eq.itemDetails.map(detail => `<div class="equipment-detail">${detail}
</div>`).join('')
           : '';
         
+        const iconHtml = eq.iconUrl 
+          ? `<img src="${eq.iconUrl}" alt="${eq.itemName}" class="equipment-icon"
 loading="lazy" />`
+          : '';
+        
+        const qualityClass = eq.quality ? `quality-${eq.quality}` : '';
+        
         return `
           <div class="equipment-slot">
             <span class="equipment-slot-name">${eq.slot}:</span>
             <div class="equipment-item-info">
-              <a href="${eq.wowheadUrl}" target="_blank" class="equipment-item-li
nk">${eq.itemName}</a>
+              <div class="equipment-item-header">
+                ${iconHtml}
+                <a href="${eq.wowheadUrl}" target="_blank" class="equipment-item-
link ${qualityClass}">${eq.itemName}</a>
+              </div>
               ${detailsHtml}
             </div>
           </div>
@@ -831,9 +957,22 @@ const generateLoadoutDropdown = (loadout, chartData) => {
       // Regular sections
       const itemsHtml = section.items.map(item => {
         const valueClass = item.isSpecial === 'talents' ? 'loadout-value loadout-
talents' : 'loadout-value';
-        const valueContent = item.isItem && item.wowheadUrl 
-          ? `<a href="${item.wowheadUrl}" target="_blank" class="equipment-item-l
ink">Item ${item.value}</a>`
-          : `<span class="${valueClass}">${item.value}</span>`;
+        
+        let valueContent;
+        if ((item.isItem || item.isGlyph) && item.wowheadUrl) {
+          const iconHtml = item.iconUrl 
+            ? `<img src="${item.iconUrl}" alt="${item.value}" class="consumable-i
con" loading="lazy" />`
+            : '';
+          const qualityClass = item.quality ? `quality-${item.quality}` : '';
+          valueContent = `
+            <div class="consumable-item-header">
+              ${iconHtml}
+              <a href="${item.wowheadUrl}" target="_blank" class="equipment-item-
link ${qualityClass}">${item.value}</a>
+            </div>
+          `;
+        } else {
+          valueContent = `<span class="${valueClass}">${item.value}</span>`;
+        }
         
         return `
           <div class="loadout-item">
@@ -858,6 +997,9 @@ const generateLoadoutDropdown = (loadout, chartData) => {
   
   return `
     <div class="chart-dropdown">
+      <div class="loadout-notice">
+        <strong>Note:</strong> Loadout details are a work in progress. Some glyph
s may show as IDs instead of names.
+      </div>
       ${sectionsHtml}
       <div class="loadout-actions">
         <a href="${rawJsonUrl}" target="_blank" class="loadout-button">View Raw J
SON</a>
@@ -1333,7 +1475,7 @@ class UnifiedChart {
     for (const [className, classData] of Object.entries(this.currentData.results)
) {
       for (const [specName, specData] of Object.entries(classData)) {
         chartItems.push({
-          label: `${className.replace(/_/g, ' ')} ${specName}`,
+          label: specName,
           dps: specData.dps,
           max: specData.max,
           min: specData.min,
@@ -1379,7 +1521,7 @@ class UnifiedChart {
                 <div class="chart-labels">
                   <span class="chart-rank">#${index + 1}</span>
                   <span class="chart-label">${item.label}</span>
-                  ${item.loadout ? '<span class="chart-expand-indicator">?</span>
' : ''}
+                  ${item.loadout ? '<span class="chart-expand-icon">?</span>' : '
'}
                 </div>
                 <div class="chart-bar-container">
                   <div class="chart-bar-track">
@@ -1451,7 +1593,7 @@ class UnifiedChart {
                 <div class="chart-labels">
                   <span class="chart-rank">#${index + 1}</span>
                   <span class="chart-label">${item.label}</span>
-                  ${item.loadout ? '<span class="chart-expand-indicator">?</span>
' : ''}
+                  ${item.loadout ? '<span class="chart-expand-icon">?</span>' : '
'}
                 </div>
                 <div class="chart-bar-container">
                   <div class="chart-bar-track">

diff --git a/web/src/layouts/ChartLayout.ast
ro b/web/src/layouts/ChartLayout.astro
index 4c148bf..4164ef0 100644
--- a/web/src/layouts/ChartLayout.astro
+++ b/web/src/layouts/ChartLayout.astro
@@ -498,6 +498,91 @@ const isFixedClassSpec 
= fixedClass && fixedSpec;
         text-align: right;
         font-family: 'Courier New', monospa
ce;
       }
+
+      /* Item icons and quality styles */
+      .equipment-icon,
+      .consumable-icon {
+        width: 24px;
+        height: 24px;
+        border-radius: 3px;
+        margin-right: 8px;
+        vertical-align: middle;
+        border: 1px solid rgba(255,255,255,
0.2);
+      }
+
+      .equipment-item-header,
+      .consumable-item-header {
+        display: flex;
+        align-items: center;
+        gap: 8px;
+      }
+
+      /* WoW item quality colors */
+      .quality-0 { color: #9d9d9d; } /* Poo
r (Gray) */
+      .quality-1 { color: #ffffff; } /* Com
mon (White) */
+      .quality-2 { color: #1eff00; } /* Unc
ommon (Green) */
+      .quality-3 { color: #0070dd; } /* Rar
e (Blue) */
+      .quality-4 { color: #a335ee; } /* Epi
c (Purple) */
+      .quality-5 { color: #ff8000; } /* Leg
endary (Orange) */
+      .quality-6 { color: #e6cc80; } /* Art
ifact (Light Orange) */
+      .quality-7 { color: #00ccff; } /* Hei
rloom (Light Blue) */
+
+      .equipment-item-link.quality-0,
+      .equipment-item-link.quality-1,
+      .equipment-item-link.quality-2,
+      .equipment-item-link.quality-3,
+      .equipment-item-link.quality-4,
+      .equipment-item-link.quality-5,
+      .equipment-item-link.quality-6,
+      .equipment-item-link.quality-7 {
+        text-decoration: none;
+        transition: all 0.2s ease;
+      }
+
+      .equipment-item-link.quality-0:hover,
+      .equipment-item-link.quality-1:hover,
+      .equipment-item-link.quality-2:hover,
+      .equipment-item-link.quality-3:hover,
+      .equipment-item-link.quality-4:hover,
+      .equipment-item-link.quality-5:hover,
+      .equipment-item-link.quality-6:hover,
+      .equipment-item-link.quality-7:hover 
{
+        text-shadow: 0 0 4px currentColor;
+        transform: translateY(-1px);
+      }
+
+      /* Glyph-specific styling */
+      .consumable-item-header img {
+        flex-shrink: 0;
+      }
+
+      /* Better spacing for talents and gly
phs section */
+      .loadout-section .loadout-grid {
+        gap: 16px;
+      }
+
+      .loadout-section .loadout-item {
+        padding: 8px;
+        background-color: rgba(255,255,255,
0.02);
+        border-radius: 4px;
+        border: 1px solid rgba(255,255,255,
0.05);
+      }
+
+      /* Loadout notice styling */
+      .loadout-notice {
+        background-color: rgba(255, 193, 7,
 0.1);
+        border: 1px solid rgba(255, 193, 7,
 0.3);
+        border-radius: 4px;
+        padding: 12px;
+        margin-bottom: 16px;
+        color: #ffc107;
+        font-size: 0.9em;
+        line-height: 1.4;
+      }
+
+      .loadout-notice strong {
+        color: #ffca28;
+      }
     </style>
   </head>
   <body>
@@ -684,8 +769,11 @@ const formatLoadout = (
loadout) => {
       items.push({ label: 'Talents', value:
 loadout.talentsString, isSpecial: 'talents'
 });
     }
     if (loadout.glyphs) {
-      const glyphText = formatGlyphs(loadou
t.glyphs);
-      if (glyphText) items.push({ label: 'G
lyphs', value: glyphText });
+      const glyphItems = formatGlyphs(loado
ut.glyphs);
+      if (glyphItems && glyphItems.length >
 0) {
+        // Add glyphs as structured items i
nstead of text
+        items.push(...glyphItems);
+      }
     }
     sections.push({ title: 'Talents & Glyph
s', items });
   }
@@ -716,11 +804,32 @@ const formatClass = (c
lassName) => {
 };
 
 const formatGlyphs = (glyphs) => {
-  const glyphList = [];
+  const glyphItems = [];
   ['major1', 'major2', 'major3', 'minor1', 
'minor2', 'minor3'].forEach(slot => {
-    if (glyphs[slot]) glyphList.push(`${slo
t}: ${glyphs[slot]}`);
+    if (glyphs[slot]) {
+      const glyphName = glyphs[`${slot}Name
`] || `Glyph ${glyphs[slot]}`;
+      const iconUrl = glyphs[`${slot}Icon`]
 
+        ? `https://wow.zamimg.com/images/wo
w/icons/large/${glyphs[`${slot}Icon`]}.jpg`
+        : null;
+      const quality = glyphs[`${slot}Qualit
y`];
+      const spellId = glyphs[`${slot}SpellI
d`];
+      
+      // Use spellId for wowhead link if av
ailable, otherwise fall back to item lookup
+      const wowheadUrl = spellId 
+        ? `https://www.wowhead.com/mop-clas
sic/spell=${spellId}`
+        : `https://www.wowhead.com/mop-clas
sic/item=${glyphs[slot]}`;
+      
+      glyphItems.push({
+        label: slot.charAt(0).toUpperCase()
 + slot.slice(1), // Capitalize slot name
+        value: glyphName,
+        iconUrl: iconUrl,
+        quality: quality,
+        wowheadUrl: wowheadUrl,
+        isGlyph: true
+      });
+    }
   });
-  return glyphList.length > 0 ? glyphList.j
oin(', ') : null;
+  return glyphItems;
 };
 
 const formatConsumables = (consumables) => 
{
@@ -728,32 +837,40 @@ const formatConsumable
s = (consumables) => {
   if (consumables.flaskId) {
     items.push({ 
       label: 'Flask', 
-      value: consumables.flaskId,
+      value: consumables.flaskName || `Item
 ${consumables.flaskId}`,
       wowheadUrl: `https://www.wowhead.com/
mop-classic/item=${consumables.flaskId}`,
+      iconUrl: consumables.flaskIcon ? `htt
ps://wow.zamimg.com/images/wow/icons/large/$
{consumables.flaskIcon}.jpg` : null,
+      quality: consumables.flaskQuality,
       isItem: true
     });
   }
   if (consumables.foodId) {
     items.push({ 
       label: 'Food', 
-      value: consumables.foodId,
+      value: consumables.foodName || `Item 
${consumables.foodId}`,
       wowheadUrl: `https://www.wowhead.com/
mop-classic/item=${consumables.foodId}`,
+      iconUrl: consumables.foodIcon ? `http
s://wow.zamimg.com/images/wow/icons/large/${
consumables.foodIcon}.jpg` : null,
+      quality: consumables.foodQuality,
       isItem: true
     });
   }
   if (consumables.potId) {
     items.push({ 
       label: 'Potion', 
-      value: consumables.potId,
+      value: consumables.potName || `Item $
{consumables.potId}`,
       wowheadUrl: `https://www.wowhead.com/
mop-classic/item=${consumables.potId}`,
+      iconUrl: consumables.potIcon ? `https
://wow.zamimg.com/images/wow/icons/large/${c
onsumables.potIcon}.jpg` : null,
+      quality: consumables.potQuality,
       isItem: true
     });
   }
   if (consumables.prepotId) {
     items.push({ 
       label: 'Pre-Potion', 
-      value: consumables.prepotId,
+      value: consumables.prepotName || `Ite
m ${consumables.prepotId}`,
       wowheadUrl: `https://www.wowhead.com/
mop-classic/item=${consumables.prepotId}`,
+      iconUrl: consumables.prepotIcon ? `ht
tps://wow.zamimg.com/images/wow/icons/large/
${consumables.prepotIcon}.jpg` : null,
+      quality: consumables.prepotQuality,
       isItem: true
     });
   }
@@ -808,11 +925,20 @@ const generateLoadoutD
ropdown = (loadout, chartData) => {
           ? eq.itemDetails.map(detail => `<
div class="equipment-detail">${detail}</div>
`).join('')
           : '';
         
+        const iconHtml = eq.iconUrl 
+          ? `<img src="${eq.iconUrl}" alt="
${eq.itemName}" class="equipment-icon" loadi
ng="lazy" />`
+          : '';
+        
+        const qualityClass = eq.quality ? `
quality-${eq.quality}` : '';
+        
         return `
           <div class="equipment-slot">
             <span class="equipment-slot-nam
e">${eq.slot}:</span>
             <div class="equipment-item-info
">
-              <a href="${eq.wowheadUrl}" ta
rget="_blank" class="equipment-item-link">${
eq.itemName}</a>
+              <div class="equipment-item-he
ader">
+                ${iconHtml}
+                <a href="${eq.wowheadUrl}" 
target="_blank" class="equipment-item-link $
{qualityClass}">${eq.itemName}</a>
+              </div>
               ${detailsHtml}
             </div>
           </div>
@@ -831,9 +957,22 @@ const generateLoadoutDr
opdown = (loadout, chartData) => {
       // Regular sections
       const itemsHtml = section.items.map(i
tem => {
         const valueClass = item.isSpecial =
== 'talents' ? 'loadout-value loadout-talent
s' : 'loadout-value';
-        const valueContent = item.isItem &&
 item.wowheadUrl 
-          ? `<a href="${item.wowheadUrl}" t
arget="_blank" class="equipment-item-link">I
tem ${item.value}</a>`
-          : `<span class="${valueClass}">${
item.value}</span>`;
+        
+        let valueContent;
+        if ((item.isItem || item.isGlyph) &
& item.wowheadUrl) {
+          const iconHtml = item.iconUrl 
+            ? `<img src="${item.iconUrl}" a
lt="${item.value}" class="consumable-icon" l
oading="lazy" />`
+            : '';
+          const qualityClass = item.quality
 ? `quality-${item.quality}` : '';
+          valueContent = `
+            <div class="consumable-item-hea
der">
+              ${iconHtml}
+              <a href="${item.wowheadUrl}" 
target="_blank" class="equipment-item-link $
{qualityClass}">${item.value}</a>
+            </div>
+          `;
+        } else {
+          valueContent = `<span class="${va
lueClass}">${item.value}</span>`;
+        }
         
         return `
           <div class="loadout-item">
@@ -858,6 +997,9 @@ const generateLoadoutDro
pdown = (loadout, chartData) => {
   
   return `
     <div class="chart-dropdown">
+      <div class="loadout-notice">
+        <strong>Note:</strong> Loadout deta
ils are a work in progress. Some glyphs may 
show as IDs instead of names.
+      </div>
       ${sectionsHtml}
       <div class="loadout-actions">
         <a href="${rawJsonUrl}" target="_bl
ank" class="loadout-button">View Raw JSON</a
>
@@ -1333,7 +1475,7 @@ class UnifiedChart {
     for (const [className, classData] of Ob
ject.entries(this.currentData.results)) {
       for (const [specName, specData] of Ob
ject.entries(classData)) {
         chartItems.push({
-          label: `${className.replace(/_/g,
 ' ')} ${specName}`,
+          label: specName,
           dps: specData.dps,
           max: specData.max,
           min: specData.min,
@@ -1379,7 +1521,7 @@ class UnifiedChart {
                 <div class="chart-labels">
                   <span class="chart-rank">
#${index + 1}</span>
                   <span class="chart-label"
>${item.label}</span>
-                  ${item.loadout ? '<span c
lass="chart-expand-indicator">?</span>' : ''
}
+                  ${item.loadout ? '<span c
lass="chart-expand-icon">?</span>' : ''}
                 </div>
                 <div class="chart-bar-conta
iner">
                   <div class="chart-bar-tra
ck">
@@ -1451,7 +1593,7 @@ class UnifiedChart {
                 <div class="chart-labels">
                   <span class="chart-rank">
#${index + 1}</span>
                   <span class="chart-label"
>${item.label}</span>
-                  ${item.loadout ? '<span c
lass="chart-expand-indicator">?</span>' : ''
}
+                  ${item.loadout ? '<span c
lass="chart-expand-icon">?</span>' : ''}
                 </div>
                 <div class="chart-bar-conta
iner">
                   <div class="chart-bar-tra
ck">
 
[ BACK TO LOG ]
──────────────────────────────────────────────────────────────────────────────────────
OOKNET
────────────────────────────────────────────────
OOKNET