Migrate components
This commit is contained in:
@@ -1,10 +1,14 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net10.0</TargetFramework>
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<BlazorDisableThrowNavigationException>true</BlazorDisableThrowNavigationException>
|
<BlazorDisableThrowNavigationException>true</BlazorDisableThrowNavigationException>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<_ContentIncludedByDefault Remove="Components\Shared\Icon.razor"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
25
src/BlazorApp/Components/AnchorLink/AnchorLink.razor
Normal file
25
src/BlazorApp/Components/AnchorLink/AnchorLink.razor
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
@* External link component *@
|
||||||
|
|
||||||
|
<a href="@Href"
|
||||||
|
target="@Target"
|
||||||
|
class="@CombinedClasses">@ChildContent</a>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public RenderFragment? ChildContent { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string? Href { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string Target { get; set; } = "_blank";
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string? CssClass { get; set; }
|
||||||
|
|
||||||
|
private string CombinedClasses => string.IsNullOrEmpty(CssClass)
|
||||||
|
? "underline underline-offset-2"
|
||||||
|
: $"underline underline-offset-2 {CssClass}";
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2,19 +2,66 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8"/>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport"
|
||||||
<base href="/" />
|
content="width=device-width, initial-scale=1.0"/>
|
||||||
<ResourcePreloader />
|
|
||||||
<link rel="stylesheet" href="css/app.css" />
|
<base href="/"/>
|
||||||
<ImportMap />
|
|
||||||
<link rel="icon" type="image/png" href="favicon.png" />
|
<ResourcePreloader/>
|
||||||
<HeadOutlet />
|
|
||||||
|
<!-- Styles -->
|
||||||
|
<link rel="stylesheet"
|
||||||
|
href="css/app.css"/>
|
||||||
|
|
||||||
|
<ImportMap/>
|
||||||
|
|
||||||
|
<!-- Standard Favicons -->
|
||||||
|
<link rel="icon"
|
||||||
|
type="image/x-icon"
|
||||||
|
href="images/favicon.ico"/>
|
||||||
|
<link rel="icon"
|
||||||
|
type="image/png"
|
||||||
|
sizes="16x16"
|
||||||
|
href="images/favicon-16x16.png"/>
|
||||||
|
<link rel="icon"
|
||||||
|
type="image/png"
|
||||||
|
sizes="32x32"
|
||||||
|
href="images/favicon-32x32.png"/>
|
||||||
|
|
||||||
|
<!-- Apple Touch Icons -->
|
||||||
|
<link rel="apple-touch-icon"
|
||||||
|
sizes="180x180"
|
||||||
|
href="images/apple-touch-icon.png"/>
|
||||||
|
|
||||||
|
<!-- Android/Chrome -->
|
||||||
|
<link rel="manifest"
|
||||||
|
href="site.webmanifest"/>
|
||||||
|
|
||||||
|
<!-- Microsoft Tiles -->
|
||||||
|
<meta name="msapplication-TileColor"
|
||||||
|
content="#1a1a1a"/>
|
||||||
|
<meta name="msapplication-config"
|
||||||
|
content="browserconfig.xml"/>
|
||||||
|
|
||||||
|
<!-- Theme Color -->
|
||||||
|
<meta name="theme-color"
|
||||||
|
content="#1a1a1a"/>
|
||||||
|
|
||||||
|
<!-- Open Graph / Social Sharing -->
|
||||||
|
<meta property="og:image"
|
||||||
|
content="images/og-image.png"/>
|
||||||
|
<meta property="og:image:width"
|
||||||
|
content="1200"/>
|
||||||
|
<meta property="og:image:height"
|
||||||
|
content="630"/>
|
||||||
|
|
||||||
|
<HeadOutlet/>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<Routes />
|
<Routes/>
|
||||||
<script src="@Assets["_framework/blazor.web.js"]"></script>
|
<script src="@Assets["_framework/blazor.web.js"]"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
10
src/BlazorApp/Components/Contact/Contact.razor
Normal file
10
src/BlazorApp/Components/Contact/Contact.razor
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
@* Contact call-to-action *@
|
||||||
|
|
||||||
|
<div class="contact-section">
|
||||||
|
<Text>If you think I can help with your project...</Text>
|
||||||
|
<a href="mailto:me@beaufindlay.com"
|
||||||
|
class="contact-button">
|
||||||
|
Get in touch
|
||||||
|
<Icon Type="IconType.SendArrow"/>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
125
src/BlazorApp/Components/Icons/Icon.razor
Normal file
125
src/BlazorApp/Components/Icons/Icon.razor
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
@switch (Type)
|
||||||
|
{
|
||||||
|
case IconType.Github:
|
||||||
|
<svg viewBox="0 0 24 24"
|
||||||
|
fill="currentColor"
|
||||||
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
|
||||||
|
</svg>
|
||||||
|
break;
|
||||||
|
case IconType.LinkedIn:
|
||||||
|
<svg viewBox="0 0 24 24"
|
||||||
|
fill="currentColor"
|
||||||
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/>
|
||||||
|
</svg>
|
||||||
|
break;
|
||||||
|
case IconType.Email:
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke-width="1.5"
|
||||||
|
stroke="currentColor">
|
||||||
|
<path stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
d="M21.75 6.75v10.5a2.25 2.25 0 01-2.25 2.25h-15a2.25 2.25 0 01-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0019.5 4.5h-15a2.25 2.25 0 00-2.25 2.25m19.5 0v.243a2.25 2.25 0 01-1.07 1.916l-7.5 4.615a2.25 2.25 0 01-2.36 0L3.32 8.91a2.25 2.25 0 01-1.07-1.916V6.75"/>
|
||||||
|
</svg>
|
||||||
|
break;
|
||||||
|
case IconType.Code:
|
||||||
|
<svg viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="1.5"
|
||||||
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
d="M17.25 6.75L22.5 12l-5.25 5.25m-10.5 0L1.5 12l5.25-5.25m7.5-3l-4.5 16.5"/>
|
||||||
|
</svg>
|
||||||
|
break;
|
||||||
|
case IconType.Hosting:
|
||||||
|
<svg viewBox="0 0 24 24"
|
||||||
|
fill="currentColor"
|
||||||
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M3 3h18v18H3V3zm16 16V5H5v14h14zm-8-2h2v-2h2v-2h-2v-2h2V9h-2V7h-2v2H9v2h2v2H9v2h2v2z"/>
|
||||||
|
</svg>
|
||||||
|
break;
|
||||||
|
case IconType.Blazor:
|
||||||
|
<svg viewBox="0 0 24 24"
|
||||||
|
fill="currentColor"
|
||||||
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M15.5 2.5c-2.5 0-4.5 2-4.5 4.5v2.5l-2.5 2.5c-1.5 1.5-1.5 4 0 5.5s4 1.5 5.5 0L16.5 15V12.5c0-2.5 2-4.5 4.5-4.5V6c-2.5 0-4.5-2-4.5-4.5h-1zm-3 7.5v2l-1.5 1.5c-.8.8-2.2.8-3 0s-.8-2.2 0-3L9.5 9h3zm3-5c.8 0 1.5.7 1.5 1.5s-.7 1.5-1.5 1.5-1.5-.7-1.5-1.5.7-1.5 1.5-1.5z"/>
|
||||||
|
</svg>
|
||||||
|
break;
|
||||||
|
case IconType.React:
|
||||||
|
<svg viewBox="0 0 24 24"
|
||||||
|
fill="currentColor"
|
||||||
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<circle cx="12"
|
||||||
|
cy="12"
|
||||||
|
r="2"/>
|
||||||
|
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/>
|
||||||
|
<ellipse cx="12"
|
||||||
|
cy="12"
|
||||||
|
rx="8"
|
||||||
|
ry="3"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="1"/>
|
||||||
|
<ellipse cx="12"
|
||||||
|
cy="12"
|
||||||
|
rx="3"
|
||||||
|
ry="8"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="1"/>
|
||||||
|
</svg>
|
||||||
|
break;
|
||||||
|
case IconType.Database:
|
||||||
|
<svg viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="1.5"
|
||||||
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
d="M20.25 6.375c0 2.278-3.694 4.125-8.25 4.125S3.75 8.653 3.75 6.375m16.5 0c0-2.278-3.694-4.125-8.25-4.125S3.75 4.097 3.75 6.375m16.5 0v11.25c0 2.278-3.694 4.125-8.25 4.125s-8.25-1.847-8.25-4.125V6.375m16.5 0v3.75m-16.5-3.75v3.75m16.5 0v3.75C20.25 16.153 16.556 18 12 18s-8.25-1.847-8.25-4.125v-3.75"/>
|
||||||
|
</svg>
|
||||||
|
break;
|
||||||
|
case IconType.Docker:
|
||||||
|
<svg viewBox="0 0 24 24"
|
||||||
|
fill="currentColor"
|
||||||
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M13 2v7h7c0-3.87-3.13-7-7-7zm-2 0C7.13 2 4 5.13 4 9h7V2zM4 11c0 3.87 3.13 7 7 7v-7H4zm9 7c3.87 0 7-3.13 7-7h-7v7z"/>
|
||||||
|
</svg>
|
||||||
|
break;
|
||||||
|
case IconType.SendArrow:
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke-width="1.5"
|
||||||
|
stroke="currentColor">
|
||||||
|
<path stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
d="M6 12L3.269 3.126A59.768 59.768 0 0121.485 12 59.77 59.77 0 013.27 20.876L5.999 12zm0 0h7.5"/>
|
||||||
|
</svg>
|
||||||
|
break;
|
||||||
|
case IconType.Menu:
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke-width="1.5"
|
||||||
|
stroke="currentColor"
|
||||||
|
aria-hidden="true">
|
||||||
|
<path stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5"/>
|
||||||
|
</svg>
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
@code {
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public IconType Type { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
16
src/BlazorApp/Components/Icons/IconType.cs
Normal file
16
src/BlazorApp/Components/Icons/IconType.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
namespace BlazorApp.Components.Icons;
|
||||||
|
|
||||||
|
public enum IconType
|
||||||
|
{
|
||||||
|
Github,
|
||||||
|
LinkedIn,
|
||||||
|
Email,
|
||||||
|
Code,
|
||||||
|
Hosting,
|
||||||
|
Blazor,
|
||||||
|
React,
|
||||||
|
Database,
|
||||||
|
Docker,
|
||||||
|
SendArrow,
|
||||||
|
Menu
|
||||||
|
}
|
||||||
19
src/BlazorApp/Components/Icons/SocialIcons.razor
Normal file
19
src/BlazorApp/Components/Icons/SocialIcons.razor
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
@* Social media links *@
|
||||||
|
|
||||||
|
<div class="social-icons-container">
|
||||||
|
<a href="https://github.com/bdfin"
|
||||||
|
class="social-icon-link">
|
||||||
|
<span class="sr-only">GitHub</span>
|
||||||
|
<Icon Type="IconType.Github"/>
|
||||||
|
</a>
|
||||||
|
<a href="https://www.linkedin.com/in/beau-findlay/"
|
||||||
|
class="social-icon-link">
|
||||||
|
<span class="sr-only">LinkedIn</span>
|
||||||
|
<Icon Type="IconType.LinkedIn"/>
|
||||||
|
</a>
|
||||||
|
<a href="mailto:me@beaufindlay.com"
|
||||||
|
class="social-icon-link">
|
||||||
|
<span class="sr-only">Email</span>
|
||||||
|
<Icon Type="IconType.Email"/>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
14
src/BlazorApp/Components/Layout/Footer.razor
Normal file
14
src/BlazorApp/Components/Layout/Footer.razor
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
@* Footer component *@
|
||||||
|
|
||||||
|
<div class="page-footer">
|
||||||
|
<footer>
|
||||||
|
<div class="footer-container">
|
||||||
|
<div class="footer-content">
|
||||||
|
<SocialIcons/>
|
||||||
|
<p class="footer-text">
|
||||||
|
© @DateTime.Now.Year Beau Findlay. All rights reserved.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
@@ -1,17 +1,11 @@
|
|||||||
@inherits LayoutComponentBase
|
@inherits LayoutComponentBase
|
||||||
|
|
||||||
<div class="page">
|
<div class="px-6 lg:px-10">
|
||||||
<div class="sidebar">
|
<div class="flex flex-col min-h-screen mx-auto max-w-7xl fade-in">
|
||||||
<NavMenu />
|
<NavBar/>
|
||||||
</div>
|
<div class="flex-1 py-8">
|
||||||
|
|
||||||
<main>
|
|
||||||
<div class="top-row px-4">
|
|
||||||
<a href="https://learn.microsoft.com/aspnet/core/" target="_blank">About</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<article class="content px-4">
|
|
||||||
@Body
|
@Body
|
||||||
</article>
|
</div>
|
||||||
</main>
|
<Footer/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
70
src/BlazorApp/Components/Layout/NavBar.razor
Normal file
70
src/BlazorApp/Components/Layout/NavBar.razor
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
@* Navigation bar with mobile menu *@
|
||||||
|
|
||||||
|
<div class="navbar">
|
||||||
|
<header>
|
||||||
|
<nav aria-label="Global">
|
||||||
|
<div class="logo-container">
|
||||||
|
<a href="/"
|
||||||
|
class="logo-link">
|
||||||
|
<span class="sr-only">Beau Findlay</span>
|
||||||
|
<img src="images/logo.webp"
|
||||||
|
alt="Logo"/>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="mobile-menu-button-container">
|
||||||
|
<label for="mobile-menu-toggle"
|
||||||
|
class="menu-button">
|
||||||
|
<span class="sr-only">Open main menu</span>
|
||||||
|
<Icon Type="IconType.Menu"/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="desktop-nav">
|
||||||
|
<NavLink href="/experience">Experience</NavLink>
|
||||||
|
<NavLink href="/about">This app</NavLink>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
@* Mobile menu using CSS checkbox hack *@
|
||||||
|
<input type="checkbox"
|
||||||
|
id="mobile-menu-toggle"
|
||||||
|
class="menu-toggle"/>
|
||||||
|
<div class="mobile-menu-overlay"></div>
|
||||||
|
<div class="mobile-menu-content">
|
||||||
|
<div class="mobile-menu-inner">
|
||||||
|
<div class="mobile-menu-header">
|
||||||
|
<a href="/"
|
||||||
|
class="logo-link">
|
||||||
|
<span class="sr-only">Beau Findlay</span>
|
||||||
|
<img src="images/logo.webp"
|
||||||
|
alt="Logo"/>
|
||||||
|
</a>
|
||||||
|
<label for="mobile-menu-toggle"
|
||||||
|
class="close-button">
|
||||||
|
<span class="sr-only">Close menu</span>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke-width="1.5"
|
||||||
|
stroke="currentColor"
|
||||||
|
aria-hidden="true">
|
||||||
|
<path stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
d="M6 18L18 6M6 6l12 12"/>
|
||||||
|
</svg>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="mobile-menu-body">
|
||||||
|
<div class="mobile-nav-links">
|
||||||
|
<NavLink href="/experience">Experience</NavLink>
|
||||||
|
<NavLink href="/about">This App</NavLink>
|
||||||
|
</div>
|
||||||
|
<div class="mobile-social-divider">
|
||||||
|
<div class="mobile-social-container">
|
||||||
|
<SocialIcons/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
</div>
|
||||||
@@ -1,22 +1,31 @@
|
|||||||
<div class="top-row ps-3 navbar navbar-dark">
|
<div class="top-row ps-3 navbar navbar-dark">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<a class="navbar-brand" href="">BlazorApp</a>
|
<a class="navbar-brand"
|
||||||
|
href="">BlazorApp</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input type="checkbox" title="Navigation menu" class="navbar-toggler" />
|
<input type="checkbox"
|
||||||
|
title="Navigation menu"
|
||||||
|
class="navbar-toggler"/>
|
||||||
|
|
||||||
<div class="nav-scrollable" onclick="document.querySelector('.navbar-toggler').click()">
|
<div class="nav-scrollable"
|
||||||
|
onclick="document.querySelector('.navbar-toggler').click()">
|
||||||
<nav class="nav flex-column">
|
<nav class="nav flex-column">
|
||||||
<div class="nav-item px-3">
|
<div class="nav-item px-3">
|
||||||
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
|
<NavLink class="nav-link"
|
||||||
<span class="bi bi-house-door-fill-nav-menu" aria-hidden="true"></span> Home
|
href=""
|
||||||
|
Match="NavLinkMatch.All">
|
||||||
|
<span class="bi bi-house-door-fill-nav-menu"
|
||||||
|
aria-hidden="true"></span> Home
|
||||||
</NavLink>
|
</NavLink>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="nav-item px-3">
|
<div class="nav-item px-3">
|
||||||
<NavLink class="nav-link" href="weather">
|
<NavLink class="nav-link"
|
||||||
<span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Weather
|
href="weather">
|
||||||
|
<span class="bi bi-list-nested-nav-menu"
|
||||||
|
aria-hidden="true"></span> Weather
|
||||||
</NavLink>
|
</NavLink>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
41
src/BlazorApp/Components/Pages/About.razor
Normal file
41
src/BlazorApp/Components/Pages/About.razor
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
@page "/about"
|
||||||
|
|
||||||
|
<PageTitle>Beau Findlay - About</PageTitle>
|
||||||
|
|
||||||
|
<Title CssClass="text-center pb-4">This App</Title>
|
||||||
|
<Text>
|
||||||
|
Below is an overview of how this simple app is made and what
|
||||||
|
technologies are used. If you'd like to dive straight in, the full
|
||||||
|
project is available on my
|
||||||
|
<AnchorLink Href="https://github.com/bdfin/my-portfolio">
|
||||||
|
GitHub
|
||||||
|
</AnchorLink>.
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<Subtitle>App</Subtitle>
|
||||||
|
|
||||||
|
<Text>
|
||||||
|
This app was originally made using
|
||||||
|
<AnchorLink Href="https://dotnet.microsoft.com/en-us/apps/aspnet/web-apps/blazor">.NET Blazor WASM</AnchorLink>
|
||||||
|
and then re-written in
|
||||||
|
<AnchorLink Href="https://react.dev/">React</AnchorLink>
|
||||||
|
with
|
||||||
|
<AnchorLink Href="https://www.typescriptlang.org/">TypeScript</AnchorLink>
|
||||||
|
as a learning exercise. I've now migrated it back to .NET Blazor to take advantage of static server-side
|
||||||
|
rendering for maximum performance and to remove unnecessary dependencies on large JS and CSS libraries.
|
||||||
|
</Text>
|
||||||
|
<Text>
|
||||||
|
This version uses pure vanilla CSS with CSS variables for theming, eliminating all JavaScript and external
|
||||||
|
dependencies; the mobile menu uses a CSS checkbox hack for zero-JavaScript interactivity.
|
||||||
|
</Text>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="mt-8">
|
||||||
|
<Subtitle>Hosting & Deployment</Subtitle>
|
||||||
|
|
||||||
|
<Text>
|
||||||
|
TODO: This section
|
||||||
|
</Text>
|
||||||
|
</section>
|
||||||
|
|
||||||
@@ -15,22 +15,28 @@
|
|||||||
|
|
||||||
<h3>Development Mode</h3>
|
<h3>Development Mode</h3>
|
||||||
<p>
|
<p>
|
||||||
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
|
Swapping to <strong>Development</strong> environment will display more detailed information about the error that
|
||||||
|
occurred.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
|
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
|
||||||
It can result in displaying sensitive information from exceptions to end users.
|
It can result in displaying sensitive information from exceptions to end users.
|
||||||
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
|
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong>
|
||||||
|
environment variable to <strong>Development</strong>
|
||||||
and restarting the app.
|
and restarting the app.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@code{
|
@code{
|
||||||
|
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
private HttpContext? HttpContext { get; set; }
|
private HttpContext? HttpContext { get; set; }
|
||||||
|
|
||||||
private string? RequestId { get; set; }
|
private string? RequestId { get; set; }
|
||||||
private bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
|
private bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
|
||||||
|
|
||||||
protected override void OnInitialized() =>
|
protected override void OnInitialized()
|
||||||
|
{
|
||||||
RequestId = Activity.Current?.Id ?? HttpContext?.TraceIdentifier;
|
RequestId = Activity.Current?.Id ?? HttpContext?.TraceIdentifier;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
107
src/BlazorApp/Components/Pages/Experience.razor
Normal file
107
src/BlazorApp/Components/Pages/Experience.razor
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
@page "/experience"
|
||||||
|
|
||||||
|
<PageTitle>Beau Findlay - Experience</PageTitle>
|
||||||
|
|
||||||
|
<Title CssClass="text-center">Experience</Title>
|
||||||
|
|
||||||
|
<p class="text-center text-xl font-semibold mb-10 ">
|
||||||
|
Software Engineer since 2018
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ol class="timeline">
|
||||||
|
@foreach (var item in experienceTimelineItems)
|
||||||
|
{
|
||||||
|
<li class="timeline-item">
|
||||||
|
<time class="timeline-date">
|
||||||
|
@item.StartDate - @(item.EndDate ?? "Present")
|
||||||
|
</time>
|
||||||
|
<h3 class="timeline-title">
|
||||||
|
@item.Title @("@") <AnchorLink Href="@item.CompanyUrl">@item.CompanyName</AnchorLink>
|
||||||
|
</h3>
|
||||||
|
@foreach (var content in item.Content)
|
||||||
|
{
|
||||||
|
<Text>@content</Text>
|
||||||
|
}
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<Contact/>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
|
||||||
|
private readonly List<WorkTimelineItem> experienceTimelineItems =
|
||||||
|
[
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
StartDate = "September 2021",
|
||||||
|
Title = "CTO",
|
||||||
|
CompanyName = "un:hurd music",
|
||||||
|
CompanyUrl = "https://unhurdmusic.com",
|
||||||
|
Content =
|
||||||
|
[
|
||||||
|
"As one of the founding developers at un:hurd music and now Chief Technology Officer, I built and scaled un:hurd's back-end and cloud infrastructure that serves automated marketing soloutions for tens-of-thousands of artists and musicians.",
|
||||||
|
"I lead a small but incredibly talented multi-disciplinary team building on the Azure cloud using a .NET backend, React web front-end and a Swift native iOS app."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
StartDate = "August 2020",
|
||||||
|
EndDate = "September 2021",
|
||||||
|
Title = "Software Development Lead",
|
||||||
|
CompanyName = "Vouch",
|
||||||
|
CompanyUrl = "https://vouch.co.uk/",
|
||||||
|
Content =
|
||||||
|
[
|
||||||
|
"At Vouch I lead the backend build of a new version of their tenant referencing software - an AI enhanced chat-bot based system utlising Azure Cognitive Services and various supporting serverless APIs written in .NET Core and hosted on Microsoft Azure."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
StartDate = "May 2020",
|
||||||
|
EndDate = "July 2020",
|
||||||
|
Title = "Software Developer",
|
||||||
|
CompanyName = "Paragon ID",
|
||||||
|
CompanyUrl = "https://www.paragon-id.com/en",
|
||||||
|
Content =
|
||||||
|
[
|
||||||
|
"I joined Paragon ID on a short-term contract where I wrote and deployed two key projects: A complex dashboard for a large construction equipment manufacturer to track assets across various manufacturing stages and a medical assets tracking dashboard deployed and used in multiple hospitals across the UK."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
StartDate = "July 2019",
|
||||||
|
EndDate = "May 2020",
|
||||||
|
Title = "Software Developer",
|
||||||
|
CompanyName = "Osborne Technologies",
|
||||||
|
CompanyUrl = "https://www.osbornetechnologies.co.uk/",
|
||||||
|
Content =
|
||||||
|
[
|
||||||
|
"I joined Osborne Technologies as the only cloud cloud-specialist and lead a project creating the first web-based version of their flag ship visitor management software utilising ASP.NET Core MVC and Microsoft SQL Server on the Microsoft Azure cloud."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
StartDate = "September 2018",
|
||||||
|
EndDate = "September 2019",
|
||||||
|
Title = " MSc Computing Student",
|
||||||
|
CompanyName = "Sheffield Hallam University",
|
||||||
|
CompanyUrl = "https://www.shu.ac.uk/courses/computing/msc-computing/full-time",
|
||||||
|
Content =
|
||||||
|
[
|
||||||
|
"I joined Sheffield Hallam University to study for a Master of Science in Computing. During my time there I completed modules in computer programming and web development, databases and big data, computer hardware, project management and my software development thesis; a .NET web application that compiles astronomy and space exploration data from various APIs into an accessible calendar."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
private class WorkTimelineItem
|
||||||
|
{
|
||||||
|
public string StartDate { get; init; } = string.Empty;
|
||||||
|
public string? EndDate { get; init; }
|
||||||
|
public string Title { get; init; } = string.Empty;
|
||||||
|
public string CompanyName { get; init; } = string.Empty;
|
||||||
|
public string CompanyUrl { get; init; } = string.Empty;
|
||||||
|
public string[] Content { get; init; } = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,7 +1,18 @@
|
|||||||
@page "/"
|
@page "/"
|
||||||
|
|
||||||
<PageTitle>Home</PageTitle>
|
<PageTitle>Beau Findlay - Home</PageTitle>
|
||||||
|
|
||||||
<h1>Hello, world!</h1>
|
<Title CssClass="text-center mb-8">Hi, I'm Beau.</Title>
|
||||||
|
<Text>
|
||||||
Welcome to your new app.
|
I'm a UK-based software engineer and I love building cool stuff.
|
||||||
|
</Text>
|
||||||
|
<Text>
|
||||||
|
I specialise in C#/.NET development and I've built systems that scale for hundreds-of-thousands of global users.
|
||||||
|
</Text>
|
||||||
|
<Text>
|
||||||
|
I've worked with businesses at all sizes and stages and I'm currently heading up the tech as CTO at a cool startup called
|
||||||
|
<AnchorLink Href="https://unhurdmusic.com">un:hurd music</AnchorLink>.
|
||||||
|
</Text>
|
||||||
|
<Text>
|
||||||
|
I believe in a privacy-first, information-focussed and performant internet. You won't find any trackers, analytics or the need for a cookie consent policy here.
|
||||||
|
</Text>
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
@page "/not-found"
|
@page "/not-found"
|
||||||
@layout MainLayout
|
|
||||||
|
|
||||||
<h3>Not Found</h3>
|
<PageTitle>Beau Findlay - Not Found</PageTitle>
|
||||||
<p>Sorry, the content you are looking for does not exist.</p>
|
|
||||||
|
<main class="grid min-h-full place-items-center px-6 py-24 sm:py-32 lg:px-8">
|
||||||
|
<div class="text-center">
|
||||||
|
<p class="text-base font-semibold">404</p>
|
||||||
|
<h1 class="mt-4 text-4xl font-bold tracking-tight">
|
||||||
|
Page not found
|
||||||
|
</h1>
|
||||||
|
<p class="mt-6 text-base leading-7">Sorry, this page doesn't exist.</p>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
@page "/weather"
|
|
||||||
@attribute [StreamRendering]
|
|
||||||
|
|
||||||
<PageTitle>Weather</PageTitle>
|
|
||||||
|
|
||||||
<h1>Weather</h1>
|
|
||||||
|
|
||||||
<p>This component demonstrates showing data.</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()
|
|
||||||
{
|
|
||||||
// Simulate asynchronous loading to demonstrate streaming rendering
|
|
||||||
await Task.Delay(500);
|
|
||||||
|
|
||||||
var startDate = DateOnly.FromDateTime(DateTime.Now);
|
|
||||||
var summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" };
|
|
||||||
forecasts = Enumerable.Range(1, 5).Select(index => new WeatherForecast
|
|
||||||
{
|
|
||||||
Date = startDate.AddDays(index),
|
|
||||||
TemperatureC = Random.Shared.Next(-20, 55),
|
|
||||||
Summary = summaries[Random.Shared.Next(summaries.Length)]
|
|
||||||
}).ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
private 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
<Router AppAssembly="typeof(Program).Assembly" NotFoundPage="typeof(Pages.NotFound)">
|
@using BlazorApp.Components.Pages
|
||||||
|
<Router AppAssembly="typeof(Program).Assembly"
|
||||||
|
NotFoundPage="typeof(NotFound)">
|
||||||
<Found Context="routeData">
|
<Found Context="routeData">
|
||||||
<RouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)" />
|
<RouteView RouteData="routeData"
|
||||||
<FocusOnNavigate RouteData="routeData" Selector="h1" />
|
DefaultLayout="typeof(MainLayout)"/>
|
||||||
</Found>
|
</Found>
|
||||||
</Router>
|
</Router>
|
||||||
|
|||||||
17
src/BlazorApp/Components/Typography/Subtitle/Subtitle.razor
Normal file
17
src/BlazorApp/Components/Typography/Subtitle/Subtitle.razor
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
@* H2 heading component *@
|
||||||
|
|
||||||
|
<h2 class="@CombinedClasses">@ChildContent</h2>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public RenderFragment? ChildContent { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string? CssClass { get; set; }
|
||||||
|
|
||||||
|
private string CombinedClasses => string.IsNullOrEmpty(CssClass)
|
||||||
|
? "flex items-center text-2xl py-4 font-semibold"
|
||||||
|
: $"flex items-center text-2xl py-4 font-semibold {CssClass}";
|
||||||
|
|
||||||
|
}
|
||||||
17
src/BlazorApp/Components/Typography/Text/Text.razor
Normal file
17
src/BlazorApp/Components/Typography/Text/Text.razor
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
@* Paragraph component *@
|
||||||
|
|
||||||
|
<p class="@CombinedClasses">@ChildContent</p>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public RenderFragment? ChildContent { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string? CssClass { get; set; }
|
||||||
|
|
||||||
|
private string CombinedClasses => string.IsNullOrEmpty(CssClass)
|
||||||
|
? "text-paragraph"
|
||||||
|
: $"text-paragraph {CssClass}";
|
||||||
|
|
||||||
|
}
|
||||||
17
src/BlazorApp/Components/Typography/Title/Title.razor
Normal file
17
src/BlazorApp/Components/Typography/Title/Title.razor
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
@* H1 heading component *@
|
||||||
|
|
||||||
|
<h1 class="@CombinedClasses">@ChildContent</h1>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public RenderFragment? ChildContent { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string? CssClass { get; set; }
|
||||||
|
|
||||||
|
private string CombinedClasses => string.IsNullOrEmpty(CssClass)
|
||||||
|
? "text-4xl py-4"
|
||||||
|
: $"text-4xl py-4 {CssClass}";
|
||||||
|
|
||||||
|
}
|
||||||
@@ -9,3 +9,9 @@
|
|||||||
@using BlazorApp
|
@using BlazorApp
|
||||||
@using BlazorApp.Components
|
@using BlazorApp.Components
|
||||||
@using BlazorApp.Components.Layout
|
@using BlazorApp.Components.Layout
|
||||||
|
@using BlazorApp.Components.Icons
|
||||||
|
@using BlazorApp.Components.AnchorLink
|
||||||
|
@using BlazorApp.Components.Contact
|
||||||
|
@using BlazorApp.Components.Typography.Title
|
||||||
|
@using BlazorApp.Components.Typography.Subtitle
|
||||||
|
@using BlazorApp.Components.Typography.Text
|
||||||
@@ -10,10 +10,11 @@ var app = builder.Build();
|
|||||||
// Configure the HTTP request pipeline.
|
// Configure the HTTP request pipeline.
|
||||||
if (!app.Environment.IsDevelopment())
|
if (!app.Environment.IsDevelopment())
|
||||||
{
|
{
|
||||||
app.UseExceptionHandler("/Error", createScopeForErrors: true);
|
app.UseExceptionHandler("/Error", true);
|
||||||
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
||||||
app.UseHsts();
|
app.UseHsts();
|
||||||
}
|
}
|
||||||
|
|
||||||
app.UseStatusCodePagesWithReExecute("/not-found", createScopeForStatusCodePages: true);
|
app.UseStatusCodePagesWithReExecute("/not-found", createScopeForStatusCodePages: true);
|
||||||
app.UseHttpsRedirection();
|
app.UseHttpsRedirection();
|
||||||
|
|
||||||
@@ -22,4 +23,4 @@ app.UseAntiforgery();
|
|||||||
app.MapStaticAssets();
|
app.MapStaticAssets();
|
||||||
app.MapRazorComponents<App>();
|
app.MapRazorComponents<App>();
|
||||||
|
|
||||||
app.Run();
|
app.Run();
|
||||||
@@ -1,23 +1,23 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/launchsettings.json",
|
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||||
"profiles": {
|
"profiles": {
|
||||||
"http": {
|
"http": {
|
||||||
"commandName": "Project",
|
"commandName": "Project",
|
||||||
"dotnetRunMessages": true,
|
"dotnetRunMessages": true,
|
||||||
"launchBrowser": true,
|
"launchBrowser": true,
|
||||||
"applicationUrl": "http://localhost:5064",
|
"applicationUrl": "http://localhost:5064",
|
||||||
"environmentVariables": {
|
"environmentVariables": {
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"https": {
|
"https": {
|
||||||
"commandName": "Project",
|
"commandName": "Project",
|
||||||
"dotnetRunMessages": true,
|
"dotnetRunMessages": true,
|
||||||
"launchBrowser": true,
|
"launchBrowser": true,
|
||||||
"applicationUrl": "https://localhost:7162;http://localhost:5064",
|
"applicationUrl": "https://localhost:7162;http://localhost:5064",
|
||||||
"environmentVariables": {
|
"environmentVariables": {
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,109 +2,109 @@
|
|||||||
|
|
||||||
/* Fade In */
|
/* Fade In */
|
||||||
.fade-in {
|
.fade-in {
|
||||||
animation: fadeInAnimation ease 1s;
|
animation: fadeInAnimation ease 1s;
|
||||||
animation-iteration-count: 1;
|
animation-iteration-count: 1;
|
||||||
animation-fill-mode: forwards;
|
animation-fill-mode: forwards;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes fadeInAnimation {
|
@keyframes fadeInAnimation {
|
||||||
from {
|
from {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
to {
|
to {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Slide */
|
/* Slide */
|
||||||
@keyframes slideInRight {
|
@keyframes slideInRight {
|
||||||
from {
|
from {
|
||||||
transform: translateX(100%);
|
transform: translateX(100%);
|
||||||
}
|
}
|
||||||
to {
|
to {
|
||||||
transform: translateX(0);
|
transform: translateX(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes slideOutRight {
|
@keyframes slideOutRight {
|
||||||
from {
|
from {
|
||||||
transform: translateX(0);
|
transform: translateX(0);
|
||||||
}
|
}
|
||||||
to {
|
to {
|
||||||
transform: translateX(100%);
|
transform: translateX(100%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes fadeInUp {
|
@keyframes fadeInUp {
|
||||||
from {
|
from {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateY(20px);
|
transform: translateY(20px);
|
||||||
}
|
}
|
||||||
to {
|
to {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.fade-in-up {
|
.fade-in-up {
|
||||||
animation: fadeInUp var(--transition-slow) var(--transition-timing);
|
animation: fadeInUp var(--transition-slow) var(--transition-timing);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Spinner */
|
/* Spinner */
|
||||||
.spinner {
|
.spinner {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 24px;
|
width: 24px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
border: 3px solid var(--color-slate-700);
|
border: 3px solid var(--color-slate-700);
|
||||||
border-top-color: var(--color-slate-50);
|
border-top-color: var(--color-slate-50);
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
animation: spin 0.8s linear infinite;
|
animation: spin 0.8s linear infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes spin {
|
@keyframes spin {
|
||||||
to {
|
to {
|
||||||
transform: rotate(360deg);
|
transform: rotate(360deg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pulse */
|
/* Pulse */
|
||||||
.pulse {
|
.pulse {
|
||||||
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes pulse {
|
@keyframes pulse {
|
||||||
0%, 100% {
|
0%, 100% {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
50% {
|
50% {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Transitions */
|
/* Transitions */
|
||||||
.transition {
|
.transition {
|
||||||
transition: all var(--transition-base) var(--transition-timing);
|
transition: all var(--transition-base) var(--transition-timing);
|
||||||
}
|
}
|
||||||
|
|
||||||
.transition-colors {
|
.transition-colors {
|
||||||
transition: color var(--transition-base) var(--transition-timing),
|
transition: color var(--transition-base) var(--transition-timing),
|
||||||
background-color var(--transition-base) var(--transition-timing),
|
background-color var(--transition-base) var(--transition-timing),
|
||||||
border-color var(--transition-base) var(--transition-timing);
|
border-color var(--transition-base) var(--transition-timing);
|
||||||
}
|
}
|
||||||
|
|
||||||
.transition-transform {
|
.transition-transform {
|
||||||
transition: transform var(--transition-base) var(--transition-timing);
|
transition: transform var(--transition-base) var(--transition-timing);
|
||||||
}
|
}
|
||||||
|
|
||||||
.transition-opacity {
|
.transition-opacity {
|
||||||
transition: opacity var(--transition-base) var(--transition-timing);
|
transition: opacity var(--transition-base) var(--transition-timing);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Hover */
|
/* Hover */
|
||||||
.hover-scale:hover {
|
.hover-scale:hover {
|
||||||
transform: scale(1.05);
|
transform: scale(1.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
.hover-lift:hover {
|
.hover-lift:hover {
|
||||||
transform: translateY(-2px);
|
transform: translateY(-2px);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
@import url('variables.css');
|
@import url('variables.css');
|
||||||
@import url('reset.css');
|
@import url('reset.css');
|
||||||
@import url('base.css');
|
@import url('base.css');
|
||||||
|
@import url('utilities.css');
|
||||||
@import url('layout.css');
|
@import url('layout.css');
|
||||||
@import url('components.css');
|
@import url('components.css');
|
||||||
@import url('animations.css');
|
@import url('animations.css');
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
/* Base Styles */
|
/* Base Styles */
|
||||||
|
|
||||||
body {
|
body {
|
||||||
background-color: var(--color-black);
|
background-color: var(--color-black);
|
||||||
color: var(--color-slate-50);
|
color: var(--color-slate-50);
|
||||||
font-family: var(--font-mono);
|
font-family: var(--font-mono);
|
||||||
font-size: var(--font-size-base);
|
font-size: var(--font-size-base);
|
||||||
line-height: var(--line-height-normal);
|
line-height: var(--line-height-normal);
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Typography */
|
/* Typography */
|
||||||
@@ -15,76 +17,78 @@ h3,
|
|||||||
h4,
|
h4,
|
||||||
h5,
|
h5,
|
||||||
h6 {
|
h6 {
|
||||||
font-weight: var(--font-weight-semibold);
|
font-weight: var(--font-weight-semibold);
|
||||||
line-height: var(--line-height-tight);
|
line-height: var(--line-height-tight);
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
font-size: var(--font-size-3xl);
|
font-size: var(--font-size-3xl);
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
font-size: var(--font-size-2xl);
|
font-size: var(--font-size-2xl);
|
||||||
}
|
}
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
font-size: var(--font-size-xl);
|
font-size: var(--font-size-xl);
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
margin-bottom: var(--space-4);
|
margin-bottom: var(--space-4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Links */
|
/* Links */
|
||||||
a {
|
a {
|
||||||
color: var(--color-slate-50);
|
color: var(--color-slate-50);
|
||||||
transition: color var(--transition-base) var(--transition-timing);
|
display: inline-block;
|
||||||
|
transition: transform var(--transition-base) var(--transition-timing);
|
||||||
}
|
}
|
||||||
|
|
||||||
a:hover {
|
a:hover {
|
||||||
color: var(--color-slate-300);
|
transform: translateY(2px);
|
||||||
|
color: var(--color-slate-50);
|
||||||
}
|
}
|
||||||
|
|
||||||
a:focus-visible {
|
a:focus-visible {
|
||||||
outline: 2px solid var(--color-slate-50);
|
outline: 2px solid var(--color-slate-50);
|
||||||
outline-offset: 2px;
|
outline-offset: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Focus */
|
/* Focus */
|
||||||
*:focus-visible {
|
*:focus-visible {
|
||||||
outline: 2px solid var(--color-slate-50);
|
outline: 2px solid var(--color-slate-50);
|
||||||
outline-offset: 2px;
|
outline-offset: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
button:focus-visible,
|
button:focus-visible,
|
||||||
input:focus-visible,
|
input:focus-visible,
|
||||||
textarea:focus-visible,
|
textarea:focus-visible,
|
||||||
select:focus-visible {
|
select:focus-visible {
|
||||||
outline: 2px solid var(--color-slate-50);
|
outline: 2px solid var(--color-slate-50);
|
||||||
outline-offset: 2px;
|
outline-offset: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Selection */
|
/* Selection */
|
||||||
::selection {
|
::selection {
|
||||||
background-color: var(--color-slate-50);
|
background-color: var(--color-slate-50);
|
||||||
color: var(--color-black);
|
color: var(--color-black);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Scrollbar */
|
/* Scrollbar */
|
||||||
body::-webkit-scrollbar {
|
body::-webkit-scrollbar {
|
||||||
width: 10px;
|
width: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
body::-webkit-scrollbar-track {
|
body::-webkit-scrollbar-track {
|
||||||
background: var(--color-white);
|
background: var(--color-white);
|
||||||
}
|
}
|
||||||
|
|
||||||
body::-webkit-scrollbar-thumb {
|
body::-webkit-scrollbar-thumb {
|
||||||
background-color: var(--color-black);
|
background-color: var(--color-black);
|
||||||
border: 1px solid var(--color-white);
|
border: 1px solid var(--color-white);
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
scrollbar-width: thin;
|
scrollbar-width: thin;
|
||||||
scrollbar-color: var(--color-black) var(--color-white);
|
scrollbar-color: var(--color-black) var(--color-white);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,213 +2,598 @@
|
|||||||
|
|
||||||
/* Buttons */
|
/* Buttons */
|
||||||
.btn {
|
.btn {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: var(--space-3) var(--space-6);
|
padding: var(--space-3) var(--space-6);
|
||||||
font-weight: var(--font-weight-medium);
|
font-weight: var(--font-weight-medium);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border-radius: var(--radius-md);
|
border-radius: var(--radius-md);
|
||||||
transition: all var(--transition-base) var(--transition-timing);
|
transition: all var(--transition-base) var(--transition-timing);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn:focus-visible {
|
.btn:focus-visible {
|
||||||
outline: 2px solid var(--color-slate-50);
|
outline: 2px solid var(--color-slate-50);
|
||||||
outline-offset: 2px;
|
outline-offset: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-primary {
|
.btn-primary {
|
||||||
background-color: var(--color-slate-50);
|
background-color: var(--color-slate-50);
|
||||||
color: var(--color-black);
|
color: var(--color-black);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-primary:hover {
|
.btn-primary:hover {
|
||||||
background-color: var(--color-slate-200);
|
background-color: var(--color-slate-200);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-secondary {
|
.btn-secondary {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
color: var(--color-slate-50);
|
color: var(--color-slate-50);
|
||||||
border: 1px solid var(--color-slate-50);
|
border: 1px solid var(--color-slate-50);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-secondary:hover {
|
.btn-secondary:hover {
|
||||||
background-color: var(--color-slate-50);
|
background-color: var(--color-slate-50);
|
||||||
color: var(--color-black);
|
color: var(--color-black);
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn:disabled {
|
.btn:disabled {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Inputs */
|
/* Inputs */
|
||||||
.input {
|
.input {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: var(--space-3);
|
padding: var(--space-3);
|
||||||
background-color: var(--color-black);
|
background-color: var(--color-black);
|
||||||
border: 1px solid var(--color-slate-700);
|
border: 1px solid var(--color-slate-700);
|
||||||
border-radius: var(--radius-md);
|
border-radius: var(--radius-md);
|
||||||
color: var(--color-slate-50);
|
color: var(--color-slate-50);
|
||||||
font-size: var(--font-size-base);
|
font-size: var(--font-size-base);
|
||||||
}
|
}
|
||||||
|
|
||||||
.input:focus {
|
.input:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
border-color: var(--color-slate-50);
|
border-color: var(--color-slate-50);
|
||||||
}
|
}
|
||||||
|
|
||||||
.input:invalid {
|
.input:invalid {
|
||||||
border-color: #ef4444;
|
border-color: #ef4444;
|
||||||
}
|
}
|
||||||
|
|
||||||
.input::placeholder {
|
.input::placeholder {
|
||||||
color: var(--color-slate-500);
|
color: var(--color-slate-500);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Textareas */
|
/* Textareas */
|
||||||
.textarea {
|
.textarea {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: var(--space-3);
|
padding: var(--space-3);
|
||||||
background-color: var(--color-black);
|
background-color: var(--color-black);
|
||||||
border: 1px solid var(--color-slate-700);
|
border: 1px solid var(--color-slate-700);
|
||||||
border-radius: var(--radius-md);
|
border-radius: var(--radius-md);
|
||||||
color: var(--color-slate-50);
|
color: var(--color-slate-50);
|
||||||
font-size: var(--font-size-base);
|
font-size: var(--font-size-base);
|
||||||
resize: vertical;
|
resize: vertical;
|
||||||
min-height: 120px;
|
min-height: 120px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.textarea:focus {
|
.textarea:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
border-color: var(--color-slate-50);
|
border-color: var(--color-slate-50);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Labels */
|
/* Labels */
|
||||||
.label {
|
.label {
|
||||||
display: block;
|
display: block;
|
||||||
margin-bottom: var(--space-2);
|
margin-bottom: var(--space-2);
|
||||||
font-size: var(--font-size-sm);
|
font-size: var(--font-size-sm);
|
||||||
font-weight: var(--font-weight-medium);
|
font-weight: var(--font-weight-medium);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cards */
|
/* Cards */
|
||||||
.card {
|
.card {
|
||||||
background-color: var(--color-slate-900);
|
background-color: var(--color-slate-900);
|
||||||
border-radius: var(--radius-lg);
|
border-radius: var(--radius-lg);
|
||||||
padding: var(--space-6);
|
padding: var(--space-6);
|
||||||
border: 1px solid var(--color-slate-800);
|
border: 1px solid var(--color-slate-800);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Navigation */
|
/* NavBar */
|
||||||
.nav {
|
.navbar header {
|
||||||
display: flex;
|
padding-top: var(--space-6);
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
padding: var(--space-6) 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-link {
|
.navbar nav {
|
||||||
padding: var(--space-2) var(--space-4);
|
margin-left: auto;
|
||||||
color: var(--color-slate-50);
|
margin-right: auto;
|
||||||
font-size: var(--font-size-sm);
|
display: flex;
|
||||||
transition: color var(--transition-base) var(--transition-timing);
|
max-width: 80rem;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-link:hover {
|
.navbar .logo-container {
|
||||||
color: var(--color-slate-300);
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-link-active {
|
.navbar .logo-link {
|
||||||
font-weight: var(--font-weight-semibold);
|
margin: -0.375rem;
|
||||||
|
padding: 0.375rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Footer */
|
.navbar .logo-link img {
|
||||||
.footer {
|
height: 4rem;
|
||||||
padding: var(--space-8) 0;
|
width: auto;
|
||||||
margin-top: auto;
|
}
|
||||||
border-top: 1px solid var(--color-slate-800);
|
|
||||||
text-align: center;
|
.navbar .mobile-menu-button-container {
|
||||||
font-size: var(--font-size-sm);
|
display: flex;
|
||||||
color: var(--color-slate-400);
|
}
|
||||||
|
|
||||||
|
.navbar .menu-button {
|
||||||
|
margin: -0.625rem;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
padding: 0.625rem;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar .menu-button svg {
|
||||||
|
height: 1.5rem;
|
||||||
|
width: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar .desktop-nav {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar .desktop-nav a {
|
||||||
|
font-size: var(--font-size-sm);
|
||||||
|
font-weight: var(--font-weight-semibold);
|
||||||
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mobile Menu (CSS-only) */
|
/* Mobile Menu (CSS-only) */
|
||||||
.mobile-menu-toggle {
|
.menu-toggle {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
|
||||||
|
|
||||||
.mobile-menu-button {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: var(--font-size-2xl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobile-menu-overlay {
|
.mobile-menu-overlay {
|
||||||
display: none;
|
display: none;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
background-color: rgba(0, 0, 0, 0.5);
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
backdrop-filter: blur(4px);
|
backdrop-filter: blur(4px);
|
||||||
z-index: var(--z-overlay);
|
z-index: var(--z-overlay);
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobile-menu {
|
.menu-toggle:checked ~ .mobile-menu-overlay {
|
||||||
display: none;
|
display: block;
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
width: 80%;
|
|
||||||
max-width: 300px;
|
|
||||||
background-color: var(--color-black);
|
|
||||||
border-left: 1px solid var(--color-slate-800);
|
|
||||||
padding: var(--space-6);
|
|
||||||
z-index: var(--z-modal);
|
|
||||||
transform: translateX(100%);
|
|
||||||
transition: transform var(--transition-slow) var(--transition-timing);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobile-menu-toggle:checked ~ .mobile-menu-overlay {
|
.mobile-menu-content {
|
||||||
display: block;
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: var(--z-modal);
|
||||||
|
background-color: var(--color-black);
|
||||||
|
width: 100%;
|
||||||
|
padding: var(--space-6);
|
||||||
|
color: white;
|
||||||
|
transform: translateX(100%);
|
||||||
|
transition: transform var(--transition-slow) var(--transition-timing);
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobile-menu-toggle:checked ~ .mobile-menu {
|
.menu-toggle:checked ~ .mobile-menu-content {
|
||||||
display: block;
|
display: block;
|
||||||
transform: translateX(0);
|
transform: translateX(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobile-menu-close {
|
.mobile-menu-inner {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
flex-direction: column;
|
||||||
margin-bottom: var(--space-6);
|
height: 100%;
|
||||||
font-size: var(--font-size-2xl);
|
}
|
||||||
cursor: pointer;
|
|
||||||
|
.mobile-menu-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-button {
|
||||||
|
margin: -0.625rem;
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
padding: 0.625rem;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-button svg {
|
||||||
|
height: 1.5rem;
|
||||||
|
width: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-menu-body {
|
||||||
|
margin-top: var(--space-6);
|
||||||
|
flex: 1 1 0%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-nav-links {
|
||||||
|
margin-top: var(--space-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-nav-links a {
|
||||||
|
margin-left: -0.75rem;
|
||||||
|
margin-right: -0.75rem;
|
||||||
|
display: block;
|
||||||
|
border-radius: var(--radius-lg);
|
||||||
|
padding: 0.75rem;
|
||||||
|
padding-top: var(--space-2);
|
||||||
|
padding-bottom: var(--space-2);
|
||||||
|
font-size: var(--font-size-base);
|
||||||
|
font-weight: var(--font-weight-semibold);
|
||||||
|
line-height: 1.75;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-social-divider {
|
||||||
|
border-top: 1px solid rgba(226, 232, 240, 0.1);
|
||||||
|
padding-top: var(--space-8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-social-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prevent body scroll when mobile menu is open */
|
||||||
|
.menu-toggle:checked ~ * {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
body:has(.menu-toggle:checked) {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 640px) {
|
||||||
|
.mobile-menu-content {
|
||||||
|
max-width: 24rem;
|
||||||
|
box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.1);
|
||||||
|
border-left: 2px solid var(--color-slate-800);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
.navbar .logo-container {
|
||||||
|
flex: 1 1 0%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar .mobile-menu-button-container {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar .desktop-nav {
|
||||||
|
display: flex;
|
||||||
|
column-gap: var(--space-12);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-menu-content {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Footer */
|
||||||
|
.page-footer footer {
|
||||||
|
margin-top: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-footer .footer-container {
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
padding-top: var(--space-8);
|
||||||
|
padding-bottom: var(--space-8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-footer .footer-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--space-4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-footer .footer-text {
|
||||||
|
font-size: var(--font-size-xs);
|
||||||
|
line-height: 1.25;
|
||||||
|
color: var(--color-slate-50);
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.page-footer .footer-content {
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-footer .footer-text {
|
||||||
|
order: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Social Icons */
|
||||||
|
.social-icons-container {
|
||||||
|
display: flex;
|
||||||
|
gap: var(--space-6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.social-icon-link {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-width: 40px;
|
||||||
|
min-height: 40px;
|
||||||
|
color: var(--color-slate-50);
|
||||||
|
transition: transform var(--transition-base) var(--transition-timing);
|
||||||
|
}
|
||||||
|
|
||||||
|
.social-icon-link svg {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.social-icon-link:hover {
|
||||||
|
transform: translateY(2px);
|
||||||
|
color: var(--color-slate-50);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.social-icons-container {
|
||||||
|
order: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.social-icon-link {
|
||||||
|
min-width: auto;
|
||||||
|
min-height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.social-icon-link svg {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tech Icons */
|
||||||
|
.tech-icons-wrapper {
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
max-width: 64rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tech-icons-title {
|
||||||
|
font-size: var(--font-size-xl);
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: var(--space-10);
|
||||||
|
font-weight: var(--font-weight-semibold);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tech-icons-grid {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--space-6);
|
||||||
|
text-align: center;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
margin-top: var(--space-4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tech-icon-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tech-icon-item svg {
|
||||||
|
width: 34px;
|
||||||
|
height: 34px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tech-icon-item p {
|
||||||
|
margin-top: var(--space-2);
|
||||||
|
font-size: var(--font-size-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.tech-icons-grid {
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
gap: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* AboutTabs */
|
||||||
|
.tabs-subtitle {
|
||||||
|
font-weight: var(--font-weight-bold);
|
||||||
|
font-size: var(--font-size-lg);
|
||||||
|
margin-top: var(--space-4);
|
||||||
|
margin-bottom: var(--space-4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Contact Section */
|
||||||
|
.contact-section {
|
||||||
|
margin-bottom: var(--space-10);
|
||||||
|
margin-top: var(--space-12);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-button {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: var(--space-2);
|
||||||
|
border: 1px solid var(--color-slate-700);
|
||||||
|
background-color: var(--color-black);
|
||||||
|
padding: 0.625rem 0.875rem;
|
||||||
|
margin-top: var(--space-2);
|
||||||
|
font-size: var(--font-size-sm);
|
||||||
|
font-weight: var(--font-weight-semibold);
|
||||||
|
color: var(--color-slate-50);
|
||||||
|
transition: transform var(--transition-base) var(--transition-timing);
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-button:hover {
|
||||||
|
transform: translateY(2px);
|
||||||
|
color: var(--color-slate-50);
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-button:focus-visible {
|
||||||
|
outline: 2px solid var(--color-slate-50);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-button svg {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Text Paragraph */
|
||||||
|
.text-paragraph {
|
||||||
|
font-size: var(--font-size-lg);
|
||||||
|
padding-top: var(--space-4);
|
||||||
|
padding-bottom: var(--space-4);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.text-paragraph {
|
||||||
|
padding-top: var(--space-2);
|
||||||
|
padding-bottom: var(--space-2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Links */
|
/* Links */
|
||||||
.link {
|
.link {
|
||||||
color: var(--color-slate-50);
|
color: var(--color-slate-50);
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
text-underline-offset: 2px;
|
text-underline-offset: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.link:hover {
|
.link:hover {
|
||||||
color: var(--color-slate-300);
|
color: var(--color-slate-300);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Icon Buttons */
|
/* Icon Buttons */
|
||||||
.icon-button {
|
.icon-button {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: var(--space-2);
|
padding: var(--space-2);
|
||||||
transition: opacity var(--transition-base) var(--transition-timing);
|
transition: opacity var(--transition-base) var(--transition-timing);
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-button:hover {
|
.icon-button:hover {
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Timeline */
|
||||||
|
.timeline {
|
||||||
|
position: relative;
|
||||||
|
border-left: 1px solid var(--color-slate-600);
|
||||||
|
list-style: none;
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-item {
|
||||||
|
margin-bottom: var(--space-10);
|
||||||
|
margin-left: var(--space-4);
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-marker {
|
||||||
|
position: absolute;
|
||||||
|
width: 0.75rem;
|
||||||
|
height: 0.75rem;
|
||||||
|
background-color: var(--color-slate-600);
|
||||||
|
border-radius: 50%;
|
||||||
|
left: -1.875rem;
|
||||||
|
top: 0.375rem;
|
||||||
|
border: 2px solid var(--color-black);
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-date {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: var(--space-1);
|
||||||
|
font-size: var(--font-size-sm);
|
||||||
|
font-weight: var(--font-weight-normal);
|
||||||
|
line-height: 1;
|
||||||
|
color: var(--color-slate-400);
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-title {
|
||||||
|
font-size: var(--font-size-2xl);
|
||||||
|
font-weight: var(--font-weight-semibold);
|
||||||
|
color: var(--color-slate-50);
|
||||||
|
margin-bottom: var(--space-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tabs (CSS Radio Buttons) */
|
||||||
|
.tabs-container {
|
||||||
|
margin-top: var(--space-4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-radio {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-labels {
|
||||||
|
display: flex;
|
||||||
|
gap: var(--space-8);
|
||||||
|
border-bottom: 1px solid var(--color-slate-700);
|
||||||
|
margin-bottom: var(--space-10);
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-label {
|
||||||
|
padding: var(--space-6) 0;
|
||||||
|
font-size: var(--font-size-sm);
|
||||||
|
font-weight: var(--font-weight-medium);
|
||||||
|
color: var(--color-slate-400);
|
||||||
|
border-bottom: 4px solid transparent;
|
||||||
|
margin-bottom: -1px;
|
||||||
|
cursor: pointer;
|
||||||
|
white-space: nowrap;
|
||||||
|
transition: all var(--transition-base) var(--transition-timing);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-label:hover {
|
||||||
|
color: var(--color-slate-200);
|
||||||
|
border-bottom-color: var(--color-slate-700);
|
||||||
|
}
|
||||||
|
|
||||||
|
#tab0:checked ~ .tab-labels label[for="tab0"],
|
||||||
|
#tab1:checked ~ .tab-labels label[for="tab1"],
|
||||||
|
#tab2:checked ~ .tab-labels label[for="tab2"],
|
||||||
|
#tab3:checked ~ .tab-labels label[for="tab3"] {
|
||||||
|
color: var(--color-slate-200);
|
||||||
|
border-bottom-color: var(--color-slate-300);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-panel {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tab0:checked ~ .tab-panels #panel0,
|
||||||
|
#tab1:checked ~ .tab-panels #panel1,
|
||||||
|
#tab2:checked ~ .tab-panels #panel2,
|
||||||
|
#tab3:checked ~ .tab-panels #panel3 {
|
||||||
|
display: block;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,239 +2,17 @@
|
|||||||
|
|
||||||
/* Container */
|
/* Container */
|
||||||
.container {
|
.container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: var(--container-max-width);
|
max-width: var(--container-max-width);
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
padding-left: var(--space-6);
|
padding-left: var(--space-6);
|
||||||
padding-right: var(--space-6);
|
padding-right: var(--space-6);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 1024px) {
|
@media (min-width: 1024px) {
|
||||||
.container {
|
.container {
|
||||||
padding-left: var(--space-10);
|
padding-left: var(--space-10);
|
||||||
padding-right: var(--space-10);
|
padding-right: var(--space-10);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Flexbox */
|
|
||||||
.flex {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.flex-col {
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.flex-row {
|
|
||||||
flex-direction: row;
|
|
||||||
}
|
|
||||||
|
|
||||||
.flex-1 {
|
|
||||||
flex: 1 1 0%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.items-start {
|
|
||||||
align-items: flex-start;
|
|
||||||
}
|
|
||||||
|
|
||||||
.items-center {
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.items-end {
|
|
||||||
align-items: flex-end;
|
|
||||||
}
|
|
||||||
|
|
||||||
.justify-start {
|
|
||||||
justify-content: flex-start;
|
|
||||||
}
|
|
||||||
|
|
||||||
.justify-center {
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.justify-end {
|
|
||||||
justify-content: flex-end;
|
|
||||||
}
|
|
||||||
|
|
||||||
.justify-between {
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.gap-1 {
|
|
||||||
gap: var(--space-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.gap-2 {
|
|
||||||
gap: var(--space-2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.gap-3 {
|
|
||||||
gap: var(--space-3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.gap-4 {
|
|
||||||
gap: var(--space-4);
|
|
||||||
}
|
|
||||||
|
|
||||||
.gap-6 {
|
|
||||||
gap: var(--space-6);
|
|
||||||
}
|
|
||||||
|
|
||||||
.gap-8 {
|
|
||||||
gap: var(--space-8);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Grid */
|
|
||||||
.grid {
|
|
||||||
display: grid;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-cols-1 {
|
|
||||||
grid-template-columns: repeat(1, minmax(0, 1fr));
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-cols-2 {
|
|
||||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-cols-3 {
|
|
||||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-cols-4 {
|
|
||||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 640px) {
|
|
||||||
.sm\:grid-cols-2 {
|
|
||||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
||||||
}
|
|
||||||
.sm\:grid-cols-3 {
|
|
||||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
|
||||||
.md\:grid-cols-3 {
|
|
||||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
||||||
}
|
|
||||||
.md\:grid-cols-4 {
|
|
||||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 1024px) {
|
|
||||||
.lg\:grid-cols-4 {
|
|
||||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
||||||
}
|
|
||||||
.lg\:grid-cols-5 {
|
|
||||||
grid-template-columns: repeat(5, minmax(0, 1fr));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Spacing */
|
|
||||||
.min-h-screen {
|
|
||||||
min-height: 100vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
.p-2 { padding: var(--space-2); }
|
|
||||||
.p-4 { padding: var(--space-4); }
|
|
||||||
.p-6 { padding: var(--space-6); }
|
|
||||||
.p-8 { padding: var(--space-8); }
|
|
||||||
|
|
||||||
.px-2 { padding-left: var(--space-2); padding-right: var(--space-2); }
|
|
||||||
.px-4 { padding-left: var(--space-4); padding-right: var(--space-4); }
|
|
||||||
.px-6 { padding-left: var(--space-6); padding-right: var(--space-6); }
|
|
||||||
.px-8 { padding-left: var(--space-8); padding-right: var(--space-8); }
|
|
||||||
|
|
||||||
.py-2 { padding-top: var(--space-2); padding-bottom: var(--space-2); }
|
|
||||||
.py-4 { padding-top: var(--space-4); padding-bottom: var(--space-4); }
|
|
||||||
.py-6 { padding-top: var(--space-6); padding-bottom: var(--space-6); }
|
|
||||||
.py-8 { padding-top: var(--space-8); padding-bottom: var(--space-8); }
|
|
||||||
|
|
||||||
.m-2 { margin: var(--space-2); }
|
|
||||||
.m-4 { margin: var(--space-4); }
|
|
||||||
.m-6 { margin: var(--space-6); }
|
|
||||||
.m-8 { margin: var(--space-8); }
|
|
||||||
|
|
||||||
.mx-auto { margin-left: auto; margin-right: auto; }
|
|
||||||
|
|
||||||
.mt-2 { margin-top: var(--space-2); }
|
|
||||||
.mt-4 { margin-top: var(--space-4); }
|
|
||||||
.mt-6 { margin-top: var(--space-6); }
|
|
||||||
.mt-8 { margin-top: var(--space-8); }
|
|
||||||
|
|
||||||
.mb-2 { margin-bottom: var(--space-2); }
|
|
||||||
.mb-4 { margin-bottom: var(--space-4); }
|
|
||||||
.mb-6 { margin-bottom: var(--space-6); }
|
|
||||||
.mb-8 { margin-bottom: var(--space-8); }
|
|
||||||
|
|
||||||
/* Display */
|
|
||||||
.hidden {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.block {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.inline-block {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Responsive */
|
|
||||||
@media (min-width: 1024px) {
|
|
||||||
.lg\:flex {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
.lg\:hidden {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.lg\:block {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Widths */
|
|
||||||
.w-full {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.max-w-sm {
|
|
||||||
max-width: 24rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.max-w-md {
|
|
||||||
max-width: 28rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.max-w-lg {
|
|
||||||
max-width: 32rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.max-w-xl {
|
|
||||||
max-width: 36rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.max-w-2xl {
|
|
||||||
max-width: 42rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.max-w-7xl {
|
|
||||||
max-width: 80rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Text */
|
|
||||||
.text-center {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-left {
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-right {
|
|
||||||
text-align: right;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,30 +3,30 @@
|
|||||||
*,
|
*,
|
||||||
*::before,
|
*::before,
|
||||||
*::after {
|
*::after {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
-webkit-text-size-adjust: 100%;
|
-webkit-text-size-adjust: 100%;
|
||||||
-moz-tab-size: 4;
|
-moz-tab-size: 4;
|
||||||
tab-size: 4;
|
tab-size: 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
html:focus-within {
|
html:focus-within {
|
||||||
scroll-behavior: smooth;
|
scroll-behavior: smooth;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
text-rendering: optimizeSpeed;
|
text-rendering: optimizeSpeed;
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
img,
|
img,
|
||||||
@@ -34,44 +34,44 @@ picture,
|
|||||||
video,
|
video,
|
||||||
canvas,
|
canvas,
|
||||||
svg {
|
svg {
|
||||||
display: block;
|
display: block;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
input,
|
input,
|
||||||
button,
|
button,
|
||||||
textarea,
|
textarea,
|
||||||
select {
|
select {
|
||||||
font: inherit;
|
font: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
background: none;
|
background: none;
|
||||||
border: none;
|
border: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-reduced-motion: reduce) {
|
@media (prefers-reduced-motion: reduce) {
|
||||||
html:focus-within {
|
html:focus-within {
|
||||||
scroll-behavior: auto;
|
scroll-behavior: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
*,
|
*,
|
||||||
*::before,
|
*::before,
|
||||||
*::after {
|
*::after {
|
||||||
animation-duration: 0.01ms !important;
|
animation-duration: 0.01ms !important;
|
||||||
animation-iteration-count: 1 !important;
|
animation-iteration-count: 1 !important;
|
||||||
transition-duration: 0.01ms !important;
|
transition-duration: 0.01ms !important;
|
||||||
scroll-behavior: auto !important;
|
scroll-behavior: auto !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
641
src/BlazorApp/wwwroot/css/utilities.css
Normal file
641
src/BlazorApp/wwwroot/css/utilities.css
Normal file
@@ -0,0 +1,641 @@
|
|||||||
|
/* Utility Classes */
|
||||||
|
|
||||||
|
/* Display */
|
||||||
|
.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.block {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-block {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-flex {
|
||||||
|
display: inline-flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flow-root {
|
||||||
|
display: flow-root;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Flexbox */
|
||||||
|
.flex {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-col {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-row {
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-1 {
|
||||||
|
flex: 1 1 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.items-start {
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.items-center {
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.items-end {
|
||||||
|
align-items: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.justify-start {
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.justify-center {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.justify-end {
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.justify-between {
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Gap */
|
||||||
|
.gap-1 {
|
||||||
|
gap: var(--space-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.gap-2 {
|
||||||
|
gap: var(--space-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.gap-3 {
|
||||||
|
gap: var(--space-3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.gap-4 {
|
||||||
|
gap: var(--space-4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.gap-6 {
|
||||||
|
gap: var(--space-6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.gap-8 {
|
||||||
|
gap: var(--space-8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Grid */
|
||||||
|
.grid {
|
||||||
|
display: grid;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-cols-1 {
|
||||||
|
grid-template-columns: repeat(1, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-cols-2 {
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-cols-3 {
|
||||||
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-cols-4 {
|
||||||
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.place-items-center {
|
||||||
|
place-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Spacing */
|
||||||
|
.min-h-screen {
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.min-h-full {
|
||||||
|
min-height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-full {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-6 {
|
||||||
|
height: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-16 {
|
||||||
|
height: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-6 {
|
||||||
|
width: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-auto {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-full {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Max Widths */
|
||||||
|
.max-w-sm {
|
||||||
|
max-width: 24rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.max-w-md {
|
||||||
|
max-width: 28rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.max-w-lg {
|
||||||
|
max-width: 32rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.max-w-xl {
|
||||||
|
max-width: 36rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.max-w-2xl {
|
||||||
|
max-width: 42rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.max-w-4xl {
|
||||||
|
max-width: 64rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.max-w-7xl {
|
||||||
|
max-width: 80rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Padding */
|
||||||
|
.p-2 {
|
||||||
|
padding: var(--space-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-4 {
|
||||||
|
padding: var(--space-4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-6 {
|
||||||
|
padding: var(--space-6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-8 {
|
||||||
|
padding: var(--space-8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-1\.5 {
|
||||||
|
padding: 0.375rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-2\.5 {
|
||||||
|
padding: 0.625rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.px-2 {
|
||||||
|
padding-left: var(--space-2);
|
||||||
|
padding-right: var(--space-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.px-3 {
|
||||||
|
padding-left: 0.75rem;
|
||||||
|
padding-right: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.px-4 {
|
||||||
|
padding-left: var(--space-4);
|
||||||
|
padding-right: var(--space-4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.px-6 {
|
||||||
|
padding-left: var(--space-6);
|
||||||
|
padding-right: var(--space-6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.px-8 {
|
||||||
|
padding-left: var(--space-8);
|
||||||
|
padding-right: var(--space-8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.py-2 {
|
||||||
|
padding-top: var(--space-2);
|
||||||
|
padding-bottom: var(--space-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.py-4 {
|
||||||
|
padding-top: var(--space-4);
|
||||||
|
padding-bottom: var(--space-4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.py-6 {
|
||||||
|
padding-top: var(--space-6);
|
||||||
|
padding-bottom: var(--space-6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.py-8 {
|
||||||
|
padding-top: var(--space-8);
|
||||||
|
padding-bottom: var(--space-8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.py-24 {
|
||||||
|
padding-top: 6rem;
|
||||||
|
padding-bottom: 6rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pt-6 {
|
||||||
|
padding-top: var(--space-6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pt-8 {
|
||||||
|
padding-top: var(--space-8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pb-4 {
|
||||||
|
padding-bottom: var(--space-4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Margins */
|
||||||
|
.m-2 {
|
||||||
|
margin: var(--space-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.m-4 {
|
||||||
|
margin: var(--space-4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.m-6 {
|
||||||
|
margin: var(--space-6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.m-8 {
|
||||||
|
margin: var(--space-8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.-m-1\.5 {
|
||||||
|
margin: -0.375rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.-m-2\.5 {
|
||||||
|
margin: -0.625rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx-auto {
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.-mx-3 {
|
||||||
|
margin-left: -0.75rem;
|
||||||
|
margin-right: -0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.-my-6 {
|
||||||
|
margin-top: -1.5rem;
|
||||||
|
margin-bottom: -1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-2 {
|
||||||
|
margin-top: var(--space-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-4 {
|
||||||
|
margin-top: var(--space-4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-6 {
|
||||||
|
margin-top: var(--space-6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-8 {
|
||||||
|
margin-top: var(--space-8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-12 {
|
||||||
|
margin-top: var(--space-12);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-auto {
|
||||||
|
margin-top: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb-2 {
|
||||||
|
margin-bottom: var(--space-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb-4 {
|
||||||
|
margin-bottom: var(--space-4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb-6 {
|
||||||
|
margin-bottom: var(--space-6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb-8 {
|
||||||
|
margin-bottom: var(--space-8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb-10 {
|
||||||
|
margin-bottom: var(--space-10);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb-12 {
|
||||||
|
margin-bottom: var(--space-12);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Space Between */
|
||||||
|
.space-x-6 > * + * {
|
||||||
|
margin-left: var(--space-6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.space-y-2 > * + * {
|
||||||
|
margin-top: var(--space-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.space-y-10 > * + * {
|
||||||
|
margin-top: var(--space-10);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Typography */
|
||||||
|
.text-center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-left {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-right {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-xs {
|
||||||
|
font-size: var(--font-size-xs);
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-sm {
|
||||||
|
font-size: var(--font-size-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-base {
|
||||||
|
font-size: var(--font-size-base);
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-lg {
|
||||||
|
font-size: var(--font-size-lg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-xl {
|
||||||
|
font-size: var(--font-size-xl);
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-2xl {
|
||||||
|
font-size: var(--font-size-2xl);
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-3xl {
|
||||||
|
font-size: var(--font-size-3xl);
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-4xl {
|
||||||
|
font-size: var(--font-size-4xl);
|
||||||
|
}
|
||||||
|
|
||||||
|
.font-normal {
|
||||||
|
font-weight: var(--font-weight-normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
.font-medium {
|
||||||
|
font-weight: var(--font-weight-medium);
|
||||||
|
}
|
||||||
|
|
||||||
|
.font-semibold {
|
||||||
|
font-weight: var(--font-weight-semibold);
|
||||||
|
}
|
||||||
|
|
||||||
|
.font-bold {
|
||||||
|
font-weight: var(--font-weight-bold);
|
||||||
|
}
|
||||||
|
|
||||||
|
.leading-tight {
|
||||||
|
line-height: var(--line-height-tight);
|
||||||
|
}
|
||||||
|
|
||||||
|
.leading-normal {
|
||||||
|
line-height: var(--line-height-normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
.leading-relaxed {
|
||||||
|
line-height: var(--line-height-relaxed);
|
||||||
|
}
|
||||||
|
|
||||||
|
.leading-6 {
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leading-7 {
|
||||||
|
line-height: 1.75;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tracking-tight {
|
||||||
|
letter-spacing: -0.025em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.underline {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.underline-offset-2 {
|
||||||
|
text-underline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.underline-offset-4 {
|
||||||
|
text-underline-offset: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Positioning */
|
||||||
|
.fixed {
|
||||||
|
position: fixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inset-0 {
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inset-y-0 {
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Border */
|
||||||
|
.border-t {
|
||||||
|
border-top: 1px solid rgba(226, 232, 240, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.divide-y > * + * {
|
||||||
|
border-top: 1px solid rgba(226, 232, 240, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rounded-lg {
|
||||||
|
border-radius: var(--radius-lg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rounded-md {
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Z-index */
|
||||||
|
.z-10 {
|
||||||
|
z-index: var(--z-dropdown);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Overflow */
|
||||||
|
.overflow-y-auto {
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cursor */
|
||||||
|
.cursor-pointer {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Screen Reader Only */
|
||||||
|
.sr-only {
|
||||||
|
position: absolute;
|
||||||
|
width: 1px;
|
||||||
|
height: 1px;
|
||||||
|
padding: 0;
|
||||||
|
margin: -1px;
|
||||||
|
overflow: hidden;
|
||||||
|
clip: rect(0, 0, 0, 0);
|
||||||
|
white-space: nowrap;
|
||||||
|
border-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive Utilities */
|
||||||
|
@media (min-width: 640px) {
|
||||||
|
.sm\:max-w-sm {
|
||||||
|
max-width: 24rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm\:ring-1 {
|
||||||
|
box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm\:border-l-2 {
|
||||||
|
border-left: 2px solid var(--color-slate-800);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm\:py-32 {
|
||||||
|
padding-top: 8rem;
|
||||||
|
padding-bottom: 8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm\:grid-cols-2 {
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm\:grid-cols-3 {
|
||||||
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.md\:flex {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md\:flex-row {
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md\:justify-evenly {
|
||||||
|
justify-content: space-evenly;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md\:items-center {
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md\:justify-between {
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md\:order-1 {
|
||||||
|
order: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md\:order-2 {
|
||||||
|
order: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md\:mt-0 {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md\:py-3 {
|
||||||
|
padding-top: var(--space-3);
|
||||||
|
padding-bottom: var(--space-3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.md\:grid-cols-3 {
|
||||||
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.md\:grid-cols-4 {
|
||||||
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
.lg\:flex {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lg\:hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lg\:block {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lg\:px-8 {
|
||||||
|
padding-left: var(--space-8);
|
||||||
|
padding-right: var(--space-8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.lg\:px-10 {
|
||||||
|
padding-left: var(--space-10);
|
||||||
|
padding-right: var(--space-10);
|
||||||
|
}
|
||||||
|
|
||||||
|
.lg\:flex-1 {
|
||||||
|
flex: 1 1 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lg\:gap-x-12 {
|
||||||
|
column-gap: var(--space-12);
|
||||||
|
}
|
||||||
|
|
||||||
|
.lg\:grid-cols-4 {
|
||||||
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.lg\:grid-cols-5 {
|
||||||
|
grid-template-columns: repeat(5, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,97 +1,97 @@
|
|||||||
/* Design Tokens */
|
/* Design Tokens */
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
/* Colors */
|
/* Colors */
|
||||||
--color-black: #000000;
|
--color-black: #000000;
|
||||||
--color-white: #ffffff;
|
--color-white: #ffffff;
|
||||||
--color-slate-50: #f8fafc;
|
--color-slate-50: #f8fafc;
|
||||||
--color-slate-100: #f1f5f9;
|
--color-slate-100: #f1f5f9;
|
||||||
--color-slate-200: #e2e8f0;
|
--color-slate-200: #e2e8f0;
|
||||||
--color-slate-300: #cbd5e1;
|
--color-slate-300: #cbd5e1;
|
||||||
--color-slate-400: #94a3b8;
|
--color-slate-400: #94a3b8;
|
||||||
--color-slate-500: #64748b;
|
--color-slate-500: #64748b;
|
||||||
--color-slate-600: #475569;
|
--color-slate-600: #475569;
|
||||||
--color-slate-700: #334155;
|
--color-slate-700: #334155;
|
||||||
--color-slate-800: #1e293b;
|
--color-slate-800: #1e293b;
|
||||||
--color-slate-900: #0f172a;
|
--color-slate-900: #0f172a;
|
||||||
--color-gray-700: #374151;
|
--color-gray-700: #374151;
|
||||||
--color-gray-800: #1f2937;
|
--color-gray-800: #1f2937;
|
||||||
|
|
||||||
/* Typography */
|
/* Typography */
|
||||||
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||||
--font-size-xs: 0.75rem;
|
--font-size-xs: 0.75rem;
|
||||||
--font-size-sm: 0.875rem;
|
--font-size-sm: 0.875rem;
|
||||||
--font-size-base: 1rem;
|
--font-size-base: 1rem;
|
||||||
--font-size-lg: 1.125rem;
|
--font-size-lg: 1.125rem;
|
||||||
--font-size-xl: 1.25rem;
|
--font-size-xl: 1.25rem;
|
||||||
--font-size-2xl: 1.5rem;
|
--font-size-2xl: 1.5rem;
|
||||||
--font-size-3xl: 1.875rem;
|
--font-size-3xl: 1.875rem;
|
||||||
--font-size-4xl: 2.25rem;
|
--font-size-4xl: 2.25rem;
|
||||||
--font-size-5xl: 3rem;
|
--font-size-5xl: 3rem;
|
||||||
--font-size-6xl: 3.75rem;
|
--font-size-6xl: 3.75rem;
|
||||||
--line-height-tight: 1.25;
|
--line-height-tight: 1.25;
|
||||||
--line-height-normal: 1.5;
|
--line-height-normal: 1.5;
|
||||||
--line-height-relaxed: 1.75;
|
--line-height-relaxed: 1.75;
|
||||||
--font-weight-normal: 400;
|
--font-weight-normal: 400;
|
||||||
--font-weight-medium: 500;
|
--font-weight-medium: 500;
|
||||||
--font-weight-semibold: 600;
|
--font-weight-semibold: 600;
|
||||||
--font-weight-bold: 700;
|
--font-weight-bold: 700;
|
||||||
|
|
||||||
/* Spacing */
|
/* Spacing */
|
||||||
--space-0: 0;
|
--space-0: 0;
|
||||||
--space-1: 0.25rem;
|
--space-1: 0.25rem;
|
||||||
--space-2: 0.5rem;
|
--space-2: 0.5rem;
|
||||||
--space-3: 0.75rem;
|
--space-3: 0.75rem;
|
||||||
--space-4: 1rem;
|
--space-4: 1rem;
|
||||||
--space-5: 1.25rem;
|
--space-5: 1.25rem;
|
||||||
--space-6: 1.5rem;
|
--space-6: 1.5rem;
|
||||||
--space-8: 2rem;
|
--space-8: 2rem;
|
||||||
--space-10: 2.5rem;
|
--space-10: 2.5rem;
|
||||||
--space-12: 3rem;
|
--space-12: 3rem;
|
||||||
--space-16: 4rem;
|
--space-16: 4rem;
|
||||||
--space-20: 5rem;
|
--space-20: 5rem;
|
||||||
--space-24: 6rem;
|
--space-24: 6rem;
|
||||||
|
|
||||||
/* Breakpoints */
|
/* Breakpoints */
|
||||||
--breakpoint-sm: 640px;
|
--breakpoint-sm: 640px;
|
||||||
--breakpoint-md: 768px;
|
--breakpoint-md: 768px;
|
||||||
--breakpoint-lg: 1024px;
|
--breakpoint-lg: 1024px;
|
||||||
--breakpoint-xl: 1280px;
|
--breakpoint-xl: 1280px;
|
||||||
--breakpoint-2xl: 1536px;
|
--breakpoint-2xl: 1536px;
|
||||||
|
|
||||||
/* Container */
|
/* Container */
|
||||||
--container-max-width: 80rem;
|
--container-max-width: 80rem;
|
||||||
|
|
||||||
/* Border Radius */
|
/* Border Radius */
|
||||||
--radius-sm: 0.125rem;
|
--radius-sm: 0.125rem;
|
||||||
--radius-base: 0.25rem;
|
--radius-base: 0.25rem;
|
||||||
--radius-md: 0.375rem;
|
--radius-md: 0.375rem;
|
||||||
--radius-lg: 0.5rem;
|
--radius-lg: 0.5rem;
|
||||||
--radius-xl: 0.75rem;
|
--radius-xl: 0.75rem;
|
||||||
--radius-2xl: 1rem;
|
--radius-2xl: 1rem;
|
||||||
--radius-full: 9999px;
|
--radius-full: 9999px;
|
||||||
|
|
||||||
/* Z-index */
|
/* Z-index */
|
||||||
--z-base: 0;
|
--z-base: 0;
|
||||||
--z-dropdown: 10;
|
--z-dropdown: 10;
|
||||||
--z-sticky: 20;
|
--z-sticky: 20;
|
||||||
--z-fixed: 30;
|
--z-fixed: 30;
|
||||||
--z-overlay: 40;
|
--z-overlay: 40;
|
||||||
--z-modal: 50;
|
--z-modal: 50;
|
||||||
--z-popover: 60;
|
--z-popover: 60;
|
||||||
--z-tooltip: 70;
|
--z-tooltip: 70;
|
||||||
|
|
||||||
/* Transitions */
|
/* Transitions */
|
||||||
--transition-fast: 150ms;
|
--transition-fast: 150ms;
|
||||||
--transition-base: 200ms;
|
--transition-base: 200ms;
|
||||||
--transition-slow: 300ms;
|
--transition-slow: 300ms;
|
||||||
--transition-slower: 500ms;
|
--transition-slower: 500ms;
|
||||||
--transition-timing: cubic-bezier(0.4, 0, 0.2, 1);
|
--transition-timing: cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
|
||||||
/* Shadows */
|
/* Shadows */
|
||||||
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
||||||
--shadow-base: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
|
--shadow-base: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
|
||||||
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
||||||
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
||||||
--shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
|
--shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user