@eric-emg/symphiq-components 1.2.178 → 1.2.180

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.
@@ -25654,226 +25654,226 @@ class JourneyProgressIndicatorComponent {
25654
25654
  }
25655
25655
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(JourneyProgressIndicatorComponent, [{
25656
25656
  type: Component,
25657
- args: [{ selector: 'symphiq-journey-progress-indicator', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: `
25658
- <!-- Sticky Banner Container with Minimal Padding for Glow Effects -->
25659
- <div [ngClass]="containerClasses()" class="sticky top-[60px] z-40 border-b pt-8 pb-6 px-6 transition-all duration-200 overflow-visible">
25660
- <div class="max-w-7xl mx-auto overflow-visible">
25661
- <!-- Desktop/Tablet Horizontal Layout (lg and up) -->
25662
- <div class="hidden lg:flex items-start justify-between overflow-visible">
25663
- <!-- Steps Container -->
25664
- <div class="flex-1 flex items-start justify-start overflow-visible">
25665
- @for (step of steps(); track step.id; let idx = $index; let isLast = $last) {
25666
- <!-- Step Column (Vertical Layout: Dot above, Label below) -->
25667
- <div
25668
- class="flex flex-col items-center relative step-column overflow-visible flex-shrink-0"
25669
- [class.cursor-pointer]="step.status === 'completed' || step.status === 'accessible'"
25670
- [style.width]="'64px'"
25671
- (mouseenter)="setHoveredStep(idx)"
25672
- (mouseleave)="clearHoveredStep()"
25673
- (click)="handleStepClick(step, idx)">
25674
-
25675
- <!-- Icon Circle -->
25676
- <div
25677
- [ngClass]="getStepIconContainerClasses(step)"
25678
- class="w-8 h-8 min-w-[2rem] min-h-[2rem] rounded-full flex items-center justify-center flex-shrink-0 step-circle relative z-10 mb-1.5">
25679
- @if (step.status === 'completed') {
25680
- <svg class="w-4 h-4" fill="currentColor" viewBox="0 0 20 20">
25681
- <path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"></path>
25682
- </svg>
25683
- } @else if (step.status === 'current') {
25684
- <div class="w-2.5 h-2.5 min-w-[0.625rem] min-h-[0.625rem] rounded-full animate-pulse" [ngClass]="getCurrentDotClasses()"></div>
25685
- } @else if (step.status === 'accessible') {
25686
- <div class="w-2 h-2 min-w-[0.5rem] min-h-[0.5rem] rounded-full" [ngClass]="getAccessibleDotClasses()"></div>
25687
- } @else {
25688
- <span [ngClass]="getStepNumberClasses(step)" class="text-xs font-bold">
25689
- {{ idx + 1 }}
25690
- </span>
25691
- }
25692
- </div>
25693
-
25694
- <!-- Abbreviated Title (Always Visible) -->
25695
- <span
25696
- [ngClass]="getAbbreviatedTitleClasses(step)"
25697
- class="text-[10px] text-center leading-tight whitespace-nowrap max-w-[64px] overflow-hidden text-ellipsis">
25698
- {{ getAbbreviatedTitle(step.title) }}
25699
- </span>
25700
-
25701
- <!-- Absolute Positioned Tooltip -->
25702
- @if (hoveredStepIndex() === idx) {
25703
- <div
25704
- [ngClass]="getExpandedCardClasses(idx)"
25705
- [class.expanded-card-right]="isExpandRight(idx)"
25706
- [class.expanded-card-left]="isExpandLeft(idx)"
25707
- class="absolute rounded-lg shadow-2xl z-50 pointer-events-none"
25708
- [style.top]="'-29px'"
25709
- [style.left]="isExpandRight(idx) ? 'calc(100% + 6px)' : 'auto'"
25710
- [style.right]="isExpandLeft(idx) ? 'calc(100% + 6px)' : 'auto'">
25711
- <div class="flex items-start px-4 py-3 expanded-content">
25712
- <!-- Step Number and Title with Description -->
25713
- <div class="flex items-start gap-2 w-full">
25714
- <span [ngClass]="tooltipStepNumberClasses()" class="text-xs font-bold flex-shrink-0 mt-0.5">{{ idx + 1 }}.</span>
25715
- <div class="flex flex-col gap-1 flex-1">
25716
- <span [ngClass]="tooltipTitleClasses()" class="text-sm font-bold leading-tight">{{ step.title }}</span>
25717
- <!-- Description (Delayed Fade In) -->
25718
- @if (shouldShowDetailedTooltip()) {
25719
- <p [ngClass]="tooltipDescriptionClasses()" class="text-xs leading-relaxed description-fade">
25720
- {{ step.description }}
25721
- </p>
25722
- }
25723
- </div>
25724
- </div>
25725
- </div>
25726
- </div>
25727
- }
25728
- </div>
25729
-
25730
- <!-- Connector Line (Horizontal, stretches to fill available space) -->
25731
- @if (!isLast) {
25732
- <div [ngClass]="getConnectorClasses(step)" class="flex-1 h-0.5 transition-all duration-200 mt-[16px]"></div>
25733
- }
25734
- }
25735
- </div>
25736
-
25737
- <!-- Next Step Button -->
25738
- @if (showNextStepAction() && getNextStep()) {
25739
- <button
25740
- type="button"
25741
- (click)="handleNextStepClick()"
25742
- [disabled]="isLoading()"
25743
- [ngClass]="nextStepButtonClasses()"
25744
- class="px-4 py-2 rounded-lg font-medium text-sm transition-all duration-200 flex-shrink-0 flex items-center gap-2 whitespace-nowrap ml-4 mt-0"
25745
- [class.cursor-pointer]="!isLoading()"
25746
- [class.cursor-not-allowed]="isLoading()"
25747
- [class.opacity-50]="isLoading()"
25748
- [class.hover:scale-105]="!isLoading()">
25749
- @if (isLoading()) {
25750
- <svg class="w-4 h-4 animate-spin" fill="none" viewBox="0 0 24 24">
25751
- <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
25752
- <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
25753
- </svg>
25754
- Loading...
25755
- } @else {
25756
- {{ currentStepId() === JourneyStepIdEnum.WELCOME ? 'Get Started' : 'Continue' }}
25757
- <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
25758
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7l5 5m0 0l-5 5m5-5H6"></path>
25759
- </svg>
25760
- }
25761
- </button>
25762
- }
25763
- </div>
25764
-
25765
- <!-- Mobile Navigation (below lg) -->
25766
- <div class="lg:hidden">
25767
- <div class="flex items-center justify-between gap-4">
25768
- <!-- Current Step Display -->
25769
- <div class="flex-1 flex items-center gap-3">
25770
- <!-- Step Icon -->
25771
- <div [ngClass]="getStepIconContainerClasses(getCurrentStep())" class="w-10 h-10 min-w-[2.5rem] min-h-[2.5rem] rounded-full flex items-center justify-center flex-shrink-0">
25772
- @if (getCurrentStep().status === 'completed') {
25773
- <svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
25774
- <path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"></path>
25775
- </svg>
25776
- } @else if (getCurrentStep().status === 'current') {
25777
- <div class="w-3 h-3 min-w-[0.75rem] min-h-[0.75rem] rounded-full animate-pulse" [ngClass]="getCurrentDotClasses()"></div>
25778
- } @else {
25779
- <span [ngClass]="getStepNumberClasses(getCurrentStep())" class="text-sm font-bold">
25780
- {{ getCurrentStepIndex() + 1 }}
25781
- </span>
25782
- }
25783
- </div>
25784
-
25785
- <!-- Step Info -->
25786
- <div class="flex-1 text-left">
25787
- <h3 [ngClass]="getStepTitleClasses(getCurrentStep())" class="text-sm font-bold">
25788
- {{ getCurrentStep().title }}
25789
- </h3>
25790
- <!-- Step Counter with Tooltip Trigger -->
25791
- <div
25792
- class="flex items-center gap-1.5 relative"
25793
- (mouseenter)="showMobileTooltip.set(true)"
25794
- (mouseleave)="showMobileTooltip.set(false)"
25795
- (click)="toggleMobileTooltip()">
25796
- <span [ngClass]="stepCounterClasses()" class="text-xs cursor-pointer">
25797
- Step {{ getCurrentStepIndex() + 1 }} of {{ steps().length }}
25798
- </span>
25799
- <div [ngClass]="tooltipTriggerClasses()" class="p-0.5 rounded-full cursor-pointer">
25800
- <svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
25801
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
25802
- </svg>
25803
- </div>
25804
-
25805
- <!-- Mobile Tooltip with All Steps -->
25806
- @if (showMobileTooltip()) {
25807
- <div [ngClass]="mobileTooltipClasses()" class="absolute top-full left-0 mt-2 w-80 max-w-[calc(100vw-2rem)] p-4 rounded-lg shadow-xl z-50">
25808
- <h4 [ngClass]="tooltipTitleClasses()" class="text-sm font-bold mb-3">Journey Progress</h4>
25809
- <div class="space-y-2">
25810
- @for (step of steps(); track step.id; let idx = $index) {
25811
- <div class="flex items-start gap-2">
25812
- <!-- Step Icon -->
25813
- <div [ngClass]="getStepIconContainerClasses(step)" class="w-6 h-6 min-w-[1.5rem] min-h-[1.5rem] rounded-full flex items-center justify-center flex-shrink-0">
25814
- @if (step.status === 'completed') {
25815
- <svg class="w-3 h-3" fill="currentColor" viewBox="0 0 20 20">
25816
- <path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"></path>
25817
- </svg>
25818
- } @else if (step.status === 'current') {
25819
- <div class="w-2 h-2 min-w-[0.5rem] min-h-[0.5rem] rounded-full animate-pulse" [ngClass]="getCurrentDotClasses()"></div>
25820
- } @else if (step.status === 'accessible') {
25821
- <div class="w-1.5 h-1.5 min-w-[0.375rem] min-h-[0.375rem] rounded-full" [ngClass]="getAccessibleDotClasses()"></div>
25822
- } @else {
25823
- <span [ngClass]="getStepNumberClasses(step)" class="text-[10px] font-bold">
25824
- {{ idx + 1 }}
25825
- </span>
25826
- }
25827
- </div>
25828
- <!-- Step Info -->
25829
- <div class="flex-1 min-w-0">
25830
- <div class="flex items-center gap-2">
25831
- <span [ngClass]="tooltipStepNumberClasses()" class="text-xs font-bold">{{ idx + 1 }}.</span>
25832
- <span [ngClass]="getStepTitleClasses(step)" class="text-xs font-medium">{{ step.title }}</span>
25833
- </div>
25834
- <p [ngClass]="tooltipDescriptionClasses()" class="text-[10px] mt-0.5">
25835
- {{ step.description }}
25836
- </p>
25837
- </div>
25838
- </div>
25839
- }
25840
- </div>
25841
- </div>
25842
- }
25843
- </div>
25844
- </div>
25845
- </div>
25846
-
25847
- <!-- Get Started Button -->
25848
- @if (showNextStepAction() && getNextStep() && getCurrentStep().status === 'current') {
25849
- <button
25850
- type="button"
25851
- (click)="handleNextStepClick()"
25852
- [disabled]="isLoading()"
25853
- [ngClass]="nextStepButtonClasses()"
25854
- class="px-3 py-1.5 rounded-lg font-medium text-xs transition-all duration-200 flex-shrink-0 flex items-center gap-1.5 whitespace-nowrap"
25855
- [class.cursor-pointer]="!isLoading()"
25856
- [class.cursor-not-allowed]="isLoading()"
25857
- [class.opacity-50]="isLoading()"
25858
- [class.hover:scale-105]="!isLoading()">
25859
- @if (isLoading()) {
25860
- <svg class="w-3.5 h-3.5 animate-spin" fill="none" viewBox="0 0 24 24">
25861
- <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
25862
- <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
25863
- </svg>
25864
- Loading...
25865
- } @else {
25866
- {{ currentStepId() === JourneyStepIdEnum.WELCOME ? 'Get Started' : 'Continue' }}
25867
- <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
25868
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7l5 5m0 0l-5 5m5-5H6"></path>
25869
- </svg>
25870
- }
25871
- </button>
25872
- }
25873
- </div>
25874
- </div>
25875
- </div>
25876
- </div>
25657
+ args: [{ selector: 'symphiq-journey-progress-indicator', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: `
25658
+ <!-- Sticky Banner Container with Minimal Padding for Glow Effects -->
25659
+ <div [ngClass]="containerClasses()" class="sticky top-[60px] z-40 border-b pt-8 pb-6 px-6 transition-all duration-200 overflow-visible">
25660
+ <div class="max-w-7xl mx-auto overflow-visible">
25661
+ <!-- Desktop/Tablet Horizontal Layout (lg and up) -->
25662
+ <div class="hidden lg:flex items-start justify-between overflow-visible">
25663
+ <!-- Steps Container -->
25664
+ <div class="flex-1 flex items-start justify-start overflow-visible">
25665
+ @for (step of steps(); track step.id; let idx = $index; let isLast = $last) {
25666
+ <!-- Step Column (Vertical Layout: Dot above, Label below) -->
25667
+ <div
25668
+ class="flex flex-col items-center relative step-column overflow-visible flex-shrink-0"
25669
+ [class.cursor-pointer]="step.status === 'completed' || step.status === 'accessible'"
25670
+ [style.width]="'64px'"
25671
+ (mouseenter)="setHoveredStep(idx)"
25672
+ (mouseleave)="clearHoveredStep()"
25673
+ (click)="handleStepClick(step, idx)">
25674
+
25675
+ <!-- Icon Circle -->
25676
+ <div
25677
+ [ngClass]="getStepIconContainerClasses(step)"
25678
+ class="w-8 h-8 min-w-[2rem] min-h-[2rem] rounded-full flex items-center justify-center flex-shrink-0 step-circle relative z-10 mb-1.5">
25679
+ @if (step.status === 'completed') {
25680
+ <svg class="w-4 h-4" fill="currentColor" viewBox="0 0 20 20">
25681
+ <path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"></path>
25682
+ </svg>
25683
+ } @else if (step.status === 'current') {
25684
+ <div class="w-2.5 h-2.5 min-w-[0.625rem] min-h-[0.625rem] rounded-full animate-pulse" [ngClass]="getCurrentDotClasses()"></div>
25685
+ } @else if (step.status === 'accessible') {
25686
+ <div class="w-2 h-2 min-w-[0.5rem] min-h-[0.5rem] rounded-full" [ngClass]="getAccessibleDotClasses()"></div>
25687
+ } @else {
25688
+ <span [ngClass]="getStepNumberClasses(step)" class="text-xs font-bold">
25689
+ {{ idx + 1 }}
25690
+ </span>
25691
+ }
25692
+ </div>
25693
+
25694
+ <!-- Abbreviated Title (Always Visible) -->
25695
+ <span
25696
+ [ngClass]="getAbbreviatedTitleClasses(step)"
25697
+ class="text-[10px] text-center leading-tight whitespace-nowrap max-w-[64px] overflow-hidden text-ellipsis">
25698
+ {{ getAbbreviatedTitle(step.title) }}
25699
+ </span>
25700
+
25701
+ <!-- Absolute Positioned Tooltip -->
25702
+ @if (hoveredStepIndex() === idx) {
25703
+ <div
25704
+ [ngClass]="getExpandedCardClasses(idx)"
25705
+ [class.expanded-card-right]="isExpandRight(idx)"
25706
+ [class.expanded-card-left]="isExpandLeft(idx)"
25707
+ class="absolute rounded-lg shadow-2xl z-50 pointer-events-none"
25708
+ [style.top]="'-29px'"
25709
+ [style.left]="isExpandRight(idx) ? 'calc(100% + 6px)' : 'auto'"
25710
+ [style.right]="isExpandLeft(idx) ? 'calc(100% + 6px)' : 'auto'">
25711
+ <div class="flex items-start px-4 py-3 expanded-content">
25712
+ <!-- Step Number and Title with Description -->
25713
+ <div class="flex items-start gap-2 w-full">
25714
+ <span [ngClass]="tooltipStepNumberClasses()" class="text-xs font-bold flex-shrink-0 mt-0.5">{{ idx + 1 }}.</span>
25715
+ <div class="flex flex-col gap-1 flex-1">
25716
+ <span [ngClass]="tooltipTitleClasses()" class="text-sm font-bold leading-tight">{{ step.title }}</span>
25717
+ <!-- Description (Delayed Fade In) -->
25718
+ @if (shouldShowDetailedTooltip()) {
25719
+ <p [ngClass]="tooltipDescriptionClasses()" class="text-xs leading-relaxed description-fade">
25720
+ {{ step.description }}
25721
+ </p>
25722
+ }
25723
+ </div>
25724
+ </div>
25725
+ </div>
25726
+ </div>
25727
+ }
25728
+ </div>
25729
+
25730
+ <!-- Connector Line (Horizontal, stretches to fill available space) -->
25731
+ @if (!isLast) {
25732
+ <div [ngClass]="getConnectorClasses(step)" class="flex-1 h-0.5 transition-all duration-200 mt-[16px]"></div>
25733
+ }
25734
+ }
25735
+ </div>
25736
+
25737
+ <!-- Next Step Button -->
25738
+ @if (showNextStepAction() && getNextStep()) {
25739
+ <button
25740
+ type="button"
25741
+ (click)="handleNextStepClick()"
25742
+ [disabled]="isLoading()"
25743
+ [ngClass]="nextStepButtonClasses()"
25744
+ class="px-4 py-2 rounded-lg font-medium text-sm transition-all duration-200 flex-shrink-0 flex items-center gap-2 whitespace-nowrap ml-4 mt-0"
25745
+ [class.cursor-pointer]="!isLoading()"
25746
+ [class.cursor-not-allowed]="isLoading()"
25747
+ [class.opacity-50]="isLoading()"
25748
+ [class.hover:scale-105]="!isLoading()">
25749
+ @if (isLoading()) {
25750
+ <svg class="w-4 h-4 animate-spin" fill="none" viewBox="0 0 24 24">
25751
+ <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
25752
+ <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
25753
+ </svg>
25754
+ Loading...
25755
+ } @else {
25756
+ {{ currentStepId() === JourneyStepIdEnum.WELCOME ? 'Get Started' : 'Continue' }}
25757
+ <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
25758
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7l5 5m0 0l-5 5m5-5H6"></path>
25759
+ </svg>
25760
+ }
25761
+ </button>
25762
+ }
25763
+ </div>
25764
+
25765
+ <!-- Mobile Navigation (below lg) -->
25766
+ <div class="lg:hidden">
25767
+ <div class="flex items-center justify-between gap-4">
25768
+ <!-- Current Step Display -->
25769
+ <div class="flex-1 flex items-center gap-3">
25770
+ <!-- Step Icon -->
25771
+ <div [ngClass]="getStepIconContainerClasses(getCurrentStep())" class="w-10 h-10 min-w-[2.5rem] min-h-[2.5rem] rounded-full flex items-center justify-center flex-shrink-0">
25772
+ @if (getCurrentStep().status === 'completed') {
25773
+ <svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
25774
+ <path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"></path>
25775
+ </svg>
25776
+ } @else if (getCurrentStep().status === 'current') {
25777
+ <div class="w-3 h-3 min-w-[0.75rem] min-h-[0.75rem] rounded-full animate-pulse" [ngClass]="getCurrentDotClasses()"></div>
25778
+ } @else {
25779
+ <span [ngClass]="getStepNumberClasses(getCurrentStep())" class="text-sm font-bold">
25780
+ {{ getCurrentStepIndex() + 1 }}
25781
+ </span>
25782
+ }
25783
+ </div>
25784
+
25785
+ <!-- Step Info -->
25786
+ <div class="flex-1 text-left">
25787
+ <h3 [ngClass]="getStepTitleClasses(getCurrentStep())" class="text-sm font-bold">
25788
+ {{ getCurrentStep().title }}
25789
+ </h3>
25790
+ <!-- Step Counter with Tooltip Trigger -->
25791
+ <div
25792
+ class="flex items-center gap-1.5 relative"
25793
+ (mouseenter)="showMobileTooltip.set(true)"
25794
+ (mouseleave)="showMobileTooltip.set(false)"
25795
+ (click)="toggleMobileTooltip()">
25796
+ <span [ngClass]="stepCounterClasses()" class="text-xs cursor-pointer">
25797
+ Step {{ getCurrentStepIndex() + 1 }} of {{ steps().length }}
25798
+ </span>
25799
+ <div [ngClass]="tooltipTriggerClasses()" class="p-0.5 rounded-full cursor-pointer">
25800
+ <svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
25801
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
25802
+ </svg>
25803
+ </div>
25804
+
25805
+ <!-- Mobile Tooltip with All Steps -->
25806
+ @if (showMobileTooltip()) {
25807
+ <div [ngClass]="mobileTooltipClasses()" class="absolute top-full left-0 mt-2 w-80 max-w-[calc(100vw-2rem)] p-4 rounded-lg shadow-xl z-50">
25808
+ <h4 [ngClass]="tooltipTitleClasses()" class="text-sm font-bold mb-3">Journey Progress</h4>
25809
+ <div class="space-y-2">
25810
+ @for (step of steps(); track step.id; let idx = $index) {
25811
+ <div class="flex items-start gap-2">
25812
+ <!-- Step Icon -->
25813
+ <div [ngClass]="getStepIconContainerClasses(step)" class="w-6 h-6 min-w-[1.5rem] min-h-[1.5rem] rounded-full flex items-center justify-center flex-shrink-0">
25814
+ @if (step.status === 'completed') {
25815
+ <svg class="w-3 h-3" fill="currentColor" viewBox="0 0 20 20">
25816
+ <path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"></path>
25817
+ </svg>
25818
+ } @else if (step.status === 'current') {
25819
+ <div class="w-2 h-2 min-w-[0.5rem] min-h-[0.5rem] rounded-full animate-pulse" [ngClass]="getCurrentDotClasses()"></div>
25820
+ } @else if (step.status === 'accessible') {
25821
+ <div class="w-1.5 h-1.5 min-w-[0.375rem] min-h-[0.375rem] rounded-full" [ngClass]="getAccessibleDotClasses()"></div>
25822
+ } @else {
25823
+ <span [ngClass]="getStepNumberClasses(step)" class="text-[10px] font-bold">
25824
+ {{ idx + 1 }}
25825
+ </span>
25826
+ }
25827
+ </div>
25828
+ <!-- Step Info -->
25829
+ <div class="flex-1 min-w-0">
25830
+ <div class="flex items-center gap-2">
25831
+ <span [ngClass]="tooltipStepNumberClasses()" class="text-xs font-bold">{{ idx + 1 }}.</span>
25832
+ <span [ngClass]="getStepTitleClasses(step)" class="text-xs font-medium">{{ step.title }}</span>
25833
+ </div>
25834
+ <p [ngClass]="tooltipDescriptionClasses()" class="text-[10px] mt-0.5">
25835
+ {{ step.description }}
25836
+ </p>
25837
+ </div>
25838
+ </div>
25839
+ }
25840
+ </div>
25841
+ </div>
25842
+ }
25843
+ </div>
25844
+ </div>
25845
+ </div>
25846
+
25847
+ <!-- Get Started Button -->
25848
+ @if (showNextStepAction() && getNextStep() && getCurrentStep().status === 'current') {
25849
+ <button
25850
+ type="button"
25851
+ (click)="handleNextStepClick()"
25852
+ [disabled]="isLoading()"
25853
+ [ngClass]="nextStepButtonClasses()"
25854
+ class="px-3 py-1.5 rounded-lg font-medium text-xs transition-all duration-200 flex-shrink-0 flex items-center gap-1.5 whitespace-nowrap"
25855
+ [class.cursor-pointer]="!isLoading()"
25856
+ [class.cursor-not-allowed]="isLoading()"
25857
+ [class.opacity-50]="isLoading()"
25858
+ [class.hover:scale-105]="!isLoading()">
25859
+ @if (isLoading()) {
25860
+ <svg class="w-3.5 h-3.5 animate-spin" fill="none" viewBox="0 0 24 24">
25861
+ <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
25862
+ <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
25863
+ </svg>
25864
+ Loading...
25865
+ } @else {
25866
+ {{ currentStepId() === JourneyStepIdEnum.WELCOME ? 'Get Started' : 'Continue' }}
25867
+ <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
25868
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7l5 5m0 0l-5 5m5-5H6"></path>
25869
+ </svg>
25870
+ }
25871
+ </button>
25872
+ }
25873
+ </div>
25874
+ </div>
25875
+ </div>
25876
+ </div>
25877
25877
  `, styles: [".scrollbar-hide{-ms-overflow-style:none;scrollbar-width:none}.scrollbar-hide::-webkit-scrollbar{display:none}.step-glow-current{box-shadow:0 0 0 3px #3b82f64d;animation:pulseGlow 2s ease-in-out infinite}.step-glow-current-dark{box-shadow:0 0 0 3px #60a5fa4d;animation:pulseGlow 2s ease-in-out infinite}.step-glow-completed{box-shadow:0 0 0 2px #10b98133}.step-glow-completed-dark{box-shadow:0 0 0 2px #34d39933}.step-glow-accessible{box-shadow:0 0 0 2px #3b82f61f}.step-glow-accessible-dark{box-shadow:0 0 0 2px #60a5fa26}@keyframes pulseGlow{0%,to{box-shadow:0 0 0 3px #3b82f64d}50%{box-shadow:0 0 0 6px #3b82f61a}}.step-column{transition:all .2s cubic-bezier(.4,0,.2,1)}.step-circle{transition:all .15s cubic-bezier(.4,0,.2,1)}.step-column:hover .step-circle{transform:scale(1.05)}.expanded-card-right{animation:expandCardRight .2s cubic-bezier(.4,0,.2,1) forwards;transform-origin:left center}.expanded-card-left{animation:expandCardLeft .2s cubic-bezier(.4,0,.2,1) forwards;transform-origin:right center}@keyframes expandCardRight{0%{opacity:0;width:0;min-height:90px}to{opacity:1;width:300px;min-height:90px}}@keyframes expandCardLeft{0%{opacity:0;width:0;min-height:90px}to{opacity:1;width:300px;min-height:90px}}.description-fade{animation:fadeIn .15s ease-out forwards;opacity:0}@keyframes fadeIn{to{opacity:1}}.expanded-content{animation:contentFadeIn .15s ease-out .1s forwards;opacity:0}@keyframes contentFadeIn{to{opacity:1}}\n"] }]
25878
25878
  }], () => [], { viewMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewMode", required: false }] }], currentStepId: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentStepId", required: false }] }], showNextStepAction: [{ type: i0.Input, args: [{ isSignal: true, alias: "showNextStepAction", required: false }] }], forDemo: [{ type: i0.Input, args: [{ isSignal: true, alias: "forDemo", required: false }] }], maxAccessibleStepId: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxAccessibleStepId", required: false }] }], nextStepClick: [{ type: i0.Output, args: ["nextStepClick"] }], stepClick: [{ type: i0.Output, args: ["stepClick"] }] }); })();
25879
25879
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(JourneyProgressIndicatorComponent, { className: "JourneyProgressIndicatorComponent", filePath: "lib/components/business-analysis-dashboard/journey-progress-indicator.component.ts", lineNumber: 369 }); })();
@@ -32412,7 +32412,7 @@ class FocusAreaOpportunityDetailModalContentComponent {
32412
32412
  `
32413
32413
  }]
32414
32414
  }], null, { opportunity: [{ type: i0.Input, args: [{ isSignal: true, alias: "opportunity", required: true }] }], viewMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewMode", required: true }] }], allMetrics: [{ type: i0.Input, args: [{ isSignal: true, alias: "allMetrics", required: false }] }], allCharts: [{ type: i0.Input, args: [{ isSignal: true, alias: "allCharts", required: false }] }], currentModalState: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentModalState", required: false }] }] }); })();
32415
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(FocusAreaOpportunityDetailModalContentComponent, { className: "FocusAreaOpportunityDetailModalContentComponent", filePath: "lib/components/profile-analysis-dashboard/modals/focus-area-opportunity-detail-modal-content.component.ts", lineNumber: 92 }); })();
32415
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(FocusAreaOpportunityDetailModalContentComponent, { className: "FocusAreaOpportunityDetailModalContentComponent", filePath: "lib/components/profile-analysis-dashboard/modals/focus-area-opportunity-detail-modal-content.component.ts", lineNumber: 94 }); })();
32416
32416
 
32417
32417
  class CircularProgressComponent {
32418
32418
  constructor() {
@@ -56291,9 +56291,6 @@ class FunnelMetricsVisualizationComponent {
56291
56291
  return formatNumber(value);
56292
56292
  }
56293
56293
  getMetricTitle(metric) {
56294
- if (metric.description) {
56295
- return metric.description;
56296
- }
56297
56294
  return metric.metric
56298
56295
  .split('_')
56299
56296
  .map(word => word.charAt(0) + word.slice(1).toLowerCase())
@@ -57359,6 +57356,74 @@ function sortDataByMonth(data) {
57359
57356
  return aMonth - bMonth;
57360
57357
  });
57361
57358
  }
57359
+ function transformTrendUiDataToChartSeries(trendUiData, metricToExtract) {
57360
+ if (!trendUiData?.convertedDataResults) {
57361
+ return [];
57362
+ }
57363
+ const convertedData = trendUiData.convertedDataResults;
57364
+ const metricIndex = convertedData.metrics?.indexOf(metricToExtract);
57365
+ if (metricIndex === undefined || metricIndex === -1)
57366
+ return [];
57367
+ const dateIndex = convertedData.dimensions?.indexOf(DimensionEnum.DATE);
57368
+ const monthIndex = convertedData.dimensions?.indexOf(DimensionEnum.MONTH);
57369
+ if (dateIndex === undefined || dateIndex === -1) {
57370
+ if (monthIndex === undefined || monthIndex === -1)
57371
+ return [];
57372
+ return extractSeriesFromConvertedData(convertedData, metricToExtract, 'Current Year')
57373
+ ? [extractSeriesFromConvertedData(convertedData, metricToExtract, 'Current Year')]
57374
+ : [];
57375
+ }
57376
+ const currentYear = new Date().getFullYear();
57377
+ const priorYear = currentYear - 1;
57378
+ const priorYearPoints = [];
57379
+ const currentYearPoints = [];
57380
+ convertedData.rows?.forEach((row) => {
57381
+ const dateValue = row.dimensionValues?.[dateIndex];
57382
+ const metricValue = parseFloat(row.metricValues?.[metricIndex] || '0');
57383
+ if (dateValue) {
57384
+ const year = parseInt(dateValue.substring(0, 4), 10);
57385
+ const month = parseInt(dateValue.substring(4, 6) || dateValue.substring(5, 7), 10);
57386
+ const point = {
57387
+ category: String(month),
57388
+ value: metricValue,
57389
+ displayLabel: formatMonthLabel(String(month))
57390
+ };
57391
+ if (year === priorYear) {
57392
+ priorYearPoints.push(point);
57393
+ }
57394
+ else if (year === currentYear) {
57395
+ currentYearPoints.push(point);
57396
+ }
57397
+ }
57398
+ });
57399
+ const series = [];
57400
+ if (priorYearPoints.length > 0) {
57401
+ series.push({
57402
+ name: 'Prior Year',
57403
+ data: aggregateAndSortByMonth(priorYearPoints)
57404
+ });
57405
+ }
57406
+ if (currentYearPoints.length > 0) {
57407
+ series.push({
57408
+ name: 'Current Year',
57409
+ data: aggregateAndSortByMonth(currentYearPoints)
57410
+ });
57411
+ }
57412
+ return series;
57413
+ }
57414
+ function aggregateAndSortByMonth(points) {
57415
+ const monthMap = new Map();
57416
+ points.forEach(point => {
57417
+ const existing = monthMap.get(point.category);
57418
+ if (existing) {
57419
+ existing.value += point.value;
57420
+ }
57421
+ else {
57422
+ monthMap.set(point.category, { ...point });
57423
+ }
57424
+ });
57425
+ return sortDataByMonth(Array.from(monthMap.values()));
57426
+ }
57362
57427
  function sumMetricFromUiData(uiData, metricToSum) {
57363
57428
  if (!uiData?.convertedDataResults) {
57364
57429
  return 0;
@@ -57673,15 +57738,12 @@ class InitialTargetSettingComponent {
57673
57738
  return this.isValid() && this.metricCalculations().length > 0;
57674
57739
  }, ...(ngDevMode ? [{ debugName: "showMetricsVisualization" }] : []));
57675
57740
  this.revenueChartData = computed(() => {
57676
- const mainData = this.mainUiData();
57677
- const yoyData = this.yoyUiData();
57678
- if (!mainData && !yoyData) {
57679
- console.log('no data', mainData, yoyData);
57741
+ const trendData = this.trendUiData();
57742
+ if (!trendData?.convertedDataResults) {
57680
57743
  return null;
57681
57744
  }
57682
- const series = transformUiDataToChartSeries(mainData, yoyData, MetricEnum.PURCHASE_REVENUE);
57745
+ const series = transformTrendUiDataToChartSeries(trendData, MetricEnum.PURCHASE_REVENUE);
57683
57746
  if (series.length === 0) {
57684
- console.log('no series length');
57685
57747
  return null;
57686
57748
  }
57687
57749
  return {
@@ -63428,7 +63490,7 @@ class SymphiqBusinessAnalysisDashboardComponent {
63428
63490
  type: HostListener,
63429
63491
  args: ['document:keydown', ['$event']]
63430
63492
  }] }); })();
63431
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(SymphiqBusinessAnalysisDashboardComponent, { className: "SymphiqBusinessAnalysisDashboardComponent", filePath: "lib/components/business-analysis-dashboard/symphiq-business-analysis-dashboard.component.ts", lineNumber: 336 }); })();
63493
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(SymphiqBusinessAnalysisDashboardComponent, { className: "SymphiqBusinessAnalysisDashboardComponent", filePath: "lib/components/business-analysis-dashboard/symphiq-business-analysis-dashboard.component.ts", lineNumber: 337 }); })();
63432
63494
 
63433
63495
  function DashboardHeaderComponent_Conditional_8_Template(rf, ctx) { if (rf & 1) {
63434
63496
  i0.ɵɵelement(0, "div", 6);
@@ -84446,525 +84508,525 @@ class SymphiqProfileAnalysisDashboardComponent {
84446
84508
  standalone: true,
84447
84509
  imports: [CommonModule, DashboardHeaderComponent, SearchModalComponent, ViewModeSwitcherModalComponent, JourneyProgressIndicatorComponent, FloatingTocComponent, SectionNavigationComponent, GradeBadgeComponent, ShopWelcomeBannerComponent, FocusAreaWelcomeBannerComponent, MetricWelcomeBannerComponent, FocusAreaExecutiveSummaryComponent, MetricExecutiveSummaryComponent, NapkinVisualPlaceholderComponent, TooltipContainerComponent, ProfileSectionContentComponent, ProfileAnalysisModalComponent, ModalComponent, GoalCardComponent, GoalObjectivesModalContentComponent, ObjectiveStrategiesModalContentComponent, StrategyRecommendationsModalContentComponent, CategoryDetailModalContentComponent, StrengthDetailModalContentComponent, GapDetailModalContentComponent, OpportunityDetailModalContentComponent, BusinessAnalysisModalComponent, SectionDividerComponent, SymphiqIconComponent, RelatedGoalChipsComponent, StrategicGoalsTiledGridComponent, CollapsibleAnalysisSectionGroupComponent],
84448
84510
  changeDetection: ChangeDetectionStrategy.OnPush,
84449
- template: `
84450
- <div [ngClass]="getContainerClasses()" class="min-h-screen relative">
84451
- <div class="animated-bubbles" [class.light-mode]="isLightMode()" style="position: fixed; top: 0; left: 0; right: 0; bottom: 0; width: 100vw; height: 100vh; z-index: 1; pointer-events: none;"></div>
84452
-
84453
- <!-- Scroll Progress Bar -->
84454
- <div
84455
- [class]="embedded() ? 'sticky top-0 left-0 right-0 h-1 z-[60] bg-slate-200/30' : 'fixed top-0 left-0 right-0 h-1 z-[60] bg-slate-200/30'">
84456
- <div
84457
- [style.width.%]="scrollProgress()"
84458
- [ngClass]="isLightMode() ? 'bg-gradient-to-r from-blue-500 to-purple-500' : 'bg-gradient-to-r from-blue-400 to-purple-400'"
84459
- class="h-full transition-all duration-200 ease-out">
84460
- </div>
84461
- </div>
84462
-
84463
- <div class="relative z-[51]">
84464
- <!-- Dashboard Header -->
84465
- <symphiq-dashboard-header
84466
- [title]="profileAnalysis()?.profileAnalysisStructured?.businessName || 'Profile Analysis'"
84467
- [subtitle]="getAnalysisSubtitle()"
84468
- [currentSection]="getAnalysisSubtitle()"
84469
- [viewMode]="viewMode()"
84470
- [viewModeLabel]="displayModeLabel()"
84471
- [isLoading]="isLoading()"
84472
- [requestedByUser]="requestedByUser()"
84473
- [createdDate]="profileAnalysis()?.selfContentCompletedDate"
84474
- (searchClick)="openSearch()"
84475
- (viewModeClick)="openViewModeSwitcher()"
84476
- />
84477
-
84478
- <!-- Journey Progress Banner -->
84479
- @if (isSimplifiedView() && !isOnboarded()) {
84480
- <symphiq-journey-progress-indicator
84481
- [viewMode]="viewMode()"
84482
- [currentStepId]="currentStepId()"
84483
- [showNextStepAction]="true"
84484
- [forDemo]="forDemo()"
84485
- [maxAccessibleStepId]="maxAccessibleStepId()"
84486
- (nextStepClick)="nextStepClick.emit()"
84487
- (stepClick)="stepClick.emit($event)"
84488
- />
84489
- }
84490
-
84491
- <!-- Main Content -->
84492
- <main class="relative z-10 max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12 space-y-12">
84493
-
84494
- <!-- Welcome Banner (Simplified View Only) -->
84495
- @if (isSimplifiedView()) {
84496
- <div class="mb-12">
84497
- @if (!isFocusAreaAnalysis() && !isMetricAnalysis()) {
84498
- <symphiq-shop-welcome-banner
84499
- [viewMode]="viewMode()"
84500
- [businessName]="profileAnalysis()?.profileAnalysisStructured?.businessName || 'your shop'"
84501
- [isOnboarded]="isOnboarded()"
84502
- />
84503
- }
84504
- @if (isFocusAreaAnalysis()) {
84505
- <symphiq-focus-area-welcome-banner
84506
- [viewMode]="viewMode()"
84507
- [focusAreaDomain]="focusAreaDomain()"
84508
- [focusAreaName]="focusAreaName()"
84509
- [focusAreaDetails]="focusAreaDetails()"
84510
- />
84511
- }
84512
- @if (isMetricAnalysis()) {
84513
- <symphiq-metric-welcome-banner
84514
- [viewMode]="viewMode()"
84515
- [metricName]="profileAnalysis()?.profileAnalysisStructured?.metricExecutiveSummary?.metric"
84516
- [isOnboarded]="isOnboarded()"
84517
- />
84518
- }
84519
- </div>
84520
- }
84521
-
84522
- <!-- Simplified View Content -->
84523
- @if (isSimplifiedView()) {
84524
- <!-- Strategic Insights & Goals -->
84525
- <div class="mb-8">
84526
- <symphiq-strategic-goals-tiled-grid
84527
- [goals]="strategicRoadmapGoals()"
84528
- [viewMode]="viewMode()"
84529
- (viewMoreClick)="openGoalModal($event)"
84530
- />
84531
- </div>
84532
-
84533
- <!-- Supporting Business Context -->
84534
- @if (nonStrategicSections().length > 0) {
84535
- <div>
84536
- <symphiq-collapsible-analysis-section-group
84537
- [sections]="nonStrategicSections()"
84538
- [viewMode]="viewMode()"
84539
- [executiveSummary]="executiveSummary()"
84540
- [focusAreaExecutiveSummary]="focusAreaExecutiveSummary()"
84541
- [metricExecutiveSummary]="metricExecutiveSummary()"
84542
- [metricName]="metricName()"
84543
- [allGoals]="allGoals()"
84544
- [allMetrics]="allMetrics()"
84545
- [allCharts]="allCharts()"
84546
- [allInsights]="allInsights()"
84547
- />
84548
- </div>
84549
- }
84550
- }
84551
-
84552
- <!-- Compact & Expanded View Content -->
84553
- @if (!isSimplifiedView()) {
84554
- <!-- SHOP Executive Summary -->
84555
- @if (!isFocusAreaAnalysis() && executiveSummary(); as summary) {
84556
- <section id="section-executive-summary" class="space-y-6 scroll-mt-24">
84557
- <!-- Summary Banner -->
84558
- <div [ngClass]="getBannerClasses()" class="rounded-2xl p-8 shadow-xl">
84559
- <div class="space-y-6">
84560
- <div class="flex items-start justify-between gap-4">
84561
- <div class="flex-1">
84562
- <h2 [ngClass]="getSectionTitleClasses()" class="text-2xl font-bold mb-3">
84563
- Executive Summary
84564
- </h2>
84565
- <p [ngClass]="getTextClasses()" class="text-lg leading-relaxed">
84566
- {{ summary.gradeRationale }}
84567
- </p>
84568
- </div>
84569
- @if (summary.overallGrade) {
84570
- <symphiq-grade-badge
84571
- [grade]="summary.overallGrade"
84572
- [gradeRationale]="summary.gradeRationale || ''"
84573
- [viewMode]="viewMode()"
84574
- />
84575
- }
84576
- </div>
84577
-
84578
- @if (summary.narrative) {
84579
- <div [ngClass]="getNarrativeClasses()" class="rounded-xl p-6">
84580
- <h3 [ngClass]="getSubheadingClasses()" class="text-lg font-semibold mb-3">
84581
- Analysis Narrative
84582
- </h3>
84583
- <div class="relative">
84584
- @if (summary.napkinVisual && summary.napkinVisual.enabled) {
84585
- <div class="mb-6 lg:float-left lg:mr-6 lg:mb-4 lg:max-w-[66%]">
84586
- <symphiq-napkin-visual-placeholder
84587
- [visual]="summary.napkinVisual"
84588
- [viewMode]="viewMode()"
84589
- />
84590
- </div>
84591
- }
84592
- <p [ngClass]="getTextClasses()" class="text-sm leading-relaxed whitespace-pre-line">
84593
- {{ summary.narrative }}
84594
- </p>
84595
- <div class="clear-both"></div>
84596
- </div>
84597
- </div>
84598
- }
84599
-
84600
- <!-- Stats -->
84601
- <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
84602
- <button
84603
- type="button"
84604
- (click)="onKeyStrengthsClick(summary)"
84605
- [ngClass]="getKeyStrengthsStatCardClasses()"
84606
- class="p-4 rounded-xl text-left transition-all duration-200 hover:scale-[1.02] active:scale-[0.98] group cursor-pointer">
84607
- <div [ngClass]="getKeyStrengthsStatLabelClasses()" class="text-xs font-semibold uppercase mb-1">
84608
- Key Strengths
84609
- </div>
84610
- <div [ngClass]="getKeyStrengthsStatValueClasses()" class="text-3xl font-bold mb-2">
84611
- {{ summary.keyStrengths?.length || 0 }}
84612
- </div>
84613
- <div class="flex items-center gap-1.5 text-xs font-medium">
84614
- <span [ngClass]="getKeyStrengthsButtonTextClasses()">View Details</span>
84615
- <symphiq-icon
84616
- [icon]="{ name: 'chevron-right', source: IconSourceEnum.HEROICONS }"
84617
- size="w-4 h-4"
84618
- [ngClass]="getKeyStrengthsButtonTextClasses()"
84619
- class="transition-transform group-hover:translate-x-1"
84620
- />
84621
- </div>
84622
- </button>
84623
- <button
84624
- type="button"
84625
- (click)="onCriticalGapsClick(summary)"
84626
- [ngClass]="getCriticalGapsStatCardClasses()"
84627
- class="p-4 rounded-xl text-left transition-all duration-200 hover:scale-[1.02] active:scale-[0.98] group cursor-pointer">
84628
- <div [ngClass]="getCriticalGapsStatLabelClasses()" class="text-xs font-semibold uppercase mb-1">
84629
- Critical Gaps
84630
- </div>
84631
- <div [ngClass]="getCriticalGapsStatValueClasses()" class="text-3xl font-bold mb-2">
84632
- {{ summary.criticalGaps?.length || 0 }}
84633
- </div>
84634
- <div class="flex items-center gap-1.5 text-xs font-medium">
84635
- <span [ngClass]="getCriticalGapsButtonTextClasses()">View Details</span>
84636
- <symphiq-icon
84637
- [icon]="{ name: 'chevron-right', source: IconSourceEnum.HEROICONS }"
84638
- size="w-4 h-4"
84639
- [ngClass]="getCriticalGapsButtonTextClasses()"
84640
- class="transition-transform group-hover:translate-x-1"
84641
- />
84642
- </div>
84643
- </button>
84644
- <button
84645
- type="button"
84646
- (click)="scrollToQuickWins()"
84647
- [ngClass]="getQuickWinsStatCardClasses()"
84648
- class="p-4 rounded-xl text-left transition-all duration-200 hover:scale-[1.02] active:scale-[0.98] group cursor-pointer">
84649
- <div [ngClass]="getQuickWinsStatLabelClasses()" class="text-xs font-semibold uppercase mb-1">
84650
- Quick Wins
84651
- </div>
84652
- <div [ngClass]="getQuickWinsStatValueClasses()" class="text-3xl font-bold mb-2">
84653
- {{ summary.quickWins?.length || 0 }}
84654
- </div>
84655
- <div class="flex items-center gap-1.5 text-xs font-medium">
84656
- <span [ngClass]="getQuickWinsButtonTextClasses()">Details Below</span>
84657
- <symphiq-icon
84658
- [icon]="{ name: 'chevron-down', source: IconSourceEnum.HEROICONS }"
84659
- size="w-4 h-4"
84660
- [ngClass]="getQuickWinsButtonTextClasses()"
84661
- class="transition-transform group-hover:translate-y-1 animate-bounce"
84662
- />
84663
- </div>
84664
- </button>
84665
- </div>
84666
- </div>
84667
- </div>
84668
-
84669
- <!-- Quick Wins -->
84670
- @if (summary.quickWins && summary.quickWins.length > 0) {
84671
- <div id="quick-wins-section" class="space-y-4 scroll-mt-24">
84672
- <h3 [ngClass]="getSectionTitleClasses()" class="text-xl font-bold">
84673
- Quick Wins
84674
- </h3>
84675
- <div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
84676
- @for (win of summary.quickWins; track $index) {
84677
- <div [ngClass]="getQuickWinCardClasses()"
84678
- class="rounded-xl p-6 transition-all duration-300">
84679
- <div class="space-y-4">
84680
- <div class="flex items-start gap-3">
84681
- <span [ngClass]="getNumberBadgeClasses()"
84682
- class="flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center text-sm font-bold">
84683
- {{ $index + 1 }}
84684
- </span>
84685
- <p [ngClass]="getQuickWinTextClasses()" class="font-semibold leading-tight flex-1">
84686
- {{ win.action }}
84687
- </p>
84688
- </div>
84689
-
84690
- <div class="flex flex-wrap gap-2">
84691
- <span [ngClass]="getEffortBadgeClasses(win.effort)"
84692
- class="px-3 py-1 rounded-full text-xs font-semibold">
84693
- {{ formatLabel(win.effort) }} Effort
84694
- </span>
84695
- <span [ngClass]="getImpactBadgeClasses(win.impact)"
84696
- class="px-3 py-1 rounded-full text-xs font-semibold">
84697
- {{ formatLabel(win.impact) }} Impact
84698
- </span>
84699
- </div>
84700
-
84701
- @if (win.estimatedTimeframe) {
84702
- <div class="flex items-center gap-2 text-sm" [ngClass]="getMetaTextClasses()">
84703
- <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
84704
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
84705
- d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
84706
- </svg>
84707
- <span>{{ win.estimatedTimeframe }}</span>
84708
- </div>
84709
- }
84710
-
84711
- @if (win.relatedGoalId) {
84712
- <div class="space-y-2">
84713
- <h4 [ngClass]="getMetaTextClasses()"
84714
- class="text-xs font-semibold uppercase tracking-wider">
84715
- Related Goal
84716
- </h4>
84717
- <symphiq-related-goal-chips
84718
- [relatedGoalIds]="[win.relatedGoalId]"
84719
- [allGoals]="allGoals()"
84720
- [viewMode]="viewMode()"
84721
- />
84722
- </div>
84723
- }
84724
- </div>
84725
- </div>
84726
- }
84727
- </div>
84728
- </div>
84729
- }
84730
- </section>
84731
- }
84732
-
84733
- <!-- FOCUS_AREA Executive Summary -->
84734
- @if (isFocusAreaAnalysis() && focusAreaExecutiveSummary(); as summary) {
84735
- <symphiq-focus-area-executive-summary
84736
- [viewMode]="viewMode()"
84737
- [summary]="summary"
84738
- [allGoals]="allGoals()"
84739
- (topPrioritiesClick)="handleTopPrioritiesClick()"
84740
- (priorityDetailClick)="handlePriorityDetailClick($event)"
84741
- />
84742
- }
84743
-
84744
- <!-- METRIC Executive Summary -->
84745
- @if (isMetricAnalysis() && metricExecutiveSummary(); as summary) {
84746
- <symphiq-metric-executive-summary
84747
- [viewMode]="viewMode()"
84748
- [summary]="summary"
84749
- [metricName]="metricName()"
84750
- [allGoals]="allGoals()"
84751
- (topPrioritiesClick)="handleMetricTopPrioritiesClick()"
84752
- (priorityDetailClick)="handleMetricPriorityDetailClick($event)"
84753
- />
84754
- }
84755
-
84756
- <!-- Divider Before First Section -->
84757
- @if (sections(); as sectionList) {
84758
- @if (sectionList.length > 0 && sectionList[0].icon) {
84759
- <symphiq-section-divider
84760
- [viewMode]="viewMode()"
84761
- [sectionIcon]="sectionList[0].icon"
84762
- />
84763
- }
84764
- }
84765
-
84766
- <!-- Profile Analysis Sections -->
84767
- @if (sections(); as sectionList) {
84768
- <section class="space-y-8">
84769
- @for (section of sectionList; track section.id; let idx = $index; let last = $last) {
84770
- <div [id]="'section-' + section.id" [ngClass]="getSectionCardClasses()"
84771
- class="rounded-xl p-8 scroll-mt-24">
84772
- <!-- Icon and Title -->
84773
- <div class="flex items-start gap-3 mb-6">
84774
- @if (section.icon) {
84775
- <div [ngClass]="getSectionIconClasses()"
84776
- class="flex-shrink-0 w-12 h-12 rounded-xl flex items-center justify-center">
84777
- <symphiq-icon [icon]="section.icon" size="w-6 h-6"></symphiq-icon>
84778
- </div>
84779
- }
84780
- <div class="flex-1">
84781
- <h3 [ngClass]="getSectionTitleClasses()" class="text-2xl font-bold">
84782
- {{ section.title }}
84783
- </h3>
84784
- </div>
84785
- </div>
84786
-
84787
- <!-- Description and Visual Side-by-Side -->
84788
- @if (section.description || (section.visual && section.visual.enabled)) {
84789
- <div class="mb-6 flex flex-col lg:flex-row gap-6 items-start"
84790
- [class.lg:flex-row-reverse]="idx % 2 === 0">
84791
- @if (section.visual && section.visual.enabled) {
84792
- <div class="w-full lg:w-2/3">
84793
- <symphiq-napkin-visual-placeholder
84794
- [visual]="section.visual"
84795
- [viewMode]="viewMode()"
84796
- />
84797
- </div>
84798
- }
84799
- @if (section.description) {
84800
- <div class="w-full"
84801
- [class.lg:w-1/3]="section.visual && section.visual.enabled" [class.lg:w-full]="!section.visual || !section.visual.enabled">
84802
- <p [ngClass]="getSectionDescriptionClasses()"
84803
- class="text-sm leading-relaxed whitespace-pre-line">
84804
- {{ section.description }}
84805
- </p>
84806
- </div>
84807
- }
84808
- </div>
84809
- }
84810
-
84811
- <!-- Section Content -->
84812
- <symphiq-profile-section-content
84813
- [section]="section"
84814
- [executiveSummary]="section.id === 'executive-summary' ? executiveSummary() : undefined"
84815
- [viewMode]="viewMode()"
84816
- [sectionIndex]="idx"
84817
- [allGoals]="allGoals()"
84818
- [allMetrics]="allMetrics()"
84819
- [allCharts]="allCharts()"
84820
- [allInsights]="allInsights()"
84821
- />
84822
- </div>
84823
-
84824
- <!-- Section Divider (between sections) -->
84825
- @if (!last) {
84826
- <symphiq-section-divider
84827
- [viewMode]="viewMode()"
84828
- [sectionIcon]="sectionList[idx + 1].icon"
84829
- />
84830
- }
84831
- }
84832
- </section>
84833
- }
84834
- }
84835
-
84836
- </main>
84837
-
84838
- <!-- Table of Contents (Compact & Expanded Views) -->
84839
- @if (!isSimplifiedView() && sections()) {
84840
- <symphiq-floating-toc
84841
- [sections]="tocSections()"
84842
- [viewMode]="viewMode()"
84843
- [embedded]="embedded()"
84844
- [scrollElement]="scrollElement() ?? undefined"
84845
- />
84846
- }
84847
-
84848
- <!-- Section Navigation Dots (Compact & Expanded Views) -->
84849
- @if (!isSimplifiedView() && sections()) {
84850
- <symphiq-section-navigation
84851
- [sections]="tocSections()"
84852
- [viewMode]="viewMode()"
84853
- [embedded]="embedded()"
84854
- [scrollElement]="scrollElement() ?? undefined"
84855
- />
84856
- }
84857
-
84858
- <!-- Search Modal -->
84859
- <symphiq-search-modal
84860
- [isOpen]="isSearchOpen()"
84861
- [isLightMode]="isLightMode()"
84862
- (close)="closeSearch()"
84863
- />
84864
-
84865
- <!-- View Mode Switcher Modal -->
84866
- <symphiq-view-mode-switcher-modal
84867
- [isOpen]="isViewModeSwitcherOpen()"
84868
- [currentMode]="currentDisplayMode()"
84869
- [viewMode]="viewMode()"
84870
- (close)="closeViewModeSwitcher()"
84871
- (modeSelected)="handleDisplayModeChange($event)"
84872
- />
84873
-
84874
- <!-- Profile Analysis Modal -->
84875
- <symphiq-profile-analysis-modal
84876
- [isLightMode]="isLightMode()"
84877
- [allMetrics]="allMetrics()"
84878
- [allInsights]="allInsights()"
84879
- [allBusinessInsights]="allBusinessInsights()"
84880
- [allCharts]="allCharts()"
84881
- >
84882
- @if (modalType() === 'goal-detail' && getGoalDetailData(); as data) {
84883
- <symphiq-goal-card
84884
- [goal]="data.goal"
84885
- [viewMode]="data.viewMode"
84886
- [isInModal]="true"
84887
- [allMetrics]="allMetrics()"
84888
- [allCharts]="allCharts()"
84889
- [allInsights]="allInsights()"
84890
- [currentModalState]="getCurrentModalState()"
84891
- />
84892
- }
84893
- @if (modalType() === 'goal-objectives' && getGoalDetailData(); as data) {
84894
- <symphiq-goal-objectives-modal-content
84895
- [goal]="data.goal"
84896
- [viewMode]="data.viewMode"
84897
- />
84898
- }
84899
- @if (modalType() === 'objective-strategies' && getObjectiveStrategiesData(); as data) {
84900
- <symphiq-objective-strategies-modal-content
84901
- [objective]="data.objective"
84902
- [goalTitle]="data.goalTitle"
84903
- [viewMode]="data.viewMode"
84904
- />
84905
- }
84906
- @if (modalType() === 'strategy-recommendations' && getStrategyRecommendationsData(); as data) {
84907
- <symphiq-strategy-recommendations-modal-content
84908
- [strategy]="data.strategy"
84909
- [objectiveTitle]="data.objectiveTitle"
84910
- [goalTitle]="data.goalTitle"
84911
- [viewMode]="data.viewMode"
84912
- [allMetrics]="allMetrics()"
84913
- [allCharts]="allCharts()"
84914
- [allInsights]="allInsights()"
84915
- [allBusinessInsights]="allBusinessInsights()"
84916
- [currentModalState]="getCurrentModalState()"
84917
- />
84918
- }
84919
- @if (modalType() === 'category-detail' && getCategoryDetailData(); as data) {
84920
- <symphiq-category-detail-modal-content
84921
- [category]="data.category"
84922
- [viewMode]="data.viewMode"
84923
- [scrollToSection]="data.scrollToSection"
84924
- />
84925
- }
84926
- @if (modalType() === 'strength-detail' && getStrengthDetailData(); as data) {
84927
- <symphiq-strength-detail-modal-content
84928
- [strength]="data.strength"
84929
- [viewMode]="data.viewMode"
84930
- [allFunnelStrengths]="funnelStrengths()"
84931
- [currentModalState]="getCurrentModalState()"
84932
- />
84933
- }
84934
- @if (modalType() === 'gap-detail' && getGapDetailData(); as data) {
84935
- <symphiq-gap-detail-modal-content
84936
- [gap]="data.gap"
84937
- [viewMode]="data.viewMode"
84938
- [allGoals]="allGoals()"
84939
- [allWeaknesses]="funnelWeaknesses()"
84940
- [currentModalState]="getCurrentModalState()"
84941
- />
84942
- }
84943
- @if (modalType() === 'opportunity-detail' && getOpportunityDetailData(); as data) {
84944
- <symphiq-opportunity-detail-modal-content
84945
- [opportunity]="data.opportunity"
84946
- [viewMode]="data.viewMode"
84947
- [allStrengths]="funnelStrengths()"
84948
- [currentModalState]="getCurrentModalState()"
84949
- />
84950
- }
84951
- </symphiq-profile-analysis-modal>
84952
-
84953
- <!-- Funnel Analysis Modal (for insights and metrics from profile goals) -->
84954
- <symphiq-funnel-analysis-modal
84955
- [isLightMode]="isLightMode()"
84956
- [viewMode]="viewMode()"
84957
- [allMetrics]="allMetrics()"
84958
- [allInsights]="allInsights()"
84959
- [allCharts]="allCharts()"
84960
- />
84961
-
84962
- <!-- Business Analysis Modal (for napkin visuals and other content) -->
84963
- <symphiq-business-analysis-modal [isLightMode]="isLightMode()"/>
84964
-
84965
- <!-- Tooltip Container -->
84966
- <symphiq-tooltip-container/>
84967
- </div>
84511
+ template: `
84512
+ <div [ngClass]="getContainerClasses()" class="min-h-screen relative">
84513
+ <div class="animated-bubbles" [class.light-mode]="isLightMode()" style="position: fixed; top: 0; left: 0; right: 0; bottom: 0; width: 100vw; height: 100vh; z-index: 1; pointer-events: none;"></div>
84514
+
84515
+ <!-- Scroll Progress Bar -->
84516
+ <div
84517
+ [class]="embedded() ? 'sticky top-0 left-0 right-0 h-1 z-[60] bg-slate-200/30' : 'fixed top-0 left-0 right-0 h-1 z-[60] bg-slate-200/30'">
84518
+ <div
84519
+ [style.width.%]="scrollProgress()"
84520
+ [ngClass]="isLightMode() ? 'bg-gradient-to-r from-blue-500 to-purple-500' : 'bg-gradient-to-r from-blue-400 to-purple-400'"
84521
+ class="h-full transition-all duration-200 ease-out">
84522
+ </div>
84523
+ </div>
84524
+
84525
+ <div class="relative z-[51]">
84526
+ <!-- Dashboard Header -->
84527
+ <symphiq-dashboard-header
84528
+ [title]="profileAnalysis()?.profileAnalysisStructured?.businessName || 'Profile Analysis'"
84529
+ [subtitle]="getAnalysisSubtitle()"
84530
+ [currentSection]="getAnalysisSubtitle()"
84531
+ [viewMode]="viewMode()"
84532
+ [viewModeLabel]="displayModeLabel()"
84533
+ [isLoading]="isLoading()"
84534
+ [requestedByUser]="requestedByUser()"
84535
+ [createdDate]="profileAnalysis()?.selfContentCompletedDate"
84536
+ (searchClick)="openSearch()"
84537
+ (viewModeClick)="openViewModeSwitcher()"
84538
+ />
84539
+
84540
+ <!-- Journey Progress Banner -->
84541
+ @if (isSimplifiedView() && !isOnboarded()) {
84542
+ <symphiq-journey-progress-indicator
84543
+ [viewMode]="viewMode()"
84544
+ [currentStepId]="currentStepId()"
84545
+ [showNextStepAction]="true"
84546
+ [forDemo]="forDemo()"
84547
+ [maxAccessibleStepId]="maxAccessibleStepId()"
84548
+ (nextStepClick)="nextStepClick.emit()"
84549
+ (stepClick)="stepClick.emit($event)"
84550
+ />
84551
+ }
84552
+
84553
+ <!-- Main Content -->
84554
+ <main class="relative z-10 max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12 space-y-12">
84555
+
84556
+ <!-- Welcome Banner (Simplified View Only) -->
84557
+ @if (isSimplifiedView()) {
84558
+ <div class="mb-12">
84559
+ @if (!isFocusAreaAnalysis() && !isMetricAnalysis()) {
84560
+ <symphiq-shop-welcome-banner
84561
+ [viewMode]="viewMode()"
84562
+ [businessName]="profileAnalysis()?.profileAnalysisStructured?.businessName || 'your shop'"
84563
+ [isOnboarded]="isOnboarded()"
84564
+ />
84565
+ }
84566
+ @if (isFocusAreaAnalysis()) {
84567
+ <symphiq-focus-area-welcome-banner
84568
+ [viewMode]="viewMode()"
84569
+ [focusAreaDomain]="focusAreaDomain()"
84570
+ [focusAreaName]="focusAreaName()"
84571
+ [focusAreaDetails]="focusAreaDetails()"
84572
+ />
84573
+ }
84574
+ @if (isMetricAnalysis()) {
84575
+ <symphiq-metric-welcome-banner
84576
+ [viewMode]="viewMode()"
84577
+ [metricName]="profileAnalysis()?.profileAnalysisStructured?.metricExecutiveSummary?.metric"
84578
+ [isOnboarded]="isOnboarded()"
84579
+ />
84580
+ }
84581
+ </div>
84582
+ }
84583
+
84584
+ <!-- Simplified View Content -->
84585
+ @if (isSimplifiedView()) {
84586
+ <!-- Strategic Insights & Goals -->
84587
+ <div class="mb-8">
84588
+ <symphiq-strategic-goals-tiled-grid
84589
+ [goals]="strategicRoadmapGoals()"
84590
+ [viewMode]="viewMode()"
84591
+ (viewMoreClick)="openGoalModal($event)"
84592
+ />
84593
+ </div>
84594
+
84595
+ <!-- Supporting Business Context -->
84596
+ @if (nonStrategicSections().length > 0) {
84597
+ <div>
84598
+ <symphiq-collapsible-analysis-section-group
84599
+ [sections]="nonStrategicSections()"
84600
+ [viewMode]="viewMode()"
84601
+ [executiveSummary]="executiveSummary()"
84602
+ [focusAreaExecutiveSummary]="focusAreaExecutiveSummary()"
84603
+ [metricExecutiveSummary]="metricExecutiveSummary()"
84604
+ [metricName]="metricName()"
84605
+ [allGoals]="allGoals()"
84606
+ [allMetrics]="allMetrics()"
84607
+ [allCharts]="allCharts()"
84608
+ [allInsights]="allInsights()"
84609
+ />
84610
+ </div>
84611
+ }
84612
+ }
84613
+
84614
+ <!-- Compact & Expanded View Content -->
84615
+ @if (!isSimplifiedView()) {
84616
+ <!-- SHOP Executive Summary -->
84617
+ @if (!isFocusAreaAnalysis() && executiveSummary(); as summary) {
84618
+ <section id="section-executive-summary" class="space-y-6 scroll-mt-24">
84619
+ <!-- Summary Banner -->
84620
+ <div [ngClass]="getBannerClasses()" class="rounded-2xl p-8 shadow-xl">
84621
+ <div class="space-y-6">
84622
+ <div class="flex items-start justify-between gap-4">
84623
+ <div class="flex-1">
84624
+ <h2 [ngClass]="getSectionTitleClasses()" class="text-2xl font-bold mb-3">
84625
+ Executive Summary
84626
+ </h2>
84627
+ <p [ngClass]="getTextClasses()" class="text-lg leading-relaxed">
84628
+ {{ summary.gradeRationale }}
84629
+ </p>
84630
+ </div>
84631
+ @if (summary.overallGrade) {
84632
+ <symphiq-grade-badge
84633
+ [grade]="summary.overallGrade"
84634
+ [gradeRationale]="summary.gradeRationale || ''"
84635
+ [viewMode]="viewMode()"
84636
+ />
84637
+ }
84638
+ </div>
84639
+
84640
+ @if (summary.narrative) {
84641
+ <div [ngClass]="getNarrativeClasses()" class="rounded-xl p-6">
84642
+ <h3 [ngClass]="getSubheadingClasses()" class="text-lg font-semibold mb-3">
84643
+ Analysis Narrative
84644
+ </h3>
84645
+ <div class="relative">
84646
+ @if (summary.napkinVisual && summary.napkinVisual.enabled) {
84647
+ <div class="mb-6 lg:float-left lg:mr-6 lg:mb-4 lg:max-w-[66%]">
84648
+ <symphiq-napkin-visual-placeholder
84649
+ [visual]="summary.napkinVisual"
84650
+ [viewMode]="viewMode()"
84651
+ />
84652
+ </div>
84653
+ }
84654
+ <p [ngClass]="getTextClasses()" class="text-sm leading-relaxed whitespace-pre-line">
84655
+ {{ summary.narrative }}
84656
+ </p>
84657
+ <div class="clear-both"></div>
84658
+ </div>
84659
+ </div>
84660
+ }
84661
+
84662
+ <!-- Stats -->
84663
+ <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
84664
+ <button
84665
+ type="button"
84666
+ (click)="onKeyStrengthsClick(summary)"
84667
+ [ngClass]="getKeyStrengthsStatCardClasses()"
84668
+ class="p-4 rounded-xl text-left transition-all duration-200 hover:scale-[1.02] active:scale-[0.98] group cursor-pointer">
84669
+ <div [ngClass]="getKeyStrengthsStatLabelClasses()" class="text-xs font-semibold uppercase mb-1">
84670
+ Key Strengths
84671
+ </div>
84672
+ <div [ngClass]="getKeyStrengthsStatValueClasses()" class="text-3xl font-bold mb-2">
84673
+ {{ summary.keyStrengths?.length || 0 }}
84674
+ </div>
84675
+ <div class="flex items-center gap-1.5 text-xs font-medium">
84676
+ <span [ngClass]="getKeyStrengthsButtonTextClasses()">View Details</span>
84677
+ <symphiq-icon
84678
+ [icon]="{ name: 'chevron-right', source: IconSourceEnum.HEROICONS }"
84679
+ size="w-4 h-4"
84680
+ [ngClass]="getKeyStrengthsButtonTextClasses()"
84681
+ class="transition-transform group-hover:translate-x-1"
84682
+ />
84683
+ </div>
84684
+ </button>
84685
+ <button
84686
+ type="button"
84687
+ (click)="onCriticalGapsClick(summary)"
84688
+ [ngClass]="getCriticalGapsStatCardClasses()"
84689
+ class="p-4 rounded-xl text-left transition-all duration-200 hover:scale-[1.02] active:scale-[0.98] group cursor-pointer">
84690
+ <div [ngClass]="getCriticalGapsStatLabelClasses()" class="text-xs font-semibold uppercase mb-1">
84691
+ Critical Gaps
84692
+ </div>
84693
+ <div [ngClass]="getCriticalGapsStatValueClasses()" class="text-3xl font-bold mb-2">
84694
+ {{ summary.criticalGaps?.length || 0 }}
84695
+ </div>
84696
+ <div class="flex items-center gap-1.5 text-xs font-medium">
84697
+ <span [ngClass]="getCriticalGapsButtonTextClasses()">View Details</span>
84698
+ <symphiq-icon
84699
+ [icon]="{ name: 'chevron-right', source: IconSourceEnum.HEROICONS }"
84700
+ size="w-4 h-4"
84701
+ [ngClass]="getCriticalGapsButtonTextClasses()"
84702
+ class="transition-transform group-hover:translate-x-1"
84703
+ />
84704
+ </div>
84705
+ </button>
84706
+ <button
84707
+ type="button"
84708
+ (click)="scrollToQuickWins()"
84709
+ [ngClass]="getQuickWinsStatCardClasses()"
84710
+ class="p-4 rounded-xl text-left transition-all duration-200 hover:scale-[1.02] active:scale-[0.98] group cursor-pointer">
84711
+ <div [ngClass]="getQuickWinsStatLabelClasses()" class="text-xs font-semibold uppercase mb-1">
84712
+ Quick Wins
84713
+ </div>
84714
+ <div [ngClass]="getQuickWinsStatValueClasses()" class="text-3xl font-bold mb-2">
84715
+ {{ summary.quickWins?.length || 0 }}
84716
+ </div>
84717
+ <div class="flex items-center gap-1.5 text-xs font-medium">
84718
+ <span [ngClass]="getQuickWinsButtonTextClasses()">Details Below</span>
84719
+ <symphiq-icon
84720
+ [icon]="{ name: 'chevron-down', source: IconSourceEnum.HEROICONS }"
84721
+ size="w-4 h-4"
84722
+ [ngClass]="getQuickWinsButtonTextClasses()"
84723
+ class="transition-transform group-hover:translate-y-1 animate-bounce"
84724
+ />
84725
+ </div>
84726
+ </button>
84727
+ </div>
84728
+ </div>
84729
+ </div>
84730
+
84731
+ <!-- Quick Wins -->
84732
+ @if (summary.quickWins && summary.quickWins.length > 0) {
84733
+ <div id="quick-wins-section" class="space-y-4 scroll-mt-24">
84734
+ <h3 [ngClass]="getSectionTitleClasses()" class="text-xl font-bold">
84735
+ Quick Wins
84736
+ </h3>
84737
+ <div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
84738
+ @for (win of summary.quickWins; track $index) {
84739
+ <div [ngClass]="getQuickWinCardClasses()"
84740
+ class="rounded-xl p-6 transition-all duration-300">
84741
+ <div class="space-y-4">
84742
+ <div class="flex items-start gap-3">
84743
+ <span [ngClass]="getNumberBadgeClasses()"
84744
+ class="flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center text-sm font-bold">
84745
+ {{ $index + 1 }}
84746
+ </span>
84747
+ <p [ngClass]="getQuickWinTextClasses()" class="font-semibold leading-tight flex-1">
84748
+ {{ win.action }}
84749
+ </p>
84750
+ </div>
84751
+
84752
+ <div class="flex flex-wrap gap-2">
84753
+ <span [ngClass]="getEffortBadgeClasses(win.effort)"
84754
+ class="px-3 py-1 rounded-full text-xs font-semibold">
84755
+ {{ formatLabel(win.effort) }} Effort
84756
+ </span>
84757
+ <span [ngClass]="getImpactBadgeClasses(win.impact)"
84758
+ class="px-3 py-1 rounded-full text-xs font-semibold">
84759
+ {{ formatLabel(win.impact) }} Impact
84760
+ </span>
84761
+ </div>
84762
+
84763
+ @if (win.estimatedTimeframe) {
84764
+ <div class="flex items-center gap-2 text-sm" [ngClass]="getMetaTextClasses()">
84765
+ <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
84766
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
84767
+ d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
84768
+ </svg>
84769
+ <span>{{ win.estimatedTimeframe }}</span>
84770
+ </div>
84771
+ }
84772
+
84773
+ @if (win.relatedGoalId) {
84774
+ <div class="space-y-2">
84775
+ <h4 [ngClass]="getMetaTextClasses()"
84776
+ class="text-xs font-semibold uppercase tracking-wider">
84777
+ Related Goal
84778
+ </h4>
84779
+ <symphiq-related-goal-chips
84780
+ [relatedGoalIds]="[win.relatedGoalId]"
84781
+ [allGoals]="allGoals()"
84782
+ [viewMode]="viewMode()"
84783
+ />
84784
+ </div>
84785
+ }
84786
+ </div>
84787
+ </div>
84788
+ }
84789
+ </div>
84790
+ </div>
84791
+ }
84792
+ </section>
84793
+ }
84794
+
84795
+ <!-- FOCUS_AREA Executive Summary -->
84796
+ @if (isFocusAreaAnalysis() && focusAreaExecutiveSummary(); as summary) {
84797
+ <symphiq-focus-area-executive-summary
84798
+ [viewMode]="viewMode()"
84799
+ [summary]="summary"
84800
+ [allGoals]="allGoals()"
84801
+ (topPrioritiesClick)="handleTopPrioritiesClick()"
84802
+ (priorityDetailClick)="handlePriorityDetailClick($event)"
84803
+ />
84804
+ }
84805
+
84806
+ <!-- METRIC Executive Summary -->
84807
+ @if (isMetricAnalysis() && metricExecutiveSummary(); as summary) {
84808
+ <symphiq-metric-executive-summary
84809
+ [viewMode]="viewMode()"
84810
+ [summary]="summary"
84811
+ [metricName]="metricName()"
84812
+ [allGoals]="allGoals()"
84813
+ (topPrioritiesClick)="handleMetricTopPrioritiesClick()"
84814
+ (priorityDetailClick)="handleMetricPriorityDetailClick($event)"
84815
+ />
84816
+ }
84817
+
84818
+ <!-- Divider Before First Section -->
84819
+ @if (sections(); as sectionList) {
84820
+ @if (sectionList.length > 0 && sectionList[0].icon) {
84821
+ <symphiq-section-divider
84822
+ [viewMode]="viewMode()"
84823
+ [sectionIcon]="sectionList[0].icon"
84824
+ />
84825
+ }
84826
+ }
84827
+
84828
+ <!-- Profile Analysis Sections -->
84829
+ @if (sections(); as sectionList) {
84830
+ <section class="space-y-8">
84831
+ @for (section of sectionList; track section.id; let idx = $index; let last = $last) {
84832
+ <div [id]="'section-' + section.id" [ngClass]="getSectionCardClasses()"
84833
+ class="rounded-xl p-8 scroll-mt-24">
84834
+ <!-- Icon and Title -->
84835
+ <div class="flex items-start gap-3 mb-6">
84836
+ @if (section.icon) {
84837
+ <div [ngClass]="getSectionIconClasses()"
84838
+ class="flex-shrink-0 w-12 h-12 rounded-xl flex items-center justify-center">
84839
+ <symphiq-icon [icon]="section.icon" size="w-6 h-6"></symphiq-icon>
84840
+ </div>
84841
+ }
84842
+ <div class="flex-1">
84843
+ <h3 [ngClass]="getSectionTitleClasses()" class="text-2xl font-bold">
84844
+ {{ section.title }}
84845
+ </h3>
84846
+ </div>
84847
+ </div>
84848
+
84849
+ <!-- Description and Visual Side-by-Side -->
84850
+ @if (section.description || (section.visual && section.visual.enabled)) {
84851
+ <div class="mb-6 flex flex-col lg:flex-row gap-6 items-start"
84852
+ [class.lg:flex-row-reverse]="idx % 2 === 0">
84853
+ @if (section.visual && section.visual.enabled) {
84854
+ <div class="w-full lg:w-2/3">
84855
+ <symphiq-napkin-visual-placeholder
84856
+ [visual]="section.visual"
84857
+ [viewMode]="viewMode()"
84858
+ />
84859
+ </div>
84860
+ }
84861
+ @if (section.description) {
84862
+ <div class="w-full"
84863
+ [class.lg:w-1/3]="section.visual && section.visual.enabled" [class.lg:w-full]="!section.visual || !section.visual.enabled">
84864
+ <p [ngClass]="getSectionDescriptionClasses()"
84865
+ class="text-sm leading-relaxed whitespace-pre-line">
84866
+ {{ section.description }}
84867
+ </p>
84868
+ </div>
84869
+ }
84870
+ </div>
84871
+ }
84872
+
84873
+ <!-- Section Content -->
84874
+ <symphiq-profile-section-content
84875
+ [section]="section"
84876
+ [executiveSummary]="section.id === 'executive-summary' ? executiveSummary() : undefined"
84877
+ [viewMode]="viewMode()"
84878
+ [sectionIndex]="idx"
84879
+ [allGoals]="allGoals()"
84880
+ [allMetrics]="allMetrics()"
84881
+ [allCharts]="allCharts()"
84882
+ [allInsights]="allInsights()"
84883
+ />
84884
+ </div>
84885
+
84886
+ <!-- Section Divider (between sections) -->
84887
+ @if (!last) {
84888
+ <symphiq-section-divider
84889
+ [viewMode]="viewMode()"
84890
+ [sectionIcon]="sectionList[idx + 1].icon"
84891
+ />
84892
+ }
84893
+ }
84894
+ </section>
84895
+ }
84896
+ }
84897
+
84898
+ </main>
84899
+
84900
+ <!-- Table of Contents (Compact & Expanded Views) -->
84901
+ @if (!isSimplifiedView() && sections()) {
84902
+ <symphiq-floating-toc
84903
+ [sections]="tocSections()"
84904
+ [viewMode]="viewMode()"
84905
+ [embedded]="embedded()"
84906
+ [scrollElement]="scrollElement() ?? undefined"
84907
+ />
84908
+ }
84909
+
84910
+ <!-- Section Navigation Dots (Compact & Expanded Views) -->
84911
+ @if (!isSimplifiedView() && sections()) {
84912
+ <symphiq-section-navigation
84913
+ [sections]="tocSections()"
84914
+ [viewMode]="viewMode()"
84915
+ [embedded]="embedded()"
84916
+ [scrollElement]="scrollElement() ?? undefined"
84917
+ />
84918
+ }
84919
+
84920
+ <!-- Search Modal -->
84921
+ <symphiq-search-modal
84922
+ [isOpen]="isSearchOpen()"
84923
+ [isLightMode]="isLightMode()"
84924
+ (close)="closeSearch()"
84925
+ />
84926
+
84927
+ <!-- View Mode Switcher Modal -->
84928
+ <symphiq-view-mode-switcher-modal
84929
+ [isOpen]="isViewModeSwitcherOpen()"
84930
+ [currentMode]="currentDisplayMode()"
84931
+ [viewMode]="viewMode()"
84932
+ (close)="closeViewModeSwitcher()"
84933
+ (modeSelected)="handleDisplayModeChange($event)"
84934
+ />
84935
+
84936
+ <!-- Profile Analysis Modal -->
84937
+ <symphiq-profile-analysis-modal
84938
+ [isLightMode]="isLightMode()"
84939
+ [allMetrics]="allMetrics()"
84940
+ [allInsights]="allInsights()"
84941
+ [allBusinessInsights]="allBusinessInsights()"
84942
+ [allCharts]="allCharts()"
84943
+ >
84944
+ @if (modalType() === 'goal-detail' && getGoalDetailData(); as data) {
84945
+ <symphiq-goal-card
84946
+ [goal]="data.goal"
84947
+ [viewMode]="data.viewMode"
84948
+ [isInModal]="true"
84949
+ [allMetrics]="allMetrics()"
84950
+ [allCharts]="allCharts()"
84951
+ [allInsights]="allInsights()"
84952
+ [currentModalState]="getCurrentModalState()"
84953
+ />
84954
+ }
84955
+ @if (modalType() === 'goal-objectives' && getGoalDetailData(); as data) {
84956
+ <symphiq-goal-objectives-modal-content
84957
+ [goal]="data.goal"
84958
+ [viewMode]="data.viewMode"
84959
+ />
84960
+ }
84961
+ @if (modalType() === 'objective-strategies' && getObjectiveStrategiesData(); as data) {
84962
+ <symphiq-objective-strategies-modal-content
84963
+ [objective]="data.objective"
84964
+ [goalTitle]="data.goalTitle"
84965
+ [viewMode]="data.viewMode"
84966
+ />
84967
+ }
84968
+ @if (modalType() === 'strategy-recommendations' && getStrategyRecommendationsData(); as data) {
84969
+ <symphiq-strategy-recommendations-modal-content
84970
+ [strategy]="data.strategy"
84971
+ [objectiveTitle]="data.objectiveTitle"
84972
+ [goalTitle]="data.goalTitle"
84973
+ [viewMode]="data.viewMode"
84974
+ [allMetrics]="allMetrics()"
84975
+ [allCharts]="allCharts()"
84976
+ [allInsights]="allInsights()"
84977
+ [allBusinessInsights]="allBusinessInsights()"
84978
+ [currentModalState]="getCurrentModalState()"
84979
+ />
84980
+ }
84981
+ @if (modalType() === 'category-detail' && getCategoryDetailData(); as data) {
84982
+ <symphiq-category-detail-modal-content
84983
+ [category]="data.category"
84984
+ [viewMode]="data.viewMode"
84985
+ [scrollToSection]="data.scrollToSection"
84986
+ />
84987
+ }
84988
+ @if (modalType() === 'strength-detail' && getStrengthDetailData(); as data) {
84989
+ <symphiq-strength-detail-modal-content
84990
+ [strength]="data.strength"
84991
+ [viewMode]="data.viewMode"
84992
+ [allFunnelStrengths]="funnelStrengths()"
84993
+ [currentModalState]="getCurrentModalState()"
84994
+ />
84995
+ }
84996
+ @if (modalType() === 'gap-detail' && getGapDetailData(); as data) {
84997
+ <symphiq-gap-detail-modal-content
84998
+ [gap]="data.gap"
84999
+ [viewMode]="data.viewMode"
85000
+ [allGoals]="allGoals()"
85001
+ [allWeaknesses]="funnelWeaknesses()"
85002
+ [currentModalState]="getCurrentModalState()"
85003
+ />
85004
+ }
85005
+ @if (modalType() === 'opportunity-detail' && getOpportunityDetailData(); as data) {
85006
+ <symphiq-opportunity-detail-modal-content
85007
+ [opportunity]="data.opportunity"
85008
+ [viewMode]="data.viewMode"
85009
+ [allStrengths]="funnelStrengths()"
85010
+ [currentModalState]="getCurrentModalState()"
85011
+ />
85012
+ }
85013
+ </symphiq-profile-analysis-modal>
85014
+
85015
+ <!-- Funnel Analysis Modal (for insights and metrics from profile goals) -->
85016
+ <symphiq-funnel-analysis-modal
85017
+ [isLightMode]="isLightMode()"
85018
+ [viewMode]="viewMode()"
85019
+ [allMetrics]="allMetrics()"
85020
+ [allInsights]="allInsights()"
85021
+ [allCharts]="allCharts()"
85022
+ />
85023
+
85024
+ <!-- Business Analysis Modal (for napkin visuals and other content) -->
85025
+ <symphiq-business-analysis-modal [isLightMode]="isLightMode()"/>
85026
+
85027
+ <!-- Tooltip Container -->
85028
+ <symphiq-tooltip-container/>
85029
+ </div>
84968
85030
  `
84969
85031
  }]
84970
85032
  }], () => [], { funnelModalComponent: [{