diff --git a/crates/modules/tahuantinsuyu/tahuantinsuyu-canvas/src/lib.rs b/crates/modules/tahuantinsuyu/tahuantinsuyu-canvas/src/lib.rs index 334396e..54ab5be 100644 --- a/crates/modules/tahuantinsuyu/tahuantinsuyu-canvas/src/lib.rs +++ b/crates/modules/tahuantinsuyu/tahuantinsuyu-canvas/src/lib.rs @@ -1212,11 +1212,36 @@ fn render_wheel( } } - let shrink = (1.0 - residual * 0.30).clamp(0.60, 1.0); - let disk_size = disk_size_base * shrink; - let font_size_eff = (font_size * shrink).max(11.0); + let shrink_residual = (1.0 - residual * 0.30).clamp(0.60, 1.0); + + // El hovered glyph y su cluster reciben tratamiento + // especial: lo postponemos para pintarlo al FINAL del + // árbol (queda por encima del resto = z-order), y le + // damos un border más fuerte. Su label cluster también + // se destaca (color fg_text en lugar de fg_muted, font + // un punto más grande). + let hovered_sym: Option<&str> = match hover { + Some(HoverInfo::Body { symbol, .. }) => Some(symbol.as_str()), + _ => None, + }; + let hovered_idx: Option = hovered_sym.and_then(|sym| { + layer.glyphs.iter().position(|g| g.symbol == sym) + }); + let hovered_cluster: Option = hovered_idx.map(|i| cluster_of[i]); for (i, g) in layer.glyphs.iter().enumerate() { + if Some(i) == hovered_idx { + continue; // se pinta al final + } + // Achicar discos cuando el glyph está en cluster + // (≥2 miembros) — al estar pegados se ven mejor + // un poco más pequeños. + let cluster_size = clusters[cluster_of[i]].len(); + let in_cluster_shrink = if cluster_size >= 2 { 0.86 } else { 1.0 }; + let effective_shrink = shrink_residual * in_cluster_shrink; + let disk_size = disk_size_base * effective_shrink; + let font_size_eff = (font_size * effective_shrink).max(11.0); + let display_deg = display_degs[i]; let (x, y) = polar_to_screen(display_deg, asc, rot_offset, ring); let color = with_alpha(planet_color(palette, &g.symbol), alpha); @@ -1240,7 +1265,6 @@ fn render_wheel( // Coord label individual: solo cuando el glyph // está SOLO en su cluster (≥2 ⇒ label compartido). - let cluster_size = clusters[cluster_of[i]].len(); if show_coords && (is_natal || is_topo) && cluster_size == 1 { let coord = format_coord_compact(g.deg); let label_r = ring - disk_size * 1.3; @@ -1252,20 +1276,21 @@ fn render_wheel( coord.into(), theme.fg_muted, halo_bg, - 9.5 * s, + 8.5 * s, )); } } // Label compartido para CADA cluster con ≥2 miembros. - // Texto = símbolos concatenados + coord del centroide - // real. Posicionado sobre el centroide DISPLAY (donde - // se ven los discos tras el shift). + // El del cluster hovereado se destaca: color fg_text + // (vs fg_muted) y font un punto más grande. if show_coords && (is_natal || is_topo) { + let disk_size_typical = disk_size_base * shrink_residual * 0.86; for (ci, c) in clusters.iter().enumerate() { if c.len() < 2 { continue; } + let highlighted = Some(ci) == hovered_cluster; let center_display_deg = display_centroids[ci]; let center_real_deg = cluster_centroids[ci]; let symbols: String = c @@ -1275,17 +1300,68 @@ fn render_wheel( .join(" "); let coord = format_coord_compact(center_real_deg); let text = format!("{} {}", symbols, coord); - let label_r = ring - disk_size * 1.5; + let label_r = ring - disk_size_typical * 1.5; let (lx, ly) = polar_to_screen( center_display_deg, asc, rot_offset, label_r, ); + let (fg, font_sz) = if highlighted { + (theme.fg_text, 10.0 * s) + } else { + (theme.fg_muted, 9.0 * s) + }; wheel = wheel.child(coord_label( cx_center + lx, cy_center + ly, text.into(), + fg, + halo_bg, + font_sz, + )); + } + } + + // Render del glyph hovered al FINAL: queda encima del + // resto en z-order. Disco un poco más grande y border + // más prominente para destacar. + if let Some(hi) = hovered_idx { + let g = &layer.glyphs[hi]; + let display_deg = display_degs[hi]; + let (x, y) = polar_to_screen(display_deg, asc, rot_offset, ring); + let color = with_alpha(planet_color(palette, &g.symbol), alpha); + let mut glyph_text = planet_unicode(&g.symbol).to_string(); + if g.retrograde { + glyph_text.push('ᴿ'); + } + if let Some(marker) = &g.dignity_marker { + glyph_text.push_str(marker); + } + let disk_size = disk_size_base * shrink_residual * 1.18; + let font_size_eff = font_size * shrink_residual * 1.12; + wheel = wheel.child(planet_glyph( + cx_center + x, + cy_center + y, + disk_size, + font_size_eff, + glyph_text.into(), + color, + halo_bg, + color, // border al color pleno (no .85) — destaca + )); + // Si el hovered no está en cluster compartido, + // pintamos su coord individual destacada acá. + let cluster_size = clusters[cluster_of[hi]].len(); + if show_coords && (is_natal || is_topo) && cluster_size == 1 { + let coord = format_coord_compact(g.deg); + let label_r = ring - disk_size * 1.3; + let (lx, ly) = + polar_to_screen(display_deg, asc, rot_offset, label_r); + wheel = wheel.child(coord_label( + cx_center + lx, + cy_center + ly, + coord.into(), theme.fg_text, halo_bg, 10.0 * s, @@ -2862,10 +2938,14 @@ fn coord_label( halo_bg: Hsla, font_size: f32, ) -> gpui::Div { - // Estimación gruesa del ancho (caracteres × ~5.5 px a font 9.5). - // Suficiente para no recortar; el flex centra dentro. - let w = (text.len() as f32 * (font_size * 0.58)).max(font_size * 2.0); - let h = font_size + 6.0; + // Estimación del ancho basada en `chars().count()` (NO `text.len()` + // — los chars unicode astronómicos cuentan 3 bytes pero ocupan + // ~1 columna de fuente). Padding lateral muy pequeño en lugar de + // un mínimo grande: pills con 1-3 chars no llevan "espacios en + // negro" que sobrescriben elementos vecinos. + let char_count = text.chars().count() as f32; + let w = (char_count * font_size * 0.62 + font_size * 0.5).max(font_size * 1.4); + let h = font_size + 5.0; div() .absolute() .left(px(x - w / 2.0))