feat: imprint
This commit is contained in:
@@ -150,8 +150,8 @@
|
||||
[ngSrc]="project.icon"
|
||||
[attr.srcset]="project.iconSrcset ?? null"
|
||||
[attr.sizes]="project.iconSizes ?? null"
|
||||
width="216"
|
||||
height="216"
|
||||
[width]="project.iconWidth ?? 216"
|
||||
[height]="project.iconHeight ?? 216"
|
||||
disableOptimizedSrcset
|
||||
[alt]="project.title + ' icon'"
|
||||
/>
|
||||
|
||||
@@ -1,84 +1,162 @@
|
||||
<main class="page-shell imprint-page">
|
||||
<section class="panel legal-hero">
|
||||
<section class="hero-section panel legal-hero">
|
||||
<div class="hero-copy">
|
||||
<div class="hero-copy-main">
|
||||
<p class="eyebrow">Legal</p>
|
||||
<h1>Imprint & Privacy</h1>
|
||||
<p class="hero-intro legal-intro">
|
||||
Legal information for this website under Austrian law, including privacy information for websites operated by Julian Lechner
|
||||
(Lechner Systems).
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="hero-actions">
|
||||
<a class="back-link" routerLink="">
|
||||
<fa-icon [icon]="faArrowLeft"></fa-icon>
|
||||
<span>Back to portfolio</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="eyebrow">Legal</p>
|
||||
<h1>Imprint & Privacy</h1>
|
||||
<p class="legal-intro">
|
||||
Legal disclosure for this website under Austrian law, in particular Section 5 ECG (E-Commerce Act) and Section 25 Austrian Media Act.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="legal-grid">
|
||||
<article class="panel legal-card">
|
||||
<p class="eyebrow">Provider</p>
|
||||
<p class="legal-provider-name">{{ global.firstname }} {{ global.lastname }}</p>
|
||||
<p class="legal-row">{{ global.address.street }} {{ global.address.houseNumber }}</p>
|
||||
<p class="legal-row">{{ global.address.zip }} {{ global.address.city }}</p>
|
||||
<p class="legal-row">{{ global.address.country }}</p>
|
||||
</article>
|
||||
|
||||
<article class="panel legal-card">
|
||||
<p class="eyebrow">Contact</p>
|
||||
<p class="legal-row">
|
||||
<div class="hero-visual">
|
||||
<div class="portrait-highlight legal-contact-box">
|
||||
<p class="hero-contact-title">Provider</p>
|
||||
<p class="legal-provider-name">{{ global.firstname }} {{ global.lastname }} / Lechner Systems</p>
|
||||
<p>{{ displayStreet }} {{ global.address.houseNumber }}</p>
|
||||
<p>{{ global.address.zip }} {{ displayCity }}</p>
|
||||
<p>{{ global.address.country }}</p>
|
||||
<hr />
|
||||
<p class="hero-contact-title">Direct Contact</p>
|
||||
<p>
|
||||
Phone:
|
||||
<a href="tel:{{ global.hrefContactPhone }}">{{ global.contactPhone }}</a>
|
||||
<a class="inline-link" href="tel:{{ global.hrefContactPhone }}">{{ global.contactPhone }}</a>
|
||||
</p>
|
||||
<p class="legal-row">
|
||||
E-mail:
|
||||
<a [href]="contactSafeMail">{{ global.contactMail }}</a>
|
||||
<p>
|
||||
Contact:
|
||||
<a class="inline-link" [href]="contactSafeMail">{{ global.contactMail }}</a>
|
||||
</p>
|
||||
<p class="legal-row">
|
||||
<p>
|
||||
Abuse:
|
||||
<a [href]="abuseSafeMail">{{ global.abuseMail }}</a>
|
||||
<a class="inline-link" [href]="abuseSafeMail">{{ global.abuseMail }}</a>
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="panel legal-copy">
|
||||
<div class="legal-block">
|
||||
<h2>Scope of Website</h2>
|
||||
<p>This website is a personal portfolio and a contact point for software engineering and related digital services.</p>
|
||||
<section class="story-section panel legal-section">
|
||||
<div class="section-heading">
|
||||
<p class="eyebrow">Scope</p>
|
||||
<h2>Scope Of These Notices</h2>
|
||||
</div>
|
||||
|
||||
<div class="legal-block">
|
||||
<h2>Media Disclosure (Section 25 Austrian Media Act)</h2>
|
||||
<div class="story-grid">
|
||||
<div class="story-copy">
|
||||
<p>
|
||||
Media owner and publisher: {{ global.firstname }} {{ global.lastname }}. Editorial policy: Information about projects, technical
|
||||
services, and professional activities in software development.
|
||||
These notices apply to this website and, unless a more specific notice is published there, to other websites operated by Julian
|
||||
Lechner under the name Lechner Systems.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="legal-block">
|
||||
<h2>Liability for Content and External Links</h2>
|
||||
<div class="story-detail">
|
||||
<p>
|
||||
Great care is taken when creating and maintaining this website. However, no liability is accepted for external websites linked from
|
||||
this page. The respective operators are solely responsible for linked content.
|
||||
This website provides information about projects, technical services, contact options, and professional work in software
|
||||
engineering, IT, and related digital services.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="story-section panel legal-section">
|
||||
<div class="section-heading compact">
|
||||
<p class="eyebrow">Privacy</p>
|
||||
<h2>Privacy And Data Processing</h2>
|
||||
</div>
|
||||
|
||||
<div class="story-grid">
|
||||
<div class="story-copy">
|
||||
<p>
|
||||
The controller for data processing within the meaning of the GDPR is {{ global.firstname }} {{ global.lastname }}, reachable at
|
||||
<a class="inline-link" [href]="contactSafeMail">{{ global.contactMail }}</a> and by phone at
|
||||
<a class="inline-link" href="tel:{{ global.hrefContactPhone }}">{{ global.contactPhone }}</a>.
|
||||
</p>
|
||||
<p>
|
||||
As currently implemented in this web project, this website does not use its own tracking, analytics cookies, marketing cookies, or
|
||||
long-term personal usage profiling.
|
||||
</p>
|
||||
<p>
|
||||
For informational website access, technically necessary connection and server data may be processed for operation, IT security,
|
||||
abuse prevention, and troubleshooting.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="legal-block">
|
||||
<h2>Copyright</h2>
|
||||
<div class="story-detail">
|
||||
<p>
|
||||
All content on this website (including text, images, and layout) is protected by copyright law. Any use beyond statutory exceptions
|
||||
requires prior written permission.
|
||||
If you contact me by email or phone, the data you provide is processed to handle your request and maintain communication.
|
||||
Applicable legal bases may include Article 6(1)(b), 6(1)(c), and 6(1)(f) GDPR, depending on context.
|
||||
</p>
|
||||
<p>
|
||||
Personal data is disclosed only where legally required, needed for the establishment, exercise, or defence of legal claims, or
|
||||
explicitly initiated by you.
|
||||
</p>
|
||||
<p>
|
||||
Data is stored only as long as required for communication, request handling, and legal retention duties.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="story-section panel legal-section">
|
||||
<div class="section-heading compact">
|
||||
<p class="eyebrow">Rights</p>
|
||||
<h2>Data Subject Rights And Complaints</h2>
|
||||
</div>
|
||||
|
||||
<div class="story-grid">
|
||||
<div class="story-copy">
|
||||
<p>
|
||||
Subject to statutory requirements, data subjects have the right of access, rectification, erasure, restriction of processing, data
|
||||
portability, and objection.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="legal-block">
|
||||
<h2>Privacy (GDPR / DSGVO)</h2>
|
||||
<div class="story-detail">
|
||||
<p>
|
||||
This website can generally be used without submitting personal data. If you contact me by e-mail, your data is processed only to
|
||||
handle your request and is not shared without a valid legal basis.
|
||||
Complaints can be submitted to the Austrian Data Protection Authority: Barichgasse 40-42, 1030 Vienna, email
|
||||
<a class="inline-link" href="mailto:dsb@dsb.gv.at">dsb@dsb.gv.at</a>, website
|
||||
<a class="inline-link" href="https://dsb.gv.at/">dsb.gv.at</a>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="story-section panel legal-section">
|
||||
<div class="section-heading compact">
|
||||
<p class="eyebrow">Copyright</p>
|
||||
<h2>Copyright, External Links, And Applicable Law</h2>
|
||||
</div>
|
||||
|
||||
<div class="story-grid">
|
||||
<div class="story-copy">
|
||||
<p>
|
||||
All content on this website, including texts, images, graphics, photographs, layouts, source code, and other works, is protected
|
||||
by copyright unless stated otherwise. All rights remain reserved.
|
||||
</p>
|
||||
<p>
|
||||
You may exercise your data subject rights (access, rectification, erasure, restriction, objection) via the contact details listed
|
||||
above.
|
||||
Any use beyond statutory exceptions requires prior written consent of the respective rights holder.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="story-detail">
|
||||
<p>
|
||||
This website may contain links to third-party websites. Their operators are solely responsible for those contents, and no liability
|
||||
is accepted for external links to the extent permitted by law.
|
||||
</p>
|
||||
<p>
|
||||
Austrian law applies exclusively, excluding conflict-of-law rules that would refer to another legal system, unless mandatory
|
||||
consumer protection provisions require otherwise.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
|
||||
@@ -20,6 +20,8 @@ export class ImprintComponent implements OnInit {
|
||||
private readonly sanitizer = inject(DomSanitizer);
|
||||
|
||||
protected readonly global: Global = global;
|
||||
protected readonly displayStreet: string = this.normalizeText(global.address.street);
|
||||
protected readonly displayCity: string = this.normalizeText(global.address.city);
|
||||
|
||||
protected contactSafeMail!: SafeUrl;
|
||||
protected abuseSafeMail!: SafeUrl;
|
||||
@@ -30,4 +32,14 @@ export class ImprintComponent implements OnInit {
|
||||
this.contactSafeMail = this.sanitizer.bypassSecurityTrustUrl(`mailto:${global.contactMail}`);
|
||||
this.abuseSafeMail = this.sanitizer.bypassSecurityTrustUrl(`mailto:${this.global.abuseMail}`);
|
||||
}
|
||||
|
||||
private normalizeText(value: string): string {
|
||||
return value
|
||||
.replaceAll('ß', 'ß')
|
||||
.replaceAll('ö', 'ö')
|
||||
.replaceAll('Ä', 'Ä')
|
||||
.replaceAll('ä', 'ä')
|
||||
.replaceAll('Ü', 'Ü')
|
||||
.replaceAll('ü', 'ü');
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 809 KiB |
@@ -6,6 +6,8 @@ export interface PortfolioProject {
|
||||
icon?: string;
|
||||
iconSrcset?: string;
|
||||
iconSizes?: string;
|
||||
iconWidth?: number;
|
||||
iconHeight?: number;
|
||||
CircleIcon?: boolean;
|
||||
}
|
||||
|
||||
@@ -163,6 +165,8 @@ export const global: Global = {
|
||||
iconSrcset:
|
||||
'assets/optimized/logos/synhost-64.webp 64w, assets/optimized/logos/synhost-128.webp 128w, assets/optimized/logos/synhost.webp 216w',
|
||||
iconSizes: '(max-width: 700px) 64px, 108px',
|
||||
iconWidth: 108,
|
||||
iconHeight: 64,
|
||||
CircleIcon: false,
|
||||
},
|
||||
{
|
||||
@@ -199,6 +203,8 @@ export const global: Global = {
|
||||
iconSrcset:
|
||||
'assets/optimized/portrait/me-64.webp 64w, assets/optimized/portrait/me-128.webp 128w, assets/optimized/portrait/me.webp 216w',
|
||||
iconSizes: '(max-width: 700px) 64px, 108px',
|
||||
iconWidth: 320,
|
||||
iconHeight: 385,
|
||||
CircleIcon: true,
|
||||
},
|
||||
{
|
||||
|
||||
+5
-45
@@ -15,54 +15,14 @@
|
||||
<body>
|
||||
<app-root></app-root>
|
||||
|
||||
<script src='https://storage.ko-fi.com/cdn/scripts/overlay-widget.js'></script>
|
||||
<script>
|
||||
(() => {
|
||||
const widgetTitle = 'Ko-fi donation chat';
|
||||
let hasLoadedWidget = false;
|
||||
|
||||
const titleKofiFrames = () => {
|
||||
document.querySelectorAll('iframe[id^="kofi-wo-container"]').forEach((frame) => {
|
||||
frame.setAttribute('title', widgetTitle);
|
||||
});
|
||||
};
|
||||
|
||||
const drawWidget = () => {
|
||||
window.kofiWidgetOverlay.draw('fraujulian', {
|
||||
type: 'floating-chat',
|
||||
'floating-chat.donateButton.text': 'Tip me',
|
||||
kofiWidgetOverlay.draw('fraujulian', {
|
||||
'type': 'floating-chat',
|
||||
'floating-chat.donateButton.text': 'Coffee',
|
||||
'floating-chat.donateButton.background-color': '#ff5f5f',
|
||||
'floating-chat.donateButton.text-color': '#fff',
|
||||
'floating-chat.donateButton.text-color': '#fff'
|
||||
});
|
||||
window.setTimeout(titleKofiFrames, 300);
|
||||
};
|
||||
|
||||
const loadWidget = () => {
|
||||
if (hasLoadedWidget) {
|
||||
return;
|
||||
}
|
||||
|
||||
hasLoadedWidget = true;
|
||||
const script = document.createElement('script');
|
||||
script.src = 'https://storage.ko-fi.com/cdn/scripts/overlay-widget.js';
|
||||
script.async = true;
|
||||
script.onload = drawWidget;
|
||||
document.body.appendChild(script);
|
||||
};
|
||||
|
||||
window.addEventListener(
|
||||
'load',
|
||||
() => {
|
||||
const observer = new MutationObserver(titleKofiFrames);
|
||||
observer.observe(document.body, { childList: true, subtree: true });
|
||||
|
||||
window.addEventListener('pointerdown', loadWidget, { once: true, passive: true });
|
||||
window.addEventListener('touchstart', loadWidget, { once: true, passive: true });
|
||||
window.addEventListener('scroll', loadWidget, { once: true, passive: true });
|
||||
window.addEventListener('keydown', loadWidget, { once: true });
|
||||
},
|
||||
{ once: true },
|
||||
);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+22
-63
@@ -191,9 +191,7 @@ hr {
|
||||
.legal-intro,
|
||||
.project-description,
|
||||
.story-copy p,
|
||||
.detail-panel p,
|
||||
.legal-copy p,
|
||||
.legal-card p {
|
||||
.detail-panel p {
|
||||
color: var(--text-muted);
|
||||
line-height: 1.75;
|
||||
}
|
||||
@@ -473,8 +471,7 @@ hr {
|
||||
|
||||
.story-section,
|
||||
.contact-strip,
|
||||
.legal-hero,
|
||||
.legal-copy {
|
||||
.legal-hero {
|
||||
margin-top: var(--space-5);
|
||||
padding: clamp(1.5rem, 3vw, 2.5rem);
|
||||
}
|
||||
@@ -513,14 +510,12 @@ hr {
|
||||
}
|
||||
|
||||
.story-copy p:first-child,
|
||||
.detail-panel p:first-child,
|
||||
.legal-copy p:first-child {
|
||||
.detail-panel p:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.story-copy p:last-child,
|
||||
.detail-panel p:last-child,
|
||||
.legal-copy p:last-child {
|
||||
.detail-panel p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
@@ -791,7 +786,7 @@ hr {
|
||||
.project-icon {
|
||||
width: clamp(84px, 12vw, 108px);
|
||||
min-width: clamp(84px, 12vw, 108px);
|
||||
height: clamp(84px, 12vw, 108px);
|
||||
height: auto;
|
||||
object-fit: contain;
|
||||
object-position: center;
|
||||
box-shadow: none;
|
||||
@@ -806,19 +801,8 @@ hr {
|
||||
gap: var(--space-5);
|
||||
}
|
||||
|
||||
.imprint-page a {
|
||||
color: #5ca8ff;
|
||||
text-decoration: underline;
|
||||
text-decoration-thickness: 1.5px;
|
||||
text-underline-offset: 2px;
|
||||
}
|
||||
|
||||
.imprint-page a:hover {
|
||||
color: #8bc2ff;
|
||||
}
|
||||
|
||||
.legal-hero .back-link {
|
||||
margin-bottom: var(--space-5);
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.legal-hero h1 {
|
||||
@@ -833,54 +817,30 @@ hr {
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
.legal-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: var(--space-4);
|
||||
}
|
||||
|
||||
.legal-card {
|
||||
padding: clamp(1.4rem, 3vw, 2rem);
|
||||
.legal-section {
|
||||
margin-top: var(--space-5);
|
||||
}
|
||||
|
||||
.legal-provider-name {
|
||||
margin: 0 0 0.6rem;
|
||||
font-size: clamp(1.35rem, 1.8vw, 1.7rem);
|
||||
font-weight: 650;
|
||||
letter-spacing: -0.02em;
|
||||
margin: 0;
|
||||
font-size: 1.1rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.legal-card p {
|
||||
margin: 0 0 0.45rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.legal-row:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.legal-copy p {
|
||||
margin: 0 0 var(--space-3);
|
||||
}
|
||||
|
||||
.legal-copy {
|
||||
.legal-contact-box {
|
||||
display: grid;
|
||||
gap: var(--space-4);
|
||||
padding: clamp(1.7rem, 3vw, 2.6rem);
|
||||
gap: 0.5rem;
|
||||
width: 100%;
|
||||
justify-items: start;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.legal-block {
|
||||
padding: var(--space-4);
|
||||
border: 1px solid var(--border-soft);
|
||||
border-radius: var(--radius-md);
|
||||
background: rgba(255, 255, 255, 0.03);
|
||||
}
|
||||
|
||||
.legal-block h2 {
|
||||
margin: 0 0 var(--space-3);
|
||||
font-size: clamp(1.4rem, 2.5vw, 2rem);
|
||||
letter-spacing: -0.03em;
|
||||
.legal-contact-box p {
|
||||
margin: 0;
|
||||
color: var(--text-muted);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.site-footer {
|
||||
@@ -922,7 +882,6 @@ hr {
|
||||
@media (max-width: 900px) {
|
||||
.hero-section,
|
||||
.story-grid,
|
||||
.legal-grid,
|
||||
.project-entry,
|
||||
.project-entry-reverse {
|
||||
grid-template-columns: 1fr;
|
||||
@@ -1017,7 +976,7 @@ hr {
|
||||
.project-icon {
|
||||
width: 64px;
|
||||
min-width: 64px;
|
||||
height: 64px;
|
||||
height: auto;
|
||||
align-self: start;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user