diff --git a/libs/workspace/dashboard/feature/src/lib/rails/dashboard-rail.component.html b/libs/workspace/dashboard/feature/src/lib/rails/dashboard-rail.component.html
index 60dd77c2f..07878677b 100644
--- a/libs/workspace/dashboard/feature/src/lib/rails/dashboard-rail.component.html
+++ b/libs/workspace/dashboard/feature/src/lib/rails/dashboard-rail.component.html
@@ -49,9 +49,21 @@
>
@if (card.imageUrl && !failedImages()[card.id]) {
+ @if (card.contentType === 'live') {
+
+ }
![]()
;
actions?: DashboardRailAction[];
diff --git a/libs/workspace/dashboard/feature/src/lib/rails/workspace-dashboard-rails.component.html b/libs/workspace/dashboard/feature/src/lib/rails/workspace-dashboard-rails.component.html
index 054be0621..abc1c3a7a 100644
--- a/libs/workspace/dashboard/feature/src/lib/rails/workspace-dashboard-rails.component.html
+++ b/libs/workspace/dashboard/feature/src/lib/rails/workspace-dashboard-rails.component.html
@@ -54,6 +54,7 @@
[class.hero--has-default-backdrop]="
item.backdropSource === 'fallback'
"
+ [class.hero--live]="item.contentType === 'live'"
[routerLink]="item.link"
[state]="item.state ?? {}"
>
diff --git a/libs/workspace/dashboard/feature/src/lib/rails/workspace-dashboard-rails.component.scss b/libs/workspace/dashboard/feature/src/lib/rails/workspace-dashboard-rails.component.scss
index 0e25da815..a7f1f8645 100644
--- a/libs/workspace/dashboard/feature/src/lib/rails/workspace-dashboard-rails.component.scss
+++ b/libs/workspace/dashboard/feature/src/lib/rails/workspace-dashboard-rails.component.scss
@@ -223,6 +223,27 @@
}
}
+// Live channel logos (small square images) get destroyed by the default
+// `object-fit: cover` poster treatment. The `.hero--live` modifier centers
+// the logo with breathing room over a tinted backdrop. The blurred
+// `.hero__backdrop` already provides the ambient color wash for the wider hero.
+.hero--live .hero__poster {
+ background:
+ radial-gradient(
+ circle at 50% 35%,
+ var(--app-selection-surface, rgba(120, 173, 255, 0.18)) 0%,
+ transparent 65%
+ ),
+ var(--app-widget-bg, #1e2330);
+
+ img {
+ box-sizing: border-box;
+ object-fit: contain;
+ padding: 22% 18%;
+ filter: drop-shadow(0 4px 12px rgba(0, 0, 0, 0.45));
+ }
+}
+
.hero__body {
position: relative;
z-index: 2;
diff --git a/libs/workspace/dashboard/feature/src/lib/rails/workspace-dashboard-rails.component.ts b/libs/workspace/dashboard/feature/src/lib/rails/workspace-dashboard-rails.component.ts
index abb12ce69..84e7163a9 100644
--- a/libs/workspace/dashboard/feature/src/lib/rails/workspace-dashboard-rails.component.ts
+++ b/libs/workspace/dashboard/feature/src/lib/rails/workspace-dashboard-rails.component.ts
@@ -52,6 +52,7 @@ const SKELETON_RAILS = [1, 2, 3] as const;
interface DashboardHeroModel {
readonly backdropUrl?: string;
readonly backdropSource: DashboardHeroBackdropSource;
+ readonly contentType?: 'live' | 'movie' | 'series';
readonly fallbackBackdropBackground: string;
readonly fallbackPosterBackground: string;
readonly hasBackdrop: boolean;
@@ -260,6 +261,7 @@ export class WorkspaceDashboardRailsComponent {
return {
...artwork,
+ contentType: item.type,
icon: this.typeIcon(item.type),
link: this.data.getRecentItemLink(item),
state: this.data.getRecentItemNavigationState(item),
@@ -379,6 +381,7 @@ export class WorkspaceDashboardRailsComponent {
subtitle: `${this.data.getRecentItemProviderLabel(item)} · ${this.data.getRecentItemTypeLabel(item)}`,
imageUrl: item.poster_url,
icon: this.typeIcon(item.type),
+ contentType: item.type,
link: this.data.getRecentItemLink(item),
state: this.data.getRecentItemNavigationState(item),
};
@@ -391,6 +394,7 @@ export class WorkspaceDashboardRailsComponent {
subtitle: `${this.data.getFavoriteItemProviderLabel(item)} · ${this.data.getFavoriteItemTypeLabel(item)}`,
imageUrl: item.poster_url,
icon: this.typeIcon(item.type),
+ contentType: item.type,
link: this.data.getGlobalFavoriteLink(item),
state: this.data.getGlobalFavoriteNavigationState(item),
};
@@ -409,6 +413,7 @@ export class WorkspaceDashboardRailsComponent {
subtitle: subtitleParts.join(' · '),
imageUrl: item.poster_url,
icon: this.typeIcon(item.type),
+ contentType: item.type,
link: this.data.getRecentlyAddedLink(item),
state: this.data.getRecentlyAddedNavigationState(item),
};