herosection erstellt

This commit is contained in:
2026-03-04 22:01:49 +01:00
parent ce8cb07834
commit 79c71fcf45
28 changed files with 633 additions and 105 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,7 +1,9 @@
import { Component, signal, inject } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { Component, signal, OnInit } from '@angular/core';
import { RouterOutlet, Router, NavigationEnd } from '@angular/router';
import {provideIcons} from "@ng-icons/core";
import { filter } from 'rxjs/operators';
import {cssMenu} from "@ng-icons/css.gg";
import { UmamiService } from '@core/services/umami.service';
@Component({
selector: 'app-root',
@@ -10,6 +12,19 @@ import {cssMenu} from "@ng-icons/css.gg";
styleUrl: './app.scss',
viewProviders: [provideIcons({cssMenu})]
})
export class App {
export class App implements OnInit {
protected readonly title = signal('hurler-webdesign-saas');
constructor(
private router: Router,
private umami: UmamiService
) {}
ngOnInit(): void {
this.router.events.pipe(
filter(event => event instanceof NavigationEnd)
).subscribe(() => {
this.umami.trackPageview();
});
}
}

View File

@@ -13,19 +13,27 @@ export class SeoService {
private renderer =
this.rendererFactory.createRenderer(null, null);
// Constants for metadata
private readonly BRAND = "Hurler Webdesign";
private readonly FALLBACK_IMAGE =
'https://hurler-webdesign.de/assets/og-default.jpg';
private readonly DEFAULT_TYPE = "website";
/**
* Updates SEO metadata with the provided data.
*
* @param data - The SeoData object containing title, description, type, and image.
* @param canonicalPath - Optional parameter for the canonical URL path.
*/
updateMetadata(data: SeoData, canonicalPath?: string) {
const fullTitle = `${data.title} | ${this.BRAND}`;
const url = `https://hurler-webdesign.de${canonicalPath || ""}`;
// Update title and meta description
this.titleService.setTitle(fullTitle);
this.metaService.updateTag({ name: "description", content: data.description });
// Open Graph
// Open Graph metadata
this.metaService.updateTag({
property: "og:title",
content: fullTitle,
@@ -44,7 +52,7 @@ export class SeoService {
});
this.metaService.updateTag({ property: "og:url", content: url });
// Twitter
// Twitter card metadata
this.metaService.updateTag({
name: "twitter:card",
content: "summary_large_image",
@@ -63,13 +71,20 @@ export class SeoService {
content: data.image || this.FALLBACK_IMAGE,
});
// Update canonical URL if provided
if (canonicalPath) {
this.updateCanonicalUrl(url);
}
// Set local business schema.org metadata
this.setLocalBusinessSchema();
}
/**
* Updates the canonical URL for the given page.
*
* @param url - The new canonical URL.
*/
private updateCanonicalUrl(url: string) {
let link: HTMLLinkElement =
this.document.querySelector("link[rel='canonical']") ||
@@ -81,7 +96,9 @@ export class SeoService {
}
}
/**
* Sets the local business schema.org JSON-LD script in the head of the document.
*/
private setLocalBusinessSchema() {
const oldScript = this.document.getElementById('schema-org-data');
if (oldScript) this.renderer.removeChild(this.document.head, oldScript);

View File

@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { UmamiService } from './umami.service';
describe('UmamiService', () => {
let service: UmamiService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(UmamiService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});

View File

@@ -0,0 +1,42 @@
import { Injectable } from '@angular/core';
export interface UmamiEventData {
[key: string]: string | number | boolean;
}
// Typdefinition für das globale umami-Objekt
declare global {
interface Window {
umami?: {
track: (eventName?: string, data?: UmamiEventData) => void;
};
}
}
@Injectable({
providedIn: 'root',
})
export class UmamiService {
private get isAvailable(): boolean {
return typeof window !== 'undefined' && typeof window.umami !== 'undefined';
}
/**
* Trackt einen Pageview manuell nötig bei SPAs wie Angular,
* da kein echter Seitenaufruf stattfindet.
*/
trackPageview(): void {
if (!this.isAvailable) return;
window.umami!.track();
}
/**
* Trackt ein benutzerdefiniertes Event.
* @param eventName Name des Events, z.B. 'button-click'
* @param data Optionale Zusatzdaten, z.B. { label: 'Hero CTA' }
*/
trackEvent(eventName: string, data?: UmamiEventData): void {
if (!this.isAvailable) return;
window.umami!.track(eventName, data);
}
}

View File

@@ -1 +1,3 @@
<p>footer works!</p>
<footer>
Hier kommt der Footer
</footer>

View File

@@ -0,0 +1,3 @@
footer {
height: 500px;
}

View File

@@ -1,16 +1,23 @@
<section class="hero-section">
<h1 class="hero-section__header">
<span>Digitales Handwerk</span> <br />
<span>statt Standard-Baukasten</span>
</h1>
<p class="hero-section__claim">
Wir programmieren Blitzschnelle, sichere und maßgeschneiderte Webseiten für kleine,
mittelständische Unternehmen und Vereine. Ohne CMS-Ballast, dafür mit maximaler Performance.
</p>
<div class="hero-section__links">
<button href="#" variant="primary" label="Leistungen ansehen">Leistungen ansehen</button>
<button href="#" variant="secondary" label="Warum kein WordPress?">
Warum kein WordPress?
</button>
<div class="hero-section__video-container">
<video autoplay muted loop>
<source src="/video/white_mit_black_stripes.webm" type="video/webm">
</video>
</div>
</section>
<div class="hero-section__wrapper">
<h1 class="hero-section__header">
Digitales Handwerk <br />
statt Standard-Baukasten
</h1>
<p class="hero-section__claim">
Wir programmieren Blitzschnelle, sichere und maßgeschneiderte Webseiten für kleine,
mittelständische Unternehmen und Vereine. Ohne CMS-Ballast, dafür mit maximaler Performance.
</p>
<div class="hero-section__links">
<app-button [item]="{ label: 'Über uns', type: 'anchor', target: '#about' }" variant="primary"></app-button>
<app-button (click)="onFeaturesClick()" [item]="{ label: 'Warum kein Wordpress', type: 'anchor', target: 'about'}"
variant="primary"></app-button>
</div>
</div>
</section>

View File

@@ -1,4 +1,66 @@
@use "abstracts";
.hero-section {
position: relative; // WICHTIG: Bezugspunkt für das Video
height: 100vh;
margin-top: -60px;
padding-top: 60px;
overflow: hidden;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center; // Zentriert den Text-Inhalt
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
max-width: 1200px;
height: 100%;
background-color: var(--overlay);
z-index: -1;
}
&__wrapper {
@include abstracts.container-wrapper;
}
&__video-container {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -2; // Hinter den Text legen
}
h1 {
color: var(--text-main); // Dein Wunsch-Style
font-size: var(--font-size-xxl);
position: relative; // Stellt sicher, dass der Text über dem Video-Layer bleibt
margin-bottom: var(--space-4);
}
&__claim {
color: var(--text-main);
font-size: var(--font-size-xl);
margin-bottom: var(--space-4);
}
&__links {
display: flex;
flex-direction: row;
gap: var(--space-2);
justify-content: center;
}
video {
/* Das hier ist der entscheidende Teil */
width: 100%;
height: 100%;
object-fit: cover; // WICHTIG: Füllt den Container komplett aus, ohne zu verzerren
object-position: center; // Zentriert das Video, falls Ränder abgeschnitten werden
}
}

View File

@@ -1,11 +1,17 @@
import { Component } from '@angular/core';
import { ButtonComponent } from '@shared/ui/button/button.component';
import { UmamiService } from '@core/services/umami.service';
@Component({
selector: 'app-hero',
imports: [],
imports: [ButtonComponent],
templateUrl: './hero.component.html',
styleUrl: './hero.component.scss',
})
export class HeroComponent {
constructor(private umami: UmamiService) {}
onFeaturesClick(): void {
this.umami.trackEvent('features-anchor-click')
}
}

View File

@@ -1,15 +1,18 @@
<section class="header">
<div class="logo-container">
<span class="logo-container__logo centered">H</span>
<p class="logo-container__company"><span>Hurler</span> Webdesign</p>
</div>
<div class="header__nav-section centered">
<div class="theme-toggle-container">
<app-toogle-theme></app-toogle-theme>
<div class="wrapper">
<section class="header">
<div class="logo-container">
<span class="logo-container__logo centered">H</span>
<p class="logo-container__company"><span>Hurler</span> Webdesign</p>
</div>
<app-nav-menu [items]="navigationService.landingNavigation()"></app-nav-menu>
<div class="burger-menu centered">
<ng-icon name="cssMenu" class="burger-menu__icon"></ng-icon>
<div class="header__nav-section centered">
<div class="theme-toggle-container">
<app-toogle-theme></app-toogle-theme>
</div>
<app-nav-menu [items]="navigationService.landingNavigation()"></app-nav-menu>
<div class="burger-menu centered">
<ng-icon name="cssMenu" class="burger-menu__icon"></ng-icon>
</div>
</div>
</div>
</section>
</section>
</div>

View File

@@ -1,5 +1,15 @@
@use "abstracts";
.wrapper {
border-radius: 0 0 10px 10px;
background-color: var(--nav-bg);
backdrop-filter: var(--nav-backdrop);
box-shadow: var(--nav-shadow);
position: sticky;
top: 0;
z-index: var(--z-index-sticky);
}
.header {
max-width: 1200px;
margin: 0 auto;

View File

@@ -1,14 +1,4 @@
<div class="landing-grid">
<div class="grid-area-navigation">
<app-navigation></app-navigation>
</div>
<div class="grid-area-hero" id="hero">
<app-hero></app-hero>
</div>
<div class="grid-area-features" id="features-section">
<app-features-section></app-features-section>
</div>
<div class="grid-area-footer">
<app-footer></app-footer>
</div>
</div>
<app-navigation></app-navigation>
<app-hero></app-hero>
<app-features-section></app-features-section>
<app-footer></app-footer>

View File

@@ -0,0 +1,118 @@
# NavButtonComponent
Eine Angular Standalone-Komponente die ein `NavigationItem` rendert und je nach `NavigationType` automatisch den passenden Link-Typ erzeugt.
## Voraussetzungen
- Angular 17+
- `RouterModule` im Projekt eingebunden
## Dateien
```
button/
├── button.component.ts
├── button.component.html
└── button.component.scss
```
## Verwendung
Die Komponente ist standalone und wird direkt in den `imports` einer anderen Komponente oder eines Moduls eingebunden:
```typescript
import { NavButtonComponent } from './nav-button/nav-button.component';
@Component({
standalone: true,
imports: [NavButtonComponent],
// ...
})
export class AppComponent {}
```
## Inputs
| Input | Typ | Pflicht | Default | Beschreibung |
|-----------|--------------------------------------|---------|-------------|-------------------------------------|
| `item` | `NavigationItem` | ✅ | — | Das NavigationItem-Objekt |
| `size` | `'sm' \| 'md' \| 'lg'` | ❌ | `'md'` | Größe des Buttons |
| `variant` | `'primary' \| 'ghost' \| 'outline'` | ❌ | `'primary'` | Visueller Stil |
| `disabled`| `boolean` | ❌ | `false` | Deaktiviert den Button |
## NavigationItem
```typescript
export type NavigationType = "anchor" | "route" | "external";
export interface NavigationItem {
readonly label: string; // Anzeigetext
readonly type: NavigationType;
readonly target: string; // Pfad, Anchor (#id) oder URL
readonly icon?: string; // Optionales Icon (z. B. Emoji oder Icon-String)
readonly children?: NavigationItem[];
}
```
## Verhalten je NavigationType
| Typ | Verhalten |
|------------|----------------------------------------------------------------|
| `route` | Rendert `<a [routerLink]>` mit `routerLinkActive` |
| `anchor` | Rendert `<a href>` mit `scrollIntoView({ behavior: 'smooth'})` |
| `external` | Rendert `<a target="_blank" rel="noopener noreferrer">` mit `↗`|
## Beispiele
```html
<!-- Interner Routerlink -->
<app-nav-button
[item]="{ label: 'Home', type: 'route', target: '/home' }"
/>
<!-- Anchor Scroll -->
<app-nav-button
[item]="{ label: 'Über uns', type: 'anchor', target: '#about' }"
variant="outline"
/>
<!-- Externer Link -->
<app-nav-button
[item]="{ label: 'GitHub', type: 'external', target: 'https://github.com', icon: '🐙' }"
variant="ghost"
size="sm"
/>
<!-- Deaktiviert -->
<app-nav-button
[item]="{ label: 'Gesperrt', type: 'route', target: '/admin' }"
[disabled]="true"
/>
```
## Theming
Alle Farben und Abstände sind über CSS Custom Properties steuerbar. Überschreibe die Tokens global in deinem `styles.scss`:
```scss
:root {
--btn-primary-bg: #1a1a2e;
--btn-primary-color: #ffffff;
--btn-primary-hover-bg: #16213e;
--btn-outline-border: #1a1a2e;
--btn-outline-color: #1a1a2e;
--btn-outline-hover-bg: #1a1a2e;
--btn-outline-hover-color: #ffffff;
--btn-radius: 8px;
--btn-font: 'Your Font', sans-serif;
}
```
## Accessibility
- Aktiver Routerlink erhält die Klasse `nav-btn--active`
- Deaktivierte Links erhalten `aria-disabled="true"`
- Externe Links sind mit `aria-label="Opens in new tab"` gekennzeichnet
- Focus-Styles über `:focus-visible` vorhanden

View File

@@ -1 +1,46 @@
<p>button works!</p>
<!-- Router Link (internal navigation) -->
@if (isRouteType) {
<a
[routerLink]="item.target"
routerLinkActive="nav-btn--active"
[class]="hostClasses.join(' ')"
[attr.aria-disabled]="disabled || null"
>
@if (item.icon) {
<span class="nav-btn__icon" aria-hidden="true">{{ item.icon }}</span>
}
<span class="nav-btn__label">{{ item.label }}</span>
</a>
}
<!-- Anchor (smooth scroll) -->
@if (isAnchorType) {
<a
[href]="item.target"
(click)="scrollToAnchor($event)"
[class]="hostClasses.join(' ')"
[attr.aria-disabled]="disabled || null"
>
@if (item.icon) {
<span class="nav-btn__icon" aria-hidden="true">{{ item.icon }}</span>
}
<span class="nav-btn__label">{{ item.label }}</span>
</a>
}
<!-- External Link -->
@if (isExternalType) {
<a
[href]="item.target"
target="_blank"
rel="noopener noreferrer"
[class]="hostClasses.join(' ')"
[attr.aria-disabled]="disabled || null"
>
@if (item.icon) {
<span class="nav-btn__icon" aria-hidden="true">{{ item.icon }}</span>
}
<span class="nav-btn__label">{{ item.label }}</span>
<span class="nav-btn__external-icon" aria-label="Opens in new tab"></span>
</a>
}

View File

@@ -0,0 +1,139 @@
// ─── Design Tokens ───────────────────────────────────────────────────────────
:host {
--btn-font: 'DM Mono', 'Courier New', monospace;
--btn-radius: 4px;
--btn-transition: 160ms cubic-bezier(0.4, 0, 0.2, 1);
// Size tokens
--btn-sm-padding: 6px 14px;
--btn-md-padding: 10px 22px;
--btn-lg-padding: 14px 32px;
--btn-sm-font: 0.75rem;
--btn-md-font: 0.875rem;
--btn-lg-font: 1rem;
// Color tokens — override at :root level to theme globally
--btn-primary-bg: #0f0f0f;
--btn-primary-color: #f5f5f5;
--btn-primary-border: #0f0f0f;
--btn-primary-hover-bg: #2a2a2a;
--btn-ghost-bg: transparent;
--btn-ghost-color: #0f0f0f;
--btn-ghost-border: transparent;
--btn-ghost-hover-bg: rgba(0, 0, 0, 0.06);
--btn-outline-bg: transparent;
--btn-outline-color: #0f0f0f;
--btn-outline-border: #0f0f0f;
--btn-outline-hover-bg: #0f0f0f;
--btn-outline-hover-color: #f5f5f5;
display: inline-block;
}
// ─── Base ─────────────────────────────────────────────────────────────────────
.nav-btn {
display: inline-flex;
align-items: center;
gap: 8px;
font-family: var(--btn-font);
font-weight: 500;
letter-spacing: 0.04em;
text-transform: uppercase;
text-decoration: none;
border: 1.5px solid;
border-radius: var(--btn-radius);
cursor: pointer;
white-space: nowrap;
outline-offset: 3px;
transition:
background-color var(--btn-transition),
color var(--btn-transition),
border-color var(--btn-transition),
box-shadow var(--btn-transition),
transform var(--btn-transition);
&:focus-visible {
outline: 2px solid currentColor;
}
&:active:not(.nav-btn--disabled) {
transform: translateY(1px);
}
// ── Sizes ──────────────────────────────────────────────────────────────────
&--sm {
padding: var(--btn-sm-padding);
font-size: var(--btn-sm-font);
}
&--md {
padding: var(--btn-md-padding);
font-size: var(--btn-md-font);
}
&--lg {
padding: var(--btn-lg-padding);
font-size: var(--btn-lg-font);
}
// ── Variants ───────────────────────────────────────────────────────────────
&--primary {
background-color: var(--btn-primary-bg);
color: var(--btn-primary-color);
border-color: var(--btn-primary-border);
&:hover:not(.nav-btn--disabled) {
background-color: var(--btn-primary-hover-bg);
}
}
&--ghost {
background-color: var(--btn-ghost-bg);
color: var(--btn-ghost-color);
border-color: var(--btn-ghost-border);
&:hover:not(.nav-btn--disabled) {
background-color: var(--btn-ghost-hover-bg);
}
}
&--outline {
background-color: var(--btn-outline-bg);
color: var(--btn-outline-color);
border-color: var(--btn-outline-border);
&:hover:not(.nav-btn--disabled) {
background-color: var(--btn-outline-hover-bg);
color: var(--btn-outline-hover-color);
}
}
// ── States ─────────────────────────────────────────────────────────────────
&--active {
box-shadow: inset 0 0 0 1.5px currentColor;
}
&--disabled {
opacity: 0.4;
cursor: not-allowed;
pointer-events: none;
}
// ── Parts ──────────────────────────────────────────────────────────────────
&__icon {
font-size: 1.1em;
line-height: 1;
}
&__label {
line-height: 1;
}
&__external-icon {
font-size: 0.85em;
opacity: 0.65;
margin-left: -2px;
}
}

View File

@@ -1,11 +1,55 @@
import { Component } from '@angular/core';
import {
Component,
Input,
OnInit,
ChangeDetectionStrategy,
} from '@angular/core';
import { RouterModule } from '@angular/router';
import { NavigationItem, isAnchor, isRoute } from '@core/models/navigation.model';
@Component({
selector: 'app-button',
imports: [],
standalone: true,
imports: [RouterModule],
templateUrl: './button.component.html',
styleUrl: './button.component.scss',
styleUrls: ['./button.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ButtonComponent {
export class ButtonComponent implements OnInit {
@Input({ required: true }) item!: NavigationItem;
}
/** Optional size variant */
@Input() size: 'sm' | 'md' | 'lg' = 'md';
/** Optional visual variant */
@Input() variant: 'primary' | 'ghost' | 'outline' = 'primary';
/** Whether the button is disabled */
@Input() disabled = false;
isAnchorType = false;
isRouteType = false;
isExternalType = false;
ngOnInit(): void {
this.isAnchorType = isAnchor(this.item);
this.isRouteType = isRoute(this.item);
this.isExternalType = this.item.type === 'external';
}
/** Scroll to anchor target */
scrollToAnchor(event: Event): void {
event.preventDefault();
const target = document.querySelector(this.item.target);
target?.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
get hostClasses(): string[] {
return [
'nav-btn',
`nav-btn--${this.variant}`,
`nav-btn--${this.size}`,
this.disabled ? 'nav-btn--disabled' : '',
].filter(Boolean);
}
}

View File

@@ -6,6 +6,7 @@
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<script defer src="https://stats.hurler-webdesign.de/script.js" data-website-id="33763c9b-43a8-4e36-a1c1-e07d31ed1e5b"></script>
</head>
<body>
<app-root></app-root>

View File

@@ -1,3 +1,2 @@
@use "abstracts";
@use "base";
@use "layout";
@use "base";

View File

@@ -12,4 +12,10 @@ $breakpoints: (
@media (width >=map.get($breakpoints, $size)) {
@content;
}
}
@mixin container-wrapper {
max-width: 1200px;
margin: auto;
padding-inline: 20px;
}

View File

@@ -26,8 +26,7 @@
--button-text: oklch(100% 0.01 250);
--border: oklch(90% 0.02 250);
--shadow-color: oklch(0% 0 250);
// Stapelbare Werte
--overlay: oklch(90% 0.02 250 / 0.9); // Stapelbare Werte
--z-index-sticky: 100;
// Skalierung (modulare Skala)
@@ -41,6 +40,7 @@
--font-size-base: clamp(1rem, 0.5vw + 0.875rem, 1.125rem);
--font-size-lg: clamp(1.25rem, 1vw + 1rem, 1.5rem);
--font-size-xl: clamp(1.5rem, 2vw + 1rem, 2.5rem);
--font-size-xxl: clamp(2.5rem, 3vw + 1.5rem, 4.5rem)
}
[data-theme="dark"] {
@@ -54,6 +54,8 @@
--border: oklch(25% 0.02 250);
--shadow-color: 0 0% 100%;
--overlay: oklch(30% 0.0075 250 / 0.9);
}
// ==============================

View File

@@ -1,51 +1,51 @@
@use "abstracts";
.landing-grid {
display: grid;
grid-template-columns: 1fr minmax(auto, 1200px) 1fr;
grid-template-areas:
"navigation navigation navigation"
"hero hero hero"
". features-section ."
"footer footer footer";
.layout-wrapper {
max-width: 1200px;
margin: auto;
padding-inline: 20px;
}
.grid-area-navigation {
grid-area: navigation;
border-radius: 0 0 10px 10px;
background-color: var(--nav-bg);
backdrop-filter: var(--nav-backdrop);
box-shadow: var(--nav-shadow);
position: sticky;
top: 0;
z-index: var(--z-index-sticky);
}
// .landing-grid {
// display: grid;
// grid-template-columns: 1fr minmax(auto, 1200px) 1fr;
// grid-template-areas:
// "navigation navigation navigation"
// "hero hero hero"
// ". features-section ."
// "footer footer footer";
// }
.grid-area-hero {
grid-area: hero;
margin-top: -60px;
padding-top: 60px;
height: 100vh;
display: flex;
justify-content: center;
background:
linear-gradient(rgba(255, 255, 255, 0.7), rgba(255, 255, 255, 0.7), rgba(255, 255, 255, 1)),
linear-gradient(0.25turn, oklch(56.347% 0.24089 260.834 / 0.8), oklch(55.088% 0.23462 260.772 / 0.8), oklch(56.347% 0.24089 260.834 / 0.8)),
url("/images/backgroundpattern.webp") center / cover no-repeat;
}
// .grid-area-navigation {
// grid-area: navigation;
[data-theme="dark"] .grid-area-hero {
background:
linear-gradient(rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0.2)),
linear-gradient(0.25turn, oklch(20.648% 0.14311 250 / 0.5), oklch(27.99% 0.10701 258.719 / 0.5), oklch(20.648% 0.14311 250 / 0.5)),
url("/images/backgroundpattern.webp") center / cover no-repeat;
}
// }
.grid-area-features {
grid-area: features-section;
height: 80vh;
}
// .grid-area-hero {
// grid-area: hero;
// margin-top: -60px;
// padding-top: 60px;
// height: 100vh;
// display: flex;
// justify-content: center;
// background:
// linear-gradient(rgba(255, 255, 255, 0.7), rgba(255, 255, 255, 0.7), rgba(255, 255, 255, 1)),
// linear-gradient(0.25turn, oklch(56.347% 0.24089 260.834 / 0.8), oklch(55.088% 0.23462 260.772 / 0.8), oklch(56.347% 0.24089 260.834 / 0.8)),
// url("/images/backgroundpattern.webp") center / cover no-repeat;
// }
.grid-area-footer {
grid-area: footer;
}
// [data-theme="dark"] .grid-area-hero {
// background:
// linear-gradient(rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0.2)),
// linear-gradient(0.25turn, oklch(20.648% 0.14311 250 / 0.5), oklch(27.99% 0.10701 258.719 / 0.5), oklch(20.648% 0.14311 250 / 0.5)),
// url("/images/backgroundpattern.webp") center / cover no-repeat;
// }
// .grid-area-features {
// grid-area: features-section;
// height: 80vh;
// }
// .grid-area-footer {
// grid-area: footer;
// }

View File

@@ -1,2 +0,0 @@
@forward "grid";
@forward "header";