diff --git a/Chrono/Web/Components/CardDialog.razor b/Chrono/Web/Components/CardDialog.razor new file mode 100644 index 0000000..68154bf --- /dev/null +++ b/Chrono/Web/Components/CardDialog.razor @@ -0,0 +1,267 @@ +@namespace Chrono.Components + +@if (Card != null) +{ + +
+ +
+ @if (HasImage) + { +
+ @Card.Name +
+ } +
+
+

@Card.Name

+
+ @Card.Category + @if (Card.Cost.HasValue) + { + @Card.Cost + } + @if (Card.Attack.HasValue) + { + @Card.Attack + } + @if (Card.Health.HasValue) + { + @Card.Health + } + @if (Card.Speed != null) + { + @Card.Speed + } +
+
+ + @if (Card.Faction != null) + { +
+ Faction + @Card.Faction +
+ } + + @if (Card.Description != null) + { +
+ + @RenderDescription(Card.Description) +
+ } + + @if (Card.Set != null) + { +
+ Set + @Card.Set +
+ } + + @if (Card.Archetypes is { Count: > 0 }) + { +
+ Archetypes + @string.Join(", ", Card.Archetypes) +
+ } + + @if (Card.ImmortalizeWhen != null) + { +
+ Immortalize When + @Card.ImmortalizeWhen +
+ } + + @if (Card.HasImmortalize) + { +
+ Immortalizes To + + @foreach (var name in Card.ImmortalizeTo!) + { + var targetName = name; + var target = LookupCard(targetName); + if (target != null) + { + + } + else + { + @targetName + } + } + +
+ } + + @if (Card.ImmortalizeFrom != null) + { +
+ Immortalizes From + + @{ + var fromCard = LookupCard(Card.ImmortalizeFrom); + if (fromCard != null) + { + + } + else + { + @Card.ImmortalizeFrom + } + } + +
+ } + + @if (ShowNotes && Card.IsAgent) + { +
+ Personal Note + + @if (isSaving) + { + Saving... + } +
+ } +
+
+
+} + +@code { + [Parameter] public CardData? Card { get; set; } + [Parameter] public EventCallback OnClose { get; set; } + [Parameter] public EventCallback OnNavigate { get; set; } + [Parameter] public bool ShowNotes { get; set; } + + [Inject] private HttpClient Http { get; set; } = default!; + + private bool HasImage => Card?.ImageFile is { Length: > 0 } && Card.ImageFile != "placeholder.png"; + + private string currentNote = ""; + private bool isSaving; + + protected override void OnParametersSet() + { + if (Card != null && Card.IsAgent) + { + currentNote = ""; + _ = LoadNote(); + } + } + + private async Task LoadNote() + { + if (Card == null || !Card.IsAgent) return; + try + { + var note = await Http.GetFromJsonAsync($"api/notes/{Uri.EscapeDataString(Card.Name)}"); + currentNote = note?.Note ?? ""; + } + catch + { + currentNote = ""; + } + } + + private async Task SaveNote() + { + if (Card == null || !Card.IsAgent) return; + + isSaving = true; + try + { + await Http.PostAsJsonAsync("api/notes", new CardNote { CardName = Card.Name, Note = currentNote }); + } + catch { } + finally + { + isSaving = false; + } + } + + private void HandleClose() + { + _ = OnClose.InvokeAsync(); + } + + private void HandleBackdropClick() + { + _ = OnClose.InvokeAsync(); + } + + private void Navigate(CardData card) + { + _ = OnNavigate.InvokeAsync(card); + } + + private static CardData? LookupCard(string cardName) + { + return CardDatabase.Cards.FirstOrDefault(c => + string.Equals(c.Name, cardName, StringComparison.OrdinalIgnoreCase)); + } + + private RenderFragment RenderDescription(string description) => builder => + { + var cardNames = CardDatabase.Cards + .Select(c => c.Name) + .Where(n => !string.IsNullOrWhiteSpace(n)) + .OrderByDescending(n => n.Length) + .ToList(); + + int seq = 0; + var remaining = description; + + while (!string.IsNullOrEmpty(remaining)) + { + int bestIdx = -1; + string? bestName = null; + + foreach (var name in cardNames) + { + int idx = remaining.IndexOf(name, StringComparison.OrdinalIgnoreCase); + if (idx != -1 && (bestIdx == -1 || idx < bestIdx)) + { + bestIdx = idx; + bestName = name; + } + } + + if (bestIdx != -1 && bestName != null) + { + if (bestIdx > 0) + builder.AddContent(seq++, remaining[..bestIdx]); + + var card = LookupCard(bestName); + if (card != null) + { + builder.OpenElement(seq++, "button"); + builder.AddAttribute(seq++, "class", "inline-card-btn"); + builder.AddAttribute(seq++, "onclick", + EventCallback.Factory.Create(this, () => Navigate(card))); + builder.AddContent(seq++, bestName); + builder.CloseElement(); + } + else + { + builder.AddContent(seq++, bestName); + } + + remaining = remaining[(bestIdx + bestName.Length)..]; + } + else + { + builder.AddContent(seq++, remaining); + remaining = ""; + } + } + }; +} diff --git a/Chrono/Web/Components/CardDialog.razor.css b/Chrono/Web/Components/CardDialog.razor.css new file mode 100644 index 0000000..3bacb6a --- /dev/null +++ b/Chrono/Web/Components/CardDialog.razor.css @@ -0,0 +1,254 @@ +.modal-backdrop { + position: fixed; + inset: 0; + z-index: 1040; + background: rgba(0, 0, 0, 0.7); + backdrop-filter: blur(4px); + animation: fade-in 0.2s ease-out; +} + +@keyframes fade-in { + from { opacity: 0; } + to { opacity: 1; } +} + +.card-detail { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + z-index: 1050; + background: var(--bg-surface); + border: 1px solid var(--border); + border-radius: 16px; + padding: 0; + max-width: 720px; + width: 92vw; + max-height: 88vh; + overflow-y: auto; + box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6); + color: var(--text-primary); + animation: detail-enter 0.25s ease-out; +} + +@keyframes detail-enter { + from { + opacity: 0; + transform: translate(-50%, -50%) scale(0.92); + } + to { + opacity: 1; + transform: translate(-50%, -50%) scale(1); + } +} + +.detail-close { + position: absolute; + top: 0.75rem; + right: 0.75rem; + z-index: 1; + background: rgba(0, 0, 0, 0.5); + border: 1px solid rgba(255, 255, 255, 0.1); + color: var(--text-primary); + width: 2rem; + height: 2rem; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + font-size: 0.8rem; + transition: all var(--transition); +} + +.detail-close:hover { + background: rgba(255, 255, 255, 0.15); +} + +.detail-layout { + display: flex; + gap: 1.5rem; + padding: 1.5rem; +} + +.detail-image { + flex: 0 0 260px; +} + +.detail-image img { + width: 100%; + border-radius: var(--radius); + box-shadow: var(--shadow); +} + +/* ── No-image layout ── */ +.card-detail-noimg { + max-width: 460px; +} + +.layout-noimg { + justify-content: center; +} + +.detail-info { + flex: 1; + min-width: 0; +} + +.detail-header { + margin-bottom: 1rem; +} + +.detail-header h2 { + margin: 0 0 0.75rem; + font-size: 1.4rem; + line-height: 1.3; +} + +.detail-meta { + display: flex; + flex-wrap: wrap; + gap: 0.4rem; +} + +.meta-badge { + display: inline-flex; + align-items: center; + gap: 0.3rem; + font-size: 0.75rem; + font-weight: 600; + padding: 0.25rem 0.6rem; + border-radius: 100px; + background: var(--bg-hover); + color: var(--text-secondary); + border: 1px solid var(--border); +} + +.meta-badge.category.agent, +.meta-badge.category.immortalized { + background: rgba(79, 195, 247, 0.15); + color: #4fc3f7; + border-color: rgba(79, 195, 247, 0.3); +} + +.meta-badge.category.spell { + background: rgba(206, 147, 216, 0.15); + color: #ce93d8; + border-color: rgba(206, 147, 216, 0.3); +} + +.meta-badge.cost { + background: rgba(255, 215, 0, 0.12); + color: var(--gold); + border-color: rgba(255, 215, 0, 0.3); +} + +.meta-badge.attack { + background: rgba(239, 83, 80, 0.15); + color: #ef5350; + border-color: rgba(239, 83, 80, 0.3); +} + +.meta-badge.health { + background: rgba(102, 187, 106, 0.15); + color: #66bb6a; + border-color: rgba(102, 187, 106, 0.3); +} + +.meta-badge.speed { + background: rgba(79, 195, 247, 0.12); + color: #4fc3f7; + border-color: rgba(79, 195, 247, 0.3); +} + +.detail-field { + display: flex; + gap: 0.5rem; + margin-bottom: 0.6rem; + font-size: 0.88rem; + line-height: 1.45; +} + +.detail-field.description { + background: var(--bg-elevated); + padding: 0.6rem 0.75rem; + border-radius: var(--radius-sm); + border-left: 3px solid var(--accent); + margin-top: 0.25rem; +} + +.field-label { + flex-shrink: 0; + color: var(--text-muted); + font-size: 0.8rem; + font-weight: 500; + min-width: 7.5rem; + display: flex; + align-items: flex-start; + gap: 0.3rem; +} + +.detail-field.description .field-label { + min-width: auto; + color: var(--accent); +} + +.field-value { + color: var(--text-secondary); +} + +.detail-field.description .field-value { + color: var(--text-primary); + font-style: italic; +} + +.card-detail::-webkit-scrollbar { + width: 4px; +} + +.card-detail::-webkit-scrollbar-thumb { + background: var(--border); + border-radius: 2px; +} + +.inline-card-btn { + background: none; + border: none; + padding: 0; + font-family: inherit; + font-size: inherit; + font-weight: 600; + color: var(--accent); + cursor: pointer; + text-decoration: underline; + text-underline-offset: 2px; + text-decoration-color: rgba(108, 99, 255, 0.3); + transition: color var(--transition), text-decoration-color var(--transition); +} + +.inline-card-btn:hover { + color: #7b73ff; + text-decoration-color: #7b73ff; +} + +@@media (max-width: 768px) { + .detail-layout { + flex-direction: column; + padding: 1rem; + } + + .detail-image { + flex: 0 0 auto; + max-width: 180px; + margin: 0 auto; + } + + .card-detail, + .card-detail-noimg { + max-height: 90vh; + } + + .card-detail-noimg { + max-width: 92vw; + } +} diff --git a/Chrono/Web/Pages/Cards.razor b/Chrono/Web/Pages/Cards.razor index 632ebe2..e9428ce 100644 --- a/Chrono/Web/Pages/Cards.razor +++ b/Chrono/Web/Pages/Cards.razor @@ -163,105 +163,11 @@ } +} + @if (selectedCard != null) { - -
- -
-
- @selectedCard.Name -
-
-
-

@selectedCard.Name

-
- @selectedCard.Category - @if (selectedCard.Cost.HasValue) - { - @selectedCard.Cost - } - @if (selectedCard.Attack.HasValue) - { - @selectedCard.Attack - } - @if (selectedCard.Health.HasValue) - { - @selectedCard.Health - } - @if (selectedCard.Speed != null) - { - @selectedCard.Speed - } -
-
- - @if (selectedCard.Faction != null) - { -
- Faction - @selectedCard.Faction -
- } - @if (selectedCard.Description != null) - { -
- - @selectedCard.Description -
- } - @if (selectedCard.Set != null) - { -
- Set - @selectedCard.Set -
- } - @if (selectedCard.Archetypes is { Count: > 0 }) - { -
- Archetypes - @string.Join(", ", selectedCard.Archetypes) -
- } - @if (selectedCard.ImmortalizeWhen != null) - { -
- Immortalize When - @selectedCard.ImmortalizeWhen -
- } - @if (selectedCard.HasImmortalize) - { -
- Immortalizes To - @string.Join(", ", selectedCard.ImmortalizeTo!) -
- } - @if (selectedCard.ImmortalizeFrom != null) - { -
- Immortalizes From - @selectedCard.ImmortalizeFrom -
- } - - @if (selectedCard.IsAgent && false) // Server-only feature. Redesign project structure - { -
- Personal Note - - @if (isSaving) - { - Saving... - } -
- } -
-
-
+ } @code { @@ -270,7 +176,6 @@ private string search = ""; private string categoryFilter = ""; private string immortalFilter = ""; - private bool agentOnly = true; private bool agentLink = true; private string factionFilter = ""; private string costFilter = ""; @@ -279,8 +184,6 @@ private bool showDetailedView; private CardData? selectedCard; private List factions = []; - private string currentNote = ""; - private bool isSaving; private bool HasActiveFilters => categoryFilter != "" || factionFilter != "" || costFilter != "" || immortalFilter != ""; @@ -354,41 +257,9 @@ search = ""; } - private async Task SelectCard(CardData card) + private void SelectCard(CardData card) { selectedCard = card; - if (card.IsAgent) - { - currentNote = ""; - try - { - var note = await Http.GetFromJsonAsync($"api/notes/{Uri.EscapeDataString(card.Name)}"); - currentNote = note?.Note ?? ""; - } - catch - { - currentNote = ""; - } - } - } - - private async Task SaveNote() - { - if (selectedCard == null || !selectedCard.IsAgent) return; - - isSaving = true; - try - { - await Http.PostAsJsonAsync("api/notes", new CardNote { CardName = selectedCard.Name, Note = currentNote }); - } - catch - { - // Error handling - } - finally - { - isSaving = false; - } } private void CloseDetail() diff --git a/Chrono/Web/Pages/Cards.razor.css b/Chrono/Web/Pages/Cards.razor.css index 4359dbe..f4b422c 100644 --- a/Chrono/Web/Pages/Cards.razor.css +++ b/Chrono/Web/Pages/Cards.razor.css @@ -492,225 +492,6 @@ margin-bottom: 1rem; } -/* ── Detail Modal ── */ -.modal-backdrop { - position: fixed; - inset: 0; - z-index: 1040; - background: rgba(0, 0, 0, 0.7); - backdrop-filter: blur(4px); - animation: fade-in 0.2s ease-out; -} - -@keyframes fade-in { - from { - opacity: 0; - } - to { - opacity: 1; - } -} - -.card-detail { - position: fixed; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - z-index: 1050; - background: var(--bg-surface); - border: 1px solid var(--border); - border-radius: 16px; - padding: 0; - max-width: 720px; - width: 92vw; - max-height: 88vh; - overflow-y: auto; - box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6); - color: var(--text-primary); - animation: detail-enter 0.25s ease-out; -} - -@keyframes detail-enter { - from { - opacity: 0; - transform: translate(-50%, -50%) scale(0.92); - } - to { - opacity: 1; - transform: translate(-50%, -50%) scale(1); - } -} - -.detail-close { - position: absolute; - top: 0.75rem; - right: 0.75rem; - z-index: 1; - background: rgba(0, 0, 0, 0.5); - border: 1px solid rgba(255, 255, 255, 0.1); - color: var(--text-primary); - width: 2rem; - height: 2rem; - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - cursor: pointer; - font-size: 0.8rem; - transition: all var(--transition); -} - -.detail-close:hover { - background: rgba(255, 255, 255, 0.15); -} - -.detail-layout { - display: flex; - gap: 1.5rem; - padding: 1.5rem; -} - -.detail-image { - flex: 0 0 260px; -} - -.detail-image img { - width: 100%; - border-radius: var(--radius); - box-shadow: var(--shadow); -} - -.detail-info { - flex: 1; - min-width: 0; -} - -.detail-header { - margin-bottom: 1rem; -} - -.detail-header h2 { - margin: 0 0 0.75rem; - font-size: 1.4rem; - line-height: 1.3; -} - -.detail-meta { - display: flex; - flex-wrap: wrap; - gap: 0.4rem; -} - -.meta-badge { - display: inline-flex; - align-items: center; - gap: 0.3rem; - font-size: 0.75rem; - font-weight: 600; - padding: 0.25rem 0.6rem; - border-radius: 100px; - background: var(--bg-hover); - color: var(--text-secondary); - border: 1px solid var(--border); -} - -.meta-badge.category { -} - -.meta-badge.category.agent { - background: rgba(79, 195, 247, 0.15); - color: #4fc3f7; - border-color: rgba(79, 195, 247, 0.3); -} - -.meta-badge.category.spell { - background: rgba(206, 147, 216, 0.15); - color: #ce93d8; - border-color: rgba(206, 147, 216, 0.3); -} - -.meta-badge.category.token { - background: rgba(255, 213, 79, 0.15); - color: #ffd54f; - border-color: rgba(255, 213, 79, 0.3); -} - -.meta-badge.cost { - background: rgba(255, 215, 0, 0.12); - color: var(--gold); - border-color: rgba(255, 215, 0, 0.3); -} - -.meta-badge.attack { - background: rgba(239, 83, 80, 0.15); - color: #ef5350; - border-color: rgba(239, 83, 80, 0.3); -} - -.meta-badge.health { - background: rgba(102, 187, 106, 0.15); - color: #66bb6a; - border-color: rgba(102, 187, 106, 0.3); -} - -.meta-badge.speed { - background: rgba(79, 195, 247, 0.12); - color: #4fc3f7; - border-color: rgba(79, 195, 247, 0.3); -} - -/* ── Detail Fields ── */ -.detail-field { - display: flex; - gap: 0.5rem; - margin-bottom: 0.6rem; - font-size: 0.88rem; - line-height: 1.45; -} - -.detail-field.description { - background: var(--bg-elevated); - padding: 0.6rem 0.75rem; - border-radius: var(--radius-sm); - border-left: 3px solid var(--accent); - margin-top: 0.25rem; -} - -.field-label { - flex-shrink: 0; - color: var(--text-muted); - font-size: 0.8rem; - font-weight: 500; - min-width: 7.5rem; - display: flex; - align-items: flex-start; - gap: 0.3rem; -} - -.detail-field.description .field-label { - min-width: auto; - color: var(--accent); -} - -.field-value { - color: var(--text-secondary); -} - -.detail-field.description .field-value { - color: var(--text-primary); - font-style: italic; -} - -/* ── Scrollbar for modal ── */ -.card-detail::-webkit-scrollbar { - width: 4px; -} - -.card-detail::-webkit-scrollbar-thumb { - background: var(--border); - border-radius: 2px; -} - /* ── Responsive ── */ @media (max-width: 768px) { .gallery-container { @@ -739,21 +520,6 @@ max-width: 500px; } - .detail-layout { - flex-direction: column; - padding: 1rem; - } - - .detail-image { - flex: 0 0 auto; - max-width: 180px; - margin: 0 auto; - } - - .card-detail { - max-height: 90vh; - } - .tab { padding: 0.4rem 0.8rem; font-size: 0.8rem; diff --git a/Chrono/Web/Pages/DeckDetail.razor b/Chrono/Web/Pages/DeckDetail.razor index c0f86dd..1a152a6 100644 --- a/Chrono/Web/Pages/DeckDetail.razor +++ b/Chrono/Web/Pages/DeckDetail.razor @@ -122,90 +122,7 @@ @if (selectedCard != null) { - -
- -
-
- @selectedCard.Name -
-
-
-

@selectedCard.Name

-
- @selectedCard.Category - @if (selectedCard.Cost.HasValue) - { - @selectedCard.Cost - } - @if (selectedCard.Attack.HasValue) - { - @selectedCard.Attack - } - @if (selectedCard.Health.HasValue) - { - @selectedCard.Health - } - @if (selectedCard.Speed != null) - { - @selectedCard.Speed - } -
-
- - @if (selectedCard.Faction != null) - { -
- Faction - @selectedCard.Faction -
- } - @if (selectedCard.Description != null) - { -
- - @selectedCard.Description -
- } - @if (selectedCard.Set != null) - { -
- Set - @selectedCard.Set -
- } - @if (selectedCard.Archetypes is { Count: > 0 }) - { -
- Archetypes - @string.Join(", ", selectedCard.Archetypes) -
- } - @if (selectedCard.ImmortalizeWhen != null) - { -
- Immortalize When - @selectedCard.ImmortalizeWhen -
- } - @if (selectedCard.HasImmortalize) - { -
- Immortalizes To - @string.Join(", ", selectedCard.ImmortalizeTo!) -
- } - @if (selectedCard.ImmortalizeFrom != null) - { -
- Immortalizes From - @selectedCard.ImmortalizeFrom -
- } -
-
-
+ } @code { diff --git a/Chrono/Web/Pages/DeckDetail.razor.css b/Chrono/Web/Pages/DeckDetail.razor.css index 385359c..514c94f 100644 --- a/Chrono/Web/Pages/DeckDetail.razor.css +++ b/Chrono/Web/Pages/DeckDetail.razor.css @@ -200,233 +200,4 @@ margin-bottom: 1rem; } -/* ── Detail Modal (shared with Cards page) ── */ -.modal-backdrop { - position: fixed; - inset: 0; - z-index: 1040; - background: rgba(0, 0, 0, 0.7); - backdrop-filter: blur(4px); - animation: fade-in 0.2s ease-out; -} -@keyframes fade-in { - from { - opacity: 0; - } - to { - opacity: 1; - } -} - -.card-detail { - position: fixed; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - z-index: 1050; - background: var(--bg-surface); - border: 1px solid var(--border); - border-radius: 16px; - padding: 0; - max-width: 720px; - width: 92vw; - max-height: 88vh; - overflow-y: auto; - box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6); - color: var(--text-primary); - animation: detail-enter 0.25s ease-out; -} - -@keyframes detail-enter { - from { - opacity: 0; - transform: translate(-50%, -50%) scale(0.92); - } - to { - opacity: 1; - transform: translate(-50%, -50%) scale(1); - } -} - -.detail-close { - position: absolute; - top: 0.75rem; - right: 0.75rem; - z-index: 1; - background: rgba(0, 0, 0, 0.5); - border: 1px solid rgba(255, 255, 255, 0.1); - color: var(--text-primary); - width: 2rem; - height: 2rem; - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - cursor: pointer; - font-size: 0.8rem; - transition: all var(--transition); -} - -.detail-close:hover { - background: rgba(255, 255, 255, 0.15); -} - -.detail-layout { - display: flex; - gap: 1.5rem; - padding: 1.5rem; -} - -.detail-image { - flex: 0 0 260px; -} - -.detail-image img { - width: 100%; - border-radius: var(--radius); - box-shadow: var(--shadow); -} - -.detail-info { - flex: 1; - min-width: 0; -} - -.detail-header { - margin-bottom: 1rem; -} - -.detail-header h2 { - margin: 0 0 0.75rem; - font-size: 1.4rem; - line-height: 1.3; -} - -.detail-meta { - display: flex; - flex-wrap: wrap; - gap: 0.4rem; -} - -.meta-badge { - display: inline-flex; - align-items: center; - gap: 0.3rem; - font-size: 0.75rem; - font-weight: 600; - padding: 0.25rem 0.6rem; - border-radius: 100px; - background: var(--bg-hover); - color: var(--text-secondary); - border: 1px solid var(--border); -} - -.meta-badge.category.agent { - background: rgba(79, 195, 247, 0.15); - color: #4fc3f7; - border-color: rgba(79, 195, 247, 0.3); -} - -.meta-badge.category.spell { - background: rgba(206, 147, 216, 0.15); - color: #ce93d8; - border-color: rgba(206, 147, 216, 0.3); -} - -.meta-badge.category.token { - background: rgba(255, 213, 79, 0.15); - color: #ffd54f; - border-color: rgba(255, 213, 79, 0.3); -} - -.meta-badge.cost { - background: rgba(255, 215, 0, 0.12); - color: var(--gold); - border-color: rgba(255, 215, 0, 0.3); -} - -.meta-badge.attack { - background: rgba(239, 83, 80, 0.15); - color: #ef5350; - border-color: rgba(239, 83, 80, 0.3); -} - -.meta-badge.health { - background: rgba(102, 187, 106, 0.15); - color: #66bb6a; - border-color: rgba(102, 187, 106, 0.3); -} - -.meta-badge.speed { - background: rgba(79, 195, 247, 0.12); - color: #4fc3f7; - border-color: rgba(79, 195, 247, 0.3); -} - -.detail-field { - display: flex; - gap: 0.5rem; - margin-bottom: 0.6rem; - font-size: 0.88rem; - line-height: 1.45; -} - -.detail-field.description { - background: var(--bg-elevated); - padding: 0.6rem 0.75rem; - border-radius: var(--radius-sm); - border-left: 3px solid var(--accent); - margin-top: 0.25rem; -} - -.field-label { - flex-shrink: 0; - color: var(--text-muted); - font-size: 0.8rem; - font-weight: 500; - min-width: 7.5rem; - display: flex; - align-items: flex-start; - gap: 0.3rem; -} - -.detail-field.description .field-label { - min-width: auto; - color: var(--accent); -} - -.field-value { - color: var(--text-secondary); -} - -.detail-field.description .field-value { - color: var(--text-primary); - font-style: italic; -} - -.card-detail::-webkit-scrollbar { - width: 4px; -} - -.card-detail::-webkit-scrollbar-thumb { - background: var(--border); - border-radius: 2px; -} - -@media (max-width: 768px) { - .detail-layout { - flex-direction: column; - padding: 1rem; - } - - .detail-image { - flex: 0 0 auto; - max-width: 180px; - margin: 0 auto; - } - - .card-detail { - max-height: 90vh; - } -} diff --git a/Chrono/Web/_Imports.razor b/Chrono/Web/_Imports.razor index 6b0f21d..29df494 100644 --- a/Chrono/Web/_Imports.razor +++ b/Chrono/Web/_Imports.razor @@ -9,6 +9,7 @@ @using Microsoft.JSInterop @using Web @using Web.Layout +@using Chrono.Components @using Telerik.Blazor @using Telerik.Blazor.Components @using Telerik.DataSource \ No newline at end of file