Implement Memory Game with Blazor WebAssembly

Co-authored-by: clayschaad <11883505+clayschaad@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2025-11-14 09:42:44 +00:00
parent 2f6910e5d5
commit d60f4a9c37
89 changed files with 60859 additions and 0 deletions

6
MemoryGame/App.razor Normal file
View file

@ -0,0 +1,6 @@
<Router AppAssembly="@typeof(App).Assembly" NotFoundPage="typeof(Pages.NotFound)">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"/>
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
</Found>
</Router>

View file

@ -0,0 +1,9 @@
@inherits LayoutComponentBase
<div class="page">
<main>
<article class="content">
@Body
</article>
</main>
</div>

View file

@ -0,0 +1,16 @@
.page {
position: relative;
display: flex;
flex-direction: column;
min-height: 100vh;
}
main {
flex: 1;
}
.content {
padding: 0;
height: 100%;
}

View file

@ -0,0 +1,39 @@
<div class="top-row ps-3 navbar navbar-dark">
<div class="container-fluid">
<a class="navbar-brand" href="">MemoryGame</a>
<button title="Navigation menu" class="navbar-toggler" @onclick="ToggleNavMenu">
<span class="navbar-toggler-icon"></span>
</button>
</div>
</div>
<div class="@NavMenuCssClass nav-scrollable" @onclick="ToggleNavMenu">
<nav class="nav flex-column">
<div class="nav-item px-3">
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
<span class="bi bi-house-door-fill-nav-menu" aria-hidden="true"></span> Home
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="counter">
<span class="bi bi-plus-square-fill-nav-menu" aria-hidden="true"></span> Counter
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="weather">
<span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Weather
</NavLink>
</div>
</nav>
</div>
@code {
private bool collapseNavMenu = true;
private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null;
private void ToggleNavMenu()
{
collapseNavMenu = !collapseNavMenu;
}
}

View file

@ -0,0 +1,83 @@
.navbar-toggler {
background-color: rgba(255, 255, 255, 0.1);
}
.top-row {
min-height: 3.5rem;
background-color: rgba(0,0,0,0.4);
}
.navbar-brand {
font-size: 1.1rem;
}
.bi {
display: inline-block;
position: relative;
width: 1.25rem;
height: 1.25rem;
margin-right: 0.75rem;
top: -1px;
background-size: cover;
}
.bi-house-door-fill-nav-menu {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-house-door-fill' viewBox='0 0 16 16'%3E%3Cpath d='M6.5 14.5v-3.505c0-.245.25-.495.5-.495h2c.25 0 .5.25.5.5v3.5a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5v-7a.5.5 0 0 0-.146-.354L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293L8.354 1.146a.5.5 0 0 0-.708 0l-6 6A.5.5 0 0 0 1.5 7.5v7a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5Z'/%3E%3C/svg%3E");
}
.bi-plus-square-fill-nav-menu {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-plus-square-fill' viewBox='0 0 16 16'%3E%3Cpath d='M2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2zm6.5 4.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3a.5.5 0 0 1 1 0z'/%3E%3C/svg%3E");
}
.bi-list-nested-nav-menu {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-list-nested' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M4.5 11.5A.5.5 0 0 1 5 11h10a.5.5 0 0 1 0 1H5a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 3 7h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 1 3h10a.5.5 0 0 1 0 1H1a.5.5 0 0 1-.5-.5z'/%3E%3C/svg%3E");
}
.nav-item {
font-size: 0.9rem;
padding-bottom: 0.5rem;
}
.nav-item:first-of-type {
padding-top: 1rem;
}
.nav-item:last-of-type {
padding-bottom: 1rem;
}
.nav-item ::deep a {
color: #d7d7d7;
border-radius: 4px;
height: 3rem;
display: flex;
align-items: center;
line-height: 3rem;
}
.nav-item ::deep a.active {
background-color: rgba(255,255,255,0.37);
color: white;
}
.nav-item ::deep a:hover {
background-color: rgba(255,255,255,0.1);
color: white;
}
@media (min-width: 641px) {
.navbar-toggler {
display: none;
}
.collapse {
/* Never collapse the sidebar for wide screens */
display: block;
}
.nav-scrollable {
/* Allow sidebar to scroll for tall menus */
height: calc(100vh - 3.5rem);
overflow-y: auto;
}
}

View file

@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<OverrideHtmlAssetPlaceholders>true</OverrideHtmlAssetPlaceholders>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="10.0.0" PrivateAssets="all" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,14 @@
namespace MemoryGame.Models;
public sealed class GameSession
{
public required List<Round> Rounds { get; init; }
public int CurrentRoundIndex { get; set; }
public DateTimeOffset StartTime { get; init; }
public DateTimeOffset? EndTime { get; set; }
public Round? CurrentRound => CurrentRoundIndex < Rounds.Count ? Rounds[CurrentRoundIndex] : null;
public bool IsComplete => CurrentRoundIndex >= Rounds.Count;
public int CorrectAnswers => Rounds.Count(r => r.SelectedAnswer != null && r.IsCorrect);
public int IncorrectAnswers => Rounds.Count(r => r.SelectedAnswer != null && !r.IsCorrect);
}

View file

@ -0,0 +1,6 @@
namespace MemoryGame.Models;
public sealed class GameStatistics
{
public required List<GameWord> Words { get; init; }
}

View file

@ -0,0 +1,23 @@
namespace MemoryGame.Models;
public sealed class GameWord
{
public required string Word { get; init; }
public required string ImagePath { get; init; }
public int CorrectCount { get; set; }
public int IncorrectCount { get; set; }
public double Priority
{
get
{
if (CorrectCount == 0 && IncorrectCount == 0)
return 1.0;
var totalAttempts = CorrectCount + IncorrectCount;
var incorrectRatio = (double)IncorrectCount / totalAttempts;
return incorrectRatio * 2 + 0.5;
}
}
}

View file

@ -0,0 +1,10 @@
namespace MemoryGame.Models;
public sealed class Round
{
public required RoundType Type { get; init; }
public required GameWord CorrectAnswer { get; init; }
public required List<GameWord> Options { get; init; }
public GameWord? SelectedAnswer { get; set; }
public bool IsCorrect => SelectedAnswer?.Word == CorrectAnswer.Word;
}

View file

@ -0,0 +1,7 @@
namespace MemoryGame.Models;
public enum RoundType
{
ImageWithWords,
WordWithImages
}

View file

@ -0,0 +1,18 @@
@page "/counter"
<PageTitle>Counter</PageTitle>
<h1>Counter</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
}

148
MemoryGame/Pages/Home.razor Normal file
View file

@ -0,0 +1,148 @@
@page "/"
@using MemoryGame.Models
@using MemoryGame.Services
@inject GameService GameService
@inject NavigationManager Navigation
<PageTitle>Memory Game</PageTitle>
<div class="memory-game-container">
@if (!_initialized)
{
<div class="loading">
<h2>Loading...</h2>
</div>
}
else if (_currentSession == null)
{
<div class="start-screen">
<h1>Memory Game</h1>
<p class="subtitle">Practice matching images with words</p>
<button class="btn-start" @onclick="StartNewGame">Start New Game</button>
</div>
}
else if (_currentSession.IsComplete)
{
<div class="results-screen">
<h1>Game Complete!</h1>
<div class="results">
<div class="result-item correct">
<span class="result-label">Correct:</span>
<span class="result-value">@_currentSession.CorrectAnswers</span>
</div>
<div class="result-item incorrect">
<span class="result-label">Incorrect:</span>
<span class="result-value">@_currentSession.IncorrectAnswers</span>
</div>
</div>
<button class="btn-start" @onclick="StartNewGame">Play Again</button>
</div>
}
else
{
var round = _currentSession.CurrentRound;
if (round != null)
{
<div class="game-screen">
<div class="game-header">
<div class="round-counter">
Round @(_currentSession.CurrentRoundIndex + 1) of @_currentSession.Rounds.Count
</div>
</div>
@if (round.Type == RoundType.ImageWithWords)
{
<div class="question-area">
<img src="@round.CorrectAnswer.ImagePath" alt="Question image" class="question-image" />
</div>
<div class="options-area">
@foreach (var option in round.Options)
{
<button class="option-button word-option" @onclick="() => SelectAnswer(option)">
@option.Word
</button>
}
</div>
}
else
{
<div class="question-area">
<div class="question-word">@round.CorrectAnswer.Word</div>
</div>
<div class="options-area image-options">
@foreach (var option in round.Options)
{
<button class="option-button image-option" @onclick="() => SelectAnswer(option)">
<img src="@option.ImagePath" alt="@option.Word" />
</button>
}
</div>
}
@if (_showFeedback && round.SelectedAnswer != null)
{
<div class="feedback @(_feedbackClass)">
@_feedbackMessage
</div>
}
</div>
}
}
</div>
@code {
private bool _initialized;
private GameSession? _currentSession;
private bool _showFeedback;
private string _feedbackMessage = "";
private string _feedbackClass = "";
protected override async Task OnInitializedAsync()
{
await GameService.InitializeAsync();
_initialized = true;
}
private void StartNewGame()
{
_currentSession = GameService.CreateNewGame();
_showFeedback = false;
}
private async Task SelectAnswer(GameWord selectedWord)
{
if (_currentSession?.CurrentRound == null || _showFeedback)
return;
var round = _currentSession.CurrentRound;
round.SelectedAnswer = selectedWord;
_showFeedback = true;
if (round.IsCorrect)
{
_feedbackMessage = "Correct! ✓";
_feedbackClass = "correct";
}
else
{
_feedbackMessage = $"Incorrect. The correct answer is: {round.CorrectAnswer.Word}";
_feedbackClass = "incorrect";
}
await GameService.UpdateStatisticsAsync(round);
StateHasChanged();
await Task.Delay(2000);
_showFeedback = false;
_currentSession.CurrentRoundIndex++;
if (_currentSession.IsComplete)
{
_currentSession.EndTime = DateTimeOffset.UtcNow;
}
StateHasChanged();
}
}

View file

@ -0,0 +1,5 @@
@page "/not-found"
@layout MainLayout
<h3>Not Found</h3>
<p>Sorry, the content you are looking for does not exist.</p>

View file

@ -0,0 +1,57 @@
@page "/weather"
@inject HttpClient Http
<PageTitle>Weather</PageTitle>
<h1>Weather</h1>
<p>This component demonstrates fetching data from the server.</p>
@if (forecasts == null)
{
<p><em>Loading...</em></p>
}
else
{
<table class="table">
<thead>
<tr>
<th>Date</th>
<th aria-label="Temperature in Celsius">Temp. (C)</th>
<th aria-label="Temperature in Fahrenheit">Temp. (F)</th>
<th>Summary</th>
</tr>
</thead>
<tbody>
@foreach (var forecast in forecasts)
{
<tr>
<td>@forecast.Date.ToShortDateString()</td>
<td>@forecast.TemperatureC</td>
<td>@forecast.TemperatureF</td>
<td>@forecast.Summary</td>
</tr>
}
</tbody>
</table>
}
@code {
private WeatherForecast[]? forecasts;
protected override async Task OnInitializedAsync()
{
forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("sample-data/weather.json");
}
public class WeatherForecast
{
public DateOnly Date { get; set; }
public int TemperatureC { get; set; }
public string? Summary { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}
}

14
MemoryGame/Program.cs Normal file
View file

@ -0,0 +1,14 @@
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using MemoryGame;
using MemoryGame.Services;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
builder.Services.AddScoped<LocalStorageService>();
builder.Services.AddScoped<GameService>();
await builder.Build().RunAsync();

View file

@ -0,0 +1,15 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
"applicationUrl": "http://localhost:5255",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View file

@ -0,0 +1,145 @@
using MemoryGame.Models;
namespace MemoryGame.Services;
public sealed class GameService
{
private readonly LocalStorageService _localStorage;
private readonly Random _random = new();
private GameStatistics? _statistics;
private readonly List<GameWord> _defaultWords =
[
new() { Word = "fork", ImagePath = "images/fork.svg", CorrectCount = 0, IncorrectCount = 0 },
new() { Word = "knife", ImagePath = "images/knife.svg", CorrectCount = 0, IncorrectCount = 0 },
new() { Word = "spoon", ImagePath = "images/spoon.svg", CorrectCount = 0, IncorrectCount = 0 },
new() { Word = "door", ImagePath = "images/door.svg", CorrectCount = 0, IncorrectCount = 0 },
new() { Word = "window", ImagePath = "images/window.svg", CorrectCount = 0, IncorrectCount = 0 },
new() { Word = "ball", ImagePath = "images/ball.svg", CorrectCount = 0, IncorrectCount = 0 },
new() { Word = "house", ImagePath = "images/house.svg", CorrectCount = 0, IncorrectCount = 0 },
new() { Word = "tree", ImagePath = "images/tree.svg", CorrectCount = 0, IncorrectCount = 0 },
new() { Word = "car", ImagePath = "images/car.svg", CorrectCount = 0, IncorrectCount = 0 },
new() { Word = "cat", ImagePath = "images/cat.svg", CorrectCount = 0, IncorrectCount = 0 },
new() { Word = "dog", ImagePath = "images/dog.svg", CorrectCount = 0, IncorrectCount = 0 },
new() { Word = "chair", ImagePath = "images/chair.svg", CorrectCount = 0, IncorrectCount = 0 },
new() { Word = "table", ImagePath = "images/table.svg", CorrectCount = 0, IncorrectCount = 0 },
new() { Word = "cup", ImagePath = "images/cup.svg", CorrectCount = 0, IncorrectCount = 0 },
new() { Word = "book", ImagePath = "images/book.svg", CorrectCount = 0, IncorrectCount = 0 },
new() { Word = "clock", ImagePath = "images/clock.svg", CorrectCount = 0, IncorrectCount = 0 },
new() { Word = "bed", ImagePath = "images/bed.svg", CorrectCount = 0, IncorrectCount = 0 },
new() { Word = "phone", ImagePath = "images/phone.svg", CorrectCount = 0, IncorrectCount = 0 },
new() { Word = "shoe", ImagePath = "images/shoe.svg", CorrectCount = 0, IncorrectCount = 0 },
new() { Word = "hat", ImagePath = "images/hat.svg", CorrectCount = 0, IncorrectCount = 0 }
];
public GameService(LocalStorageService localStorage)
{
_localStorage = localStorage;
}
public async Task InitializeAsync()
{
_statistics = await _localStorage.LoadStatisticsAsync();
if (_statistics == null)
{
_statistics = new GameStatistics { Words = new List<GameWord>(_defaultWords) };
}
else
{
foreach (var defaultWord in _defaultWords)
{
var existingWord = _statistics.Words.FirstOrDefault(w => w.Word == defaultWord.Word);
if (existingWord == null)
{
_statistics.Words.Add(defaultWord);
}
}
}
}
public GameSession CreateNewGame()
{
var rounds = new List<Round>();
for (var i = 0; i < 10; i++)
{
var roundType = _random.Next(2) == 0 ? RoundType.ImageWithWords : RoundType.WordWithImages;
var round = CreateRound(roundType);
rounds.Add(round);
}
return new GameSession
{
Rounds = rounds,
CurrentRoundIndex = 0,
StartTime = DateTimeOffset.UtcNow
};
}
private Round CreateRound(RoundType type)
{
var correctAnswer = SelectWeightedRandomWord();
var incorrectAnswers = SelectRandomWords(3, correctAnswer);
var options = new List<GameWord> { correctAnswer };
options.AddRange(incorrectAnswers);
options = [.. options.OrderBy(_ => _random.Next())];
return new Round
{
Type = type,
CorrectAnswer = correctAnswer,
Options = options
};
}
private GameWord SelectWeightedRandomWord()
{
if (_statistics == null || _statistics.Words.Count == 0)
throw new InvalidOperationException("No words available");
var totalPriority = _statistics.Words.Sum(w => w.Priority);
var randomValue = _random.NextDouble() * totalPriority;
var cumulativePriority = 0.0;
foreach (var word in _statistics.Words)
{
cumulativePriority += word.Priority;
if (randomValue <= cumulativePriority)
return word;
}
return _statistics.Words[^1];
}
private List<GameWord> SelectRandomWords(int count, GameWord exclude)
{
if (_statistics == null)
throw new InvalidOperationException("Statistics not initialized");
var availableWords = _statistics.Words.Where(w => w.Word != exclude.Word).ToList();
return [.. availableWords.OrderBy(_ => _random.Next()).Take(count)];
}
public async Task UpdateStatisticsAsync(Round round)
{
if (_statistics == null || round.SelectedAnswer == null)
return;
var word = _statistics.Words.FirstOrDefault(w => w.Word == round.CorrectAnswer.Word);
if (word == null)
return;
if (round.IsCorrect)
{
word.CorrectCount++;
}
else
{
word.IncorrectCount++;
}
await _localStorage.SaveStatisticsAsync(_statistics);
}
}

View file

@ -0,0 +1,38 @@
using System.Text.Json;
using Microsoft.JSInterop;
using MemoryGame.Models;
namespace MemoryGame.Services;
public sealed class LocalStorageService
{
private readonly IJSRuntime _jsRuntime;
private const string StatisticsKey = "memoryGameStatistics";
public LocalStorageService(IJSRuntime jsRuntime)
{
_jsRuntime = jsRuntime;
}
public async Task<GameStatistics?> LoadStatisticsAsync()
{
try
{
var json = await _jsRuntime.InvokeAsync<string>("localStorage.getItem", StatisticsKey);
if (string.IsNullOrEmpty(json))
return null;
return JsonSerializer.Deserialize<GameStatistics>(json);
}
catch
{
return null;
}
}
public async Task SaveStatisticsAsync(GameStatistics statistics)
{
var json = JsonSerializer.Serialize(statistics);
await _jsRuntime.InvokeVoidAsync("localStorage.setItem", StatisticsKey, json);
}
}

10
MemoryGame/_Imports.razor Normal file
View file

@ -0,0 +1,10 @@
@using System.Net.Http
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.AspNetCore.Components.WebAssembly.Http
@using Microsoft.JSInterop
@using MemoryGame
@using MemoryGame.Layout

View file

@ -0,0 +1,345 @@
html, body {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
}
h1:focus {
outline: none;
}
a, .btn-link {
color: #0071c1;
}
.btn-primary {
color: #fff;
background-color: #1b6ec2;
border-color: #1861ac;
}
.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
}
.content {
padding-top: 1.1rem;
}
.valid.modified:not([type=checkbox]) {
outline: 1px solid #26b050;
}
.invalid {
outline: 1px solid red;
}
.validation-message {
color: red;
}
#blazor-error-ui {
color-scheme: light only;
background: lightyellow;
bottom: 0;
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
box-sizing: border-box;
display: none;
left: 0;
padding: 0.6rem 1.25rem 0.7rem 1.25rem;
position: fixed;
width: 100%;
z-index: 1000;
}
#blazor-error-ui .dismiss {
cursor: pointer;
position: absolute;
right: 0.75rem;
top: 0.5rem;
}
.blazor-error-boundary {
background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
padding: 1rem 1rem 1rem 3.7rem;
color: white;
}
.blazor-error-boundary::after {
content: "An error has occurred."
}
.loading-progress {
position: absolute;
display: block;
width: 8rem;
height: 8rem;
inset: 20vh 0 auto 0;
margin: 0 auto 0 auto;
}
.loading-progress circle {
fill: none;
stroke: #e0e0e0;
stroke-width: 0.6rem;
transform-origin: 50% 50%;
transform: rotate(-90deg);
}
.loading-progress circle:last-child {
stroke: #1b6ec2;
stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%;
transition: stroke-dasharray 0.05s ease-in-out;
}
.loading-progress-text {
position: absolute;
text-align: center;
font-weight: bold;
inset: calc(20vh + 3.25rem) 0 auto 0.2rem;
}
.loading-progress-text:after {
content: var(--blazor-load-percentage-text, "Loading");
}
code {
color: #c02d76;
}
.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
color: var(--bs-secondary-color);
text-align: end;
}
.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
text-align: start;
}
.memory-game-container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.start-screen, .results-screen {
text-align: center;
padding: 40px;
}
.start-screen h1, .results-screen h1 {
font-size: 3rem;
margin-bottom: 20px;
color: #333;
}
.subtitle {
font-size: 1.5rem;
color: #666;
margin-bottom: 40px;
}
.btn-start {
font-size: 1.8rem;
padding: 20px 60px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 10px;
cursor: pointer;
transition: background-color 0.3s;
font-weight: bold;
}
.btn-start:hover {
background-color: #45a049;
}
.btn-start:active {
transform: scale(0.98);
}
.game-screen {
width: 100%;
max-width: 900px;
}
.game-header {
text-align: center;
margin-bottom: 30px;
}
.round-counter {
font-size: 1.5rem;
font-weight: bold;
color: #333;
padding: 10px;
background-color: #f0f0f0;
border-radius: 8px;
}
.question-area {
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 30px;
min-height: 300px;
}
.question-image {
max-width: 100%;
max-height: 400px;
object-fit: contain;
border: 3px solid #ddd;
border-radius: 10px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.question-word {
font-size: 4rem;
font-weight: bold;
color: #333;
text-transform: capitalize;
}
.options-area {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
margin-bottom: 30px;
}
.options-area.image-options {
grid-template-columns: 1fr 1fr;
}
.option-button {
padding: 30px;
font-size: 2rem;
background-color: #f8f9fa;
border: 3px solid #ddd;
border-radius: 10px;
cursor: pointer;
transition: all 0.3s;
font-weight: 600;
text-transform: capitalize;
}
.option-button:hover {
background-color: #e9ecef;
border-color: #4CAF50;
transform: scale(1.05);
}
.option-button:active {
transform: scale(0.98);
}
.option-button.image-option {
padding: 20px;
height: 250px;
display: flex;
align-items: center;
justify-content: center;
}
.option-button.image-option img {
max-width: 100%;
max-height: 200px;
object-fit: contain;
}
.feedback {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
padding: 40px 60px;
font-size: 2.5rem;
font-weight: bold;
border-radius: 15px;
z-index: 1000;
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);
animation: fadeIn 0.3s;
}
.feedback.correct {
background-color: #4CAF50;
color: white;
}
.feedback.incorrect {
background-color: #f44336;
color: white;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translate(-50%, -50%) scale(0.8);
}
to {
opacity: 1;
transform: translate(-50%, -50%) scale(1);
}
}
.results {
display: flex;
justify-content: center;
gap: 40px;
margin: 40px 0;
flex-wrap: wrap;
}
.result-item {
padding: 30px;
border-radius: 10px;
min-width: 200px;
text-align: center;
}
.result-item.correct {
background-color: #4CAF50;
color: white;
}
.result-item.incorrect {
background-color: #f44336;
color: white;
}
.result-label {
display: block;
font-size: 1.5rem;
margin-bottom: 10px;
}
.result-value {
display: block;
font-size: 3.5rem;
font-weight: bold;
}
.loading {
text-align: center;
padding: 40px;
}
@media (max-width: 768px) {
.question-word {
font-size: 3rem;
}
.option-button {
font-size: 1.5rem;
padding: 20px;
}
.btn-start {
font-size: 1.5rem;
padding: 15px 40px;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View file

@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
<rect width="200" height="200" fill="#f0f0f0"/>
<g transform="translate(100,100)">
<circle cx="0" cy="0" r="50" fill="#FF6347" stroke="#333" stroke-width="2"/>
<path d="M -35,-35 Q 0,-50 35,-35" fill="none" stroke="#333" stroke-width="2"/>
<path d="M -35,35 Q 0,50 35,35" fill="none" stroke="#333" stroke-width="2"/>
</g>
<text x="100" y="180" text-anchor="middle" font-size="20" fill="#666">BALL</text>
</svg>

After

Width:  |  Height:  |  Size: 494 B

View file

@ -0,0 +1,10 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
<rect width="200" height="200" fill="#f0f0f0"/>
<g transform="translate(100,100)">
<rect x="-50" y="-10" width="100" height="20" fill="#8B4513"/>
<rect x="-50" y="-30" width="100" height="20" fill="#4169E1"/>
<line x1="-45" y1="10" x2="-45" y2="30" stroke="#8B4513" stroke-width="5"/>
<line x1="45" y1="10" x2="45" y2="30" stroke="#8B4513" stroke-width="5"/>
</g>
<text x="100" y="180" text-anchor="middle" font-size="20" fill="#666">BED</text>
</svg>

After

Width:  |  Height:  |  Size: 539 B

View file

@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
<rect width="200" height="200" fill="#f0f0f0"/>
<g transform="translate(100,100)">
<rect x="-35" y="-40" width="70" height="80" fill="#8B0000" stroke="#333" stroke-width="2"/>
<line x1="0" y1="-40" x2="0" y2="40" stroke="#333" stroke-width="2"/>
<rect x="-30" y="-30" width="25" height="10" fill="#FFF"/>
</g>
<text x="100" y="180" text-anchor="middle" font-size="20" fill="#666">BOOK</text>
</svg>

After

Width:  |  Height:  |  Size: 482 B

View file

@ -0,0 +1,10 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
<rect width="200" height="200" fill="#f0f0f0"/>
<g transform="translate(100,100)">
<rect x="-50" y="-10" width="100" height="30" fill="#FF0000" stroke="#333" stroke-width="2"/>
<rect x="-35" y="-30" width="40" height="20" fill="#FF0000" stroke="#333" stroke-width="2"/>
<circle cx="-30" cy="20" r="10" fill="#333"/>
<circle cx="30" cy="20" r="10" fill="#333"/>
</g>
<text x="100" y="180" text-anchor="middle" font-size="20" fill="#666">CAR</text>
</svg>

After

Width:  |  Height:  |  Size: 541 B

View file

@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
<rect width="200" height="200" fill="#f0f0f0"/>
<g transform="translate(100,100)">
<ellipse cx="0" cy="0" rx="40" ry="30" fill="#FFA500"/>
<circle cx="0" cy="-25" r="25" fill="#FFA500"/>
<polygon points="-20,-45 -25,-55 -15,-40" fill="#FFA500"/>
<polygon points="20,-45 25,-55 15,-40" fill="#FFA500"/>
<circle cx="-10" cy="-25" r="3" fill="#333"/>
<circle cx="10" cy="-25" r="3" fill="#333"/>
</g>
<text x="100" y="180" text-anchor="middle" font-size="20" fill="#666">CAT</text>
</svg>

After

Width:  |  Height:  |  Size: 581 B

View file

@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
<rect width="200" height="200" fill="#f0f0f0"/>
<g transform="translate(100,100)">
<rect x="-30" y="-40" width="60" height="10" fill="#8B4513"/>
<line x1="-25" y1="-30" x2="-25" y2="40" stroke="#8B4513" stroke-width="6"/>
<line x1="25" y1="-30" x2="25" y2="40" stroke="#8B4513" stroke-width="6"/>
<line x1="-25" y1="-40" x2="-25" y2="-60" stroke="#8B4513" stroke-width="6"/>
<line x1="25" y1="-40" x2="25" y2="-60" stroke="#8B4513" stroke-width="6"/>
<line x1="-25" y1="-60" x2="25" y2="-60" stroke="#8B4513" stroke-width="6"/>
</g>
<text x="100" y="180" text-anchor="middle" font-size="20" fill="#666">CHAIR</text>
</svg>

After

Width:  |  Height:  |  Size: 718 B

View file

@ -0,0 +1,10 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
<rect width="200" height="200" fill="#f0f0f0"/>
<g transform="translate(100,100)">
<circle cx="0" cy="0" r="50" fill="#FFF" stroke="#333" stroke-width="3"/>
<line x1="0" y1="0" x2="0" y2="-30" stroke="#333" stroke-width="3"/>
<line x1="0" y1="0" x2="20" y2="0" stroke="#333" stroke-width="2"/>
<circle cx="0" cy="0" r="3" fill="#333"/>
</g>
<text x="100" y="180" text-anchor="middle" font-size="20" fill="#666">CLOCK</text>
</svg>

After

Width:  |  Height:  |  Size: 518 B

View file

@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
<rect width="200" height="200" fill="#f0f0f0"/>
<g transform="translate(100,100)">
<path d="M -25,-30 L -20,30 L 20,30 L 25,-30 Z" fill="#87CEEB" stroke="#333" stroke-width="2"/>
<path d="M 25,-10 Q 40,-10 40,10 Q 40,30 25,30" fill="none" stroke="#333" stroke-width="2"/>
</g>
<text x="100" y="180" text-anchor="middle" font-size="20" fill="#666">CUP</text>
</svg>

After

Width:  |  Height:  |  Size: 444 B

View file

@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
<rect width="200" height="200" fill="#f0f0f0"/>
<g transform="translate(100,100)">
<ellipse cx="0" cy="0" rx="45" ry="30" fill="#8B4513"/>
<circle cx="-15" cy="-20" r="20" fill="#8B4513"/>
<ellipse cx="-30" cy="-30" rx="10" ry="20" fill="#8B4513"/>
<ellipse cx="0" cy="-30" rx="10" ry="20" fill="#8B4513"/>
<circle cx="-20" cy="-25" r="3" fill="#333"/>
<circle cx="-10" cy="-25" r="3" fill="#333"/>
</g>
<text x="100" y="180" text-anchor="middle" font-size="20" fill="#666">DOG</text>
</svg>

After

Width:  |  Height:  |  Size: 587 B

View file

@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
<rect width="200" height="200" fill="#f0f0f0"/>
<g transform="translate(100,100)">
<rect x="-35" y="-60" width="70" height="120" fill="#8B4513" stroke="#654321" stroke-width="3"/>
<circle cx="20" cy="0" r="4" fill="#FFD700"/>
</g>
<text x="100" y="180" text-anchor="middle" font-size="20" fill="#666">DOOR</text>
</svg>

After

Width:  |  Height:  |  Size: 399 B

View file

@ -0,0 +1,11 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
<rect width="200" height="200" fill="#f0f0f0"/>
<g transform="translate(100,100)">
<line x1="0" y1="-60" x2="0" y2="60" stroke="#666" stroke-width="6"/>
<line x1="-20" y1="-60" x2="-20" y2="0" stroke="#666" stroke-width="4"/>
<line x1="-10" y1="-60" x2="-10" y2="0" stroke="#666" stroke-width="4"/>
<line x1="10" y1="-60" x2="10" y2="0" stroke="#666" stroke-width="4"/>
<line x1="20" y1="-60" x2="20" y2="0" stroke="#666" stroke-width="4"/>
</g>
<text x="100" y="180" text-anchor="middle" font-size="20" fill="#666">FORK</text>
</svg>

After

Width:  |  Height:  |  Size: 626 B

View file

@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
<rect width="200" height="200" fill="#f0f0f0"/>
<g transform="translate(100,100)">
<ellipse cx="0" cy="10" rx="50" ry="10" fill="#8B4513" stroke="#333" stroke-width="2"/>
<path d="M -30,-30 Q -30,-50 0,-50 Q 30,-50 30,-30 L 20,10 L -20,10 Z" fill="#8B4513" stroke="#333" stroke-width="2"/>
</g>
<text x="100" y="180" text-anchor="middle" font-size="20" fill="#666">HAT</text>
</svg>

After

Width:  |  Height:  |  Size: 462 B

View file

@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
<rect width="200" height="200" fill="#f0f0f0"/>
<g transform="translate(100,100)">
<polygon points="0,-50 50,0 -50,0" fill="#8B4513"/>
<rect x="-40" y="0" width="80" height="60" fill="#DEB887" stroke="#333" stroke-width="2"/>
<rect x="-15" y="20" width="30" height="40" fill="#654321"/>
</g>
<text x="100" y="180" text-anchor="middle" font-size="20" fill="#666">HOUSE</text>
</svg>

After

Width:  |  Height:  |  Size: 465 B

View file

@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
<rect width="200" height="200" fill="#f0f0f0"/>
<g transform="translate(100,100) rotate(-45)">
<rect x="-10" y="-50" width="20" height="100" fill="#666"/>
<polygon points="-10,-60 0,-80 10,-60" fill="#999"/>
</g>
<text x="100" y="180" text-anchor="middle" font-size="20" fill="#666">KNIFE</text>
</svg>

After

Width:  |  Height:  |  Size: 382 B

View file

@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
<rect width="200" height="200" fill="#f0f0f0"/>
<g transform="translate(100,100)">
<rect x="-25" y="-50" width="50" height="100" rx="5" fill="#333" stroke="#666" stroke-width="2"/>
<rect x="-20" y="-40" width="40" height="70" fill="#87CEEB"/>
<circle cx="0" cy="40" r="5" fill="#666"/>
</g>
<text x="100" y="180" text-anchor="middle" font-size="20" fill="#666">PHONE</text>
</svg>

After

Width:  |  Height:  |  Size: 464 B

View file

@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
<rect width="200" height="200" fill="#f0f0f0"/>
<g transform="translate(100,100)">
<path d="M -40,20 L -30,-10 L 30,-10 L 40,20 Z" fill="#8B4513" stroke="#333" stroke-width="2"/>
<ellipse cx="0" cy="20" rx="40" ry="15" fill="#654321" stroke="#333" stroke-width="2"/>
</g>
<text x="100" y="180" text-anchor="middle" font-size="20" fill="#666">SHOE</text>
</svg>

After

Width:  |  Height:  |  Size: 440 B

View file

@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
<rect width="200" height="200" fill="#f0f0f0"/>
<g transform="translate(100,100)">
<ellipse cx="0" cy="-40" rx="20" ry="30" fill="#666"/>
<rect x="-5" y="-10" width="10" height="70" fill="#666"/>
</g>
<text x="100" y="180" text-anchor="middle" font-size="20" fill="#666">SPOON</text>
</svg>

After

Width:  |  Height:  |  Size: 370 B

View file

@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
<rect width="200" height="200" fill="#f0f0f0"/>
<g transform="translate(100,100)">
<rect x="-50" y="-10" width="100" height="10" fill="#8B4513"/>
<line x1="-40" y1="0" x2="-40" y2="40" stroke="#8B4513" stroke-width="6"/>
<line x1="40" y1="0" x2="40" y2="40" stroke="#8B4513" stroke-width="6"/>
</g>
<text x="100" y="180" text-anchor="middle" font-size="20" fill="#666">TABLE</text>
</svg>

After

Width:  |  Height:  |  Size: 472 B

View file

@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
<rect width="200" height="200" fill="#f0f0f0"/>
<g transform="translate(100,100)">
<rect x="-10" y="20" width="20" height="40" fill="#8B4513"/>
<circle cx="0" cy="-20" r="40" fill="#228B22"/>
</g>
<text x="100" y="180" text-anchor="middle" font-size="20" fill="#666">TREE</text>
</svg>

After

Width:  |  Height:  |  Size: 365 B

View file

@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
<rect width="200" height="200" fill="#f0f0f0"/>
<g transform="translate(100,100)">
<rect x="-40" y="-40" width="80" height="80" fill="#87CEEB" stroke="#333" stroke-width="3"/>
<line x1="-40" y1="0" x2="40" y2="0" stroke="#333" stroke-width="3"/>
<line x1="0" y1="-40" x2="0" y2="40" stroke="#333" stroke-width="3"/>
</g>
<text x="100" y="180" text-anchor="middle" font-size="20" fill="#666">WINDOW</text>
</svg>

After

Width:  |  Height:  |  Size: 495 B

View file

@ -0,0 +1,34 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>MemoryGame</title>
<base href="/" />
<link rel="preload" id="webassembly" />
<link rel="stylesheet" href="lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="css/app.css" />
<link rel="icon" type="image/png" href="favicon.png" />
<link href="MemoryGame.styles.css" rel="stylesheet" />
<script type="importmap"></script>
</head>
<body>
<div id="app">
<svg class="loading-progress">
<circle r="40%" cx="50%" cy="50%" />
<circle r="40%" cx="50%" cy="50%" />
</svg>
<div class="loading-progress-text"></div>
</div>
<div id="blazor-error-ui">
An unhandled error has occurred.
<a href="." class="reload">Reload</a>
<span class="dismiss">🗙</span>
</div>
<script src="_framework/blazor.webassembly#[.{fingerprint}].js"></script>
</body>
</html>

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,597 @@
/*!
* Bootstrap Reboot v5.3.3 (https://getbootstrap.com/)
* Copyright 2011-2024 The Bootstrap Authors
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
:root,
[data-bs-theme=light] {
--bs-blue: #0d6efd;
--bs-indigo: #6610f2;
--bs-purple: #6f42c1;
--bs-pink: #d63384;
--bs-red: #dc3545;
--bs-orange: #fd7e14;
--bs-yellow: #ffc107;
--bs-green: #198754;
--bs-teal: #20c997;
--bs-cyan: #0dcaf0;
--bs-black: #000;
--bs-white: #fff;
--bs-gray: #6c757d;
--bs-gray-dark: #343a40;
--bs-gray-100: #f8f9fa;
--bs-gray-200: #e9ecef;
--bs-gray-300: #dee2e6;
--bs-gray-400: #ced4da;
--bs-gray-500: #adb5bd;
--bs-gray-600: #6c757d;
--bs-gray-700: #495057;
--bs-gray-800: #343a40;
--bs-gray-900: #212529;
--bs-primary: #0d6efd;
--bs-secondary: #6c757d;
--bs-success: #198754;
--bs-info: #0dcaf0;
--bs-warning: #ffc107;
--bs-danger: #dc3545;
--bs-light: #f8f9fa;
--bs-dark: #212529;
--bs-primary-rgb: 13, 110, 253;
--bs-secondary-rgb: 108, 117, 125;
--bs-success-rgb: 25, 135, 84;
--bs-info-rgb: 13, 202, 240;
--bs-warning-rgb: 255, 193, 7;
--bs-danger-rgb: 220, 53, 69;
--bs-light-rgb: 248, 249, 250;
--bs-dark-rgb: 33, 37, 41;
--bs-primary-text-emphasis: #052c65;
--bs-secondary-text-emphasis: #2b2f32;
--bs-success-text-emphasis: #0a3622;
--bs-info-text-emphasis: #055160;
--bs-warning-text-emphasis: #664d03;
--bs-danger-text-emphasis: #58151c;
--bs-light-text-emphasis: #495057;
--bs-dark-text-emphasis: #495057;
--bs-primary-bg-subtle: #cfe2ff;
--bs-secondary-bg-subtle: #e2e3e5;
--bs-success-bg-subtle: #d1e7dd;
--bs-info-bg-subtle: #cff4fc;
--bs-warning-bg-subtle: #fff3cd;
--bs-danger-bg-subtle: #f8d7da;
--bs-light-bg-subtle: #fcfcfd;
--bs-dark-bg-subtle: #ced4da;
--bs-primary-border-subtle: #9ec5fe;
--bs-secondary-border-subtle: #c4c8cb;
--bs-success-border-subtle: #a3cfbb;
--bs-info-border-subtle: #9eeaf9;
--bs-warning-border-subtle: #ffe69c;
--bs-danger-border-subtle: #f1aeb5;
--bs-light-border-subtle: #e9ecef;
--bs-dark-border-subtle: #adb5bd;
--bs-white-rgb: 255, 255, 255;
--bs-black-rgb: 0, 0, 0;
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
--bs-body-font-family: var(--bs-font-sans-serif);
--bs-body-font-size: 1rem;
--bs-body-font-weight: 400;
--bs-body-line-height: 1.5;
--bs-body-color: #212529;
--bs-body-color-rgb: 33, 37, 41;
--bs-body-bg: #fff;
--bs-body-bg-rgb: 255, 255, 255;
--bs-emphasis-color: #000;
--bs-emphasis-color-rgb: 0, 0, 0;
--bs-secondary-color: rgba(33, 37, 41, 0.75);
--bs-secondary-color-rgb: 33, 37, 41;
--bs-secondary-bg: #e9ecef;
--bs-secondary-bg-rgb: 233, 236, 239;
--bs-tertiary-color: rgba(33, 37, 41, 0.5);
--bs-tertiary-color-rgb: 33, 37, 41;
--bs-tertiary-bg: #f8f9fa;
--bs-tertiary-bg-rgb: 248, 249, 250;
--bs-heading-color: inherit;
--bs-link-color: #0d6efd;
--bs-link-color-rgb: 13, 110, 253;
--bs-link-decoration: underline;
--bs-link-hover-color: #0a58ca;
--bs-link-hover-color-rgb: 10, 88, 202;
--bs-code-color: #d63384;
--bs-highlight-color: #212529;
--bs-highlight-bg: #fff3cd;
--bs-border-width: 1px;
--bs-border-style: solid;
--bs-border-color: #dee2e6;
--bs-border-color-translucent: rgba(0, 0, 0, 0.175);
--bs-border-radius: 0.375rem;
--bs-border-radius-sm: 0.25rem;
--bs-border-radius-lg: 0.5rem;
--bs-border-radius-xl: 1rem;
--bs-border-radius-xxl: 2rem;
--bs-border-radius-2xl: var(--bs-border-radius-xxl);
--bs-border-radius-pill: 50rem;
--bs-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
--bs-box-shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
--bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, 0.175);
--bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.075);
--bs-focus-ring-width: 0.25rem;
--bs-focus-ring-opacity: 0.25;
--bs-focus-ring-color: rgba(13, 110, 253, 0.25);
--bs-form-valid-color: #198754;
--bs-form-valid-border-color: #198754;
--bs-form-invalid-color: #dc3545;
--bs-form-invalid-border-color: #dc3545;
}
[data-bs-theme=dark] {
color-scheme: dark;
--bs-body-color: #dee2e6;
--bs-body-color-rgb: 222, 226, 230;
--bs-body-bg: #212529;
--bs-body-bg-rgb: 33, 37, 41;
--bs-emphasis-color: #fff;
--bs-emphasis-color-rgb: 255, 255, 255;
--bs-secondary-color: rgba(222, 226, 230, 0.75);
--bs-secondary-color-rgb: 222, 226, 230;
--bs-secondary-bg: #343a40;
--bs-secondary-bg-rgb: 52, 58, 64;
--bs-tertiary-color: rgba(222, 226, 230, 0.5);
--bs-tertiary-color-rgb: 222, 226, 230;
--bs-tertiary-bg: #2b3035;
--bs-tertiary-bg-rgb: 43, 48, 53;
--bs-primary-text-emphasis: #6ea8fe;
--bs-secondary-text-emphasis: #a7acb1;
--bs-success-text-emphasis: #75b798;
--bs-info-text-emphasis: #6edff6;
--bs-warning-text-emphasis: #ffda6a;
--bs-danger-text-emphasis: #ea868f;
--bs-light-text-emphasis: #f8f9fa;
--bs-dark-text-emphasis: #dee2e6;
--bs-primary-bg-subtle: #031633;
--bs-secondary-bg-subtle: #161719;
--bs-success-bg-subtle: #051b11;
--bs-info-bg-subtle: #032830;
--bs-warning-bg-subtle: #332701;
--bs-danger-bg-subtle: #2c0b0e;
--bs-light-bg-subtle: #343a40;
--bs-dark-bg-subtle: #1a1d20;
--bs-primary-border-subtle: #084298;
--bs-secondary-border-subtle: #41464b;
--bs-success-border-subtle: #0f5132;
--bs-info-border-subtle: #087990;
--bs-warning-border-subtle: #997404;
--bs-danger-border-subtle: #842029;
--bs-light-border-subtle: #495057;
--bs-dark-border-subtle: #343a40;
--bs-heading-color: inherit;
--bs-link-color: #6ea8fe;
--bs-link-hover-color: #8bb9fe;
--bs-link-color-rgb: 110, 168, 254;
--bs-link-hover-color-rgb: 139, 185, 254;
--bs-code-color: #e685b5;
--bs-highlight-color: #dee2e6;
--bs-highlight-bg: #664d03;
--bs-border-color: #495057;
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
--bs-form-valid-color: #75b798;
--bs-form-valid-border-color: #75b798;
--bs-form-invalid-color: #ea868f;
--bs-form-invalid-border-color: #ea868f;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
@media (prefers-reduced-motion: no-preference) {
:root {
scroll-behavior: smooth;
}
}
body {
margin: 0;
font-family: var(--bs-body-font-family);
font-size: var(--bs-body-font-size);
font-weight: var(--bs-body-font-weight);
line-height: var(--bs-body-line-height);
color: var(--bs-body-color);
text-align: var(--bs-body-text-align);
background-color: var(--bs-body-bg);
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
hr {
margin: 1rem 0;
color: inherit;
border: 0;
border-top: var(--bs-border-width) solid;
opacity: 0.25;
}
h6, h5, h4, h3, h2, h1 {
margin-top: 0;
margin-bottom: 0.5rem;
font-weight: 500;
line-height: 1.2;
color: var(--bs-heading-color);
}
h1 {
font-size: calc(1.375rem + 1.5vw);
}
@media (min-width: 1200px) {
h1 {
font-size: 2.5rem;
}
}
h2 {
font-size: calc(1.325rem + 0.9vw);
}
@media (min-width: 1200px) {
h2 {
font-size: 2rem;
}
}
h3 {
font-size: calc(1.3rem + 0.6vw);
}
@media (min-width: 1200px) {
h3 {
font-size: 1.75rem;
}
}
h4 {
font-size: calc(1.275rem + 0.3vw);
}
@media (min-width: 1200px) {
h4 {
font-size: 1.5rem;
}
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
abbr[title] {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
-webkit-text-decoration-skip-ink: none;
text-decoration-skip-ink: none;
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul {
padding-left: 2rem;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: 700;
}
dd {
margin-bottom: 0.5rem;
margin-left: 0;
}
blockquote {
margin: 0 0 1rem;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 0.875em;
}
mark {
padding: 0.1875em;
color: var(--bs-highlight-color);
background-color: var(--bs-highlight-bg);
}
sub,
sup {
position: relative;
font-size: 0.75em;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
a {
color: rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1));
text-decoration: underline;
}
a:hover {
--bs-link-color-rgb: var(--bs-link-hover-color-rgb);
}
a:not([href]):not([class]), a:not([href]):not([class]):hover {
color: inherit;
text-decoration: none;
}
pre,
code,
kbd,
samp {
font-family: var(--bs-font-monospace);
font-size: 1em;
}
pre {
display: block;
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
font-size: 0.875em;
}
pre code {
font-size: inherit;
color: inherit;
word-break: normal;
}
code {
font-size: 0.875em;
color: var(--bs-code-color);
word-wrap: break-word;
}
a > code {
color: inherit;
}
kbd {
padding: 0.1875rem 0.375rem;
font-size: 0.875em;
color: var(--bs-body-bg);
background-color: var(--bs-body-color);
border-radius: 0.25rem;
}
kbd kbd {
padding: 0;
font-size: 1em;
}
figure {
margin: 0 0 1rem;
}
img,
svg {
vertical-align: middle;
}
table {
caption-side: bottom;
border-collapse: collapse;
}
caption {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
color: var(--bs-secondary-color);
text-align: left;
}
th {
text-align: inherit;
text-align: -webkit-match-parent;
}
thead,
tbody,
tfoot,
tr,
td,
th {
border-color: inherit;
border-style: solid;
border-width: 0;
}
label {
display: inline-block;
}
button {
border-radius: 0;
}
button:focus:not(:focus-visible) {
outline: 0;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
select {
text-transform: none;
}
[role=button] {
cursor: pointer;
}
select {
word-wrap: normal;
}
select:disabled {
opacity: 1;
}
[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator {
display: none !important;
}
button,
[type=button],
[type=reset],
[type=submit] {
-webkit-appearance: button;
}
button:not(:disabled),
[type=button]:not(:disabled),
[type=reset]:not(:disabled),
[type=submit]:not(:disabled) {
cursor: pointer;
}
::-moz-focus-inner {
padding: 0;
border-style: none;
}
textarea {
resize: vertical;
}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
legend {
float: left;
width: 100%;
padding: 0;
margin-bottom: 0.5rem;
font-size: calc(1.275rem + 0.3vw);
line-height: inherit;
}
@media (min-width: 1200px) {
legend {
font-size: 1.5rem;
}
}
legend + * {
clear: left;
}
::-webkit-datetime-edit-fields-wrapper,
::-webkit-datetime-edit-text,
::-webkit-datetime-edit-minute,
::-webkit-datetime-edit-hour-field,
::-webkit-datetime-edit-day-field,
::-webkit-datetime-edit-month-field,
::-webkit-datetime-edit-year-field {
padding: 0;
}
::-webkit-inner-spin-button {
height: auto;
}
[type=search] {
-webkit-appearance: textfield;
outline-offset: -2px;
}
/* rtl:raw:
[type="tel"],
[type="url"],
[type="email"],
[type="number"] {
direction: ltr;
}
*/
::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-color-swatch-wrapper {
padding: 0;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
::file-selector-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
iframe {
border: 0;
}
summary {
display: list-item;
cursor: pointer;
}
progress {
vertical-align: baseline;
}
[hidden] {
display: none !important;
}
/*# sourceMappingURL=bootstrap-reboot.css.map */

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,594 @@
/*!
* Bootstrap Reboot v5.3.3 (https://getbootstrap.com/)
* Copyright 2011-2024 The Bootstrap Authors
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
:root,
[data-bs-theme=light] {
--bs-blue: #0d6efd;
--bs-indigo: #6610f2;
--bs-purple: #6f42c1;
--bs-pink: #d63384;
--bs-red: #dc3545;
--bs-orange: #fd7e14;
--bs-yellow: #ffc107;
--bs-green: #198754;
--bs-teal: #20c997;
--bs-cyan: #0dcaf0;
--bs-black: #000;
--bs-white: #fff;
--bs-gray: #6c757d;
--bs-gray-dark: #343a40;
--bs-gray-100: #f8f9fa;
--bs-gray-200: #e9ecef;
--bs-gray-300: #dee2e6;
--bs-gray-400: #ced4da;
--bs-gray-500: #adb5bd;
--bs-gray-600: #6c757d;
--bs-gray-700: #495057;
--bs-gray-800: #343a40;
--bs-gray-900: #212529;
--bs-primary: #0d6efd;
--bs-secondary: #6c757d;
--bs-success: #198754;
--bs-info: #0dcaf0;
--bs-warning: #ffc107;
--bs-danger: #dc3545;
--bs-light: #f8f9fa;
--bs-dark: #212529;
--bs-primary-rgb: 13, 110, 253;
--bs-secondary-rgb: 108, 117, 125;
--bs-success-rgb: 25, 135, 84;
--bs-info-rgb: 13, 202, 240;
--bs-warning-rgb: 255, 193, 7;
--bs-danger-rgb: 220, 53, 69;
--bs-light-rgb: 248, 249, 250;
--bs-dark-rgb: 33, 37, 41;
--bs-primary-text-emphasis: #052c65;
--bs-secondary-text-emphasis: #2b2f32;
--bs-success-text-emphasis: #0a3622;
--bs-info-text-emphasis: #055160;
--bs-warning-text-emphasis: #664d03;
--bs-danger-text-emphasis: #58151c;
--bs-light-text-emphasis: #495057;
--bs-dark-text-emphasis: #495057;
--bs-primary-bg-subtle: #cfe2ff;
--bs-secondary-bg-subtle: #e2e3e5;
--bs-success-bg-subtle: #d1e7dd;
--bs-info-bg-subtle: #cff4fc;
--bs-warning-bg-subtle: #fff3cd;
--bs-danger-bg-subtle: #f8d7da;
--bs-light-bg-subtle: #fcfcfd;
--bs-dark-bg-subtle: #ced4da;
--bs-primary-border-subtle: #9ec5fe;
--bs-secondary-border-subtle: #c4c8cb;
--bs-success-border-subtle: #a3cfbb;
--bs-info-border-subtle: #9eeaf9;
--bs-warning-border-subtle: #ffe69c;
--bs-danger-border-subtle: #f1aeb5;
--bs-light-border-subtle: #e9ecef;
--bs-dark-border-subtle: #adb5bd;
--bs-white-rgb: 255, 255, 255;
--bs-black-rgb: 0, 0, 0;
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
--bs-body-font-family: var(--bs-font-sans-serif);
--bs-body-font-size: 1rem;
--bs-body-font-weight: 400;
--bs-body-line-height: 1.5;
--bs-body-color: #212529;
--bs-body-color-rgb: 33, 37, 41;
--bs-body-bg: #fff;
--bs-body-bg-rgb: 255, 255, 255;
--bs-emphasis-color: #000;
--bs-emphasis-color-rgb: 0, 0, 0;
--bs-secondary-color: rgba(33, 37, 41, 0.75);
--bs-secondary-color-rgb: 33, 37, 41;
--bs-secondary-bg: #e9ecef;
--bs-secondary-bg-rgb: 233, 236, 239;
--bs-tertiary-color: rgba(33, 37, 41, 0.5);
--bs-tertiary-color-rgb: 33, 37, 41;
--bs-tertiary-bg: #f8f9fa;
--bs-tertiary-bg-rgb: 248, 249, 250;
--bs-heading-color: inherit;
--bs-link-color: #0d6efd;
--bs-link-color-rgb: 13, 110, 253;
--bs-link-decoration: underline;
--bs-link-hover-color: #0a58ca;
--bs-link-hover-color-rgb: 10, 88, 202;
--bs-code-color: #d63384;
--bs-highlight-color: #212529;
--bs-highlight-bg: #fff3cd;
--bs-border-width: 1px;
--bs-border-style: solid;
--bs-border-color: #dee2e6;
--bs-border-color-translucent: rgba(0, 0, 0, 0.175);
--bs-border-radius: 0.375rem;
--bs-border-radius-sm: 0.25rem;
--bs-border-radius-lg: 0.5rem;
--bs-border-radius-xl: 1rem;
--bs-border-radius-xxl: 2rem;
--bs-border-radius-2xl: var(--bs-border-radius-xxl);
--bs-border-radius-pill: 50rem;
--bs-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
--bs-box-shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
--bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, 0.175);
--bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.075);
--bs-focus-ring-width: 0.25rem;
--bs-focus-ring-opacity: 0.25;
--bs-focus-ring-color: rgba(13, 110, 253, 0.25);
--bs-form-valid-color: #198754;
--bs-form-valid-border-color: #198754;
--bs-form-invalid-color: #dc3545;
--bs-form-invalid-border-color: #dc3545;
}
[data-bs-theme=dark] {
color-scheme: dark;
--bs-body-color: #dee2e6;
--bs-body-color-rgb: 222, 226, 230;
--bs-body-bg: #212529;
--bs-body-bg-rgb: 33, 37, 41;
--bs-emphasis-color: #fff;
--bs-emphasis-color-rgb: 255, 255, 255;
--bs-secondary-color: rgba(222, 226, 230, 0.75);
--bs-secondary-color-rgb: 222, 226, 230;
--bs-secondary-bg: #343a40;
--bs-secondary-bg-rgb: 52, 58, 64;
--bs-tertiary-color: rgba(222, 226, 230, 0.5);
--bs-tertiary-color-rgb: 222, 226, 230;
--bs-tertiary-bg: #2b3035;
--bs-tertiary-bg-rgb: 43, 48, 53;
--bs-primary-text-emphasis: #6ea8fe;
--bs-secondary-text-emphasis: #a7acb1;
--bs-success-text-emphasis: #75b798;
--bs-info-text-emphasis: #6edff6;
--bs-warning-text-emphasis: #ffda6a;
--bs-danger-text-emphasis: #ea868f;
--bs-light-text-emphasis: #f8f9fa;
--bs-dark-text-emphasis: #dee2e6;
--bs-primary-bg-subtle: #031633;
--bs-secondary-bg-subtle: #161719;
--bs-success-bg-subtle: #051b11;
--bs-info-bg-subtle: #032830;
--bs-warning-bg-subtle: #332701;
--bs-danger-bg-subtle: #2c0b0e;
--bs-light-bg-subtle: #343a40;
--bs-dark-bg-subtle: #1a1d20;
--bs-primary-border-subtle: #084298;
--bs-secondary-border-subtle: #41464b;
--bs-success-border-subtle: #0f5132;
--bs-info-border-subtle: #087990;
--bs-warning-border-subtle: #997404;
--bs-danger-border-subtle: #842029;
--bs-light-border-subtle: #495057;
--bs-dark-border-subtle: #343a40;
--bs-heading-color: inherit;
--bs-link-color: #6ea8fe;
--bs-link-hover-color: #8bb9fe;
--bs-link-color-rgb: 110, 168, 254;
--bs-link-hover-color-rgb: 139, 185, 254;
--bs-code-color: #e685b5;
--bs-highlight-color: #dee2e6;
--bs-highlight-bg: #664d03;
--bs-border-color: #495057;
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
--bs-form-valid-color: #75b798;
--bs-form-valid-border-color: #75b798;
--bs-form-invalid-color: #ea868f;
--bs-form-invalid-border-color: #ea868f;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
@media (prefers-reduced-motion: no-preference) {
:root {
scroll-behavior: smooth;
}
}
body {
margin: 0;
font-family: var(--bs-body-font-family);
font-size: var(--bs-body-font-size);
font-weight: var(--bs-body-font-weight);
line-height: var(--bs-body-line-height);
color: var(--bs-body-color);
text-align: var(--bs-body-text-align);
background-color: var(--bs-body-bg);
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
hr {
margin: 1rem 0;
color: inherit;
border: 0;
border-top: var(--bs-border-width) solid;
opacity: 0.25;
}
h6, h5, h4, h3, h2, h1 {
margin-top: 0;
margin-bottom: 0.5rem;
font-weight: 500;
line-height: 1.2;
color: var(--bs-heading-color);
}
h1 {
font-size: calc(1.375rem + 1.5vw);
}
@media (min-width: 1200px) {
h1 {
font-size: 2.5rem;
}
}
h2 {
font-size: calc(1.325rem + 0.9vw);
}
@media (min-width: 1200px) {
h2 {
font-size: 2rem;
}
}
h3 {
font-size: calc(1.3rem + 0.6vw);
}
@media (min-width: 1200px) {
h3 {
font-size: 1.75rem;
}
}
h4 {
font-size: calc(1.275rem + 0.3vw);
}
@media (min-width: 1200px) {
h4 {
font-size: 1.5rem;
}
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
abbr[title] {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
-webkit-text-decoration-skip-ink: none;
text-decoration-skip-ink: none;
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul {
padding-right: 2rem;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: 700;
}
dd {
margin-bottom: 0.5rem;
margin-right: 0;
}
blockquote {
margin: 0 0 1rem;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 0.875em;
}
mark {
padding: 0.1875em;
color: var(--bs-highlight-color);
background-color: var(--bs-highlight-bg);
}
sub,
sup {
position: relative;
font-size: 0.75em;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
a {
color: rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1));
text-decoration: underline;
}
a:hover {
--bs-link-color-rgb: var(--bs-link-hover-color-rgb);
}
a:not([href]):not([class]), a:not([href]):not([class]):hover {
color: inherit;
text-decoration: none;
}
pre,
code,
kbd,
samp {
font-family: var(--bs-font-monospace);
font-size: 1em;
}
pre {
display: block;
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
font-size: 0.875em;
}
pre code {
font-size: inherit;
color: inherit;
word-break: normal;
}
code {
font-size: 0.875em;
color: var(--bs-code-color);
word-wrap: break-word;
}
a > code {
color: inherit;
}
kbd {
padding: 0.1875rem 0.375rem;
font-size: 0.875em;
color: var(--bs-body-bg);
background-color: var(--bs-body-color);
border-radius: 0.25rem;
}
kbd kbd {
padding: 0;
font-size: 1em;
}
figure {
margin: 0 0 1rem;
}
img,
svg {
vertical-align: middle;
}
table {
caption-side: bottom;
border-collapse: collapse;
}
caption {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
color: var(--bs-secondary-color);
text-align: right;
}
th {
text-align: inherit;
text-align: -webkit-match-parent;
}
thead,
tbody,
tfoot,
tr,
td,
th {
border-color: inherit;
border-style: solid;
border-width: 0;
}
label {
display: inline-block;
}
button {
border-radius: 0;
}
button:focus:not(:focus-visible) {
outline: 0;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
select {
text-transform: none;
}
[role=button] {
cursor: pointer;
}
select {
word-wrap: normal;
}
select:disabled {
opacity: 1;
}
[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator {
display: none !important;
}
button,
[type=button],
[type=reset],
[type=submit] {
-webkit-appearance: button;
}
button:not(:disabled),
[type=button]:not(:disabled),
[type=reset]:not(:disabled),
[type=submit]:not(:disabled) {
cursor: pointer;
}
::-moz-focus-inner {
padding: 0;
border-style: none;
}
textarea {
resize: vertical;
}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
legend {
float: right;
width: 100%;
padding: 0;
margin-bottom: 0.5rem;
font-size: calc(1.275rem + 0.3vw);
line-height: inherit;
}
@media (min-width: 1200px) {
legend {
font-size: 1.5rem;
}
}
legend + * {
clear: right;
}
::-webkit-datetime-edit-fields-wrapper,
::-webkit-datetime-edit-text,
::-webkit-datetime-edit-minute,
::-webkit-datetime-edit-hour-field,
::-webkit-datetime-edit-day-field,
::-webkit-datetime-edit-month-field,
::-webkit-datetime-edit-year-field {
padding: 0;
}
::-webkit-inner-spin-button {
height: auto;
}
[type=search] {
-webkit-appearance: textfield;
outline-offset: -2px;
}
[type="tel"],
[type="url"],
[type="email"],
[type="number"] {
direction: ltr;
}
::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-color-swatch-wrapper {
padding: 0;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
::file-selector-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
iframe {
border: 0;
}
summary {
display: list-item;
cursor: pointer;
}
progress {
vertical-align: baseline;
}
[hidden] {
display: none !important;
}
/*# sourceMappingURL=bootstrap-reboot.rtl.css.map */

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,27 @@
[
{
"date": "2022-01-06",
"temperatureC": 1,
"summary": "Freezing"
},
{
"date": "2022-01-07",
"temperatureC": 14,
"summary": "Bracing"
},
{
"date": "2022-01-08",
"temperatureC": -13,
"summary": "Freezing"
},
{
"date": "2022-01-09",
"temperatureC": -16,
"summary": "Balmy"
},
{
"date": "2022-01-10",
"temperatureC": -2,
"summary": "Chilly"
}
]