fix: cleanup component structure

This commit is contained in:
Alexander Daichendt 2025-06-30 17:58:41 +02:00
parent 2abae63f4b
commit bf720b79ee
19 changed files with 899 additions and 250 deletions

View file

@ -1,14 +0,0 @@
---
const today = new Date();
---
<footer class="bg-gray-100/60 dark:bg-mytheme-900 shadow-sm">
&copy; {today.getFullYear()} Alexander Daichendt. All rights reserved.
</footer>
<style>
footer {
padding: 2em 1em 6em 1em;
color: rgb(var(--gray));
text-align: center;
}
</style>

View file

@ -0,0 +1,275 @@
---
interface Props {
companyName?: string;
ownerName?: string;
address?: {
street?: string;
city?: string;
postalCode?: string;
country?: string;
};
contact?: {
phone?: string;
email: string;
website: string;
};
business?: {
vatId?: string;
registrationOffice?: string;
};
responsiblePerson?: {
name: string;
address: {
street: string;
city: string;
postalCode: string;
country: string;
};
};
}
const {
companyName,
ownerName,
address,
contact,
business,
responsiblePerson,
} = Astro.props;
---
<div class="max-w-4xl mx-auto space-y-12">
<section>
<h2
class="text-2xl font-bold text-gray-900 dark:text-white mb-6 border-b border-gray-200 dark:border-gray-700 pb-3"
>
Diensteanbieter
</h2>
<div class="space-y-4">
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<dt class="font-semibold text-gray-900 dark:text-white">Firmenname:</dt>
<dd class="md:col-span-2 text-gray-700 dark:text-gray-300">
{companyName}
</dd>
</div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<dt class="font-semibold text-gray-900 dark:text-white">Inhaber:</dt>
<dd class="md:col-span-2 text-gray-700 dark:text-gray-300">
{ownerName}
</dd>
</div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<dt class="font-semibold text-gray-900 dark:text-white">Anschrift:</dt>
<dd class="md:col-span-2 text-gray-700 dark:text-gray-300">
{address?.street}<br />
{address?.postalCode}
{address?.city}<br />
{address?.country}
</dd>
</div>
</div>
</section>
<!-- Contact Information -->
<section>
<h2
class="text-2xl font-bold text-gray-900 dark:text-white mb-6 border-b border-gray-200 dark:border-gray-700 pb-3"
>
Kontaktdaten
</h2>
<div class="space-y-4">
{
contact?.phone && (
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<dt class="font-semibold text-gray-900 dark:text-white">
Telefon:
</dt>
<dd class="md:col-span-2 text-gray-700 dark:text-gray-300">
{contact?.phone}
</dd>
</div>
)
}
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<dt class="font-semibold text-gray-900 dark:text-white">E-Mail:</dt>
<dd class="md:col-span-2">
<a
href={`mailto:${contact?.email}`}
class="text-blue-600 dark:text-blue-400 hover:text-blue-800 dark:hover:text-blue-300 underline"
>
{contact?.email}
</a>
</dd>
</div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<dt class="font-semibold text-gray-900 dark:text-white">Website:</dt>
<dd class="md:col-span-2">
<a
href={contact?.website}
target="_blank"
rel="noopener noreferrer"
class="text-blue-600 dark:text-blue-400 hover:text-blue-800 dark:hover:text-blue-300 underline"
>
{contact?.website}
</a>
</dd>
</div>
</div>
</section>
<!-- Business Registration -->
{
(business?.vatId || business?.registrationOffice) && (
<section>
<h2 class="text-2xl font-bold text-gray-900 dark:text-white mb-6 border-b border-gray-200 dark:border-gray-700 pb-3">
Gewerbliche Angaben
</h2>
<div class="space-y-4">
{business?.vatId && (
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<dt class="font-semibold text-gray-900 dark:text-white">
Umsatzsteuer-ID:
</dt>
<dd class="md:col-span-2 text-gray-700 dark:text-gray-300">
{business.vatId}
<br />
<span class="text-sm text-gray-500 dark:text-gray-400">
gemäß § 27a Umsatzsteuergesetz
</span>
</dd>
</div>
)}
{business.registrationOffice && (
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<dt class="font-semibold text-gray-900 dark:text-white">
Gewerbeanmeldung:
</dt>
<dd class="md:col-span-2 text-gray-700 dark:text-gray-300">
{business?.registrationOffice}
</dd>
</div>
)}
</div>
</section>
)
}
<!-- Responsible for Content -->
<section>
<h2
class="text-2xl font-bold text-gray-900 dark:text-white mb-6 border-b border-gray-200 dark:border-gray-700 pb-3"
>
Verantwortlich für den Inhalt
</h2>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<dt class="font-semibold text-gray-900 dark:text-white">
Verantwortlich nach § 55 Abs. 2 RStV:
</dt>
<dd class="md:col-span-2 text-gray-700 dark:text-gray-300">
{responsiblePerson?.name}<br />
{responsiblePerson?.address.street}<br />
{responsiblePerson?.address.postalCode}
{responsiblePerson?.address.city}<br />
{responsiblePerson?.address.country}
</dd>
</div>
</section>
<!-- EU Dispute Resolution -->
<section>
<h2
class="text-2xl font-bold text-gray-900 dark:text-white mb-6 border-b border-gray-200 dark:border-gray-700 pb-3"
>
EU-Streitschlichtung
</h2>
<div class="space-y-4">
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<dt class="font-semibold text-gray-900 dark:text-white">
Online-Streitbeilegung:
</dt>
<dd class="md:col-span-2 text-gray-700 dark:text-gray-300">
Die Europäische Kommission stellt eine Plattform zur
Online-Streitbeilegung (OS) bereit:<br />
<a
href="https://ec.europa.eu/consumers/odr/"
target="_blank"
rel="noopener noreferrer"
class="text-blue-600 dark:text-blue-400 hover:text-blue-800 dark:hover:text-blue-300 underline"
>
https://ec.europa.eu/consumers/odr/
</a>
</dd>
</div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<dt class="font-semibold text-gray-900 dark:text-white">
Verbraucherschlichtung:
</dt>
<dd class="md:col-span-2 text-gray-700 dark:text-gray-300">
Wir sind nicht bereit oder verpflichtet, an Streitbeilegungsverfahren
vor einer Verbraucherschlichtungsstelle teilzunehmen.
</dd>
</div>
</div>
</section>
<!-- Disclaimer Section -->
<section>
<h2
class="text-2xl font-bold text-gray-900 dark:text-white mb-6 border-b border-gray-200 dark:border-gray-700 pb-3"
>
Haftungsausschluss
</h2>
<!-- Content Liability -->
<div class="mb-8">
<h3 class="text-lg font-semibold text-gray-900 dark:text-white mb-4">
Haftung für Inhalte
</h3>
<p class="text-gray-700 dark:text-gray-300 leading-relaxed">
Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf
diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8
bis 10 TMG sind wir als Diensteanbieter jedoch nicht unter der
Verpflichtung, übermittelte oder gespeicherte fremde Informationen zu
überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige
Tätigkeit hinweisen.
</p>
</div>
<!-- Links Liability -->
<div class="mb-8">
<h3 class="text-lg font-semibold text-gray-900 dark:text-white mb-4">
Haftung für Links
</h3>
<p class="text-gray-700 dark:text-gray-300 leading-relaxed">
Unser Angebot enthält Links zu externen Websites Dritter, auf deren
Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden
Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten
Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten
verantwortlich.
</p>
</div>
<!-- Copyright -->
<div class="mb-8">
<h3 class="text-lg font-semibold text-gray-900 dark:text-white mb-4">
Urheberrecht
</h3>
<p class="text-gray-700 dark:text-gray-300 leading-relaxed">
Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen
Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung,
Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der
Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des
jeweiligen Autors bzw. Erstellers.
</p>
</div>
</section>
<!-- Footer Note -->
<div class="border-t border-gray-200 dark:border-gray-600 pt-8 mt-12">
<p class="text-sm text-gray-500 dark:text-gray-400 text-center">
Letzte Aktualisierung: <span class="font-medium">
{new Date().toLocaleDateString("de-DE")}
</span>
</p>
</div>
</div>

168
src/components/Logo.astro Normal file
View file

@ -0,0 +1,168 @@
<!--?xml version="1.0" encoding="UTF-8" standalone="no"?-->
<svg
version="1.0"
width="3364pt"
height="832pt"
viewBox="0 0 3364 832"
preserveAspectRatio="xMidYMid"
id="svg44"
class="logo"
xmlns="http://www.w3.org/2000/svg"
>
<g
transform="matrix(0.1,0,0,-0.1,-312.98366,2490.1118)"
stroke="none"
id="g44"
class="logo-group"
>
<path
d="m 4485,24500 c -123,-9 -208,-30 -304,-75 -324,-154 -540,-444 -581,-785 -14,-114 -14,-5531 0,-5722 17,-236 62,-375 172,-535 135,-196 338,-342 568,-406 l 75,-21 2762,-4 c 2804,-3 3115,0 3238,33 93,25 255,108 336,173 216,172 354,409 373,642 3,36 6,1363 8,2950 2,2719 1,2889 -15,2960 -35,150 -87,259 -186,389 -108,142 -225,236 -386,312 -126,59 -224,79 -430,90 -214,10 -5485,9 -5630,-1 z m 5700,-411 c 205,-25 386,-151 475,-333 82,-165 75,114 75,-3041 v -2810 l -22,-82 c -51,-190 -161,-327 -328,-408 -141,-68 45,-64 -3039,-65 -2759,-1 -2782,-1 -2859,19 -116,30 -190,74 -282,166 -93,92 -145,184 -173,305 -16,70 -17,253 -15,2898 2,3087 -2,2873 59,2994 82,165 211,282 374,340 l 65,23 1650,6 c 2136,7 3902,2 4020,-12 z"
id="path1"></path>
<path
d="m 6386,23148 c -15,-23 -124,-291 -294,-723 -125,-316 -183,-470 -407,-1065 -106,-283 -274,-724 -373,-980 -216,-559 -431,-1137 -445,-1195 -3,-14 161,-22 474,-24 l 266,-1 36,78 c 33,73 85,196 226,546 33,83 66,155 73,162 10,10 105,13 385,15 205,2 375,0 378,-3 4,-3 9,-417 12,-920 4,-649 9,-915 17,-920 17,-12 1352,-9 1516,2 352,25 581,87 860,232 397,206 682,521 817,902 67,190 88,421 79,861 -6,309 -12,356 -71,560 -34,118 -138,328 -217,437 -91,126 -231,281 -312,347 -272,221 -475,310 -771,341 -94,9 -396,28 -402,25 -1,-1 29,-84 68,-186 38,-101 94,-249 123,-329 78,-211 86,-228 104,-235 9,-4 59,-16 111,-26 352,-70 592,-366 672,-827 44,-258 8,-542 -101,-793 -49,-114 -107,-197 -201,-290 -217,-216 -542,-354 -889,-380 -204,-15 -662,-8 -683,10 -15,12 -17,66 -17,587 0,476 2,575 14,586 9,9 59,19 137,26 67,7 125,14 127,17 13,13 -205,594 -235,628 -15,16 -58,17 -634,17 -339,0 -624,3 -633,6 -14,5 -14,10 0,42 8,21 48,125 89,232 90,239 188,495 220,575 25,63 115,294 167,430 17,44 70,179 118,300 48,121 95,245 105,275 10,30 24,68 32,84 26,50 32,38 193,-394 185,-497 310,-821 457,-1190 277,-695 326,-821 462,-1200 73,-201 151,-417 174,-480 l 43,-115 39,1 c 39,1 232,21 425,45 52,6 128,14 167,18 94,8 103,17 79,79 -10,26 -29,74 -41,107 -12,33 -34,89 -47,125 -14,36 -66,175 -116,310 -222,598 -313,841 -437,1160 -70,178 -118,305 -273,715 -183,488 -403,1049 -520,1330 l -29,70 -239,6 c -131,4 -380,7 -551,8 l -313,1 z"
id="path2"></path>
<path
d="m 18208,22228 c -1,-304 -1,-588 1,-630 2,-43 -1,-78 -6,-78 -5,0 -52,37 -105,83 -166,143 -340,214 -548,224 -189,9 -349,-28 -502,-116 -175,-100 -295,-230 -388,-416 -233,-467 -142,-1104 205,-1434 122,-116 277,-202 430,-237 110,-26 380,-27 475,-1 145,38 312,144 405,256 28,33 55,59 60,57 6,-2 11,-61 13,-144 l 3,-142 h 214 c 117,0 216,3 218,8 6,9 9,822 8,2100 l -1,1022 h -240 -240 z m -433,-855 c 108,-29 184,-72 267,-154 84,-82 131,-165 165,-289 25,-92 25,-348 -1,-440 -28,-103 -83,-197 -165,-283 -60,-63 -91,-86 -155,-117 -100,-47 -160,-60 -284,-60 -177,0 -285,43 -403,159 -84,84 -122,152 -162,289 -18,65 -22,101 -22,232 0,180 13,240 76,367 89,178 240,288 429,313 71,10 179,2 255,-17 z"
id="path3"></path>
<path
d="m 24805,21214 v -1566 l 242,4 c 133,1 244,6 248,10 4,4 9,303 12,665 5,607 6,663 24,724 78,270 377,420 654,327 143,-48 241,-169 271,-337 10,-59 13,-228 14,-735 v -658 l 239,4 c 132,2 243,7 248,12 13,13 16,1294 3,1421 -29,290 -199,563 -417,672 -124,62 -203,76 -391,70 -159,-5 -193,-11 -303,-58 -77,-32 -204,-118 -272,-184 -33,-31 -61,-54 -64,-52 -2,3 -4,285 -3,626 l 1,621 h -253 -253 z"
id="path4"></path>
<path
d="m 33730,22144 c 1,-350 0,-638 -3,-640 -2,-2 -40,29 -84,69 -94,87 -143,122 -240,170 -241,122 -556,121 -798,-1 -147,-73 -244,-153 -335,-274 -101,-134 -179,-306 -216,-478 -28,-128 -26,-412 4,-536 65,-275 193,-497 368,-640 119,-98 302,-181 446,-204 110,-18 353,-8 438,18 143,42 281,132 399,258 38,41 72,74 75,74 3,0 7,-69 8,-152 l 3,-153 216,-3 216,-2 7,297 c 7,316 6,2651 -1,2766 l -5,67 h -249 -250 z m -466,-759 c 240,-51 421,-234 470,-477 20,-95 20,-276 1,-381 -21,-120 -90,-253 -172,-333 -112,-109 -252,-164 -419,-164 -248,0 -435,112 -543,326 -94,186 -113,416 -51,616 47,150 173,304 302,367 117,58 274,75 412,46 z"
id="path5"></path>
<path
d="m 21683,22716 c -90,-28 -179,-110 -201,-184 -62,-206 93,-394 313,-380 93,6 174,47 243,122 60,66 76,110 69,181 -11,110 -103,225 -207,258 -61,20 -158,21 -217,3 z"
id="path6"></path>
<path
d="m 35036,22349 c -3,-34 -6,-174 -6,-310 v -249 h -215 -215 v -149 c 0,-81 3,-176 6,-210 l 7,-61 h 96 c 53,0 146,-3 208,-7 l 111,-6 5,-611 c 5,-674 6,-688 69,-816 45,-92 159,-203 261,-253 176,-86 389,-97 599,-31 126,40 122,32 126,238 4,144 2,176 -9,176 -8,0 -48,-7 -89,-16 -44,-10 -125,-17 -195,-18 -115,-1 -122,0 -169,28 -36,21 -54,40 -70,75 -21,45 -21,54 -21,633 0,322 2,589 5,591 3,3 124,8 270,12 146,4 268,10 272,14 7,6 13,389 6,396 -2,2 -118,6 -258,10 -140,3 -265,8 -277,11 l -23,4 v 305 305 h -244 -243 z"
id="path7"></path>
<path
d="m 13699,21840 c -235,-22 -415,-107 -585,-275 -88,-87 -107,-112 -147,-195 -48,-99 -93,-248 -79,-262 5,-5 109,-11 233,-15 252,-7 232,-12 267,74 60,151 154,218 339,245 162,23 331,-19 406,-101 75,-83 108,-165 122,-300 7,-70 7,-71 -20,-81 -14,-5 -119,-17 -233,-25 -685,-50 -847,-92 -1028,-270 -153,-151 -199,-363 -124,-581 70,-202 278,-372 525,-430 125,-29 322,-25 438,10 48,14 114,39 146,56 67,33 194,128 264,195 26,25 51,44 56,41 5,-3 12,-64 16,-136 7,-122 9,-131 29,-135 11,-3 104,-4 206,-3 l 185,3 6,130 c 10,207 10,1096 -1,1255 -14,213 -52,330 -156,477 -80,113 -217,215 -359,269 -122,45 -342,69 -506,54 z m 559,-1254 c 10,-10 12,-171 3,-219 -15,-84 -38,-124 -106,-193 -69,-70 -162,-122 -270,-150 -97,-25 -291,-26 -360,-1 -124,43 -209,151 -208,265 1,70 12,99 54,146 41,47 93,74 178,91 55,12 422,54 591,68 41,4 111,-1 118,-7 z"
id="path8"></path>
<path
d="m 19935,21840 c -95,-15 -223,-58 -315,-106 -160,-84 -272,-195 -349,-343 -42,-83 -109,-276 -98,-287 9,-9 397,-18 440,-10 21,4 37,11 37,16 0,6 14,40 32,77 70,148 162,204 378,228 75,9 224,-17 288,-49 90,-46 162,-163 188,-305 19,-108 18,-120 -11,-131 -13,-5 -102,-14 -197,-20 -392,-24 -678,-66 -821,-120 -133,-50 -272,-172 -332,-291 -55,-108 -71,-269 -39,-393 60,-232 269,-419 542,-482 89,-21 275,-20 376,1 159,33 302,111 428,233 78,75 72,82 91,-93 l 12,-110 95,-3 c 52,-2 150,0 218,3 l 122,7 v 679 c 0,412 -4,718 -11,777 -39,362 -287,629 -654,707 -93,20 -332,28 -420,15 z m 608,-1388 c -1,-113 -5,-139 -23,-177 -32,-67 -119,-147 -208,-194 -99,-51 -171,-70 -297,-77 -208,-13 -339,58 -391,210 -25,72 -15,135 32,203 61,89 147,118 419,143 72,7 164,16 205,20 41,4 118,7 170,6 l 95,-1 z"
id="path9"></path>
<path
d="m 28005,21826 c -195,-38 -360,-127 -514,-279 -97,-96 -150,-171 -215,-308 -88,-184 -124,-370 -113,-584 13,-246 87,-455 226,-643 116,-156 213,-236 385,-318 156,-74 223,-87 426,-88 151,-1 186,2 260,22 172,46 298,120 441,259 102,98 217,252 204,272 -3,6 -30,23 -58,38 -62,31 -278,123 -289,123 -5,0 -43,-34 -85,-76 -91,-91 -195,-165 -272,-196 -48,-19 -75,-22 -186,-22 -124,0 -134,1 -205,32 -136,58 -230,150 -301,294 -37,73 -76,209 -65,226 3,5 342,12 778,16 495,4 777,11 783,17 17,18 9,274 -13,380 -49,239 -186,470 -372,627 -92,76 -261,163 -380,193 -108,27 -331,35 -435,15 z m 355,-422 c 30,-9 74,-27 97,-41 62,-36 174,-161 215,-240 35,-67 66,-178 53,-191 -4,-4 -247,-8 -541,-10 -613,-3 -552,-16 -511,105 30,88 99,195 168,262 63,59 171,116 249,130 71,13 201,6 270,-15 z"
id="path10"></path>
<path
d="m 23315,21821 c -206,-33 -386,-126 -541,-279 -311,-306 -413,-835 -243,-1260 149,-376 443,-620 808,-673 118,-17 343,-7 446,21 278,72 542,305 655,577 23,54 29,82 23,92 -11,17 -106,35 -258,50 -55,6 -125,13 -156,17 l -57,6 -37,-58 c -111,-177 -272,-274 -452,-274 -211,0 -387,116 -487,322 -114,234 -118,492 -13,707 104,214 267,323 482,323 111,-1 199,-26 281,-81 64,-43 109,-97 170,-204 45,-79 21,-76 259,-33 247,45 255,47 255,60 0,25 -78,181 -128,256 -131,198 -320,341 -537,406 -79,24 -110,27 -255,30 -91,1 -187,-1 -215,-5 z"
id="path11"></path>
<path
d="m 30636,21814 c -155,-34 -251,-84 -411,-213 -55,-44 -103,-77 -107,-75 -5,3 -8,60 -8,128 v 123 l -216,6 c -119,4 -220,5 -224,2 -11,-7 -12,-578 -4,-1418 l 7,-719 236,4 236,3 5,660 c 5,601 7,665 24,715 87,266 307,410 565,372 159,-23 259,-86 327,-208 71,-127 69,-102 69,-862 v -682 h 195 c 107,0 211,3 232,6 l 36,6 6,67 c 4,36 7,356 8,711 2,689 0,733 -48,872 -39,117 -90,195 -188,293 -76,76 -107,99 -186,138 -52,26 -122,54 -155,63 -86,23 -310,28 -399,8 z"
id="path12"></path>
<path
d="m 21540,20721 v -1073 l 239,4 c 132,1 243,7 248,11 9,9 9,2104 0,2113 -3,3 -114,8 -246,11 l -241,6 z"
id="path13"></path>
<path
d="m 15358,20207 c -140,-53 -208,-147 -208,-289 0,-60 5,-84 29,-133 34,-70 88,-126 151,-154 67,-30 188,-29 257,3 60,29 120,85 159,152 24,41 28,58 28,128 1,69 -3,89 -27,138 -30,62 -74,106 -140,140 -53,27 -193,36 -249,15 z"
id="path14"></path>
<path
d="m 15901,18323 c -10,-20 96,-485 148,-653 38,-120 52,-140 96,-140 32,0 34,2 69,86 56,134 136,430 136,504 0,43 10,33 16,-16 7,-55 100,-379 135,-471 35,-89 53,-113 84,-113 30,0 38,12 74,100 23,57 152,530 188,688 5,20 1,22 -30,22 -49,0 -65,-8 -82,-41 -28,-53 -134,-509 -136,-586 -2,-34 -3,-33 -11,17 -28,165 -149,553 -185,592 -10,11 -27,18 -42,16 -28,-3 -43,-45 -172,-455 -41,-130 -59,-162 -59,-104 0,16 -11,71 -24,123 -13,51 -36,145 -51,208 -35,145 -61,217 -85,230 -28,15 -58,12 -69,-7 z"
id="path15"></path>
<path
d="m 17206,18317 c -9,-12 -22,-42 -31,-66 -8,-24 -20,-49 -25,-56 -15,-18 -250,-625 -250,-646 0,-15 7,-19 38,-19 20,0 43,4 50,9 8,4 31,47 51,93 61,136 52,130 178,134 59,2 119,4 132,6 21,3 28,-4 45,-47 77,-193 85,-205 159,-205 45,0 48,-18 -25,185 -80,223 -121,329 -198,505 -54,125 -92,157 -124,107 z m 81,-284 c 28,-87 51,-158 50,-159 -1,-1 -46,-4 -101,-8 l -99,-7 7,33 c 3,18 17,60 31,93 13,34 30,94 36,133 7,40 15,72 18,72 3,0 29,-71 58,-157 z"
id="path16"></path>
<path
d="m 20902,18327 c -13,-15 56,-228 173,-542 93,-249 96,-255 146,-255 46,0 70,44 164,300 30,80 79,213 111,295 71,189 74,202 42,210 -13,3 -36,1 -51,-4 -37,-14 -72,-91 -171,-376 -43,-121 -81,-229 -85,-240 -6,-14 -26,36 -78,190 -100,294 -137,393 -156,416 -19,22 -79,26 -95,6 z"
id="path17"></path>
<path
d="m 31314,18326 c -72,-17 -112,-50 -141,-114 -63,-135 2,-242 192,-317 146,-57 185,-89 185,-149 0,-55 -73,-108 -149,-109 -53,-1 -92,17 -142,66 -45,44 -70,57 -108,57 -25,0 -31,-4 -31,-21 0,-118 221,-243 352,-200 108,36 188,127 188,216 0,106 -62,172 -221,235 -101,40 -158,76 -179,113 -13,24 -13,30 0,54 19,34 85,73 123,73 42,0 86,-22 146,-73 62,-53 88,-59 97,-23 9,37 -23,93 -78,137 -70,55 -152,74 -234,55 z"
id="path18"></path>
<path
d="m 34121,18323 c -33,-28 -308,-750 -297,-780 7,-17 67,-17 88,0 8,6 30,52 47,101 47,131 35,122 143,118 53,-2 106,1 122,7 43,17 66,-4 104,-96 51,-123 64,-140 112,-148 23,-4 46,-3 50,1 5,5 -10,56 -32,114 -22,58 -58,152 -78,210 -135,376 -187,490 -226,490 -6,0 -21,-8 -33,-17 z m 32,-175 c 3,-13 26,-79 52,-147 25,-68 44,-125 43,-126 -7,-4 -203,-24 -206,-20 -3,2 16,64 42,138 25,74 46,144 46,156 0,28 16,27 23,-1 z"
id="path19"></path>
<path
d="m 34672,18327 c -12,-14 -22,-780 -10,-792 13,-13 79,-9 89,5 5,8 9,150 9,315 1,281 2,298 17,270 39,-72 204,-302 311,-435 97,-120 124,-147 156,-158 21,-7 42,-10 45,-6 7,7 10,773 3,792 -2,7 -23,12 -54,12 h -50 l 4,-304 c 3,-282 2,-303 -13,-290 -9,8 -68,90 -130,182 -152,226 -284,391 -326,408 -39,17 -38,17 -51,1 z"
id="path20"></path>
<path
d="m 13091,18311 c -102,-41 -148,-108 -139,-202 9,-88 77,-155 212,-210 179,-72 212,-109 171,-189 -16,-31 -89,-80 -120,-80 -44,0 -102,28 -150,72 -60,54 -93,70 -118,57 -21,-12 -22,-60 -2,-99 16,-31 123,-99 189,-120 66,-21 146,-8 210,35 94,62 121,120 106,228 -8,54 -14,66 -47,95 -40,35 -86,59 -191,98 -98,37 -159,81 -175,127 -5,13 8,28 54,62 91,67 119,64 232,-27 18,-15 48,-29 68,-30 30,-3 34,0 37,24 2,15 -4,40 -12,56 -16,31 -89,89 -139,110 -40,17 -135,14 -186,-7 z"
id="path21"></path>
<path
d="m 14575,18321 c -3,-2 -5,-176 -5,-386 0,-283 3,-384 12,-393 7,-7 31,-12 55,-12 h 43 v 129 c 0,71 3,142 6,159 l 6,30 149,4 c 81,1 152,8 158,13 5,6 11,26 13,45 l 3,35 -160,5 -160,5 -5,100 c -3,55 -3,112 -1,128 l 3,27 h 174 174 v 61 61 l -230,-3 c -127,-2 -233,-5 -235,-8 z"
id="path22"></path>
<path
d="m 15179,18318 c -14,-6 -19,-17 -19,-46 0,-21 5,-43 12,-50 8,-8 50,-12 125,-12 62,0 114,-1 115,-2 1,-2 4,-154 7,-338 l 6,-335 44,-3 c 28,-2 47,1 52,10 5,7 9,153 10,323 0,171 4,319 8,330 8,18 18,20 117,20 h 109 l 8,48 c 5,26 7,51 3,54 -8,9 -573,9 -597,1 z"
id="path23"></path>
<path
d="m 17775,18323 c -11,-3 -23,-8 -27,-12 -11,-10 -22,-513 -13,-653 l 7,-128 h 53 53 l 4,138 c 4,161 10,176 67,166 20,-3 43,-8 52,-10 9,-3 49,-53 88,-113 103,-155 142,-191 208,-191 22,0 24,3 18,28 -10,39 -59,122 -121,204 -30,39 -54,77 -54,84 0,6 17,24 38,40 83,64 121,128 122,204 0,56 -36,134 -81,177 -59,56 -98,66 -254,68 -77,1 -149,0 -160,-2 z m 291,-122 c 59,-27 84,-63 84,-124 0,-46 -3,-53 -49,-98 l -48,-49 -79,6 c -130,11 -124,4 -124,138 0,91 3,118 16,130 23,23 146,21 200,-3 z"
id="path24"></path>
<path
d="m 18610,18323 c -75,-2 -117,-8 -122,-16 -11,-18 -10,-749 2,-767 8,-12 37,-14 177,-12 92,1 192,5 221,8 l 52,6 v 58 57 l -167,-1 -168,-1 -3,100 c -5,159 -16,148 146,144 l 137,-4 3,53 c 4,61 20,55 -158,56 l -125,1 -9,47 c -6,29 -6,70 0,105 l 9,58 157,-4 158,-4 15,36 c 30,72 26,77 -69,77 -46,0 -96,1 -112,3 -16,2 -81,2 -144,0 z"
id="path25"></path>
<path
d="m 19553,18323 -83,-4 v -389 -389 l 37,-7 c 62,-12 263,4 324,25 106,36 178,98 228,199 45,88 44,266 -2,362 -31,67 -131,161 -192,182 -54,19 -182,27 -312,21 z m 249,-115 c 57,-17 131,-87 158,-150 19,-45 22,-64 18,-140 -5,-72 -10,-96 -35,-140 -53,-94 -156,-143 -290,-136 l -58,3 -3,279 c -2,217 1,281 10,288 20,12 156,10 200,-4 z"
id="path26"></path>
<path
d="m 20390,18321 -75,-6 -7,-340 c -4,-187 -5,-364 -2,-392 l 5,-53 142,1 c 198,1 306,11 318,29 9,14 6,77 -5,87 -3,3 -80,6 -173,7 l -168,1 -3,80 c -2,44 0,99 3,123 l 6,42 h 150 149 v 50 49 l -152,3 -153,3 -3,107 -3,108 173,-3 173,-2 8,48 c 5,26 6,51 2,55 -9,9 -287,11 -385,3 z"
id="path27"></path>
<path
d="m 21755,18319 c -3,-8 -6,-187 -7,-399 l -3,-385 175,-3 c 96,-1 202,1 235,5 l 60,8 v 53 53 l -175,2 -175,2 -3,70 c -2,39 0,94 3,124 l 7,54 126,-5 c 70,-2 135,-3 145,0 14,3 17,14 17,59 v 56 l -140,-6 c -167,-8 -162,-11 -158,120 l 3,86 170,1 170,1 9,48 c 4,26 5,51 2,54 -4,4 -107,9 -231,11 -185,4 -226,2 -230,-9 z"
id="path28"></path>
<path
d="m 22417,18143 c -9,-236 -9,-526 -1,-576 l 7,-37 h 205 c 113,1 219,4 234,7 27,5 28,8 28,59 0,63 26,56 -207,54 l -153,-1 -2,338 -3,338 -51,3 -51,3 z"
id="path29"></path>
<path
d="m 23275,18319 c -206,-27 -350,-252 -301,-470 42,-186 160,-301 326,-316 109,-10 242,52 321,150 77,96 101,195 79,317 -18,102 -45,153 -116,219 -90,85 -187,116 -309,100 z m 153,-124 c 51,-22 120,-91 144,-145 24,-56 27,-179 5,-232 -21,-49 -92,-125 -140,-150 -51,-25 -130,-33 -185,-18 -58,15 -124,77 -152,143 -33,75 -34,214 -3,274 25,46 78,93 138,123 49,24 140,26 193,5 z"
id="path30"></path>
<path
d="m 23939,18321 c -8,-2 -17,-9 -21,-15 -4,-6 -8,-180 -8,-387 0,-420 -6,-389 71,-389 h 39 v 134 c 0,73 3,147 6,164 l 6,30 122,4 c 108,3 127,7 173,31 107,55 146,184 89,295 -56,110 -112,134 -317,136 -81,1 -153,0 -160,-3 z m 302,-111 c 55,-15 82,-50 87,-115 6,-70 -11,-97 -74,-119 -58,-20 -209,-22 -221,-3 -9,15 -18,211 -9,232 4,12 24,15 93,15 48,0 104,-5 124,-10 z"
id="path31"></path>
<path
d="m 24710,18320 -95,-5 -3,-384 c -2,-301 1,-386 10,-393 16,-9 216,-10 351,-1 l 97,6 v 56 56 h -172 -173 l -3,100 c -5,157 -15,146 141,145 73,-1 142,-1 155,-1 20,1 22,6 22,57 v 57 l -147,-7 c -82,-3 -154,-2 -161,2 -9,6 -12,35 -10,108 l 3,99 h 155 c 212,1 197,-2 202,45 2,23 1,45 -2,49 -7,11 -250,18 -370,11 z"
id="path32"></path>
<path
d="m 25286,18323 c -3,-4 -6,-183 -6,-400 v -393 h 65 65 v 128 c 0,70 3,137 6,149 6,23 29,30 82,24 29,-3 40,-15 106,-115 41,-61 89,-126 106,-143 39,-40 130,-70 130,-43 0,12 -86,152 -146,237 -24,34 -44,66 -44,71 0,6 21,22 46,37 62,36 124,131 124,190 0,100 -78,218 -162,245 -43,14 -360,25 -372,13 z m 317,-114 c 21,-5 52,-23 69,-38 26,-23 32,-37 36,-85 l 5,-57 -47,-43 c -50,-47 -77,-56 -165,-56 -83,0 -84,2 -85,122 -1,117 6,155 32,161 33,9 117,7 155,-4 z"
id="path33"></path>
<path
d="m 27150,17929 v -402 l 50,5 c 28,3 54,8 58,12 9,10 15,676 6,739 l -7,47 h -53 -54 z"
id="path34"></path>
<path
d="m 27428,18324 c -5,-4 -8,-29 -8,-56 0,-46 1,-48 28,-49 77,-2 209,-10 220,-14 9,-3 12,-80 12,-340 v -335 h 54 54 l 7,318 c 3,174 10,328 14,342 7,24 10,25 113,28 101,3 105,4 117,28 6,14 11,36 11,49 v 25 h -257 c -142,0 -280,3 -308,6 -27,3 -53,3 -57,-2 z"
id="path35"></path>
<path
d="m 28780,18315 c -78,-22 -134,-59 -179,-116 -160,-202 -96,-521 127,-631 58,-29 76,-33 147,-33 72,0 86,3 142,34 101,55 179,144 153,176 -22,27 -47,22 -104,-21 -104,-77 -166,-96 -254,-74 -132,31 -213,189 -183,355 14,76 52,130 121,172 57,35 120,49 173,39 18,-3 69,-29 112,-56 44,-28 87,-50 95,-50 16,0 40,38 40,63 0,25 -76,91 -138,120 -78,36 -170,44 -252,22 z"
id="path36"></path>
<path
d="m 29632,18319 c -146,-29 -258,-136 -296,-284 -61,-232 88,-463 323,-501 90,-14 214,38 303,127 83,82 109,143 109,257 1,147 -29,222 -126,310 -84,77 -207,113 -313,91 z m 194,-142 c 118,-74 160,-177 129,-314 -18,-78 -51,-125 -120,-173 -124,-85 -283,-47 -361,86 -35,60 -46,200 -20,267 28,74 118,149 201,167 48,10 129,-6 171,-33 z"
id="path37"></path>
<path
d="m 30287,18323 c -4,-3 -7,-181 -7,-394 v -387 l 23,-6 c 12,-3 37,-6 55,-6 h 32 l 1,203 c 0,111 0,249 -1,306 -1,63 2,101 8,97 5,-3 28,-36 50,-73 22,-38 78,-120 124,-184 249,-349 244,-343 305,-355 22,-4 32,-2 36,9 6,15 9,290 8,619 l -1,167 -34,6 c -19,4 -44,4 -56,0 -21,-7 -21,-8 -18,-310 2,-167 2,-303 2,-302 -31,37 -76,104 -97,142 -47,86 -328,459 -353,469 -21,8 -69,8 -77,-1 z"
id="path38"></path>
<path
d="m 31861,18316 c -10,-11 -12,-81 -9,-288 l 3,-273 33,-68 c 27,-55 44,-74 85,-102 157,-102 376,-51 459,109 21,39 22,53 23,336 v 295 h -55 -55 v -275 c -1,-297 -4,-320 -56,-366 -84,-74 -248,-51 -294,41 -18,37 -20,61 -21,320 l -1,280 -50,3 c -35,2 -53,-2 -62,-12 z"
id="path39"></path>
<path
d="m 32712,18323 -22,-4 2,-392 3,-392 219,1 c 245,2 244,2 253,73 l 6,41 h -181 c -155,0 -181,2 -186,16 -3,9 -6,154 -6,324 0,359 2,350 -88,333 z"
id="path40"></path>
<path
d="m 13868,18301 c -71,-28 -113,-57 -162,-112 -100,-111 -117,-299 -41,-449 35,-70 106,-142 172,-175 50,-26 69,-30 138,-30 69,0 89,4 148,32 81,39 166,116 210,192 31,54 32,60 32,171 0,106 -2,120 -28,173 -38,76 -113,151 -184,185 -77,36 -213,42 -285,13 z m 240,-117 c 93,-46 152,-145 152,-253 0,-106 -69,-208 -180,-267 -49,-26 -164,-25 -209,1 -113,67 -167,224 -125,366 42,144 225,221 362,153 z"
id="path41"></path>
<path
d="m 33171,18311 c -17,-11 -19,-67 -3,-83 7,-7 51,-12 116,-12 57,-1 108,-5 113,-9 4,-5 10,-159 12,-343 l 3,-335 57,3 56,3 5,330 c 3,182 9,336 13,343 6,8 40,12 112,12 h 103 l 11,31 c 26,74 45,69 -286,69 -164,0 -304,-4 -312,-9 z"
id="path42"></path>
<path
d="m 35462,18273 3,-48 118,-6 c 65,-3 122,-10 126,-15 5,-5 11,-155 15,-333 5,-242 9,-327 19,-333 19,-12 72,-9 85,4 9,9 12,97 12,333 0,176 4,325 8,332 5,8 45,13 117,15 l 110,3 11,35 c 6,19 9,40 7,47 -4,10 -76,13 -320,13 h -314 z"
id="path43"></path>
<path
d="m 26404,17976 c -37,-37 -45,-83 -23,-145 14,-40 35,-51 99,-51 44,0 56,4 82,31 28,27 30,34 25,78 -8,67 -25,98 -60,111 -55,19 -87,12 -123,-24 z"
id="path44"></path>
</g>
</svg>
<style>
.logo {
width: 100%;
height: 64px;
max-width: 300px; /* Adjust as needed */
}
.logo-group path {
fill: #061e45; /* Dark blue for light mode */
transition: fill 0.3s ease;
}
/* If you're using a class-based dark mode approach */
:global(.dark) .logo-group path {
fill: #e5e7eb;
}
</style>

After

Width:  |  Height:  |  Size: 20 KiB

View file

@ -1,85 +0,0 @@
---
import { Icon } from "astro-icon/components";
import HeaderLink from "./HeaderLink.astro";
---
<header
class="mb-8 w-full lg:w-[768px] max-w-[calc(100%-2em)] lg:mx-auto hidden lg:block"
>
<nav>
<div class="flex gap-4">
<HeaderLink href="/">Home</HeaderLink>
<HeaderLink href="/blog">Blog</HeaderLink>
<HeaderLink href="/projects">Projects</HeaderLink>
<HeaderLink href="/publications">Publications</HeaderLink>
<HeaderLink href="/contact">Contact</HeaderLink>
</div>
</nav>
</header>
<button id="nav-menu" class="lg:hidden relative w-[30px] h-[30px]">
<Icon
name="mdi:menu"
id="iconMenu"
class="absolute inset-0 transition-all duration-300 ease-in-out"
size={30}
/>
<Icon
name="mdi:close"
id="iconClose"
class="absolute inset-0 opacity-0 rotate-90 transition-all duration-300 ease-in-out"
size={30}
/>
</button>
<header
id="drawer"
class="fixed z-50 top-14 right-0 h-full bg-neutral-50 shadow dark:bg-gray-700 p-6 rounded w-54 transform translate-x-full transition-transform duration-300 ease-in-out"
>
<div class="flex flex-col gap-4">
<HeaderLink href="/">Home</HeaderLink>
<HeaderLink href="/blog">Blog</HeaderLink>
<HeaderLink href="/projects">Projects</HeaderLink>
<HeaderLink href="/publications">Publications</HeaderLink>
<HeaderLink href="/contact">Contact</HeaderLink>
</div>
</header>
<script>
const menu = document.getElementById("nav-menu")!;
const drawer = document.getElementById("drawer")!;
const iconMenu = document.getElementById("iconMenu")!;
const iconClose = document.getElementById("iconClose")!;
function toggle() {
drawer.classList.toggle("translate-x-full");
document.body.classList.toggle("overflow-hidden");
if (iconMenu.classList.contains("opacity-0")) {
iconMenu.classList.remove("opacity-0", "rotate-90");
iconClose.classList.add("opacity-0", "rotate-90");
} else {
iconMenu.classList.add("opacity-0", "rotate-90");
iconClose.classList.remove("opacity-0", "rotate-90");
}
}
menu.addEventListener("click", () => {
toggle();
});
// click-away listener
document.addEventListener("click", (event: MouseEvent) => {
const target = event.target as Node;
if (
!drawer.classList.contains("translate-x-full") &&
!drawer.contains(target) &&
!menu.contains(target)
) {
console.log(
!drawer.classList.contains("translate-x-full"),
!drawer.contains(target),
!menu.contains(target),
);
toggle();
}
});
</script>

View file

@ -0,0 +1,22 @@
---
interface Props {
title: string;
subtitle?: string;
}
const { title, subtitle } = Astro.props;
---
<div class="text-center mb-16">
<h1 class="text-4xl md:text-5xl font-bold text-gray-900 dark:text-white mb-4">
{title}
</h1>
{
subtitle && (
<p class="text-xl text-gray-600 dark:text-gray-400 max-w-2xl mx-auto">
{subtitle}
</p>
)
}
<div class="mt-8 w-24 h-1 bg-blue-600 mx-auto rounded-full"></div>
</div>

View file

@ -0,0 +1,22 @@
---
import HeaderLink from "../HeaderLink.astro";
export const navItems = [
{ href: "/", label: "Home" },
{ href: "/blog", label: "Blog" },
{ href: "/projects", label: "Projects" },
{ href: "/publications", label: "Publications" },
{ href: "/contact", label: "Contact" },
];
---
<!-- Desktop Navigation -->
<nav class="hidden lg:block">
<div class="flex gap-4">
{
navItems.map((item) => (
<HeaderLink href={item.href}>{item.label}</HeaderLink>
))
}
</div>
</nav>

View file

@ -0,0 +1,39 @@
---
const today = new Date();
const lastUpdated = new Date(); // You can set this to a specific date or pull from your build process
---
<footer
class="bg-gray-100/60 dark:bg-mytheme-900 shadow-sm text-gray-600 dark:text-gray-400 px-4 py-8"
>
<div class="max-w-full mx-auto">
<!-- Main horizontal layout -->
<div
class="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-4"
>
<!-- Copyright -->
<div class="text-center sm:text-left">
<p>
&copy; {today.getFullYear()} Alexander Daichendt. All rights reserved.
</p>
</div>
<!-- Legal links -->
<div class="flex items-center justify-center gap-4">
<a
href="/impressum"
class="text-gray-600 dark:text-gray-400 hover:text-accent hover:underline transition-colors duration-200"
>
Impressum
</a>
<span class="opacity-60">•</span>
<a
href="/datenschutz"
class="text-gray-600 dark:text-gray-400 hover:text-accent hover:underline transition-colors duration-200"
>
Datenschutz
</a>
</div>
</div>
</div>
</footer>

View file

@ -0,0 +1,40 @@
---
---
<!-- Mobile Navigation Button Only -->
<div class="lg:hidden">
<button
id="mobile-nav-toggle"
class="relative w-8 h-8 flex items-center justify-center flex-col z-50"
aria-label="Toggle navigation"
type="button"
>
<span class="hamburger-line"></span>
<span class="hamburger-line"></span>
<span class="hamburger-line"></span>
</button>
</div>
<style>
.hamburger-line {
@apply block w-5 h-0.5 bg-gray-600 dark:bg-gray-300 transition-all duration-300;
margin-bottom: 3px;
}
.hamburger-line:last-child {
margin-bottom: 0;
}
#mobile-nav-toggle.nav-open .hamburger-line:nth-child(1) {
transform: rotate(45deg) translate(2px, 2px);
}
#mobile-nav-toggle.nav-open .hamburger-line:nth-child(2) {
opacity: 0;
}
#mobile-nav-toggle.nav-open .hamburger-line:nth-child(3) {
transform: rotate(-45deg) translate(2px, -2px);
}
</style>

View file

@ -0,0 +1,130 @@
---
import { navItems } from "./DesktopNav.astro";
import HeaderLink from "../HeaderLink.astro";
import DarkModeToggle from "./DarkModeToggle.astro";
---
<!-- Mobile Navigation Drawer and Backdrop -->
<div class="lg:hidden">
<!-- Backdrop -->
<div
id="mobile-backdrop"
class="fixed inset-0 bg-black/25 z-40 opacity-0 pointer-events-none transition-opacity duration-300"
>
</div>
<!-- Mobile Drawer -->
<nav
id="mobile-drawer"
class="fixed top-0 right-0 h-full w-64 bg-white dark:bg-gray-800 shadow-xl transform translate-x-full transition-transform duration-300 ease-in-out z-50"
>
<!-- Close button in drawer -->
<div
class="flex justify-between p-4 border-b border-gray-200 dark:border-gray-700"
>
<DarkModeToggle />
<button
id="mobile-nav-close"
class="w-8 h-8 flex items-center justify-center text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white rounded-md hover:bg-gray-100 dark:hover:bg-gray-700"
aria-label="Close navigation"
>
</button>
</div>
<!-- Navigation Links -->
<div class="p-6">
<div class="flex flex-col space-y-4">
{
navItems.map((item) => (
<HeaderLink href={item.href}>{item.label}</HeaderLink>
))
}
</div>
</div>
</nav>
</div>
<script>
function initMobileNav() {
const toggle = document.getElementById("mobile-nav-toggle")!;
const closeBtn = document.getElementById("mobile-nav-close")!;
const drawer = document.getElementById("mobile-drawer")!;
const backdrop = document.getElementById("mobile-backdrop")!;
if (!toggle || !drawer || !backdrop) {
console.error("Missing elements, retrying in 100ms...");
setTimeout(initMobileNav, 100);
return;
}
let isOpen = false;
function openNav() {
console.log("Opening nav");
isOpen = true;
toggle.classList.add("nav-open");
backdrop.classList.remove("opacity-0", "pointer-events-none");
drawer.classList.remove("translate-x-full");
document.body.style.overflow = "hidden";
}
function closeNav() {
console.log("Closing nav");
isOpen = false;
toggle.classList.remove("nav-open");
backdrop.classList.add("opacity-0", "pointer-events-none");
drawer.classList.add("translate-x-full");
document.body.style.overflow = "";
}
// Toggle button click
toggle.addEventListener("click", (e) => {
e.preventDefault();
console.log("Toggle clicked, isOpen:", isOpen);
isOpen ? closeNav() : openNav();
});
// Close button click
if (closeBtn) {
closeBtn.addEventListener("click", (e) => {
e.preventDefault();
console.log("Close button clicked");
closeNav();
});
}
// Backdrop click
backdrop.addEventListener("click", () => {
console.log("Backdrop clicked");
closeNav();
});
// Navigation links
drawer.querySelectorAll("a").forEach((link) => {
link.addEventListener("click", () => {
console.log("Nav link clicked");
closeNav();
});
});
// Escape key
document.addEventListener("keydown", (e) => {
if (e.key === "Escape" && isOpen) {
console.log("Escape pressed");
closeNav();
}
});
console.log("Mobile nav initialized successfully");
}
// Try multiple initialization strategies
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", initMobileNav);
} else {
initMobileNav();
}
// Also try with astro:page-load for Astro's client-side navigation
document.addEventListener("astro:page-load", initMobileNav);
</script>

View file

@ -0,0 +1,41 @@
---
import DarkModeToggle from "./DarkModeToggle.astro";
import DesktopNav from "./DesktopNav.astro";
import Logo from "../Logo.astro";
import MobileNav from "./MobileNav.astro";
---
<header
class="bg-white/80 dark:bg-gray-900/80 backdrop-blur-sm border-b border-gray-200 dark:border-gray-700 z-20 relative"
>
<div class="max-w-full px-4 py-4">
<div class="flex items-center justify-between">
<!-- Site Title - stays on far left -->
<h2 class="font-bold text-xl mb-0 font-mono flex">
<a
href="/"
class="hover:text-blue-600 dark:hover:text-blue-400 transition-colors"
>
<Logo />
</a>
</h2>
<!-- Center container aligned with content -->
<div class="flex-1 flex justify-center">
<div class="max-w-2xl w-full flex justify-end lg:justify-start">
<!-- Desktop: Nav Menu aligned with content -->
<DesktopNav />
</div>
</div>
<!-- Right side: Dark Mode Toggle + Mobile Menu -->
<div class="flex items-center gap-4">
<!-- Dark Mode Toggle - always visible -->
<div class="hidden lg:block"><DarkModeToggle /></div>
<!-- Mobile Navigation Toggle - only on mobile -->
<MobileNav />
</div>
</div>
</div>
</header>

View file

@ -1,18 +1,24 @@
---
import BaseHead from "../components/BaseHead.astro";
import NavMenu from "../components/NavMenu.astro";
import Footer from "../components/Footer.astro";
import Footer from "../components/nav/Footer.astro";
import { SITE_TITLE, SITE_DESCRIPTION } from "../consts";
import DarkModeToggle from "../components/DarkModeToggle.astro";
import "@fontsource/ubuntu";
import "@fontsource/ubuntu/700.css";
import TopHeader from "../components/nav/TopHeader.astro";
import PageHeadline from "../components/PageHeadline.astro";
import MobileNavDrawer from "../components/nav/MobileNavDrawer.astro";
interface Props {
title?: string;
description?: string;
subtitle?: string;
}
const { title = SITE_TITLE, description = SITE_DESCRIPTION } = Astro.props;
const {
title = SITE_TITLE,
description = SITE_DESCRIPTION,
subtitle,
} = Astro.props;
---
<!doctype html>
@ -20,7 +26,7 @@ const { title = SITE_TITLE, description = SITE_DESCRIPTION } = Astro.props;
<head>
<BaseHead title={title} description={description} />
<script is:inline>
// On page load or when changing themes, best to add inline in `head` to avoid FOUC
// Prevent FOUC for dark mode
if (
localStorage.getItem("color-theme") === "dark" ||
(!("color-theme" in localStorage) &&
@ -32,45 +38,25 @@ const { title = SITE_TITLE, description = SITE_DESCRIPTION } = Astro.props;
}
</script>
</head>
<body class="bg-white dark:bg-gray-900 text-black dark:text-white">
<!-- Mobile layout -->
<div class="lg:hidden flex flex-col min-h-screen p-2 sm:p-4">
<div class="flex justify-between items-center mb-4">
<h2 class="font-bold text-lg mb-0">
<a href="/">{SITE_TITLE}</a>
</h2>
<div class="flex items-center gap-4">
<DarkModeToggle />
<NavMenu />
</div>
</div>
<main class="flex-grow">
<body
class="bg-white dark:bg-gray-900 text-black dark:text-white min-h-screen flex flex-col"
>
<!-- Mobile Navigation Drawer (at body level for proper positioning) -->
<MobileNavDrawer />
<!-- Header -->
<TopHeader />
<!-- Main Content -->
<main class="flex-1">
<div class="max-w-2xl mx-auto px-4 py-8">
<PageHeadline title={title} subtitle={subtitle} />
<slot />
</main>
</div>
<!-- Desktop layout -->
<div
class="hidden lg:grid grid-cols-[150px_1fr_60px] gap-4 min-h-screen p-4"
>
<div class="flex items-start">
<h2 class="font-bold text-xl mt-3">
<a href="/">{SITE_TITLE}</a>
</h2>
</div>
</main>
<div>
<NavMenu />
<main class="w-full lg:w-[768px] max-w-[calc(100%-2em)] mx-auto p-2">
<slot />
</main>
</div>
<div class="flex justify-end">
<DarkModeToggle />
</div>
</div>
<!-- Footer -->
<Footer />
</body>
</html>

View file

@ -8,8 +8,7 @@ const posts = (await getCollection("blog")).sort(
);
---
<BaseLayout>
<h1 class="mb-16">Blog</h1>
<BaseLayout title="Blog" subtitle="Thoughts and Reflections">
<section class="max-w-4xl mx-auto">
<ul class="">
{

View file

@ -1,11 +1,9 @@
---
import BaseLayout from "../layouts/BaseLayout.astro";
import BaseLayout from "../../layouts/BaseLayout.astro";
import { Icon } from "astro-icon/components";
---
<BaseLayout title="Contact">
<h1 class="mb-16">Contact</h1>
<ul class="space-y-2">
<li class="flex items-center space-x-3">
<span class="flex items-center">

View file

@ -0,0 +1,34 @@
---
import BaseLayout from "../../layouts/BaseLayout.astro";
import ImpressumContent from "../../components/ImpressumContent.astro";
const address = {
street: "Wiesenweg 10a",
city: "Neufinsing",
postalCode: "85464",
country: "Germany",
};
---
<BaseLayout
title="Impressum"
subtitle="Rechtliche Angaben gemäß § 5 TMG (Telemediengesetz)"
>
<ImpressumContent
companyName="Daichendt IT (freiberuflich)"
ownerName="Alexander Daichendt"
contact={{
email: "inquiries@daichendt.one",
website: "https://daichendt.one",
}}
responsiblePerson={{
name: "Alexander Daichendt",
address,
}}
business={{
vatId: "beantragt",
registrationOffice: "Finanzamt Erding",
}}
address={address}
/>
</BaseLayout>

View file

@ -2,12 +2,10 @@
import BaseLayout from "../layouts/BaseLayout.astro";
---
<BaseLayout>
<h1 class="">Hi, my name is Alex!</h1>
<p>
I am a software engineer, Linux enthusiast and a friend of lightweight,
resilient systems.
</p>
<BaseLayout
title="Hi, my name is Alex!"
subtitle="Software Engineer, Linux Enthusiast, Lightweight Systems Advocate"
>
<p>
My journey in the tech world has been a dynamic one. I've immersed myself in
countless projects spanning various video games and, for the past few years,

View file

@ -166,9 +166,7 @@ const getCardStyle = (company?: string) => {
};
---
<BaseLayout title="Projects">
<h1 class="mb-16">Projects</h1>
<BaseLayout title="Projects" subtitle="Selected Passion Projects I am proud of">
<p>
Here are some of the projects I have worked on in the past. They are sorted
by my personal rating of relevancy. Projects done for a company are marked

View file

@ -1,97 +0,0 @@
---
import BaseLayout from "../layouts/BaseLayout.astro";
import { publications } from "../data/publications";
---
<BaseLayout title="Publications">
<h2>Conference papers</h2>
<ul class="space-y-4">
{
publications.map((pub) => (
<li class="rounded-lg border border-gray-200 dark:border-gray-700 p-4 hover:shadow-lg transition-shadow">
<div class="space-y-2">
<p class="text-lg dark:text-gray-200">
{pub.authors.join(", ")}
</p>
<p class="text-xl font-semibold dark:text-gray-100">
"{pub.title}"
</p>
<p class="text-gray-600 dark:text-gray-400">
{pub.conference ||
pub.journal +
", Volume " +
pub.volume +
", " +
pub.date +
", " +
pub.pages}
</p>
{pub.location && (
<p class="text-gray-600 dark:text-gray-400">
{pub.location}, {pub.date}
</p>
)}
{pub.links && (
<div class="flex gap-4 mt-3">
{pub.links.pdf && (
<a
href={pub.links.pdf}
class="text-mytheme-600 dark:text-mytheme-400 hover:underline flex items-center gap-1"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5"
viewBox="0 0 20 20"
fill="currentColor"
>
<path d="M9 2a2 2 0 00-2 2v8a2 2 0 002 2h6a2 2 0 002-2V6.414A2 2 0 0016.414 5L14 2.586A2 2 0 0012.586 2H9z" />
<path d="M3 8a2 2 0 012-2v10h8a2 2 0 01-2 2H5a2 2 0 01-2-2V8z" />
</svg>
PDF
</a>
)}
{pub.links.homepage && (
<a
href={pub.links.homepage}
class="text-mytheme-600 dark:text-mytheme-400 hover:underline flex items-center gap-1"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5"
viewBox="0 0 20 20"
fill="currentColor"
>
<path d="M11 3a1 1 0 100 2h2.586l-6.293 6.293a1 1 0 101.414 1.414L15 6.414V9a1 1 0 102 0V4a1 1 0 00-1-1h-5z" />
<path d="M5 5a2 2 0 00-2 2v8a2 2 0 002 2h8a2 2 0 002-2v-3a1 1 0 10-2 0v3H5V7h3a1 1 0 000-2H5z" />
</svg>
Homepage
</a>
)}
{pub.links.bibtex && (
<a
href={pub.links.bibtex}
class="text-mytheme-600 dark:text-mytheme-400 hover:underline flex items-center gap-1"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fill-rule="evenodd"
d="M4 4a2 2 0 012-2h4.586A2 2 0 0112 2.586L15.414 6A2 2 0 0116 7.414V16a2 2 0 01-2 2H6a2 2 0 01-2-2V4z"
clip-rule="evenodd"
/>
</svg>
BibTeX
</a>
)}
</div>
)}
</div>
</li>
))
}
</ul>
</BaseLayout>

View file

@ -0,0 +1,95 @@
---
import BaseLayout from "../../layouts/BaseLayout.astro";
import { publications } from "../../data/publications";
---
<BaseLayout title="Publications">
<h2>Conference papers</h2>
<ul class="space-y-4">
{
publications.map((pub) => (
<li class="rounded-lg border border-gray-200 dark:border-gray-700 p-4 hover:shadow-lg transition-shadow">
<div class="space-y-2">
<p class="text-lg dark:text-gray-200">{pub.authors.join(", ")}</p>
<p class="text-xl font-semibold dark:text-gray-100">
"{pub.title}"
</p>
<p class="text-gray-600 dark:text-gray-400">
{pub.conference ||
pub.journal +
", Volume " +
pub.volume +
", " +
pub.date +
", " +
pub.pages}
</p>
{pub.location && (
<p class="text-gray-600 dark:text-gray-400">
{pub.location}, {pub.date}
</p>
)}
{pub.links && (
<div class="flex gap-4 mt-3">
{pub.links.pdf && (
<a
href={pub.links.pdf}
class="text-mytheme-600 dark:text-mytheme-400 hover:underline flex items-center gap-1"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5"
viewBox="0 0 20 20"
fill="currentColor"
>
<path d="M9 2a2 2 0 00-2 2v8a2 2 0 002 2h6a2 2 0 002-2V6.414A2 2 0 0016.414 5L14 2.586A2 2 0 0012.586 2H9z" />
<path d="M3 8a2 2 0 012-2v10h8a2 2 0 01-2 2H5a2 2 0 01-2-2V8z" />
</svg>
PDF
</a>
)}
{pub.links.homepage && (
<a
href={pub.links.homepage}
class="text-mytheme-600 dark:text-mytheme-400 hover:underline flex items-center gap-1"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5"
viewBox="0 0 20 20"
fill="currentColor"
>
<path d="M11 3a1 1 0 100 2h2.586l-6.293 6.293a1 1 0 101.414 1.414L15 6.414V9a1 1 0 102 0V4a1 1 0 00-1-1h-5z" />
<path d="M5 5a2 2 0 00-2 2v8a2 2 0 002 2h8a2 2 0 002-2v-3a1 1 0 10-2 0v3H5V7h3a1 1 0 000-2H5z" />
</svg>
Homepage
</a>
)}
{pub.links.bibtex && (
<a
href={pub.links.bibtex}
class="text-mytheme-600 dark:text-mytheme-400 hover:underline flex items-center gap-1"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fill-rule="evenodd"
d="M4 4a2 2 0 012-2h4.586A2 2 0 0112 2.586L15.414 6A2 2 0 0116 7.414V16a2 2 0 01-2 2H6a2 2 0 01-2-2V4z"
clip-rule="evenodd"
/>
</svg>
BibTeX
</a>
)}
</div>
)}
</div>
</li>
))
}
</ul>
</BaseLayout>