diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Component_Compatibility.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Component_Compatibility.png
index 5f84bdcfb29f99fbd6bccc256a06d0ad6a6b1c6f..4eb17524fee2f4d803f2a426c77f527f4d153b04 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Component_Compatibility.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Component_Compatibility.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Dark_Theme_Default.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Dark_Theme_Default.png
index d7da5127bc020bde7fd7c5a7be10d1dea3e1cc59..9a22069a635c5304842777aa500c4d11f0335e1a 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Dark_Theme_Default.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Dark_Theme_Default.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Dark_Theme_No_Background_Default.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Dark_Theme_No_Background_Default.png
index c1443174b06b11466414194ad1990cb089f6b72f..f66d386b6852409cde7d7e0ff00e1c0e17ecbaa6 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Dark_Theme_No_Background_Default.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Dark_Theme_No_Background_Default.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Dark_Theme_No_Background_Scroll.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Dark_Theme_No_Background_Scroll.png
index c68e23130bb95265a73d910ef90079ea53013769..7b1a17aa9ff6161de47fde8f372922ca3097a538 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Dark_Theme_No_Background_Scroll.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Dark_Theme_No_Background_Scroll.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Dark_Theme_Scroll.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Dark_Theme_Scroll.png
index 3d9d9b7bef47f1454a96aa21ae8b243932d46e20..81679da6eb92b75775180d6d22bf335ec9eea8cb 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Dark_Theme_Scroll.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Dark_Theme_Scroll.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Light_Theme_Default.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Light_Theme_Default.png
index 63142b826eaf75e57f1c1d3a6812edb5bf42ad4f..c8d8d36f6e693628a6e37aca5aad5cb66d0ef479 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Light_Theme_Default.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Light_Theme_Default.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Light_Theme_No_Background_Default.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Light_Theme_No_Background_Default.png
index 99ac71d7b4ab91fe383d5ae0cec727de19db2818..50134055e87bf2d39fcd876b3e7b14abe43cf625 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Light_Theme_No_Background_Default.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Light_Theme_No_Background_Default.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Light_Theme_No_Background_Scroll.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Light_Theme_No_Background_Scroll.png
index 096161254fe85e5b422a69838d5e211d00a27a17..e2bed84eda915d6ebfdd0256008a6d20d4804431 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Light_Theme_No_Background_Scroll.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Light_Theme_No_Background_Scroll.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Light_Theme_Scroll.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Light_Theme_Scroll.png
index 2c6241ec44d841ca928620f93a6f46aebaec58a3..3ad34876611e9e2022ade0173c05a82164b8d1f9 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Light_Theme_Scroll.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Light_Theme_Scroll.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Transparent_Theme_Default.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Transparent_Theme_Default.png
index e0c920384888e1a1fd15ad4943a0d05e34e9a705..2f923ead58df06e3c619a5cd6963e298151d4eb6 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Transparent_Theme_Default.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Transparent_Theme_Default.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Transparent_Theme_No_Background_Default.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Transparent_Theme_No_Background_Default.png
index 0a611518b4495d98598d4d268b419066390a1df0..b75c17b90f0942ca88b427e06da29903649a1e6e 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Transparent_Theme_No_Background_Default.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Transparent_Theme_No_Background_Default.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Transparent_Theme_No_Background_Scroll.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Transparent_Theme_No_Background_Scroll.png
index e62b4dbf474fc41ae590dd6077c210a9c65b8d17..25f6a7cfc9f717b457f8646ceb7897e9838b857f 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Transparent_Theme_No_Background_Scroll.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Transparent_Theme_No_Background_Scroll.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Transparent_Theme_Scroll.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Transparent_Theme_Scroll.png
index 95a52912f972662e03656b9617613ad13585d626..83b2bee35fbaf9c1dfc85f68dcb9e5c2f6147b17 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Transparent_Theme_Scroll.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_Transparent_Theme_Scroll.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Date_Filter_All_Options.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Date_Filter_All_Options.png
index 974bcd8853a836ed119972670b5c580312e8a087..a5370c4db793dfe471d3182370b04737e62b00b5 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Date_Filter_All_Options.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Date_Filter_All_Options.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Date_Filter_Month_Year.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Date_Filter_Month_Year.png
index 3fa84f4b514ff82d4fca59ed1f590c2e1c7a4d38..768007a171f9e2c502e18125393c09fcf6c633d5 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Date_Filter_Month_Year.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Date_Filter_Month_Year.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Date_Filter_Quarter_Year.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Date_Filter_Quarter_Year.png
index 1220048a046cbe358d817a9881b87873ab78f335..4cff910ea3004af53ab9a88487a62afef7fb1747 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Date_Filter_Quarter_Year.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Date_Filter_Quarter_Year.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Date_Filter_Quarter_Year_Dropdown.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Date_Filter_Quarter_Year_Dropdown.png
index c9f5497d05d15a80a92af422006d68e2218011fd..3883f48de71ca8298d53d96d0b34f9a5124dd040 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Date_Filter_Quarter_Year_Dropdown.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Date_Filter_Quarter_Year_Dropdown.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Date_Filter_Range.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Date_Filter_Range.png
index 0d44e0cddb8290c7321c091182e493b8e8158fad..db8d573b51f6074bd83a5abd524a117b876bb622 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Date_Filter_Range.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Date_Filter_Range.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Date_Filter_Relative.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Date_Filter_Relative.png
index c69214c00effd36d5275760faff2055a27c2b578..639b1505ca68f95dfbb3e86cf570073f2718bd53 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Date_Filter_Relative.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Date_Filter_Relative.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Date_Filter_Single.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Date_Filter_Single.png
index f1ae7312e34528869dc9ba7529ad4c2e8f0b9aab..3f73165e05bc5a6f556cbb2c6451db23b0b32926 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Date_Filter_Single.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Date_Filter_Single.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Number.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Number.png
index f2a326fde2c86010fa8d84c6c64effd072be063b..d23c7183daf62f5a30515b6b12eff8983c48946c 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Number.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Number.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Parameter_List.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Parameter_List.png
index fbf3c5bf940d43af8746ca00681c6d92c4b81f5f..698e8f561871cf7431cea15a5ed760e8588f15f7 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Parameter_List.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Parameter_List.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Parameter_List_Single_With_Value.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Parameter_List_Single_With_Value.png
index d90c5895d22e8f317869b4f3f3d5e7fa1ab6ce1e..399fdcbd480d27145ab1c34f3ae3242b3e3ca300 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Parameter_List_Single_With_Value.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Parameter_List_Single_With_Value.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Parameter_List_With_Value.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Parameter_List_With_Value.png
index c9e4045439fcfb2166ba3e35b0520c488a04acf3..dd6f8d9d66e891c324621f162a77503d40302c8b 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Parameter_List_With_Value.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Parameter_List_With_Value.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Parameter_Search.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Parameter_Search.png
index 6555bf66f963f92bdabdd1b29fdda7ad75068f4f..583a9696b18a626f4e262b8aa29f573ccd120d49 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Parameter_Search.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Parameter_Search.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Parameter_Search_With_Value.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Parameter_Search_With_Value.png
index 78719309549ba8ed232edc8806694273d156883f..f3ff304f8d374fe0937e88e8a32a05f967aa8d9e 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Parameter_Search_With_Value.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Parameter_Search_With_Value.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Text.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Text.png
index 504ebb9502a0671ca4a0a6f23e56ce530e79ae26..8a2e3a5b43552374f1e056c64bcb44f85a58cede 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Text.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Text.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Text_With_Value.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Text_With_Value.png
index a937efc98fa8ade268b34c218c04b2ec69ac9dd4..e8893719a3f6308a3191760bfa0392c69f83a315 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Text_With_Value.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Text_With_Value.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Unit_Of_Time.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Unit_Of_Time.png
index 5bfc491dac04e8656a60afb4f1aaa36748aec3eb..eafe23d5f6cc89a2124385d2b0c5800a7b01fc37 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Unit_Of_Time.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Dark_Theme_Unit_Of_Time.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Date_Filter_All_Options.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Date_Filter_All_Options.png
index 31c3976c188473ab3494e697d4ef48bf82ec55f5..a401f04507b8430a9420c125c6689fc0af022173 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Date_Filter_All_Options.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Date_Filter_All_Options.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Date_Filter_Month_Year.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Date_Filter_Month_Year.png
index c56605e598c1b1492e4ae8c34c8966a9522218ae..075a0dd2e86cf7ba4f0acd614c294efcf931d7fb 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Date_Filter_Month_Year.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Date_Filter_Month_Year.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Date_Filter_Quarter_Year.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Date_Filter_Quarter_Year.png
index f4ee8a121fd6b6026fa394419faa45555cf7e0bd..25db56801beaac1c92da3d9d69918c91d6d76a07 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Date_Filter_Quarter_Year.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Date_Filter_Quarter_Year.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Date_Filter_Quarter_Year_Dropdown.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Date_Filter_Quarter_Year_Dropdown.png
index 99c7f14814d926de6648998522d52cc83a65e321..a30f79954011559abf2119afc5d207d4db74b99e 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Date_Filter_Quarter_Year_Dropdown.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Date_Filter_Quarter_Year_Dropdown.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Date_Filter_Range.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Date_Filter_Range.png
index b16e53e9f43a1e9b6b643fea1b7c75a734397182..f42f3c1a7c58389502aeb1cab6001d92aec92cde 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Date_Filter_Range.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Date_Filter_Range.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Date_Filter_Relative.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Date_Filter_Relative.png
index 7178a9b0749e3a94cc6701eca5ec421270529858..23f6cfd0d138dc64e322e0ccba1da8abcbbe15ed 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Date_Filter_Relative.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Date_Filter_Relative.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Date_Filter_Single.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Date_Filter_Single.png
index 960204a6a2137f7fe132d325fe6c466f4cbaacfc..be11694112ff76eae0283f6cc8fd13e469e51a56 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Date_Filter_Single.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Date_Filter_Single.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Number.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Number.png
index 3ee55033066407e8596c4be75dde38757b6ca3d5..202a2dcfa7fafe064893b1cdc8cae575bc23db00 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Number.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Number.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Parameter_List.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Parameter_List.png
index ac01ad5a8e945c5be9d66d45c4f9852fe59ecc6d..b85290c3c9e246c5b7c0b47a3c00238e0922f506 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Parameter_List.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Parameter_List.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Parameter_List_Single_With_Value.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Parameter_List_Single_With_Value.png
index 51ff8f3199beada911b053ec1d5875ebf0879ea6..8d7e8d7572c110de6205e0f2e0f9da3f241a659e 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Parameter_List_Single_With_Value.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Parameter_List_Single_With_Value.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Parameter_List_With_Value.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Parameter_List_With_Value.png
index 71a5a4920bea80a471e285725c936e65ec15edfd..74213a1d2e66b9a3bcfb926290605c97df528208 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Parameter_List_With_Value.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Parameter_List_With_Value.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Parameter_Search.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Parameter_Search.png
index eb8de21a0bbf623ef1b727a213d117936f636d1e..3490d00097befc6e766217a5359cecf21894a96c 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Parameter_Search.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Parameter_Search.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Parameter_Search_With_Value.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Parameter_Search_With_Value.png
index f8594d414c2794ad04f51f4f19578fdcbe37f167..225530ad1a468b9b136d92f82c17fc3c76b23fdc 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Parameter_Search_With_Value.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Parameter_Search_With_Value.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Text.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Text.png
index 52d9a776b26cd747cd24be1f769914ab493462a7..8ec1a847457040106c7f5d580010285210e9349c 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Text.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Text.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Text_With_Value.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Text_With_Value.png
index 70ef2dbdc313f6f7dc9cbb9d6452a1a02ee8d821..121599d45be5ef01cacb58adc97a1a6cc3f55197 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Text_With_Value.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Text_With_Value.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Unit_Of_Time.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Unit_Of_Time.png
index 95eca09668373e9159a8909dff062afeba01171a..9b95e05459494079f7e55e1b75c7471437c285e3 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Unit_Of_Time.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedDashboardView_filters_Light_Theme_Unit_Of_Time.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Dark_Theme_Default.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Dark_Theme_Default.png
index 999ecc6399effe08ebd8b4337a18779f735cf5cf..16f4665179b3f04746f1b9b0a86378fbb9508373 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Dark_Theme_Default.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Dark_Theme_Default.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Dark_Theme_Default_No_Results.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Dark_Theme_Default_No_Results.png
index 0e9199f42df96a00d23d963931b3409753e2fe7e..ed42da0c6a4c1d11a5a05ddefdd51690fe5b2334 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Dark_Theme_Default_No_Results.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Dark_Theme_Default_No_Results.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Light_Theme_Default.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Light_Theme_Default.png
index 5ff355271691d4a6ba95d328c0530d14306efabb..95e2ef2dbb093271e1bb083d761b9d28fb5f18f7 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Light_Theme_Default.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Light_Theme_Default.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Light_Theme_Default_No_Results.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Light_Theme_Default_No_Results.png
index 2da8a24f488712217487a52e9fef35ea38971a9f..e674272a92a06803dc93a43c2d3b56714e8d716c 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Light_Theme_Default_No_Results.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Light_Theme_Default_No_Results.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Pivot_Table_Dark_Theme.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Pivot_Table_Dark_Theme.png
index 76eaa63a555d927cc4e7de96695ec7e4959ae802..c91eb0200f32ab8cceae23d648afe4946af44ad9 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Pivot_Table_Dark_Theme.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Pivot_Table_Dark_Theme.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Pivot_Table_Light_Theme.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Pivot_Table_Light_Theme.png
index 6f48a812430e280dd028284912b8f6ebde4e4cba..5d974736731bded7bb7cb49015120c6b011e4556 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Pivot_Table_Light_Theme.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Pivot_Table_Light_Theme.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Smart_Scalar_Dark_Theme.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Smart_Scalar_Dark_Theme.png
index 91e85cf82311b0a869633a73ec3d4b0d5f506382..5a65f3339230af6c6c8f0d94ded92babcee2ba9e 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Smart_Scalar_Dark_Theme.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Smart_Scalar_Dark_Theme.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Smart_Scalar_Dark_Theme_Tooltip.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Smart_Scalar_Dark_Theme_Tooltip.png
index 79cfe86b813aeb80bb484452b1ace90619375f4f..1f5cfa0d0af8df6f86558c80655480bffefe22ee 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Smart_Scalar_Dark_Theme_Tooltip.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Smart_Scalar_Dark_Theme_Tooltip.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Smart_Scalar_Light_Theme.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Smart_Scalar_Light_Theme.png
index ae5297dd9d222342ce491503bd4b29b30e3b2003..e993994774c479793c87f12ad461350207f3ac5a 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Smart_Scalar_Light_Theme.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Smart_Scalar_Light_Theme.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Smart_Scalar_Light_Theme_Tooltip.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Smart_Scalar_Light_Theme_Tooltip.png
index d5948901ab773ab55e06306a2d7a0c1ea1ac6f0a..7e03128614ed59acac2e23984f34f6c3257c51fa 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Smart_Scalar_Light_Theme_Tooltip.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Smart_Scalar_Light_Theme_Tooltip.png differ
diff --git a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Transparent_Theme_Default.png b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Transparent_Theme_Default.png
index 71c03f5c07e1951c927b1e204d3c32ecff3f3ab3..94b303d975892342db427255e765cda0759d81a1 100644
Binary files a/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Transparent_Theme_Default.png and b/.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Transparent_Theme_Default.png differ
diff --git a/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Auto_Y_Axis_Exclude_Zero_With_Goal.png b/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Auto_Y_Axis_Exclude_Zero_With_Goal.png
index 474658f9d49b04f54ab6d28a262675dfb42accde..20948e59b968e8ce0f1aad403707ca206842cefb 100644
Binary files a/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Auto_Y_Axis_Exclude_Zero_With_Goal.png and b/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Auto_Y_Axis_Exclude_Zero_With_Goal.png differ
diff --git a/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Bubble_Size.png b/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Bubble_Size.png
index 3cc9bd2935a42a1b8ef2ce64a94b7d2c93da70af..4c16532ba75871cbc5f5b0c2063afea526ba6bfc 100644
Binary files a/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Bubble_Size.png and b/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Bubble_Size.png differ
diff --git a/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Custom_Y_Axis_Range.png b/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Custom_Y_Axis_Range.png
index 863d648c99b72ac55ad9c0016c24a372aed4e54d..55a134513b24c87e0cd93cc2bdf913922b6c38fd 100644
Binary files a/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Custom_Y_Axis_Range.png and b/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Custom_Y_Axis_Range.png differ
diff --git a/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Custom_Y_Axis_Range_With_Column_Scaling.png b/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Custom_Y_Axis_Range_With_Column_Scaling.png
index 77678cfc54351054dc196197d5cd752de3f07103..3f5943f64e3221adc3c5b0271e6167c3ff57843a 100644
Binary files a/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Custom_Y_Axis_Range_With_Column_Scaling.png and b/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Custom_Y_Axis_Range_With_Column_Scaling.png differ
diff --git a/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Default.png b/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Default.png
index 5d6bdf38aaa020724a459dfc6f01efbb185f9f04..9410fc76b1db0eeb77f110398232231c454ff676 100644
Binary files a/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Default.png and b/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Default.png differ
diff --git a/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Goal_Line.png b/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Goal_Line.png
index 2fa8705fcc2c96c0edc4263c4c3ea3b406d3fa29..5af2c42311a18b9e37b70e5b9022b93b9e622f01 100644
Binary files a/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Goal_Line.png and b/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Goal_Line.png differ
diff --git a/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Histogram_X_Scale.png b/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Histogram_X_Scale.png
index fa0e17113dee8861e0ed6b29fb4e82adf4c0183b..08572942401726b607f197396b017509028c494f 100644
Binary files a/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Histogram_X_Scale.png and b/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Histogram_X_Scale.png differ
diff --git a/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Log_X_Scale.png b/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Log_X_Scale.png
index 089f9ea8bb3820362f1264d1c26083a30588d8ad..a500cdc8b457dee9c12f9c602417f1fac2c0582e 100644
Binary files a/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Log_X_Scale.png and b/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Log_X_Scale.png differ
diff --git a/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Log_X_Scale_At_One.png b/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Log_X_Scale_At_One.png
index 2d20e5bf6ae28463aaee40a3e12e3315d714114c..345fe2d3330caa726da47ab0557c5cdef93bfe37 100644
Binary files a/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Log_X_Scale_At_One.png and b/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Log_X_Scale_At_One.png differ
diff --git a/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Multi_Dimension_Breakout.png b/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Multi_Dimension_Breakout.png
index a14337d68a023010c412c9f371f1ecef074d2950..1c541ecf57ad03701624648504150a6be61fd17f 100644
Binary files a/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Multi_Dimension_Breakout.png and b/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Multi_Dimension_Breakout.png differ
diff --git a/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Multi_Dimension_Breakout_Bubble_Size.png b/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Multi_Dimension_Breakout_Bubble_Size.png
index 417b327b3ba95c18de99fef6975e19622a616a5d..85c85fa238fc5d6347898f3a50f15febdaa4a77e 100644
Binary files a/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Multi_Dimension_Breakout_Bubble_Size.png and b/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Multi_Dimension_Breakout_Bubble_Size.png differ
diff --git a/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Multi_Metric_Series.png b/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Multi_Metric_Series.png
index 0c027b56c6842177bfb5e7779775f1a0e245a3d8..98a0e4ffa77f9fde552c657271c06bd14b19faa1 100644
Binary files a/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Multi_Metric_Series.png and b/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Multi_Metric_Series.png differ
diff --git a/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Ordinal_X_Scale.png b/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Ordinal_X_Scale.png
index 5f8cb0ffb6551384cae3583e5579ec9ed449e7aa..4fb6f44401a54232bf9fd8770c87e3f8e626fe5d 100644
Binary files a/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Ordinal_X_Scale.png and b/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Ordinal_X_Scale.png differ
diff --git a/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Power_X_Scale.png b/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Power_X_Scale.png
index 5d8c283f9bd5ed3d3dca82c194e25668866d9e63..b419924ab3222f44481189c4750e6e68460893b9 100644
Binary files a/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Power_X_Scale.png and b/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Power_X_Scale.png differ
diff --git a/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Power_X_Scale_Multi_Series.png b/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Power_X_Scale_Multi_Series.png
index d0160e6e959a6ecb926d7fe3e311bc4cb46f6ba9..eaa070000e77074c7cd0537205175aff46d94b20 100644
Binary files a/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Power_X_Scale_Multi_Series.png and b/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Power_X_Scale_Multi_Series.png differ
diff --git a/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Timeseries_X_Scale.png b/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Timeseries_X_Scale.png
index 8c30e666adc139e3a9d1b952c10f0c81ddca0baa..265c3bfd2bcc09c2181481f5dc38880a86a71db8 100644
Binary files a/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Timeseries_X_Scale.png and b/.loki/reference/chrome_laptop_static_viz_ScatterPlot_Timeseries_X_Scale.png differ
diff --git a/.loki/reference/chrome_laptop_viz_BarChart_Default.png b/.loki/reference/chrome_laptop_viz_BarChart_Default.png
index 5790438a905aa3c20c01eacb01920b37546cda6b..e3a67f0cfc0c44ebbdf5f95aee3e5d53b0870c44 100644
Binary files a/.loki/reference/chrome_laptop_viz_BarChart_Default.png and b/.loki/reference/chrome_laptop_viz_BarChart_Default.png differ
diff --git a/.loki/reference/chrome_laptop_viz_BarChart_Embedding_Huge_Font.png b/.loki/reference/chrome_laptop_viz_BarChart_Embedding_Huge_Font.png
index f7eb5e4c14cdb869dd1975d90a9acf2322f3c544..91c5a2ee49d82db82f0de6b431d60b9e8889d375 100644
Binary files a/.loki/reference/chrome_laptop_viz_BarChart_Embedding_Huge_Font.png and b/.loki/reference/chrome_laptop_viz_BarChart_Embedding_Huge_Font.png differ
diff --git a/.loki/reference/chrome_laptop_viz_LineChart_Default.png b/.loki/reference/chrome_laptop_viz_LineChart_Default.png
index b1222d607f01306a7d6a6af5af3c5ab24501e07d..0c067ea6dfef6767301631629cf4e9e8531cdbd4 100644
Binary files a/.loki/reference/chrome_laptop_viz_LineChart_Default.png and b/.loki/reference/chrome_laptop_viz_LineChart_Default.png differ
diff --git a/.loki/reference/chrome_laptop_viz_LineChart_Embedding_Huge_Font.png b/.loki/reference/chrome_laptop_viz_LineChart_Embedding_Huge_Font.png
index ba0678a5625ea3665a71e5049e8d9cbc930881ce..542a23537b34de41df4b02bf285a3390082b2f88 100644
Binary files a/.loki/reference/chrome_laptop_viz_LineChart_Embedding_Huge_Font.png and b/.loki/reference/chrome_laptop_viz_LineChart_Embedding_Huge_Font.png differ
diff --git a/.loki/reference/chrome_laptop_viz_TableSimple_Default.png b/.loki/reference/chrome_laptop_viz_TableSimple_Default.png
index 9dfebe2892d30c7267e3495f79135103d80039ec..19ed2d70f15986a00848c28200bf8fda710d6cb3 100644
Binary files a/.loki/reference/chrome_laptop_viz_TableSimple_Default.png and b/.loki/reference/chrome_laptop_viz_TableSimple_Default.png differ
diff --git a/.loki/reference/chrome_laptop_viz_TableSimple_Embedding_Theme.png b/.loki/reference/chrome_laptop_viz_TableSimple_Embedding_Theme.png
index 43f6eeccf39d2266338036c5b74bd497acafaf2c..b67a3d026e63826b17ab6482b3eca8a153064e39 100644
Binary files a/.loki/reference/chrome_laptop_viz_TableSimple_Embedding_Theme.png and b/.loki/reference/chrome_laptop_viz_TableSimple_Embedding_Theme.png differ
diff --git a/e2e/support/helpers/e2e-visual-tests-helpers.js b/e2e/support/helpers/e2e-visual-tests-helpers.js
index 429e855ef875f2588db2691b5fd7e5e9960c96e2..41e89cdc3844f52961649ef9bec6eab1dc60c922 100644
--- a/e2e/support/helpers/e2e-visual-tests-helpers.js
+++ b/e2e/support/helpers/e2e-visual-tests-helpers.js
@@ -119,3 +119,60 @@ export function pieSliceWithColor(color) {
     `path[stroke-linejoin='bevel'][fill='${color}']`,
   );
 }
+
+export function echartsTooltip() {
+  // ECharts may keep two dom instances of the tooltip
+  return cy
+    .findAllByTestId("echarts-tooltip")
+    .filter(":visible")
+    .should("have.length", 1)
+    .eq(0);
+}
+
+export function tooltipHeader() {
+  return cy.findByTestId("echarts-tooltip-header");
+}
+
+export function assertTooltipRow(
+  name,
+  { color, value, secondaryValue, index } = {},
+) {
+  cy.findAllByText(name)
+    .eq(index ?? 0)
+    .parent("tr")
+    .within(() => {
+      if (color) {
+        cy.get("td")
+          .eq(0)
+          .find("span")
+          .should("have.class", `marker-${color.replace("#", "")}`);
+      }
+
+      if (value) {
+        cy.findByText(value);
+      }
+
+      if (secondaryValue) {
+        cy.findByText(secondaryValue);
+      }
+    });
+}
+
+export function assertEChartsTooltip({ header, rows, blurAfter }) {
+  echartsTooltip().within(() => {
+    if (header != null) {
+      tooltipHeader().should("have.text", header);
+    }
+
+    if (rows != null) {
+      rows.forEach(row => {
+        const { name, ...rest } = row;
+        assertTooltipRow(name, rest);
+      });
+    }
+  });
+
+  if (blurAfter) {
+    echartsTriggerBlur();
+  }
+}
diff --git a/e2e/test/scenarios/dashboard-cards/dashboard-drill.cy.spec.js b/e2e/test/scenarios/dashboard-cards/dashboard-drill.cy.spec.js
index d847d58fff50fda09ebdb7a3183f004261f25b07..f512b256df56a89bd0e11f7e6116c69674678d65 100644
--- a/e2e/test/scenarios/dashboard-cards/dashboard-drill.cy.spec.js
+++ b/e2e/test/scenarios/dashboard-cards/dashboard-drill.cy.spec.js
@@ -22,9 +22,11 @@ import {
   chartPathWithFillColor,
   echartsContainer,
   entityPickerModal,
-  testPairedTooltipValues,
   editDashboard,
   saveDashboard,
+  echartsTooltip,
+  tooltipHeader,
+  assertTooltipRow,
 } from "e2e/support/helpers";
 
 const {
@@ -884,19 +886,18 @@ describe("scenarios > dashboard > dashboard drill", () => {
 
           visitDashboard(DASHBOARD_ID);
 
-          chartPathWithFillColor("#88BF4D").first().trigger("mousemove");
+          const assertTooltipValues = () =>
+            echartsTooltip().within(() => {
+              tooltipHeader().should("have.text", 1);
+              assertTooltipRow("15612_1", { color: "#88BF4D", value: "5" });
+              assertTooltipRow("15612_2", { color: "#98D9D9", value: "10" });
+            });
 
-          popover().within(() => {
-            testPairedTooltipValues("AXIS", "1");
-            testPairedTooltipValues("VALUE", "5");
-          });
+          chartPathWithFillColor("#88BF4D").first().trigger("mousemove");
+          assertTooltipValues();
 
           chartPathWithFillColor("#98D9D9").first().trigger("mousemove");
-
-          popover().within(() => {
-            testPairedTooltipValues("AXIS", "1");
-            testPairedTooltipValues("VALUE", "10");
-          });
+          assertTooltipValues();
         });
       });
     });
diff --git a/e2e/test/scenarios/dashboard/x-rays.cy.spec.js b/e2e/test/scenarios/dashboard/x-rays.cy.spec.js
index 9bb18437a9a65e1cab47cfe46900ba78815586f7..1bde6c79a7320d30d9e5acc9a64fe5c440348ffe 100644
--- a/e2e/test/scenarios/dashboard/x-rays.cy.spec.js
+++ b/e2e/test/scenarios/dashboard/x-rays.cy.spec.js
@@ -12,6 +12,7 @@ import {
   saveDashboard,
   cartesianChartCircle,
   chartPathWithFillColor,
+  assertEChartsTooltip,
 } from "e2e/support/helpers";
 
 const { ORDERS, ORDERS_ID, PRODUCTS, PRODUCTS_ID, PEOPLE, PEOPLE_ID } =
@@ -302,9 +303,15 @@ describe("scenarios > x-rays", { tags: "@slow" }, () => {
     chartPathWithFillColor("#509EE3").should("have.length", 5);
     chartPathWithFillColor("#509EE3").eq(0).realHover();
 
-    popover().within(() => {
-      cy.findByText("Affiliate").should("be.visible");
-      cy.findByText("3,520").should("be.visible");
+    assertEChartsTooltip({
+      header: "Affiliate",
+      rows: [
+        {
+          color: "#509EE3",
+          name: "Count",
+          value: "3,520",
+        },
+      ],
     });
   });
 
diff --git a/e2e/test/scenarios/embedding/embedding-linked-filters.cy.spec.js b/e2e/test/scenarios/embedding/embedding-linked-filters.cy.spec.js
index 74fdf1318c9b8eb2c55618d31c638c44338494a9..b8934c6614d1e31c1810f2932dc3b351929a346c 100644
--- a/e2e/test/scenarios/embedding/embedding-linked-filters.cy.spec.js
+++ b/e2e/test/scenarios/embedding/embedding-linked-filters.cy.spec.js
@@ -6,9 +6,9 @@ import {
   getDashboardCard,
   chartPathWithFillColor,
   echartsContainer,
-  testPairedTooltipValues,
   multiAutocompleteInput,
   removeMultiAutocompleteValue,
+  assertEChartsTooltip,
 } from "e2e/support/helpers";
 
 import {
@@ -84,10 +84,10 @@ describe("scenarios > embedding > dashboard > linked filters (metabase#13639, me
         .and("not.contain", "TX");
 
       chartPathWithFillColor("#509EE3").should("have.length", 1).realHover();
-
-      popover().within(() => {
-        testPairedTooltipValues("STATE", "AK");
-        testPairedTooltipValues("Count", "68");
+      assertEChartsTooltip({
+        header: "AK",
+        rows: [{ color: "#509EE3", name: "Count", value: "68" }],
+        blurAfter: true,
       });
 
       openFilterOptions("City");
@@ -105,9 +105,9 @@ describe("scenarios > embedding > dashboard > linked filters (metabase#13639, me
 
       chartPathWithFillColor("#509EE3").should("have.length", 1).realHover();
 
-      popover().within(() => {
-        testPairedTooltipValues("STATE", "AK");
-        testPairedTooltipValues("Count", "1");
+      assertEChartsTooltip({
+        header: "AK",
+        rows: [{ color: "#509EE3", name: "Count", value: "1" }],
       });
     });
 
@@ -157,9 +157,10 @@ describe("scenarios > embedding > dashboard > linked filters (metabase#13639, me
 
       chartPathWithFillColor("#509EE3").should("have.length", 1).realHover();
 
-      popover().within(() => {
-        testPairedTooltipValues("STATE", "AK");
-        testPairedTooltipValues("Count", "68");
+      assertEChartsTooltip({
+        header: "AK",
+        rows: [{ color: "#509EE3", name: "Count", value: "68" }],
+        blurAfter: true,
       });
 
       openFilterOptions("City");
@@ -180,9 +181,9 @@ describe("scenarios > embedding > dashboard > linked filters (metabase#13639, me
 
       chartPathWithFillColor("#509EE3").should("have.length", 1).realHover();
 
-      popover().within(() => {
-        testPairedTooltipValues("STATE", "AK");
-        testPairedTooltipValues("Count", "1");
+      assertEChartsTooltip({
+        header: "AK",
+        rows: [{ color: "#509EE3", name: "Count", value: "1" }],
       });
     });
 
@@ -202,9 +203,10 @@ describe("scenarios > embedding > dashboard > linked filters (metabase#13639, me
 
       chartPathWithFillColor("#509EE3").should("have.length", 1).realHover();
 
-      popover().within(() => {
-        testPairedTooltipValues("STATE", "AK");
-        testPairedTooltipValues("Count", "68");
+      assertEChartsTooltip({
+        header: "AK",
+        rows: [{ color: "#509EE3", name: "Count", value: "68" }],
+        blurAfter: true,
       });
 
       openFilterOptions("City");
@@ -222,9 +224,9 @@ describe("scenarios > embedding > dashboard > linked filters (metabase#13639, me
 
       chartPathWithFillColor("#509EE3").should("have.length", 1).realHover();
 
-      popover().within(() => {
-        testPairedTooltipValues("STATE", "AK");
-        testPairedTooltipValues("Count", "1");
+      assertEChartsTooltip({
+        header: "AK",
+        rows: [{ color: "#509EE3", name: "Count", value: "1" }],
       });
     });
 
@@ -243,9 +245,10 @@ describe("scenarios > embedding > dashboard > linked filters (metabase#13639, me
 
       chartPathWithFillColor("#509EE3").should("have.length", 1).realHover();
 
-      popover().within(() => {
-        testPairedTooltipValues("STATE", "AK");
-        testPairedTooltipValues("Count", "68");
+      assertEChartsTooltip({
+        header: "AK",
+        rows: [{ color: "#509EE3", name: "Count", value: "68" }],
+        blurAfter: true,
       });
 
       filterWidget().should("have.length", 1).and("contain", "City").click();
@@ -263,9 +266,9 @@ describe("scenarios > embedding > dashboard > linked filters (metabase#13639, me
 
       chartPathWithFillColor("#509EE3").should("have.length", 1).realHover();
 
-      popover().within(() => {
-        testPairedTooltipValues("STATE", "AK");
-        testPairedTooltipValues("Count", "1");
+      assertEChartsTooltip({
+        header: "AK",
+        rows: [{ color: "#509EE3", name: "Count", value: "1" }],
       });
     });
 
diff --git a/e2e/test/scenarios/embedding/embedding-questions.cy.spec.js b/e2e/test/scenarios/embedding/embedding-questions.cy.spec.js
index 807334941e3cc24135034df2f59706cb13f5b350..78af16fb91fb8917405f69b03575d08d7d225e84 100644
--- a/e2e/test/scenarios/embedding/embedding-questions.cy.spec.js
+++ b/e2e/test/scenarios/embedding/embedding-questions.cy.spec.js
@@ -8,7 +8,7 @@ import {
   openStaticEmbeddingModal,
   echartsContainer,
   cartesianChartCircle,
-  testPairedTooltipValues,
+  assertEChartsTooltip,
   describeEE,
   filterWidget,
   visitEmbeddedPage,
@@ -107,12 +107,11 @@ describe("scenarios > embedding > questions", () => {
     echartsContainer().should("contain", "60");
 
     // Check the tooltip for the last point on the line
-    cartesianChartCircle().last().realHover();
+    cartesianChartCircle().last().trigger("mousemove");
 
-    popover().within(() => {
-      testPairedTooltipValues("Created At", "Aug 2022");
-      testPairedTooltipValues("Math", "2");
-      testPairedTooltipValues("Count", "79");
+    assertEChartsTooltip({
+      header: "Aug 2022",
+      rows: [{ name: "2", value: "79" }],
     });
   });
 
diff --git a/e2e/test/scenarios/question-reproductions/reproductions-3.cy.spec.js b/e2e/test/scenarios/question-reproductions/reproductions-3.cy.spec.js
index dd83c24f741a11141bfa3a505530b77d1326d041..9b6c892c28e40e8f0812c496ade2976561bf074a 100644
--- a/e2e/test/scenarios/question-reproductions/reproductions-3.cy.spec.js
+++ b/e2e/test/scenarios/question-reproductions/reproductions-3.cy.spec.js
@@ -41,7 +41,7 @@ import {
   assertQueryBuilderRowCount,
   visitDashboard,
   getDashboardCard,
-  testTooltipPairs,
+  assertEChartsTooltip,
   join,
   visitQuestion,
   tableHeaderClick,
@@ -1207,11 +1207,12 @@ describe("issue 31960", () => {
     getDashboardCard().within(() => {
       cartesianChartCircle().eq(dotIndex).realHover();
     });
-    testTooltipPairs([
-      ["Created At:", "July 10–16, 2022"],
-      ["Count:", String(rowCount)],
-      ["Compared to previous week", "+10%"],
-    ]);
+    assertEChartsTooltip({
+      header: "July 10–16, 2022",
+      rows: [
+        { name: "Count", value: String(rowCount), secondaryValue: "+10%" },
+      ],
+    });
     getDashboardCard().within(() => {
       cartesianChartCircle().eq(dotIndex).click({ force: true });
     });
diff --git a/e2e/test/scenarios/visualizations-charts/bar_chart.cy.spec.js b/e2e/test/scenarios/visualizations-charts/bar_chart.cy.spec.js
index 3948946bdcf497dbda45398e38c4e75c21991033..479341feea0b7fbff166b227f928927a5c071a9d 100644
--- a/e2e/test/scenarios/visualizations-charts/bar_chart.cy.spec.js
+++ b/e2e/test/scenarios/visualizations-charts/bar_chart.cy.spec.js
@@ -15,7 +15,7 @@ import {
   createQuestion,
   chartPathsWithFillColors,
   createNativeQuestion,
-  testStackedTooltipRows,
+  assertEChartsTooltip,
 } from "e2e/support/helpers";
 
 const { ORDERS, ORDERS_ID, PEOPLE, PRODUCTS, PRODUCTS_ID } = SAMPLE_DATABASE;
@@ -617,12 +617,22 @@ describe("scenarios > visualizations > bar chart", () => {
     });
 
     chartPathWithFillColor("#88BF4D").first().realHover();
-    popover().within(() => {
-      cy.contains("Sum of Total");
-      // half of the unscaled metric
-      cy.contains("21,078.43");
-      // full value of the unscale metric
-      cy.contains("42,156.87");
+    assertEChartsTooltip({
+      header: "2022",
+      rows: [
+        {
+          color: "#88BF4D",
+          name: "Sum of Total",
+          value: "21,078.43",
+          index: 0,
+        },
+        {
+          color: "#98D9D9",
+          name: "Sum of Total",
+          value: "42,156.87",
+          index: 1,
+        },
+      ],
     });
   });
 
@@ -648,43 +658,123 @@ describe("scenarios > visualizations > bar chart", () => {
     );
 
     chartPathWithFillColor("#A989C5").eq(0).realHover();
-    testStackedTooltipRows([
-      ["blue", "2", "20.00 %"],
-      ["yellow", "8", "80.00 %"],
-      ["Total", "10", "100 %"],
-    ]);
+    assertEChartsTooltip({
+      rows: [
+        {
+          color: "#A989C5",
+          name: "blue",
+          value: "2",
+          secondaryValue: "20.00 %",
+        },
+        {
+          color: "#F9D45C",
+          name: "yellow",
+          value: "8",
+          secondaryValue: "80.00 %",
+        },
+        {
+          name: "Total",
+          value: "10",
+          secondaryValue: "100 %",
+        },
+      ],
+    });
     resetHoverState();
 
     chartPathWithFillColor("#A989C5").eq(1).realHover();
-    testStackedTooltipRows([
-      ["blue", "-16", "-200.00 %"],
-      ["yellow", "8", "100 %"],
-      ["Total", "-8", "-100.00 %"],
-    ]);
+    assertEChartsTooltip({
+      rows: [
+        {
+          color: "#A989C5",
+          name: "blue",
+          value: "-16",
+          secondaryValue: "-200.00 %",
+        },
+        {
+          color: "#F9D45C",
+          name: "yellow",
+          value: "8",
+          secondaryValue: "100 %",
+        },
+        {
+          name: "Total",
+          value: "-8",
+          secondaryValue: "-100.00 %",
+        },
+      ],
+    });
     resetHoverState();
 
     chartPathWithFillColor("#A989C5").eq(2).realHover();
-    testStackedTooltipRows([
-      ["blue", "-7", "-350.00 %"],
-      ["yellow", "5", "250.00 %"],
-      ["Total", "-2", "-100.00 %"],
-    ]);
+    assertEChartsTooltip({
+      rows: [
+        {
+          color: "#A989C5",
+          name: "blue",
+          value: "-7",
+          secondaryValue: "-350.00 %",
+        },
+        {
+          color: "#F9D45C",
+          name: "yellow",
+          value: "5",
+          secondaryValue: "250.00 %",
+        },
+        {
+          name: "Total",
+          value: "-2",
+          secondaryValue: "-100.00 %",
+        },
+      ],
+    });
     resetHoverState();
 
     chartPathWithFillColor("#A989C5").eq(3).realHover();
-    testStackedTooltipRows([
-      ["blue", "2", "Infinity %"],
-      ["yellow", "-2", "-Infinity %"],
-      ["Total", "0", "NaN %"],
-    ]);
+    assertEChartsTooltip({
+      rows: [
+        {
+          color: "#A989C5",
+          name: "blue",
+          value: "2",
+          secondaryValue: "Infinity %",
+        },
+        {
+          color: "#F9D45C",
+          name: "yellow",
+          value: "-2",
+          secondaryValue: "-Infinity %",
+        },
+        {
+          name: "Total",
+          value: "0",
+          secondaryValue: "NaN %",
+        },
+      ],
+    });
     resetHoverState();
 
     chartPathWithFillColor("#A989C5").eq(4).realHover();
-    testStackedTooltipRows([
-      ["blue", "3", "300.00 %"],
-      ["yellow", "-2", "-200.00 %"],
-      ["Total", "1", "100 %"],
-    ]);
+    assertEChartsTooltip({
+      rows: [
+        {
+          color: "#A989C5",
+          name: "blue",
+          value: "3",
+          secondaryValue: "300.00 %",
+        },
+        {
+          color: "#F9D45C",
+          name: "yellow",
+          value: "-2",
+          secondaryValue: "-200.00 %",
+        },
+        {
+          name: "Total",
+          value: "1",
+          secondaryValue: "100 %",
+        },
+      ],
+    });
     resetHoverState();
   });
 });
diff --git a/e2e/test/scenarios/visualizations-charts/combo.cy.spec.js b/e2e/test/scenarios/visualizations-charts/combo.cy.spec.js
index f2d4920052f30c723a8ec4a714cf06db2acada1b..48e60bae2502b20c0e86b6f55b0bfba59624bda7 100644
--- a/e2e/test/scenarios/visualizations-charts/combo.cy.spec.js
+++ b/e2e/test/scenarios/visualizations-charts/combo.cy.spec.js
@@ -4,10 +4,9 @@ import {
   echartsContainer,
   restore,
   visitQuestionAdhoc,
-  testTooltipPairs,
   cartesianChartCircleWithColor,
-  testStackedTooltipRows,
   chartPathWithFillColor,
+  assertEChartsTooltip,
 } from "e2e/support/helpers";
 
 const { PRODUCTS, PRODUCTS_ID, ORDERS_ID, ORDERS } = SAMPLE_DATABASE;
@@ -93,35 +92,75 @@ describe("scenarios > visualizations > combo", () => {
 
     // First circle of the line series
     cartesianChartCircleWithColor("#A989C5").eq(0).trigger("mousemove");
-    testTooltipPairs([
-      ["Created At:", "2022"],
-      ["Average of Total:", "56.66"],
-      ["Average of Subtotal:", "54.44"],
-      ["Min of Total:", "12.32"],
-      ["Min of Subtotal:", "15.69"],
-      ["Max of Total:", "102.77"],
-      ["Max of Subtotal:", "98.82"],
-    ]);
+    assertEChartsTooltip({
+      header: "2022",
+      rows: [
+        { color: "#A989C5", name: "Average of Total", value: "56.66" },
+        { color: "#F2A86F", name: "Average of Subtotal", value: "54.44" },
+        { color: "#EF8C8C", name: "Min of Total", value: "12.32" },
+        { color: "#98D9D9", name: "Min of Subtotal", value: "15.69" },
+        { color: "#F9D45C", name: "Max of Total", value: "102.77" },
+        { color: "#7172AD", name: "Max of Subtotal", value: "98.82" },
+      ],
+    });
 
     // First circle of stacked area series
     cartesianChartCircleWithColor("#98D9D9").eq(0).trigger("mousemove");
 
     // Check the tooltip shows only stacked areas series
-    testStackedTooltipRows([
-      ["Min of Subtotal", "15.69", "56.01 %"],
-      ["Min of Total", "12.32", "43.99 %"],
-      ["Total", "28.02", "100 %"],
-    ]);
+    assertEChartsTooltip({
+      header: "2022",
+      rows: [
+        {
+          color: "#EF8C8C",
+          name: "Min of Total",
+          value: "12.32",
+          secondaryValue: "43.99 %",
+        },
+        {
+          color: "#98D9D9",
+          name: "Min of Subtotal",
+          value: "15.69",
+          secondaryValue: "56.01 %",
+        },
+        {
+          name: "Total",
+          value: "28.02",
+          secondaryValue: "100 %",
+        },
+      ],
+    });
 
     // First bar of stacked bar series
     chartPathWithFillColor("#7172AD").eq(0).realHover();
-
-    testStackedTooltipRows([
-      ["Max of Subtotal", "98.82", "38.60 %"],
-      ["Max of Total", "102.77", "40.14 %"],
-      ["Average of Subtotal", "54.44", "21.26 %"],
-      ["Total", "256.03", "100 %"],
-    ]);
+    assertEChartsTooltip({
+      header: "2022",
+      rows: [
+        {
+          color: "#7172AD",
+          name: "Max of Subtotal",
+          value: "98.82",
+          secondaryValue: "38.60 %",
+        },
+        {
+          color: "#F9D45C",
+          name: "Max of Total",
+          value: "102.77",
+          secondaryValue: "40.14 %",
+        },
+        {
+          color: "#F2A86F",
+          name: "Average of Subtotal",
+          value: "54.44",
+          secondaryValue: "21.26 %",
+        },
+        {
+          name: "Total",
+          value: "256.03",
+          secondaryValue: "100 %",
+        },
+      ],
+    });
 
     // Switch to normalized stacking
     cy.findByTestId("chartsettings-sidebar").findByText("Stack - 100%").click();
diff --git a/e2e/test/scenarios/visualizations-charts/line-bar-tooltips.cy.spec.js b/e2e/test/scenarios/visualizations-charts/line-bar-tooltips.cy.spec.js
index 2f2c526560c690eefaac2bbe2223f3fa59f3ba17..c7e3009b7ffd068de7a4ea9a4ad7172ba426b250 100644
--- a/e2e/test/scenarios/visualizations-charts/line-bar-tooltips.cy.spec.js
+++ b/e2e/test/scenarios/visualizations-charts/line-bar-tooltips.cy.spec.js
@@ -8,11 +8,11 @@ import {
   cartesianChartCircle,
   chartPathWithFillColor,
   cartesianChartCircleWithColor,
-  testPairedTooltipValues,
-  testTooltipPairs,
-  popover,
   echartsTriggerBlur,
-  POPOVER_ELEMENT,
+  echartsTooltip,
+  tooltipHeader,
+  assertTooltipRow,
+  assertEChartsTooltip,
 } from "e2e/support/helpers";
 
 const { ORDERS, ORDERS_ID } = SAMPLE_DATABASE;
@@ -27,20 +27,26 @@ const SUM_OF_TOTAL = {
   display: "line",
 };
 
-function testSumTotalChange(tooltipSelector = showTooltipForCircleInSeries) {
+function testSumTotalChange(
+  tooltipSelector = showTooltipForCircleInSeries,
+  seriesName = "Sum of Total",
+) {
   tooltipSelector("#88BF4D", 0);
-  testTooltipPairs([
-    ["Created At", "2022"],
-    ["Sum of Total", "42,156.87"],
-  ]);
-  testTooltipExcludesText("Compared to previous year");
+  echartsTooltip().within(() => {
+    tooltipHeader("2022");
+    assertTooltipRow(seriesName, { color: "#88BF4D", value: "42,156.87" });
+  });
 
   tooltipSelector("#88BF4D", 1);
-  testTooltipPairs([
-    ["Created At", "2023"],
-    ["Sum of Total", "205,256.02"],
-    ["Compared to previous year", "+386.89%"],
-  ]);
+
+  echartsTooltip().within(() => {
+    tooltipHeader("2023");
+    assertTooltipRow(seriesName, {
+      color: "#88BF4D",
+      value: "205,256.02",
+      secondaryValue: "+386.89%",
+    });
+  });
 }
 
 const SUM_OF_TOTAL_MONTH = {
@@ -98,20 +104,28 @@ const AVG_OF_TOTAL = {
   display: "line",
 };
 
-function testAvgTotalChange(tooltipSelector = showTooltipForCircleInSeries) {
+function testAvgTotalChange(
+  tooltipSelector = showTooltipForCircleInSeries,
+  seriesName = "Average of Total",
+) {
   tooltipSelector("#A989C5", 0);
-  testTooltipPairs([
-    ["Created At", "2022"],
-    ["Average of Total", "56.66"],
-  ]);
-  testTooltipExcludesText("Compared to previous year");
+  echartsTooltip().within(() => {
+    tooltipHeader("2022");
+    assertTooltipRow(seriesName, {
+      color: "#A989C5",
+      value: "56.66",
+    });
+  });
 
   tooltipSelector("#A989C5", 1);
-  testTooltipPairs([
-    ["Created At", "2023"],
-    ["Average of Total", "56.86"],
-    ["Compared to previous year", "+0.34%"],
-  ]);
+  echartsTooltip().within(() => {
+    tooltipHeader("2022");
+    assertTooltipRow(seriesName, {
+      color: "#A989C5",
+      value: "56.86",
+      secondaryValue: "+0.34%",
+    });
+  });
 }
 
 const AVG_OF_TOTAL_CUM_SUM_QUANTITY = {
@@ -127,25 +141,33 @@ const AVG_OF_TOTAL_CUM_SUM_QUANTITY = {
   display: "line",
 };
 
-function testCumSumChange(testFirstTooltip = true) {
+function testCumSumChange(
+  testFirstTooltip = true,
+  seriesName = "Cumulative sum of Quantity",
+) {
   // In the multi series question with added question spec, this first circle
   // ends up hidden behind another circle, so we'll just skip it in that
   // specific spec
   if (testFirstTooltip) {
     showTooltipForCircleInSeries("#88BF4D", 0);
-    testTooltipPairs([
-      ["Created At", "2022"],
-      ["Cumulative sum of Quantity", "3,236"],
-    ]);
-    testTooltipExcludesText("Compared to previous year");
+    echartsTooltip().within(() => {
+      tooltipHeader("2022");
+      assertTooltipRow(seriesName, {
+        color: "#88BF4D",
+        value: "3,236",
+      });
+    });
   }
 
   showTooltipForCircleInSeries("#88BF4D", 1);
-  testTooltipPairs([
-    ["Created At", "2023"],
-    ["Cumulative sum of Quantity", "17,587"],
-    ["Compared to previous year", "+443.48%"],
-  ]);
+  echartsTooltip().within(() => {
+    tooltipHeader("2023");
+    assertTooltipRow(seriesName, {
+      color: "#88BF4D",
+      value: "17,587",
+      secondaryValue: "+443.48%",
+    });
+  });
 }
 
 const AVG_DISCOUNT_SUM_DISCOUNT = {
@@ -161,36 +183,46 @@ const AVG_DISCOUNT_SUM_DISCOUNT = {
   display: "line",
 };
 
-function testAvgDiscountChange() {
+function testAvgDiscountChange(seriesName = "Average of Discount") {
   showTooltipForCircleInSeries("#509EE3", 0);
-  testTooltipPairs([
-    ["Created At", "2022"],
-    ["Average of Discount", "5.03"],
-  ]);
-  testTooltipExcludesText("Compared to previous year");
+  echartsTooltip().within(() => {
+    tooltipHeader("2022");
+    assertTooltipRow(seriesName, {
+      color: "#509EE3",
+      value: "5.03",
+    });
+  });
 
   showTooltipForCircleInSeries("#509EE3", 1);
-  testTooltipPairs([
-    ["Created At", "2023"],
-    ["Average of Discount", "5.41"],
-    ["Compared to previous year", "+7.54%"],
-  ]);
+  echartsTooltip().within(() => {
+    tooltipHeader("2023");
+    assertTooltipRow(seriesName, {
+      color: "#509EE3",
+      value: "5.41",
+      secondaryValue: "+7.54%",
+    });
+  });
 }
 
-function testSumDiscountChange() {
+function testSumDiscountChange(seriesName = "Sum of Discount") {
   showTooltipForCircleInSeries("#98D9D9", 0);
-  testTooltipPairs([
-    ["Created At", "2022"],
-    ["Sum of Discount", "342.09"],
-  ]);
-  testTooltipExcludesText("Compared to previous year");
+  echartsTooltip().within(() => {
+    tooltipHeader("2022");
+    assertTooltipRow(seriesName, {
+      color: "#98D9D9",
+      value: "342.09",
+    });
+  });
 
   showTooltipForCircleInSeries("#98D9D9", 1);
-  testTooltipPairs([
-    ["Created At", "2023"],
-    ["Sum of Discount", "1,953.08"],
-    ["Compared to previous year", "+470.93%"],
-  ]);
+  echartsTooltip().within(() => {
+    tooltipHeader("2023");
+    assertTooltipRow(seriesName, {
+      color: "#98D9D9",
+      value: "1,953.08",
+      secondaryValue: "+470.93%",
+    });
+  });
 }
 
 describe("scenarios > visualizations > line/bar chart > tooltips", () => {
@@ -209,27 +241,26 @@ describe("scenarios > visualizations > line/bar chart > tooltips", () => {
     });
 
     it("should show updated column titles in tooltips after editing them via Visualization Options", () => {
-      const originalTooltipText = [
-        ["Created At", "2022"],
-        ["Sum of Total", "42,156.87"],
-      ];
-
-      const updatedTooltipText = [
-        ["Created At", "2022"],
-        ["Custom", "42,156.87"],
-      ];
+      const originalName = "Sum of Total";
+      const customName = "Custom";
 
       cartesianChartCircle().first().realHover();
-      testTooltipPairs(originalTooltipText);
+      assertEChartsTooltip({
+        header: "2022",
+        rows: [{ name: originalName, value: "42,156.87" }],
+      });
 
       openDashCardVisualizationOptions();
 
-      updateColumnTitle(originalTooltipText[1][0], updatedTooltipText[1][0]);
+      updateColumnTitle(originalName, customName);
 
       saveDashCardVisualizationOptions();
 
       cartesianChartCircle().first().realHover();
-      testTooltipPairs(updatedTooltipText);
+      assertEChartsTooltip({
+        header: "2022",
+        rows: [{ name: customName, value: "42,156.87" }],
+      });
     });
 
     it("should show percent change in tooltip for timeseries axis", () => {
@@ -248,47 +279,66 @@ describe("scenarios > visualizations > line/bar chart > tooltips", () => {
     });
 
     it("should show updated column titles in tooltips after editing them via Visualization Options", () => {
-      const originalSeriesTooltipText = [
-        ["Created At", "2022"],
-        ["Sum of Total", "42,156.87"],
-      ];
-      const updatedOriginalSeriesTooltipText = [
-        ["Created At", "2022"],
-        ["Custom Q1", "42,156.87"],
-      ];
-
-      const addedSeriesTooltipText = [
-        ["Created At", "2022"],
-        ["Average of Total", "56.66"],
-      ];
-      const updatedAddedSeriesTooltipText = [
-        ["Created At", "2022"],
-        ["Custom Q2", "56.66"],
-      ];
+      const originalSeriesName = "Q1";
+      const updatedOriginalSeriesName = "Custom Q1";
+      const addedSeriesName = "Q2";
+      const updatedAddedSeriesName = "Custom Q2";
 
       showTooltipForCircleInSeries("#88BF4D");
-      testTooltipPairs(originalSeriesTooltipText);
+      assertEChartsTooltip({
+        header: "2022",
+        rows: [
+          { color: "#88BF4D", name: originalSeriesName, value: "42,156.87" },
+        ],
+      });
 
       showTooltipForCircleInSeries("#A989C5");
-      testTooltipPairs(addedSeriesTooltipText);
+      assertEChartsTooltip({
+        header: "2022",
+        rows: [
+          {
+            color: "#A989C5",
+            name: addedSeriesName,
+            value: "56.66",
+          },
+        ],
+      });
 
       openDashCardVisualizationOptions();
 
-      updateColumnTitle("Q1", updatedOriginalSeriesTooltipText[1][0]);
-      updateColumnTitle("Q2", updatedAddedSeriesTooltipText[1][0]);
+      updateColumnTitle("Q1", updatedOriginalSeriesName);
+      updateColumnTitle("Q2", updatedAddedSeriesName);
 
       saveDashCardVisualizationOptions();
 
       showTooltipForCircleInSeries("#88BF4D");
-      testTooltipPairs(updatedOriginalSeriesTooltipText);
+      assertEChartsTooltip({
+        header: "2022",
+        rows: [
+          {
+            color: "#88BF4D",
+            name: updatedOriginalSeriesName,
+            value: "42,156.87",
+          },
+        ],
+      });
 
       showTooltipForCircleInSeries("#A989C5");
-      testTooltipPairs(updatedAddedSeriesTooltipText);
+      assertEChartsTooltip({
+        header: "2022",
+        rows: [
+          {
+            color: "#A989C5",
+            name: updatedAddedSeriesName,
+            value: "56.66",
+          },
+        ],
+      });
     });
 
     it("should show percent change in tooltip for timeseries axis", () => {
-      testSumTotalChange();
-      testAvgTotalChange();
+      testSumTotalChange(showTooltipForCircleInSeries, "Q1");
+      testAvgTotalChange(showTooltipForCircleInSeries, "Q2");
     });
   });
 
@@ -302,30 +352,51 @@ describe("scenarios > visualizations > line/bar chart > tooltips", () => {
     });
 
     it("should show updated column titles in tooltips after editing them via Visualization Options", () => {
-      const originalTooltipText = [
-        ["Created At", "2022"],
-        ["Average of Total", "56.66"],
-        ["Cumulative sum of Quantity", "3,236"],
-      ];
-
-      const updatedTooltipText = [
-        ["Created At", "2022"],
-        ["Custom 1", "56.66"],
-        ["Custom 2", "3,236"],
-      ];
+      const originalAvgSeriesName = "Average of Total";
+      const originalCumSumSeriesName = "Cumulative sum of Quantity";
+      const customAvgSeriesName = "Custom 1";
+      const customCumSumSeriesName = "Custom 2";
 
       cartesianChartCircle().first().realHover();
-      testTooltipPairs(originalTooltipText);
+      assertEChartsTooltip({
+        header: "2022",
+        rows: [
+          {
+            color: "#A989C5",
+            name: originalAvgSeriesName,
+            value: "56.66",
+          },
+          {
+            color: "#88BF4D",
+            name: originalCumSumSeriesName,
+            value: "3,236",
+          },
+        ],
+      });
 
       openDashCardVisualizationOptions();
 
-      updateColumnTitle(originalTooltipText[1][0], updatedTooltipText[1][0]);
-      updateColumnTitle(originalTooltipText[2][0], updatedTooltipText[2][0]);
+      updateColumnTitle(originalAvgSeriesName, customAvgSeriesName);
+      updateColumnTitle(originalCumSumSeriesName, customCumSumSeriesName);
 
       saveDashCardVisualizationOptions();
 
       cartesianChartCircle().first().realHover();
-      testTooltipPairs(updatedTooltipText);
+      assertEChartsTooltip({
+        header: "2022",
+        rows: [
+          {
+            color: "#A989C5",
+            name: customAvgSeriesName,
+            value: "56.66",
+          },
+          {
+            color: "#88BF4D",
+            name: customCumSumSeriesName,
+            value: "3,236",
+          },
+        ],
+      });
     });
 
     it("should show percent change in tooltip for timeseries axis", () => {
@@ -347,77 +418,95 @@ describe("scenarios > visualizations > line/bar chart > tooltips", () => {
     it("should show updated column titles in tooltips after editing them via Visualization Options", () => {
       // Checking the second datum since the first circle of one series is covered with a circle from the other series
       const circleIndex = 1;
-      const originalSeriesColors = ["#A989C5", "#88BF4D"];
-      const addedSeriesColors = ["#98D9D9", "#509EE3"];
-      const originalSeriesTooltipText = [
-        ["Created At", "2023"],
-        ["Average of Total", "56.86"],
-        ["Cumulative sum of Quantity", "17,587"],
-      ];
-      const updatedOriginalSeriesTooltipText = [
-        ["Created At", "2023"],
-        ["Q1 Custom 1", "56.86"],
-        ["Q1 Custom 2", "17,587"],
-      ];
-
-      const addedSeriesTooltipText = [
-        ["Created At", "2023"],
-        ["Average of Discount", "5.41"],
-        ["Sum of Discount", "1,953.08"],
-      ];
-      const updatedAddedSeriesTooltipText = [
-        ["Created At", "2023"],
-        ["Q2 Custom 1", "5.41"],
-        ["Q2 Custom 2", "1,953.08"],
-      ];
-
-      originalSeriesColors.forEach(color => {
-        showTooltipForCircleInSeries(color, circleIndex);
-        testTooltipPairs(originalSeriesTooltipText);
-      });
 
-      addedSeriesColors.forEach(color => {
+      const originalSeriesColors = ["#A989C5", "#88BF4D"];
+      const addedSeriesColors = ["#509EE3", "#98D9D9"];
+      const originalAvgSeriesName = "Q1: Average of Total";
+      const originalCumSumSeriesName = "Q1: Cumulative sum of Quantity";
+      const updatedOriginalAvgSeriesName = "Q1 Custom 1";
+      const updatedOriginalCumSumSeriesName = "Q1 Custom 2";
+      const addedAvgSeriesName = "Q2: Average of Discount";
+      const addedSumSeriesName = "Q2: Sum of Discount";
+      const updatedAddedAvgSeriesName = "Q2 Custom 1";
+      const updatedAddedSumSeriesName = "Q2 Custom 2";
+
+      [...originalSeriesColors, ...addedSeriesColors].forEach(color => {
         showTooltipForCircleInSeries(color, circleIndex);
-        testTooltipPairs(addedSeriesTooltipText);
+        assertEChartsTooltip({
+          header: "2023",
+          rows: [
+            {
+              color: originalSeriesColors[0],
+              name: originalAvgSeriesName,
+              value: "56.86",
+            },
+            {
+              color: originalSeriesColors[1],
+              name: originalCumSumSeriesName,
+              value: "17,587",
+            },
+            {
+              color: addedSeriesColors[0],
+              name: addedAvgSeriesName,
+              value: "5.41",
+            },
+            {
+              color: addedSeriesColors[1],
+              name: addedSumSeriesName,
+              value: "1,953.08",
+            },
+          ],
+        });
       });
 
       openDashCardVisualizationOptions();
 
+      updateColumnTitle(originalAvgSeriesName, updatedOriginalAvgSeriesName);
       updateColumnTitle(
-        `Q1: ${originalSeriesTooltipText[1][0]}`,
-        updatedOriginalSeriesTooltipText[1][0],
-      );
-      updateColumnTitle(
-        `Q1: ${originalSeriesTooltipText[2][0]}`,
-        updatedOriginalSeriesTooltipText[2][0],
+        originalCumSumSeriesName,
+        updatedOriginalCumSumSeriesName,
       );
 
-      updateColumnTitle(
-        `Q2: ${addedSeriesTooltipText[1][0]}`,
-        updatedAddedSeriesTooltipText[1][0],
-      );
-      updateColumnTitle(
-        `Q2: ${addedSeriesTooltipText[2][0]}`,
-        updatedAddedSeriesTooltipText[2][0],
-      );
+      updateColumnTitle(addedAvgSeriesName, updatedAddedAvgSeriesName);
+      updateColumnTitle(addedSumSeriesName, updatedAddedSumSeriesName);
 
       saveDashCardVisualizationOptions();
 
-      originalSeriesColors.forEach(color => {
+      [...originalSeriesColors, ...addedSeriesColors].forEach(color => {
         showTooltipForCircleInSeries(color, circleIndex);
-        testTooltipPairs(updatedOriginalSeriesTooltipText);
-      });
-      addedSeriesColors.forEach(color => {
-        showTooltipForCircleInSeries(color, circleIndex);
-        testTooltipPairs(updatedAddedSeriesTooltipText);
+        assertEChartsTooltip({
+          header: "2023",
+          rows: [
+            {
+              color: originalSeriesColors[0],
+              name: updatedOriginalAvgSeriesName,
+              value: "56.86",
+            },
+            {
+              color: originalSeriesColors[1],
+              name: updatedOriginalCumSumSeriesName,
+              value: "17,587",
+            },
+            {
+              color: addedSeriesColors[0],
+              name: updatedAddedAvgSeriesName,
+              value: "5.41",
+            },
+            {
+              color: addedSeriesColors[1],
+              name: updatedAddedSumSeriesName,
+              value: "1,953.08",
+            },
+          ],
+        });
       });
     });
 
     it("should show percent change in tooltip for timeseries axis", () => {
-      testAvgTotalChange();
-      testCumSumChange(false);
-      testAvgDiscountChange();
-      testSumDiscountChange();
+      testAvgTotalChange(showTooltipForCircleInSeries, "Q1: Average of Total");
+      testCumSumChange(false, "Q1: Cumulative sum of Quantity");
+      testAvgDiscountChange("Q2: Average of Discount");
+      testSumDiscountChange("Q2: Sum of Discount");
     });
   });
 
@@ -431,27 +520,38 @@ describe("scenarios > visualizations > line/bar chart > tooltips", () => {
     });
 
     it("should show updated column titles in tooltips after editing them via Visualization Options", () => {
-      const originalTooltipText = [
-        ["Created At", "2022"],
-        ["Sum of Total", "42,156.87"],
-      ];
-
-      const updatedTooltipText = [
-        ["Created At", "2022"],
-        ["Custom", "42,156.87"],
-      ];
+      const originalName = "Sum of Total";
+      const updatedName = "Custom";
 
       chartPathWithFillColor("#88BF4D").first().realHover();
-      testTooltipPairs(originalTooltipText);
+      assertEChartsTooltip({
+        header: "2022",
+        rows: [
+          {
+            color: "#88BF4D",
+            name: originalName,
+            value: "42,156.87",
+          },
+        ],
+      });
 
       openDashCardVisualizationOptions();
 
-      updateColumnTitle(originalTooltipText[1][0], updatedTooltipText[1][0]);
+      updateColumnTitle(originalName, updatedName);
 
       saveDashCardVisualizationOptions();
 
       chartPathWithFillColor("#88BF4D").first().realHover();
-      testTooltipPairs(updatedTooltipText);
+      assertEChartsTooltip({
+        header: "2022",
+        rows: [
+          {
+            color: "#88BF4D",
+            name: updatedName,
+            value: "42,156.87",
+          },
+        ],
+      });
     });
 
     it("should show percent change in tooltip for timeseries axis", () => {
@@ -472,47 +572,70 @@ describe("scenarios > visualizations > line/bar chart > tooltips", () => {
     it("should show updated column titles in tooltips after editing them via Visualization Options", () => {
       const originalSeriesColor = "#88BF4D";
       const addedSeriesColor = "#A989C5";
-      const originalSeriesTooltipText = [
-        ["Created At", "2022"],
-        ["Sum of Total", "42,156.87"],
-      ];
-      const updatedOriginalSeriesTooltipText = [
-        ["Created At", "2022"],
-        ["Custom Q1", "42,156.87"],
-      ];
-
-      const addedSeriesTooltipText = [
-        ["Created At", "2022"],
-        ["Average of Total", "56.66"],
-      ];
-      const updatedAddedSeriesTooltipText = [
-        ["Created At", "2022"],
-        ["Custom Q2", "56.66"],
-      ];
+      const originalSeriesName = "Q1";
+      const updatedOriginalSeriesName = "Custom Q1";
+      const addedSeriesName = "Q2";
+      const updatedAddedSeriesName = "Custom Q2";
 
       showTooltipForBarInSeries(originalSeriesColor, 0);
-      testTooltipPairs(originalSeriesTooltipText);
+      assertEChartsTooltip({
+        header: "2022",
+        rows: [
+          {
+            color: "#88BF4D",
+            name: originalSeriesName,
+            value: "42,156.87",
+          },
+        ],
+      });
 
       showTooltipForBarInSeries(addedSeriesColor, 0);
-      testTooltipPairs(addedSeriesTooltipText);
+      assertEChartsTooltip({
+        header: "2022",
+        rows: [
+          {
+            color: "#A989C5",
+            name: addedSeriesName,
+            value: "56.66",
+          },
+        ],
+      });
 
       openDashCardVisualizationOptions();
 
-      updateColumnTitle("Q1", updatedOriginalSeriesTooltipText[1][0]);
-      updateColumnTitle("Q2", updatedAddedSeriesTooltipText[1][0]);
+      updateColumnTitle(originalSeriesName, updatedOriginalSeriesName);
+      updateColumnTitle(addedSeriesName, updatedAddedSeriesName);
 
       saveDashCardVisualizationOptions();
 
       showTooltipForBarInSeries(originalSeriesColor, 0);
-      testTooltipPairs(updatedOriginalSeriesTooltipText);
+      assertEChartsTooltip({
+        header: "2022",
+        rows: [
+          {
+            color: "#88BF4D",
+            name: updatedOriginalSeriesName,
+            value: "42,156.87",
+          },
+        ],
+      });
 
       showTooltipForBarInSeries(addedSeriesColor, 0);
-      testTooltipPairs(updatedAddedSeriesTooltipText);
+      assertEChartsTooltip({
+        header: "2022",
+        rows: [
+          {
+            color: "#A989C5",
+            name: updatedAddedSeriesName,
+            value: "56.66",
+          },
+        ],
+      });
     });
 
     it("should show percent change in tooltip for timeseries axis", () => {
-      testSumTotalChange(showTooltipForBarInSeries);
-      testAvgTotalChange(showTooltipForBarInSeries);
+      testSumTotalChange(showTooltipForBarInSeries, "Q1");
+      testAvgTotalChange(showTooltipForBarInSeries, "Q2");
     });
   });
 
@@ -525,18 +648,30 @@ describe("scenarios > visualizations > line/bar chart > tooltips", () => {
       });
 
       showTooltipForCircleInSeries("#88BF4D", 0);
-      testTooltipPairs([
-        ["Created At", "April 2022"],
-        ["Sum of Total", "52.76"],
-      ]);
+      assertEChartsTooltip({
+        header: "April 2022",
+        rows: [
+          {
+            color: "#88BF4D",
+            name: "Sum of Total",
+            value: "52.76",
+          },
+        ],
+      });
       testTooltipExcludesText("Compared to previous month");
 
       showTooltipForCircleInSeries("#88BF4D", 1);
-      testTooltipPairs([
-        ["Created At", "May 2022"],
-        ["Sum of Total", "1,265.72"],
-        ["Compared to previous month", "+2,299.19%"],
-      ]);
+      assertEChartsTooltip({
+        header: "May 2022",
+        rows: [
+          {
+            color: "#88BF4D",
+            name: "Sum of Total",
+            value: "1,265.72",
+            secondaryValue: "+2,299.19%",
+          },
+        ],
+      });
     });
 
     it("should not show percent change when previous month is missing from result data", () => {
@@ -547,30 +682,54 @@ describe("scenarios > visualizations > line/bar chart > tooltips", () => {
       });
 
       showTooltipForCircleInSeries("#88BF4D", 0);
-      testTooltipPairs([
-        ["Created At", "April 2022"],
-        ["Sum of Total", "52.76"],
-      ]);
+      assertEChartsTooltip({
+        header: "April 2022",
+        rows: [
+          {
+            color: "#88BF4D",
+            name: "Sum of Total",
+            value: "52.76",
+          },
+        ],
+      });
       testTooltipExcludesText("Compared to previous month");
       showTooltipForCircleInSeries("#88BF4D", 1);
-      testTooltipPairs([
-        ["Created At", "June 2022"],
-        ["Sum of Total", "2,072.94"],
-      ]);
+      assertEChartsTooltip({
+        header: "June 2022",
+        rows: [
+          {
+            color: "#88BF4D",
+            name: "Sum of Total",
+            value: "2,072.94",
+          },
+        ],
+      });
       testTooltipExcludesText("Compared to previous month");
 
       showTooltipForCircleInSeries("#88BF4D", 2);
-      testTooltipPairs([
-        ["Created At", "July 2022"],
-        ["Sum of Total", "3,734.69"],
-        ["Compared to previous month", "+80.16%"],
-      ]);
+      assertEChartsTooltip({
+        header: "July 2022",
+        rows: [
+          {
+            color: "#88BF4D",
+            name: "Sum of Total",
+            value: "3,734.69",
+            secondaryValue: "+80.16%",
+          },
+        ],
+      });
 
       showTooltipForCircleInSeries("#88BF4D", 3);
-      testTooltipPairs([
-        ["Created At", "September 2022"],
-        ["Sum of Total", "5,372.08"],
-      ]);
+      assertEChartsTooltip({
+        header: "September 2022",
+        rows: [
+          {
+            color: "#88BF4D",
+            name: "Sum of Total",
+            value: "5,372.08",
+          },
+        ],
+      });
       testTooltipExcludesText("Compared to previous month");
     });
 
@@ -582,17 +741,30 @@ describe("scenarios > visualizations > line/bar chart > tooltips", () => {
       });
 
       showTooltipForCircleInSeries("#88BF4D", 0);
-      testTooltipPairs([
-        ["Created At", "April 2022"],
-        ["Sum of Total", "52.76"],
-      ]);
+      assertEChartsTooltip({
+        header: "April 2022",
+        rows: [
+          {
+            color: "#88BF4D",
+            name: "Sum of Total",
+            value: "52.76",
+          },
+        ],
+      });
       testTooltipExcludesText("Compared to previous month");
 
       showTooltipForCircleInSeries("#88BF4D", 1);
-      testTooltipPairs([
-        ["Created At", "May 2022"],
-        ["Sum of Total", "1,265.72"],
-      ]);
+      assertEChartsTooltip({
+        header: "May 2022",
+        rows: [
+          {
+            color: "#88BF4D",
+            name: "Sum of Total",
+            value: "1,265.72",
+          },
+        ],
+      });
+
       testTooltipExcludesText("Compared to previous month");
     });
   });
@@ -663,7 +835,15 @@ describe("scenarios > visualizations > line/bar chart > tooltips", () => {
           testTooltipExcludesText("Compared to previous");
           return;
         }
-        testPairedTooltipValues("Compared to previous month", change);
+        assertEChartsTooltip({
+          rows: [
+            {
+              color: "#88BF4D",
+              name: "Sum of Total",
+              secondaryValue: change,
+            },
+          ],
+        });
       });
     });
 
@@ -678,7 +858,16 @@ describe("scenarios > visualizations > line/bar chart > tooltips", () => {
           testTooltipExcludesText("Compared to previous");
           return;
         }
-        testPairedTooltipValues("Compared to previous week", change);
+
+        assertEChartsTooltip({
+          rows: [
+            {
+              color: "#88BF4D",
+              name: "Sum of Total",
+              secondaryValue: change,
+            },
+          ],
+        });
       });
     });
 
@@ -693,7 +882,15 @@ describe("scenarios > visualizations > line/bar chart > tooltips", () => {
           testTooltipExcludesText("Compared to previous");
           return;
         }
-        testPairedTooltipValues("Compared to previous day", change);
+        assertEChartsTooltip({
+          rows: [
+            {
+              color: "#88BF4D",
+              name: "Sum of Total",
+              secondaryValue: change,
+            },
+          ],
+        });
       });
     });
   });
@@ -728,27 +925,23 @@ function setupDashboard(cardId, addedSeriesCardId) {
     });
   });
 }
-
 function resetHoverState() {
   echartsTriggerBlur();
-  cy.get(POPOVER_ELEMENT).should("not.exist");
   cy.wait(50);
 }
 
 function showTooltipForCircleInSeries(seriesColor, index = 0) {
   resetHoverState();
-  cy.get(POPOVER_ELEMENT).should("not.exist");
   cartesianChartCircleWithColor(seriesColor).eq(index).realHover();
 }
 
 function showTooltipForBarInSeries(seriesColor, index = 0) {
   resetHoverState();
-  cy.get(POPOVER_ELEMENT).should("not.exist");
   chartPathWithFillColor(seriesColor).eq(index).realHover();
 }
 
 function testTooltipExcludesText(text) {
-  popover().within(() => {
+  echartsTooltip().within(() => {
     cy.contains(text).should("not.exist");
   });
 }
diff --git a/e2e/test/scenarios/visualizations-charts/line_chart.cy.spec.js b/e2e/test/scenarios/visualizations-charts/line_chart.cy.spec.js
index cf5f7f61cac24905beffce06c1c88e5cedc50c1a..c2d8a3adb2fe1bc54959327e5f8cd8037bf0f166 100644
--- a/e2e/test/scenarios/visualizations-charts/line_chart.cy.spec.js
+++ b/e2e/test/scenarios/visualizations-charts/line_chart.cy.spec.js
@@ -14,7 +14,7 @@ import {
   cartesianChartCircleWithColor,
   cartesianChartCircle,
   trendLine,
-  testPairedTooltipValues,
+  assertEChartsTooltip,
 } from "e2e/support/helpers";
 
 const { ORDERS, ORDERS_ID, PRODUCTS, PRODUCTS_ID, PEOPLE, PEOPLE_ID } =
@@ -286,11 +286,25 @@ describe("scenarios > visualizations > line chart", () => {
     });
 
     cartesianChartCircleWithColor("#509EE3").eq(3).realHover();
-    popover().within(() => {
-      testPairedTooltipValues("Product → Rating", "2.7");
-      testPairedTooltipValues("Count", "191");
-      testPairedTooltipValues("Sum of Total", "14,747.05");
-      testPairedTooltipValues("Average of Quantity", "4.3");
+    assertEChartsTooltip({
+      header: "2.7",
+      rows: [
+        {
+          color: "#509EE3",
+          name: "Count",
+          value: "191",
+        },
+        {
+          color: "#88BF4D",
+          name: "Sum of Total",
+          value: "14,747.05",
+        },
+        {
+          color: "#A989C5",
+          name: "Average of Quantity",
+          value: "4.3",
+        },
+      ],
     });
   });
 
@@ -562,15 +576,20 @@ describe("scenarios > visualizations > line chart", () => {
             assertOnYAxisValues();
 
             showTooltipForFirstCircleInSeries("#88BF4D");
-            popover().within(() => {
-              testPairedTooltipValues("Created At", "2022");
-              testPairedTooltipValues(RENAMED_FIRST_SERIES, "42,156.87");
-            });
-
-            showTooltipForFirstCircleInSeries("#98D9D9");
-            popover().within(() => {
-              testPairedTooltipValues("Created At", "2022");
-              testPairedTooltipValues(RENAMED_SECOND_SERIES, "54.44");
+            assertEChartsTooltip({
+              header: "2022",
+              rows: [
+                {
+                  color: "#88BF4D",
+                  name: RENAMED_FIRST_SERIES,
+                  value: "42,156.87",
+                },
+                {
+                  color: "#98D9D9",
+                  name: RENAMED_SECOND_SERIES,
+                  value: "54.44",
+                },
+              ],
             });
           });
         });
@@ -611,15 +630,20 @@ describe("scenarios > visualizations > line chart", () => {
             assertOnYAxisValues();
 
             showTooltipForFirstCircleInSeries("#88BF4D");
-            popover().within(() => {
-              testPairedTooltipValues("Created At", "2022");
-              testPairedTooltipValues(RENAMED_FIRST_SERIES, "42,156.87");
-            });
-
-            showTooltipForFirstCircleInSeries("#509EE3");
-            popover().within(() => {
-              testPairedTooltipValues("Created At", "2022");
-              testPairedTooltipValues(RENAMED_SECOND_SERIES, "2,829.03");
+            assertEChartsTooltip({
+              header: "2022",
+              rows: [
+                {
+                  color: "#88BF4D",
+                  name: RENAMED_FIRST_SERIES,
+                  value: "42,156.87",
+                },
+                {
+                  color: "#509EE3",
+                  name: RENAMED_SECOND_SERIES,
+                  value: "2,829.03",
+                },
+              ],
             });
           });
         });
diff --git a/e2e/test/scenarios/visualizations-charts/scatter.cy.spec.js b/e2e/test/scenarios/visualizations-charts/scatter.cy.spec.js
index 483cfba50ebdb15b78ea1cf9e22d389a48f209fe..0a747efea8cdd63ef54796b7b742400c7445e51a 100644
--- a/e2e/test/scenarios/visualizations-charts/scatter.cy.spec.js
+++ b/e2e/test/scenarios/visualizations-charts/scatter.cy.spec.js
@@ -3,8 +3,8 @@ import { SAMPLE_DATABASE } from "e2e/support/cypress_sample_database";
 import {
   restore,
   visitQuestionAdhoc,
-  popover,
   cartesianChartCircle,
+  assertEChartsTooltip,
 } from "e2e/support/helpers";
 
 const { ORDERS, ORDERS_ID, PRODUCTS } = SAMPLE_DATABASE;
@@ -42,10 +42,21 @@ describe("scenarios > visualizations > scatter", () => {
     });
 
     triggerPopoverForBubble();
-    popover().within(() => {
-      cy.findByText("Created At:");
-      cy.findByText("Count:");
-      cy.findByText(/Distinct values of Products? → ID:/);
+    assertEChartsTooltip({
+      rows: [
+        {
+          name: "Created At",
+          value: "May 2023",
+        },
+        {
+          name: "Count",
+          value: "271",
+        },
+        {
+          name: "Distinct values of Product → ID",
+          value: "137",
+        },
+      ],
     });
   });
 
@@ -68,10 +79,21 @@ describe("scenarios > visualizations > scatter", () => {
     });
 
     triggerPopoverForBubble();
-    popover().within(() => {
-      cy.findByText("Created At:");
-      cy.findByText("Orders count:");
-      cy.findByText("Products count:");
+    assertEChartsTooltip({
+      rows: [
+        {
+          name: "Created At",
+          value: "May 2023",
+        },
+        {
+          name: "Orders count",
+          value: "271",
+        },
+        {
+          name: "Products count",
+          value: "137",
+        },
+      ],
     });
   });
 
diff --git a/e2e/test/scenarios/visualizations-charts/visualizations-charts-reproductions.cy.spec.js b/e2e/test/scenarios/visualizations-charts/visualizations-charts-reproductions.cy.spec.js
index 147ee740a7b03e2f27aaa99475fe85e183564b2a..f3a9fc3be4edf35b3d00586477170ffc22cb5bbe 100644
--- a/e2e/test/scenarios/visualizations-charts/visualizations-charts-reproductions.cy.spec.js
+++ b/e2e/test/scenarios/visualizations-charts/visualizations-charts-reproductions.cy.spec.js
@@ -30,6 +30,7 @@ import {
   selectFilterOperator,
   saveSavedQuestion,
   runNativeQuery,
+  assertEChartsTooltip,
 } from "e2e/support/helpers";
 
 const { ORDERS, ORDERS_ID } = SAMPLE_DATABASE;
@@ -129,9 +130,14 @@ describe("issue 16170", { tags: "@mongo" }, () => {
 
       cartesianChartCircle().eq(-2).trigger("mousemove");
 
-      popover().within(() => {
-        testPairedTooltipValues("Created At", "2019");
-        testPairedTooltipValues("Count", "6,524");
+      assertEChartsTooltip({
+        header: "2019",
+        rows: [
+          {
+            name: "Count",
+            value: "6,524",
+          },
+        ],
       });
     });
   });
@@ -559,9 +565,15 @@ describe("issue 21452", () => {
 
     cartesianChartCircle().first().realHover();
 
-    popover().within(() => {
-      testPairedTooltipValues("Created At", "2022");
-      testPairedTooltipValues("Foo", "3,236");
+    assertEChartsTooltip({
+      header: "2022",
+      rows: [
+        {
+          color: "#88BF4D",
+          name: "Foo",
+          value: "3,236",
+        },
+      ],
     });
 
     cy.get("@dataset.all").should("have.length", 1);
@@ -853,17 +865,58 @@ describe("issue 27279", () => {
 
     // Extra step, just to be overly cautious
     chartPathWithFillColor("#98D9D9").realHover();
-    popover().within(() => {
-      testPairedTooltipValues("K", "F2021");
-      testPairedTooltipValues("O", "-3");
-      testPairedTooltipValues("Sum of V", "1");
+
+    assertEChartsTooltip({
+      header: "F2021",
+      rows: [
+        {
+          color: "#98D9D9",
+          name: "-3",
+          value: "1",
+        },
+        {
+          color: "#F2A86F",
+          name: "-2",
+          value: "(empty)",
+        },
+        {
+          color: "#F9D45C",
+          name: "-1",
+          value: "(empty)",
+        },
+        {
+          color: "#509EE3",
+          name: "0",
+          value: "(empty)",
+        },
+      ],
     });
 
     chartPathWithFillColor("#509EE3").realHover();
-    popover().within(() => {
-      testPairedTooltipValues("K", "F2022");
-      testPairedTooltipValues("O", "0");
-      testPairedTooltipValues("Sum of V", "4");
+    assertEChartsTooltip({
+      header: "F2022",
+      rows: [
+        {
+          color: "#98D9D9",
+          name: "-3",
+          value: "(empty)",
+        },
+        {
+          color: "#F2A86F",
+          name: "-2",
+          value: "(empty)",
+        },
+        {
+          color: "#F9D45C",
+          name: "-1",
+          value: "(empty)",
+        },
+        {
+          color: "#509EE3",
+          name: "0",
+          value: "4",
+        },
+      ],
     });
   });
 });
diff --git a/e2e/test/scenarios/visualizations-charts/waterfall.cy.spec.js b/e2e/test/scenarios/visualizations-charts/waterfall.cy.spec.js
index 1b9b8ceced7bee93fc15f342cea74bb9c19a8fc1..e128f7b88a9819fdad0dddc66201c56f110bedb5 100644
--- a/e2e/test/scenarios/visualizations-charts/waterfall.cy.spec.js
+++ b/e2e/test/scenarios/visualizations-charts/waterfall.cy.spec.js
@@ -9,7 +9,7 @@ import {
   summarize,
   echartsContainer,
   chartPathWithFillColor,
-  testPairedTooltipValues,
+  assertEChartsTooltip,
 } from "e2e/support/helpers";
 
 const { ORDERS, ORDERS_ID, PRODUCTS } = SAMPLE_DATABASE;
@@ -303,7 +303,18 @@ describe("scenarios > visualizations > waterfall", () => {
 
     chartPathWithFillColor("#88BF4D").first().trigger("mousemove");
 
-    testPairedTooltipValues("C2:", "0.2");
+    assertEChartsTooltip({
+      rows: [
+        {
+          name: "C1",
+          value: "a",
+        },
+        {
+          name: "C2",
+          value: "0.2",
+        },
+      ],
+    });
   });
 
   describe("scenarios > visualizations > waterfall settings", () => {
diff --git a/e2e/test/scenarios/visualizations-tabular/drillthroughs/chart_drill.cy.spec.js b/e2e/test/scenarios/visualizations-tabular/drillthroughs/chart_drill.cy.spec.js
index 96a8391236d4c49131094971768e0769873016eb..353dd089dc516abf0c89ca25b140b7c28824ad68 100644
--- a/e2e/test/scenarios/visualizations-tabular/drillthroughs/chart_drill.cy.spec.js
+++ b/e2e/test/scenarios/visualizations-tabular/drillthroughs/chart_drill.cy.spec.js
@@ -21,6 +21,8 @@ import {
   entityPickerModalTab,
   tableHeaderClick,
   pieSliceWithColor,
+  assertEChartsTooltip,
+  echartsTriggerBlur,
 } from "e2e/support/helpers";
 
 const { ORDERS, ORDERS_ID, PRODUCTS, PRODUCTS_ID, PEOPLE, PEOPLE_ID } =
@@ -395,19 +397,29 @@ describe("scenarios > visualizations > drillthroughs > chart drill", () => {
     );
 
     cartesianChartCircle().eq(0).realHover();
-    popover().within(() => {
-      cy.findByText("January 1, 2026");
-      cy.findByText("10");
+    assertEChartsTooltip({
+      header: "January 1, 2026",
+      rows: [
+        {
+          color: "#EF8C8C",
+          name: "c",
+          value: "10",
+        },
+      ],
     });
 
-    queryBuilderMain()
-      .findByText("This question is written in SQL.")
-      .realHover();
+    echartsTriggerBlur();
 
     cartesianChartCircle().eq(1).realHover();
-    popover().within(() => {
-      cy.findByText("January 2, 2026");
-      cy.findByText("5");
+    assertEChartsTooltip({
+      header: "January 2, 2026",
+      rows: [
+        {
+          color: "#EF8C8C",
+          name: "c",
+          value: "5",
+        },
+      ],
     });
   });
 
@@ -429,7 +441,21 @@ describe("scenarios > visualizations > drillthroughs > chart drill", () => {
     });
 
     chartPathWithFillColor("#7172AD").first().trigger("mousemove");
-    popover().findByText("12");
+    assertEChartsTooltip({
+      header: "2",
+      rows: [
+        {
+          color: "#88BF4D",
+          name: "9",
+          value: "(empty)",
+        },
+        {
+          color: "#7172AD",
+          name: "10",
+          value: "12",
+        },
+      ],
+    });
   });
 
   it.skip("should drill-through a custom question that joins a native SQL question (metabase#14495)", () => {
@@ -607,9 +633,30 @@ describe("scenarios > visualizations > drillthroughs > chart drill", () => {
       .as("doohickeyChart")
       .trigger("mousemove");
 
-    popover().within(() => {
-      cy.findByText("Doohickey");
-      cy.findByText("42");
+    assertEChartsTooltip({
+      header: "Category",
+      rows: [
+        {
+          color: "#88BF4D",
+          name: "Doohickey",
+          value: "42",
+        },
+        {
+          color: "#F9D45C",
+          name: "Gadget",
+          value: "53",
+        },
+        {
+          color: "#A989C5",
+          name: "Gizmo",
+          value: "51",
+        },
+        {
+          color: "#F2A86F",
+          name: "Widget",
+          value: "54",
+        },
+      ],
     });
 
     cy.get("@doohickeyChart").click();
diff --git a/e2e/test/scenarios/visualizations-tabular/visualizations-tabular-reproductions.cy.spec.js b/e2e/test/scenarios/visualizations-tabular/visualizations-tabular-reproductions.cy.spec.js
index 03a490b1399a0ecd42c809a99e96e2b8c99a2639..db3cf546c6167b6d04726b079526d2047fd98e89 100644
--- a/e2e/test/scenarios/visualizations-tabular/visualizations-tabular-reproductions.cy.spec.js
+++ b/e2e/test/scenarios/visualizations-tabular/visualizations-tabular-reproductions.cy.spec.js
@@ -28,6 +28,7 @@ import {
   visualize,
   tableInteractive,
   createNativeQuestion,
+  assertEChartsTooltip,
 } from "e2e/support/helpers";
 
 const { ORDERS, ORDERS_ID, PEOPLE, PEOPLE_ID, PRODUCTS, PRODUCTS_ID } =
@@ -159,7 +160,16 @@ describe("issue 11435", () => {
   it("should use time formatting settings in tooltips for native questions (metabase#11435)", () => {
     cy.createNativeQuestion(questionDetails, { visitQuestion: true });
     hoverLineDot({ index: 1 });
-    popover().findByTextEnsureVisible("March 11, 2025, 8:45:17.010 PM");
+    assertEChartsTooltip({
+      header: "March 11, 2025, 8:45:17.010 PM",
+      rows: [
+        {
+          color: "#F9D45C",
+          name: "TOTAL",
+          value: "25.03",
+        },
+      ],
+    });
   });
 });
 
diff --git a/frontend/src/metabase/static-viz/components/ComboChart/ComboChart.tsx b/frontend/src/metabase/static-viz/components/ComboChart/ComboChart.tsx
index 44c86efd18cce09435f05b1639b79a64a857b0ee..e8a753fdb3993949aa40e8a74b28a4b39de59eef 100644
--- a/frontend/src/metabase/static-viz/components/ComboChart/ComboChart.tsx
+++ b/frontend/src/metabase/static-viz/components/ComboChart/ComboChart.tsx
@@ -75,7 +75,6 @@ export const ComboChart = ({
     computedVisualizationSettings,
     WIDTH,
     false,
-    null,
     renderingContext,
   );
 
diff --git a/frontend/src/metabase/visualizations/components/ChartTooltip/ChartTooltip.tsx b/frontend/src/metabase/visualizations/components/ChartTooltip/ChartTooltip.tsx
index 5f965bcc129778d2ecdcb0ffd82d0a549155caa0..a4ff5178515a567832d3d26aa0133552db136e2f 100644
--- a/frontend/src/metabase/visualizations/components/ChartTooltip/ChartTooltip.tsx
+++ b/frontend/src/metabase/visualizations/components/ChartTooltip/ChartTooltip.tsx
@@ -18,21 +18,26 @@ export interface ChartTooltipProps {
   settings: VisualizationSettings;
 }
 
-const ChartTooltip = ({ hovered, settings }: ChartTooltipProps) => {
-  const tooltip = useMemo(() => {
-    if (!hovered) {
-      return null;
-    }
-    if (!_.isEmpty(hovered.timelineEvents)) {
-      return <TimelineEventTooltip hovered={hovered as HoveredTimelineEvent} />;
-    }
+export const ChartTooltipContent = ({
+  hovered,
+  settings,
+}: ChartTooltipProps) => {
+  if (!hovered) {
+    return null;
+  }
+  if (!_.isEmpty(hovered.timelineEvents)) {
+    return <TimelineEventTooltip hovered={hovered as HoveredTimelineEvent} />;
+  }
 
-    if (hovered.stackedTooltipModel) {
-      return <StackedDataTooltip {...hovered.stackedTooltipModel} />;
-    }
+  if (hovered.stackedTooltipModel) {
+    return <StackedDataTooltip {...hovered.stackedTooltipModel} />;
+  }
+
+  return <KeyValuePairChartTooltip hovered={hovered} settings={settings} />;
+};
 
-    return <KeyValuePairChartTooltip hovered={hovered} settings={settings} />;
-  }, [hovered, settings]);
+const ChartTooltip = ({ hovered, settings }: ChartTooltipProps) => {
+  const tooltip = <ChartTooltipContent hovered={hovered} settings={settings} />;
 
   const isNotEmpty = useMemo(() => {
     if (!hovered) {
diff --git a/frontend/src/metabase/visualizations/components/ChartTooltip/EChartsTooltip/EChartsTooltip.module.css b/frontend/src/metabase/visualizations/components/ChartTooltip/EChartsTooltip/EChartsTooltip.module.css
new file mode 100644
index 0000000000000000000000000000000000000000..293a33f1f50490845e25d1f4196748fbe84d0f99
--- /dev/null
+++ b/frontend/src/metabase/visualizations/components/ChartTooltip/EChartsTooltip/EChartsTooltip.module.css
@@ -0,0 +1,92 @@
+/* This class should be set to the ECharts tooltip root element via option to override ECharts defaults */
+.ChartTooltipRoot {
+  font: unset !important;
+  background-color: var(--mb-color-bg-black) !important;
+  border: none !important;
+  padding: 0 !important;
+  color: var(--mb-color-text-white) !important;
+}
+
+.Table {
+  min-width: 240px;
+  border-collapse: collapse;
+  margin: 0.25rem 0 0.875rem 0;
+}
+
+.TableNoHeader {
+  margin-top: 1rem;
+}
+
+.Header {
+  display: flex;
+  margin: 1rem 1rem 0.25rem 1rem;
+  font-weight: 400;
+  font-size: 13px;
+  color: var(--mb-color-text-light);
+}
+
+.RowFocused {
+  background-color: color-mix(
+    in srgb,
+    var(--mb-color-bg-black) 50%,
+    #000
+  ) !important;
+}
+
+.Cell {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  max-width: 240px;
+  padding: 0.25rem 0;
+  vertical-align: middle;
+  text-align: right;
+  font-weight: 600;
+}
+
+.Cell + .Cell:not(.NameCell) {
+  padding-left: 0.75rem;
+}
+
+.Cell:first-of-type {
+  padding-left: 1rem;
+}
+
+.Cell:last-of-type {
+  padding-right: 1rem;
+}
+
+.NameCell {
+  padding-left: 0.375rem;
+  font-weight: 400;
+  font-size: 14px;
+  text-align: left;
+}
+
+.MainValueCell {
+  width: 1px;
+  font-size: 14px;
+}
+
+.SecondaryValueCell {
+  width: 1px;
+  font-weight: 600;
+  color: var(--mb-color-text-light);
+}
+
+.IndicatorCell {
+  line-height: 12px;
+  text-align: center;
+  width: 1px;
+}
+
+.Indicator {
+  border-radius: 100%;
+  width: 12px;
+  height: 12px;
+  display: inline-block;
+}
+
+.FooterRow .Cell {
+  padding-top: 0.75rem;
+}
diff --git a/frontend/src/metabase/visualizations/components/ChartTooltip/EChartsTooltip/EChartsTooltip.tsx b/frontend/src/metabase/visualizations/components/ChartTooltip/EChartsTooltip/EChartsTooltip.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..3daf0e2db1a206beb9da5eddc03b2132024d5f28
--- /dev/null
+++ b/frontend/src/metabase/visualizations/components/ChartTooltip/EChartsTooltip/EChartsTooltip.tsx
@@ -0,0 +1,154 @@
+import cx from "classnames";
+import type React from "react";
+import _ from "underscore";
+
+import { isNotNull } from "metabase/lib/types";
+
+import TooltipStyles from "./EChartsTooltip.module.css";
+
+export interface EChartsTooltipRow {
+  /* We pass CSS class with marker colors because setting styles in tooltip rendered by ECharts violates CSP */
+  markerColorClass?: string;
+  name: string;
+  isFocused?: boolean;
+  values: React.ReactNode[];
+}
+
+export interface EChartsTooltipFooter {
+  name: string;
+  values: React.ReactNode[];
+}
+
+export interface EChartsTooltipModel {
+  header?: string;
+  rows: EChartsTooltipRow[];
+  footer?: EChartsTooltipFooter;
+}
+
+export type EChartsTooltipProps = EChartsTooltipModel;
+
+export const EChartsTooltip = ({
+  header,
+  rows,
+  footer,
+}: EChartsTooltipProps) => {
+  const hasMarkers = rows.some(row => row.markerColorClass != null);
+  const maxValuesColumns = rows.reduce((currentMax, row) => {
+    return Math.max(currentMax, row.values.filter(isNotNull).length);
+  }, 0);
+
+  const paddedRows = rows.map(row => {
+    const paddedValues = [...row.values];
+    paddedValues.length = maxValuesColumns;
+
+    return {
+      ...row,
+      values: paddedValues,
+    };
+  });
+
+  return (
+    <div data-testid="echarts-tooltip">
+      {header != null && (
+        <div
+          data-testid="echarts-tooltip-header"
+          className={TooltipStyles.Header}
+        >
+          {header}
+        </div>
+      )}
+      <table
+        className={cx(TooltipStyles.Table, {
+          [TooltipStyles.TableNoHeader]: header == null,
+        })}
+      >
+        <tbody>
+          {paddedRows.map((row, index) => {
+            return <TooltipRow key={index} {...row} />;
+          })}
+        </tbody>
+        {footer != null && (
+          <tfoot>
+            <FooterRow
+              {...footer}
+              markerContent={hasMarkers ? <span /> : null}
+            />
+          </tfoot>
+        )}
+      </table>
+    </div>
+  );
+};
+
+type TooltipRowProps = EChartsTooltipRow;
+
+const TooltipRow = ({
+  name,
+  values,
+  markerColorClass,
+  isFocused,
+}: TooltipRowProps) => (
+  <BaseRow
+    className={cx({ [TooltipStyles.RowFocused]: isFocused })}
+    name={name}
+    values={values}
+    markerContent={
+      markerColorClass ? (
+        <span className={cx(TooltipStyles.Indicator, markerColorClass)} />
+      ) : null
+    }
+  />
+);
+
+const FooterRow = ({
+  name,
+  values,
+  className,
+  markerContent,
+}: BaseRowProps) => (
+  <BaseRow
+    className={cx(TooltipStyles.FooterRow, className)}
+    name={name}
+    values={values}
+    markerContent={markerContent}
+  />
+);
+
+interface BaseRowProps {
+  className?: string;
+  markerContent?: React.ReactNode;
+  name: string;
+  values: React.ReactNode[];
+}
+
+const BaseRow = ({ className, name, values, markerContent }: BaseRowProps) => (
+  <tr className={className}>
+    {markerContent != null ? (
+      <td className={cx(TooltipStyles.Cell, TooltipStyles.IndicatorCell)}>
+        {markerContent}
+      </td>
+    ) : null}
+    {name ? (
+      <td className={cx(TooltipStyles.Cell, TooltipStyles.NameCell)}>{name}</td>
+    ) : (
+      <td className={TooltipStyles.Cell} />
+    )}
+    {values.map((value, i) => {
+      const isMainValue = i === 0;
+
+      return (
+        <td
+          key={i}
+          className={cx(
+            TooltipStyles.Cell,
+            isMainValue
+              ? TooltipStyles.MainValueCell
+              : TooltipStyles.SecondaryValueCell,
+          )}
+        >
+          {value}
+        </td>
+      );
+    })}
+  </tr>
+);
diff --git a/frontend/src/metabase/visualizations/components/ChartTooltip/EChartsTooltip/index.ts b/frontend/src/metabase/visualizations/components/ChartTooltip/EChartsTooltip/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3d2288557d27aaade856f3740ed6b45f180c902b
--- /dev/null
+++ b/frontend/src/metabase/visualizations/components/ChartTooltip/EChartsTooltip/index.ts
@@ -0,0 +1 @@
+export * from "./EChartsTooltip";
diff --git a/frontend/src/metabase/visualizations/components/ChartTooltip/KeyValuePairChartTooltip/KeyValuePairChartTooltip.tsx b/frontend/src/metabase/visualizations/components/ChartTooltip/KeyValuePairChartTooltip/KeyValuePairChartTooltip.tsx
index 7661dbce1fff9c728ce9fd2abc9fa21b3e8d045d..29f8cc5a114d1129a56222a7218985a91fd61c8f 100644
--- a/frontend/src/metabase/visualizations/components/ChartTooltip/KeyValuePairChartTooltip/KeyValuePairChartTooltip.tsx
+++ b/frontend/src/metabase/visualizations/components/ChartTooltip/KeyValuePairChartTooltip/KeyValuePairChartTooltip.tsx
@@ -118,7 +118,7 @@ const getRows = (hovered: HoveredObject) => {
   return [];
 };
 
-const getRowFromDataPoint = (data: DataPoint) => ({
+export const getRowFromDataPoint = (data: DataPoint) => ({
   ...data,
   key: data.key || (data.col && getFriendlyName(data.col)),
 });
diff --git a/frontend/src/metabase/visualizations/components/ChartTooltip/StackedDataTooltip/utils.ts b/frontend/src/metabase/visualizations/components/ChartTooltip/StackedDataTooltip/utils.ts
index 9adc5f127367199a9b3e21b07c478ea240e5131c..c8fba62ef6365f6140795579270e83b2a8f5c97b 100644
--- a/frontend/src/metabase/visualizations/components/ChartTooltip/StackedDataTooltip/utils.ts
+++ b/frontend/src/metabase/visualizations/components/ChartTooltip/StackedDataTooltip/utils.ts
@@ -54,7 +54,7 @@ export const groupExcessiveTooltipRows = (
   return [...rowsToKeep, groupedRow];
 };
 
-export const getSortedRows = (rows: TooltipRowModel[]) => {
+export const getSortedRows = <TRow extends TooltipRowModel>(rows: TRow[]) => {
   return [...rows].sort(({ value: leftValue }, { value: rightValue }) => {
     return (
       (typeof rightValue === "number" ? rightValue : 0) -
diff --git a/frontend/src/metabase/visualizations/components/ChartTooltip/utils.ts b/frontend/src/metabase/visualizations/components/ChartTooltip/utils.ts
index 9ca56705ac71f59bae0f61f23e9e553074a5dae6..11bc261322f0edb9fbebb09fcc0d400ef550f076 100644
--- a/frontend/src/metabase/visualizations/components/ChartTooltip/utils.ts
+++ b/frontend/src/metabase/visualizations/components/ChartTooltip/utils.ts
@@ -1,3 +1,4 @@
+import { NULL_DISPLAY_VALUE } from "metabase/lib/constants";
 import { formatValue } from "metabase/lib/formatting";
 import type { OptionsType } from "metabase/lib/formatting/types";
 import type {
@@ -29,5 +30,5 @@ export const formatValueForTooltip = ({
     options.scale = 1;
   }
 
-  return formatValue(value, options);
+  return formatValue(value, options) ?? NULL_DISPLAY_VALUE;
 };
diff --git a/frontend/src/metabase/visualizations/components/Visualization/Visualization.jsx b/frontend/src/metabase/visualizations/components/Visualization/Visualization.jsx
index f1c4b1f4edad0ce077c7439a9fd304002bc08cab..bd42c69d3d916c4a64e314ae3d7836990d8c5a60 100644
--- a/frontend/src/metabase/visualizations/components/Visualization/Visualization.jsx
+++ b/frontend/src/metabase/visualizations/components/Visualization/Visualization.jsx
@@ -1,6 +1,5 @@
 /* eslint-disable react/prop-types */
 import cx from "classnames";
-import { assoc } from "icepick";
 import { PureComponent } from "react";
 import { connect } from "react-redux";
 import { t } from "ttag";
@@ -81,7 +80,6 @@ class Visualization extends PureComponent {
     error: null,
     genericError: null,
     warnings: [],
-    yAxisSplit: null,
     series: null,
     visualization: null,
     computedSettings: {},
@@ -158,7 +156,6 @@ class Visualization extends PureComponent {
       error: null,
       genericError: null,
       warnings: [],
-      yAxisSplit: null,
       series: series,
       visualization: visualization,
       computedSettings: computedSettings,
@@ -178,14 +175,6 @@ class Visualization extends PureComponent {
 
   handleHoverChange = hovered => {
     if (hovered) {
-      const { yAxisSplit } = this.state;
-      // if we have Y axis split info then find the Y axis index (0 = left, 1 = right)
-      if (yAxisSplit) {
-        const axisIndex = _.findIndex(yAxisSplit, indexes =>
-          _.contains(indexes, hovered.index),
-        );
-        hovered = assoc(hovered, "axisIndex", axisIndex);
-      }
       this.setState({ hovered });
       // If we previously set a timeout for clearing the hover clear it now since we received
       // a new hover.
@@ -319,8 +308,11 @@ class Visualization extends PureComponent {
     });
   };
 
-  onRender = ({ yAxisSplit, warnings = [] } = {}) => {
-    this.setState({ yAxisSplit, warnings });
+  onRender = ({ warnings = [] } = {}) => {
+    const currentWarnings = this.state.warnings;
+    if (!_.isEqual(currentWarnings, warnings)) {
+      this.setState({ warnings });
+    }
   };
 
   onRenderError = error => {
diff --git a/frontend/src/metabase/visualizations/echarts/cartesian/option/axis.ts b/frontend/src/metabase/visualizations/echarts/cartesian/option/axis.ts
index e9f6eceb6f55b13de34acb2f31c2630d1365a010..a37d0bcbacdfd2ac12f3fd364818ab2036dbb171 100644
--- a/frontend/src/metabase/visualizations/echarts/cartesian/option/axis.ts
+++ b/frontend/src/metabase/visualizations/echarts/cartesian/option/axis.ts
@@ -5,7 +5,6 @@ import { parseNumberValue } from "metabase/lib/number";
 import { CHART_STYLE } from "metabase/visualizations/echarts/cartesian/constants/style";
 import type {
   BaseCartesianChartModel,
-  DataKey,
   Extent,
   NumericAxisScaleTransforms,
   NumericXAxisModel,
@@ -362,23 +361,15 @@ export const buildMetricAxis = (
   settings: ComputedVisualizationSettings,
   position: "left" | "right",
   hasSplitLine: boolean,
-  hoveredSeriesDataKey: DataKey | null,
   renderingContext: RenderingContext,
 ): YAXisOption => {
   const shouldFlipAxisName = position === "right";
   const nameGap = getAxisNameGap(ticksWidth);
 
   const range = getYAxisRange(axisModel, yAxisScaleTransforms, settings);
-  let isFocused = false;
-  let isBlurred = false;
-
-  if (hoveredSeriesDataKey != null) {
-    isFocused = axisModel.seriesKeys.includes(hoveredSeriesDataKey);
-    isBlurred = !isFocused;
-  }
 
   return {
-    show: !isBlurred,
+    show: true,
     scale: !!settings["graph.y_axis.unpin_from_zero"],
     type: "value",
     ...range,
@@ -389,7 +380,7 @@ export const buildMetricAxis = (
       shouldFlipAxisName ? -90 : undefined,
     ),
     splitLine:
-      (hasSplitLine || isFocused) && !!settings["graph.y_axis.axis_enabled"]
+      hasSplitLine && !!settings["graph.y_axis.axis_enabled"]
         ? {
             lineStyle: {
               type: 5,
@@ -421,7 +412,6 @@ const buildMetricsAxes = (
   chartModel: BaseCartesianChartModel,
   chartMeasurements: ChartMeasurements,
   settings: ComputedVisualizationSettings,
-  hoveredSeriesDataKey: DataKey | null,
   renderingContext: RenderingContext,
 ): YAXisOption[] => {
   const axes: YAXisOption[] = [];
@@ -436,7 +426,6 @@ const buildMetricsAxes = (
         settings,
         "left",
         true,
-        hoveredSeriesDataKey,
         renderingContext,
       ),
     );
@@ -452,7 +441,6 @@ const buildMetricsAxes = (
         settings,
         "right",
         isOnlyAxis,
-        hoveredSeriesDataKey,
         renderingContext,
       ),
     );
@@ -467,7 +455,6 @@ export const buildAxes = (
   chartMeasurements: ChartMeasurements,
   settings: ComputedVisualizationSettings,
   hasTimelineEvents: boolean,
-  hoveredSeriesDataKey: DataKey | null,
   renderingContext: RenderingContext,
 ) => {
   return {
@@ -483,7 +470,6 @@ export const buildAxes = (
       chartModel,
       chartMeasurements,
       settings,
-      hoveredSeriesDataKey,
       renderingContext,
     ),
   };
diff --git a/frontend/src/metabase/visualizations/echarts/cartesian/option/index.ts b/frontend/src/metabase/visualizations/echarts/cartesian/option/index.ts
index d4b943bc67062b6e30c35deac57efec6259264cf..f75c987ae8622bfe8c508e85a2e73eb2b0caac93 100644
--- a/frontend/src/metabase/visualizations/echarts/cartesian/option/index.ts
+++ b/frontend/src/metabase/visualizations/echarts/cartesian/option/index.ts
@@ -6,10 +6,7 @@ import {
   POSITIVE_STACK_TOTAL_DATA_KEY,
   X_AXIS_DATA_KEY,
 } from "metabase/visualizations/echarts/cartesian/constants/dataset";
-import type {
-  DataKey,
-  CartesianChartModel,
-} from "metabase/visualizations/echarts/cartesian/model/types";
+import type { CartesianChartModel } from "metabase/visualizations/echarts/cartesian/model/types";
 import { buildAxes } from "metabase/visualizations/echarts/cartesian/option/axis";
 import { buildEChartsSeries } from "metabase/visualizations/echarts/cartesian/option/series";
 import { getTimelineEventsSeries } from "metabase/visualizations/echarts/cartesian/timeline-events/option";
@@ -50,7 +47,6 @@ export const getCartesianChartOption = (
   settings: ComputedVisualizationSettings,
   chartWidth: number,
   isAnimated: boolean,
-  hoveredSeriesDataKey: DataKey | null,
   renderingContext: RenderingContext,
 ): EChartsCoreOption => {
   const hasTimelineEvents = timelineEventsModel != null;
@@ -131,7 +127,6 @@ export const getCartesianChartOption = (
       chartMeasurements,
       settings,
       hasTimelineEvents,
-      hoveredSeriesDataKey,
       renderingContext,
     ),
   };
diff --git a/frontend/src/metabase/visualizations/echarts/cartesian/option/tooltip.tsx b/frontend/src/metabase/visualizations/echarts/cartesian/option/tooltip.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..3f3fe90c7d8a4ea8318025ff2f34ff43c292a5eb
--- /dev/null
+++ b/frontend/src/metabase/visualizations/echarts/cartesian/option/tooltip.tsx
@@ -0,0 +1,77 @@
+import type { TooltipOption } from "echarts/types/dist/shared";
+import { renderToString } from "react-dom/server";
+
+import { EChartsTooltip } from "metabase/visualizations/components/ChartTooltip/EChartsTooltip";
+import type { ComputedVisualizationSettings } from "metabase/visualizations/types";
+import { getTooltipModel } from "metabase/visualizations/visualizations/CartesianChart/events";
+
+import { TOOLTIP_BASE_OPTION } from "../../tooltip";
+import {
+  GOAL_LINE_SERIES_ID,
+  TIMELINE_EVENT_SERIES_ID,
+} from "../constants/dataset";
+import type { BaseCartesianChartModel, DataKey } from "../model/types";
+
+interface ChartItemTooltip {
+  dataIndex: number;
+  seriesId?: DataKey | null;
+  settings: ComputedVisualizationSettings;
+  chartModel: BaseCartesianChartModel;
+}
+
+const ChartItemTooltip = ({
+  chartModel,
+  settings,
+  dataIndex,
+  seriesId,
+}: ChartItemTooltip) => {
+  if (dataIndex == null || seriesId == null) {
+    return null;
+  }
+
+  const tooltipModel = getTooltipModel(
+    chartModel,
+    settings,
+    dataIndex,
+    seriesId,
+  );
+
+  if (!tooltipModel) {
+    return null;
+  }
+
+  return <EChartsTooltip {...tooltipModel} />;
+};
+
+export const getTooltipOption = (
+  chartModel: BaseCartesianChartModel,
+  settings: ComputedVisualizationSettings,
+): TooltipOption => {
+  return {
+    trigger: "item",
+    ...TOOLTIP_BASE_OPTION,
+    formatter: params => {
+      if (Array.isArray(params)) {
+        return "";
+      }
+
+      const { dataIndex, seriesId } = params;
+
+      if (
+        seriesId === TIMELINE_EVENT_SERIES_ID ||
+        seriesId === GOAL_LINE_SERIES_ID
+      ) {
+        return "";
+      }
+
+      return renderToString(
+        <ChartItemTooltip
+          settings={settings}
+          chartModel={chartModel}
+          dataIndex={dataIndex}
+          seriesId={seriesId}
+        />,
+      );
+    },
+  };
+};
diff --git a/frontend/src/metabase/visualizations/echarts/cartesian/scatter/option/index.ts b/frontend/src/metabase/visualizations/echarts/cartesian/scatter/option/index.ts
index 377e987858cfcf7352d77914a0af63e11c6fb63b..bfe92da43f4f47559e4d2d9ec3c8e4ef3000f50f 100644
--- a/frontend/src/metabase/visualizations/echarts/cartesian/scatter/option/index.ts
+++ b/frontend/src/metabase/visualizations/echarts/cartesian/scatter/option/index.ts
@@ -104,7 +104,6 @@ export function getScatterPlotOption(
       chartMeasurements,
       settings,
       hasTimelineEvents,
-      null,
       renderingContext,
     ),
   };
diff --git a/frontend/src/metabase/visualizations/echarts/cartesian/waterfall/option/index.ts b/frontend/src/metabase/visualizations/echarts/cartesian/waterfall/option/index.ts
index 9e45b0f7a7d6f734e52c4a49c351545f720b90ab..6c54fb34e853f27a2c0472b537ba83b38dbf8346 100644
--- a/frontend/src/metabase/visualizations/echarts/cartesian/waterfall/option/index.ts
+++ b/frontend/src/metabase/visualizations/echarts/cartesian/waterfall/option/index.ts
@@ -255,7 +255,6 @@ export const getWaterfallChartOption = (
       chartMeasurements,
       settings,
       hasTimelineEvents,
-      null,
       renderingContext,
     ),
   };
diff --git a/frontend/src/metabase/visualizations/echarts/index.ts b/frontend/src/metabase/visualizations/echarts/index.ts
index 5c923798eaadb7d1d15815d0f07c4f5943c8dd76..76961d1ca2c90aae938807b5d50cb20cbb105302 100644
--- a/frontend/src/metabase/visualizations/echarts/index.ts
+++ b/frontend/src/metabase/visualizations/echarts/index.ts
@@ -13,6 +13,7 @@ import {
   ToolboxComponent,
   DatasetComponent,
   GraphicComponent,
+  TooltipComponent,
 } from "echarts/components";
 import { use } from "echarts/core";
 import { LabelLayout } from "echarts/features";
@@ -35,5 +36,6 @@ export const registerEChartsModules = () => {
     BrushComponent,
     DatasetComponent,
     LabelLayout,
+    TooltipComponent,
   ]);
 };
diff --git a/frontend/src/metabase/visualizations/echarts/pie/tooltip.tsx b/frontend/src/metabase/visualizations/echarts/pie/tooltip.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..56bccf9526c1a2751df9198fec4f1b81eccab563
--- /dev/null
+++ b/frontend/src/metabase/visualizations/echarts/pie/tooltip.tsx
@@ -0,0 +1,47 @@
+import type { TooltipOption } from "echarts/types/dist/shared";
+import { renderToString } from "react-dom/server";
+
+import { EChartsTooltip } from "metabase/visualizations/components/ChartTooltip/EChartsTooltip";
+import { getTooltipModel } from "metabase/visualizations/visualizations/PieChart/use-chart-events";
+
+import { TOOLTIP_BASE_OPTION } from "../tooltip";
+
+import type { PieChartFormatters } from "./format";
+import type { PieChartModel } from "./model/types";
+
+interface ChartItemTooltip {
+  chartModel: PieChartModel;
+  formatters: PieChartFormatters;
+  dataIndex: number;
+}
+
+const ChartItemTooltip = ({
+  chartModel,
+  formatters,
+  dataIndex,
+}: ChartItemTooltip) => {
+  const tooltipModel = getTooltipModel(dataIndex, chartModel, formatters);
+  return <EChartsTooltip {...tooltipModel} />;
+};
+
+export const getTooltipOption = (
+  chartModel: PieChartModel,
+  formatters: PieChartFormatters,
+): TooltipOption => {
+  return {
+    ...TOOLTIP_BASE_OPTION,
+    trigger: "item",
+    formatter: params => {
+      if (Array.isArray(params) || typeof params.dataIndex !== "number") {
+        return "";
+      }
+      return renderToString(
+        <ChartItemTooltip
+          formatters={formatters}
+          chartModel={chartModel}
+          dataIndex={params.dataIndex}
+        />,
+      );
+    },
+  };
+};
diff --git a/frontend/src/metabase/visualizations/echarts/tooltip/index.tsx b/frontend/src/metabase/visualizations/echarts/tooltip/index.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..0922192eb402fed062bcc7d32b67abe945b29f81
--- /dev/null
+++ b/frontend/src/metabase/visualizations/echarts/tooltip/index.tsx
@@ -0,0 +1,83 @@
+import { useMemo } from "react";
+
+import { isNotNull } from "metabase/lib/types";
+import TooltipStyles from "metabase/visualizations/components/ChartTooltip/EChartsTooltip/EChartsTooltip.module.css";
+
+import type { BaseCartesianChartModel } from "../cartesian/model/types";
+import type { PieChartModel } from "../pie/model/types";
+
+export const TOOLTIP_BASE_OPTION = {
+  confine: true,
+  appendTo: () => {
+    let container = document.querySelector(
+      ".echarts-tooltip-container",
+    ) as HTMLDivElement;
+    if (!container) {
+      container = document.createElement("div");
+      container.classList.add("echarts-tooltip-container");
+      container.style.setProperty("overflow", "hidden");
+      container.style.setProperty("height", "100%");
+      container.style.setProperty("position", "relative");
+      container.style.setProperty("pointer-events", "none");
+
+      document.body.append(container);
+    }
+
+    return container;
+  },
+  className: TooltipStyles.ChartTooltipRoot,
+};
+
+export const getMarkerColorClass = (hexColor: string) => {
+  return `marker-${hexColor.slice(1, 7)}`;
+};
+
+export const useInjectSeriesColorsClasses = (hexColors: string[]) => {
+  const cssString = useMemo(() => {
+    if (hexColors.length === 0) {
+      return null;
+    }
+
+    return hexColors
+      .map(color => {
+        const cssClassName = getMarkerColorClass(color);
+        return `
+    .${cssClassName} {
+      background-color: ${color};
+    }`;
+      })
+      .join("\n");
+  }, [hexColors]);
+
+  const style = useMemo(
+    () =>
+      cssString !== null ? (
+        <style nonce={window.MetabaseNonce}>{cssString}</style>
+      ) : null,
+    [cssString],
+  );
+
+  return style;
+};
+
+export const useCartesianChartSeriesColorsClasses = (
+  chartModel: BaseCartesianChartModel,
+) => {
+  const hexColors = useMemo(
+    () =>
+      chartModel.seriesModels
+        .map(seriesModel => seriesModel.color)
+        .filter(isNotNull),
+    [chartModel],
+  );
+
+  return useInjectSeriesColorsClasses(hexColors);
+};
+
+export const usePieChartValuesColorsClasses = (chartModel: PieChartModel) => {
+  const hexColors = useMemo(() => {
+    return chartModel.slices.map(slice => slice.data.color);
+  }, [chartModel.slices]);
+
+  return useInjectSeriesColorsClasses(hexColors);
+};
diff --git a/frontend/src/metabase/visualizations/lib/settings/graph.js b/frontend/src/metabase/visualizations/lib/settings/graph.js
index aeaeb84d2d84f939d94bca1417eb35e16ee75ea8..86bc88e32838dd72da11866abdbd2d1f88b42cdc 100644
--- a/frontend/src/metabase/visualizations/lib/settings/graph.js
+++ b/frontend/src/metabase/visualizations/lib/settings/graph.js
@@ -262,9 +262,10 @@ export const LEGEND_SETTINGS = {
 
 export const TOOLTIP_SETTINGS = {
   "graph.tooltip_type": {
-    getDefault: (series, settings) => {
-      const shouldShowComparisonTooltip =
-        settings["stackable.stack_type"] != null;
+    getDefault: ([{ card }]) => {
+      const shouldShowComparisonTooltip = !["waterfall", "scatter"].includes(
+        card.display,
+      );
       return shouldShowComparisonTooltip ? "series_comparison" : "default";
     },
     hidden: true,
diff --git a/frontend/src/metabase/visualizations/types/hover.ts b/frontend/src/metabase/visualizations/types/hover.ts
index 897f76a3e6221cf4786eaa0bb9afd6c50c683a42..f59ffa6ed7d8a70cb3ea49a801f3b764e4032a2d 100644
--- a/frontend/src/metabase/visualizations/types/hover.ts
+++ b/frontend/src/metabase/visualizations/types/hover.ts
@@ -1,5 +1,5 @@
 import type { ClickObjectDataRow } from "metabase-lib";
-import type { TimelineEvent } from "metabase-types/api";
+import type { RowValue, TimelineEvent } from "metabase-types/api";
 
 import type { RemappingHydratedDatasetColumn } from "./columns";
 import type { ComputedVisualizationSettings } from "./visualization";
@@ -21,8 +21,8 @@ export interface HoveredTimelineEvent {
 export interface TooltipRowModel {
   color?: string;
   name: string;
-  value: unknown;
-  formatter?: (value: unknown) => string;
+  value: RowValue;
+  formatter?: (value: RowValue) => string;
 }
 
 export interface StackedTooltipModel {
@@ -37,7 +37,6 @@ export interface StackedTooltipModel {
 
 export interface HoveredObject {
   index?: number;
-  axisIndex?: number;
   seriesIndex?: number;
   seriesId?: number;
   datumIndex?: number;
diff --git a/frontend/src/metabase/visualizations/visualizations/CartesianChart/CartesianChart.tsx b/frontend/src/metabase/visualizations/visualizations/CartesianChart/CartesianChart.tsx
index d4af656f391e92e018e60deb3c7bfe0638f365f4..ceb756357c4b3e1956411f7a3c0bab9d1dd0fb36 100644
--- a/frontend/src/metabase/visualizations/visualizations/CartesianChart/CartesianChart.tsx
+++ b/frontend/src/metabase/visualizations/visualizations/CartesianChart/CartesianChart.tsx
@@ -4,6 +4,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
 import { ChartRenderingErrorBoundary } from "metabase/visualizations/components/ChartRenderingErrorBoundary";
 import LegendCaption from "metabase/visualizations/components/legend/LegendCaption";
 import { getLegendItems } from "metabase/visualizations/echarts/cartesian/model/legend";
+import { useCartesianChartSeriesColorsClasses } from "metabase/visualizations/echarts/tooltip";
 import type { VisualizationProps } from "metabase/visualizations/types";
 import {
   CartesianChartLegendLayout,
@@ -88,6 +89,7 @@ function _CartesianChart(props: VisualizationProps) {
   }, []);
 
   const canSelectTitle = !!onChangeCardAndRun;
+  const seriesColorsCss = useCartesianChartSeriesColorsClasses(chartModel);
 
   return (
     <CartesianChartRoot isQueryBuilder={isQueryBuilder}>
@@ -129,6 +131,7 @@ function _CartesianChart(props: VisualizationProps) {
           onInit={handleInit}
         />
       </CartesianChartLegendLayout>
+      {seriesColorsCss}
     </CartesianChartRoot>
   );
 }
diff --git a/frontend/src/metabase/visualizations/visualizations/CartesianChart/constants.ts b/frontend/src/metabase/visualizations/visualizations/CartesianChart/constants.ts
deleted file mode 100644
index 1e59032646c9fe2e3afa47fdb20bdf9057a7b411..0000000000000000000000000000000000000000
--- a/frontend/src/metabase/visualizations/visualizations/CartesianChart/constants.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { t } from "ttag";
-
-import type { CartesianChartDateTimeAbsoluteUnit } from "metabase/visualizations/echarts/cartesian/model/types";
-
-export const DATETIME_ABSOLUTE_UNIT_COMPARISON: Record<
-  CartesianChartDateTimeAbsoluteUnit,
-  string
-> = {
-  year: t`Compared to previous year`,
-  quarter: t`Compared to previous quarter`,
-  month: t`Compared to previous month`,
-  week: t`Compared to previous week`,
-  day: t`Compared to previous day`,
-  hour: t`Compared to previous hour`,
-  minute: t`Compared to previous minute`,
-  second: t`Compared to previous second`,
-  ms: t`Compared to previous millisecond`,
-};
diff --git a/frontend/src/metabase/visualizations/visualizations/CartesianChart/events.ts b/frontend/src/metabase/visualizations/visualizations/CartesianChart/events.ts
index 5fcfbf05c78dfe829f1d26edc200384be475337c..a5ffb96b558c03271bd6899ee2fdaff2d376fc17 100644
--- a/frontend/src/metabase/visualizations/visualizations/CartesianChart/events.ts
+++ b/frontend/src/metabase/visualizations/visualizations/CartesianChart/events.ts
@@ -1,3 +1,4 @@
+import { t } from "ttag";
 import _ from "underscore";
 
 import { NULL_DISPLAY_VALUE } from "metabase/lib/constants";
@@ -8,6 +9,17 @@ import {
   parseTimestamp,
 } from "metabase/lib/time-dayjs";
 import { checkNumber, isNotNull } from "metabase/lib/types";
+import { formatPercent } from "metabase/static-viz/lib/numbers";
+import type {
+  EChartsTooltipModel,
+  EChartsTooltipRow,
+} from "metabase/visualizations/components/ChartTooltip/EChartsTooltip";
+import { getRowFromDataPoint } from "metabase/visualizations/components/ChartTooltip/KeyValuePairChartTooltip/KeyValuePairChartTooltip";
+import {
+  getPercent,
+  getTotalValue,
+} from "metabase/visualizations/components/ChartTooltip/StackedDataTooltip/utils";
+import { formatValueForTooltip } from "metabase/visualizations/components/ChartTooltip/utils";
 import {
   ORIGINAL_INDEX_DATA_KEY,
   X_AXIS_DATA_KEY,
@@ -24,8 +36,10 @@ import type {
   Datum,
   DimensionModel,
   SeriesModel,
+  StackModel,
 } from "metabase/visualizations/echarts/cartesian/model/types";
 import type { TimelineEventsModel } from "metabase/visualizations/echarts/cartesian/timeline-events/types";
+import { getMarkerColorClass } from "metabase/visualizations/echarts/tooltip";
 import type {
   EChartsSeriesMouseEvent,
   EChartsSeriesBrushEndEvent,
@@ -36,13 +50,11 @@ import {
   isRemappedToString,
 } from "metabase/visualizations/lib/renderer_utils";
 import { dimensionIsTimeseries } from "metabase/visualizations/lib/timeseries";
-import { formatValueForTooltip } from "metabase/visualizations/lib/tooltip";
 import { getFriendlyName } from "metabase/visualizations/lib/utils";
 import type {
   ComputedVisualizationSettings,
   DataPoint,
   OnChangeCardAndRun,
-  TooltipRowModel,
 } from "metabase/visualizations/types";
 import type { ClickObject, ClickObjectDimension } from "metabase-lib";
 import * as Lib from "metabase-lib";
@@ -56,8 +68,6 @@ import type {
   TimelineEventId,
 } from "metabase-types/api";
 
-import { DATETIME_ABSOLUTE_UNIT_COMPARISON } from "./constants";
-
 export const parseDataKey = (dataKey: DataKey) => {
   let cardId: Nullable<CardId> = null;
 
@@ -191,18 +201,13 @@ const getEventColumnsData = (
   return dataPoints;
 };
 
-const getTooltipFooterData = (
+const computeDiffWithPreviousPeriod = (
   chartModel: BaseCartesianChartModel,
-  display: string,
   seriesIndex: number,
   dataIndex: number,
-): DataPoint[] => {
-  if (
-    display === "scatter" ||
-    display === "waterfall" ||
-    !isTimeSeriesAxis(chartModel.xAxisModel)
-  ) {
-    return [];
+): string | null => {
+  if (!isTimeSeriesAxis(chartModel.xAxisModel)) {
+    return null;
   }
 
   const datum = chartModel.dataset[dataIndex];
@@ -213,8 +218,8 @@ const getTooltipFooterData = (
   const previousValue =
     chartModel.dataset[dataIndex - 1]?.[seriesModel.dataKey];
 
-  if (previousValue == null) {
-    return [];
+  if (previousValue == null || currentValue == null) {
+    return null;
   }
   const previousDate = parseTimestamp(
     chartModel.dataset[dataIndex - 1][X_AXIS_DATA_KEY],
@@ -246,84 +251,12 @@ const getTooltipFooterData = (
   }
 
   if (!isOneIntervalAgo) {
-    return [];
+    return null;
   }
 
   const change = computeChange(previousValue, currentValue);
 
-  return [
-    {
-      key: DATETIME_ABSOLUTE_UNIT_COMPARISON[unit],
-      col: seriesModel.column,
-      value: formatChangeWithSign(change),
-    },
-  ];
-};
-
-const getStackedTooltipModel = (
-  chartModel: BaseCartesianChartModel,
-  settings: ComputedVisualizationSettings,
-  seriesIndex: number,
-  dataIndex: number,
-) => {
-  const hoveredSeries = chartModel.seriesModels[seriesIndex];
-  const seriesStack = chartModel.stackModels.find(stackModel =>
-    stackModel.seriesKeys.includes(hoveredSeries.dataKey),
-  );
-
-  if (!seriesStack) {
-    return undefined;
-  }
-
-  const column =
-    chartModel.leftAxisModel?.column ?? chartModel.rightAxisModel?.column;
-
-  const formatter = (value: unknown) =>
-    String(
-      formatValueForTooltip({
-        value,
-        settings,
-        column,
-      }),
-    );
-
-  const rows: (TooltipRowModel & { dataKey: DataKey })[] =
-    chartModel.seriesModels
-      .filter(seriesModel =>
-        seriesStack?.seriesKeys.includes(seriesModel.dataKey),
-      )
-      .map(seriesModel => {
-        return {
-          dataKey: seriesModel.dataKey,
-          name: seriesModel.name,
-          color: seriesModel.color,
-          value: chartModel.dataset[dataIndex][seriesModel.dataKey],
-          formatter,
-        };
-      });
-  const [headerRows, bodyRows] = _.partition(
-    rows,
-    row => row.dataKey === hoveredSeries.dataKey,
-  );
-
-  const dimensionValue = chartModel.dataset[dataIndex][X_AXIS_DATA_KEY];
-
-  const headerTitle = String(
-    formatValueForTooltip({
-      value: dimensionValue,
-      column: chartModel.dimensionModel.column,
-      settings,
-    }),
-  );
-
-  return {
-    headerTitle,
-    headerRows,
-    bodyRows: bodyRows.filter(row => row.value != null),
-    totalFormatter: formatter,
-    showTotal: true,
-    showPercentages: true,
-  };
+  return formatChangeWithSign(change);
 };
 
 export const canBrush = (
@@ -359,31 +292,33 @@ function getDataIndex(
   return originalDataIndex ?? echartsDataIndex;
 }
 
-const CIRCLE_PATH = "M1 0A1 1 0 1 1 1 -0.0001";
-
-// HACK: Native events may wrongly have the entire series path or the entire svg as target when hovering a single datum
-const isValidDatumElement = (
-  element: SVGElement | undefined,
-  seriesType: string,
+export const getSeriesHovered = (
+  chartModel: BaseCartesianChartModel,
+  event: EChartsSeriesMouseEvent,
 ) => {
-  if (element?.nodeName === "svg") {
-    return false;
-  }
+  const { dataIndex: echartsDataIndex, seriesId } = event;
+  const dataIndex = getDataIndex(
+    chartModel.transformedDataset,
+    echartsDataIndex,
+  );
+  const seriesIndex = findSeriesModelIndexById(chartModel, seriesId);
 
-  if (seriesType !== "line") {
-    return true;
+  if (seriesIndex < 0 || dataIndex == null) {
+    return;
   }
 
-  return element?.getAttribute("d") === CIRCLE_PATH;
+  return {
+    index: seriesIndex,
+    datumIndex: dataIndex,
+  };
 };
 
 export const getSeriesHoverData = (
   chartModel: BaseCartesianChartModel,
   settings: ComputedVisualizationSettings,
-  display: string,
-  event: EChartsSeriesMouseEvent,
+  echartsDataIndex: number,
+  seriesId: DataKey,
 ) => {
-  const { dataIndex: echartsDataIndex, seriesId } = event;
   const dataIndex = getDataIndex(
     chartModel.transformedDataset,
     echartsDataIndex,
@@ -394,37 +329,218 @@ export const getSeriesHoverData = (
     return;
   }
 
-  const target = event.event.event.target as SVGElement | undefined;
+  return {
+    settings,
+    isAlreadyScaled: true,
+    index: seriesIndex,
+    datumIndex: dataIndex,
+  };
+};
 
-  // TODO: For some reason ECharts sometimes trigger series mouse move element with the root SVG as target
-  // Find a better fix
-  if (!isValidDatumElement(target, event.seriesType)) {
-    return;
+export const getTooltipModel = (
+  chartModel: BaseCartesianChartModel,
+  settings: ComputedVisualizationSettings,
+  echartsDataIndex: number,
+  seriesDataKey: DataKey,
+): EChartsTooltipModel | null => {
+  const dataIndex = getDataIndex(
+    chartModel.transformedDataset,
+    echartsDataIndex,
+  );
+
+  if (dataIndex == null) {
+    return null;
+  }
+  const datum = chartModel.dataset[dataIndex];
+  const seriesIndex = chartModel.seriesModels.findIndex(
+    seriesModel => seriesModel.dataKey === seriesDataKey,
+  );
+  const hoveredSeries = chartModel.seriesModels[seriesIndex];
+  const seriesStack = chartModel.stackModels.find(stackModel =>
+    stackModel.seriesKeys.includes(hoveredSeries.dataKey),
+  );
+
+  const shouldShowAllColumnValuesTooltip =
+    settings["graph.tooltip_type"] === "default";
+  if (shouldShowAllColumnValuesTooltip) {
+    return getAllColumnsTooltipModel(
+      chartModel,
+      settings,
+      dataIndex,
+      seriesDataKey,
+    );
   }
 
-  const data = getEventColumnsData(chartModel, seriesIndex, dataIndex);
-  const footerData = getTooltipFooterData(
+  const shouldShowStackedTooltip = seriesStack != null;
+  if (shouldShowStackedTooltip) {
+    return getStackedTooltipModel(
+      chartModel,
+      settings,
+      seriesStack,
+      seriesDataKey,
+      dataIndex,
+      datum,
+    );
+  }
+
+  return getSeriesOnlyTooltipModel(
     chartModel,
-    display,
-    seriesIndex,
+    settings,
+    datum,
     dataIndex,
+    seriesDataKey,
   );
+};
 
-  const stackedTooltipModel =
-    settings["graph.tooltip_type"] === "series_comparison"
-      ? getStackedTooltipModel(chartModel, settings, seriesIndex, dataIndex)
-      : undefined;
+const getAllColumnsTooltipModel = (
+  chartModel: BaseCartesianChartModel,
+  settings: ComputedVisualizationSettings,
+  dataIndex: number,
+  seriesDataKey: DataKey,
+): EChartsTooltipModel | null => {
+  const seriesIndex = findSeriesModelIndexById(chartModel, seriesDataKey);
+  const rows = getEventColumnsData(chartModel, seriesIndex, dataIndex)
+    .map(getRowFromDataPoint)
+    .map(dataPoint => {
+      return {
+        name: dataPoint.key,
+        values: [
+          formatValueForTooltip({
+            isAlreadyScaled: true,
+            value: dataPoint.value,
+            column: dataPoint.col,
+            settings,
+          }),
+        ],
+      };
+    });
 
   return {
-    settings,
-    isAlreadyScaled: true,
-    index: seriesIndex,
-    datumIndex: dataIndex,
-    event: event.event.event,
-    element: target,
-    data,
-    footerData,
-    stackedTooltipModel,
+    rows,
+  };
+};
+
+export const getSeriesOnlyTooltipModel = (
+  chartModel: BaseCartesianChartModel,
+  settings: ComputedVisualizationSettings,
+  datum: Datum,
+  dataIndex: number,
+  seriesDataKey: DataKey,
+): EChartsTooltipModel | null => {
+  const header = String(
+    formatValueForTooltip({
+      value: datum[X_AXIS_DATA_KEY],
+      column: chartModel.dimensionModel.column,
+      settings,
+    }),
+  );
+
+  const rows: EChartsTooltipRow[] = chartModel.seriesModels.map(
+    (seriesModel, seriesIndex) => {
+      const prevValue = computeDiffWithPreviousPeriod(
+        chartModel,
+        seriesIndex,
+        dataIndex,
+      );
+      return {
+        isFocused:
+          chartModel.seriesModels.length > 1 &&
+          seriesModel.dataKey === seriesDataKey,
+        name: seriesModel.name,
+        markerColorClass: getMarkerColorClass(seriesModel.color),
+        values: [
+          formatValueForTooltip({
+            value: datum[seriesModel.dataKey],
+            column: seriesModel.column,
+            settings,
+            isAlreadyScaled: true,
+          }),
+          prevValue,
+        ],
+      };
+    },
+  );
+
+  return {
+    header,
+    rows,
+  };
+};
+
+export const getStackedTooltipModel = (
+  chartModel: BaseCartesianChartModel,
+  settings: ComputedVisualizationSettings,
+  seriesStack: StackModel,
+  seriesDataKey: DataKey,
+  dataIndex: number,
+  datum: Datum,
+): EChartsTooltipModel | null => {
+  const stackSeriesRows = chartModel.seriesModels
+    .filter(seriesModel =>
+      seriesStack?.seriesKeys.includes(seriesModel.dataKey),
+    )
+    .map(seriesModel => {
+      return {
+        isFocused: seriesModel.dataKey === seriesDataKey,
+        name: seriesModel.name,
+        color: seriesModel.color,
+        value: chartModel.dataset[dataIndex][seriesModel.dataKey],
+        dataKey: seriesModel.dataKey,
+      };
+    });
+
+  // Reverse rows as they appear reversed on the stacked chart to match the order
+  stackSeriesRows.reverse();
+
+  const formatter = (value: unknown) =>
+    String(
+      formatValueForTooltip({
+        isAlreadyScaled: true,
+        value,
+        settings,
+        column:
+          chartModel.leftAxisModel?.column ?? chartModel.rightAxisModel?.column,
+      }),
+    );
+
+  const rowsTotal = getTotalValue(stackSeriesRows);
+  const isShowingTotalSensible = stackSeriesRows.length > 1;
+  const header = String(
+    formatValueForTooltip({
+      value: datum[X_AXIS_DATA_KEY],
+      column: chartModel.dimensionModel.column,
+      settings,
+    }),
+  );
+
+  const formattedTooltipRows: EChartsTooltipRow[] = stackSeriesRows
+    .filter(row => row.value != null)
+    .map(tooltipRow => {
+      return {
+        isFocused: tooltipRow.isFocused,
+        name: tooltipRow.name,
+        markerColorClass: tooltipRow.color
+          ? getMarkerColorClass(tooltipRow.color)
+          : undefined,
+        values: [
+          formatter(tooltipRow.value),
+          formatPercent(getPercent(rowsTotal, tooltipRow.value) ?? 0),
+        ],
+      };
+    });
+
+  return {
+    header,
+    rows: formattedTooltipRows,
+    footer: isShowingTotalSensible
+      ? {
+          name: t`Total`,
+          values: [
+            formatter(rowsTotal),
+            formatPercent(getPercent(rowsTotal, rowsTotal) ?? 0),
+          ],
+        }
+      : undefined,
   };
 };
 
diff --git a/frontend/src/metabase/visualizations/visualizations/CartesianChart/use-chart-events.ts b/frontend/src/metabase/visualizations/visualizations/CartesianChart/use-chart-events.ts
index 0b9f7e27a72564d95436ee6e5ac8831ad5d71b10..07d2ea7f9a937f599eea52ca47f8b839e7cb2dc4 100644
--- a/frontend/src/metabase/visualizations/visualizations/CartesianChart/use-chart-events.ts
+++ b/frontend/src/metabase/visualizations/visualizations/CartesianChart/use-chart-events.ts
@@ -23,14 +23,17 @@ import {
   getBrushData,
   getGoalLineHoverData,
   getSeriesClickData,
-  getSeriesHoverData,
+  getSeriesHovered,
   getTimelineEventsForEvent,
   getTimelineEventsHoverData,
   hasSelectedTimelineEvents,
 } from "metabase/visualizations/visualizations/CartesianChart/events";
 import type { CardId } from "metabase-types/api";
 
-import { getHoveredEChartsSeriesDataKeyAndIndex } from "./utils";
+import {
+  getHoveredEChartsSeriesDataKeyAndIndex,
+  getHoveredSeriesDataKey,
+} from "./utils";
 
 export const useChartEvents = (
   chartRef: React.MutableRefObject<EChartsType | undefined>,
@@ -69,6 +72,42 @@ export const useChartEvents = (
     [card, onChangeCardAndRun, rawSeries],
   );
 
+  const hoveredSeriesDataKey = useMemo(
+    () => getHoveredSeriesDataKey(chartModel.seriesModels, hovered),
+    [chartModel.seriesModels, hovered],
+  );
+
+  useEffect(
+    function updateYAxisVisibility() {
+      const hasSingleYAxis = !(
+        chartModel.leftAxisModel != null && chartModel.rightAxisModel != null
+      );
+
+      if (hasSingleYAxis) {
+        return;
+      }
+
+      const yAxisShowOption = [{ show: true }, { show: true }];
+      if (hoveredSeriesDataKey != null) {
+        const hiddenYAxisIndex = chartModel.leftAxisModel?.seriesKeys.includes(
+          hoveredSeriesDataKey,
+        )
+          ? 0
+          : 1;
+
+        yAxisShowOption[hiddenYAxisIndex].show = false;
+      }
+
+      chartRef.current?.setOption({ yAxis: yAxisShowOption }, false, true);
+    },
+    [
+      chartModel.leftAxisModel,
+      chartModel.rightAxisModel,
+      chartRef,
+      hoveredSeriesDataKey,
+    ],
+  );
+
   const eventHandlers: EChartsEventHandler[] = useMemo(
     () => [
       {
@@ -103,22 +142,14 @@ export const useChartEvents = (
             return;
           }
 
-          const hoveredData = getSeriesHoverData(
-            chartModel,
-            settings,
-            rawSeries[0].card.display,
-            event,
-          );
-
+          const hoveredObject = getSeriesHovered(chartModel, event);
           const isSameDatumHovered =
-            hoveredData?.index === hovered?.index &&
-            hoveredData?.datumIndex === hovered?.datumIndex;
+            hoveredObject?.index === hovered?.index &&
+            hoveredObject?.datumIndex === hovered?.datumIndex;
 
-          if (isSameDatumHovered) {
-            return;
+          if (!isSameDatumHovered) {
+            onHoverChange?.(hoveredObject);
           }
-
-          onHoverChange?.(hoveredData);
         },
       },
       {
@@ -182,21 +213,21 @@ export const useChartEvents = (
       },
     ],
     [
+      onHoverChange,
+      timelineEventsModel,
       chartModel,
-      onOpenQuestion,
-      rawSeries,
-      metadata,
       hovered,
-      selectedTimelineEventIds,
       settings,
-      timelineEventsModel,
       visualizationIsClickable,
-      onChangeCardAndRun,
       onVisualizationClick,
-      onHoverChange,
       onOpenTimelines,
+      selectedTimelineEventIds,
       onSelectTimelineEvents,
       onDeselectTimelineEvents,
+      onOpenQuestion,
+      rawSeries,
+      metadata,
+      onChangeCardAndRun,
     ],
   );
 
diff --git a/frontend/src/metabase/visualizations/visualizations/CartesianChart/use-models-and-option.ts b/frontend/src/metabase/visualizations/visualizations/CartesianChart/use-models-and-option.ts
index 2b052053fe83019d01d0b756ec33e7a1f57761bb..34a22a6b0f67823f4aca0b84979d040a7f59f97a 100644
--- a/frontend/src/metabase/visualizations/visualizations/CartesianChart/use-models-and-option.ts
+++ b/frontend/src/metabase/visualizations/visualizations/CartesianChart/use-models-and-option.ts
@@ -10,6 +10,7 @@ import type {
   WaterfallChartModel,
 } from "metabase/visualizations/echarts/cartesian/model/types";
 import { getCartesianChartOption } from "metabase/visualizations/echarts/cartesian/option";
+import { getTooltipOption } from "metabase/visualizations/echarts/cartesian/option/tooltip";
 import { getScatterPlotModel } from "metabase/visualizations/echarts/cartesian/scatter/model";
 import { getScatterPlotOption } from "metabase/visualizations/echarts/cartesian/scatter/option";
 import { getTimelineEventsModel } from "metabase/visualizations/echarts/cartesian/timeline-events/model";
@@ -18,8 +19,6 @@ import { getWaterfallChartOption } from "metabase/visualizations/echarts/cartesi
 import { useBrowserRenderingContext } from "metabase/visualizations/hooks/use-browser-rendering-context";
 import type { VisualizationProps } from "metabase/visualizations/types";
 
-import { getHoveredSeriesDataKey } from "./utils";
-
 export function useModelsAndOption({
   rawSeries,
   series: transformedSeries,
@@ -92,11 +91,6 @@ export function useModelsAndOption({
     [chartModel, chartMeasurements, timelineEvents, renderingContext],
   );
 
-  const hoveredSeriesDataKey = useMemo(
-    () => getHoveredSeriesDataKey(chartModel.seriesModels, hovered),
-    [chartModel.seriesModels, hovered],
-  );
-
   const selectedOrHoveredTimelineEventIds = useMemo(() => {
     const ids = [];
 
@@ -110,6 +104,10 @@ export function useModelsAndOption({
     return ids;
   }, [selectedTimelineEventIds, hovered?.timelineEvents]);
 
+  const tooltipOption = useMemo(() => {
+    return getTooltipOption(chartModel, settings);
+  }, [chartModel, settings]);
+
   const option = useMemo(() => {
     if (width === 0 || height === 0) {
       return {};
@@ -117,9 +115,10 @@ export function useModelsAndOption({
 
     const shouldAnimate = !isPlaceholder && !isReducedMotionPreferred();
 
+    let baseOption;
     switch (card.display) {
       case "waterfall":
-        return getWaterfallChartOption(
+        baseOption = getWaterfallChartOption(
           chartModel as WaterfallChartModel,
           width,
           chartMeasurements,
@@ -129,8 +128,9 @@ export function useModelsAndOption({
           shouldAnimate,
           renderingContext,
         );
+        break;
       case "scatter":
-        return getScatterPlotOption(
+        baseOption = getScatterPlotOption(
           chartModel as ScatterPlotModel,
           chartMeasurements,
           timelineEventsModel,
@@ -140,8 +140,9 @@ export function useModelsAndOption({
           shouldAnimate,
           renderingContext,
         );
+        break;
       default:
-        return getCartesianChartOption(
+        baseOption = getCartesianChartOption(
           chartModel as CartesianChartModel,
           chartMeasurements,
           timelineEventsModel,
@@ -149,22 +150,26 @@ export function useModelsAndOption({
           settings,
           width,
           shouldAnimate,
-          hoveredSeriesDataKey,
           renderingContext,
         );
     }
+
+    return {
+      ...baseOption,
+      tooltip: tooltipOption,
+    };
   }, [
+    width,
+    height,
+    isPlaceholder,
     card.display,
+    tooltipOption,
     chartModel,
     chartMeasurements,
-    renderingContext,
-    settings,
     timelineEventsModel,
-    hoveredSeriesDataKey,
-    width,
-    height,
-    isPlaceholder,
     selectedOrHoveredTimelineEventIds,
+    settings,
+    renderingContext,
   ]);
 
   return { chartModel, timelineEventsModel, option };
diff --git a/frontend/src/metabase/visualizations/visualizations/PieChart/PieChart.tsx b/frontend/src/metabase/visualizations/visualizations/PieChart/PieChart.tsx
index 17eb9770707fbf5eda2c6612737d06b656401e01..fd4901e3b76a7688663b7756ac75e793eb26623d 100644
--- a/frontend/src/metabase/visualizations/visualizations/PieChart/PieChart.tsx
+++ b/frontend/src/metabase/visualizations/visualizations/PieChart/PieChart.tsx
@@ -5,12 +5,14 @@ import ChartWithLegend from "metabase/visualizations/components/ChartWithLegend"
 import { getPieChartFormatters } from "metabase/visualizations/echarts/pie/format";
 import { getPieChartModel } from "metabase/visualizations/echarts/pie/model";
 import { getPieChartOption } from "metabase/visualizations/echarts/pie/option";
+import { getTooltipOption } from "metabase/visualizations/echarts/pie/tooltip";
+import { usePieChartValuesColorsClasses } from "metabase/visualizations/echarts/tooltip";
 import { useBrowserRenderingContext } from "metabase/visualizations/hooks/use-browser-rendering-context";
 import type { VisualizationProps } from "metabase/visualizations/types";
 
 import { ChartRenderer } from "./PieChart.styled";
 import { PIE_CHART_DEFINITION } from "./chart-definition";
-import { getTooltipModel, useChartEvents } from "./use-chart-events";
+import { useChartEvents } from "./use-chart-events";
 
 Object.assign(PieChart, PIE_CHART_DEFINITION);
 
@@ -47,8 +49,8 @@ export function PieChart(props: VisualizationProps) {
     [chartModel, settings, renderingContext],
   );
   const option = useMemo(
-    () =>
-      getPieChartOption(
+    () => ({
+      ...getPieChartOption(
         chartModel,
         formatters,
         settings,
@@ -56,6 +58,8 @@ export function PieChart(props: VisualizationProps) {
         sideLength,
         hoveredIndex,
       ),
+      tooltip: getTooltipOption(chartModel, formatters),
+    }),
     [
       chartModel,
       formatters,
@@ -66,6 +70,8 @@ export function PieChart(props: VisualizationProps) {
     ],
   );
 
+  const valuesColorsCss = usePieChartValuesColorsClasses(chartModel);
+
   const handleInit = useCallback((chart: EChartsType) => {
     chartRef.current = chart;
   }, []);
@@ -75,7 +81,7 @@ export function PieChart(props: VisualizationProps) {
     [],
   );
 
-  const eventHandlers = useChartEvents(props, chartRef, chartModel, formatters);
+  const eventHandlers = useChartEvents(props, chartRef, chartModel);
 
   const legendTitles = chartModel.slices
     .filter(s => s.data.includeInLegend)
@@ -103,11 +109,6 @@ export function PieChart(props: VisualizationProps) {
     props.onHoverChange(
       hoverData && {
         ...hoverData,
-        stackedTooltipModel: getTooltipModel(
-          hoverData.index,
-          chartModel,
-          formatters,
-        ),
       },
     );
 
@@ -137,6 +138,7 @@ export function PieChart(props: VisualizationProps) {
         notMerge={false}
         style={null}
       />
+      {valuesColorsCss}
     </ChartWithLegend>
   );
 }
diff --git a/frontend/src/metabase/visualizations/visualizations/PieChart/use-chart-events.ts b/frontend/src/metabase/visualizations/visualizations/PieChart/use-chart-events.ts
index 7291da7c39d75f2ef8a4006f6e1f42460d64aada..c5d01d081b71907a9edc7df306d380cd3829bb7c 100644
--- a/frontend/src/metabase/visualizations/visualizations/PieChart/use-chart-events.ts
+++ b/frontend/src/metabase/visualizations/visualizations/PieChart/use-chart-events.ts
@@ -1,23 +1,34 @@
 import type { EChartsType } from "echarts/core";
 import { type MutableRefObject, useEffect, useMemo } from "react";
+import { t } from "ttag";
 import _ from "underscore";
 
+import { formatPercent } from "metabase/static-viz/lib/numbers";
+import type {
+  EChartsTooltipModel,
+  EChartsTooltipRow,
+} from "metabase/visualizations/components/ChartTooltip/EChartsTooltip";
+import {
+  getPercent,
+  getTotalValue,
+} from "metabase/visualizations/components/ChartTooltip/StackedDataTooltip/utils";
 import type { PieChartFormatters } from "metabase/visualizations/echarts/pie/format";
 import type { PieChartModel } from "metabase/visualizations/echarts/pie/model/types";
+import { getMarkerColorClass } from "metabase/visualizations/echarts/tooltip";
 import type { EChartsSeriesMouseEvent } from "metabase/visualizations/echarts/types";
 import { getFriendlyName } from "metabase/visualizations/lib/utils";
 import type {
   ClickObject,
-  StackedTooltipModel,
   VisualizationProps,
 } from "metabase/visualizations/types";
 import type { EChartsEventHandler } from "metabase/visualizations/types/echarts";
 
 export const getTooltipModel = (
-  hoveredIndex: number,
+  dataIndex: number,
   chartModel: PieChartModel,
   formatters: PieChartFormatters,
-): StackedTooltipModel => {
+): EChartsTooltipModel => {
+  const hoveredIndex = dataIndexToHoveredIndex(dataIndex);
   const hoveredOther =
     chartModel.slices[hoveredIndex].data.isOther &&
     chartModel.otherSlices.length > 1;
@@ -31,19 +42,36 @@ export const getTooltipModel = (
     }),
   );
 
-  const [headerRows, bodyRows] = _.partition(
-    rows,
-    (_, index) => index === (hoveredOther ? null : hoveredIndex),
-  );
+  const rowsTotal = getTotalValue(rows);
+  const isShowingTotalSensible = rows.length > 1;
+
+  const formattedRows: EChartsTooltipRow[] = rows.map((row, index) => {
+    const markerColorClass = row.color
+      ? getMarkerColorClass(row.color)
+      : undefined;
+    return {
+      isFocused: !hoveredOther && index === hoveredIndex,
+      markerColorClass,
+      name: row.name,
+      values: [
+        row.formatter(row.value),
+        formatPercent(getPercent(chartModel.total, row.value) ?? 0),
+      ],
+    };
+  });
 
   return {
-    headerTitle: getFriendlyName(chartModel.colDescs.dimensionDesc.column),
-    headerRows,
-    bodyRows,
-    totalFormatter: formatters.formatMetric,
-    grandTotal: chartModel.total,
-    showTotal: true,
-    showPercentages: true,
+    header: getFriendlyName(chartModel.colDescs.dimensionDesc.column),
+    rows: formattedRows,
+    footer: isShowingTotalSensible
+      ? {
+          name: t`Total`,
+          values: [
+            formatters.formatMetric(rowsTotal),
+            formatPercent(getPercent(chartModel.total, rowsTotal) ?? 0),
+          ],
+        }
+      : undefined,
   };
 };
 
@@ -53,7 +81,6 @@ const hoveredIndexToDataIndex = (index: number) => index + 1;
 function getHoverData(
   event: EChartsSeriesMouseEvent,
   chartModel: PieChartModel,
-  formatters: PieChartFormatters,
 ) {
   if (event.dataIndex == null) {
     return null;
@@ -68,7 +95,6 @@ function getHoverData(
   return {
     index,
     event: event.event.event,
-    stackedTooltipModel: getTooltipModel(index, chartModel, formatters),
   };
 }
 
@@ -115,7 +141,6 @@ export function useChartEvents(
   props: VisualizationProps,
   chartRef: MutableRefObject<EChartsType | undefined>,
   chartModel: PieChartModel,
-  formatters: PieChartFormatters,
 ) {
   const {
     onHoverChange,
@@ -163,7 +188,7 @@ export function useChartEvents(
         eventName: "mousemove",
         query: "series",
         handler: (event: EChartsSeriesMouseEvent) => {
-          onHoverChange?.(getHoverData(event, chartModel, formatters));
+          onHoverChange?.(getHoverData(event, chartModel));
         },
       },
       {
@@ -188,7 +213,6 @@ export function useChartEvents(
       visualizationIsClickable,
       onVisualizationClick,
       chartModel,
-      formatters,
     ],
   );
 
diff --git a/frontend/src/metabase/visualizations/visualizations/ScatterPlot/ScatterPlot.tsx b/frontend/src/metabase/visualizations/visualizations/ScatterPlot/ScatterPlot.tsx
index 65e7fbba735cbbe4fb01e58974a85e42b986cf85..f840b2fcb777444b9838528d2a8c10bc9cdac90e 100644
--- a/frontend/src/metabase/visualizations/visualizations/ScatterPlot/ScatterPlot.tsx
+++ b/frontend/src/metabase/visualizations/visualizations/ScatterPlot/ScatterPlot.tsx
@@ -14,6 +14,7 @@ import {
   GRAPH_COLORS_SETTINGS,
   GRAPH_AXIS_SETTINGS,
   GRAPH_BUBBLE_SETTINGS,
+  TOOLTIP_SETTINGS,
 } from "../../lib/settings/graph";
 import type {
   VisualizationProps,
@@ -36,6 +37,7 @@ Object.assign(
       ...GRAPH_COLORS_SETTINGS,
       ...GRAPH_AXIS_SETTINGS,
       ...GRAPH_DATA_SETTINGS,
+      ...TOOLTIP_SETTINGS,
     } as any as VisualizationSettingsDefinitions,
   }),
 );
diff --git a/frontend/src/metabase/visualizations/visualizations/WaterfallChart/WaterfallChart.tsx b/frontend/src/metabase/visualizations/visualizations/WaterfallChart/WaterfallChart.tsx
index 84992b8f89b8ce61ca3cbc17d7af1fe60be66990..d6b94decbdb4d7ae003f6764994020f704a45e59 100644
--- a/frontend/src/metabase/visualizations/visualizations/WaterfallChart/WaterfallChart.tsx
+++ b/frontend/src/metabase/visualizations/visualizations/WaterfallChart/WaterfallChart.tsx
@@ -5,6 +5,7 @@ import {
   GRAPH_AXIS_SETTINGS,
   GRAPH_DISPLAY_VALUES_SETTINGS,
   GRAPH_DATA_SETTINGS,
+  TOOLTIP_SETTINGS,
 } from "metabase/visualizations/lib/settings/graph";
 import {
   getDefaultSize,
@@ -62,6 +63,7 @@ Object.assign(
       },
       ...GRAPH_DISPLAY_VALUES_SETTINGS,
       ...GRAPH_DATA_SETTINGS,
+      ...TOOLTIP_SETTINGS,
     } as any as VisualizationSettingsDefinitions,
   }),
 );