fodda-mcp 1.38.0 → 1.46.97
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -91
- package/dist/agents/fodda-researcher/skills.d.ts +1 -1
- package/dist/agents/fodda-researcher/skills.d.ts.map +1 -1
- package/dist/agents/fodda-researcher/skills.js +1 -1
- package/dist/brandTemplate.d.ts +1 -1
- package/dist/brandTemplate.d.ts.map +1 -1
- package/dist/brandTemplate.js +278 -83
- package/dist/brandTemplate.js.map +1 -1
- package/dist/catalogCache.d.ts +39 -0
- package/dist/catalogCache.d.ts.map +1 -1
- package/dist/catalogCache.js +293 -22
- package/dist/catalogCache.js.map +1 -1
- package/dist/coverageRelevance.d.ts +251 -0
- package/dist/coverageRelevance.d.ts.map +1 -0
- package/dist/coverageRelevance.js +1857 -0
- package/dist/coverageRelevance.js.map +1 -0
- package/dist/editorialFill.d.ts +5 -0
- package/dist/editorialFill.d.ts.map +1 -1
- package/dist/editorialFill.js +1 -1
- package/dist/editorialFill.js.map +1 -1
- package/dist/enrichment.d.ts +26 -0
- package/dist/enrichment.d.ts.map +1 -1
- package/dist/enrichment.js +442 -29
- package/dist/enrichment.js.map +1 -1
- package/dist/errorHandling.d.ts +35 -7
- package/dist/errorHandling.d.ts.map +1 -1
- package/dist/errorHandling.js +225 -155
- package/dist/errorHandling.js.map +1 -1
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +411 -106
- package/dist/index.js.map +1 -1
- package/dist/pricingCache.d.ts.map +1 -1
- package/dist/pricingCache.js +55 -3
- package/dist/pricingCache.js.map +1 -1
- package/dist/queryCache.d.ts.map +1 -1
- package/dist/queryCache.js +2 -0
- package/dist/queryCache.js.map +1 -1
- package/dist/reportBriefing.d.ts +89 -0
- package/dist/reportBriefing.d.ts.map +1 -0
- package/dist/reportBriefing.js +662 -0
- package/dist/reportBriefing.js.map +1 -0
- package/dist/searchTemplate.d.ts.map +1 -1
- package/dist/searchTemplate.js +65 -53
- package/dist/searchTemplate.js.map +1 -1
- package/dist/services/graphRouter.d.ts +7 -0
- package/dist/services/graphRouter.d.ts.map +1 -0
- package/dist/services/graphRouter.js +7 -0
- package/dist/services/graphRouter.js.map +1 -0
- package/dist/services/notifications.d.ts +2 -2
- package/dist/services/notifications.js +3 -3
- package/dist/services/notifications.js.map +1 -1
- package/dist/sessionTracker.d.ts +42 -3
- package/dist/sessionTracker.d.ts.map +1 -1
- package/dist/sessionTracker.js +261 -14
- package/dist/sessionTracker.js.map +1 -1
- package/dist/skillClient.d.ts.map +1 -1
- package/dist/skillClient.js +11 -6
- package/dist/skillClient.js.map +1 -1
- package/dist/svgVisuals.d.ts +17 -19
- package/dist/svgVisuals.d.ts.map +1 -1
- package/dist/svgVisuals.js +189 -233
- package/dist/svgVisuals.js.map +1 -1
- package/dist/systemPrompt.d.ts +7 -2
- package/dist/systemPrompt.d.ts.map +1 -1
- package/dist/systemPrompt.js +153 -81
- package/dist/systemPrompt.js.map +1 -1
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/telemetry.js +15 -0
- package/dist/telemetry.js.map +1 -1
- package/dist/test_adjacent_trends_polymorphic.d.ts +2 -0
- package/dist/test_adjacent_trends_polymorphic.d.ts.map +1 -0
- package/dist/test_adjacent_trends_polymorphic.js +154 -0
- package/dist/test_adjacent_trends_polymorphic.js.map +1 -0
- package/dist/test_book_a_call_live.d.ts +2 -0
- package/dist/test_book_a_call_live.d.ts.map +1 -0
- package/dist/test_book_a_call_live.js +161 -0
- package/dist/test_book_a_call_live.js.map +1 -0
- package/dist/test_brand_intelligence_endpoint.js +2 -2
- package/dist/test_byo_mcp_submission_clarity.d.ts +2 -0
- package/dist/test_byo_mcp_submission_clarity.d.ts.map +1 -0
- package/dist/test_byo_mcp_submission_clarity.js +142 -0
- package/dist/test_byo_mcp_submission_clarity.js.map +1 -0
- package/dist/test_capabilities_guidance.d.ts +2 -0
- package/dist/test_capabilities_guidance.d.ts.map +1 -0
- package/dist/test_capabilities_guidance.js +372 -0
- package/dist/test_capabilities_guidance.js.map +1 -0
- package/dist/test_client_provenance.d.ts +2 -0
- package/dist/test_client_provenance.d.ts.map +1 -0
- package/dist/test_client_provenance.js +77 -0
- package/dist/test_client_provenance.js.map +1 -0
- package/dist/test_connection_surface_cleanup.d.ts +2 -0
- package/dist/test_connection_surface_cleanup.d.ts.map +1 -0
- package/dist/test_connection_surface_cleanup.js +203 -0
- package/dist/test_connection_surface_cleanup.js.map +1 -0
- package/dist/test_consult_routing.d.ts +2 -0
- package/dist/test_consult_routing.d.ts.map +1 -0
- package/dist/test_consult_routing.js +86 -0
- package/dist/test_consult_routing.js.map +1 -0
- package/dist/test_consult_split.d.ts +2 -0
- package/dist/test_consult_split.d.ts.map +1 -0
- package/dist/test_consult_split.js +30 -0
- package/dist/test_consult_split.js.map +1 -0
- package/dist/test_coverage_relevance.d.ts +12 -0
- package/dist/test_coverage_relevance.d.ts.map +1 -0
- package/dist/test_coverage_relevance.js +162 -0
- package/dist/test_coverage_relevance.js.map +1 -0
- package/dist/test_coverage_replay.d.ts +2 -0
- package/dist/test_coverage_replay.d.ts.map +1 -0
- package/dist/test_coverage_replay.js +170 -0
- package/dist/test_coverage_replay.js.map +1 -0
- package/dist/test_dcr_and_legacy_deprecation.d.ts +2 -0
- package/dist/test_dcr_and_legacy_deprecation.d.ts.map +1 -0
- package/dist/test_dcr_and_legacy_deprecation.js +143 -0
- package/dist/test_dcr_and_legacy_deprecation.js.map +1 -0
- package/dist/test_demand_signal_logging.d.ts +2 -0
- package/dist/test_demand_signal_logging.d.ts.map +1 -0
- package/dist/test_demand_signal_logging.js +92 -0
- package/dist/test_demand_signal_logging.js.map +1 -0
- package/dist/test_earnings_activity_scope.d.ts +5 -0
- package/dist/test_earnings_activity_scope.d.ts.map +1 -0
- package/dist/test_earnings_activity_scope.js +101 -0
- package/dist/test_earnings_activity_scope.js.map +1 -0
- package/dist/test_earnings_divergence_live.d.ts +5 -0
- package/dist/test_earnings_divergence_live.d.ts.map +1 -0
- package/dist/test_earnings_divergence_live.js +135 -0
- package/dist/test_earnings_divergence_live.js.map +1 -0
- package/dist/test_earnings_hygiene_and_binding.d.ts +5 -0
- package/dist/test_earnings_hygiene_and_binding.d.ts.map +1 -0
- package/dist/test_earnings_hygiene_and_binding.js +104 -0
- package/dist/test_earnings_hygiene_and_binding.js.map +1 -0
- package/dist/test_exec_quotes_render.d.ts +2 -0
- package/dist/test_exec_quotes_render.d.ts.map +1 -0
- package/dist/test_exec_quotes_render.js +86 -0
- package/dist/test_exec_quotes_render.js.map +1 -0
- package/dist/test_expert_intro.d.ts +2 -0
- package/dist/test_expert_intro.d.ts.map +1 -0
- package/dist/test_expert_intro.js +57 -0
- package/dist/test_expert_intro.js.map +1 -0
- package/dist/test_expert_layer.d.ts +11 -0
- package/dist/test_expert_layer.d.ts.map +1 -0
- package/dist/test_expert_layer.js +356 -0
- package/dist/test_expert_layer.js.map +1 -0
- package/dist/test_financial_snapshot_render.d.ts +2 -0
- package/dist/test_financial_snapshot_render.d.ts.map +1 -0
- package/dist/test_financial_snapshot_render.js +167 -0
- package/dist/test_financial_snapshot_render.js.map +1 -0
- package/dist/test_gap_alert.d.ts +12 -0
- package/dist/test_gap_alert.d.ts.map +1 -0
- package/dist/test_gap_alert.js +51 -0
- package/dist/test_gap_alert.js.map +1 -0
- package/dist/test_grok_offering_surfaces.d.ts +2 -0
- package/dist/test_grok_offering_surfaces.d.ts.map +1 -0
- package/dist/test_grok_offering_surfaces.js +155 -0
- package/dist/test_grok_offering_surfaces.js.map +1 -0
- package/dist/test_human_agent_live.d.ts +2 -0
- package/dist/test_human_agent_live.d.ts.map +1 -0
- package/dist/test_human_agent_live.js +48 -0
- package/dist/test_human_agent_live.js.map +1 -0
- package/dist/test_identity_gap.d.ts +2 -0
- package/dist/test_identity_gap.d.ts.map +1 -0
- package/dist/test_identity_gap.js +171 -0
- package/dist/test_identity_gap.js.map +1 -0
- package/dist/test_intelligence_and_verifier.d.ts +17 -0
- package/dist/test_intelligence_and_verifier.d.ts.map +1 -0
- package/dist/test_intelligence_and_verifier.js +162 -0
- package/dist/test_intelligence_and_verifier.js.map +1 -0
- package/dist/test_latency_mcp_brief5.d.ts +12 -0
- package/dist/test_latency_mcp_brief5.d.ts.map +1 -0
- package/dist/test_latency_mcp_brief5.js +200 -0
- package/dist/test_latency_mcp_brief5.js.map +1 -0
- package/dist/test_limit_and_credit_card_capture.d.ts +21 -0
- package/dist/test_limit_and_credit_card_capture.d.ts.map +1 -0
- package/dist/test_limit_and_credit_card_capture.js +216 -0
- package/dist/test_limit_and_credit_card_capture.js.map +1 -0
- package/dist/test_list_graphs_topics.js +1 -1
- package/dist/test_list_graphs_topics.js.map +1 -1
- package/dist/test_live_deployed_mcp_search.d.ts +2 -0
- package/dist/test_live_deployed_mcp_search.d.ts.map +1 -0
- package/dist/test_live_deployed_mcp_search.js +85 -0
- package/dist/test_live_deployed_mcp_search.js.map +1 -0
- package/dist/test_live_deployed_split.d.ts +2 -0
- package/dist/test_live_deployed_split.d.ts.map +1 -0
- package/dist/test_live_deployed_split.js +72 -0
- package/dist/test_live_deployed_split.js.map +1 -0
- package/dist/test_live_endpoint_runner.js +2 -2
- package/dist/test_live_endpoint_runner.js.map +1 -1
- package/dist/test_live_mcp.js +1 -1
- package/dist/test_live_mcp.js.map +1 -1
- package/dist/test_live_neil_widget.d.ts +2 -0
- package/dist/test_live_neil_widget.d.ts.map +1 -0
- package/dist/test_live_neil_widget.js +84 -0
- package/dist/test_live_neil_widget.js.map +1 -0
- package/dist/test_longpoll_status.d.ts +2 -0
- package/dist/test_longpoll_status.d.ts.map +1 -0
- package/dist/test_longpoll_status.js +117 -0
- package/dist/test_longpoll_status.js.map +1 -0
- package/dist/test_mcp_find_expert_and_vocabulary_routing.d.ts +2 -0
- package/dist/test_mcp_find_expert_and_vocabulary_routing.d.ts.map +1 -0
- package/dist/test_mcp_find_expert_and_vocabulary_routing.js +130 -0
- package/dist/test_mcp_find_expert_and_vocabulary_routing.js.map +1 -0
- package/dist/test_next_moves.d.ts +2 -0
- package/dist/test_next_moves.d.ts.map +1 -0
- package/dist/test_next_moves.js +714 -0
- package/dist/test_next_moves.js.map +1 -0
- package/dist/test_next_moves_transcripts.d.ts +2 -0
- package/dist/test_next_moves_transcripts.d.ts.map +1 -0
- package/dist/test_next_moves_transcripts.js +495 -0
- package/dist/test_next_moves_transcripts.js.map +1 -0
- package/dist/test_on_request_caller_identity.d.ts +13 -0
- package/dist/test_on_request_caller_identity.d.ts.map +1 -0
- package/dist/test_on_request_caller_identity.js +131 -0
- package/dist/test_on_request_caller_identity.js.map +1 -0
- package/dist/test_on_request_intercept.d.ts +10 -0
- package/dist/test_on_request_intercept.d.ts.map +1 -0
- package/dist/test_on_request_intercept.js +95 -0
- package/dist/test_on_request_intercept.js.map +1 -0
- package/dist/test_onboarding_consent_and_errors.d.ts +2 -0
- package/dist/test_onboarding_consent_and_errors.d.ts.map +1 -0
- package/dist/test_onboarding_consent_and_errors.js +110 -0
- package/dist/test_onboarding_consent_and_errors.js.map +1 -0
- package/dist/test_onboarding_live_scenarios.d.ts +2 -0
- package/dist/test_onboarding_live_scenarios.d.ts.map +1 -0
- package/dist/test_onboarding_live_scenarios.js +189 -0
- package/dist/test_onboarding_live_scenarios.js.map +1 -0
- package/dist/test_referral_live.d.ts +2 -0
- package/dist/test_referral_live.d.ts.map +1 -0
- package/dist/test_referral_live.js +33 -0
- package/dist/test_referral_live.js.map +1 -0
- package/dist/test_referral_piers.d.ts +2 -0
- package/dist/test_referral_piers.d.ts.map +1 -0
- package/dist/test_referral_piers.js +33 -0
- package/dist/test_referral_piers.js.map +1 -0
- package/dist/test_report_editorial_briefing.d.ts +21 -0
- package/dist/test_report_editorial_briefing.d.ts.map +1 -0
- package/dist/test_report_editorial_briefing.js +356 -0
- package/dist/test_report_editorial_briefing.js.map +1 -0
- package/dist/test_search_graph_quality.d.ts +2 -0
- package/dist/test_search_graph_quality.d.ts.map +1 -0
- package/dist/test_search_graph_quality.js +493 -0
- package/dist/test_search_graph_quality.js.map +1 -0
- package/dist/test_service_to_service_auth.d.ts +2 -0
- package/dist/test_service_to_service_auth.d.ts.map +1 -0
- package/dist/test_service_to_service_auth.js +199 -0
- package/dist/test_service_to_service_auth.js.map +1 -0
- package/dist/test_session_next_moves_telemetry.d.ts +2 -0
- package/dist/test_session_next_moves_telemetry.d.ts.map +1 -0
- package/dist/test_session_next_moves_telemetry.js +100 -0
- package/dist/test_session_next_moves_telemetry.js.map +1 -0
- package/dist/test_sources_live.d.ts +2 -0
- package/dist/test_sources_live.d.ts.map +1 -0
- package/dist/test_sources_live.js +30 -0
- package/dist/test_sources_live.js.map +1 -0
- package/dist/test_specialist_and_analyst_tiers.d.ts +2 -0
- package/dist/test_specialist_and_analyst_tiers.d.ts.map +1 -0
- package/dist/test_specialist_and_analyst_tiers.js +155 -0
- package/dist/test_specialist_and_analyst_tiers.js.map +1 -0
- package/dist/test_v2_2_visual_hardening.d.ts +5 -0
- package/dist/test_v2_2_visual_hardening.d.ts.map +1 -0
- package/dist/test_v2_2_visual_hardening.js +333 -0
- package/dist/test_v2_2_visual_hardening.js.map +1 -0
- package/dist/test_verify_deprecate_render_spec.d.ts +2 -0
- package/dist/test_verify_deprecate_render_spec.d.ts.map +1 -0
- package/dist/test_verify_deprecate_render_spec.js +217 -0
- package/dist/test_verify_deprecate_render_spec.js.map +1 -0
- package/dist/test_verify_neil_demo.d.ts +2 -0
- package/dist/test_verify_neil_demo.d.ts.map +1 -0
- package/dist/test_verify_neil_demo.js +149 -0
- package/dist/test_verify_neil_demo.js.map +1 -0
- package/dist/test_waitable_research_and_grounded_links.d.ts +2 -0
- package/dist/test_waitable_research_and_grounded_links.d.ts.map +1 -0
- package/dist/test_waitable_research_and_grounded_links.js +129 -0
- package/dist/test_waitable_research_and_grounded_links.js.map +1 -0
- package/dist/test_widget_guards.d.ts +2 -0
- package/dist/test_widget_guards.d.ts.map +1 -0
- package/dist/test_widget_guards.js +229 -0
- package/dist/test_widget_guards.js.map +1 -0
- package/dist/test_zero_retention_alerts.d.ts +14 -0
- package/dist/test_zero_retention_alerts.d.ts.map +1 -0
- package/dist/test_zero_retention_alerts.js +76 -0
- package/dist/test_zero_retention_alerts.js.map +1 -0
- package/dist/toolHandlers.d.ts +38 -1
- package/dist/toolHandlers.d.ts.map +1 -1
- package/dist/toolHandlers.js +4290 -711
- package/dist/toolHandlers.js.map +1 -1
- package/dist/tools.d.ts +22 -1
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +29 -4
- package/dist/tools.js.map +1 -1
- package/dist/verify_tools_endpoint.js +19 -5
- package/dist/verify_tools_endpoint.js.map +1 -1
- package/dist/widgetShell.d.ts +2 -2
- package/dist/widgetShell.d.ts.map +1 -1
- package/dist/widgetShell.js +1 -1
- package/dist/widgetShell.js.map +1 -1
- package/package.json +1 -1
- package/server.json +3 -31
- package/dist/debug_tools.d.ts +0 -2
- package/dist/debug_tools.d.ts.map +0 -1
- package/dist/debug_tools.js +0 -19
- package/dist/debug_tools.js.map +0 -1
- package/dist/inspect_list_graphs.d.ts +0 -2
- package/dist/inspect_list_graphs.d.ts.map +0 -1
- package/dist/inspect_list_graphs.js +0 -25
- package/dist/inspect_list_graphs.js.map +0 -1
- package/dist/scratch_test.d.ts.map +0 -1
- package/dist/scripts/simulate_gemini.d.ts +0 -2
- package/dist/scripts/simulate_gemini.d.ts.map +0 -1
- package/dist/scripts/simulate_gemini.js +0 -100
- package/dist/scripts/simulate_gemini.js.map +0 -1
- package/dist/scripts/verify_registry.d.ts +0 -2
- package/dist/scripts/verify_registry.d.ts.map +0 -1
- package/dist/scripts/verify_registry.js +0 -77
- package/dist/scripts/verify_registry.js.map +0 -1
- package/dist/src/index.d.ts +0 -2
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/index.js +0 -332
- package/dist/src/index.js.map +0 -1
- package/dist/src/tools.d.ts +0 -12
- package/dist/src/tools.d.ts.map +0 -1
- package/dist/src/tools.js +0 -104
- package/dist/src/tools.js.map +0 -1
- package/dist/src/types.d.ts +0 -44
- package/dist/src/types.d.ts.map +0 -1
- package/dist/src/types.js +0 -2
- package/dist/src/types.js.map +0 -1
- package/dist/src/verify.d.ts +0 -2
- package/dist/src/verify.d.ts.map +0 -1
- package/dist/src/verify.js +0 -47
- package/dist/src/verify.js.map +0 -1
- package/dist/src/verify_hmac.d.ts +0 -2
- package/dist/src/verify_hmac.d.ts.map +0 -1
- package/dist/src/verify_hmac.js +0 -106
- package/dist/src/verify_hmac.js.map +0 -1
- package/dist/src/verify_tools_endpoint.d.ts +0 -2
- package/dist/src/verify_tools_endpoint.d.ts.map +0 -1
- package/dist/src/verify_tools_endpoint.js +0 -40
- package/dist/src/verify_tools_endpoint.js.map +0 -1
- package/dist/test-waverunner-response.d.ts +0 -2
- package/dist/test-waverunner-response.d.ts.map +0 -1
- package/dist/test-waverunner-response.js +0 -20
- package/dist/test-waverunner-response.js.map +0 -1
- package/dist/test_coverage_r2.d.ts +0 -2
- package/dist/test_coverage_r2.d.ts.map +0 -1
- package/dist/test_coverage_scratch.d.ts +0 -2
- package/dist/test_coverage_scratch.d.ts.map +0 -1
package/dist/brandTemplate.js
CHANGED
|
@@ -175,12 +175,23 @@ function velocityClass(trend) {
|
|
|
175
175
|
function gtY(value) {
|
|
176
176
|
return Math.round(88 - (value / 100 * 76));
|
|
177
177
|
}
|
|
178
|
+
function formatMonthYear(dStr) {
|
|
179
|
+
if (!dStr)
|
|
180
|
+
return '12m ago';
|
|
181
|
+
const d = new Date(dStr);
|
|
182
|
+
if (isNaN(d.getTime()))
|
|
183
|
+
return '12m ago';
|
|
184
|
+
const mon = d.toLocaleString('en-US', { month: 'short' });
|
|
185
|
+
const yr = String(d.getFullYear()).slice(-2);
|
|
186
|
+
return `${mon} '${yr}`;
|
|
187
|
+
}
|
|
178
188
|
function buildGoogleTrendsSVG(gtData) {
|
|
179
189
|
const defaults = {
|
|
180
190
|
polyline: '0,88 300,88', polygon: '0,88 300,88,300,88,0,88',
|
|
181
191
|
peakX: 150, peakY: 88, peakLabel: '', nowLabel: '',
|
|
182
192
|
annX: 297, annY: 84, annText: '', description: 'Google Trends',
|
|
183
193
|
caption: 'Relative interest (0–100). Not absolute volume. Source: Google Trends.',
|
|
194
|
+
startDateLabel: '12m ago',
|
|
184
195
|
relatedQueriesHtml: '',
|
|
185
196
|
comparisonBarsHtml: '',
|
|
186
197
|
};
|
|
@@ -212,6 +223,7 @@ function buildGoogleTrendsSVG(gtData) {
|
|
|
212
223
|
const peakY = gtY(peakVal);
|
|
213
224
|
const peakDate = points[peakIdx]?.date || '';
|
|
214
225
|
const trend = lastVal > peakVal * 0.9 ? '↑ near peak' : lastVal > peakVal * 0.6 ? '↑ rising' : '→ moderate';
|
|
226
|
+
const startDateLabel = points[0]?.date ? formatMonthYear(points[0].date) : '12m ago';
|
|
215
227
|
const relatedQueriesHtml = (gt.related_queries || [])
|
|
216
228
|
.slice(0, 8)
|
|
217
229
|
.map((q) => `<span class="rqp">${esc(q)}</span>`)
|
|
@@ -229,6 +241,7 @@ function buildGoogleTrendsSVG(gtData) {
|
|
|
229
241
|
annX: 297, annY: lastY - 4, annText: trend,
|
|
230
242
|
description: `"${gt.query || 'brand'}", US, past 12 months`,
|
|
231
243
|
caption: 'Relative interest (0–100). Not absolute volume. Source: Google Trends.',
|
|
244
|
+
startDateLabel,
|
|
232
245
|
relatedQueriesHtml,
|
|
233
246
|
comparisonBarsHtml,
|
|
234
247
|
};
|
|
@@ -241,6 +254,46 @@ function barRow(label, value, maxValue) {
|
|
|
241
254
|
return `<div class="br"><div class="brl">${esc(label)}</div><div class="brt"><div class="brf" style="width:${pct}%"></div></div><div class="brc">${value.toLocaleString()}</div></div>`;
|
|
242
255
|
}
|
|
243
256
|
// ---------------------------------------------------------------------------
|
|
257
|
+
// Financial data formatting helpers
|
|
258
|
+
// ---------------------------------------------------------------------------
|
|
259
|
+
function formatFinancialCurrency(val) {
|
|
260
|
+
if (val === undefined || val === null || isNaN(val))
|
|
261
|
+
return '—';
|
|
262
|
+
const abs = Math.abs(val);
|
|
263
|
+
const sign = val < 0 ? '-' : '';
|
|
264
|
+
if (abs >= 1e9) {
|
|
265
|
+
return `${sign}$${(abs / 1e9).toFixed(2)}B`;
|
|
266
|
+
}
|
|
267
|
+
if (abs >= 1e6) {
|
|
268
|
+
return `${sign}$${(abs / 1e6).toFixed(1)}M`;
|
|
269
|
+
}
|
|
270
|
+
if (abs >= 1e3) {
|
|
271
|
+
return `${sign}$${(abs / 1e3).toFixed(1)}K`;
|
|
272
|
+
}
|
|
273
|
+
return `${sign}$${abs.toLocaleString()}`;
|
|
274
|
+
}
|
|
275
|
+
function formatEps(eps, dilutedEps) {
|
|
276
|
+
if ((eps === undefined || eps === null || isNaN(eps)) && (dilutedEps === undefined || dilutedEps === null || isNaN(dilutedEps))) {
|
|
277
|
+
return '—';
|
|
278
|
+
}
|
|
279
|
+
const fmt = (v) => `${v < 0 ? '-' : ''}$${Math.abs(v).toFixed(2)}`;
|
|
280
|
+
if (eps != null && !isNaN(eps) && dilutedEps != null && !isNaN(dilutedEps)) {
|
|
281
|
+
return `${fmt(eps)} (Diluted ${fmt(dilutedEps)})`;
|
|
282
|
+
}
|
|
283
|
+
if (eps != null && !isNaN(eps)) {
|
|
284
|
+
return fmt(eps);
|
|
285
|
+
}
|
|
286
|
+
return `${fmt(dilutedEps)} (diluted)`;
|
|
287
|
+
}
|
|
288
|
+
function formatStockPrice(priceWindow) {
|
|
289
|
+
if (!priceWindow || priceWindow.current_price == null || isNaN(priceWindow.current_price))
|
|
290
|
+
return '';
|
|
291
|
+
const dateStr = priceWindow.as_of_date ? ` (as of ${esc(priceWindow.as_of_date)})` : '';
|
|
292
|
+
const p = priceWindow.current_price;
|
|
293
|
+
const priceFormatted = `${p < 0 ? '-' : ''}$${Math.abs(p).toFixed(2)}`;
|
|
294
|
+
return `${priceFormatted}${dateStr}`;
|
|
295
|
+
}
|
|
296
|
+
// ---------------------------------------------------------------------------
|
|
244
297
|
// Main render function
|
|
245
298
|
// ---------------------------------------------------------------------------
|
|
246
299
|
export async function renderBrandWidget(profile) {
|
|
@@ -250,7 +303,62 @@ export async function renderBrandWidget(profile) {
|
|
|
250
303
|
const competitors = profile.competitive_context?.co_occurring_brands || [];
|
|
251
304
|
const crossGraph = profile.cross_graph_presence || [];
|
|
252
305
|
const supplemental = profile.supplemental_signals || {};
|
|
253
|
-
const
|
|
306
|
+
const lcDist = profile.summary?.lifecycle_distribution || {};
|
|
307
|
+
const buildingCount = (lcDist.building || 0) + (lcDist.emerging || 0);
|
|
308
|
+
const fadingCount = (lcDist.fading || 0) + (lcDist.mature || 0);
|
|
309
|
+
// Enrich trends with lifecycle if missing
|
|
310
|
+
trends.forEach((t) => {
|
|
311
|
+
if (!t.lifecycle || t.lifecycle === 'unknown') {
|
|
312
|
+
t.lifecycle = computeLifecycle(t);
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
// Derive headline verdict from per-trend momentums and lifecycle distribution
|
|
316
|
+
let accCount = 0;
|
|
317
|
+
let bldCount = 0;
|
|
318
|
+
let stdCount = 0;
|
|
319
|
+
let slowCount = 0;
|
|
320
|
+
trends.forEach((t) => {
|
|
321
|
+
const m = typeof t.momentum === 'string' ? t.momentum : (t.momentum?.trend || t.momentum?.state || '');
|
|
322
|
+
if (m === 'accelerating' || t.momentum?.fastMover)
|
|
323
|
+
accCount++;
|
|
324
|
+
else if (m === 'building')
|
|
325
|
+
bldCount++;
|
|
326
|
+
else if (m === 'slowing' || m === 'fading')
|
|
327
|
+
slowCount++;
|
|
328
|
+
else if (m === 'steady')
|
|
329
|
+
stdCount++;
|
|
330
|
+
else {
|
|
331
|
+
// fallback to lifecycle if momentum not explicitly set
|
|
332
|
+
if (t.lifecycle === 'emerging')
|
|
333
|
+
accCount++;
|
|
334
|
+
else if (t.lifecycle === 'building')
|
|
335
|
+
bldCount++;
|
|
336
|
+
else if (t.lifecycle === 'fading')
|
|
337
|
+
slowCount++;
|
|
338
|
+
else
|
|
339
|
+
stdCount++;
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
let rawVelocityTrend = 'stable';
|
|
343
|
+
const totalWithMomentum = accCount + bldCount + stdCount + slowCount;
|
|
344
|
+
if (totalWithMomentum > 0) {
|
|
345
|
+
if ((accCount + bldCount) > slowCount && accCount >= bldCount && accCount > 0) {
|
|
346
|
+
rawVelocityTrend = 'accelerating';
|
|
347
|
+
}
|
|
348
|
+
else if ((accCount + bldCount) > slowCount && bldCount > 0) {
|
|
349
|
+
rawVelocityTrend = 'building';
|
|
350
|
+
}
|
|
351
|
+
else if (slowCount > (accCount + bldCount) && slowCount > stdCount) {
|
|
352
|
+
rawVelocityTrend = 'decelerating';
|
|
353
|
+
}
|
|
354
|
+
else {
|
|
355
|
+
rawVelocityTrend = 'stable';
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
else {
|
|
359
|
+
rawVelocityTrend = profile.summary?.evidence_velocity?.trend || 'stable';
|
|
360
|
+
}
|
|
361
|
+
const velocity = velocityClass(rawVelocityTrend);
|
|
254
362
|
const timeline = profile.activity_timeline || [];
|
|
255
363
|
// Build set of graphIds the target brand is present in (for sector-aware competitor labels)
|
|
256
364
|
const brandGraphIds = new Set(crossGraph.map((g) => g.graphId).filter(Boolean));
|
|
@@ -267,28 +375,28 @@ export async function renderBrandWidget(profile) {
|
|
|
267
375
|
const parts = [];
|
|
268
376
|
if (truthLayer.headline) {
|
|
269
377
|
parts.push(`<div class="ec">
|
|
270
|
-
<div class="et" style="font-size:13px;font-weight:600;">${esc(truthLayer.company || '')} — ${esc(truthLayer.period || '')}</div>
|
|
378
|
+
<div class="et" style="font-size:13px;font-weight:600;">${esc(truthLayer.company || '')} — ${esc(truthLayer.period || '')} Earnings Call Analysis</div>
|
|
271
379
|
<div class="ex" style="font-weight:500;margin-top:4px;">${esc(truthLayer.headline)}</div>
|
|
272
380
|
</div>`);
|
|
273
381
|
}
|
|
274
382
|
if (truthLayer.analyst_concerns) {
|
|
275
383
|
parts.push(`<div class="ec">
|
|
276
|
-
<div class="et" style="font-size:11px;font-weight:
|
|
384
|
+
<div class="et" style="font-size:11px;font-weight:600;color:var(--color-text-warning);">Wall Street Analyst Concerns & Q&A Focus</div>
|
|
277
385
|
<div class="ex">${esc(truthLayer.analyst_concerns)}</div>
|
|
278
386
|
</div>`);
|
|
279
387
|
}
|
|
280
388
|
if (truthLayer.analyst_sentiment) {
|
|
281
389
|
parts.push(`<div class="ec">
|
|
282
|
-
<div class="et" style="font-size:11px;font-weight:
|
|
390
|
+
<div class="et" style="font-size:11px;font-weight:600;">Institutional Analyst Consensus & Sentiment</div>
|
|
283
391
|
<div class="ex">${esc(truthLayer.analyst_sentiment)}</div>
|
|
284
392
|
</div>`);
|
|
285
393
|
}
|
|
286
394
|
// Activity fields — show if present
|
|
287
395
|
const activities = [
|
|
288
|
-
{ key: 'marketing_activity', label: 'Marketing' },
|
|
289
|
-
{ key: 'retail_activity', label: 'Retail' },
|
|
290
|
-
{ key: 'technology_activity', label: 'Technology' },
|
|
291
|
-
{ key: 'sustainability_activity', label: 'Sustainability' },
|
|
396
|
+
{ key: 'marketing_activity', label: 'Marketing & Brand Building' },
|
|
397
|
+
{ key: 'retail_activity', label: 'Retail & Channel Expansion' },
|
|
398
|
+
{ key: 'technology_activity', label: 'Technology & AI Infrastructure' },
|
|
399
|
+
{ key: 'sustainability_activity', label: 'ESG & Sustainability' },
|
|
292
400
|
];
|
|
293
401
|
const activityPills = activities
|
|
294
402
|
.filter(a => truthLayer[a.key])
|
|
@@ -296,13 +404,13 @@ export async function renderBrandWidget(profile) {
|
|
|
296
404
|
.join('');
|
|
297
405
|
if (activityPills) {
|
|
298
406
|
parts.push(`<div class="ec">
|
|
299
|
-
<div class="et" style="font-size:11px;font-weight:
|
|
407
|
+
<div class="et" style="font-size:11px;font-weight:600;">Management Focus & Strategic Investment Areas</div>
|
|
300
408
|
<div class="rq" style="margin-top:4px;">${activityPills}</div>
|
|
301
409
|
</div>`);
|
|
302
410
|
}
|
|
303
411
|
if (truthLayer.exec_sentiment) {
|
|
304
412
|
parts.push(`<div class="ec">
|
|
305
|
-
<div class="et" style="font-size:11px;font-weight:
|
|
413
|
+
<div class="et" style="font-size:11px;font-weight:600;">C-Suite Executive Outlook & Forward Guidance</div>
|
|
306
414
|
<div class="ex">${esc(truthLayer.exec_sentiment)}${truthLayer.quote_from_ceo ? ` — "${esc(truthLayer.quote_from_ceo)}"` : ''}</div>
|
|
307
415
|
</div>`);
|
|
308
416
|
}
|
|
@@ -312,7 +420,7 @@ export async function renderBrandWidget(profile) {
|
|
|
312
420
|
.map((t) => `<span class="rqp">${esc(t.trend_name)}</span>`)
|
|
313
421
|
.join('');
|
|
314
422
|
parts.push(`<div class="ec">
|
|
315
|
-
<div class="et" style="font-size:11px;font-weight:
|
|
423
|
+
<div class="et" style="font-size:11px;font-weight:600;color:var(--color-text-success);">Market Trends Confirmed by Executives</div>
|
|
316
424
|
<div class="rq" style="margin-top:4px;">${trendPills}</div>
|
|
317
425
|
</div>`);
|
|
318
426
|
}
|
|
@@ -335,6 +443,59 @@ export async function renderBrandWidget(profile) {
|
|
|
335
443
|
</div>`;
|
|
336
444
|
}).join('\n');
|
|
337
445
|
}
|
|
446
|
+
// ── Institutional Financial Snapshot (Market Data) section ──
|
|
447
|
+
const marketData = profile.market_data;
|
|
448
|
+
let financialSnapshotHtml = '';
|
|
449
|
+
if (marketData && marketData.data_status !== 'no_signal') {
|
|
450
|
+
const symbol = marketData.primary_symbol || marketData.ticker || '';
|
|
451
|
+
const profileInfo = marketData.company_profile;
|
|
452
|
+
const companyName = profileInfo?.company_name || profile.brand || '';
|
|
453
|
+
const sector = profileInfo?.sector || '';
|
|
454
|
+
const industry = profileInfo?.industry || '';
|
|
455
|
+
const priceStr = formatStockPrice(marketData.price_window);
|
|
456
|
+
const quarters = (marketData.quarterly_financials || []).slice(0, 2);
|
|
457
|
+
const hasContent = Boolean(symbol || profileInfo || priceStr || quarters.length > 0);
|
|
458
|
+
if (hasContent) {
|
|
459
|
+
const headerTitle = companyName ? `${esc(companyName)}${symbol ? ` (${esc(symbol)})` : ''}` : esc(symbol);
|
|
460
|
+
const metaTokens = [];
|
|
461
|
+
if (sector)
|
|
462
|
+
metaTokens.push(`Sector: ${esc(sector)}`);
|
|
463
|
+
if (industry)
|
|
464
|
+
metaTokens.push(`Industry: ${esc(industry)}`);
|
|
465
|
+
const metaHtml = metaTokens.length > 0
|
|
466
|
+
? `<div style="font-size:11px;color:var(--color-text-secondary);margin-top:2px;margin-bottom:8px;">${metaTokens.join(' · ')}</div>`
|
|
467
|
+
: '';
|
|
468
|
+
const priceHtml = priceStr
|
|
469
|
+
? `<div style="font-size:12px;color:var(--color-text-primary);margin-bottom:8px;font-weight:500;">Stock Price: <span style="font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-weight:600;">${priceStr}</span></div>`
|
|
470
|
+
: '';
|
|
471
|
+
let quartersHtml = '';
|
|
472
|
+
if (quarters.length > 0) {
|
|
473
|
+
const qCards = quarters.map((q) => {
|
|
474
|
+
const qPeriod = q.period || q.period_label || 'Quarterly Financials';
|
|
475
|
+
const rev = formatFinancialCurrency(q.revenue);
|
|
476
|
+
const opInc = formatFinancialCurrency(q.operating_income);
|
|
477
|
+
const netInc = formatFinancialCurrency(q.net_income);
|
|
478
|
+
const eps = formatEps(q.eps, q.diluted_eps);
|
|
479
|
+
return `<div style="background:var(--color-background-secondary);border-radius:6px;padding:8px 10px;margin-top:6px;">
|
|
480
|
+
<div style="font-size:11px;font-weight:600;color:var(--color-text-primary);margin-bottom:4px;">${esc(qPeriod)}</div>
|
|
481
|
+
<div style="display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px;font-size:11px;">
|
|
482
|
+
<div><span style="color:var(--color-text-secondary);">Revenue:</span> <strong style="font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;">${rev}</strong></div>
|
|
483
|
+
<div><span style="color:var(--color-text-secondary);">Op. Income:</span> <strong style="font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;">${opInc}</strong></div>
|
|
484
|
+
<div><span style="color:var(--color-text-secondary);">Net Income:</span> <strong style="font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;">${netInc}</strong></div>
|
|
485
|
+
<div><span style="color:var(--color-text-secondary);">EPS:</span> <strong style="font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;">${eps}</strong></div>
|
|
486
|
+
</div>
|
|
487
|
+
</div>`;
|
|
488
|
+
}).join('\n');
|
|
489
|
+
quartersHtml = `<div style="margin-top:6px;">${qCards}</div>`;
|
|
490
|
+
}
|
|
491
|
+
financialSnapshotHtml = `<div class="ec">
|
|
492
|
+
<div class="et" style="font-size:13px;font-weight:600;">${headerTitle}</div>
|
|
493
|
+
${metaHtml}
|
|
494
|
+
${priceHtml}
|
|
495
|
+
${quartersHtml}
|
|
496
|
+
</div>`;
|
|
497
|
+
}
|
|
498
|
+
}
|
|
338
499
|
// Enrich trends with lifecycle if missing
|
|
339
500
|
trends.forEach((t) => {
|
|
340
501
|
if (!t.lifecycle || t.lifecycle === 'unknown') {
|
|
@@ -342,7 +503,6 @@ export async function renderBrandWidget(profile) {
|
|
|
342
503
|
}
|
|
343
504
|
});
|
|
344
505
|
// ── Lifecycle bar ──
|
|
345
|
-
const lcDist = profile.summary?.lifecycle_distribution || {};
|
|
346
506
|
const lcTotal = Object.values(lcDist).reduce((a, b) => a + b, 0);
|
|
347
507
|
const lcColors = { building: 'var(--color-text-info)', emerging: 'var(--color-text-success)', mature: 'var(--color-text-secondary)', fading: 'var(--color-text-warning)' };
|
|
348
508
|
const lifecycleBar = Object.entries(lcDist)
|
|
@@ -359,8 +519,7 @@ export async function renderBrandWidget(profile) {
|
|
|
359
519
|
weakSignals.forEach((t) => weakSignalNames.add(t.trend_name?.trim()));
|
|
360
520
|
// ── Trend cards (exclude weak signals to avoid duplication) ──
|
|
361
521
|
const mainTrends = trends.filter((t) => !weakSignalNames.has(t.trend_name?.trim()));
|
|
362
|
-
const trendsHtml = mainTrends.map((t
|
|
363
|
-
const spark = deriveSparklineShape(t);
|
|
522
|
+
const trendsHtml = mainTrends.map((t) => {
|
|
364
523
|
const tName = (t.trend_name || '').trim();
|
|
365
524
|
const badges = [
|
|
366
525
|
`<span class="bdp">${esc(t.graphName)}</span>`,
|
|
@@ -405,8 +564,10 @@ export async function renderBrandWidget(profile) {
|
|
|
405
564
|
const parsed = new Date(ev.published_at);
|
|
406
565
|
date = isNaN(parsed.getTime()) ? '' : parsed.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' });
|
|
407
566
|
}
|
|
408
|
-
const
|
|
409
|
-
|
|
567
|
+
const dateBadge = date ? `<span class="bd">${esc(date)}</span>` : '';
|
|
568
|
+
const hasRealUrl = ev.source_url && !ev.source_url.startsWith('https://fodda.ai') && !ev.source_url.startsWith('https://www.fodda.ai');
|
|
569
|
+
const titleHtml = hasRealUrl
|
|
570
|
+
? `<a href="${esc(ev.source_url)}" target="_blank" rel="noopener noreferrer">${esc(ev.title)}</a>`
|
|
410
571
|
: esc(ev.title);
|
|
411
572
|
const speakerHtml = ev.speaker_name ? `<div style="font-size:11px;color:var(--color-text-secondary);margin-top:4px;font-style:italic;">${esc(ev.speaker_name)}${ev.speaker_title ? ', ' + esc(ev.speaker_title) : ''}</div>` : '';
|
|
412
573
|
return `<div class="ec">
|
|
@@ -416,7 +577,7 @@ export async function renderBrandWidget(profile) {
|
|
|
416
577
|
<div class="em">
|
|
417
578
|
<span class="lb ${catClass(ev.category)} bd">${esc(ev.category)}</span>
|
|
418
579
|
<span class="bdp">${esc(ev.graphName)}</span>
|
|
419
|
-
|
|
580
|
+
${dateBadge}
|
|
420
581
|
${placeBadge}
|
|
421
582
|
</div>
|
|
422
583
|
</div>`;
|
|
@@ -436,24 +597,6 @@ export async function renderBrandWidget(profile) {
|
|
|
436
597
|
</div>
|
|
437
598
|
</div>`;
|
|
438
599
|
}).join('\n');
|
|
439
|
-
// ── Network SVG ──
|
|
440
|
-
const topComps = competitors.slice(0, 5);
|
|
441
|
-
const networkNodesHtml = topComps.map((c, i) => {
|
|
442
|
-
const pos = ORBIT_POSITIONS[i] || { cx: 150, cy: 113 };
|
|
443
|
-
const pType = guessPressureType(i, c, brandGraphIds, domainGIds);
|
|
444
|
-
const colors = PRESSURE_COLORS[pType] || DEFAULT_PRESSURE;
|
|
445
|
-
return `<line x1="150" y1="113" x2="${pos.cx}" y2="${pos.cy}" stroke="${colors.color}" stroke-width="0.5" stroke-dasharray="3,3"/>
|
|
446
|
-
<circle cx="${pos.cx}" cy="${pos.cy}" r="18" fill="${colors.bg}" stroke="${colors.color}" stroke-width="1"/>
|
|
447
|
-
<text x="${pos.cx}" y="${pos.cy + 3}" class="svgt" font-size="7.5" text-anchor="middle" fill="${colors.color}">${esc(truncSvg(c.brand))}</text>`;
|
|
448
|
-
}).join('\n ');
|
|
449
|
-
// Network legend — bottom-right (avoid overlapping left orbit node)
|
|
450
|
-
const legendTypes = [...new Set(topComps.map((c, i) => guessPressureType(i, c, brandGraphIds, domainGIds)))].slice(0, 5);
|
|
451
|
-
const networkLegendHtml = legendTypes.map((pType, i) => {
|
|
452
|
-
const colors = PRESSURE_COLORS[pType] || DEFAULT_PRESSURE;
|
|
453
|
-
const y = 190 + i * 11;
|
|
454
|
-
return `<rect x="200" y="${y}" width="6" height="6" rx="1" fill="${colors.bg}" stroke="${colors.color}" stroke-width=".5"/>
|
|
455
|
-
<text x="210" y="${y + 5}" class="svgt" font-size="6" fill="var(--color-text-secondary)">${pType}</text>`;
|
|
456
|
-
}).join('\n ');
|
|
457
600
|
// ── Compare buttons ──
|
|
458
601
|
const compareButtonsHtml = competitors.slice(0, 4).map((c) => `<button class="cp" onclick="sendPrompt('brand intelligence: ${esc(c.brand)}')">${esc(c.brand)} ↗</button>`).join('\n ');
|
|
459
602
|
// ── Google Trends ──
|
|
@@ -515,6 +658,8 @@ export async function renderBrandWidget(profile) {
|
|
|
515
658
|
const graphNames = crossGraph.map((g) => g.graphName).filter(Boolean);
|
|
516
659
|
const sourcePills = [
|
|
517
660
|
...graphNames.map((n) => `<span class="gp">${esc(n)}</span>`),
|
|
661
|
+
(earningsSource === 'truth_layer' || earnings.length > 0) ? '<span class="gp">Earnings Intelligence</span>' : '',
|
|
662
|
+
(marketData && marketData.data_status !== 'no_signal') ? '<span class="gp">Financial Snapshot</span>' : '',
|
|
518
663
|
hasGoogleTrendsData ? '<span class="gp">Google Trends</span>' : '',
|
|
519
664
|
supplemental?.wikipedia ? '<span class="gp">Wikipedia</span>' : '',
|
|
520
665
|
supplemental?.amazon ? '<span class="gp">Amazon</span>' : '',
|
|
@@ -541,24 +686,24 @@ export async function renderBrandWidget(profile) {
|
|
|
541
686
|
'TRENDS_HTML': trendsHtml,
|
|
542
687
|
'WEAK_SIGNALS_HTML': weakSignalsHtml,
|
|
543
688
|
'EVIDENCE_HTML': evidenceHtml,
|
|
544
|
-
'
|
|
689
|
+
'COMPETITIVE_SECTION_HTML': competitors.length > 0 ? `<div class="sec">Competitive</div>\n${competitorListHtml}` : '',
|
|
545
690
|
'GT_SECTION_HTML': hasGoogleTrendsData ? `<div class="sl2">${gt.description}</div>
|
|
546
691
|
<svg viewBox="0 0 300 96" xmlns="http://www.w3.org/2000/svg" style="width:100%;height:96px;margin-bottom:4px;">
|
|
547
692
|
<defs>
|
|
548
693
|
<linearGradient id="gtg" x1="0" y1="0" x2="0" y2="1">
|
|
549
|
-
<stop offset="0%" stop-color="#663399" stop-opacity=".
|
|
550
|
-
<stop offset="100%" stop-color="#663399" stop-opacity="0"/>
|
|
694
|
+
<stop offset="0%" stop-color="var(--fodda-accent, #663399)" stop-opacity=".18"/>
|
|
695
|
+
<stop offset="100%" stop-color="var(--fodda-accent, #663399)" stop-opacity="0"/>
|
|
551
696
|
</linearGradient>
|
|
552
697
|
</defs>
|
|
553
698
|
<polygon points="${gt.polygon}" fill="url(#gtg)"/>
|
|
554
|
-
<polyline points="${gt.polyline}" fill="none" stroke="#663399" stroke-width="1.5" stroke-linejoin="round"/>
|
|
699
|
+
<polyline points="${gt.polyline}" fill="none" stroke="var(--fodda-accent, #663399)" stroke-width="1.5" stroke-linejoin="round"/>
|
|
555
700
|
<line x1="0" y1="88" x2="300" y2="88" stroke="var(--color-border-tertiary)" stroke-width=".5"/>
|
|
556
|
-
<text x="2" y="93" font-size="7" fill="var(--color-text-secondary)" font-family="monospace"
|
|
701
|
+
<text x="2" y="93" font-size="7" fill="var(--color-text-secondary)" font-family="monospace">${gt.startDateLabel}</text>
|
|
557
702
|
<text x="150" y="93" font-size="7" fill="var(--color-text-secondary)" text-anchor="middle" font-family="monospace">${gt.peakLabel}</text>
|
|
558
703
|
<text x="298" y="93" font-size="7" fill="var(--color-text-secondary)" text-anchor="end" font-family="monospace">${gt.nowLabel}</text>
|
|
559
|
-
<circle cx="${gt.peakX}" cy="${gt.peakY}" r="2" fill="#663399"/>
|
|
560
|
-
<circle cx="300" cy="${gt.annY}" r="2.5" fill="#663399"/>
|
|
561
|
-
<text x="${gt.annX}" y="${gt.annY}" font-size="7" fill="#663399" text-anchor="end" font-family="monospace">${gt.annText}</text>
|
|
704
|
+
<circle cx="${gt.peakX}" cy="${gt.peakY}" r="2" fill="var(--fodda-accent, #663399)"/>
|
|
705
|
+
<circle cx="300" cy="${gt.annY}" r="2.5" fill="var(--fodda-accent, #663399)"/>
|
|
706
|
+
<text x="${gt.annX}" y="${gt.annY}" font-size="7" fill="var(--fodda-accent, #663399)" text-anchor="end" font-family="monospace">${gt.annText}</text>
|
|
562
707
|
</svg>
|
|
563
708
|
<p class="note">{{GT_CAPTION}}</p>` : '',
|
|
564
709
|
'GT_COMPARISON_SECTION_HTML': gt.comparisonBarsHtml ? `<div class="sl2">Search interest — brand vs competitors</div>
|
|
@@ -589,9 +734,12 @@ export async function renderBrandWidget(profile) {
|
|
|
589
734
|
'BEA_STAT_2_SUB': beaChangeSub,
|
|
590
735
|
'GEO_SECTION_HTML': geoBarsHtml ? `<div class="sl2">Geographic spread</div>
|
|
591
736
|
${geoBarsHtml}` : '',
|
|
592
|
-
'EARNINGS_SECTION_HTML': earningsHtml ? `<div class="sl2">Earnings
|
|
737
|
+
'EARNINGS_SECTION_HTML': earningsHtml ? `<div class="sl2">Quarterly Earnings & Wall Street Intelligence</div>
|
|
593
738
|
${earningsHtml}
|
|
594
|
-
<p class="note">Source: Fodda Earnings Intelligence.</p>` : '',
|
|
739
|
+
<p class="note">Source: Fodda Institutional Earnings Intelligence (SEC Filings & Executive Earnings Call Transcripts).</p>` : '',
|
|
740
|
+
'FINANCIAL_SNAPSHOT_SECTION_HTML': financialSnapshotHtml ? `<div class="sl2">Institutional Financial Snapshot</div>
|
|
741
|
+
${financialSnapshotHtml}
|
|
742
|
+
<p class="note">Source: Institutional SEC & Market Financial Filings.</p>` : '',
|
|
595
743
|
'SOURCE_PILLS_HTML': sourcePills,
|
|
596
744
|
'EXPORT_1_LABEL': exportLabels[0].label,
|
|
597
745
|
'EXPORT_1_DESC': exportLabels[0].desc,
|
|
@@ -626,10 +774,12 @@ export async function renderBrandWidget(profile) {
|
|
|
626
774
|
fills['GT_CAPTION'] = supplemental?.google_trends ? `12-month search interest for "${brand}". Peak: ${supplemental.google_trends.peak_interest || '—'}, current: ${supplemental.google_trends.latest_value || '—'}. Source: Google Trends.` : `Search interest data for "${brand}". Source: Google Trends.`;
|
|
627
775
|
fills['RELATED_QUERIES_NOTE'] = supplemental?.google_trends?.related_queries?.length ? `Top related searches when people look for ${brand}.` : '';
|
|
628
776
|
fills['WIKI_NOTE'] = wikiData.length > 0 ? `Daily Wikipedia pageviews for ${brand}-related articles. Higher = more cultural attention.` : '';
|
|
777
|
+
const safeBrandName = esc(brand).replace(/'/g, "\\'");
|
|
778
|
+
const safeCompName = competitors[0]?.brand ? esc(competitors[0].brand).replace(/'/g, "\\'") : 'top rival';
|
|
629
779
|
fills['SUGGESTED_NEXT_HTML'] = `<div style="display:flex;flex-wrap:wrap;gap:6px;">
|
|
630
|
-
<button class="btn-out" onclick="sendPrompt('What are ${
|
|
631
|
-
<button class="btn-out" onclick="sendPrompt('Show me the evidence behind
|
|
632
|
-
<button class="btn-out" onclick="sendPrompt('
|
|
780
|
+
<button class="btn-out" onclick="sendPrompt('What are competitors of ${safeBrandName} doing differently?')">Competitive landscape</button>
|
|
781
|
+
<button class="btn-out" onclick="sendPrompt('Show me the evidence behind the strongest trend for ${safeBrandName}')">Deep dive</button>
|
|
782
|
+
<button class="btn-out" onclick="sendPrompt('Compare ${safeBrandName} vs ${safeCompName}')">Head-to-head</button>
|
|
633
783
|
</div>`;
|
|
634
784
|
html = replaceSlots(html, fills);
|
|
635
785
|
// ── Final cleanup: strip any remaining unfilled {{...}} placeholders ──
|
|
@@ -637,25 +787,66 @@ export async function renderBrandWidget(profile) {
|
|
|
637
787
|
const editorialContext = { brand, total_trends: trends.length };
|
|
638
788
|
return { widget_html: html, editorial_context: editorialContext, open_slots: [] };
|
|
639
789
|
}
|
|
640
|
-
// const TEMPLATE = `
|
|
641
790
|
export const TEMPLATE = `
|
|
642
791
|
<style>
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
792
|
+
.fodda-brand-widget, .w {
|
|
793
|
+
--fodda-bg: #ffffff;
|
|
794
|
+
--fodda-bg-secondary: #f8fafc;
|
|
795
|
+
--fodda-text: #18181b;
|
|
796
|
+
--fodda-muted: #71717a;
|
|
797
|
+
--fodda-line: #e4e4e7;
|
|
798
|
+
--fodda-accent: #663399;
|
|
799
|
+
--fodda-accent-light: #f5f0ff;
|
|
800
|
+
--p: var(--fodda-accent);
|
|
801
|
+
--pl: var(--fodda-accent-light);
|
|
802
|
+
--pm: var(--fodda-line);
|
|
803
|
+
--pl-on: var(--fodda-accent);
|
|
804
|
+
--color-text-primary: var(--fodda-text);
|
|
805
|
+
--color-text-secondary: var(--fodda-muted);
|
|
806
|
+
--color-border-tertiary: var(--fodda-line);
|
|
807
|
+
--color-background-primary: var(--fodda-bg);
|
|
808
|
+
--color-background-secondary: var(--fodda-bg-secondary);
|
|
809
|
+
--color-text-info: #2563eb;
|
|
810
|
+
--color-text-success: #16a34a;
|
|
811
|
+
--color-text-warning: #d97706;
|
|
812
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
813
|
+
color: var(--fodda-text);
|
|
814
|
+
background: var(--fodda-bg);
|
|
815
|
+
border: 1px solid var(--fodda-line);
|
|
816
|
+
border-top: 3px solid var(--fodda-accent);
|
|
817
|
+
border-radius: 6px;
|
|
818
|
+
padding: 1.25rem;
|
|
819
|
+
}
|
|
820
|
+
@media (prefers-color-scheme: dark) {
|
|
821
|
+
.fodda-brand-widget, .w {
|
|
822
|
+
--fodda-bg: #18181b;
|
|
823
|
+
--fodda-bg-secondary: #27272a;
|
|
824
|
+
--fodda-text: #f4f4f5;
|
|
825
|
+
--fodda-muted: #a1a1aa;
|
|
826
|
+
--fodda-line: #3f3f46;
|
|
827
|
+
--fodda-accent: #9d65d4;
|
|
828
|
+
--fodda-accent-light: rgba(157, 101, 212, 0.15);
|
|
829
|
+
--p: var(--fodda-accent);
|
|
830
|
+
--pl: var(--fodda-accent-light);
|
|
831
|
+
--pm: var(--fodda-line);
|
|
832
|
+
--pl-on: #c4a7e8;
|
|
833
|
+
--color-text-info: #60a5fa;
|
|
834
|
+
--color-text-success: #4ade80;
|
|
835
|
+
--color-text-warning: #fbbf24;
|
|
836
|
+
}
|
|
837
|
+
}
|
|
646
838
|
.hd{display:flex;align-items:center;justify-content:space-between;margin-bottom:1.25rem;padding-bottom:1rem;border-bottom:.5px solid var(--color-border-tertiary);}
|
|
647
839
|
.logo{display:flex;align-items:center;gap:10px;}
|
|
648
|
-
.
|
|
649
|
-
.
|
|
650
|
-
.bfolio{font-family:var(--font-mono);font-size:10px;letter-spacing:0.18em;text-transform:uppercase;color:var(--color-text-secondary);}
|
|
840
|
+
.lt{font-size:13px;font-weight:600;}.ls{font-size:10px;color:var(--color-text-secondary);}
|
|
841
|
+
.bfolio{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:10px;letter-spacing:0.18em;text-transform:uppercase;color:var(--color-text-secondary);}
|
|
651
842
|
.bh{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:.75rem;}
|
|
652
|
-
.bn{font-family:
|
|
653
|
-
.vc{font-size:9px;font-weight:700;letter-spacing:0.18em;text-transform:uppercase;padding:3px 8px;border:1px solid currentColor;border-radius:2px;font-family:
|
|
843
|
+
.bn{font-family:Georgia,serif;font-style:italic;font-weight:400;font-size:22px;letter-spacing:-0.01em;}
|
|
844
|
+
.vc{font-size:9px;font-weight:700;letter-spacing:0.18em;text-transform:uppercase;padding:3px 8px;border:1px solid currentColor;border-radius:2px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;}
|
|
654
845
|
.vc-up{color:var(--color-text-success);}
|
|
655
846
|
.vc-build{color:var(--color-text-info);}
|
|
656
847
|
.vc-steady{color:var(--color-text-secondary);}
|
|
657
848
|
.vc-slow{color:var(--color-text-warning);}
|
|
658
|
-
.pv{font-size:14px;font-family:
|
|
849
|
+
.pv{font-size:14px;font-family:Georgia,serif;font-style:italic;font-weight:400;line-height:1.65;padding:14px 16px;background:var(--pl);border:1px solid var(--p);border-left-width:3px;border-radius:4px;margin-bottom:1.25rem;color:var(--color-text-primary);}
|
|
659
850
|
.lcb{display:flex;height:8px;border-radius:4px;overflow:hidden;margin-bottom:.75rem;gap:2px;}
|
|
660
851
|
.lcl{display:flex;gap:12px;margin-bottom:1.25rem;flex-wrap:wrap;}
|
|
661
852
|
.lci{display:flex;align-items:center;gap:5px;font-size:10px;color:var(--color-text-secondary);}
|
|
@@ -663,37 +854,37 @@ export const TEMPLATE = `
|
|
|
663
854
|
.card{background:var(--color-background-primary);border:1px solid var(--color-border-tertiary);border-radius:4px;padding:1rem 1.25rem;margin-bottom:8px;transition:border-color .15s,background .15s;}
|
|
664
855
|
.card:hover{border-color:var(--p);background:var(--pl);}
|
|
665
856
|
.th{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:6px;gap:8px;}
|
|
666
|
-
.tn{font-size:13px;font-weight:
|
|
857
|
+
.tn{font-size:13px;font-weight:600;}
|
|
667
858
|
.ta{display:flex;align-items:center;gap:4px;flex-shrink:0;}
|
|
668
859
|
.td{font-size:12px;color:var(--color-text-secondary);margin-bottom:5px;line-height:1.5;}
|
|
669
|
-
.lb{font-size:9px;font-weight:700;letter-spacing:0.18em;text-transform:uppercase;padding:3px 8px;border:1px solid currentColor;border-radius:2px;white-space:nowrap;font-family:
|
|
860
|
+
.lb{font-size:9px;font-weight:700;letter-spacing:0.18em;text-transform:uppercase;padding:3px 8px;border:1px solid currentColor;border-radius:2px;white-space:nowrap;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;background:transparent;}
|
|
670
861
|
.lb-b{color:var(--color-text-info);}
|
|
671
862
|
.lb-e{color:var(--color-text-success);}
|
|
672
863
|
.lb-m{color:var(--color-text-secondary);}
|
|
673
864
|
.lb-f{color:var(--color-text-warning);}
|
|
674
|
-
.bd{font-size:9px;font-weight:700;letter-spacing:0.18em;text-transform:uppercase;padding:3px 8px;border:1px solid currentColor;border-radius:2px;background:transparent;color:var(--color-text-secondary);font-family:
|
|
675
|
-
.bd-fast{font-size:9px;font-weight:700;letter-spacing:0.18em;text-transform:uppercase;padding:3px 8px;border:1px solid currentColor;border-radius:2px;background:transparent;color:#7A4000;font-family:
|
|
676
|
-
.bdp{font-size:10px;padding:2px 8px;border-radius:20px;background:var(--pl);color:var(--pl-on);font-family:
|
|
865
|
+
.bd{font-size:9px;font-weight:700;letter-spacing:0.18em;text-transform:uppercase;padding:3px 8px;border:1px solid currentColor;border-radius:2px;background:transparent;color:var(--color-text-secondary);font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;}
|
|
866
|
+
.bd-fast{font-size:9px;font-weight:700;letter-spacing:0.18em;text-transform:uppercase;padding:3px 8px;border:1px solid currentColor;border-radius:2px;background:transparent;color:#7A4000;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;}
|
|
867
|
+
.bdp{font-size:10px;padding:2px 8px;border-radius:20px;background:var(--pl);color:var(--pl-on);font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;}
|
|
677
868
|
.brow{display:flex;gap:6px;flex-wrap:wrap;margin-top:8px;}
|
|
678
869
|
.wl{font-size:11px;color:var(--color-text-secondary);margin:1.25rem 0 8px;display:flex;align-items:center;gap:6px;}
|
|
679
870
|
.wd{width:6px;height:6px;border-radius:50%;background:var(--color-text-warning);display:inline-block;}
|
|
680
871
|
.ec{border:1px dashed var(--color-border-tertiary);border-radius:4px;margin-bottom:8px;padding:1rem 1.25rem;}
|
|
681
|
-
.et a{color:var(--color-text-info);text-decoration:none;font-size:13px;font-weight:
|
|
872
|
+
.et a{color:var(--color-text-info);text-decoration:none;font-size:13px;font-weight:600;}.et a:hover{text-decoration:underline;}
|
|
682
873
|
.ex{font-size:12px;color:var(--color-text-secondary);line-height:1.5;margin:6px 0 8px;}
|
|
683
874
|
.em{display:flex;gap:6px;flex-wrap:wrap;}
|
|
684
875
|
.cit{font-size:10px;color:var(--color-text-secondary);margin-top:8px;padding-top:8px;border-top:.5px solid var(--color-border-tertiary);}
|
|
685
876
|
.cit a{color:var(--color-text-info);text-decoration:none;}
|
|
686
|
-
.cat-cs{background:var(--color-background-
|
|
877
|
+
.cat-cs{background:var(--color-background-secondary);color:var(--color-text-info);}
|
|
687
878
|
.cat-si{background:var(--pl);color:var(--p);}
|
|
688
|
-
.cat-me{background:var(--color-background-
|
|
689
|
-
.cat-qu{background:var(--color-background-
|
|
879
|
+
.cat-me{background:var(--color-background-secondary);color:var(--color-text-success);}
|
|
880
|
+
.cat-qu{background:var(--color-background-secondary);color:var(--color-text-warning);}
|
|
690
881
|
.cat-in{background:var(--color-background-secondary);color:var(--color-text-secondary);}
|
|
691
882
|
.cc{background:var(--color-background-primary);border:1px solid var(--color-border-tertiary);border-radius:4px;padding:.875rem 1.25rem;margin-bottom:6px;display:flex;justify-content:space-between;align-items:center;}
|
|
692
|
-
.cn{font-size:13px;font-weight:
|
|
883
|
+
.cn{font-size:13px;font-weight:600;margin-bottom:3px;}
|
|
693
884
|
.cd{font-size:11px;color:var(--color-text-secondary);}
|
|
694
885
|
.ca{display:flex;flex-direction:column;align-items:flex-end;gap:6px;}
|
|
695
|
-
.pb{font-size:9px;font-weight:700;letter-spacing:0.18em;text-transform:uppercase;padding:3px 8px;border:1px solid currentColor;border-radius:2px;font-family:
|
|
696
|
-
.sl2, .sec{font-size:13px;font-weight:
|
|
886
|
+
.pb{font-size:9px;font-weight:700;letter-spacing:0.18em;text-transform:uppercase;padding:3px 8px;border:1px solid currentColor;border-radius:2px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;background:transparent;}
|
|
887
|
+
.sl2, .sec{font-size:13px;font-weight:600;color:var(--color-text-primary);margin:1.25rem 0 8px;}.sl2:first-child, .sec:first-child{margin-top:0;}
|
|
697
888
|
.br{display:flex;align-items:center;gap:8px;margin-bottom:5px;font-size:12px;}
|
|
698
889
|
.brl{width:120px;color:var(--color-text-secondary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex-shrink:0;}
|
|
699
890
|
.brt{flex:1;height:4px;background:var(--color-background-secondary);border-radius:3px;overflow:hidden;}
|
|
@@ -702,38 +893,41 @@ export const TEMPLATE = `
|
|
|
702
893
|
.sg{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;margin-bottom:1rem;}
|
|
703
894
|
.sk{background:var(--color-background-secondary);border-radius:8px;padding:10px 12px;}
|
|
704
895
|
.skl{font-size:10px;color:var(--color-text-secondary);margin-bottom:3px;}
|
|
705
|
-
.skv{font-family:
|
|
896
|
+
.skv{font-family:Georgia,serif;font-style:italic;font-size:22px;font-weight:400;}.sks{font-size:10px;color:var(--color-text-secondary);margin-top:2px;}
|
|
706
897
|
.rq{display:flex;gap:5px;flex-wrap:wrap;margin-bottom:.75rem;}
|
|
707
898
|
.rqp{font-size:10px;padding:3px 9px;border-radius:20px;background:var(--color-background-secondary);color:var(--color-text-secondary);border:.5px solid var(--color-border-tertiary);}
|
|
708
|
-
.xb{display:flex;align-items:center;gap:10px;padding:12px 16px;background:var(--color-background-secondary);border:.5px solid var(--color-border-tertiary);border-radius:8px;cursor:pointer;text-align:left;width:100%;margin-bottom:8px;font-family:
|
|
899
|
+
.xb{display:flex;align-items:center;gap:10px;padding:12px 16px;background:var(--color-background-secondary);border:.5px solid var(--color-border-tertiary);border-radius:8px;cursor:pointer;text-align:left;width:100%;margin-bottom:8px;font-family:inherit;transition:all .15s;}
|
|
709
900
|
.xb:hover{background:var(--pl);border-color:var(--pm);}
|
|
710
|
-
.xi{font-size:11px;width:28px;font-weight:
|
|
901
|
+
.xi{font-size:11px;width:28px;font-weight:600;flex-shrink:0;color:var(--color-text-secondary);}
|
|
711
902
|
.xd{font-size:11px;color:var(--color-text-secondary);margin-top:2px;}
|
|
712
|
-
.xbl{font-weight:
|
|
903
|
+
.xbl{font-weight:600;font-size:12px;}
|
|
713
904
|
.gf{display:flex;gap:5px;flex-wrap:wrap;margin-top:1.5rem;padding-top:1rem;border-top:.5px solid var(--color-border-tertiary);align-items:center;}
|
|
714
905
|
.gfl{font-size:10px;color:var(--color-text-secondary);margin-right:2px;}
|
|
715
906
|
.gp{font-size:10px;padding:2px 9px;border-radius:20px;background:var(--pl);color:var(--pl-on);border:.5px solid var(--pm);}
|
|
716
907
|
.ap{background:var(--color-background-secondary);border-radius:8px;margin-bottom:6px;padding:.75rem 1rem;display:flex;justify-content:space-between;align-items:center;}
|
|
717
|
-
.an2{font-size:12px;font-weight:
|
|
908
|
+
.an2{font-size:12px;font-weight:600;}
|
|
718
909
|
.am2{font-size:11px;color:var(--color-text-secondary);margin-top:2px;}
|
|
719
910
|
.astar{font-size:11px;color:var(--p);}
|
|
720
911
|
.note{font-size:10px;color:var(--color-text-secondary);margin-bottom:1.25rem;}
|
|
721
|
-
.btn-out{font-size:9px;padding:2px 7px;cursor:pointer;border:.5px solid var(--pm);border-radius:20px;background:var(--pl);color:var(--pl-on);font-family:
|
|
912
|
+
.btn-out{font-size:9px;padding:2px 7px;cursor:pointer;border:.5px solid var(--pm);border-radius:20px;background:var(--pl);color:var(--pl-on);font-family:inherit;}
|
|
722
913
|
.btn-out:hover{background:var(--p);color:#fff;border-color:var(--p);}
|
|
723
|
-
.cp{font-size:11px;background:var(--pl);color:var(--pl-on);border:.5px solid var(--pm);border-radius:20px;padding:3px 10px;cursor:pointer;font-family:
|
|
914
|
+
.cp{font-size:11px;background:var(--pl);color:var(--pl-on);border:.5px solid var(--pm);border-radius:20px;padding:3px 10px;cursor:pointer;font-family:inherit;transition:all .15s;}
|
|
724
915
|
.cp:hover{background:var(--p);color:#fff;}
|
|
725
|
-
.cv{font-size:10px;background:var(--pl);color:var(--pl-on);border:.5px solid var(--pm);border-radius:20px;padding:2px 8px;cursor:pointer;font-family:
|
|
916
|
+
.cv{font-size:10px;background:var(--pl);color:var(--pl-on);border:.5px solid var(--pm);border-radius:20px;padding:2px 8px;cursor:pointer;font-family:inherit;transition:all .15s;}
|
|
726
917
|
.cv:hover{background:var(--p);color:#fff;}
|
|
727
918
|
.an{font-size:13px;line-height:1.7;color:var(--color-text-primary);}
|
|
728
919
|
.an p{margin:0 0 .75rem;}
|
|
729
|
-
.an strong{font-weight:
|
|
920
|
+
.an strong{font-weight:600;}
|
|
730
921
|
.si{font-size:12px;line-height:1.65;color:var(--color-text-secondary);font-style:italic;margin:0 0 1rem;}
|
|
731
922
|
</style>
|
|
732
923
|
|
|
733
|
-
<div class="w">
|
|
924
|
+
<div class="fodda-brand-widget w">
|
|
734
925
|
<div class="hd">
|
|
735
926
|
<div class="logo">
|
|
736
|
-
<
|
|
927
|
+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" style="height:24px;width:24px;flex-shrink:0;">
|
|
928
|
+
<rect width="24" height="24" rx="6" fill="var(--fodda-accent)"/>
|
|
929
|
+
<circle cx="12" cy="12" r="5" fill="#ffffff"/>
|
|
930
|
+
</svg>
|
|
737
931
|
<div><div class="lt">Fodda</div><div class="ls">Brand Intelligence</div></div>
|
|
738
932
|
</div>
|
|
739
933
|
<div class="bfolio">{{FOLIO}}</div>
|
|
@@ -750,6 +944,7 @@ export const TEMPLATE = `
|
|
|
750
944
|
{{EVIDENCE_HTML}}
|
|
751
945
|
|
|
752
946
|
{{EARNINGS_SECTION_HTML}}
|
|
947
|
+
{{FINANCIAL_SNAPSHOT_SECTION_HTML}}
|
|
753
948
|
|
|
754
949
|
<div class="sec">Relevant trends</div>
|
|
755
950
|
{{TREND_FOOTPRINT_INTRO}}
|
|
@@ -758,8 +953,7 @@ export const TEMPLATE = `
|
|
|
758
953
|
{{TRENDS_HTML}}
|
|
759
954
|
{{WEAK_SIGNALS_HTML}}
|
|
760
955
|
|
|
761
|
-
|
|
762
|
-
{{COMPETITOR_LIST_HTML}}
|
|
956
|
+
{{COMPETITIVE_SECTION_HTML}}
|
|
763
957
|
|
|
764
958
|
<div class="sec">Market data</div>
|
|
765
959
|
{{MARKET_DATA_INTRO}}
|
|
@@ -799,5 +993,6 @@ export const TEMPLATE = `
|
|
|
799
993
|
<div class="gf">
|
|
800
994
|
<span class="gfl">Sources:</span>
|
|
801
995
|
{{SOURCE_PILLS_HTML}}
|
|
996
|
+
</div>
|
|
802
997
|
</div>`;
|
|
803
998
|
//# sourceMappingURL=brandTemplate.js.map
|