diff --git a/DeepDrftPublic.Client/Controls/GalleryViewMode.cs b/DeepDrftPublic.Client/Controls/GalleryViewMode.cs
new file mode 100644
index 0000000..b1f1cc2
--- /dev/null
+++ b/DeepDrftPublic.Client/Controls/GalleryViewMode.cs
@@ -0,0 +1,7 @@
+namespace DeepDrftPublic.Client.Controls;
+
+public enum GalleryViewMode
+{
+ Grid,
+ List
+}
diff --git a/DeepDrftPublic.Client/Controls/TrackCard.razor b/DeepDrftPublic.Client/Controls/TrackCard.razor
index 5464481..3d331d3 100644
--- a/DeepDrftPublic.Client/Controls/TrackCard.razor
+++ b/DeepDrftPublic.Client/Controls/TrackCard.razor
@@ -1,9 +1,12 @@
@{
var hasLink = !string.IsNullOrEmpty(TrackModel?.EntryKey);
var trackHref = hasLink ? $"/track/{TrackModel!.EntryKey}" : null;
+ var hasArt = !string.IsNullOrEmpty(TrackModel?.ImagePath);
}
-
+@if (ViewMode == GalleryViewMode.Grid)
+{
+
@* Cover and title/artist link to the detail page; the play button (below, outside any
anchor) stays the sole playback entry point. display:contents keeps the grid intact. *@
@@ -107,3 +110,102 @@
+}
+else
+{
+
+}
diff --git a/DeepDrftPublic.Client/Controls/TrackCard.razor.cs b/DeepDrftPublic.Client/Controls/TrackCard.razor.cs
index e4be2c5..3b2dd76 100644
--- a/DeepDrftPublic.Client/Controls/TrackCard.razor.cs
+++ b/DeepDrftPublic.Client/Controls/TrackCard.razor.cs
@@ -11,6 +11,7 @@ public partial class TrackCard : ComponentBase
[Parameter] public EventCallback OnPause { get; set; }
[Parameter] public bool IsPlaying { get; set; } = false;
[Parameter] public bool IsPaused { get; set; } = false;
+ [Parameter] public GalleryViewMode ViewMode { get; set; } = GalleryViewMode.Grid;
// Pause only when actively playing; every other state (idle, paused) reads as "press to play".
private bool IsActivelyPlaying => IsPlaying && !IsPaused;
diff --git a/DeepDrftPublic.Client/Controls/TrackCard.razor.css b/DeepDrftPublic.Client/Controls/TrackCard.razor.css
index 05845b7..a018ce1 100644
--- a/DeepDrftPublic.Client/Controls/TrackCard.razor.css
+++ b/DeepDrftPublic.Client/Controls/TrackCard.razor.css
@@ -86,3 +86,100 @@
height: 200px;
}
}
+
+/* ── Mode A: hover-reveal overlay (art cards only) ──────────────────────── */
+
+/* Gate the hidden-at-rest rule on (a) art present and (b) a hover-capable pointer.
+ Fallback cards (no --art modifier) and touch devices always show the overlay. */
+@media (hover: hover) and (pointer: fine) {
+ .deepdrft-track-card-container--art .deepdrft-track-card-content {
+ opacity: 0;
+ background: transparent;
+ transition: opacity 180ms ease, background-color 180ms ease;
+ }
+ .deepdrft-track-card-container--art:hover .deepdrft-track-card-content {
+ opacity: 1;
+ background: var(--deepdrft-navy-mid, #162437);
+ transition: opacity 180ms ease, background-color 180ms ease;
+ }
+}
+
+/* ── Mode B: list row ───────────────────────────────────────────────────── */
+
+.deepdrft-track-row {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ gap: 16px;
+ height: 80px;
+ padding: 8px 16px;
+ background: var(--deepdrft-navy-mid, #162437);
+ border: 1px solid rgba(250, 250, 248, 0.12);
+ border-radius: 4px;
+ box-sizing: border-box;
+ width: 100%;
+}
+
+.deepdrft-track-row-link {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ gap: 16px;
+ flex: 1 1 auto;
+ min-width: 0;
+ text-decoration: none;
+ color: inherit;
+}
+
+::deep .deepdrft-track-row-fab {
+ flex: 0 0 auto;
+}
+
+.deepdrft-track-row-thumb {
+ flex: 0 0 64px;
+ width: 64px;
+ height: 64px;
+ background-size: cover;
+ background-position: center;
+ border-radius: 2px;
+}
+
+.deepdrft-track-row-thumb--fallback {
+ background: color-mix(in srgb, var(--deepdrft-navy-mid, #162437) 60%, rgba(250,250,248,0.1));
+ border: 1px solid rgba(250, 250, 248, 0.12);
+}
+
+.deepdrft-track-row-text {
+ flex: 1 1 auto;
+ min-width: 0;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+}
+
+.deepdrft-track-row-meta {
+ flex: 0 0 auto;
+ display: flex;
+ flex-direction: column;
+ align-items: flex-end;
+ justify-content: center;
+ gap: 4px;
+}
+
+@media (max-width: 480px) {
+ .deepdrft-track-row {
+ height: auto;
+ min-height: 72px;
+ padding: 8px 12px;
+ gap: 10px;
+ }
+ .deepdrft-track-row-thumb {
+ flex: 0 0 48px;
+ width: 48px;
+ height: 48px;
+ }
+}
+
+.deepdrft-track-row--playing {
+ border-left: 3px solid var(--deepdrft-green-interactive, #3aa163);
+}
diff --git a/DeepDrftPublic.Client/Controls/TracksGallery.razor b/DeepDrftPublic.Client/Controls/TracksGallery.razor
index 808e76d..db42790 100644
--- a/DeepDrftPublic.Client/Controls/TracksGallery.razor
+++ b/DeepDrftPublic.Client/Controls/TracksGallery.razor
@@ -1,16 +1,36 @@
-
-
- @foreach (var track in Tracks)
- {
-
-
-
-
-
- }
-
-
+@if (ViewMode == GalleryViewMode.Grid)
+{
+
+
+ @foreach (var track in Tracks)
+ {
+
+
+
+
+
+ }
+
+
+}
+else
+{
+
+
+ @foreach (var track in Tracks)
+ {
+
+ }
+
+
+}
diff --git a/DeepDrftPublic.Client/Controls/TracksGallery.razor.cs b/DeepDrftPublic.Client/Controls/TracksGallery.razor.cs
index bc6a8f5..47878c7 100644
--- a/DeepDrftPublic.Client/Controls/TracksGallery.razor.cs
+++ b/DeepDrftPublic.Client/Controls/TracksGallery.razor.cs
@@ -13,6 +13,7 @@ public partial class TracksGallery : ComponentBase
[Parameter] public TrackDto? ActiveTrack { get; set; }
[Parameter] public bool IsPlaying { get; set; }
[Parameter] public bool IsPaused { get; set; }
+ [Parameter] public GalleryViewMode ViewMode { get; set; } = GalleryViewMode.Grid;
[Parameter] public EventCallback OnPlay { get; set; }
[Parameter] public EventCallback OnPause { get; set; }
diff --git a/DeepDrftPublic.Client/Controls/TracksGallery.razor.css b/DeepDrftPublic.Client/Controls/TracksGallery.razor.css
index be316f8..0d0736c 100644
--- a/DeepDrftPublic.Client/Controls/TracksGallery.razor.css
+++ b/DeepDrftPublic.Client/Controls/TracksGallery.razor.css
@@ -6,3 +6,10 @@
display: flex;
justify-content: center;
}
+
+.deepdrft-track-list {
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+ width: 100%;
+}
diff --git a/DeepDrftPublic.Client/Pages/TracksView.razor b/DeepDrftPublic.Client/Pages/TracksView.razor
index 27b4659..83a0e79 100644
--- a/DeepDrftPublic.Client/Pages/TracksView.razor
+++ b/DeepDrftPublic.Client/Pages/TracksView.razor
@@ -7,8 +7,19 @@
@if (ViewModel.Page != null)
{
+
interactive (WASM) seam.
diff --git a/DeepDrftPublic.Client/Pages/TracksView.razor.css b/DeepDrftPublic.Client/Pages/TracksView.razor.css
index 4134c43..8a57c43 100644
--- a/DeepDrftPublic.Client/Pages/TracksView.razor.css
+++ b/DeepDrftPublic.Client/Pages/TracksView.razor.css
@@ -18,3 +18,9 @@
align-items: center;
gap: 16px;
}
+
+.tracks-view-header {
+ display: flex;
+ justify-content: flex-end;
+ padding: 0 0 12px 0;
+}