generated from Websites/symfony-template
Compare commits
8 Commits
e0ea470c76
...
2945c32bb6
| Author | SHA1 | Date | |
|---|---|---|---|
| 2945c32bb6 | |||
| 70675c3ccc | |||
| e9b2e30d43 | |||
| dd4b5d98d5 | |||
| dde45bd90b | |||
| e8020ea334 | |||
| ef45866bb0 | |||
| 41b5ddd0e5 |
@@ -40,3 +40,8 @@ desktop.ini
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
###< symfony/webpack-encore-bundle ###
|
||||
|
||||
###> symfony/asset-mapper ###
|
||||
/public/assets/
|
||||
/assets/vendor/
|
||||
###< symfony/asset-mapper ###
|
||||
|
||||
Generated
+1
@@ -6,6 +6,7 @@
|
||||
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" packagePrefix="App\Tests\" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/var" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/public/build" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
|
||||
Generated
+24
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="PhpDockerContainerSettings">
|
||||
<list>
|
||||
<map>
|
||||
<entry key="0bef9119-879f-4b48-9f5f-1234513849a3">
|
||||
<value>
|
||||
<DockerContainerSettings>
|
||||
<option name="version" value="1" />
|
||||
<option name="volumeBindings">
|
||||
<list>
|
||||
<DockerVolumeBindingImpl>
|
||||
<option name="containerPath" value="/opt/project" />
|
||||
<option name="hostPath" value="$PROJECT_DIR$" />
|
||||
</DockerVolumeBindingImpl>
|
||||
</list>
|
||||
</option>
|
||||
</DockerContainerSettings>
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</list>
|
||||
</component>
|
||||
</project>
|
||||
Generated
+6
@@ -59,6 +59,12 @@
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/translation-contracts" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/webpack-encore-bundle" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/asset" />
|
||||
<path value="$PROJECT_DIR$/vendor/twig/extra-bundle" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/http-client-contracts" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/asset-mapper" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/http-client" />
|
||||
<path value="$PROJECT_DIR$/vendor/psr/link" />
|
||||
<path value="$PROJECT_DIR$/vendor/symfony/web-link" />
|
||||
</include_path>
|
||||
</component>
|
||||
<component name="PhpProjectSharedConfiguration" php_language_level="8.2" />
|
||||
|
||||
Generated
+7
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Symfony2PluginSettings">
|
||||
<option name="pluginEnabled" value="true" />
|
||||
<option name="profilerCsvPath" value="" />
|
||||
</component>
|
||||
</project>
|
||||
Generated
+4
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectTasksOptions" suppressed-tasks="SCSS" />
|
||||
</project>
|
||||
@@ -5,5 +5,7 @@
|
||||
* (and its CSS file) in your base layout (base.html.twig).
|
||||
*/
|
||||
|
||||
require('bootstrap');
|
||||
|
||||
// any CSS you import will output into a single css file (app.scss in this case)
|
||||
import './styles/app.scss';
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 328 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
+594
-2
@@ -1,3 +1,595 @@
|
||||
body {
|
||||
background-color: lightgray;
|
||||
@use 'app/nav';
|
||||
@use 'app/footer';
|
||||
|
||||
// =============================================================================
|
||||
// Fonts
|
||||
// =============================================================================
|
||||
|
||||
@font-face {
|
||||
font-family: 'Agave';
|
||||
src: url('../fonts/agave-regular.woff2') format('woff2');
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Fantasque Sans Mono';
|
||||
src: url('../fonts/fantasque-sans-mono-regular.woff2') format('woff2');
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
src: url('../fonts/jetbrains-mono-regular.woff2') format('woff2');
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Material Symbols Outlined';
|
||||
font-style: normal;
|
||||
src: url('../fonts/material-symbols-outlined.woff2') format('woff');
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Design Tokens — Light Palette
|
||||
// =============================================================================
|
||||
|
||||
$lt-surface: #f7f9fb;
|
||||
$lt-surface-dim: #d8dadc;
|
||||
$lt-surface-bright: #f7f9fb;
|
||||
$lt-surface-container-lowest: #ffffff;
|
||||
$lt-surface-container-low: #f2f4f6;
|
||||
$lt-surface-container: #eceef0;
|
||||
$lt-surface-container-high: #e6e8ea;
|
||||
$lt-surface-container-highest: #e0e3e5;
|
||||
$lt-on-surface: #191c1e;
|
||||
$lt-on-surface-variant: #404751;
|
||||
$lt-outline: #707883;
|
||||
$lt-outline-variant: #c0c7d3;
|
||||
$lt-surface-tint: #0061a2;
|
||||
$lt-surface-variant: #e0e3e5;
|
||||
|
||||
$lt-primary: #0061a2;
|
||||
$lt-on-primary: #ffffff;
|
||||
$lt-primary-container: #50a7fa;
|
||||
$lt-on-primary-container: #003b65;
|
||||
$lt-inverse-primary: #9dcaff;
|
||||
|
||||
$lt-secondary: #565e74;
|
||||
$lt-on-secondary: #ffffff;
|
||||
$lt-secondary-container: #dae2fd;
|
||||
$lt-on-secondary-container: #5c647a;
|
||||
|
||||
$lt-tertiary: #505f76;
|
||||
$lt-on-tertiary: #ffffff;
|
||||
$lt-tertiary-container: #94a4bc;
|
||||
$lt-on-tertiary-container: #2a3a4f;
|
||||
|
||||
$lt-error: #ba1a1a;
|
||||
$lt-on-error: #ffffff;
|
||||
$lt-error-container: #ffdad6;
|
||||
$lt-on-error-container: #93000a;
|
||||
|
||||
$lt-background: #f7f9fb;
|
||||
$lt-on-background: #191c1e;
|
||||
|
||||
// =============================================================================
|
||||
// Design Tokens — Dark Palette
|
||||
// =============================================================================
|
||||
|
||||
$dk-surface: #0b1326;
|
||||
$dk-surface-dim: #0b1326;
|
||||
$dk-surface-bright: #31394d;
|
||||
$dk-surface-container-lowest: #060e20;
|
||||
$dk-surface-container-low: #131b2e;
|
||||
$dk-surface-container: #171f33;
|
||||
$dk-surface-container-high: #222a3d;
|
||||
$dk-surface-container-highest: #2d3449;
|
||||
$dk-on-surface: #dae2fd;
|
||||
$dk-on-surface-variant: #c0c7d3;
|
||||
$dk-inverse-surface: #dae2fd;
|
||||
$dk-inverse-on-surface: #283044;
|
||||
$dk-outline: #8a919d;
|
||||
$dk-outline-variant: #404751;
|
||||
$dk-surface-tint: #9dcaff;
|
||||
$dk-surface-variant: #2d3449;
|
||||
|
||||
$dk-primary: #9dcaff;
|
||||
$dk-on-primary: #003257;
|
||||
$dk-primary-container: #50a7fa;
|
||||
$dk-on-primary-container: #003b65;
|
||||
$dk-inverse-primary: #0061a2;
|
||||
|
||||
$dk-secondary: #89ceff;
|
||||
$dk-on-secondary: #00344d;
|
||||
$dk-secondary-container: #00a2e6;
|
||||
$dk-on-secondary-container: #00344e;
|
||||
|
||||
$dk-tertiary: #c0c1ff;
|
||||
$dk-on-tertiary: #1000a9;
|
||||
$dk-tertiary-container: #9598ff;
|
||||
$dk-on-tertiary-container: #1c16b1;
|
||||
|
||||
$dk-error: #ffb4ab;
|
||||
$dk-on-error: #690005;
|
||||
$dk-error-container: #93000a;
|
||||
$dk-on-error-container: #ffdad6;
|
||||
|
||||
$dk-background: #0b1326;
|
||||
$dk-on-background: #dae2fd;
|
||||
|
||||
// =============================================================================
|
||||
// Shared Tokens — Typography & Radius
|
||||
// =============================================================================
|
||||
|
||||
$font-display: 'Agave', system-ui, sans-serif;
|
||||
$font-body: 'Fantasque Sans Mono', system-ui, -apple-system, sans-serif;
|
||||
$font-mono: 'JetBrains Mono', 'Courier New', monospace;
|
||||
|
||||
$radius-sm: 0.25rem;
|
||||
$radius-default: 0.5rem;
|
||||
$radius-md: 0.75rem;
|
||||
$radius-lg: 1rem;
|
||||
$radius-xl: 1.5rem;
|
||||
$radius-full: 9999px;
|
||||
|
||||
// =============================================================================
|
||||
// Bootstrap Variable Overrides
|
||||
// Light mode values are the compiled baseline.
|
||||
// $color-mode-type: media-query makes Bootstrap emit its own dark-mode block
|
||||
// inside @media (prefers-color-scheme: dark) automatically.
|
||||
// =============================================================================
|
||||
|
||||
$enable-dark-mode: true;
|
||||
$color-mode-type: media-query; // use prefers-color-scheme instead of data-bs-theme
|
||||
|
||||
// Semantic colors — light baseline
|
||||
$primary: $lt-primary-container; // #50a7fa — Electric Azure anchor
|
||||
$secondary: $lt-secondary; // #565e74
|
||||
$success: #16a34a;
|
||||
$info: $lt-primary; // #0061a2
|
||||
$warning: #d97706;
|
||||
$danger: $lt-error; // #ba1a1a
|
||||
$light: $lt-surface-container-low; // #f2f4f6
|
||||
$dark: $lt-on-surface; // #191c1e
|
||||
|
||||
// Body — light defaults
|
||||
$body-bg: $lt-background; // #f7f9fb
|
||||
$body-color: $lt-on-surface; // #191c1e
|
||||
$body-secondary-color: $lt-on-surface-variant; // #404751
|
||||
|
||||
// Links
|
||||
$link-color: $lt-primary; // #0061a2
|
||||
$link-hover-color: $lt-primary-container; // #50a7fa
|
||||
|
||||
// Borders
|
||||
$border-color: $lt-outline-variant; // #c0c7d3
|
||||
|
||||
// Border radius
|
||||
$border-radius: $radius-default;
|
||||
$border-radius-sm: $radius-sm;
|
||||
$border-radius-lg: $radius-md;
|
||||
$border-radius-xl: $radius-lg;
|
||||
$border-radius-xxl: $radius-xl;
|
||||
$border-radius-pill: $radius-full;
|
||||
|
||||
// Typography
|
||||
$font-family-sans-serif: $font-body;
|
||||
$font-family-monospace: $font-mono;
|
||||
$font-size-base: 1rem;
|
||||
$line-height-base: 1.5;
|
||||
|
||||
// Headings — Bootstrap uses var(--bs-heading-color), dark mode auto-switches
|
||||
$headings-font-family: $font-display;
|
||||
$headings-font-weight: 600;
|
||||
$headings-line-height: 1.3;
|
||||
$headings-color: $lt-on-surface; // #191c1e
|
||||
|
||||
// Grid
|
||||
$grid-gutter-width: 1.5rem; // 24px
|
||||
$container-max-widths: (
|
||||
sm: 540px,
|
||||
md: 720px,
|
||||
lg: 960px,
|
||||
xl: 1140px,
|
||||
xxl: 1200px,
|
||||
);
|
||||
|
||||
// Code
|
||||
$code-color: $lt-tertiary; // #505f76
|
||||
|
||||
// Bootstrap dark mode variables — used inside Bootstrap's generated media query
|
||||
$body-color-dark: $dk-on-surface; // #dae2fd
|
||||
$body-bg-dark: $dk-background; // #0b1326
|
||||
$body-secondary-color-dark: $dk-on-surface-variant; // #c0c7d3
|
||||
$border-color-dark: $dk-outline-variant; // #404751
|
||||
$link-color-dark: $dk-primary; // #9dcaff
|
||||
$headings-color-dark: $dk-on-surface; // #dae2fd
|
||||
$code-color-dark: $dk-tertiary; // #c0c1ff
|
||||
|
||||
// =============================================================================
|
||||
// Bootstrap Import
|
||||
// Bootstrap 5.x uses @import internally — @use with() is not supported.
|
||||
// =============================================================================
|
||||
|
||||
@import '~bootstrap/scss/bootstrap';
|
||||
|
||||
// =============================================================================
|
||||
// CSS Custom Properties — Light Mode (default)
|
||||
// =============================================================================
|
||||
|
||||
:root {
|
||||
// Surface
|
||||
--color-surface: #{$lt-surface};
|
||||
--color-surface-dim: #{$lt-surface-dim};
|
||||
--color-surface-bright: #{$lt-surface-bright};
|
||||
--color-surface-container-lowest: #{$lt-surface-container-lowest};
|
||||
--color-surface-container-low: #{$lt-surface-container-low};
|
||||
--color-surface-container: #{$lt-surface-container};
|
||||
--color-surface-container-high: #{$lt-surface-container-high};
|
||||
--color-surface-container-highest: #{$lt-surface-container-highest};
|
||||
--color-on-surface: #{$lt-on-surface};
|
||||
--color-on-surface-variant: #{$lt-on-surface-variant};
|
||||
--color-outline: #{$lt-outline};
|
||||
--color-outline-variant: #{$lt-outline-variant};
|
||||
--color-surface-tint: #{$lt-surface-tint};
|
||||
--color-surface-variant: #{$lt-surface-variant};
|
||||
// RGB channels for rgba() composition (navbar glass, overlays)
|
||||
--color-surface-container-lowest-rgb: 255, 255, 255;
|
||||
|
||||
// Primary
|
||||
--color-primary: #{$lt-primary};
|
||||
--color-on-primary: #{$lt-on-primary};
|
||||
--color-primary-container: #{$lt-primary-container};
|
||||
--color-on-primary-container: #{$lt-on-primary-container};
|
||||
--color-inverse-primary: #{$lt-inverse-primary};
|
||||
|
||||
// Secondary
|
||||
--color-secondary: #{$lt-secondary};
|
||||
--color-on-secondary: #{$lt-on-secondary};
|
||||
--color-secondary-container: #{$lt-secondary-container};
|
||||
--color-on-secondary-container: #{$lt-on-secondary-container};
|
||||
|
||||
// Tertiary
|
||||
--color-tertiary: #{$lt-tertiary};
|
||||
--color-on-tertiary: #{$lt-on-tertiary};
|
||||
--color-tertiary-container: #{$lt-tertiary-container};
|
||||
--color-on-tertiary-container: #{$lt-on-tertiary-container};
|
||||
|
||||
// Error
|
||||
--color-error: #{$lt-error};
|
||||
--color-on-error: #{$lt-on-error};
|
||||
--color-error-container: #{$lt-error-container};
|
||||
--color-on-error-container: #{$lt-on-error-container};
|
||||
|
||||
// Background
|
||||
--color-background: #{$lt-background};
|
||||
--color-on-background: #{$lt-on-background};
|
||||
|
||||
// Font stacks
|
||||
--font-display: #{$font-display};
|
||||
--font-body: #{$font-body};
|
||||
--font-mono: #{$font-mono};
|
||||
|
||||
// Spacing (8px base from light design doc)
|
||||
--spacing-xs: 4px;
|
||||
--spacing-sm: 8px;
|
||||
--spacing-md: 16px;
|
||||
--spacing-lg: 24px;
|
||||
--spacing-xl: 32px;
|
||||
--spacing-section: 120px;
|
||||
--spacing-section-mobile: 64px;
|
||||
|
||||
// Border radius
|
||||
--radius-sm: #{$radius-sm};
|
||||
--radius: #{$radius-default};
|
||||
--radius-md: #{$radius-md};
|
||||
--radius-lg: #{$radius-lg};
|
||||
--radius-xl: #{$radius-xl};
|
||||
--radius-full: #{$radius-full};
|
||||
|
||||
// Elevation
|
||||
--shadow-card-hover: 0px 4px 20px rgba(15, 23, 42, 0.05);
|
||||
--glow-primary: 0 0 0 3px rgba(80, 167, 250, 0.2);
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// CSS Custom Properties — Dark Mode Overrides
|
||||
// =============================================================================
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
// Surface
|
||||
--color-surface: #{$dk-surface};
|
||||
--color-surface-dim: #{$dk-surface-dim};
|
||||
--color-surface-bright: #{$dk-surface-bright};
|
||||
--color-surface-container-lowest: #{$dk-surface-container-lowest};
|
||||
--color-surface-container-low: #{$dk-surface-container-low};
|
||||
--color-surface-container: #{$dk-surface-container};
|
||||
--color-surface-container-high: #{$dk-surface-container-high};
|
||||
--color-surface-container-highest: #{$dk-surface-container-highest};
|
||||
--color-on-surface: #{$dk-on-surface};
|
||||
--color-on-surface-variant: #{$dk-on-surface-variant};
|
||||
--color-outline: #{$dk-outline};
|
||||
--color-outline-variant: #{$dk-outline-variant};
|
||||
--color-surface-tint: #{$dk-surface-tint};
|
||||
--color-surface-variant: #{$dk-surface-variant};
|
||||
--color-surface-container-lowest-rgb: 6, 14, 32;
|
||||
|
||||
// Primary
|
||||
--color-primary: #{$dk-primary};
|
||||
--color-on-primary: #{$dk-on-primary};
|
||||
--color-primary-container: #{$dk-primary-container};
|
||||
--color-on-primary-container: #{$dk-on-primary-container};
|
||||
--color-inverse-primary: #{$dk-inverse-primary};
|
||||
|
||||
// Secondary
|
||||
--color-secondary: #{$dk-secondary};
|
||||
--color-on-secondary: #{$dk-on-secondary};
|
||||
--color-secondary-container: #{$dk-secondary-container};
|
||||
--color-on-secondary-container: #{$dk-on-secondary-container};
|
||||
|
||||
// Tertiary
|
||||
--color-tertiary: #{$dk-tertiary};
|
||||
--color-on-tertiary: #{$dk-on-tertiary};
|
||||
--color-tertiary-container: #{$dk-tertiary-container};
|
||||
--color-on-tertiary-container: #{$dk-on-tertiary-container};
|
||||
|
||||
// Error
|
||||
--color-error: #{$dk-error};
|
||||
--color-on-error: #{$dk-on-error};
|
||||
--color-error-container: #{$dk-error-container};
|
||||
--color-on-error-container: #{$dk-on-error-container};
|
||||
|
||||
// Background
|
||||
--color-background: #{$dk-background};
|
||||
--color-on-background: #{$dk-on-background};
|
||||
|
||||
// Elevation adjustments for dark backgrounds
|
||||
--shadow-card-hover: 0px 4px 20px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Base Styles
|
||||
// =============================================================================
|
||||
|
||||
body {
|
||||
background-color: var(--color-background);
|
||||
color: var(--color-on-surface);
|
||||
font-family: var(--font-body);
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: var(--font-display);
|
||||
}
|
||||
|
||||
code, kbd, pre, samp {
|
||||
font-family: var(--font-mono);
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Typography Utility Classes
|
||||
// =============================================================================
|
||||
|
||||
.text-display-lg {
|
||||
font-family: var(--font-display);
|
||||
font-size: 64px;
|
||||
font-weight: 700;
|
||||
line-height: 1.1;
|
||||
letter-spacing: -0.02em;
|
||||
|
||||
@media (max-width: 768px) {
|
||||
font-size: 40px;
|
||||
line-height: 1.2;
|
||||
}
|
||||
}
|
||||
|
||||
.text-headline-md {
|
||||
font-family: var(--font-display);
|
||||
font-size: 32px;
|
||||
font-weight: 600;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.text-body-lg {
|
||||
font-family: var(--font-body);
|
||||
font-size: 18px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.text-body-md {
|
||||
font-family: var(--font-body);
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
// Primary label style (light design doc)
|
||||
.text-label-sm {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
// Variant with uppercase transform (dark design doc)
|
||||
.text-label-caps {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
line-height: 1;
|
||||
letter-spacing: 0.05em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Component Overrides
|
||||
// All colors use var(--color-*) to auto-switch between modes.
|
||||
// =============================================================================
|
||||
|
||||
// --- Buttons ---
|
||||
|
||||
.btn-primary {
|
||||
// #50a7fa is the shared anchor; light text gives better contrast
|
||||
color: $lt-on-primary; // #ffffff
|
||||
|
||||
&:hover,
|
||||
&:focus-visible {
|
||||
color: $lt-on-primary;
|
||||
box-shadow: var(--glow-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.btn-outline-primary {
|
||||
&:hover,
|
||||
&:focus-visible {
|
||||
box-shadow: var(--glow-primary);
|
||||
}
|
||||
}
|
||||
|
||||
// --- Cards ---
|
||||
// Project cards: border shifts to azure on hover, subtle shadow appears
|
||||
|
||||
.card {
|
||||
background-color: var(--color-surface-container);
|
||||
border: 1px solid var(--color-outline-variant);
|
||||
border-radius: var(--radius-lg); // 1rem — large containers per design doc
|
||||
box-shadow: none;
|
||||
transition: border-color 0.2s ease, box-shadow 0.2s ease;
|
||||
|
||||
&:hover {
|
||||
border-color: #50a7fa;
|
||||
box-shadow: var(--shadow-card-hover);
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-family: var(--font-display);
|
||||
color: var(--color-on-surface);
|
||||
}
|
||||
}
|
||||
|
||||
// --- Form Inputs ---
|
||||
|
||||
.form-control,
|
||||
.form-select {
|
||||
background-color: var(--color-surface-container-low);
|
||||
border-color: var(--color-outline-variant);
|
||||
color: var(--color-on-surface);
|
||||
|
||||
&::placeholder {
|
||||
color: var(--color-on-surface-variant);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
background-color: var(--color-surface-container-low);
|
||||
border-color: #50a7fa;
|
||||
color: var(--color-on-surface);
|
||||
box-shadow: var(--glow-primary);
|
||||
}
|
||||
}
|
||||
|
||||
// JetBrains Mono for all form labels
|
||||
label,
|
||||
.form-label {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.05em;
|
||||
color: var(--color-on-surface-variant);
|
||||
}
|
||||
|
||||
// --- Navbar ---
|
||||
// Sticky glassmorphism; links use JetBrains Mono (label-sm style)
|
||||
|
||||
.navbar {
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
// rgba() with RGB channel variable — correct way to compose transparency on a CSS var color
|
||||
background-color: rgba(var(--color-surface-container-lowest-rgb), 0.85);
|
||||
border-bottom: 1px solid var(--color-outline-variant);
|
||||
|
||||
.nav-link {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.05em;
|
||||
color: var(--color-on-surface);
|
||||
transition: color 0.15s ease;
|
||||
|
||||
&:hover,
|
||||
&.active {
|
||||
color: #50a7fa;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- Tech Chips / Badges ---
|
||||
|
||||
.badge-tech {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.05em;
|
||||
border-radius: var(--radius);
|
||||
padding: 4px 8px;
|
||||
background-color: rgba(80, 167, 250, 0.1);
|
||||
// --color-primary is #0061a2 (light) / #9dcaff (dark) — both readable on their backgrounds
|
||||
color: var(--color-primary);
|
||||
border: 1px solid rgba(80, 167, 250, 0.25);
|
||||
}
|
||||
|
||||
// --- Code Blocks ---
|
||||
|
||||
pre {
|
||||
position: relative;
|
||||
background-color: var(--color-surface-container-lowest);
|
||||
border: 1px solid var(--color-outline-variant);
|
||||
border-radius: var(--radius);
|
||||
|
||||
code {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 14px;
|
||||
color: var(--color-on-surface);
|
||||
}
|
||||
|
||||
.code-lang {
|
||||
position: absolute;
|
||||
top: var(--spacing-sm);
|
||||
right: var(--spacing-md);
|
||||
font-family: var(--font-mono);
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.05em;
|
||||
text-transform: uppercase;
|
||||
color: var(--color-on-surface-variant);
|
||||
}
|
||||
}
|
||||
|
||||
// --- Interactive Glow Helper ---
|
||||
|
||||
.interactive-glow {
|
||||
transition: box-shadow 0.2s ease;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
box-shadow: var(--glow-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.material-symbols-outlined {
|
||||
font-family: 'Material Symbols Outlined';
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-size: 20px;
|
||||
display: inline-block;
|
||||
line-height: 1;
|
||||
text-transform: none;
|
||||
letter-spacing: normal;
|
||||
word-wrap: normal;
|
||||
white-space: nowrap;
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
.footer-link {
|
||||
color: rgba(255, 255, 255, .6);
|
||||
transition: color .15s ease;
|
||||
}
|
||||
|
||||
.footer-link:hover {
|
||||
color: var(--color-primary-container);
|
||||
}
|
||||
|
||||
#footer {
|
||||
z-index: 50;
|
||||
background: rgba(0,0,0,.3);
|
||||
backdrop-filter: blur(8px);
|
||||
-webkit-backdrop-filter: blur(8px);
|
||||
border-color: rgba(192, 199, 211, .1) !important;
|
||||
}
|
||||
|
||||
#footer-copyright {
|
||||
color: rgba(255,255,255,.4);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
nav div {
|
||||
height: 64px;
|
||||
}
|
||||
|
||||
/* Glassmorphism nav — uses RGB channel var for rgba() composition */
|
||||
.nav-glass {
|
||||
background-color: rgba(var(--color-surface-container-lowest-rgb), .85);
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
}
|
||||
|
||||
/* Nav link colours — needs :hover, can't do inline */
|
||||
.nav-link-ds {
|
||||
color: var(--color-on-surface-variant);
|
||||
transition: color .15s ease;
|
||||
}
|
||||
|
||||
.nav-link-ds:hover {
|
||||
color: #50a7fa;
|
||||
}
|
||||
|
||||
#top-nav {
|
||||
z-index: 50;
|
||||
border-color: rgba(192, 199, 211, .3) !important;
|
||||
}
|
||||
|
||||
#nav-site-name {
|
||||
font-family: var(--font-display);
|
||||
letter-spacing: -.02em;
|
||||
font-size: 1rem;
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
body {
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
/* Scanline sweep */
|
||||
.scanline {
|
||||
position: absolute;
|
||||
bottom: 100%;
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
pointer-events: none;
|
||||
background: linear-gradient(0deg, transparent 0%, rgba(80, 167, 250, .05) 50%, transparent 100%);
|
||||
opacity: .1;
|
||||
animation: scanline 8s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes scanline {
|
||||
0% {
|
||||
bottom: 100%;
|
||||
}
|
||||
100% {
|
||||
bottom: -100px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Primary hero button shimmer */
|
||||
.hero-btn-primary {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.hero-btn-primary::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: rgba(255, 255, 255, .2);
|
||||
transform: translateY(100%);
|
||||
transition: transform .3s ease;
|
||||
}
|
||||
|
||||
.hero-btn-primary:hover::before {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
/* Azure glow on hover */
|
||||
.glow-hover:hover {
|
||||
box-shadow: 0 0 25px rgba(80, 167, 250, .4);
|
||||
}
|
||||
|
||||
.badge {
|
||||
background: rgba(80, 167, 250, .1);
|
||||
border: 1px solid rgba(80, 167, 250, .3);
|
||||
}
|
||||
|
||||
.badge .text-label-sm {
|
||||
color: var(--color-primary-container);
|
||||
letter-spacing: .15em;
|
||||
}
|
||||
|
||||
/* Pulsing availability dot */
|
||||
.dot-pulse {
|
||||
animation: dot-pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;
|
||||
|
||||
display: inline-block;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background: #50a7fa;
|
||||
}
|
||||
|
||||
@keyframes dot-pulse {
|
||||
0%, 100% {
|
||||
opacity: 1;
|
||||
}
|
||||
50% {
|
||||
opacity: .35;
|
||||
}
|
||||
}
|
||||
|
||||
.headline {
|
||||
text-shadow: 0 2px 4px rgba(0, 0, 0, .8);
|
||||
}
|
||||
|
||||
.headline span {
|
||||
color: var(--color-primary-container);
|
||||
}
|
||||
|
||||
.subheadline {
|
||||
max-width: 640px;
|
||||
color: rgba(255, 255, 255, .85);
|
||||
text-shadow: 0 1px 2px rgba(0, 0, 0, .9);
|
||||
}
|
||||
|
||||
/* Scroll indicator line */
|
||||
.scroll-line {
|
||||
width: 1px;
|
||||
height: 48px;
|
||||
background: linear-gradient(to bottom, #50a7fa, transparent);
|
||||
}
|
||||
|
||||
.hud-decorator-line {
|
||||
width: 128px;
|
||||
height: 1px;
|
||||
background-color: var(--color-primary-container);
|
||||
}
|
||||
|
||||
.hud-decorator {
|
||||
opacity: .4;
|
||||
}
|
||||
|
||||
.hud-decorator p {
|
||||
color: var(--color-primary-container);
|
||||
letter-spacing: .3em;
|
||||
}
|
||||
|
||||
#bg {
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
#bg-img {
|
||||
filter: grayscale(.2) brightness(.75);
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
#bg-overlay {
|
||||
background: linear-gradient(to bottom, rgba(0, 0, 0, .6) 0%, transparent 50%, rgba(0, 0, 0, .8) 100%);
|
||||
}
|
||||
|
||||
#content-div {
|
||||
z-index: 10;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
#hud-decorator-top-left {
|
||||
margin-top: 96px;
|
||||
}
|
||||
|
||||
#hud-decorator-bottom-right {
|
||||
margin-bottom: 96px;
|
||||
}
|
||||
|
||||
#hud-decorator-bottom span {
|
||||
letter-spacing: .2em;
|
||||
}
|
||||
|
||||
#hero-content {
|
||||
max-width: 896px;
|
||||
}
|
||||
|
||||
#button-about-me {
|
||||
background: rgba(255, 255, 255, .05);
|
||||
border: 1px solid rgba(255, 255, 255, .2);
|
||||
backdrop-filter: blur(4px);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import "../../styles/root/root.css";
|
||||
|
||||
document.addEventListener('mousemove', (e) => {
|
||||
const bg = document.getElementById('bg-img');
|
||||
const x = (e.clientX - window.innerWidth / 2) * 0.005;
|
||||
const y = (e.clientY - window.innerHeight / 2) * 0.005;
|
||||
|
||||
if (bg) {
|
||||
bg.style.transform = `scale(1.05) translate(${x}px, ${y}px)`;
|
||||
}
|
||||
});
|
||||
+9
-2
@@ -10,14 +10,20 @@
|
||||
"ext-ctype": "*",
|
||||
"ext-iconv": "*",
|
||||
"ext-redis": "*",
|
||||
"symfony/asset": "8.1.*",
|
||||
"symfony/asset-mapper": "8.1.*",
|
||||
"symfony/cache": "8.1.*",
|
||||
"symfony/console": "8.1.*",
|
||||
"symfony/dotenv": "8.1.*",
|
||||
"symfony/flex": "^2",
|
||||
"symfony/framework-bundle": "8.1.*",
|
||||
"symfony/runtime": "8.1.*",
|
||||
"symfony/twig-bundle": "8.1.*",
|
||||
"symfony/web-link": "8.1.*",
|
||||
"symfony/webpack-encore-bundle": "^2.4",
|
||||
"symfony/yaml": "8.1.*"
|
||||
"symfony/yaml": "8.1.*",
|
||||
"twig/extra-bundle": "^2.12|^3.0",
|
||||
"twig/twig": "^2.12|^3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/debug-bundle": "8.1.*",
|
||||
@@ -47,7 +53,8 @@
|
||||
"scripts": {
|
||||
"auto-scripts": {
|
||||
"cache:clear": "symfony-cmd",
|
||||
"assets:install %PUBLIC_DIR%": "symfony-cmd"
|
||||
"assets:install %PUBLIC_DIR%": "symfony-cmd",
|
||||
"importmap:install": "symfony-cmd"
|
||||
},
|
||||
"post-install-cmd": [
|
||||
"@auto-scripts"
|
||||
|
||||
Generated
+906
-355
File diff suppressed because it is too large
Load Diff
@@ -7,4 +7,5 @@ return [
|
||||
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
|
||||
Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
|
||||
Symfony\WebpackEncoreBundle\WebpackEncoreBundle::class => ['all' => true],
|
||||
Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true],
|
||||
];
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
framework:
|
||||
asset_mapper:
|
||||
# The paths to make available to the asset mapper.
|
||||
paths:
|
||||
- assets/
|
||||
missing_import_mode: strict
|
||||
|
||||
when@prod:
|
||||
framework:
|
||||
asset_mapper:
|
||||
missing_import_mode: warn
|
||||
@@ -17,3 +17,7 @@ when@test:
|
||||
test: true
|
||||
session:
|
||||
storage_factory_id: session.storage.factory.mock_file
|
||||
|
||||
when@prod:
|
||||
framework:
|
||||
http_cache: true
|
||||
|
||||
+54
-3
@@ -286,7 +286,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
|
||||
* }>,
|
||||
* },
|
||||
* asset_mapper?: bool|array{ // Asset Mapper configuration
|
||||
* enabled?: bool|Param, // Default: false
|
||||
* enabled?: bool|Param, // Default: true
|
||||
* paths?: string|array<string, scalar|Param|null>,
|
||||
* excluded_patterns?: list<scalar|Param|null>,
|
||||
* exclude_dotfiles?: bool|Param, // If true, any files starting with "." will be excluded from the asset mapper. // Default: true
|
||||
@@ -416,7 +416,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
|
||||
* log_channel?: scalar|Param|null, // The channel of log message. Null to let Symfony decide. // Default: null
|
||||
* }>,
|
||||
* web_link?: bool|array{ // Web links configuration
|
||||
* enabled?: bool|Param, // Default: false
|
||||
* enabled?: bool|Param, // Default: true
|
||||
* },
|
||||
* lock?: bool|string|array{ // Lock configuration
|
||||
* enabled?: bool|Param, // Default: false
|
||||
@@ -471,7 +471,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
|
||||
* },
|
||||
* disallow_search_engine_index?: bool|Param, // Enabled by default when debug is enabled. // Default: true
|
||||
* http_client?: bool|array{ // HTTP Client configuration
|
||||
* enabled?: bool|Param, // Default: false
|
||||
* enabled?: bool|Param, // Default: true
|
||||
* max_host_connections?: int|Param, // The maximum number of connections to a single host.
|
||||
* default_options?: array{
|
||||
* headers?: array<string, mixed>,
|
||||
@@ -763,6 +763,53 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
|
||||
* script_attributes?: array<string, scalar|Param|null>,
|
||||
* link_attributes?: array<string, scalar|Param|null>,
|
||||
* }
|
||||
* @psalm-type TwigExtraConfig = array{
|
||||
* cache?: bool|array{
|
||||
* enabled?: bool|Param, // Default: false
|
||||
* },
|
||||
* html?: bool|array{
|
||||
* enabled?: bool|Param, // Default: false
|
||||
* },
|
||||
* markdown?: bool|array{
|
||||
* enabled?: bool|Param, // Default: false
|
||||
* },
|
||||
* intl?: bool|array{
|
||||
* enabled?: bool|Param, // Default: false
|
||||
* },
|
||||
* cssinliner?: bool|array{
|
||||
* enabled?: bool|Param, // Default: false
|
||||
* },
|
||||
* inky?: bool|array{
|
||||
* enabled?: bool|Param, // Default: false
|
||||
* },
|
||||
* string?: bool|array{
|
||||
* enabled?: bool|Param, // Default: false
|
||||
* },
|
||||
* commonmark?: array{
|
||||
* renderer?: array{ // Array of options for rendering HTML.
|
||||
* block_separator?: scalar|Param|null,
|
||||
* inner_separator?: scalar|Param|null,
|
||||
* soft_break?: scalar|Param|null,
|
||||
* },
|
||||
* html_input?: "strip"|"allow"|"escape"|Param, // How to handle HTML input.
|
||||
* allow_unsafe_links?: bool|Param, // Remove risky link and image URLs by setting this to false. // Default: true
|
||||
* max_nesting_level?: int|Param, // The maximum nesting level for blocks. // Default: 9223372036854775807
|
||||
* max_delimiters_per_line?: int|Param, // The maximum number of strong/emphasis delimiters per line. // Default: 9223372036854775807
|
||||
* slug_normalizer?: array{ // Array of options for configuring how URL-safe slugs are created.
|
||||
* instance?: mixed,
|
||||
* max_length?: int|Param, // Default: 255
|
||||
* unique?: mixed,
|
||||
* },
|
||||
* commonmark?: array{ // Array of options for configuring the CommonMark core extension.
|
||||
* enable_em?: bool|Param, // Default: true
|
||||
* enable_strong?: bool|Param, // Default: true
|
||||
* use_asterisk?: bool|Param, // Default: true
|
||||
* use_underscore?: bool|Param, // Default: true
|
||||
* unordered_list_markers?: list<scalar|Param|null>,
|
||||
* },
|
||||
* ...<string, mixed>
|
||||
* },
|
||||
* }
|
||||
* @psalm-type ConfigType = array{
|
||||
* imports?: ImportsConfig,
|
||||
* parameters?: ParametersConfig,
|
||||
@@ -770,6 +817,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
|
||||
* framework?: FrameworkConfig,
|
||||
* twig?: TwigConfig,
|
||||
* webpack_encore?: WebpackEncoreConfig,
|
||||
* twig_extra?: TwigExtraConfig,
|
||||
* "when@dev"?: array{
|
||||
* imports?: ImportsConfig,
|
||||
* parameters?: ParametersConfig,
|
||||
@@ -780,6 +828,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
|
||||
* twig?: TwigConfig,
|
||||
* maker?: MakerConfig,
|
||||
* webpack_encore?: WebpackEncoreConfig,
|
||||
* twig_extra?: TwigExtraConfig,
|
||||
* },
|
||||
* "when@prod"?: array{
|
||||
* imports?: ImportsConfig,
|
||||
@@ -788,6 +837,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
|
||||
* framework?: FrameworkConfig,
|
||||
* twig?: TwigConfig,
|
||||
* webpack_encore?: WebpackEncoreConfig,
|
||||
* twig_extra?: TwigExtraConfig,
|
||||
* },
|
||||
* "when@test"?: array{
|
||||
* imports?: ImportsConfig,
|
||||
@@ -798,6 +848,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param;
|
||||
* debug?: DebugConfig,
|
||||
* twig?: TwigConfig,
|
||||
* webpack_encore?: WebpackEncoreConfig,
|
||||
* twig_extra?: TwigExtraConfig,
|
||||
* },
|
||||
* ...<string, ExtensionType|array{ // extra keys must follow the when@%env% pattern or match an extension alias
|
||||
* imports?: ImportsConfig,
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Returns the importmap for this application.
|
||||
*
|
||||
* - "path" is a path inside the asset mapper system. Use the
|
||||
* "debug:asset-map" command to see the full list of paths.
|
||||
*
|
||||
* - "entrypoint" (JavaScript only) set to true for any module that will
|
||||
* be used as an "entrypoint" (and passed to the importmap() Twig function).
|
||||
*
|
||||
* The "importmap:require" command can be used to add new entries to this file.
|
||||
*/
|
||||
return [
|
||||
'app' => [
|
||||
'path' => './assets/app.js',
|
||||
'entrypoint' => true,
|
||||
],
|
||||
];
|
||||
@@ -20,5 +20,9 @@
|
||||
"dev": "encore dev",
|
||||
"watch": "encore dev --watch",
|
||||
"build": "encore production --progress"
|
||||
},
|
||||
"dependencies": {
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"bootstrap": "^5.3.8"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ server {
|
||||
include fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_param DOCUMENT_ROOT $document_root;
|
||||
fastcgi_param PHP_IDE_CONFIG "serverName=localhost";
|
||||
fastcgi_buffer_size 128k;
|
||||
fastcgi_buffers 4 256k;
|
||||
fastcgi_busy_buffers_size 256k;
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
|
||||
final class RootController extends AbstractController
|
||||
{
|
||||
#[Route('/', name: 'app_root')]
|
||||
public function index(): Response
|
||||
{
|
||||
return $this->render('root/root.html.twig', [
|
||||
'controller_name' => 'RootController',
|
||||
]);
|
||||
}
|
||||
}
|
||||
+19
-1
@@ -1,4 +1,19 @@
|
||||
{
|
||||
"symfony/asset-mapper": {
|
||||
"version": "8.1",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "6.4",
|
||||
"ref": "c01c47af2ec66a74ec046eccb919cfe27d3464ec"
|
||||
},
|
||||
"files": [
|
||||
"assets/app.js",
|
||||
"assets/styles/app.css",
|
||||
"config/packages/asset_mapper.yaml",
|
||||
"importmap.php"
|
||||
]
|
||||
},
|
||||
"symfony/console": {
|
||||
"version": "8.1",
|
||||
"recipe": {
|
||||
@@ -113,11 +128,14 @@
|
||||
"ref": "b346dae458e64a1921ded2125993d94bd719a8dd"
|
||||
},
|
||||
"files": [
|
||||
"assets/app.ts",
|
||||
"assets/app.js",
|
||||
"assets/styles/app.css",
|
||||
"config/packages/webpack_encore.yaml",
|
||||
"package.json",
|
||||
"webpack.config.js"
|
||||
]
|
||||
},
|
||||
"twig/extra-bundle": {
|
||||
"version": "v3.24.0"
|
||||
}
|
||||
}
|
||||
|
||||
+20
-12
@@ -1,29 +1,37 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>{% block title %}Welcome!{% endblock %}</title>
|
||||
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 128 128%22><text y=%221.2em%22 font-size=%2296%22>⚫️</text><text y=%221.3em%22 x=%220.2em%22 font-size=%2276%22 fill=%22%23fff%22>sf</text></svg>">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% block title %}creative-dragonslayer.de{% endblock %}</title>
|
||||
|
||||
<link rel="icon" href="{{ asset('images/logo.png') }}">
|
||||
|
||||
{% block stylesheets %}
|
||||
{{ encore_entry_link_tags('app') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block head %}{% endblock %}
|
||||
|
||||
{% set frankenphpHotReload = app.request.server.get('FRANKENPHP_HOT_RELOAD') %}
|
||||
{% if frankenphpHotReload %}
|
||||
<meta name="frankenphp-hot-reload:url" content="{{ frankenphpHotReload }}">
|
||||
<script src="https://cdn.jsdelivr.net/npm/idiomorph"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/frankenphp-hot-reload/+esm" type="module"></script>
|
||||
<meta name="frankenphp-hot-reload:url" content="{{ frankenphpHotReload }}">
|
||||
<script src="https://cdn.jsdelivr.net/npm/idiomorph"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/frankenphp-hot-reload/+esm" type="module"></script>
|
||||
{% endif %}
|
||||
</head>
|
||||
<body>
|
||||
{% include 'widgets/nav_bar.html.twig' %}
|
||||
|
||||
<main>
|
||||
{% block body %}{% endblock %}
|
||||
{% block body %}{% endblock %}
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
{% block javascripts %}
|
||||
{{ encore_entry_script_tags('app') }}
|
||||
{% endblock %}
|
||||
</footer>
|
||||
{% include 'widgets/footer.html.twig' %}
|
||||
|
||||
{% block javascripts %}
|
||||
{% block importmap %}{{ importmap('app') }}{% endblock %}
|
||||
{{ encore_entry_script_tags('app') }}
|
||||
{% endblock %}
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}creative-dragonslayer.de | Deep Space Engineering{% endblock %}
|
||||
|
||||
{% block stylesheets %}
|
||||
{{ parent() }}
|
||||
{{ encore_entry_link_tags('root') }}
|
||||
|
||||
<link rel="preload" href="{{ preload(asset('images/root/background.jpg'), { as: 'image' }) }}">
|
||||
{% endblock %}
|
||||
|
||||
{% block javascripts %}
|
||||
{{ parent() }}
|
||||
{{ encore_entry_script_tags('root') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
|
||||
{# ── Fixed Background ────────────────────────────────────────────────────── #}
|
||||
<div id="bg" class="position-fixed top-0 start-0 w-100 h-100">
|
||||
<img
|
||||
id="bg-img"
|
||||
src="{{ asset('images/root/background.jpg') }}"
|
||||
alt="Hintergrundbild"
|
||||
class="w-100 h-100 object-fit-cover"
|
||||
>
|
||||
<div id="bg-overlay" class="position-absolute top-0 start-0 w-100 h-100"></div>
|
||||
<div class="scanline"></div>
|
||||
</div>
|
||||
|
||||
<div id="content-div" class="position-relative d-flex flex-column align-items-center justify-content-center
|
||||
w-100 text-center px-4">
|
||||
{# HUD Decorator — Top Left #}
|
||||
<div id="hud-decorator-top-left"
|
||||
class="hud-decorator position-absolute top-0 start-0 d-none d-xl-flex flex-column gap-3 ps-4">
|
||||
<div class="hud-decorator-line"></div>
|
||||
<p class="text-label-sm mb-0 text-uppercase">System.Status: Stable</p>
|
||||
<p class="text-label-sm mb-0 text-uppercase">Lat: 52.5200° N</p>
|
||||
</div>
|
||||
|
||||
{# HUD Decorator — Bottom Right #}
|
||||
<div id="hud-decorator-bottom-right"
|
||||
class="hud-decorator position-absolute bottom-0 end-0 d-none d-xl-flex flex-column align-items-end gap-3 pe-4">
|
||||
<p class="text-label-sm mb-0 text-end text-uppercase">V.0.9.0 // CORE</p>
|
||||
<p class="text-label-sm mb-0 text-end text-uppercase">Syncing Precision...</p>
|
||||
<div class="hud-decorator-line"></div>
|
||||
</div>
|
||||
|
||||
{# Hero Content #}
|
||||
<div id="hero-content" class="d-flex flex-column align-items-center gap-4">
|
||||
|
||||
{# Badge #}
|
||||
<div class="badge d-inline-flex align-items-center gap-2 px-3 py-1 rounded-pill">
|
||||
<span class="rounded-circle dot-pulse"></span>
|
||||
<span class="text-label-sm text-uppercase">
|
||||
Debugging Life Since 2018
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{# Headline #}
|
||||
<h1 class="text-display-lg mb-0 text-white lh-1 headline">
|
||||
CREATIVE
|
||||
<span class="fst-italic fw-light">
|
||||
DRAGONSLAYER
|
||||
</span>
|
||||
</h1>
|
||||
|
||||
{# Subheadline #}
|
||||
<p class="text-body-lg mb-0 mx-auto subheadline">
|
||||
Code, Kommandozeile und Kaffee. Dies ist eine Sammlung meiner Hobbyprojekte, entwickelt mit
|
||||
Leidenschaft. Hier geht es nicht um Skalierung oder Marktanteile, sondern darum, Probleme zu lösen,
|
||||
die mich beschäftigen, und Techniken auszuprobieren, die mich neugierig machen.
|
||||
</p>
|
||||
|
||||
{# CTAs #}
|
||||
<div class="d-flex flex-column flex-sm-row gap-3 justify-content-center align-items-center mt-2">
|
||||
<a href="#projects"
|
||||
class="hero-btn-primary btn btn-primary text-white fw-bold px-5 py-3 rounded-3
|
||||
glow-hover d-inline-flex align-items-center gap-2">
|
||||
Zu den Projekten
|
||||
<span class="material-symbols-outlined">arrow_forward</span>
|
||||
</a>
|
||||
<a href="#about" id="button-about-me" class="btn fw-bold px-5 py-3 rounded-3 text-white">
|
||||
Werdegang
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Scroll Indicator #}
|
||||
<div id="hud-decorator-bottom" class="position-absolute bottom-0 start-50 translate-middle-x
|
||||
d-flex flex-column align-items-center gap-2 pb-4 hud-decorator">
|
||||
<span class="text-label-sm text-white text-uppercase">Deploying Scroll</span>
|
||||
<div class="scroll-line"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,14 @@
|
||||
<footer class="position-fixed bottom-0 start-0 end-0 border-top"
|
||||
id="footer">
|
||||
<div class="container d-flex flex-column flex-md-row justify-content-between align-items-center py-3">
|
||||
<div id="footer-copyright" class="text-label-sm fw-bold">
|
||||
© 2026 creative-dragonslayer.de
|
||||
</div>
|
||||
<div class="d-flex gap-4 mt-2 mt-md-0">
|
||||
{# <a href="#" class="text-label-sm text-decoration-none footer-link">Impressum</a>#}
|
||||
{# <a href="#" class="text-label-sm text-decoration-none footer-link">Datenschutz</a>#}
|
||||
{# <a href="#" class="text-label-sm text-decoration-none footer-link">Nutzungsbedingungen</a>#}
|
||||
<a href="#" class="text-label-sm text-decoration-none footer-link">Credits</a>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
@@ -0,0 +1,17 @@
|
||||
<nav class="position-fixed top-0 start-0 end-0 nav-glass border-bottom"
|
||||
id="top-nav"
|
||||
aria-label="Hauptnavigation">
|
||||
<div class="container d-flex justify-content-between align-items-center">
|
||||
<span id="nav-site-name" class="fw-bold text-white">
|
||||
CTDRA
|
||||
</span>
|
||||
|
||||
<div class="d-none d-md-flex align-items-center gap-4">
|
||||
<a href="#" class="text-label-sm text-decoration-none nav-link-ds">News</a>
|
||||
<a href="#" class="text-label-sm text-decoration-none nav-link-ds">Projects</a>
|
||||
<a href="#" class="text-label-sm text-decoration-none nav-link-ds">About Me</a>
|
||||
</div>
|
||||
|
||||
<div> </div>
|
||||
</div>
|
||||
</nav>
|
||||
+6
-1
@@ -8,7 +8,12 @@
|
||||
"isolatedModules": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"noEmit": true
|
||||
"noEmit": true,
|
||||
"plugins":[
|
||||
{
|
||||
"name": "typescript-plugin-css"
|
||||
}
|
||||
]
|
||||
},
|
||||
"include": ["assets/**/*"]
|
||||
}
|
||||
|
||||
+6
-1
@@ -20,7 +20,9 @@ Encore
|
||||
* Each entry will result in one JavaScript file (e.g. app.js)
|
||||
* and one CSS file (e.g. app.css) if your JavaScript imports CSS.
|
||||
*/
|
||||
.addEntry('app', './assets/app.ts')
|
||||
.addEntry('app', './assets/app.js')
|
||||
|
||||
.addEntry('root', './assets/ts/root/root.ts')
|
||||
|
||||
// When enabled, Webpack "splits" your files into smaller pieces for greater optimization.
|
||||
.splitEntryChunks()
|
||||
@@ -61,6 +63,9 @@ Encore
|
||||
|
||||
// uncomment if you use TypeScript
|
||||
.enableTypeScriptLoader()
|
||||
// optionally enable forked type script for faster builds
|
||||
// https://www.npmjs.com/package/fork-ts-checker-webpack-plugin
|
||||
// requires that you have a tsconfig.json file that is setup correctly.
|
||||
.enableForkedTypeScriptTypesChecking()
|
||||
|
||||
// uncomment if you use React
|
||||
|
||||
@@ -972,6 +972,11 @@
|
||||
"@parcel/watcher-win32-ia32" "2.5.6"
|
||||
"@parcel/watcher-win32-x64" "2.5.6"
|
||||
|
||||
"@popperjs/core@^2.11.8":
|
||||
version "2.11.8"
|
||||
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f"
|
||||
integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==
|
||||
|
||||
"@sinclair/typebox@^0.34.0":
|
||||
version "0.34.49"
|
||||
resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.34.49.tgz#4f1369234f2ecf693866476c3b2e1b54d2a9d68e"
|
||||
@@ -1323,6 +1328,11 @@ boolbase@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
|
||||
integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==
|
||||
|
||||
bootstrap@^5.3.8:
|
||||
version "5.3.8"
|
||||
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.3.8.tgz#6401a10057a22752d21f4e19055508980656aeed"
|
||||
integrity sha512-HP1SZDqaLDPwsNiqRqi5NcP0SSXciX2s9E+RyqJIIqGo+vJeN5AJVM98CXmW/Wux0nQ5L7jeWUdplCEf0Ee+tg==
|
||||
|
||||
brace-expansion@^1.1.7:
|
||||
version "1.1.15"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.15.tgz#a6d90d54067236e5f42570a3b7378d594d9b7738"
|
||||
|
||||
Reference in New Issue
Block a user