Implement multilingual support in footer and add legal pages
This commit is contained in:
parent
7bd0905ecf
commit
2975984104
12 changed files with 719 additions and 8 deletions
|
|
@ -1,15 +1,52 @@
|
||||||
---
|
---
|
||||||
|
import { DEFAULT_LOCALE, type Locale } from '~/consts';
|
||||||
|
import { getLocaleFromUrl, localizePath, t } from '~/i18n/ui';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
locale?: Locale;
|
||||||
|
}
|
||||||
|
|
||||||
|
const locale: Locale = Astro.props.locale ?? getLocaleFromUrl(Astro.url) ?? DEFAULT_LOCALE;
|
||||||
|
const contactSegment = locale === 'de' ? 'kontakt' : 'contact';
|
||||||
|
const imprintSegment = locale === 'de' ? 'impressum' : 'imprint';
|
||||||
|
const privacySegment = locale === 'de' ? 'datenschutz' : 'privacy-policy';
|
||||||
|
|
||||||
const today = new Date();
|
const today = new Date();
|
||||||
---
|
---
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
© {today.getFullYear()} Adrian Altner
|
<div class="footer__inner">
|
||||||
|
<span>© {today.getFullYear()} Adrian Altner</span>
|
||||||
|
<nav class="footer__links" aria-label="Legal">
|
||||||
|
<a href={localizePath(`/${contactSegment}`, locale)}>{t(locale, 'footer.contact')}</a>
|
||||||
|
<a href={localizePath(`/${imprintSegment}`, locale)}>{t(locale, 'footer.imprint')}</a>
|
||||||
|
<a href={localizePath(`/${privacySegment}`, locale)}>{t(locale, 'footer.privacy')}</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
<style>
|
<style>
|
||||||
footer {
|
footer {
|
||||||
padding: 2em 1em 6em 1em;
|
padding: 2em 20px;
|
||||||
background: linear-gradient(var(--gray-gradient)) no-repeat;
|
font-size: 0.75em;
|
||||||
|
line-height: 0;
|
||||||
|
}
|
||||||
|
.footer__inner {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 0.5em 1.25em;
|
||||||
|
}
|
||||||
|
.footer__links {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 1em;
|
||||||
|
}
|
||||||
|
.footer__links a {
|
||||||
color: rgb(var(--gray));
|
color: rgb(var(--gray));
|
||||||
text-align: center;
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.footer__links a:hover {
|
||||||
|
color: var(--accent);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
import type { CollectionEntry } from 'astro:content';
|
import type { CollectionEntry } from 'astro:content';
|
||||||
import { DEFAULT_LOCALE, type Locale, SITE } from '~/consts';
|
import { type Locale, SITE } from '~/consts';
|
||||||
import {
|
import {
|
||||||
aboutSegment,
|
aboutSegment,
|
||||||
categoryIndexSegment,
|
categoryIndexSegment,
|
||||||
|
|
@ -131,6 +131,12 @@ const switchHref = await resolveSwitchHref();
|
||||||
h2 {
|
h2 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
nav > h2 a {
|
||||||
|
display: block;
|
||||||
|
padding: 1em 0;
|
||||||
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 a,
|
h2 a,
|
||||||
|
|
@ -138,11 +144,20 @@ const switchHref = await resolveSwitchHref();
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
nav {
|
nav {
|
||||||
display: flex;
|
display: grid;
|
||||||
|
grid-template-columns: auto 1fr auto;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
|
||||||
gap: 1em;
|
gap: 1em;
|
||||||
}
|
}
|
||||||
|
nav > h2 {
|
||||||
|
justify-self: start;
|
||||||
|
}
|
||||||
|
nav > .internal-links {
|
||||||
|
justify-self: center;
|
||||||
|
}
|
||||||
|
nav > .toolbar {
|
||||||
|
justify-self: end;
|
||||||
|
}
|
||||||
nav a {
|
nav a {
|
||||||
padding: 1em 0.5em;
|
padding: 1em 0.5em;
|
||||||
color: var(--black);
|
color: var(--black);
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,9 @@ export const ui = {
|
||||||
'tags.description': 'Alle Schlagwörter im Überblick.',
|
'tags.description': 'Alle Schlagwörter im Überblick.',
|
||||||
'tag.postsTagged': 'Beiträge mit',
|
'tag.postsTagged': 'Beiträge mit',
|
||||||
'tag.noPosts': 'Noch keine Beiträge mit diesem Stichwort.',
|
'tag.noPosts': 'Noch keine Beiträge mit diesem Stichwort.',
|
||||||
|
'footer.contact': 'Kontakt',
|
||||||
|
'footer.imprint': 'Impressum',
|
||||||
|
'footer.privacy': 'Datenschutz',
|
||||||
'lang.de': 'Deutsch',
|
'lang.de': 'Deutsch',
|
||||||
'lang.en': 'English',
|
'lang.en': 'English',
|
||||||
},
|
},
|
||||||
|
|
@ -40,6 +43,9 @@ export const ui = {
|
||||||
'tags.description': 'All tags at a glance.',
|
'tags.description': 'All tags at a glance.',
|
||||||
'tag.postsTagged': 'Posts tagged',
|
'tag.postsTagged': 'Posts tagged',
|
||||||
'tag.noPosts': 'No posts with this tag yet.',
|
'tag.noPosts': 'No posts with this tag yet.',
|
||||||
|
'footer.contact': 'Contact',
|
||||||
|
'footer.imprint': 'Imprint',
|
||||||
|
'footer.privacy': 'Privacy',
|
||||||
'lang.de': 'Deutsch',
|
'lang.de': 'Deutsch',
|
||||||
'lang.en': 'English',
|
'lang.en': 'English',
|
||||||
},
|
},
|
||||||
|
|
@ -82,6 +88,9 @@ const LOCALIZED_SEGMENTS: Record<Locale, Record<string, string>> = {
|
||||||
about: 'ueber-mich',
|
about: 'ueber-mich',
|
||||||
tag: 'schlagwort',
|
tag: 'schlagwort',
|
||||||
tags: 'schlagwoerter',
|
tags: 'schlagwoerter',
|
||||||
|
contact: 'kontakt',
|
||||||
|
imprint: 'impressum',
|
||||||
|
'privacy-policy': 'datenschutz',
|
||||||
},
|
},
|
||||||
en: {
|
en: {
|
||||||
kategorie: 'category',
|
kategorie: 'category',
|
||||||
|
|
@ -89,6 +98,9 @@ const LOCALIZED_SEGMENTS: Record<Locale, Record<string, string>> = {
|
||||||
'ueber-mich': 'about',
|
'ueber-mich': 'about',
|
||||||
schlagwort: 'tag',
|
schlagwort: 'tag',
|
||||||
schlagwoerter: 'tags',
|
schlagwoerter: 'tags',
|
||||||
|
kontakt: 'contact',
|
||||||
|
impressum: 'imprint',
|
||||||
|
datenschutz: 'privacy-policy',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,6 @@ const {
|
||||||
<main transition:animate="fade">
|
<main transition:animate="fade">
|
||||||
<slot />
|
<slot />
|
||||||
</main>
|
</main>
|
||||||
<Footer transition:persist />
|
<Footer locale={locale} transition:persist />
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
50
src/layouts/Prose.astro
Normal file
50
src/layouts/Prose.astro
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
---
|
||||||
|
import BaseLayout from '~/layouts/BaseLayout.astro';
|
||||||
|
import { DEFAULT_LOCALE, type Locale } from '~/consts';
|
||||||
|
import { getLocaleFromUrl } from '~/i18n/ui';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
locale?: Locale;
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
locale = getLocaleFromUrl(Astro.url) ?? DEFAULT_LOCALE,
|
||||||
|
} = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<BaseLayout title={title} description={description} locale={locale} bodyClass="prose-page">
|
||||||
|
<article class="prose">
|
||||||
|
<slot />
|
||||||
|
</article>
|
||||||
|
</BaseLayout>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
body.prose-page main {
|
||||||
|
width: 720px;
|
||||||
|
max-width: calc(100% - 2em);
|
||||||
|
margin: 2em auto;
|
||||||
|
}
|
||||||
|
body.prose-page .prose :global(.r) {
|
||||||
|
direction: rtl;
|
||||||
|
unicode-bidi: bidi-override;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function decode() {
|
||||||
|
document.querySelectorAll<HTMLElement>('[data-obf]').forEach((el) => {
|
||||||
|
el.textContent = atob(el.dataset.obf!);
|
||||||
|
el.removeAttribute('data-obf');
|
||||||
|
});
|
||||||
|
document.querySelectorAll<HTMLAnchorElement>('[data-obf-href]').forEach((el) => {
|
||||||
|
el.href = atob(el.dataset.obfHref!);
|
||||||
|
el.removeAttribute('data-obf-href');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
decode();
|
||||||
|
document.addEventListener('astro:page-load', decode);
|
||||||
|
</script>
|
||||||
119
src/pages/datenschutz.md
Normal file
119
src/pages/datenschutz.md
Normal file
|
|
@ -0,0 +1,119 @@
|
||||||
|
---
|
||||||
|
layout: ~/layouts/Prose.astro
|
||||||
|
title: Datenschutzerklärung
|
||||||
|
description: Datenschutzerklärung und Informationen zum Datenschutz für adrian-altner.de.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Datenschutzerklärung
|
||||||
|
|
||||||
|
*Zuletzt aktualisiert: März 2026 (ergänzt: Hosting-Anbieter, interaktive Karte)*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Verantwortlicher
|
||||||
|
|
||||||
|
Verantwortlicher für die Datenverarbeitung auf dieser Website im Sinne der Datenschutz-Grundverordnung (DSGVO) ist:
|
||||||
|
|
||||||
|
<strong><span class="r" data-obf="cmVudGxBIG5haXJkQQ=="></span></strong><br>
|
||||||
|
**E-Mail:** <span class="r" data-obf="bW9je3RvZH1yZW50bGEtbmFpcmRhe3RhfXllaA=="></span>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Allgemeine Hinweise zur Datenverarbeitung
|
||||||
|
|
||||||
|
Der Schutz deiner personenbezogenen Daten ist mir sehr wichtig. Ich behandle deine personenbezogenen Daten vertraulich und entsprechend den gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung.
|
||||||
|
|
||||||
|
Die Nutzung dieser Website ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf dieser Website personenbezogene Daten (z.B. Name oder E-Mail-Adresse) erhoben werden, erfolgt dies, soweit möglich, auf freiwilliger Basis. Diese Daten werden ohne deine ausdrückliche Zustimmung nicht an Dritte weitergegeben.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Datenerfassung beim Besuch dieser Website
|
||||||
|
|
||||||
|
**Server-Logfiles**
|
||||||
|
|
||||||
|
Beim Besuch dieser Website erhebt und speichert der Hosting-Anbieter automatisch Informationen in sogenannten Server-Logfiles, die dein Browser automatisch übermittelt. Dies sind:
|
||||||
|
|
||||||
|
- Deine IP-Adresse
|
||||||
|
- Datum und Uhrzeit der Anfrage
|
||||||
|
- Inhalt der Anforderung (konkrete Seite)
|
||||||
|
- Zugriffsstatus / HTTP-Statuscode
|
||||||
|
- Übertragene Datenmenge
|
||||||
|
- Website, von der die Anforderung kommt (Referrer)
|
||||||
|
- Browsertyp und Version
|
||||||
|
- Betriebssystem
|
||||||
|
|
||||||
|
Diese Daten werden nicht mit anderen Datenquellen zusammengeführt. Rechtsgrundlage der Verarbeitung ist Art. 6 Abs. 1 lit. f DSGVO (berechtigtes Interesse). Das berechtigte Interesse liegt in der technisch fehlerfreien Darstellung und Optimierung dieser Website.
|
||||||
|
|
||||||
|
Die Server-Logfiles werden maximal 7 Tage gespeichert und anschließend gelöscht, sofern keine weitere Aufbewahrung aus Sicherheitsgründen erforderlich ist.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Hosting
|
||||||
|
|
||||||
|
Diese Website wird gehostet bei der **Hetzner Online GmbH**, Industriestr. 25, 91710 Gunzenhausen, Deutschland (<https://www.hetzner.com>). Die Datenverarbeitung erfolgt ausschließlich auf Servern innerhalb der Europäischen Union und gewährleistet damit ein hohes Datenschutzniveau im Sinne der DSGVO.
|
||||||
|
|
||||||
|
Beim Besuch dieser Website kann Hetzner technische Verbindungsdaten (z.B. IP-Adresse) im Rahmen des Serverbetriebs verarbeiten. Mit Hetzner wurde ein Auftragsverarbeitungsvertrag (AVV) nach Art. 28 DSGVO abgeschlossen.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Interaktive Karte (Stadia Maps)
|
||||||
|
|
||||||
|
Die Foto-Karten-Seite (`/photos/map`) verwendet Kartenkacheln von **Stadia Maps** (Stadia Maps, LLC, <https://stadiamaps.com>). Beim Besuch dieser Seite lädt dein Browser Kartenkacheln direkt von Servern von Stadia Maps innerhalb der Europäischen Union (`tiles-eu.stadiamaps.com`). Dabei werden deine IP-Adresse sowie Browser-Informationen an Stadia Maps übertragen.
|
||||||
|
|
||||||
|
Stadia Maps verfolgt keine Nutzer websiteübergreifend und verarbeitet Daten DSGVO-konform. Details siehe Datenschutzerklärung: <https://stadiamaps.com/privacy-policy/>. Ein Auftragsverarbeitungsvertrag (AVV) ist verfügbar unter <https://stadiamaps.com/legal/data-processing-addendum/>.
|
||||||
|
|
||||||
|
Rechtsgrundlage ist Art. 6 Abs. 1 lit. f DSGVO (berechtigtes Interesse am Bereitstellen einer interaktiven Karte der Foto-Standorte). Kartenkachel-Anfragen erfolgen nur bei aktivem Aufruf der Kartenseite.
|
||||||
|
|
||||||
|
Die Kartendaten stammen von den **OpenStreetMap**-Mitwirkenden (<https://www.openstreetmap.org/copyright>, ODbL-Lizenz) und werden von **OpenMapTiles** (<https://openmaptiles.org>) zu Vektorkacheln verarbeitet.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Cookies
|
||||||
|
|
||||||
|
Diese Website verwendet keine Cookies, Tracking-Technologien oder Analyse-Tools. Beim Besuch werden keine Informationen auf deinem Gerät gespeichert.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Kontaktaufnahme
|
||||||
|
|
||||||
|
Wenn du mich per E-Mail kontaktierst, werden die von dir mitgeteilten Daten (deine E-Mail-Adresse und der Inhalt deiner Nachricht) zum Zweck der Bearbeitung deiner Anfrage und für den Fall von Anschlussfragen gespeichert. Diese Daten werden ohne deine Einwilligung nicht an Dritte weitergegeben.
|
||||||
|
|
||||||
|
Rechtsgrundlage für die Verarbeitung ist Art. 6 Abs. 1 lit. f DSGVO (berechtigtes Interesse an der Beantwortung deiner Anfrage) bzw. Art. 6 Abs. 1 lit. b DSGVO, sofern deine Anfrage auf den Abschluss eines Vertrages abzielt.
|
||||||
|
|
||||||
|
Du kannst der Speicherung deiner Daten jederzeit widersprechen. In diesem Fall kann die Konversation nicht fortgeführt werden. Alle im Kontext gespeicherten personenbezogenen Daten werden gelöscht.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Deine Rechte
|
||||||
|
|
||||||
|
Dir stehen folgende Rechte bezüglich deiner personenbezogenen Daten zu:
|
||||||
|
|
||||||
|
- **Auskunftsrecht** (Art. 15 DSGVO) – du kannst Auskunft über die zu dir verarbeiteten personenbezogenen Daten verlangen.
|
||||||
|
- **Recht auf Berichtigung** (Art. 16 DSGVO) – du kannst die Berichtigung unrichtiger oder unvollständiger Daten verlangen.
|
||||||
|
- **Recht auf Löschung** (Art. 17 DSGVO) – du kannst unter bestimmten Voraussetzungen die Löschung deiner Daten verlangen.
|
||||||
|
- **Recht auf Einschränkung der Verarbeitung** (Art. 18 DSGVO) – du kannst verlangen, dass die Verarbeitung deiner Daten eingeschränkt wird.
|
||||||
|
- **Recht auf Datenübertragbarkeit** (Art. 20 DSGVO) – du kannst verlangen, deine Daten in einem strukturierten, maschinenlesbaren Format zu erhalten.
|
||||||
|
- **Widerspruchsrecht** (Art. 21 DSGVO) – du kannst einer auf berechtigten Interessen beruhenden Verarbeitung jederzeit widersprechen.
|
||||||
|
|
||||||
|
Zur Ausübung dieser Rechte wende dich bitte an die oben angegebene Adresse.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Beschwerderecht
|
||||||
|
|
||||||
|
Du hast das Recht, dich bei einer Datenschutz-Aufsichtsbehörde zu beschweren. Die zuständige Aufsichtsbehörde richtet sich nach deinem Wohnort bzw. dem Ort des mutmaßlichen Verstoßes.
|
||||||
|
|
||||||
|
In Deutschland ist in der Regel die Datenschutzbehörde des Bundeslands zuständig, in dem du wohnst. Eine Liste aller deutschen Aufsichtsbehörden findest du unter:
|
||||||
|
<https://www.bfdi.bund.de/DE/Service/Anschriften/Laender/Laender-node.html>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. Datensicherheit
|
||||||
|
|
||||||
|
Diese Website nutzt aus Sicherheitsgründen und zum Schutz der Übertragung vertraulicher Inhalte eine SSL/TLS-Verschlüsselung. Eine verschlüsselte Verbindung erkennst du am Schloss-Symbol in der Adressleiste deines Browsers sowie am Präfix `https://`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11. Änderungen dieser Datenschutzerklärung
|
||||||
|
|
||||||
|
Ich behalte mir vor, diese Datenschutzerklärung anzupassen, damit sie stets den aktuellen rechtlichen Anforderungen entspricht oder um Änderungen meiner Leistungen in der Datenschutzerklärung umzusetzen. Die aktuelle Version der Datenschutzerklärung ist immer auf dieser Seite verfügbar. Bitte prüfe diese Seite regelmäßig.
|
||||||
138
src/pages/en/contact.astro
Normal file
138
src/pages/en/contact.astro
Normal file
|
|
@ -0,0 +1,138 @@
|
||||||
|
---
|
||||||
|
import BaseLayout from '~/layouts/BaseLayout.astro';
|
||||||
|
---
|
||||||
|
|
||||||
|
<BaseLayout title="Contact" description="Get in touch with Adrian Altner." locale="en" bodyClass="contact-page">
|
||||||
|
<article class="prose">
|
||||||
|
<h1>Contact</h1>
|
||||||
|
|
||||||
|
<h3>Notes & Feedback</h3>
|
||||||
|
<p>Feedback and corrections are always welcome. I read everything, but rarely reply — please don't be discouraged if you don't hear back.</p>
|
||||||
|
|
||||||
|
<div class="note">
|
||||||
|
<strong>Please note:</strong> Unsolicited press releases, advertising, and SEO pitches will be deleted without a response.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>How to reach me</h2>
|
||||||
|
|
||||||
|
<div class="cards">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card__icon" aria-hidden="true">
|
||||||
|
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<rect x="2" y="4" width="20" height="16" rx="2"></rect>
|
||||||
|
<path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"></path>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div class="card__body">
|
||||||
|
<p class="card__label">Email</p>
|
||||||
|
<span class="card__value r" data-obf="bW9je3RvZH1yZW50bGEtbmFpcmRhe3RhfXllaA=="></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card card--placeholder">
|
||||||
|
<div class="card__icon" aria-hidden="true">
|
||||||
|
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07A19.5 19.5 0 0 1 4.15 12a19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 3.05 2h3a2 2 0 0 1 2 1.72c.127.96.361 1.903.7 2.81a2 2 0 0 1-.45 2.11L7.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.907.339 1.85.573 2.81.7A2 2 0 0 1 21 17z"></path>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div class="card__body">
|
||||||
|
<p class="card__label">Signal</p>
|
||||||
|
<p class="card__value card__value--muted">Coming soon.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</BaseLayout>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function decode() {
|
||||||
|
document.querySelectorAll<HTMLElement>('[data-obf]').forEach((el) => {
|
||||||
|
el.textContent = atob(el.dataset.obf!);
|
||||||
|
el.removeAttribute('data-obf');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
decode();
|
||||||
|
document.addEventListener('astro:page-load', decode);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
body.contact-page main {
|
||||||
|
width: 720px;
|
||||||
|
max-width: calc(100% - 2em);
|
||||||
|
margin: 2em auto;
|
||||||
|
}
|
||||||
|
body.contact-page h2 {
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: 0.06em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: rgb(var(--gray));
|
||||||
|
margin: 2rem 0 1rem;
|
||||||
|
padding-bottom: 0.4rem;
|
||||||
|
border-bottom: 2px solid rgb(var(--black));
|
||||||
|
}
|
||||||
|
body.contact-page h3 {
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
margin: 0 0 0.5rem;
|
||||||
|
}
|
||||||
|
body.contact-page .note {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: rgb(var(--gray-dark));
|
||||||
|
background: rgb(var(--gray-light));
|
||||||
|
padding: 0.9rem 1.25rem;
|
||||||
|
border-radius: 6px;
|
||||||
|
line-height: 1.6;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
}
|
||||||
|
body.contact-page .cards {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.75rem;
|
||||||
|
}
|
||||||
|
body.contact-page .card {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 1rem;
|
||||||
|
padding: 1rem 1.25rem;
|
||||||
|
background: rgb(var(--surface));
|
||||||
|
border: 1px solid rgb(var(--gray-light));
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
body.contact-page .card--placeholder {
|
||||||
|
opacity: 0.55;
|
||||||
|
}
|
||||||
|
body.contact-page .card__icon {
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-top: 0.2rem;
|
||||||
|
color: rgb(var(--gray));
|
||||||
|
}
|
||||||
|
body.contact-page .card__body {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.1rem;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
body.contact-page .card__label {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: rgb(var(--gray));
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
body.contact-page .card__value {
|
||||||
|
font-size: clamp(0.8rem, 3.5vw, 1rem);
|
||||||
|
color: rgb(var(--gray-dark));
|
||||||
|
margin: 0;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
body.contact-page .card__value--muted {
|
||||||
|
color: rgb(var(--gray));
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
body.contact-page .r {
|
||||||
|
direction: rtl;
|
||||||
|
unicode-bidi: bidi-override;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
38
src/pages/en/imprint.md
Normal file
38
src/pages/en/imprint.md
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
---
|
||||||
|
layout: ~/layouts/Prose.astro
|
||||||
|
title: Imprint
|
||||||
|
description: Legal notice for adrian-altner.de.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Imprint
|
||||||
|
|
||||||
|
## Information pursuant to Section 5 DDG
|
||||||
|
|
||||||
|
<span class="r" data-obf="cmVudGxBIG5haXJkQQ=="></span><br>
|
||||||
|
<span class="r" data-obf="MTMgLnJ0Uy1kcmFobm9lTC1mbG9kdVI="></span><br>
|
||||||
|
<span class="r" data-obf="bmVkc2VyRCA3OTAxMA=="></span><br>
|
||||||
|
<span class="r" data-obf="eW5hbXJlRw=="></span>
|
||||||
|
|
||||||
|
**Phone:** <span class="r" data-obf="MDI0MDM1ODcgNjUxIDk0Kw=="></span><br>
|
||||||
|
**Email:** <span class="r" data-obf="bW9je3RvZH1yZW50bGEtbmFpcmRhe3RhfXllaA=="></span>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Responsible for Editorial Content pursuant to Section 18 para. 2 MStV
|
||||||
|
|
||||||
|
<span class="r" data-obf="cmVudGxBIG5haXJkQQ=="></span><br>
|
||||||
|
<span class="r" data-obf="MTMgLnJ0Uy1kcmFobm9lTC1mbG9kdVI="></span><br>
|
||||||
|
<span class="r" data-obf="bmVkc2VyRCA3OTAxMA=="></span><br>
|
||||||
|
<span class="r" data-obf="eW5hbXJlRw=="></span>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Unless otherwise noted, content published on this website is licensed under the [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International](https://creativecommons.org/licenses/by-nc-sa/4.0/) license. The source code is licensed under the [MIT License](https://mit-license.org/).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Privacy
|
||||||
|
|
||||||
|
Information on the processing of personal data can be found in the [Privacy Policy](/privacy-policy).
|
||||||
119
src/pages/en/privacy-policy.md
Normal file
119
src/pages/en/privacy-policy.md
Normal file
|
|
@ -0,0 +1,119 @@
|
||||||
|
---
|
||||||
|
layout: ~/layouts/Prose.astro
|
||||||
|
title: Privacy Policy
|
||||||
|
description: Privacy policy and data protection information for adrian-altner.de.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Privacy Policy
|
||||||
|
|
||||||
|
*Last updated: March 2026 (added: hosting provider, interactive map)*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Controller
|
||||||
|
|
||||||
|
The controller responsible for data processing on this website within the meaning of the General Data Protection Regulation (GDPR) is:
|
||||||
|
|
||||||
|
<strong><span class="r" data-obf="cmVudGxBIG5haXJkQQ=="></span></strong><br>
|
||||||
|
**Email:** <span class="r" data-obf="bW9je3RvZH1yZW50bGEtbmFpcmRhe3RhfXllaA=="></span>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. General Information on Data Processing
|
||||||
|
|
||||||
|
We take the protection of your personal data very seriously. We treat your personal data confidentially and in accordance with the statutory data protection regulations and this privacy policy.
|
||||||
|
|
||||||
|
As a rule, it is possible to use this website without providing personal data. If personal data (e.g. name or email address) is collected on this website, this is done on a voluntary basis where possible. This data will not be passed on to third parties without your explicit consent.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Data Collection When Visiting This Website
|
||||||
|
|
||||||
|
**Server Log Files**
|
||||||
|
|
||||||
|
When you visit this website, our hosting provider automatically collects and stores information in server log files that your browser transmits to us. This includes:
|
||||||
|
|
||||||
|
- Your IP address
|
||||||
|
- Date and time of the request
|
||||||
|
- Content of the request (specific page)
|
||||||
|
- Access status / HTTP status code
|
||||||
|
- Amount of data transferred
|
||||||
|
- Website from which the request originated (referrer)
|
||||||
|
- Browser type and version
|
||||||
|
- Operating system
|
||||||
|
|
||||||
|
This data is not merged with other data sources. The legal basis for this processing is Art. 6(1)(f) GDPR (legitimate interest). Our legitimate interest lies in the technically error-free presentation and optimisation of this website.
|
||||||
|
|
||||||
|
The server log files are stored for a maximum of 7 days and then deleted, unless further retention is required for security purposes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Hosting
|
||||||
|
|
||||||
|
This website is hosted by **Hetzner Online GmbH**, Industriestr. 25, 91710 Gunzenhausen, Germany (<https://www.hetzner.com>). All data processing takes place on servers within the European Union, ensuring a high level of data protection in accordance with GDPR.
|
||||||
|
|
||||||
|
When you visit this website, Hetzner may process technical connection data (e.g. IP address) as part of server operations. We have concluded a data processing agreement (DPA) with Hetzner in accordance with Art. 28 GDPR.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Interactive Map (Stadia Maps)
|
||||||
|
|
||||||
|
The photo map page (`/photos/map`) uses map tiles provided by **Stadia Maps** (Stadia Maps, LLC, <https://stadiamaps.com>). When you visit this page, your browser loads map tiles directly from Stadia Maps servers located in the European Union (`tiles-eu.stadiamaps.com`). This causes your IP address and browser information to be transmitted to Stadia Maps.
|
||||||
|
|
||||||
|
Stadia Maps does not track users across websites and processes data in accordance with GDPR. For details, see their privacy policy: <https://stadiamaps.com/privacy-policy/>. A Data Processing Addendum (DPA) is available at <https://stadiamaps.com/legal/data-processing-addendum/>.
|
||||||
|
|
||||||
|
The legal basis for this processing is Art. 6(1)(f) GDPR (legitimate interest in providing an interactive map of photo locations). Map tile requests are only made when you actively visit the map page.
|
||||||
|
|
||||||
|
The map data is provided by **OpenStreetMap** contributors (<https://www.openstreetmap.org/copyright>, ODbL license) and processed into vector tiles by **OpenMapTiles** (<https://openmaptiles.org>).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Cookies
|
||||||
|
|
||||||
|
This website does not use cookies, tracking technologies, or any analytics tools. No information is stored on your device when you visit this website.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Contact
|
||||||
|
|
||||||
|
If you contact us by email, the data you provide (your email address and the content of your message) will be stored for the purpose of processing your inquiry and in case of follow-up questions. This data will not be passed on to third parties without your consent.
|
||||||
|
|
||||||
|
The legal basis for processing this data is Art. 6(1)(f) GDPR (legitimate interest in responding to your inquiry) or, where your inquiry aims at concluding a contract, Art. 6(1)(b) GDPR.
|
||||||
|
|
||||||
|
You may object to the storage of your data at any time. In this case, the conversation cannot be continued. All personal data stored in the course of the contact will be deleted.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Your Rights
|
||||||
|
|
||||||
|
You have the following rights regarding your personal data:
|
||||||
|
|
||||||
|
- **Right of access** (Art. 15 GDPR) – you may request information about the personal data we process about you.
|
||||||
|
- **Right to rectification** (Art. 16 GDPR) – you may request correction of inaccurate or incomplete data.
|
||||||
|
- **Right to erasure** (Art. 17 GDPR) – you may request deletion of your data under certain conditions.
|
||||||
|
- **Right to restriction of processing** (Art. 18 GDPR) – you may request that processing of your data be restricted.
|
||||||
|
- **Right to data portability** (Art. 20 GDPR) – you may request to receive your data in a structured, machine-readable format.
|
||||||
|
- **Right to object** (Art. 21 GDPR) – you may object to processing based on legitimate interests at any time.
|
||||||
|
|
||||||
|
To exercise any of these rights, please contact us at the address provided above.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Right to Lodge a Complaint
|
||||||
|
|
||||||
|
You have the right to lodge a complaint with a data protection supervisory authority. The supervisory authority competent for you depends on your place of residence or the location of the alleged infringement.
|
||||||
|
|
||||||
|
In Germany, the competent authority is typically the data protection authority of the federal state in which you reside. A list of all German supervisory authorities is available at:
|
||||||
|
<https://www.bfdi.bund.de/DE/Service/Anschriften/Laender/Laender-node.html>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. Data Security
|
||||||
|
|
||||||
|
This website uses SSL/TLS encryption for security reasons and to protect the transmission of confidential content. You can recognise an encrypted connection by the padlock icon in your browser address bar and by the `https://` prefix.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11. Changes to This Privacy Policy
|
||||||
|
|
||||||
|
We reserve the right to update this privacy policy to reflect changes in legal requirements or changes to our services. The current version of the privacy policy is always available on this page. Please check this page regularly.
|
||||||
38
src/pages/impressum.md
Normal file
38
src/pages/impressum.md
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
---
|
||||||
|
layout: ~/layouts/Prose.astro
|
||||||
|
title: Impressum
|
||||||
|
description: Rechtliche Hinweise für adrian-altner.de.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Impressum
|
||||||
|
|
||||||
|
## Angaben gemäß § 5 DDG
|
||||||
|
|
||||||
|
<span class="r" data-obf="cmVudGxBIG5haXJkQQ=="></span><br>
|
||||||
|
<span class="r" data-obf="MTMgLnJ0Uy1kcmFobm9lTC1mbG9kdVI="></span><br>
|
||||||
|
<span class="r" data-obf="bmVkc2VyRCA3OTAxMA=="></span><br>
|
||||||
|
<span class="r" data-obf="eW5hbXJlRw=="></span>
|
||||||
|
|
||||||
|
**Telefon:** <span class="r" data-obf="MDI0MDM1ODcgNjUxIDk0Kw=="></span><br>
|
||||||
|
**E-Mail:** <span class="r" data-obf="bW9je3RvZH1yZW50bGEtbmFpcmRhe3RhfXllaA=="></span>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Redaktionell verantwortlich gemäß § 18 Abs. 2 MStV
|
||||||
|
|
||||||
|
<span class="r" data-obf="cmVudGxBIG5haXJkQQ=="></span><br>
|
||||||
|
<span class="r" data-obf="MTMgLnJ0Uy1kcmFobm9lTC1mbG9kdVI="></span><br>
|
||||||
|
<span class="r" data-obf="bmVkc2VyRCA3OTAxMA=="></span><br>
|
||||||
|
<span class="r" data-obf="eW5hbXJlRw=="></span>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Lizenz
|
||||||
|
|
||||||
|
Soweit nicht anders angegeben, stehen die auf dieser Website veröffentlichten Inhalte unter der Lizenz [Creative Commons Namensnennung – Nicht kommerziell – Weitergabe unter gleichen Bedingungen 4.0 International](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.de). Der Quellcode steht unter der [MIT-Lizenz](https://mit-license.org/).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Datenschutz
|
||||||
|
|
||||||
|
Informationen zur Verarbeitung personenbezogener Daten findest du in der [Datenschutzerklärung](/datenschutz).
|
||||||
138
src/pages/kontakt.astro
Normal file
138
src/pages/kontakt.astro
Normal file
|
|
@ -0,0 +1,138 @@
|
||||||
|
---
|
||||||
|
import BaseLayout from '~/layouts/BaseLayout.astro';
|
||||||
|
---
|
||||||
|
|
||||||
|
<BaseLayout title="Kontakt" description="Kontakt zu Adrian Altner." locale="de" bodyClass="contact-page">
|
||||||
|
<article class="prose">
|
||||||
|
<h1>Kontakt</h1>
|
||||||
|
|
||||||
|
<h3>Hinweise & Feedback</h3>
|
||||||
|
<p>Anmerkungen und Korrekturen sind jederzeit willkommen. Ich lese alles, antworte aber nur selten — lass dich davon bitte nicht abschrecken.</p>
|
||||||
|
|
||||||
|
<div class="note">
|
||||||
|
<strong>Bitte beachten:</strong> Unaufgefordert zugesandte Pressemitteilungen, Werbung und SEO-Angebote werden ohne Antwort gelöscht.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>So erreichst du mich</h2>
|
||||||
|
|
||||||
|
<div class="cards">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card__icon" aria-hidden="true">
|
||||||
|
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<rect x="2" y="4" width="20" height="16" rx="2"></rect>
|
||||||
|
<path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"></path>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div class="card__body">
|
||||||
|
<p class="card__label">E-Mail</p>
|
||||||
|
<span class="card__value r" data-obf="bW9je3RvZH1yZW50bGEtbmFpcmRhe3RhfXllaA=="></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card card--placeholder">
|
||||||
|
<div class="card__icon" aria-hidden="true">
|
||||||
|
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07A19.5 19.5 0 0 1 4.15 12a19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 3.05 2h3a2 2 0 0 1 2 1.72c.127.96.361 1.903.7 2.81a2 2 0 0 1-.45 2.11L7.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.907.339 1.85.573 2.81.7A2 2 0 0 1 21 17z"></path>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div class="card__body">
|
||||||
|
<p class="card__label">Signal</p>
|
||||||
|
<p class="card__value card__value--muted">Folgt demnächst.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</BaseLayout>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function decode() {
|
||||||
|
document.querySelectorAll<HTMLElement>('[data-obf]').forEach((el) => {
|
||||||
|
el.textContent = atob(el.dataset.obf!);
|
||||||
|
el.removeAttribute('data-obf');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
decode();
|
||||||
|
document.addEventListener('astro:page-load', decode);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
body.contact-page main {
|
||||||
|
width: 720px;
|
||||||
|
max-width: calc(100% - 2em);
|
||||||
|
margin: 2em auto;
|
||||||
|
}
|
||||||
|
body.contact-page h2 {
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: 0.06em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: rgb(var(--gray));
|
||||||
|
margin: 2rem 0 1rem;
|
||||||
|
padding-bottom: 0.4rem;
|
||||||
|
border-bottom: 2px solid rgb(var(--black));
|
||||||
|
}
|
||||||
|
body.contact-page h3 {
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
margin: 0 0 0.5rem;
|
||||||
|
}
|
||||||
|
body.contact-page .note {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: rgb(var(--gray-dark));
|
||||||
|
background: rgb(var(--gray-light));
|
||||||
|
padding: 0.9rem 1.25rem;
|
||||||
|
border-radius: 6px;
|
||||||
|
line-height: 1.6;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
}
|
||||||
|
body.contact-page .cards {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.75rem;
|
||||||
|
}
|
||||||
|
body.contact-page .card {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 1rem;
|
||||||
|
padding: 1rem 1.25rem;
|
||||||
|
background: rgb(var(--surface));
|
||||||
|
border: 1px solid rgb(var(--gray-light));
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
body.contact-page .card--placeholder {
|
||||||
|
opacity: 0.55;
|
||||||
|
}
|
||||||
|
body.contact-page .card__icon {
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-top: 0.2rem;
|
||||||
|
color: rgb(var(--gray));
|
||||||
|
}
|
||||||
|
body.contact-page .card__body {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.1rem;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
body.contact-page .card__label {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: rgb(var(--gray));
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
body.contact-page .card__value {
|
||||||
|
font-size: clamp(0.8rem, 3.5vw, 1rem);
|
||||||
|
color: rgb(var(--gray-dark));
|
||||||
|
margin: 0;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
body.contact-page .card__value--muted {
|
||||||
|
color: rgb(var(--gray));
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
body.contact-page .r {
|
||||||
|
direction: rtl;
|
||||||
|
unicode-bidi: bidi-override;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -47,6 +47,13 @@ body {
|
||||||
color: rgb(var(--gray-dark));
|
color: rgb(var(--gray-dark));
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
line-height: 1.7;
|
line-height: 1.7;
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
body > main {
|
||||||
|
flex: 1 0 auto;
|
||||||
}
|
}
|
||||||
main {
|
main {
|
||||||
width: 720px;
|
width: 720px;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue