diff --git a/pages/projetos.md b/pages/projetos.md
index 4b81d290..436c57e2 100755
--- a/pages/projetos.md
+++ b/pages/projetos.md
@@ -462,6 +462,8 @@ document.addEventListener('DOMContentLoaded', () => {
function enrichCards(data) {
const mapDados = {};
+
+ // Mapeamento dos dados
data.forEach(item => {
const k1 = normalizarChaveJS(item.arquivo.replace('.wav','').replace('.mp3',''));
mapDados[k1] = item;
@@ -471,65 +473,83 @@ document.addEventListener('DOMContentLoaded', () => {
cards.forEach(card => {
const info = mapDados[normalizarChaveJS(card.dataset.title)];
- // Defaults
+ // --- 1. Definição de Valores Padrão (Safety First) ---
let genero = "Unknown";
let estrelas = 0;
let intensidade = -100;
let bpm = 0;
let tomHtml = "";
+ let tomRaw = "all"; // Valor padrão para o filtro
+ let subTagsHTML = ""; // Para os subgêneros
+ // --- 2. Só tenta extrair dados SE 'info' existir ---
if (info) {
- genero = info.analise_ia?.genero_macro || "Unknown";
- intensidade = parseFloat(info.analise_tecnica?.intensidade_db || -100);
- bpm = parseFloat(info.analise_tecnica?.bpm || 0);
- estrelas = Math.round(info.analise_tecnica?.complexidade?.estrelas || 0);
+ // Dados IA
+ if (info.analise_ia) {
+ genero = info.analise_ia.genero_macro || "Unknown";
+
+ // Lógica de Subgêneros (Top 2)
+ if (Array.isArray(info.analise_ia.nuvem_tags)) {
+ const topTags = info.analise_ia.nuvem_tags.slice(0, 2);
+ topTags.forEach(t => {
+ // Multiplica por 100 para porcentagem legível
+ const scorePercent = Math.round((t.score || 0) * 100);
+ subTagsHTML += `
+
+ #${t.tag}
+ `;
+ });
+ }
+ }
- // HTML do Tom
- if (info.analise_tecnica?.tom) {
- const t = info.analise_tecnica.tom;
- const e = info.analise_tecnica.escala === 'minor' ? 'm' : '';
- tomHtml = `🎹 ${t}${e}`;
+ // Dados Técnicos
+ if (info.analise_tecnica) {
+ intensidade = parseFloat(info.analise_tecnica.intensidade_db || -100);
+ bpm = parseFloat(info.analise_tecnica.bpm || 0);
+ // Correção: Usando Math.round para bater com o visual
+ estrelas = Math.round(info.analise_tecnica.complexidade?.estrelas || 0);
+
+ // Lógica do Tom (Visual + Filtro)
+ if (info.analise_tecnica.tom) {
+ const t = info.analise_tecnica.tom;
+ const e = info.analise_tecnica.escala === 'minor' ? 'm' : '';
+
+ // HTML visual (Badge)
+ tomHtml = `🎹 ${t}${e}`;
+
+ // Valor cru para o filtro (Ex: "C", "Cm", "Ab")
+ tomRaw = t + e;
+ }
}
}
- // Salva no dataset para filtros
+ // --- 3. Salva no Dataset para os Filtros ---
card.dataset.genre = genero;
card.dataset.stars = estrelas;
card.dataset.intensity = intensidade;
card.dataset.bpm_real = bpm;
- // Dentro do enrichCards, salve o tom 'cru' no dataset
- let tomRaw = "Unknown";
- if (info.analise_tecnica?.tom) {
- // Ex: "Ab"
- tomRaw = info.analise_tecnica.tom;
- // Se a escala for minor, adiciona 'm'. Ex: "Ab" + "m" -> "Abm"
- if (info.analise_tecnica.escala === 'minor') {
- tomRaw += 'm';
- }
- }
- card.dataset.key = tomRaw; // Salva no HTML: data-key="Ab" ou "Cm"
+ card.dataset.key = tomRaw; // Novo dataset para o filtro de Tom
- // Injeta HTML
+ // --- 4. Renderização no DOM ---
const bpmContainer = card.querySelector('.bpm-container');
if (bpmContainer) {
- // Limpa conteúdo anterior injetado via JS se houver (opcional)
- // bpmContainer.innerHTML = ''; // Cuidado se tiver o BPM original do Liquid aqui.
-
const iaDiv = document.createElement('div');
iaDiv.style.display = "flex";
iaDiv.style.flexDirection = "column";
iaDiv.style.alignItems = "center";
- iaDiv.style.gap = "6px"; // Aumentei um pouco o gap
- iaDiv.className = "mt-3"; // Margem topo para separar do título
+ iaDiv.style.gap = "6px";
+ iaDiv.className = "mt-3";
- // 1. Renderiza a Dificuldade (Nova função)
+ // Dificuldade
const diffDiv = document.createElement('div');
diffDiv.innerHTML = renderizarDificuldade(estrelas);
iaDiv.appendChild(diffDiv);
- // 2. Tags (Gênero + Tom)
+ // Tags (Gênero Macro + Tom)
const tagsRow = document.createElement('div');
- tagsRow.className = "tags is-centered mb-0";
+ tagsRow.className = "tags is-centered mb-1"; // mb-1 para dar espaço pros subgeneros
tagsRow.style.gap = "4px";
if(genero !== "Unknown") {
@@ -537,35 +557,24 @@ document.addEventListener('DOMContentLoaded', () => {
if(genero === 'Electronic') color = 'is-info';
if(genero === 'Hip Hop') color = 'is-warning';
if(genero === 'Rock') color = 'is-danger';
- let subTagsHTML = "";
- if (info.analise_ia?.nuvem_tags && Array.isArray(info.analise_ia.nuvem_tags)) {
- // Pega os 2 primeiros
- const topTags = info.analise_ia.nuvem_tags.slice(0, 2);
-
- topTags.forEach(t => {
- // Dica: Use title para mostrar o score no hover (mouse em cima)
- const scorePercent = Math.round(t.score * 100);
- subTagsHTML += `
-
- #${t.tag}
- `;
- });
- }
- // Tag de Gênero
tagsRow.innerHTML += `🤖 ${genero}`;
}
- // Adiciona o Tom se existir
tagsRow.innerHTML += tomHtml;
-
iaDiv.appendChild(tagsRow);
- // Limpa o container antes de adicionar para evitar duplicatas se rodar 2x
+ // Nova Linha: Subgêneros
+ if (subTagsHTML) {
+ const subTagsRow = document.createElement('div');
+ subTagsRow.className = "tags is-centered mb-0";
+ subTagsRow.style.flexWrap = "wrap";
+ subTagsRow.innerHTML = subTagsHTML;
+ iaDiv.appendChild(subTagsRow);
+ }
+
+ // Limpa e reinsere
bpmContainer.innerHTML = '';
- // Re-adiciona o BPM original se necessário, ou apenas adiciona o novo bloco IA
if(card.dataset.bpm_real > 0) {
bpmContainer.innerHTML = `🎵 ${Math.round(card.dataset.bpm_real)} BPM`;
}
@@ -617,7 +626,8 @@ document.addEventListener('DOMContentLoaded', () => {
const col = c.closest('.project-column');
const g = c.dataset.genre;
const s = parseInt(c.dataset.stars || 0);
- const k = c.dataset.key; // Pega o que salvamos ("Ab", "Cm", etc)
+ const k = c.dataset.key || 'all'; // Pega o tom salvo no card
+ const currentKey = document.getElementById('key-filter')?.value || 'all';
const matchG = (currentGenre === 'all' || g === currentGenre);
const matchS = (currentMinStars === 'all' || s === parseInt(currentMinStars));