Compare commits
10
Commits
ef45866bb0
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
067ff488d2 | ||
|
|
9121d57dcc | ||
|
|
00436fdf3c | ||
|
|
0f7d7a452a | ||
|
|
2945c32bb6 | ||
|
|
70675c3ccc | ||
|
|
e9b2e30d43 | ||
|
|
dd4b5d98d5 | ||
|
|
dde45bd90b | ||
|
|
e8020ea334 |
@@ -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>
|
||||
@@ -5,7 +5,7 @@
|
||||
* (and its CSS file) in your base layout (base.html.twig).
|
||||
*/
|
||||
|
||||
// require('bootstrap');
|
||||
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 |
+74
-17
@@ -1,3 +1,37 @@
|
||||
@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
|
||||
// =============================================================================
|
||||
@@ -90,8 +124,8 @@ $dk-on-background: #dae2fd;
|
||||
// Shared Tokens — Typography & Radius
|
||||
// =============================================================================
|
||||
|
||||
$font-display: 'Space Grotesk', system-ui, sans-serif;
|
||||
$font-body: 'Geist', system-ui, -apple-system, sans-serif;
|
||||
$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;
|
||||
@@ -325,15 +359,15 @@ $code-color-dark: $dk-tertiary; // #c0c1ff
|
||||
body {
|
||||
background-color: var(--color-background);
|
||||
color: var(--color-on-surface);
|
||||
font-family: var(--font-body);
|
||||
font-family: var(--font-body), sans-serif;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: var(--font-display);
|
||||
font-family: var(--font-display), serif;
|
||||
}
|
||||
|
||||
code, kbd, pre, samp {
|
||||
font-family: var(--font-mono);
|
||||
font-family: var(--font-mono), monospace;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
@@ -341,7 +375,7 @@ code, kbd, pre, samp {
|
||||
// =============================================================================
|
||||
|
||||
.text-display-lg {
|
||||
font-family: var(--font-display);
|
||||
font-family: var(--font-display), serif;
|
||||
font-size: 64px;
|
||||
font-weight: 700;
|
||||
line-height: 1.1;
|
||||
@@ -354,27 +388,27 @@ code, kbd, pre, samp {
|
||||
}
|
||||
|
||||
.text-headline-md {
|
||||
font-family: var(--font-display);
|
||||
font-family: var(--font-display), serif;
|
||||
font-size: 32px;
|
||||
font-weight: 600;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.text-body-lg {
|
||||
font-family: var(--font-body);
|
||||
font-family: var(--font-body), sans-serif;
|
||||
font-size: 18px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.text-body-md {
|
||||
font-family: var(--font-body);
|
||||
font-family: var(--font-body), sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
// Primary label style (light design doc)
|
||||
.text-label-sm {
|
||||
font-family: var(--font-mono);
|
||||
font-family: var(--font-mono), monospace;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
@@ -383,7 +417,7 @@ code, kbd, pre, samp {
|
||||
|
||||
// Variant with uppercase transform (dark design doc)
|
||||
.text-label-caps {
|
||||
font-family: var(--font-mono);
|
||||
font-family: var(--font-mono), monospace;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
line-height: 1;
|
||||
@@ -432,7 +466,7 @@ code, kbd, pre, samp {
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-family: var(--font-display);
|
||||
font-family: var(--font-display), serif;
|
||||
color: var(--color-on-surface);
|
||||
}
|
||||
}
|
||||
@@ -461,7 +495,7 @@ code, kbd, pre, samp {
|
||||
// JetBrains Mono for all form labels
|
||||
label,
|
||||
.form-label {
|
||||
font-family: var(--font-mono);
|
||||
font-family: var(--font-mono), monospace;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.05em;
|
||||
@@ -479,7 +513,7 @@ label,
|
||||
border-bottom: 1px solid var(--color-outline-variant);
|
||||
|
||||
.nav-link {
|
||||
font-family: var(--font-mono);
|
||||
font-family: var(--font-mono), monospace;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.05em;
|
||||
@@ -496,7 +530,7 @@ label,
|
||||
// --- Tech Chips / Badges ---
|
||||
|
||||
.badge-tech {
|
||||
font-family: var(--font-mono);
|
||||
font-family: var(--font-mono), monospace;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.05em;
|
||||
@@ -517,7 +551,7 @@ pre {
|
||||
border-radius: var(--radius);
|
||||
|
||||
code {
|
||||
font-family: var(--font-mono);
|
||||
font-family: var(--font-mono), monospace;
|
||||
font-size: 14px;
|
||||
color: var(--color-on-surface);
|
||||
}
|
||||
@@ -526,7 +560,7 @@ pre {
|
||||
position: absolute;
|
||||
top: var(--spacing-sm);
|
||||
right: var(--spacing-md);
|
||||
font-family: var(--font-mono);
|
||||
font-family: var(--font-mono), monospace;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.05em;
|
||||
@@ -545,3 +579,26 @@ pre {
|
||||
box-shadow: var(--glow-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.material-symbols-outlined {
|
||||
font-family: 'Material Symbols Outlined', serif;
|
||||
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;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// CSS Settings
|
||||
// =============================================================================
|
||||
|
||||
main {
|
||||
margin-top: 64px;
|
||||
margin-bottom: 45px;
|
||||
}
|
||||
|
||||
@@ -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,37 @@
|
||||
nav div {
|
||||
min-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), serif;
|
||||
letter-spacing: -.02em;
|
||||
font-size: 1rem;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#nav-brand-logo {
|
||||
height: 30px;
|
||||
width: auto;
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
body {
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
main {
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
/* 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)`;
|
||||
}
|
||||
});
|
||||
+1
-1
@@ -14,7 +14,7 @@ if (!is_file(dirname(__DIR__).'/vendor/autoload_runtime.php')) {
|
||||
|
||||
require_once dirname(__DIR__).'/vendor/autoload_runtime.php';
|
||||
|
||||
return function (array $context) {
|
||||
return static function (array $context) {
|
||||
$kernel = new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);
|
||||
|
||||
return new Application($kernel);
|
||||
|
||||
+10
-2
@@ -10,14 +10,21 @@
|
||||
"ext-ctype": "*",
|
||||
"ext-iconv": "*",
|
||||
"ext-redis": "*",
|
||||
"ext-zend-opcache": "*",
|
||||
"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 +54,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
+908
-356
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
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
|
||||
if (file_exists(dirname(__DIR__).'/var/cache/prod/App_KernelProdContainer.preload.php')) {
|
||||
require dirname(__DIR__).'/var/cache/prod/App_KernelProdContainer.preload.php';
|
||||
opcache_compile_file(dirname(__DIR__) . '/var/cache/prod/App_KernelProdContainer.preload.php');
|
||||
}
|
||||
|
||||
+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,31 @@
|
||||
<?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 array<string, array{ // Import name as key, description of the imported file as value
|
||||
* path: string, // Logical, relative or absolute path to the file
|
||||
* type?: 'js'|'css'|'json', // Type of the file, defaults to 'js'
|
||||
* entrypoint?: bool, // Whether the file is an entrypoint, for 'js' only
|
||||
* }|array{
|
||||
* version: string, // Version of the remote package
|
||||
* package_specifier?: string, // Remote "package-name/path" specifier, defaults to the import name
|
||||
* type?: 'js'|'css'|'json',
|
||||
* entrypoint?: bool,
|
||||
* }>
|
||||
*/
|
||||
return [
|
||||
'app' => ['path' => './assets/app.js', 'entrypoint' => true],
|
||||
'@symfony/webpack-encore' => ['version' => '6.0.0'],
|
||||
'bootstrap' => ['version' => '5.3.8'],
|
||||
'@popperjs/core' => ['version' => '2.11.8'],
|
||||
'bootstrap/dist/css/bootstrap.min.css' => ['version' => '5.3.8', 'type' => 'css'],
|
||||
];
|
||||
@@ -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;
|
||||
|
||||
+1
-1
@@ -4,6 +4,6 @@ use App\Kernel;
|
||||
|
||||
require_once dirname(__DIR__).'/vendor/autoload_runtime.php';
|
||||
|
||||
return function (array $context) {
|
||||
return static function (array $context) {
|
||||
return new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);
|
||||
};
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
<!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 }}">
|
||||
@@ -16,14 +21,17 @@
|
||||
{% endif %}
|
||||
</head>
|
||||
<body>
|
||||
{% include 'widgets/nav_bar.html.twig' %}
|
||||
|
||||
<main>
|
||||
{% block body %}{% endblock %}
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
{% include 'widgets/footer.html.twig' %}
|
||||
|
||||
{% block javascripts %}
|
||||
{% block importmap %}{{ importmap('app') }}{% endblock %}
|
||||
{{ encore_entry_script_tags('app') }}
|
||||
{% endblock %}
|
||||
</footer>
|
||||
</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,51 @@
|
||||
<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">
|
||||
|
||||
{# Links: Logo + CTDRA #}
|
||||
<a href="/" id="nav-site-name" class="d-flex align-items-center gap-2 text-decoration-none">
|
||||
<img src="{{ asset('images/logo.png') }}"
|
||||
alt="CTDRA Logo"
|
||||
id="nav-brand-logo"
|
||||
style="height: 40px; width: auto;">
|
||||
<span class="fw-bold text-white">CTDRA</span>
|
||||
</a>
|
||||
|
||||
{# Mitte: Desktop-Links zentriert #}
|
||||
<div class="d-none d-md-flex align-items-center gap-4 mx-auto">
|
||||
<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>
|
||||
|
||||
{# Rechts: Hamburger-Button (nur Mobile) + Platzhalter für Desktop #}
|
||||
<div class="d-flex align-items-center">
|
||||
{# Hamburger Button für Mobile mit Material Icon #}
|
||||
<button class="navbar-toggler d-md-none border-0 text-white p-0"
|
||||
type="button"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#mobile-menu"
|
||||
aria-controls="mobile-menu"
|
||||
aria-expanded="false"
|
||||
aria-label="Navigation umschalten">
|
||||
<span class="material-symbols-outlined">menu</span>
|
||||
</button>
|
||||
|
||||
{# Platzhalter für Desktop (hält Balance) #}
|
||||
<div class="d-none d-md-block"> </div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{# Mobile Menu Container (Collapsible) #}
|
||||
<div class="collapse d-md-none" id="mobile-menu">
|
||||
<div class="container py-3">
|
||||
<div class="d-flex flex-column gap-3">
|
||||
<a href="#" class="text-label-sm text-decoration-none text-white fs-6">News</a>
|
||||
<a href="#" class="text-label-sm text-decoration-none text-white fs-6">Projects</a>
|
||||
<a href="#" class="text-label-sm text-decoration-none text-white fs-6">About Me</a>
|
||||
</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
|
||||
|
||||
Reference in New Issue
Block a user