Compare commits

...
Author SHA1 Message Date
libretech 028f5f0fb8 223015b kap2: demos + barn rgb/cmyk
- 18 demos aus refactor/didaktik-rewrite-2026 cherry-picked (aliasing-paar, byte-fuer-byte, container-vs-codec, drei-dateien, jpeg-pipeline, kap02-05-eroeffner, kb-vs-kib, nyquist-diagram, pivot-signal-zu-byte, psychoakustik/psychovisualitaet-grafik, raster-vs-vektor, summary-kap02, summary-organizer, usb-c-drei-achsen)
- barn-rgb.png + barn-cmyk.png neu generiert (analog zu ybcbr.webp, kanaltrennung mit korrekter k-extraktion)
- lv-original-vs-fake.jpg + 02-bild-audio-video.md slides wired up
2026-06-11 09:55:58 +02:00
libretech 7ae2a9964a 223015c 02: layer 1 (bit) ergänzt, tabellen-refactor, http/2.0, dimmed/klausur-klassen 2026-05-22 09:47:58 +02:00
libretech abc8dece9c 223015b 01: edit-müll raus (style-tag-injection + eof-tippfehler) 2026-05-15 22:06:58 +02:00
libretech a5f890ae24 hdm fixes 2026-05-15 09:44:50 +02:00
libretech 56901d6068 update logos 2026-05-14 22:58:35 +02:00
libretech 2184870e0b dhbw 01-intro: über-mich collage refresh + wording-fixes + index-script polish
- collage.png neu: 11 marken (3 spalten brick-staggered + breite kombi-row für klett+pons+langenscheidt), normalisiert mit padding rechts, dhbw-dark + uni-stuttgart-dark variants (light-svgs unsichtbar auf weiß)
- neue logos: pons.svg (wikimedia, ersetzt gecropptes pons.jpg), bosch.svg, leibniz-fh.svg (alle wikimedia), hdm.jpg, libretech.png (gitea avatar), nextlevelshit.png (github avatar), pons-langenscheidt-klett.png (kombi)
- 01-intro slide: "Web App" -> "Web Applikation" (PWA-fachbegriff bleibt), "Betriebssystem (GNU/Linux, Windows, macOS, iOS, Android)" als erste kategorie ergänzt + OSs aus desktop/mobile rausgezogen, "ODER" -> "XOR"
- scripts/generate-index: dhbw spezifisch — KONTAKT_URL/LABEL pro course, QR_IMG-pfad pro course, footer 'Kursübersicht'-link conditional auf BREADCRUMB_URL, dhbw-subtitle ohne hdm-modul-name
2026-05-09 20:47:03 +02:00
libretech 755aadbc6a scripts/generate-index: per-course BREADCRUMB_URL + EXAM_URL/EXAM_LABEL — dhbw ohne 'kursübersicht'-link (ging fälschlich auf homepage), dhbw mit prüfungsleistung-link (git.librete.ch/DHBW/pruefungsleistung) 2026-05-08 21:49:55 +02:00
libretech 3554908246 scripts/generate-index: dhbw-case ergänzt (web engineering, dhbw stuttgart, himbeer-akzent, sitzung statt kapitel), HEADLINE+INSTITUTION+KAPITEL_TERM pro course, dhbw-topics in TOPIC_MAP (html-css, js-frameworks, nodejs-basics, express, testing, typescript, docker, best-practices) 2026-05-08 21:39:55 +02:00
libretech 2ac3303167 dhbw: file-namen auf dash-convention vereinheitlicht (consistent mit hdm), Makefile dhbw_KAPITEL aktualisiert 2026-05-08 21:36:59 +02:00
libretech 7970ba84d1 dhbw 09_best_practices: qr-code-folie nach cover + url unter cover, mirror hdm-pattern 2026-05-08 13:57:44 +02:00
libretech bb7c2730ca dhbw 08_docker: qr-code-folie nach cover + url unter cover, mirror hdm-pattern 2026-05-08 13:57:14 +02:00
libretech 4f4e989721 dhbw 07_typescript: qr-code-folie nach cover + url unter cover, mirror hdm-pattern 2026-05-08 13:56:42 +02:00
libretech 32a633188a dhbw 06_testing: qr-code-folie nach cover + url unter cover, mirror hdm-pattern 2026-05-08 13:56:09 +02:00
libretech 8ae050baad dhbw 05_express: qr-code-folie nach cover + url unter cover, mirror hdm-pattern 2026-05-08 13:55:33 +02:00
libretech 19d05252ef dhbw 04_nodejs_basics: qr-code-folie nach cover + url unter cover, mirror hdm-pattern 2026-05-08 13:54:53 +02:00
libretech e1c75a1ba3 dhbw 03_js_frameworks: qr-code-folie nach cover + url unter cover, mirror hdm-pattern 2026-05-08 13:54:17 +02:00
libretech c21a073984 dhbw 02_html_css: qr-code-folie nach cover + url unter cover, mirror hdm-pattern 2026-05-08 13:53:36 +02:00
libretech bd473fc890 dhbw 01_intro: qr-code-folie nach cover (zeigt auf librete.ch/dhbw/) + url unter cover, mirror hdm-pattern 2026-05-08 13:52:40 +02:00
libretech 95ff4a08d7 dhbw assets: qr-code zu librete.ch/dhbw/ (slides-dhbw.png) für post-cover-folien 2026-05-08 13:51:54 +02:00
libretech 29403e0f78 dhbw 01_intro: was-keine-webapp-folie auf * statt - bullets für marp-fragmented-list 2026-05-08 13:35:44 +02:00
libretech 0a7730ad9a dhbw 01_intro: vorstellungsrunde-folie zwischen über-mich und vorlesungsplan (gap aus original-PDF slide 4 — wer bist du, was machst du) 2026-05-08 13:32:43 +02:00
libretech c4c6119b8a dhbw 01_intro: was-ist-keine-webapp-block (cover + content) zwischen prüfungsleistung-abgabe und internet-timeline (gap aus original-PDF slides 8/9) 2026-05-08 13:30:43 +02:00
libretech a830480100 dhbw 01_intro: erwartungen-und-wünsche-folie zwischen vorlesungsplan und prüfungsleistung (gap aus original-PDF slide 6) 2026-05-08 13:27:46 +02:00
libretech a56b487bd4 dhbw 01_intro: editor-folie titel präzisiert (Editor → Editor (IDE)) 2026-05-08 13:24:27 +02:00
libretech 81f233b61a dhbw slides: 1 file pro sitzung (issue #2)
01_web_eng.md (103 slides) aufgesplittet:
- 01_intro.md: cover, ueber-mich, vorlesungsplan, pruefungsleistung, internet 101, onboarding
- 02_html_css.md: html, a11y/wcag, css basics + css extended (aus 02_css_extended.md gemergt)
- 03_js_frameworks.md: ecmascript, js, dom, fetch, async, frameworks, build tools, microfrontends

renames (03-08 -> 04-09):
- 03_nodejs_basics -> 04_nodejs_basics
- 04_nodejs_advanced -> 05_express
- 05_testing -> 06_testing
- 06_typescript -> 07_typescript
- 07_docker -> 08_docker
- 08_best_practices -> 09_best_practices

02_css_extended.md geloescht (inhalte in 02_html_css.md)
makefile: dhbw_KAPITEL + dhbw_NAME aktualisiert
2026-05-08 09:06:19 +02:00
libretech 0774b8652d dhbw 01: pruefungsleistung aktualisiert (100 basis + 15 bonus statt 75+10)
punkteverteilung nach source-of-truth (git.librete.ch/DHBW/pruefungsleistung):
- grundanforderungen 30p (projektgrundlagen 15 + praesentation 15)
- clean code 25p (struktur 10 + qualitaet 10 + doku 5)
- accessibility & ux 25p (a11y 15 + responsive 10) — neu
- technische umsetzung 20p — neu
- bonus max 15p (6 bereiche statt 8, je 5p)
2026-05-08 08:54:40 +02:00
libretech dde33f108f dhbw 01: fix pruefungsleistung link (git.librete.ch) 2026-05-08 08:46:23 +02:00
76 changed files with 5029 additions and 1294 deletions

No files matched your search

+2 -2
View File
@@ -22,8 +22,8 @@ DEPLOY_HOST = tengo@tuttle.uberspace.de
223015c_DEPLOY = /home/tengo/html/hdm/223015c 223015c_DEPLOY = /home/tengo/html/hdm/223015c
223015c_KLAUSUR = 1 223015c_KLAUSUR = 1
dhbw_NAME = Technik I – Grundlagen IT dhbw_NAME = Web Engineering
dhbw_KAPITEL = 01_web_eng 02_css_extended 03_nodejs_basics 04_nodejs_advanced 05_testing 06_typescript 07_docker 08_best_practices dhbw_KAPITEL = 01-intro 02-html-css 03-js-frameworks 04-nodejs-basics 05-express 06-testing 07-typescript 08-docker 09-best-practices
dhbw_DEPLOY = /home/tengo/html/dhbw dhbw_DEPLOY = /home/tengo/html/dhbw
dhbw_KLAUSUR = dhbw_KLAUSUR =
+92 -9
View File
@@ -13,6 +13,15 @@ case "$COURSE" in
SLIDES_URL="https://librete.ch/hdm/223015b" SLIDES_URL="https://librete.ch/hdm/223015b"
ACCENT_COLOR="#1e5f8a" ACCENT_COLOR="#1e5f8a"
ACCENT_LIGHT="#e8f4fc" ACCENT_LIGHT="#e8f4fc"
INSTITUTION="HdM Stuttgart"
HEADLINE="HdM Vorlesungen"
KAPITEL_TERM="Kapitel"
BREADCRUMB_URL="../"
EXAM_URL=""
EXAM_LABEL=""
KONTAKT_URL="mailto:mail@librete.ch"
KONTAKT_LABEL="Kontakt"
QR_IMG="qr-index.svg"
;; ;;
223015c) 223015c)
TITLE="Grundlagen IT- und Internettechnik" TITLE="Grundlagen IT- und Internettechnik"
@@ -20,16 +29,72 @@ case "$COURSE" in
SLIDES_URL="https://librete.ch/hdm/223015c" SLIDES_URL="https://librete.ch/hdm/223015c"
ACCENT_COLOR="#d63384" ACCENT_COLOR="#d63384"
ACCENT_LIGHT="#fce4ec" ACCENT_LIGHT="#fce4ec"
INSTITUTION="HdM Stuttgart"
HEADLINE="HdM Vorlesungen"
KAPITEL_TERM="Kapitel"
BREADCRUMB_URL="../"
EXAM_URL=""
EXAM_LABEL=""
KONTAKT_URL="mailto:mail@librete.ch"
KONTAKT_LABEL="Kontakt"
QR_IMG="qr-index.svg"
;;
dhbw)
TITLE="Web Engineering"
SUBTITLE="Informatik / Wirtschaftsinformatik"
SLIDES_URL="https://librete.ch/dhbw"
ACCENT_COLOR="#a02060"
ACCENT_LIGHT="#fce4ec"
INSTITUTION="DHBW Stuttgart"
HEADLINE="DHBW Vorlesungen"
KAPITEL_TERM="Sitzung"
BREADCRUMB_URL=""
EXAM_URL="https://git.librete.ch/DHBW/pruefungsleistung"
EXAM_LABEL="Prüfungsleistung"
KONTAKT_URL="mailto:michael.czechowski@lehre.dhbw-stuttgart.de"
KONTAKT_LABEL="Kontakt"
QR_IMG="assets/slides-dhbw.png"
;; ;;
*) *)
TITLE="$COURSE - HdM Slides" TITLE="$COURSE - Slides"
SUBTITLE="Lecture Slides" SUBTITLE="Lecture Slides"
SLIDES_URL="https://librete.ch/hdm/$COURSE" SLIDES_URL="https://librete.ch/$COURSE"
ACCENT_COLOR="#0066cc" ACCENT_COLOR="#0066cc"
ACCENT_LIGHT="#e8f4fc" ACCENT_LIGHT="#e8f4fc"
INSTITUTION="Stuttgart"
HEADLINE="Vorlesungen"
KAPITEL_TERM="Kapitel"
BREADCRUMB_URL=""
EXAM_URL=""
EXAM_LABEL=""
KONTAKT_URL="mailto:mail@librete.ch"
KONTAKT_LABEL="Kontakt"
QR_IMG="qr-index.svg"
;; ;;
esac esac
# Optional breadcrumb HTML (empty if no parent overview)
if [[ -n "$BREADCRUMB_URL" ]]; then
BREADCRUMB_HTML="<p class=\"breadcrumb\"><a href=\"$BREADCRUMB_URL\">← Kursübersicht</a></p>"
else
BREADCRUMB_HTML=""
fi
# Optional exam-link HTML
if [[ -n "$EXAM_URL" ]]; then
EXAM_HTML="<p class=\"exam-link\"><a href=\"$EXAM_URL\">$EXAM_LABEL →</a></p>"
else
EXAM_HTML=""
fi
# Footer kursübersicht link only when breadcrumb parent exists
if [[ -n "$BREADCRUMB_URL" ]]; then
FOOTER_KURS_HTML=" ·
<a href=\"$BREADCRUMB_URL\">Kursübersicht</a>"
else
FOOTER_KURS_HTML=""
fi
# Topic mappings for nice German titles # Topic mappings for nice German titles
declare -A TOPIC_MAP declare -A TOPIC_MAP
TOPIC_MAP["intro"]="Einführung" TOPIC_MAP["intro"]="Einführung"
@@ -41,6 +106,14 @@ TOPIC_MAP["vertiefung-offene-fragen"]="Vertiefung & Offene Fragen"
TOPIC_MAP["geschichte-grundlagen-html"]="Geschichte, Grundlagen & HTML" TOPIC_MAP["geschichte-grundlagen-html"]="Geschichte, Grundlagen & HTML"
TOPIC_MAP["netzwerke-protokolle-css"]="Netzwerke, Protokolle & CSS" TOPIC_MAP["netzwerke-protokolle-css"]="Netzwerke, Protokolle & CSS"
TOPIC_MAP["interaktivitaet-javascript"]="Interaktivität & JavaScript" TOPIC_MAP["interaktivitaet-javascript"]="Interaktivität & JavaScript"
TOPIC_MAP["html-css"]="HTML & CSS"
TOPIC_MAP["js-frameworks"]="JS, Frameworks & Build Tools"
TOPIC_MAP["nodejs-basics"]="Node.js: Scripting, Running & Building"
TOPIC_MAP["express"]="Express API, CRUD & Middlewares"
TOPIC_MAP["testing"]="Testing"
TOPIC_MAP["typescript"]="TypeScript"
TOPIC_MAP["docker"]="Docker, Proxies & DBs"
TOPIC_MAP["best-practices"]="Wrap-up & Best Practices"
# Configure which topics should appear disabled per course # Configure which topics should appear disabled per course
# Two modes: fully disabled (non-clickable card) and buttons-disabled (link remains clickable, buttons are disabled) # Two modes: fully disabled (non-clickable card) and buttons-disabled (link remains clickable, buttons are disabled)
@@ -101,6 +174,16 @@ cat > "$BUILD_DIR/index.html" << HEADER
font-size: 0.875rem; font-size: 0.875rem;
margin-top: 0.25rem; margin-top: 0.25rem;
} }
.exam-link {
margin-top: 1rem;
font-size: 0.95rem;
}
.exam-link a {
color: $ACCENT_COLOR;
text-decoration: none;
font-weight: 500;
}
.exam-link a:hover { text-decoration: underline; }
/* Use the .termine wrapper and add a gap between cards */ /* Use the .termine wrapper and add a gap between cards */
.termine { .termine {
margin-top: 1.5rem; margin-top: 1.5rem;
@@ -226,11 +309,12 @@ cat > "$BUILD_DIR/index.html" << HEADER
</head> </head>
<body> <body>
<header> <header>
<p class="breadcrumb"><a href="../">← Kursübersicht</a></p> $BREADCRUMB_HTML
<h1>HdM Vorlesungen</h1> <h1>$HEADLINE</h1>
<h2 class="course-heading">$TITLE</h2> <h2 class="course-heading">$TITLE</h2>
<p class="subtitle">$SUBTITLE</p> <p class="subtitle">$SUBTITLE</p>
<p class="meta">HdM Stuttgart · Sommersemester 2026 · Michael Czechowski</p> <p class="meta">$INSTITUTION · Sommersemester 2026 · Michael Czechowski</p>
$EXAM_HTML
</header> </header>
<div class="termine"> <div class="termine">
HEADER HEADER
@@ -253,7 +337,7 @@ for html in $(ls "$BUILD_DIR"/[0-9][0-9]-*.html 2>/dev/null | sort); do
if [[ "$kapitel_num" == "0" ]] || [[ -z "$kapitel_num" ]]; then if [[ "$kapitel_num" == "0" ]] || [[ -z "$kapitel_num" ]]; then
kapitel_label="Einführung" kapitel_label="Einführung"
else else
kapitel_label="Kapitel $kapitel_num" kapitel_label="$KAPITEL_TERM $kapitel_num"
fi fi
pdf_filename="${filename%.html}.pdf" pdf_filename="${filename%.html}.pdf"
@@ -363,12 +447,11 @@ fi
cat >> "$BUILD_DIR/index.html" << FOOTER cat >> "$BUILD_DIR/index.html" << FOOTER
</div> </div>
<div class="qr-section"> <div class="qr-section">
<img src="qr-index.svg" alt="QR Code" class="qr-code"> <img src="$QR_IMG" alt="QR Code" class="qr-code">
<p class="qr-url">$SLIDES_URL</p> <p class="qr-url">$SLIDES_URL</p>
</div> </div>
<footer> <footer>
<a href="mailto:mail@librete.ch">Kontakt</a> · <a href="$KONTAKT_URL">$KONTAKT_LABEL</a>$FOOTER_KURS_HTML
<a href="../">Kursübersicht</a>
</footer> </footer>
</body> </body>
</html> </html>
+2 -72
View File
@@ -9,6 +9,7 @@ title: Dateiformate, Schnittstellen, Speichermedien & Distributionswege
--- ---
<style> <style>
:root { :root {
--color-foreground: #1a1a2e; --color-foreground: #1a1a2e;
--color-highlight: #1e5f8a; --color-highlight: #1e5f8a;
@@ -1191,33 +1192,6 @@ Sog. RGB Tuple (geordnete endliche Liste)
--- ---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/demos/byte-nibble-hex.png)
<!--
Kernidee: jedes Byte lässt sich sauber in zwei 4-Bit-Hälften (Nibbles) zerlegen. Jede Hälfte hat 2⁴ = 16 Zustände – und genau 16 Symbole hat Hex (0-F). Deshalb passt Hex perfekt: 1 Nibble = 1 Hex-Ziffer, 1 Byte = 2 Hex-Ziffern. Keine krumme Umrechnung.
-->
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/demos/why-8-bit.png)
<!--
Warum gerade 8 Bit?
- CPU adressiert byteweise — kleinste adressierbare Einheit
- Halbe Byte (z.B. 0x0000.5) existieren nicht
- Speichercontroller, Bus, CPU-Register alle auf 8-Bit-Häppchen ausgelegt
- Einzelne Bit lesen: erst Byte holen, dann mit Bitmaske isolieren (byte & 0b1000_0000)
- Hardware-Geschichte: IBM System/360 (1964) setzte 8-Bit-Standard, 7-Bit-ASCII + 1 Paritätsbit
-->
---
<!-- _class: lead --> <!-- _class: lead -->
# Hexadezimal # Hexadezimal
@@ -1249,50 +1223,6 @@ Warum gerade 8 Bit?
--- ---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/demos/hex-dec-table.png)
<!--
Hex ↔ Dezimal Lookup-Tabelle: 0–F = 0–15
A=10, B=11, C=12, D=13, E=14, F=15
-->
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/demos/byte-flow.png)
<!--
1 Byte = 8 Bit = 2 Hex-Ziffern = 1 ASCII-Zeichen
- Dieselbe Datei, drei Schreibweisen
- Jeder Rahmen = ein Byte
- Byte ändern sich nicht, nur unsere Anzeige
- ↵ (0x0A) = nicht druckbar → Hex-Editoren zeigen . als Platzhalter
-->
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/demos/three-views.png)
<!--
Dieselben 8 Byte (PNG-Dateianfang: 89 50 4E 47 0D 0A 1A 0A) — drei Perspektiven:
1. Bitstream — was wirklich gespeichert wird (unleserlich)
2. Hex — gruppiert in 8-Bit-Häppchen (kompakt)
3. Bedeutung — was die Byte signalisieren:
- 89: Magic Byte (>127 → "ich bin Binärdatei")
- 50 4E 47: P N G (ASCII-Format-Kürzel)
- 0D 0A 1A 0A: CR LF EOF LF (erkennt kaputte Übertragung)
-->
---
# Wo begegnet Ihnen Hex-Code? # Wo begegnet Ihnen Hex-Code?
| Kontext | Beispiel | | Kontext | Beispiel |
@@ -2143,4 +2073,4 @@ Vollständige Lizenz: https://creativecommons.org/licenses/by-sa/4.0/
- hex5: ZIP (50 4B 03 04) - hex5: ZIP (50 4B 03 04)
- Gruppenarbeit: 3-4 Personen - Gruppenarbeit: 3-4 Personen
- Ziel: Hex-Dump lesen lernen, Dateiformate verstehen - Ziel: Hex-Dump lesen lernen, Dateiformate verstehen
--> -->
+57 -61
View File
@@ -220,7 +220,7 @@ Jeder Pixel speichert einen RGB-Farbwert (3 Bytes).
**Aufbau:** Liste von Pixeln mit Farbwerten (2D-Array) **Aufbau:** Liste von Pixeln mit Farbwerten (2D-Array)
**Speicherbedarf (unkomprimiert):** **Speicherbedarf (unkomprimiert):**
Breite × Höhe × Farbtiefe (in Bytes) Breite × Höhe × Farbtiefe (in Byte)
**Beispiele:** JPEG, PNG, WebP **Beispiele:** JPEG, PNG, WebP
@@ -361,6 +361,15 @@ Vektorgrafiken speichern keine Pixel, sondern mathematische Beschreibungen: Koor
- Frage: "Warum verschickt euch der Grafiker das Logo als .ai oder .svg?" - Frage: "Warum verschickt euch der Grafiker das Logo als .ai oder .svg?"
--> -->
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/demos/raster-vs-vektor.png)
--- ---
<!-- _class: lead --> <!-- _class: lead -->
@@ -374,6 +383,14 @@ Vektorgrafiken speichern keine Pixel, sondern mathematische Beschreibungen: Koor
- Wir nutzen seine Schwächen aus - Wir nutzen seine Schwächen aus
--> -->
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/lv-original-vs-fake.jpg)
--- ---
<!-- _class: klausur --> <!-- _class: klausur -->
@@ -498,6 +515,16 @@ Das Auge ist ein Tiefpassfilter: Hohe Frequenzen (feine Details) werden schwäch
- Interaktive Demo: https://claude.ai/public/artifacts/452e62f1-8525-442d-aa88-bf3795cab2c5 - Interaktive Demo: https://claude.ai/public/artifacts/452e62f1-8525-442d-aa88-bf3795cab2c5
--> -->
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/demos/jpeg-pipeline.png)
--- ---
<!-- _class: klausur --> <!-- _class: klausur -->
@@ -507,7 +534,7 @@ Das Auge ist ein Tiefpassfilter: Hohe Frequenzen (feine Details) werden schwäch
![bg right:20%](./assets/Barn-yuv.png) ![bg right:20%](./assets/Barn-yuv.png)
# JPEG Schritt 1: Farbraumkonversion # JPEG Schritt 1: Farbraumkonvertierung
**RGB → Y'CbCr** **RGB → Y'CbCr**
@@ -530,11 +557,33 @@ KLAUSURRELEVANT:
--- ---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/ybcbr.webp)
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/Barn-rgb.png)
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/Barn-cmyk.png)
---
<!-- _class: erklaerung --> <!-- _class: erklaerung -->
<!-- _header: '' --> <!-- _header: '' -->
<!-- _footer: '' --> <!-- _footer: '' -->
# Farbraumkonversion – Vertiefung # Farbraumkonvertierung – Vertiefung
RGB→YCbCr nutzt die Biologie des menschlichen Auges: 120 Mio. Stäbchen (Helligkeit) vs. nur 6 Mio. Zapfen (Farbe) – ein 20:1-Verhältnis. Die Transformation erfolgt über eine lineare Matrix: RGB→YCbCr nutzt die Biologie des menschlichen Auges: 120 Mio. Stäbchen (Helligkeit) vs. nur 6 Mio. Zapfen (Farbe) – ein 20:1-Verhältnis. Die Transformation erfolgt über eine lineare Matrix:
@@ -546,7 +595,7 @@ Cr = 0.500·R − 0.419·G − 0.081·B + 128
Die Gewichtung (G dominiert mit 59%) entspricht der spektralen Empfindlichkeit des Auges bei Tageslicht. Y enthält alle Schärfeinformation; Cb/Cr können reduziert werden. Die Gewichtung (G dominiert mit 59%) entspricht der spektralen Empfindlichkeit des Auges bei Tageslicht. Y enthält alle Schärfeinformation; Cb/Cr können reduziert werden.
**Chroma Subsampling – Notation J:a:b** (bezogen auf 4×2 Pixel): **Chroma Subsampling – Notation `J:a:b`** (bezogen auf 4×2 Pixel):
| Schema | Farbdaten | Einsatz | | Schema | Farbdaten | Einsatz |
|--------|-----------|---------| |--------|-----------|---------|
@@ -713,11 +762,6 @@ KLAUSURRELEVANT:
--- ---
<!-- _class: klausur -->
<!-- _header: '' -->
<!-- _footer: '' -->
<!-- _backgroundColor: #e3f2fd -->
# JPEG Schritt 6: Huffman-Coding # JPEG Schritt 6: Huffman-Coding
**Verlustfreie Kompression der Restwerte** **Verlustfreie Kompression der Restwerte**
@@ -770,37 +814,10 @@ JPEG verwendet zwei Huffman-Tabellen: eine für DC-Koeffizienten (Durchschnittsw
--- ---
<!-- _class: klausur -->
<!-- _header: '' --> <!-- _header: '' -->
<!-- _footer: '' --> <!-- _footer: '' -->
<!-- _backgroundColor: #e3f2fd -->
<!--
# Huffman-Coding: Beispiel
**Originaltext:** `ABRACADABRA` (11 Zeichen × 8 Bit = 88 Bit) ![bg](./assets/demos/summary-kap02.png)
**Häufigkeitsanalyse:**
A=5, B=2, R=2, C=1, D=1
**Huffman-Baum → Codes:**
| Zeichen | Häufigkeit | Code |
|---------|------------|------|
| A | 5 | `0` |
| B | 2 | `10` |
| R | 2 | `110` |
| C | 1 | `1110` |
| D | 1 | `1111` |
**Codiert:** `0 10 110 0 1110 0 1111 0 10 110 0` = **23 Bit**
**Kompression:** 88 → 23 Bit = **74% gespart**
- Beispiel Schritt für Schritt durchrechnen
- Warum funktioniert's? A kommt 5× vor, bekommt kürzesten Code
- Präfix-Eigenschaft: Kein Code ist Anfang eines anderen → eindeutig dekodierbar
- Frage: "Was passiert, wenn alle Zeichen gleich häufig sind?" → Keine Ersparnis
- In JPEG: Nicht Buchstaben, sondern DCT-Koeffizienten werden so codiert
-->
--- ---
@@ -824,8 +841,6 @@ A=5, B=2, R=2, C=1, D=1
# Andere Bildformate # Andere Bildformate
## PNG, GIF, WebP, AVIF ## PNG, GIF, WebP, AVIF
15:33 Uhr weiter
<!-- <!--
- JPEG ist nicht für alles geeignet - JPEG ist nicht für alles geeignet
- Jetzt: Alternativen und ihre Stärken - Jetzt: Alternativen und ihre Stärken
@@ -1117,29 +1132,10 @@ KLAUSURRELEVANT:
--- ---
# Container + Codec = Video <!-- _header: '' -->
<!-- _footer: '' -->
``` ![bg fit](./assets/demos/container-vs-codec.png)
┌─────────────────────────────┐
│ Container (z.B. MP4) │
│ ┌────────────────────────┐ │
│ │ Video-Stream (H.264) │ │
│ ├────────────────────────┤ │
│ │ Audio-Stream (AAC) │ │
│ ├────────────────────────┤ │
│ │ Untertitel (SRT) │ │
│ ├────────────────────────┤ │
│ │ Metadaten │ │
│ └────────────────────────┘ │
└─────────────────────────────┘
```
<!--
- Container = Verpackung
- Codec = wie der Inhalt komprimiert ist
- Ein MP4 mit H.264 und ein MP4 mit H.265 haben dieselbe Endung
- Wichtig für Kompatibilität: Player muss Codec unterstützen
-->
--- ---
@@ -119,7 +119,7 @@ Hochschule der Medien Stuttgart
<!-- _class: lead --> <!-- _class: lead -->
# Kapitel 3 – 23.01.2026 # Kapitel 3
## Speichermedien & Schnittstellen ## Speichermedien & Schnittstellen
--- ---
@@ -369,8 +369,7 @@ Seitdem native Linux-Unterstützung.
**Features:** **Features:**
- Journaling (Crash-Sicherheit) - Journaling (Crash-Sicherheit)
- Dateirechte (ACLs) - Dateirechte (ACLs)
- Kompression, Verschlüsselung - Kompression, Verschlüsselung, große Dateien und Volumes
- Große Dateien und Volumes
**Nachteile:** **Nachteile:**
- Nur Windows schreibt nativ - Nur Windows schreibt nativ
@@ -629,11 +628,6 @@ Millionen von Websites und Spielen verloren.
- 30 Jahre Haltbarkeit - 30 Jahre Haltbarkeit
- Für Cold Storage ideal - Für Cold Storage ideal
**M-DISC:**
- Spezielle DVD/Blu-ray
- 1.000+ Jahre Haltbarkeit (Herstellerangabe)
- Für kleine, wichtige Daten
**Cloud:** **Cloud:**
- Glacier, Backblaze B2 - Glacier, Backblaze B2
- Günstig für Langzeit - Günstig für Langzeit
Binary file not shown.

After

Width:  |  Height:  |  Size: 283 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 284 KiB

@@ -0,0 +1,205 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Aliasing — derselbe Fehler in zwei Sinnen</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
--soft: #f8fafc;
--border: #cbd5e1;
--hl: #d63384;
--audio: #ea580c;
--bild: #2563eb;
}
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 30px 40px; }
h1 { text-align: center; margin: 0 0 6px; font-size: 1.75rem; }
.sub { text-align: center; color: var(--muted); margin-bottom: 24px; font-size: 1.05rem; }
.sub strong { color: var(--dark); }
.pair {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 22px;
max-width: 1200px;
margin: 0 auto;
}
.modality {
border: 2px solid;
border-radius: 12px;
padding: 16px 18px;
background: #fff;
display: flex;
flex-direction: column;
gap: 12px;
}
.modality.audio { border-color: var(--audio); }
.modality.bild { border-color: var(--bild); }
.mod-head { display: flex; justify-content: space-between; align-items: baseline; }
.mod-name { font-size: 1.25rem; font-weight: 700; }
.modality.audio .mod-name { color: var(--audio); }
.modality.bild .mod-name { color: var(--bild); }
.mod-tag { font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.12em; color: var(--muted); }
.canvas {
background: var(--soft);
border-radius: 8px;
overflow: hidden;
}
.canvas svg { display: block; }
.scene-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.scene { display: flex; flex-direction: column; gap: 4px; }
.scene-label {
font-size: 0.68rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.1em;
color: var(--muted);
}
.scene-cap {
font-size: 0.78rem;
color: var(--muted);
line-height: 1.4;
font-family: ui-monospace, monospace;
}
.scene-cap strong { color: var(--dark); }
.ear-eye {
font-size: 0.86rem;
line-height: 1.5;
color: var(--dark);
}
.ear-eye .arrow { color: var(--hl); font-weight: 700; }
.ear-eye-headline {
font-size: 0.9rem;
font-weight: 700;
}
.modality.audio .ear-eye-headline { color: var(--audio); }
.modality.bild .ear-eye-headline { color: var(--bild); }
.verdict {
margin-top: 22px;
max-width: 1200px;
margin-left: auto;
margin-right: auto;
text-align: center;
border: 2px solid var(--hl);
border-radius: 12px;
padding: 14px 22px;
}
.verdict-q { font-size: 1.1rem; font-weight: 700; color: var(--hl); }
.verdict-a { font-size: 0.93rem; color: var(--dark); margin-top: 4px; }
.verdict-a strong { color: var(--hl); }
</style>
</head>
<body>
<h1>Aliasing — derselbe Fehler in zwei Sinnen</h1>
<div class="sub">Was im Ohr <strong>Brummen</strong> macht, macht im Auge <strong>Moiré</strong>. Wurzel: Sampling zu grob.</div>
<div class="pair">
<div class="modality audio">
<div class="mod-head">
<span class="mod-name">Audio</span>
<span class="mod-tag">Unterabtastung</span>
</div>
<div class="scene-pair">
<div class="scene">
<div class="scene-label">Original (18 kHz)</div>
<div class="canvas">
<svg viewBox="0 0 280 80" width="100%" height="80" preserveAspectRatio="none">
<line x1="0" y1="40" x2="280" y2="40" stroke="#cbd5e1" stroke-width="1" stroke-dasharray="3,4"/>
<path d="M0,40 Q7,5 14,40 T28,40 T42,40 T56,40 T70,40 T84,40 T98,40 T112,40 T126,40 T140,40 T154,40 T168,40 T182,40 T196,40 T210,40 T224,40 T238,40 T252,40 T266,40 T280,40"
stroke="#ea580c" stroke-width="2" fill="none"/>
</svg>
</div>
<div class="scene-cap">20 Schwingungen<br>schnelle Welle</div>
</div>
<div class="scene">
<div class="scene-label">Bei 22 kHz gesampelt</div>
<div class="canvas">
<svg viewBox="0 0 280 80" width="100%" height="80" preserveAspectRatio="none">
<line x1="0" y1="40" x2="280" y2="40" stroke="#cbd5e1" stroke-width="1" stroke-dasharray="3,4"/>
<path d="M0,40 Q7,5 14,40 T28,40 T42,40 T56,40 T70,40 T84,40 T98,40 T112,40 T126,40 T140,40 T154,40 T168,40 T182,40 T196,40 T210,40 T224,40 T238,40 T252,40 T266,40 T280,40"
stroke="#fed7aa" stroke-width="1.2" fill="none"/>
<path d="M0,40 Q70,10 140,40 T280,40"
stroke="#ea580c" stroke-width="2.5" fill="none"/>
</svg>
</div>
<div class="scene-cap"><strong>2 Schwingungen</strong><br>Brumm-Frequenz</div>
</div>
</div>
<div class="ear-eye">
<div class="ear-eye-headline">Was das Ohr hört</div>
Ein schriller 18-kHz-Ton wird zu einem dumpfen 4-kHz-Brumm. Das hohe ist <strong>nicht leiser</strong> — es ist <strong>verloren und falsch ersetzt</strong>.
</div>
</div>
<div class="modality bild">
<div class="mod-head">
<span class="mod-name">Bild</span>
<span class="mod-tag">Moiré-Effekt</span>
</div>
<div class="scene-pair">
<div class="scene">
<div class="scene-label">Original (feine Streifen)</div>
<div class="canvas">
<svg viewBox="0 0 280 80" width="100%" height="80" preserveAspectRatio="none">
<defs>
<pattern id="fine-real" x="0" y="0" width="3" height="80" patternUnits="userSpaceOnUse">
<rect x="0" y="0" width="1.5" height="80" fill="#1e3a8a"/>
</pattern>
</defs>
<rect x="0" y="0" width="280" height="80" fill="url(#fine-real)"/>
</svg>
</div>
<div class="scene-cap">93 Linien<br>volle Auflösung</div>
</div>
<div class="scene">
<div class="scene-label">In niedriger DPI gerendert</div>
<div class="canvas">
<svg viewBox="0 0 280 80" width="100%" height="80" preserveAspectRatio="none">
<defs>
<linearGradient id="moire-bands" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#1e3a8a"/>
<stop offset="10%" stop-color="#bfdbfe"/>
<stop offset="20%" stop-color="#1e3a8a"/>
<stop offset="30%" stop-color="#bfdbfe"/>
<stop offset="40%" stop-color="#1e3a8a"/>
<stop offset="50%" stop-color="#bfdbfe"/>
<stop offset="60%" stop-color="#1e3a8a"/>
<stop offset="70%" stop-color="#bfdbfe"/>
<stop offset="80%" stop-color="#1e3a8a"/>
<stop offset="90%" stop-color="#bfdbfe"/>
<stop offset="100%" stop-color="#1e3a8a"/>
</linearGradient>
</defs>
<rect x="0" y="0" width="280" height="80" fill="url(#moire-bands)"/>
</svg>
</div>
<div class="scene-cap"><strong>5 breite Bänder</strong><br>Moiré-Frequenz</div>
</div>
</div>
<div class="ear-eye">
<div class="ear-eye-headline">Was das Auge sieht</div>
Feine Linien sind weg, dafür <strong>breite Streifen</strong>, die nie da waren. Aus 93 Linien werden 5 Bänder — das Bild lügt.
</div>
</div>
</div>
<div class="verdict">
<div class="verdict-q">Aliasing kennt keine Modalität. Es ist ein <strong>mathematischer</strong> Fehler — kein technischer.</div>
<div class="verdict-a">Egal ob Ton, Bild, Video, Radar, GPS — Sampling muss immer mindestens <strong>doppelt</strong> so dicht sein wie das Signal. Sonst tauscht die Realität Frequenzen aus.</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

@@ -0,0 +1,117 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Byte für Byte — drei Brillen</title>
<style>
:root {
--hl: #d63384;
--dark: #1a1a2e;
--muted: #6b7280;
--border: #cbd5e1;
--bg-soft: #f8fafc;
--bin-bg: #0f0f23;
--bin-fg: #e5e7eb;
--binary-mark: #ef4444;
--ascii-ok: #16a34a;
--ctrl: #9ca3af;
}
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 28px 32px; }
h1 { text-align: center; margin: 0 0 4px; font-size: 1.75rem; }
.sub { text-align: center; color: var(--muted); margin-bottom: 22px; font-size: 1rem; }
.sub code { font-family: ui-monospace, "SF Mono", Menlo, monospace; }
.windows { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 18px; max-width: 1180px; margin: 0 auto; }
.window { border: 2px solid var(--border); border-radius: 10px; overflow: hidden; display: flex; flex-direction: column; }
.window-header { background: var(--bg-soft); padding: 10px 14px; border-bottom: 2px solid var(--border); display: flex; flex-direction: column; gap: 2px; }
.window-title { font-size: 0.78rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.1em; color: var(--muted); }
.window-name { font-size: 1.15rem; font-weight: 700; color: var(--dark); }
.window-body { padding: 14px 16px; flex: 1; display: flex; flex-direction: column; gap: 6px; font-family: ui-monospace, "SF Mono", Menlo, monospace; }
.window.bin .window-body { background: var(--bin-bg); }
.window.bin .row { color: var(--bin-fg); font-size: 1.05rem; letter-spacing: 0.04em; }
.window.hex .row { color: var(--dark); font-size: 1.4rem; font-weight: 700; letter-spacing: 0.06em; }
.window.text .row { font-size: 1.4rem; font-weight: 700; display: flex; align-items: center; gap: 10px; }
.window.text .glyph.printable { color: var(--ascii-ok); }
.window.text .glyph.ctrl { color: var(--ctrl); font-size: 1.1rem; }
.window.text .glyph.binary { color: var(--binary-mark); }
.window.text .note { font-size: 0.78rem; font-weight: 400; color: var(--muted); margin-left: auto; }
.footnote { margin-top: 24px; max-width: 1100px; margin-left: auto; margin-right: auto; display: flex; gap: 32px; justify-content: center; font-size: 0.95rem; }
.legend { display: flex; align-items: center; gap: 8px; }
.swatch { display: inline-block; width: 16px; height: 16px; border-radius: 3px; }
.swatch.binary { background: #fee2e2; border: 2px solid var(--binary-mark); }
.swatch.ascii { background: #dcfce7; border: 2px solid var(--ascii-ok); }
.verdict { margin-top: 14px; text-align: center; font-size: 1.05rem; color: var(--dark); }
.verdict strong { color: var(--binary-mark); }
</style>
</head>
<body>
<h1>Byte für Byte</h1>
<div class="sub">Eine Datei — drei Brillen. Beispiel: erste 8 Byte einer PNG-Datei.</div>
<div class="windows">
<div class="window bin">
<div class="window-header">
<div class="window-title">Fenster 1</div>
<div class="window-name">Bin · rohe 0 und 1</div>
</div>
<div class="window-body">
<div class="row">10001001</div>
<div class="row">01010000</div>
<div class="row">01001110</div>
<div class="row">01000111</div>
<div class="row">00001101</div>
<div class="row">00001010</div>
<div class="row">00011010</div>
<div class="row">00001010</div>
</div>
</div>
<div class="window hex">
<div class="window-header">
<div class="window-title">Fenster 2</div>
<div class="window-name">Hex · 2 Ziffern pro Byte</div>
</div>
<div class="window-body">
<div class="row">89</div>
<div class="row">50</div>
<div class="row">4E</div>
<div class="row">47</div>
<div class="row">0D</div>
<div class="row">0A</div>
<div class="row">1A</div>
<div class="row">0A</div>
</div>
</div>
<div class="window text">
<div class="window-header">
<div class="window-title">Fenster 3</div>
<div class="window-name">Text · ASCII oder ✗ (> 126)</div>
</div>
<div class="window-body">
<div class="row"><span class="glyph binary">✗</span><span class="note">137 &gt; 126</span></div>
<div class="row"><span class="glyph printable">P</span><span class="note">80</span></div>
<div class="row"><span class="glyph printable">N</span><span class="note">78</span></div>
<div class="row"><span class="glyph printable">G</span><span class="note">71</span></div>
<div class="row"><span class="glyph ctrl">CR</span><span class="note">13 · Steuerz.</span></div>
<div class="row"><span class="glyph ctrl">LF</span><span class="note">10 · Steuerz.</span></div>
<div class="row"><span class="glyph ctrl">SUB</span><span class="note">26 · Steuerz.</span></div>
<div class="row"><span class="glyph ctrl">LF</span><span class="note">10 · Steuerz.</span></div>
</div>
</div>
</div>
<div class="verdict">
Mindestens ein Byte mit Wert &gt; 126 → <strong>Binärdatei</strong>. Sonst: reine Textdatei.
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

@@ -0,0 +1,172 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Container ≠ Codec</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
--soft: #f8fafc;
--border: #cbd5e1;
--hl: #d63384;
--container: #2563eb;
--video: #7c3aed;
--audio: #ea580c;
--subs: #16a34a;
--meta: #94a3b8;
}
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 28px 40px; }
h1 { text-align: center; margin: 0 0 6px; font-size: 1.75rem; }
.sub { text-align: center; color: var(--muted); margin-bottom: 22px; font-size: 1.05rem; }
.sub strong { color: var(--dark); }
.scene {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 22px;
max-width: 1200px;
margin: 0 auto;
}
.container-box {
border: 3px dashed var(--container);
border-radius: 14px;
padding: 14px 16px 18px;
background: #fff;
position: relative;
}
.container-tag {
position: absolute;
top: -12px;
left: 18px;
background: #fff;
padding: 0 10px;
font-family: ui-monospace, monospace;
font-size: 0.78rem;
font-weight: 700;
color: var(--container);
}
.container-label {
text-align: center;
font-size: 0.7rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.12em;
color: var(--muted);
margin-bottom: 10px;
}
.track {
display: grid;
grid-template-columns: 90px 1fr;
gap: 12px;
align-items: center;
background: var(--soft);
border-left: 4px solid;
border-radius: 6px;
padding: 9px 14px;
margin-bottom: 6px;
}
.track.video { border-left-color: var(--video); }
.track.audio { border-left-color: var(--audio); }
.track.subs { border-left-color: var(--subs); }
.track.meta { border-left-color: var(--meta); }
.track-label {
font-size: 0.78rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.08em;
}
.track.video .track-label { color: var(--video); }
.track.audio .track-label { color: var(--audio); }
.track.subs .track-label { color: var(--subs); }
.track.meta .track-label { color: var(--meta); }
.codec-pill {
display: inline-block;
font-family: ui-monospace, monospace;
font-size: 0.82rem;
background: #fff;
border: 1px solid var(--border);
padding: 2px 9px;
border-radius: 4px;
color: var(--dark);
}
.verdict {
margin-top: 22px;
max-width: 1200px;
margin-left: auto;
margin-right: auto;
text-align: center;
border: 2px solid var(--hl);
border-radius: 12px;
padding: 14px 22px;
}
.verdict-q { font-size: 1.1rem; font-weight: 700; color: var(--hl); }
.verdict-a { font-size: 0.93rem; color: var(--dark); margin-top: 4px; }
.verdict-a strong { color: var(--hl); }
.verdict-a code { font-family: ui-monospace, monospace; background: var(--soft); padding: 1px 5px; border-radius: 4px; }
</style>
</head>
<body>
<h1>Container ≠ Codec</h1>
<div class="sub">Die <strong>Hülle</strong> sagt nichts darüber, <strong>wie</strong> der Inhalt komprimiert wurde.</div>
<div class="scene">
<div class="container-box">
<span class="container-tag">.mp4</span>
<div class="container-label">Datei A — älterer Stand</div>
<div class="track video">
<span class="track-label">Video</span>
<span><span class="codec-pill">H.264 / AVC</span> · 1080p · 8 Mbit/s</span>
</div>
<div class="track audio">
<span class="track-label">Audio</span>
<span><span class="codec-pill">AAC</span> · 192 kbit/s · Stereo</span>
</div>
<div class="track subs">
<span class="track-label">Untertitel</span>
<span><span class="codec-pill">TTML</span> · de + en</span>
</div>
<div class="track meta">
<span class="track-label">Metadaten</span>
<span>Titel · Dauer · Datum · Bitrate</span>
</div>
</div>
<div class="container-box">
<span class="container-tag">.mp4</span>
<div class="container-label">Datei B — modern</div>
<div class="track video">
<span class="track-label">Video</span>
<span><span class="codec-pill">AV1</span> · 4K · 25 Mbit/s</span>
</div>
<div class="track audio">
<span class="track-label">Audio</span>
<span><span class="codec-pill">Opus</span> · 128 kbit/s · 5.1 Surround</span>
</div>
<div class="track subs">
<span class="track-label">Untertitel</span>
<span><span class="codec-pill">WebVTT</span> · de + en + ja</span>
</div>
<div class="track meta">
<span class="track-label">Metadaten</span>
<span>Titel · Dauer · Datum · HDR-Info</span>
</div>
</div>
</div>
<div class="verdict">
<div class="verdict-q">Gleiche Endung. Anderes Innenleben.</div>
<div class="verdict-a"><strong>Container</strong> = Verpackung (<code>.mp4</code>, <code>.mkv</code>, <code>.webm</code>). <strong>Codec</strong> = Komprimierer (H.264 / AV1 / AAC / Opus). <strong>Tool:</strong> <code>mediainfo &lt;datei&gt;</code> zeigt beides.</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

@@ -0,0 +1,200 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Drei Dateien — dasselbe Innenleben</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
--soft: #f8fafc;
--border: #cbd5e1;
--hl: #d63384;
--foto: #2563eb;
--audio: #ea580c;
--pdf: #7c3aed;
}
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 32px 40px; }
h1 { text-align: center; margin: 0 0 6px; font-size: 1.85rem; }
.sub { text-align: center; color: var(--muted); margin-bottom: 28px; font-size: 1.05rem; }
.sub strong { color: var(--dark); }
.files {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 22px;
max-width: 1200px;
margin: 0 auto;
}
.file {
border: 2px solid;
border-radius: 12px;
padding: 16px 18px;
background: #fff;
display: flex;
flex-direction: column;
gap: 12px;
}
.file.foto { border-color: var(--foto); }
.file.audio { border-color: var(--audio); }
.file.pdf { border-color: var(--pdf); }
.file-head { display: flex; justify-content: space-between; align-items: baseline; }
.file-name { font-size: 1.2rem; font-weight: 700; }
.file.foto .file-name { color: var(--foto); }
.file.audio .file-name { color: var(--audio); }
.file.pdf .file-name { color: var(--pdf); }
.file-ext { font-family: ui-monospace, monospace; font-size: 0.78rem; color: var(--muted); }
.preview {
border-radius: 8px;
border: 1px solid var(--border);
overflow: hidden;
display: block;
height: 130px;
background: var(--soft);
}
.hex-strip {
background: #0f0f23;
border-radius: 6px;
padding: 8px 10px;
font-family: ui-monospace, monospace;
font-size: 0.78rem;
line-height: 1.6;
color: #cbd5e1;
overflow: hidden;
}
.hex-strip .magic { color: #fff; font-weight: 700; padding: 0 2px; border-radius: 2px; }
.hex-strip.foto-magic .magic { background: var(--foto); }
.hex-strip.audio-magic .magic { background: var(--audio); }
.hex-strip.pdf-magic .magic { background: var(--pdf); }
.hex-label {
font-size: 0.68rem;
text-transform: uppercase;
letter-spacing: 0.1em;
color: var(--muted);
font-weight: 700;
margin-bottom: 2px;
}
.magic-caption {
font-size: 0.78rem;
color: var(--muted);
text-align: center;
font-family: ui-monospace, monospace;
}
.magic-caption .magic-word {
color: var(--dark);
font-weight: 700;
}
.verdict {
margin-top: 26px;
max-width: 1200px;
margin-left: auto;
margin-right: auto;
text-align: center;
border: 2px solid var(--hl);
border-radius: 12px;
padding: 14px 22px;
}
.verdict-q { font-size: 1.15rem; font-weight: 700; color: var(--hl); }
.verdict-a { font-size: 0.95rem; color: var(--dark); margin-top: 4px; }
.verdict-a strong { color: var(--hl); }
</style>
</head>
<body>
<h1>Drei Dateien — dasselbe Innenleben</h1>
<div class="sub">Außen <strong>völlig verschieden</strong>. Innen reden alle dieselbe Sprache: <strong>Byte für Byte</strong>.</div>
<div class="files">
<div class="file foto">
<div class="file-head">
<span class="file-name">Foto</span>
<span class="file-ext">.png</span>
</div>
<svg class="preview" viewBox="0 0 220 130" preserveAspectRatio="xMidYMid slice">
<defs>
<linearGradient id="sky-f" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#fde68a"/>
<stop offset="60%" stop-color="#fb923c"/>
<stop offset="100%" stop-color="#7c3aed"/>
</linearGradient>
</defs>
<rect x="0" y="0" width="220" height="130" fill="url(#sky-f)"/>
<circle cx="160" cy="50" r="18" fill="#fef3c7" opacity="0.95"/>
<path d="M0,95 L40,80 L80,90 L120,72 L160,86 L220,75 L220,130 L0,130 Z" fill="#1e1b4b"/>
<path d="M0,110 L60,100 L120,108 L180,98 L220,105 L220,130 L0,130 Z" fill="#0f172a" opacity="0.7"/>
</svg>
<div>
<div class="hex-label">Erste Bytes der Datei</div>
<div class="hex-strip foto-magic">
<span class="magic">89 50 4E 47</span> 0D 0A 1A 0A 00 00 00 0D 49 48 44 52
</div>
</div>
<div class="magic-caption"><span class="magic-word">50 4E 47</span> = <span class="magic-word">"PNG"</span></div>
</div>
<div class="file audio">
<div class="file-head">
<span class="file-name">Sprachnachricht</span>
<span class="file-ext">.mp3</span>
</div>
<svg class="preview" viewBox="0 0 220 130" preserveAspectRatio="none">
<rect x="0" y="0" width="220" height="130" fill="#0f0f23"/>
<line x1="0" y1="65" x2="220" y2="65" stroke="#374151" stroke-width="1"/>
<path d="M0,65 L8,65 L12,55 L16,75 L20,40 L24,90 L28,30 L32,95 L36,35 L40,90
L48,45 L56,82 L64,50 L72,78 L80,52 L88,75 L96,55 L104,72
L116,58 L128,72 L140,60 L152,70 L168,62 L184,68 L200,64 L220,65
L220,130 L0,130 Z" fill="#fb923c" stroke="#ea580c" stroke-width="1"/>
</svg>
<div>
<div class="hex-label">Erste Bytes der Datei</div>
<div class="hex-strip audio-magic">
<span class="magic">49 44 33</span> 03 00 00 00 00 03 76 54 49 54 32 00 00
</div>
</div>
<div class="magic-caption"><span class="magic-word">49 44 33</span> = <span class="magic-word">"ID3"</span></div>
</div>
<div class="file pdf">
<div class="file-head">
<span class="file-name">PDF-Dokument</span>
<span class="file-ext">.pdf</span>
</div>
<svg class="preview" viewBox="0 0 220 130" preserveAspectRatio="xMidYMid meet">
<rect x="0" y="0" width="220" height="130" fill="#f8fafc"/>
<rect x="50" y="14" width="120" height="102" rx="4" fill="#fff" stroke="#cbd5e1" stroke-width="1"/>
<rect x="58" y="24" width="80" height="4" rx="1" fill="#7c3aed"/>
<rect x="58" y="34" width="104" height="2" fill="#cbd5e1"/>
<rect x="58" y="40" width="98" height="2" fill="#cbd5e1"/>
<rect x="58" y="46" width="92" height="2" fill="#cbd5e1"/>
<rect x="58" y="52" width="100" height="2" fill="#cbd5e1"/>
<rect x="58" y="62" width="80" height="2" fill="#cbd5e1"/>
<rect x="58" y="68" width="96" height="2" fill="#cbd5e1"/>
<rect x="58" y="74" width="88" height="2" fill="#cbd5e1"/>
<rect x="58" y="84" width="40" height="3" rx="1" fill="#7c3aed" opacity="0.7"/>
<rect x="58" y="92" width="92" height="2" fill="#cbd5e1"/>
<rect x="58" y="98" width="86" height="2" fill="#cbd5e1"/>
<rect x="58" y="104" width="78" height="2" fill="#cbd5e1"/>
</svg>
<div>
<div class="hex-label">Erste Bytes der Datei</div>
<div class="hex-strip pdf-magic">
<span class="magic">25 50 44 46</span> 2D 31 2E 37 0A 25 E2 E3 CF D3 0A 0A
</div>
</div>
<div class="magic-caption"><span class="magic-word">25 50 44 46</span> = <span class="magic-word">"%PDF"</span></div>
</div>
</div>
<div class="verdict">
<div class="verdict-q">Drei verschiedene Dinge — eine Sprache.</div>
<div class="verdict-a">Jede Datei beginnt mit ihrer <strong>Visitenkarte</strong> (Magic Number) und besteht ab da aus nichts als Byte. Foto, Audio, PDF — alle dieselben Bauteile, nur anders zusammengesetzt.</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

@@ -0,0 +1,206 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>JPEG-Pipeline — 6 Schritte vom Foto zur Datei</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
--soft: #f8fafc;
--border: #cbd5e1;
--hl: #d63384;
--lossless-step: #2563eb;
--lossy-step: #ea580c;
}
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 28px 40px; }
h1 { text-align: center; margin: 0 0 6px; font-size: 1.75rem; }
.sub { text-align: center; color: var(--muted); margin-bottom: 26px; font-size: 1.05rem; }
.sub strong { color: var(--dark); }
.pipeline {
display: grid;
grid-template-columns: 110px repeat(6, 1fr) 110px;
gap: 4px;
max-width: 1200px;
margin: 0 auto;
align-items: stretch;
}
.endpoint {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 6px;
text-align: center;
}
.endpoint-art { width: 88px; height: 60px; display: block; }
.endpoint-label {
font-size: 0.92rem;
font-weight: 700;
color: var(--dark);
}
.endpoint-size {
font-family: ui-monospace, monospace;
font-size: 0.82rem;
color: var(--muted);
}
.step {
border: 2px solid;
border-radius: 8px;
padding: 8px 6px;
background: #fff;
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
text-align: center;
}
.step.lossless { border-color: var(--lossless-step); }
.step.lossy { border-color: var(--lossy-step); }
.step-num {
font-family: ui-monospace, monospace;
font-size: 0.72rem;
font-weight: 700;
color: var(--muted);
}
.step-name {
font-size: 0.78rem;
font-weight: 700;
line-height: 1.2;
}
.step.lossless .step-name { color: var(--lossless-step); }
.step.lossy .step-name { color: var(--lossy-step); }
.step-desc {
font-size: 0.66rem;
color: var(--muted);
line-height: 1.3;
}
.arrow {
display: flex;
align-items: center;
justify-content: center;
color: var(--muted);
font-family: ui-monospace, monospace;
font-size: 1rem;
}
.legend {
margin-top: 16px;
display: flex;
justify-content: center;
gap: 24px;
font-size: 0.84rem;
color: var(--dark);
}
.legend-item { display: flex; align-items: center; gap: 6px; }
.legend-swatch {
width: 14px;
height: 14px;
border-radius: 3px;
display: inline-block;
}
.legend-swatch.lossless { background: var(--lossless-step); }
.legend-swatch.lossy { background: var(--lossy-step); }
.verdict {
margin-top: 22px;
max-width: 1200px;
margin-left: auto;
margin-right: auto;
text-align: center;
border: 2px solid var(--hl);
border-radius: 12px;
padding: 14px 22px;
}
.verdict-q { font-size: 1.1rem; font-weight: 700; color: var(--hl); }
.verdict-a { font-size: 0.93rem; color: var(--dark); margin-top: 4px; }
.verdict-a strong { color: var(--hl); }
</style>
</head>
<body>
<h1>JPEG-Pipeline — 6 Schritte vom Foto zur Datei</h1>
<div class="sub">Nur <strong>einer</strong> dieser Schritte verliert Information. Die anderen fünf sind verlustfrei.</div>
<div class="pipeline">
<div class="endpoint">
<svg class="endpoint-art" viewBox="0 0 88 60">
<defs>
<linearGradient id="photo-grad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#fde68a"/>
<stop offset="55%" stop-color="#fb923c"/>
<stop offset="100%" stop-color="#7c3aed"/>
</linearGradient>
</defs>
<rect x="0" y="0" width="88" height="60" rx="3" fill="url(#photo-grad)"/>
<circle cx="66" cy="22" r="9" fill="#fef3c7"/>
<path d="M0,42 L18,34 L40,40 L60,30 L80,38 L88,33 L88,60 L0,60 Z" fill="#1e1b4b"/>
</svg>
<div class="endpoint-label">Foto (Roh)</div>
<div class="endpoint-size">~36 MB</div>
</div>
<div class="step lossless">
<div class="step-num">1</div>
<div class="step-name">Farbraum</div>
<div class="step-desc">RGB → Y'CbCr<br>Helligkeit von Farbe trennen</div>
</div>
<div class="step lossy">
<div class="step-num">2</div>
<div class="step-name">Chroma-Subsampling</div>
<div class="step-desc">Cb &amp; Cr auf <strong>¼</strong><br>Auge sieht Farbe grob</div>
</div>
<div class="step lossless">
<div class="step-num">3</div>
<div class="step-name">8×8 Blöcke</div>
<div class="step-desc">Bild in Kacheln<br>jeder Block einzeln</div>
</div>
<div class="step lossless">
<div class="step-num">4</div>
<div class="step-name">DCT</div>
<div class="step-desc">Frequenz-Zerlegung<br>häufige Muster</div>
</div>
<div class="step lossy">
<div class="step-num">5</div>
<div class="step-name">Quantisierung</div>
<div class="step-desc"><strong>Hier</strong> wird weggeworfen<br>hohe Frequenzen raus</div>
</div>
<div class="step lossless">
<div class="step-num">6</div>
<div class="step-name">Huffman</div>
<div class="step-desc">Verlustfrei kürzen<br>häufig → kurz</div>
</div>
<div class="endpoint">
<svg class="endpoint-art" viewBox="0 0 88 60">
<rect x="0" y="0" width="88" height="60" rx="3" fill="url(#photo-grad)"/>
<circle cx="66" cy="22" r="9" fill="#fef3c7"/>
<path d="M0,42 L18,34 L40,40 L60,30 L80,38 L88,33 L88,60 L0,60 Z" fill="#1e1b4b"/>
</svg>
<div class="endpoint-label">JPEG</div>
<div class="endpoint-size">~3,5 MB</div>
</div>
</div>
<div class="legend">
<span class="legend-item"><span class="legend-swatch lossless"></span>verlustfrei (umkehrbar)</span>
<span class="legend-item"><span class="legend-swatch lossy"></span>verlustbehaftet (Information weg)</span>
</div>
<div class="verdict">
<div class="verdict-q">Der <strong>Quanten-Schritt</strong> ist das ganze Geheimnis von JPEG.</div>
<div class="verdict-a">Schritte 1, 3, 4, 6 verlieren nichts. Schritt 2 wirft Farb-Detail weg (Auge merkt nicht). Schritt 5 entscheidet — je nach Qualitäts-Stufe — wie viel <strong>Frequenz-Detail</strong> verloren geht. Niedrige Quality = aggressivere Schritt-5-Quantisierung.</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

@@ -0,0 +1,158 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Dieselbe Aufnahme, zwei Formate</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
--soft: #f8fafc;
--border: #cbd5e1;
--hl: #d63384;
--lossless: #16a34a;
--lossy: #ef4444;
}
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 36px 48px; }
h1 { text-align: center; margin: 0 0 6px; font-size: 1.85rem; }
.sub { text-align: center; color: var(--muted); margin-bottom: 28px; font-size: 1.05rem; }
.grid { display: grid; grid-template-columns: 1fr 1fr; gap: 26px; max-width: 1200px; margin: 0 auto; }
.panel { border: 2px solid var(--border); border-radius: 12px; padding: 22px 24px; display: flex; flex-direction: column; gap: 14px; background: #fff; }
.panel.left { border-color: var(--lossless); }
.panel.right { border-color: var(--lossy); }
.panel-head { display: flex; justify-content: space-between; align-items: baseline; }
.panel-tag {
font-size: 0.74rem;
font-weight: 700;
letter-spacing: 0.12em;
text-transform: uppercase;
color: var(--muted);
}
.panel-name { font-size: 1.5rem; font-weight: 700; }
.panel.left .panel-name { color: var(--lossless); }
.panel.right .panel-name { color: var(--lossy); }
.panel-format {
font-family: ui-monospace, "SF Mono", Menlo, monospace;
font-size: 0.85rem;
color: var(--muted);
}
.waveform {
background: #0f0f23;
border-radius: 8px;
padding: 6px;
display: block;
}
.stats { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.stat { background: var(--soft); border: 1px solid var(--border); border-radius: 7px; padding: 8px 12px; }
.stat .label { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--muted); font-weight: 700; }
.stat .value { font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 1rem; font-weight: 700; color: var(--dark); margin-top: 2px; }
.verdict {
margin-top: 26px;
border: 2px solid var(--hl);
background: #fff;
border-radius: 12px;
padding: 16px 22px;
text-align: center;
max-width: 1200px;
margin-left: auto;
margin-right: auto;
}
.verdict-q { font-size: 1.2rem; font-weight: 700; color: var(--hl); }
.verdict-a { font-size: 1rem; color: var(--dark); margin-top: 6px; }
.verdict-a strong { color: var(--hl); }
</style>
</head>
<body>
<h1>Dieselbe Aufnahme, zwei Formate</h1>
<div class="sub">3 Sekunden Snare-Hit mit Cymbal-Tail · 44,1 kHz Sample-Rate · Stereo</div>
<div class="grid">
<div class="panel left">
<div class="panel-head">
<span class="panel-name">Lossless</span>
<span class="panel-tag">FLAC</span>
</div>
<div class="panel-format">verlustfrei · alle Frequenzen 0–22 kHz erhalten</div>
<svg class="waveform" viewBox="0 0 800 160" preserveAspectRatio="none">
<defs>
<linearGradient id="green-grad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#34d399"/>
<stop offset="100%" stop-color="#16a34a"/>
</linearGradient>
</defs>
<line x1="0" y1="80" x2="800" y2="80" stroke="#374151" stroke-width="1"/>
<!-- detailed waveform: transient peak + cymbal decay with high-freq noise -->
<path d="M0,80
L40,80 L42,78 L44,82 L46,74 L48,88
L60,30 L62,135 L64,18 L66,142 L68,28 L70,128 L72,38 L74,118 L76,48 L78,108
L90,55 L92,108 L94,52 L96,112 L98,58 L100,105 L102,62 L104,98 L106,68 L108,92
L130,72 L132,92 L134,68 L136,94 L138,72 L140,90 L142,74 L144,88
L170,76 L172,86 L174,74 L176,87 L178,76 L180,85
L220,77 L222,84 L224,76 L226,85 L228,77 L230,83
L280,78 L282,83 L284,77 L286,84 L288,78 L290,82
L340,79 L342,82 L344,78 L346,82 L348,79 L350,81
L400,79 L402,81 L404,79 L406,81 L408,79 L410,81
L460,80 L462,81 L464,79 L466,81 L468,80 L470,80
L520,80 L522,81 L524,79 L526,80
L580,80 L582,80 L584,80
L640,80 L700,80 L800,80 Z"
fill="url(#green-grad)" stroke="#16a34a" stroke-width="1" opacity="0.95"/>
</svg>
<div class="stats">
<div class="stat"><div class="label">Dateigröße</div><div class="value">5,3 MB</div></div>
<div class="stat"><div class="label">Bitrate</div><div class="value">1.411 kbit/s</div></div>
</div>
</div>
<div class="panel right">
<div class="panel-head">
<span class="panel-name">Lossy</span>
<span class="panel-tag">MP3 128 kbit/s</span>
</div>
<div class="panel-format">verlustbehaftet · hohe Frequenzen weggeworfen, Transienten geglättet</div>
<svg class="waveform" viewBox="0 0 800 160" preserveAspectRatio="none">
<defs>
<linearGradient id="red-grad" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#fca5a5"/>
<stop offset="100%" stop-color="#ef4444"/>
</linearGradient>
</defs>
<line x1="0" y1="80" x2="800" y2="80" stroke="#374151" stroke-width="1"/>
<!-- smoothed waveform: same overall shape, no fine detail in transient peak -->
<path d="M0,80
L40,80 L48,80
L60,48 L65,120 L70,52 L75,115 L80,58 L85,108
L100,68 L108,92 L114,70 L120,90
L150,75 L160,86 L168,76 L174,85
L200,77 L210,84 L220,77 L230,83
L260,78 L280,82 L300,78 L320,82
L360,79 L380,81 L400,79 L420,81
L460,80 L480,80 L520,80
L580,80 L640,80 L700,80 L800,80 Z"
fill="url(#red-grad)" stroke="#ef4444" stroke-width="1" opacity="0.95"/>
</svg>
<div class="stats">
<div class="stat"><div class="label">Dateigröße</div><div class="value">0,48 MB</div></div>
<div class="stat"><div class="label">Bitrate</div><div class="value">128 kbit/s</div></div>
</div>
</div>
</div>
<div class="verdict">
<div class="verdict-q">Hört man den Unterschied?</div>
<div class="verdict-a">Auf dem Smartphone-Lautsprecher: meist nicht. Im Studio-Monitor mit Kopfhörer: oft schon. — MP3 wirft <strong>91 % der Daten weg</strong>, die der Mensch im Alltag nicht vermisst.</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

@@ -0,0 +1,119 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Drei Modalitäten, ein Hebel</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
--soft: #f8fafc;
--border: #cbd5e1;
--hl: #d63384;
--bild: #2563eb;
--audio: #ea580c;
--video: #7c3aed;
}
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 32px 48px; }
h1 { text-align: center; margin: 0 0 6px; font-size: 1.85rem; }
.sub { text-align: center; color: var(--muted); margin-bottom: 26px; font-size: 1.05rem; }
.table { display: grid; grid-template-columns: 140px 1fr 1fr 1fr; gap: 12px; max-width: 1180px; margin: 0 auto; align-items: stretch; }
.col-head { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.1em; font-weight: 700; color: var(--muted); padding: 0 8px 4px; }
.row-label { font-size: 1.15rem; font-weight: 700; padding: 16px 12px; display: flex; flex-direction: column; gap: 4px; justify-content: center; border-radius: 10px; }
.row-label.bild { background: #dbeafe; color: var(--bild); }
.row-label.audio { background: #ffedd5; color: var(--audio); }
.row-label.video { background: #ede9fe; color: var(--video); }
.row-label small { font-size: 0.78rem; font-weight: 400; color: var(--muted); text-transform: none; letter-spacing: 0; }
.cell { border: 1.5px solid var(--border); border-radius: 10px; padding: 12px 14px; background: #fff; display: flex; flex-direction: column; gap: 8px; }
.cell-format { font-family: ui-monospace, monospace; font-size: 0.85rem; color: var(--muted); }
.cell-size { font-size: 1.7rem; font-weight: 700; color: var(--dark); font-family: ui-monospace, monospace; }
.cell-bar { height: 8px; border-radius: 4px; background: var(--soft); position: relative; overflow: hidden; }
.cell-bar .fill { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 4px; }
.verdict {
margin-top: 22px;
max-width: 1180px;
margin-left: auto;
margin-right: auto;
border: 2px solid var(--hl);
border-radius: 12px;
padding: 14px 22px;
text-align: center;
}
.verdict-q { font-size: 1.05rem; font-weight: 700; color: var(--hl); }
.verdict-a { font-size: 0.95rem; color: var(--dark); margin-top: 4px; }
.verdict-a strong { color: var(--hl); }
</style>
</head>
<body>
<h1>Drei Modalitäten — derselbe Hebel</h1>
<div class="sub">Bild, Audio, Video schrumpfen alle dramatisch. Warum? Weil Wahrnehmung Lücken hat.</div>
<div class="table">
<div></div>
<div class="col-head">Roh</div>
<div class="col-head">Lossy (modern)</div>
<div class="col-head">Lossy (aggressiv)</div>
<div class="row-label bild">Bild<small>12-MP-Foto</small></div>
<div class="cell">
<div class="cell-format">RAW</div>
<div class="cell-size">36 MB</div>
<div class="cell-bar"><div class="fill" style="width:100%;background:#2563eb"></div></div>
</div>
<div class="cell">
<div class="cell-format">JPEG · Q 90</div>
<div class="cell-size">4 MB</div>
<div class="cell-bar"><div class="fill" style="width:11%;background:#2563eb"></div></div>
</div>
<div class="cell">
<div class="cell-format">JPEG · Q 50</div>
<div class="cell-size">800 KB</div>
<div class="cell-bar"><div class="fill" style="width:2.2%;background:#2563eb"></div></div>
</div>
<div class="row-label audio">Audio<small>30 s Stereo</small></div>
<div class="cell">
<div class="cell-format">WAV · 44,1 kHz · 16 bit</div>
<div class="cell-size">5,3 MB</div>
<div class="cell-bar"><div class="fill" style="width:100%;background:#ea580c"></div></div>
</div>
<div class="cell">
<div class="cell-format">MP3 · 192 kbit/s</div>
<div class="cell-size">720 KB</div>
<div class="cell-bar"><div class="fill" style="width:14%;background:#ea580c"></div></div>
</div>
<div class="cell">
<div class="cell-format">MP3 · 64 kbit/s</div>
<div class="cell-size">240 KB</div>
<div class="cell-bar"><div class="fill" style="width:4.5%;background:#ea580c"></div></div>
</div>
<div class="row-label video">Video<small>30 s · 4K · 30 fps</small></div>
<div class="cell">
<div class="cell-format">Roh · 8 bit</div>
<div class="cell-size">12 GB</div>
<div class="cell-bar"><div class="fill" style="width:100%;background:#7c3aed"></div></div>
</div>
<div class="cell">
<div class="cell-format">H.264 · 25 Mbit/s</div>
<div class="cell-size">94 MB</div>
<div class="cell-bar"><div class="fill" style="width:0.8%;background:#7c3aed"></div></div>
</div>
<div class="cell">
<div class="cell-format">H.265 · 12 Mbit/s</div>
<div class="cell-size">45 MB</div>
<div class="cell-bar"><div class="fill" style="width:0.4%;background:#7c3aed"></div></div>
</div>
</div>
<div class="verdict">
<div class="verdict-q">Bilder schrumpfen ×45. Audio ×22. Video ×270.</div>
<div class="verdict-a">Jede Reduktion nutzt eine andere Wahrnehmungs-Lücke: <strong>Bild</strong> die geringere Farbschärfe, <strong>Audio</strong> die Maskierung, <strong>Video</strong> die Frame-zu-Frame-Ähnlichkeit.</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

@@ -0,0 +1,182 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Die Reise einer Datei</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
--soft: #f8fafc;
--border: #cbd5e1;
--hl: #d63384;
--slot1: #0891b2;
--slot2: #2563eb;
--slot3: #7c3aed;
--slot4: #be185d;
--slot5: #ea580c;
}
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 32px 40px; }
h1 { text-align: center; margin: 0 0 6px; font-size: 1.85rem; }
.sub { text-align: center; color: var(--muted); margin-bottom: 30px; font-size: 1.05rem; }
.sub strong { color: var(--dark); }
.journey {
display: grid;
grid-template-columns: 1fr auto 1fr auto 1fr auto 1fr auto 1fr;
gap: 6px;
align-items: stretch;
max-width: 1200px;
margin: 0 auto;
}
.station {
border: 2px solid;
border-radius: 10px;
padding: 14px 12px 12px;
background: #fff;
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
}
.station.s1 { border-color: var(--slot1); }
.station.s2 { border-color: var(--slot2); }
.station.s3 { border-color: var(--slot3); }
.station.s4 { border-color: var(--slot4); }
.station.s5 { border-color: var(--slot5); }
.station-tag { font-size: 0.68rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.12em; color: var(--muted); }
.station-name { font-size: 1.05rem; font-weight: 700; text-align: center; line-height: 1.2; }
.station.s1 .station-name { color: var(--slot1); }
.station.s2 .station-name { color: var(--slot2); }
.station.s3 .station-name { color: var(--slot3); }
.station.s4 .station-name { color: var(--slot4); }
.station.s5 .station-name { color: var(--slot5); }
.station-detail { font-size: 0.78rem; color: var(--muted); text-align: center; }
.link {
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
padding: 0 4px;
justify-content: center;
}
.link-rate {
font-family: ui-monospace, monospace;
font-size: 0.88rem;
font-weight: 700;
color: var(--dark);
white-space: nowrap;
}
.link-protocol {
font-size: 0.7rem;
color: var(--muted);
text-transform: uppercase;
letter-spacing: 0.06em;
}
.link-arrow svg { width: 32px; height: 14px; }
.scenario {
margin-top: 28px;
max-width: 1200px;
margin-left: auto;
margin-right: auto;
background: var(--soft);
border: 1.5px solid var(--border);
border-radius: 10px;
padding: 16px 22px;
}
.scenario-head { font-size: 0.78rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.1em; color: var(--muted); margin-bottom: 6px; }
.scenario-body { font-size: 0.98rem; line-height: 1.55; }
.scenario-body code { font-family: ui-monospace, monospace; background: #fff; padding: 1px 6px; border-radius: 4px; border: 1px solid var(--border); }
.verdict {
margin-top: 18px;
max-width: 1200px;
margin-left: auto;
margin-right: auto;
text-align: center;
border: 2px solid var(--hl);
border-radius: 12px;
padding: 14px 22px;
}
.verdict-q { font-size: 1.1rem; font-weight: 700; color: var(--hl); }
.verdict-a { font-size: 0.92rem; color: var(--dark); margin-top: 4px; }
</style>
</head>
<body>
<h1>Die Reise einer Datei</h1>
<div class="sub">Ein 4K-Trailer (<strong>1,2 GB</strong>) reist von der externen SSD auf den Monitor — jede Etappe ist ein eigener Engpass.</div>
<div class="journey">
<div class="station s1">
<div class="station-tag">Quelle</div>
<div class="station-name">SSD<br>extern</div>
<div class="station-detail">NVMe-Stick</div>
</div>
<div class="link">
<div class="link-rate">3 200 MB/s</div>
<svg class="link-arrow" viewBox="0 0 32 14"><path d="M2,7 L26,7 M22,2 L28,7 L22,12" stroke="#d63384" stroke-width="2" fill="none"/></svg>
<div class="link-protocol">USB 4 / TB4</div>
</div>
<div class="station s2">
<div class="station-tag">Aufnahme</div>
<div class="station-name">Laptop</div>
<div class="station-detail">RAM &amp; CPU</div>
</div>
<div class="link">
<div class="link-rate">~7 000 MB/s</div>
<svg class="link-arrow" viewBox="0 0 32 14"><path d="M2,7 L26,7 M22,2 L28,7 L22,12" stroke="#d63384" stroke-width="2" fill="none"/></svg>
<div class="link-protocol">PCIe 4.0</div>
</div>
<div class="station s3">
<div class="station-tag">Decoder</div>
<div class="station-name">GPU</div>
<div class="station-detail">H.264-Hardware</div>
</div>
<div class="link">
<div class="link-rate">2 200 MB/s</div>
<svg class="link-arrow" viewBox="0 0 32 14"><path d="M2,7 L26,7 M22,2 L28,7 L22,12" stroke="#d63384" stroke-width="2" fill="none"/></svg>
<div class="link-protocol">HDMI 2.1</div>
</div>
<div class="station s4">
<div class="station-tag">Display</div>
<div class="station-name">4K-Monitor</div>
<div class="station-detail">3840 × 2160</div>
</div>
<div class="link">
<div class="link-rate">visuell</div>
<svg class="link-arrow" viewBox="0 0 32 14"><path d="M2,7 L26,7 M22,2 L28,7 L22,12" stroke="#d63384" stroke-width="2" fill="none"/></svg>
<div class="link-protocol">Licht</div>
</div>
<div class="station s5">
<div class="station-tag">Ziel</div>
<div class="station-name">Auge</div>
<div class="station-detail">Bewusstsein</div>
</div>
</div>
<div class="scenario">
<div class="scenario-head">Was hier passiert</div>
<div class="scenario-body">
Die <code>1,2 GB</code> liegen verschlüsselt komprimiert auf dem Stick. Sie reisen über <strong>USB-C</strong> in den RAM, werden vom GPU <strong>dekodiert</strong> (H.264 → roher RGB-Strom), und über <strong>HDMI</strong> als unkomprimiertes Bild an den Monitor geschickt. Dort entstehen pro Sekunde 60 Bilder mit je rund <code>24 MB</code> — also <strong>1,4 GB/s an rohem Pixelstrom</strong>, der niemals als Datei vorliegt.
</div>
</div>
<div class="verdict">
<div class="verdict-q">Speicher und Schnittstelle sind keine zwei Themen — sie sind die zwei Seiten desselben Engpasses.</div>
<div class="verdict-a">Wo Bytes wohnen entscheidet, wie schnell sie reisen können. Wo sie reisen entscheidet, wo sie wohnen müssen.</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

@@ -0,0 +1,254 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Eine Datei reist — und erzählt</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
--soft: #f8fafc;
--border: #cbd5e1;
--hl: #d63384;
--visible: #2563eb;
--hidden: #7c3aed;
--transit: #ea580c;
}
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 28px 40px; }
h1 { text-align: center; margin: 0 0 6px; font-size: 1.85rem; }
.sub { text-align: center; color: var(--muted); margin-bottom: 22px; font-size: 1.05rem; }
.sub strong { color: var(--dark); }
.scene {
display: grid;
grid-template-columns: 1fr 1.2fr;
gap: 22px;
max-width: 1200px;
margin: 0 auto;
}
.panel {
border: 2px solid;
border-radius: 12px;
padding: 16px 18px;
background: #fff;
display: flex;
flex-direction: column;
gap: 10px;
}
.panel.visible { border-color: var(--visible); }
.panel.hidden { border-color: var(--hidden); }
.panel-head { display: flex; justify-content: space-between; align-items: baseline; }
.panel-tag {
font-size: 0.7rem;
font-weight: 700;
letter-spacing: 0.12em;
text-transform: uppercase;
color: var(--muted);
}
.panel-name { font-size: 1.25rem; font-weight: 700; }
.panel.visible .panel-name { color: var(--visible); }
.panel.hidden .panel-name { color: var(--hidden); }
.photo {
border-radius: 8px;
overflow: hidden;
border: 1px solid var(--border);
display: block;
}
.photo-meta {
display: flex;
justify-content: space-between;
font-family: ui-monospace, monospace;
font-size: 0.78rem;
color: var(--muted);
padding: 0 2px;
}
.exif-list {
display: grid;
grid-template-columns: 130px 1fr;
gap: 4px 12px;
font-size: 0.86rem;
line-height: 1.4;
}
.exif-key {
font-size: 0.7rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--muted);
padding-top: 3px;
}
.exif-val { font-family: ui-monospace, monospace; color: var(--dark); }
.exif-val.gps { color: var(--hl); font-weight: 700; }
.transit-strip {
max-width: 1200px;
margin: 18px auto 0;
border: 2px solid var(--transit);
border-radius: 12px;
padding: 14px 18px;
background: #fff;
display: grid;
grid-template-columns: auto 1fr;
gap: 16px;
align-items: center;
}
.transit-tag {
font-size: 0.7rem;
font-weight: 700;
letter-spacing: 0.12em;
text-transform: uppercase;
color: var(--transit);
writing-mode: vertical-rl;
transform: rotate(180deg);
text-align: center;
}
.transit-body { display: flex; flex-direction: column; gap: 8px; }
.transit-route {
display: flex;
align-items: center;
gap: 6px;
font-size: 0.92rem;
font-weight: 700;
flex-wrap: wrap;
}
.hop {
background: var(--soft);
border: 1.5px solid var(--border);
padding: 4px 10px;
border-radius: 6px;
font-family: ui-monospace, monospace;
font-size: 0.82rem;
color: var(--dark);
}
.hop.origin { border-color: var(--visible); color: var(--visible); }
.hop.dest { border-color: var(--visible); color: var(--visible); }
.hop.edge { border-color: var(--transit); color: var(--transit); }
.arrow { color: var(--muted); font-family: ui-monospace, monospace; }
.transit-headers {
font-family: ui-monospace, monospace;
font-size: 0.78rem;
color: var(--muted);
line-height: 1.5;
}
.transit-headers strong { color: var(--dark); }
.verdict {
margin-top: 18px;
max-width: 1200px;
margin-left: auto;
margin-right: auto;
text-align: center;
border: 2px solid var(--hl);
border-radius: 12px;
padding: 14px 22px;
}
.verdict-q { font-size: 1.1rem; font-weight: 700; color: var(--hl); }
.verdict-a { font-size: 0.93rem; color: var(--dark); margin-top: 4px; }
.verdict-a strong { color: var(--hl); }
</style>
</head>
<body>
<h1>Eine Datei reist — und erzählt</h1>
<div class="sub">Ein Smartphone-Foto geht von <strong>Stuttgart</strong> nach <strong>Tokyo</strong>. Was sieht der Empfänger — und was bekommt er noch dazu?</div>
<div class="scene">
<div class="panel visible">
<div class="panel-head">
<span class="panel-name">Inhalt</span>
<span class="panel-tag">Was du siehst</span>
</div>
<svg class="photo" viewBox="0 0 420 280" preserveAspectRatio="xMidYMid slice">
<defs>
<linearGradient id="sky" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#fde68a"/>
<stop offset="55%" stop-color="#fda4af"/>
<stop offset="100%" stop-color="#9333ea"/>
</linearGradient>
<linearGradient id="hills" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#312e81"/>
<stop offset="100%" stop-color="#0f172a"/>
</linearGradient>
</defs>
<rect x="0" y="0" width="420" height="280" fill="url(#sky)"/>
<circle cx="320" cy="105" r="32" fill="#fff7ed" opacity="0.95"/>
<path d="M0,200 L60,170 L110,185 L160,160 L210,178 L260,150 L310,172 L360,148 L420,168 L420,280 L0,280 Z" fill="url(#hills)"/>
<path d="M0,225 L50,210 L100,222 L150,205 L200,220 L250,202 L300,218 L350,200 L420,215 L420,280 L0,280 Z" fill="#1e1b4b" opacity="0.7"/>
<rect x="80" y="225" width="14" height="42" fill="#0f172a"/>
<rect x="180" y="232" width="10" height="35" fill="#0f172a"/>
<rect x="240" y="220" width="18" height="48" fill="#0f172a"/>
<rect x="300" y="234" width="11" height="34" fill="#0f172a"/>
<rect x="86" y="232" width="3" height="3" fill="#fbbf24"/>
<rect x="188" y="240" width="2" height="2" fill="#fbbf24"/>
<rect x="248" y="228" width="3" height="3" fill="#fbbf24"/>
<rect x="307" y="240" width="2" height="2" fill="#fbbf24"/>
</svg>
<div class="photo-meta">
<span>HEIC · 4032 × 3024</span>
<span>3,2 MB</span>
</div>
</div>
<div class="panel hidden">
<div class="panel-head">
<span class="panel-name">Gepäck</span>
<span class="panel-tag">Was die Datei über sich weiß</span>
</div>
<div class="exif-list">
<div class="exif-key">Kamera</div>
<div class="exif-val">Apple iPhone 15 Pro · 24 mm · ƒ/1.78</div>
<div class="exif-key">Belichtung</div>
<div class="exif-val">1/250 s · ISO 100 · EV 0</div>
<div class="exif-key">Aufgenommen</div>
<div class="exif-val">2026-04-12 · 18:47:12 · +02:00</div>
<div class="exif-key">GPS</div>
<div class="exif-val gps">48.7847° N · 9.1825° E · 248 m<br><span style="font-weight:400">(Stuttgart, Königstraße 28)</span></div>
<div class="exif-key">Software</div>
<div class="exif-val">iOS 18.4.1 · HDR · Live Photo</div>
<div class="exif-key">Farbprofil</div>
<div class="exif-val">Display P3</div>
</div>
</div>
</div>
<div class="transit-strip">
<div class="transit-tag">Weg</div>
<div class="transit-body">
<div class="transit-route">
<span class="hop origin">Stuttgart</span>
<span class="arrow">→</span>
<span class="hop">DNS</span>
<span class="arrow">→</span>
<span class="hop">TLS 1.3</span>
<span class="arrow">→</span>
<span class="hop edge">CDN-Edge Tokyo</span>
<span class="arrow">→</span>
<span class="hop dest">Tokyo</span>
</div>
<div class="transit-headers">
<strong>HTTP/3 200 OK</strong> · content-type: image/heic · content-length: 3 220 480 · <strong>RTT 47 ms</strong> · cache: HIT (Edge tok-7) · age: 312 s
</div>
</div>
</div>
<div class="verdict">
<div class="verdict-q">Eine Datei = Inhalt + Gepäck + Weg.</div>
<div class="verdict-a"><strong>Inhalt</strong> sieht der Empfänger. <strong>Gepäck</strong> verrät, wer sie gemacht hat — und wo. <strong>Weg</strong> entscheidet, wie schnell sie ankommt. Drei Schichten, eine Datei.</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

+194
View File
@@ -0,0 +1,194 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>1 TB verkauft, 931 GB angezeigt — wo gehen die 69 GB hin?</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
--soft: #f8fafc;
--border: #cbd5e1;
--hl: #d63384;
--marketing: #2563eb;
--os: #ea580c;
}
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 32px 40px; }
h1 { text-align: center; margin: 0 0 6px; font-size: 1.75rem; }
.sub { text-align: center; color: var(--muted); margin-bottom: 24px; font-size: 1.05rem; }
.sub strong { color: var(--dark); }
.compare {
display: grid;
grid-template-columns: 1fr 80px 1fr;
gap: 18px;
max-width: 1100px;
margin: 0 auto;
align-items: stretch;
}
.side {
border: 2px solid;
border-radius: 12px;
padding: 18px 22px;
background: #fff;
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
}
.side.marketing { border-color: var(--marketing); }
.side.os { border-color: var(--os); }
.side-tag {
font-size: 0.72rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.12em;
color: var(--muted);
}
.side.marketing .side-name { color: var(--marketing); }
.side.os .side-name { color: var(--os); }
.side-name { font-size: 1.15rem; font-weight: 700; }
.label-mock {
background: var(--soft);
border: 1.5px solid var(--border);
border-radius: 8px;
padding: 14px 22px;
min-width: 240px;
text-align: center;
font-family: ui-monospace, monospace;
font-size: 0.85rem;
color: var(--muted);
line-height: 1.5;
}
.label-mock .big {
font-family: system-ui, sans-serif;
font-size: 2.2rem;
font-weight: 900;
display: block;
color: var(--dark);
line-height: 1.05;
}
.side.marketing .label-mock .big { color: var(--marketing); }
.side.os .label-mock .big { color: var(--os); }
.label-mock .small-line { font-size: 0.78rem; }
.formel {
font-family: ui-monospace, monospace;
font-size: 0.85rem;
color: var(--muted);
text-align: center;
line-height: 1.6;
}
.formel strong { color: var(--dark); }
.arrow-col {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 4px;
color: var(--muted);
}
.arrow-col svg { display: block; }
.arrow-col .why {
font-size: 0.78rem;
font-weight: 700;
color: var(--hl);
text-align: center;
line-height: 1.25;
}
.math-box {
margin-top: 22px;
max-width: 1100px;
margin-left: auto;
margin-right: auto;
background: var(--soft);
border: 1.5px solid var(--border);
border-radius: 10px;
padding: 16px 22px;
}
.math-box-head { font-size: 0.78rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.1em; color: var(--muted); margin-bottom: 8px; }
.math-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 22px; font-family: ui-monospace, monospace; font-size: 0.9rem; line-height: 1.6; }
.math-grid .key { color: var(--muted); }
.math-grid .val { color: var(--dark); font-weight: 700; }
.math-grid .val.hl { color: var(--hl); }
.verdict {
margin-top: 18px;
max-width: 1100px;
margin-left: auto;
margin-right: auto;
text-align: center;
border: 2px solid var(--hl);
border-radius: 12px;
padding: 14px 22px;
}
.verdict-q { font-size: 1.05rem; font-weight: 700; color: var(--hl); }
.verdict-a { font-size: 0.93rem; color: var(--dark); margin-top: 4px; }
.verdict-a code { font-family: ui-monospace, monospace; background: #fff; padding: 1px 5px; border-radius: 4px; border: 1px solid var(--border); }
</style>
</head>
<body>
<h1>„1 TB" gekauft — 931 GB im Finder. Wo sind die 69 GB hin?</h1>
<div class="sub">Nirgendwo. Es sind <strong>dieselben Byte</strong>. Nur zwei Welten zählen anders.</div>
<div class="compare">
<div class="side marketing">
<div class="side-tag">Auf der Verpackung</div>
<div class="side-name">Marketing</div>
<div class="label-mock">
<span class="big">1 TB</span>
<span class="small-line">externe SSD</span>
</div>
<div class="formel">
1 TB = <strong>10<sup>12</sup></strong> Byte<br>
= 1 000 000 000 000
</div>
</div>
<div class="arrow-col">
<svg viewBox="0 0 60 30" width="56" height="30"><path d="M5,15 L48,15 M42,7 L52,15 L42,23" stroke="#d63384" stroke-width="2.5" fill="none"/></svg>
<div class="why">geteilt durch<br>2<sup>30</sup></div>
</div>
<div class="side os">
<div class="side-tag">Im Finder · Explorer</div>
<div class="side-name">Betriebssystem</div>
<div class="label-mock">
<span class="big">931 GB</span>
<span class="small-line">eigentlich: 931 GiB</span>
</div>
<div class="formel">
1 GiB = <strong>2<sup>30</sup></strong> Byte<br>
= 1 073 741 824
</div>
</div>
</div>
<div class="math-box">
<div class="math-box-head">Die Rechnung</div>
<div class="math-grid">
<span class="key">Marketing schreibt</span>
<span class="val">1 TB = 1 000 000 000 000 Byte (Basis 10)</span>
<span class="key">Betriebssystem rechnet</span>
<span class="val">1 TiB = 1 099 511 627 776 Byte (Basis 2)</span>
<span class="key">1 TB in GiB umrechnen</span>
<span class="val hl">10<sup>12</sup> ÷ 2<sup>30</sup> ≈ 931,3 GiB — der Finder zeigt also „931 GB"</span>
<span class="key">Was die Studis sehen</span>
<span class="val">Etikett: GB · Anzeige: GB · Bedeutung: zwei verschiedene Dinge</span>
</div>
</div>
<div class="verdict">
<div class="verdict-q">Es fehlt nichts. Es wird nur in zwei Sprachen gezählt.</div>
<div class="verdict-a">Korrekt wären <code>GiB</code> (binär, 1024) und <code>GB</code> (dezimal, 1000). In der Realität verwenden beide Welten <code>GB</code> und meinen verschiedene Zahlen.</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

@@ -0,0 +1,232 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Nyquist-Shannon — wie oft muss man messen?</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
--soft: #f8fafc;
--border: #cbd5e1;
--hl: #d63384;
--bad: #ef4444;
--warn: #f59e0b;
--good: #16a34a;
}
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 28px 40px; }
h1 { text-align: center; margin: 0 0 6px; font-size: 1.75rem; }
.sub { text-align: center; color: var(--muted); margin-bottom: 22px; font-size: 1.05rem; }
.sub strong { color: var(--dark); }
.cases {
display: flex;
flex-direction: column;
gap: 12px;
max-width: 1180px;
margin: 0 auto;
}
.case {
display: grid;
grid-template-columns: 200px 1fr;
gap: 18px;
align-items: center;
border: 2px solid;
border-radius: 10px;
padding: 10px 14px;
background: #fff;
}
.case.bad { border-color: var(--bad); }
.case.warn { border-color: var(--warn); }
.case.good { border-color: var(--good); }
.case-meta { display: flex; flex-direction: column; gap: 4px; }
.case-tag {
font-size: 0.7rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.12em;
color: var(--muted);
}
.case-name { font-size: 1.05rem; font-weight: 700; }
.case.bad .case-name { color: var(--bad); }
.case.warn .case-name { color: var(--warn); }
.case.good .case-name { color: var(--good); }
.case-rate { font-family: ui-monospace, monospace; font-size: 0.82rem; color: var(--dark); }
.case-note { font-size: 0.78rem; color: var(--muted); line-height: 1.35; }
.plot { background: var(--soft); border-radius: 8px; }
.plot svg { display: block; }
.verdict {
margin-top: 20px;
max-width: 1180px;
margin-left: auto;
margin-right: auto;
text-align: center;
border: 2px solid var(--hl);
border-radius: 12px;
padding: 14px 22px;
}
.verdict-q { font-size: 1.05rem; font-weight: 700; color: var(--hl); }
.verdict-a { font-size: 0.92rem; color: var(--dark); margin-top: 4px; }
.verdict-a strong { color: var(--hl); }
.verdict-a code { font-family: ui-monospace, monospace; background: var(--soft); padding: 1px 5px; border-radius: 4px; }
</style>
</head>
<body>
<h1>Nyquist-Shannon — wie oft müssen wir messen?</h1>
<div class="sub">Dieselbe Welle, drei Sample-Raten. Eine fällt durch, eine reicht knapp, eine ist sicher.</div>
<div class="cases">
<div class="case bad">
<div class="case-meta">
<div class="case-tag">Zu wenig</div>
<div class="case-name">Aliasing</div>
<div class="case-rate">f<sub>s</sub> = 0,9 · f</div>
<div class="case-note">Die Sample-Punkte sitzen auf der Welle — aber verbunden sehen sie aus wie eine <strong>ganz andere, langsamere</strong> Welle.</div>
</div>
<div class="plot">
<svg viewBox="0 0 880 140" width="100%" height="140" preserveAspectRatio="none">
<line x1="20" y1="70" x2="860" y2="70" stroke="#cbd5e1" stroke-width="1" stroke-dasharray="3,4"/>
<path d="M 20,70 Q 46.25,-20 72.5,70 T 125,70 T 177.5,70 T 230,70 T 282.5,70 T 335,70 T 387.5,70 T 440,70 T 492.5,70 T 545,70 T 597.5,70 T 650,70 T 702.5,70 T 755,70 T 807.5,70 T 860,70"
stroke="#cbd5e1" stroke-width="1.5" fill="none"/>
<polyline points="20,70 136.7,41 253.4,25.7 370.1,31.2 486.8,54.9 603.5,85.8 720.2,109.2 836.9,114.2"
stroke="#ef4444" stroke-width="2.5" fill="none"/>
<circle cx="20" cy="70" r="5" fill="#ef4444"/>
<circle cx="136.7" cy="41" r="5" fill="#ef4444"/>
<circle cx="253.4" cy="25.7" r="5" fill="#ef4444"/>
<circle cx="370.1" cy="31.2" r="5" fill="#ef4444"/>
<circle cx="486.8" cy="54.9" r="5" fill="#ef4444"/>
<circle cx="603.5" cy="85.8" r="5" fill="#ef4444"/>
<circle cx="720.2" cy="109.2" r="5" fill="#ef4444"/>
<circle cx="836.9" cy="114.2" r="5" fill="#ef4444"/>
</svg>
</div>
</div>
<div class="case warn">
<div class="case-meta">
<div class="case-tag">Genau</div>
<div class="case-name">Nyquist-Grenze</div>
<div class="case-rate">f<sub>s</sub> = 2 · f</div>
<div class="case-note">Sample exakt auf <strong>Peak und Tal</strong>. Mathematisch reicht das — visuell sieht es kaputt aus.</div>
</div>
<div class="plot">
<svg viewBox="0 0 880 140" width="100%" height="140" preserveAspectRatio="none">
<line x1="20" y1="70" x2="860" y2="70" stroke="#cbd5e1" stroke-width="1" stroke-dasharray="3,4"/>
<path d="M 20,70 Q 46.25,-20 72.5,70 T 125,70 T 177.5,70 T 230,70 T 282.5,70 T 335,70 T 387.5,70 T 440,70 T 492.5,70 T 545,70 T 597.5,70 T 650,70 T 702.5,70 T 755,70 T 807.5,70 T 860,70"
stroke="#cbd5e1" stroke-width="1.5" fill="none"/>
<polyline points="46.25,25 98.75,115 151.25,25 203.75,115 256.25,25 308.75,115 361.25,25 413.75,115 466.25,25 518.75,115 571.25,25 623.75,115 676.25,25 728.75,115 781.25,25 833.75,115"
stroke="#f59e0b" stroke-width="2" fill="none" opacity="0.5"/>
<circle cx="46.25" cy="25" r="5" fill="#f59e0b"/>
<circle cx="98.75" cy="115" r="5" fill="#f59e0b"/>
<circle cx="151.25" cy="25" r="5" fill="#f59e0b"/>
<circle cx="203.75" cy="115" r="5" fill="#f59e0b"/>
<circle cx="256.25" cy="25" r="5" fill="#f59e0b"/>
<circle cx="308.75" cy="115" r="5" fill="#f59e0b"/>
<circle cx="361.25" cy="25" r="5" fill="#f59e0b"/>
<circle cx="413.75" cy="115" r="5" fill="#f59e0b"/>
<circle cx="466.25" cy="25" r="5" fill="#f59e0b"/>
<circle cx="518.75" cy="115" r="5" fill="#f59e0b"/>
<circle cx="571.25" cy="25" r="5" fill="#f59e0b"/>
<circle cx="623.75" cy="115" r="5" fill="#f59e0b"/>
<circle cx="676.25" cy="25" r="5" fill="#f59e0b"/>
<circle cx="728.75" cy="115" r="5" fill="#f59e0b"/>
<circle cx="781.25" cy="25" r="5" fill="#f59e0b"/>
<circle cx="833.75" cy="115" r="5" fill="#f59e0b"/>
</svg>
</div>
</div>
<div class="case good">
<div class="case-meta">
<div class="case-tag">Sicher</div>
<div class="case-name">Überabtastung</div>
<div class="case-rate">f<sub>s</sub> = 8 · f</div>
<div class="case-note">Genug Punkte — die Welle wird Punkt für Punkt nachgezeichnet. So macht es eine CD.</div>
</div>
<div class="plot">
<svg viewBox="0 0 880 140" width="100%" height="140" preserveAspectRatio="none">
<line x1="20" y1="70" x2="860" y2="70" stroke="#cbd5e1" stroke-width="1" stroke-dasharray="3,4"/>
<path d="M 20,70 Q 46.25,-20 72.5,70 T 125,70 T 177.5,70 T 230,70 T 282.5,70 T 335,70 T 387.5,70 T 440,70 T 492.5,70 T 545,70 T 597.5,70 T 650,70 T 702.5,70 T 755,70 T 807.5,70 T 860,70"
stroke="#16a34a" stroke-width="2.5" fill="none" opacity="0.9"/>
<circle cx="20" cy="70" r="2.5" fill="#16a34a"/>
<circle cx="33.1" cy="38.2" r="2.5" fill="#16a34a"/>
<circle cx="46.2" cy="25" r="2.5" fill="#16a34a"/>
<circle cx="59.4" cy="38.2" r="2.5" fill="#16a34a"/>
<circle cx="72.5" cy="70" r="2.5" fill="#16a34a"/>
<circle cx="85.6" cy="101.8" r="2.5" fill="#16a34a"/>
<circle cx="98.8" cy="115" r="2.5" fill="#16a34a"/>
<circle cx="111.9" cy="101.8" r="2.5" fill="#16a34a"/>
<circle cx="125" cy="70" r="2.5" fill="#16a34a"/>
<circle cx="138.1" cy="38.2" r="2.5" fill="#16a34a"/>
<circle cx="151.2" cy="25" r="2.5" fill="#16a34a"/>
<circle cx="164.4" cy="38.2" r="2.5" fill="#16a34a"/>
<circle cx="177.5" cy="70" r="2.5" fill="#16a34a"/>
<circle cx="190.6" cy="101.8" r="2.5" fill="#16a34a"/>
<circle cx="203.8" cy="115" r="2.5" fill="#16a34a"/>
<circle cx="216.9" cy="101.8" r="2.5" fill="#16a34a"/>
<circle cx="230" cy="70" r="2.5" fill="#16a34a"/>
<circle cx="243.1" cy="38.2" r="2.5" fill="#16a34a"/>
<circle cx="256.2" cy="25" r="2.5" fill="#16a34a"/>
<circle cx="269.4" cy="38.2" r="2.5" fill="#16a34a"/>
<circle cx="282.5" cy="70" r="2.5" fill="#16a34a"/>
<circle cx="295.6" cy="101.8" r="2.5" fill="#16a34a"/>
<circle cx="308.8" cy="115" r="2.5" fill="#16a34a"/>
<circle cx="321.9" cy="101.8" r="2.5" fill="#16a34a"/>
<circle cx="335" cy="70" r="2.5" fill="#16a34a"/>
<circle cx="348.1" cy="38.2" r="2.5" fill="#16a34a"/>
<circle cx="361.2" cy="25" r="2.5" fill="#16a34a"/>
<circle cx="374.4" cy="38.2" r="2.5" fill="#16a34a"/>
<circle cx="387.5" cy="70" r="2.5" fill="#16a34a"/>
<circle cx="400.6" cy="101.8" r="2.5" fill="#16a34a"/>
<circle cx="413.8" cy="115" r="2.5" fill="#16a34a"/>
<circle cx="426.9" cy="101.8" r="2.5" fill="#16a34a"/>
<circle cx="440" cy="70" r="2.5" fill="#16a34a"/>
<circle cx="453.1" cy="38.2" r="2.5" fill="#16a34a"/>
<circle cx="466.2" cy="25" r="2.5" fill="#16a34a"/>
<circle cx="479.4" cy="38.2" r="2.5" fill="#16a34a"/>
<circle cx="492.5" cy="70" r="2.5" fill="#16a34a"/>
<circle cx="505.6" cy="101.8" r="2.5" fill="#16a34a"/>
<circle cx="518.8" cy="115" r="2.5" fill="#16a34a"/>
<circle cx="531.9" cy="101.8" r="2.5" fill="#16a34a"/>
<circle cx="545" cy="70" r="2.5" fill="#16a34a"/>
<circle cx="558.1" cy="38.2" r="2.5" fill="#16a34a"/>
<circle cx="571.2" cy="25" r="2.5" fill="#16a34a"/>
<circle cx="584.4" cy="38.2" r="2.5" fill="#16a34a"/>
<circle cx="597.5" cy="70" r="2.5" fill="#16a34a"/>
<circle cx="610.6" cy="101.8" r="2.5" fill="#16a34a"/>
<circle cx="623.8" cy="115" r="2.5" fill="#16a34a"/>
<circle cx="636.9" cy="101.8" r="2.5" fill="#16a34a"/>
<circle cx="650" cy="70" r="2.5" fill="#16a34a"/>
<circle cx="663.1" cy="38.2" r="2.5" fill="#16a34a"/>
<circle cx="676.2" cy="25" r="2.5" fill="#16a34a"/>
<circle cx="689.4" cy="38.2" r="2.5" fill="#16a34a"/>
<circle cx="702.5" cy="70" r="2.5" fill="#16a34a"/>
<circle cx="715.6" cy="101.8" r="2.5" fill="#16a34a"/>
<circle cx="728.8" cy="115" r="2.5" fill="#16a34a"/>
<circle cx="741.9" cy="101.8" r="2.5" fill="#16a34a"/>
<circle cx="755" cy="70" r="2.5" fill="#16a34a"/>
<circle cx="768.1" cy="38.2" r="2.5" fill="#16a34a"/>
<circle cx="781.2" cy="25" r="2.5" fill="#16a34a"/>
<circle cx="794.4" cy="38.2" r="2.5" fill="#16a34a"/>
<circle cx="807.5" cy="70" r="2.5" fill="#16a34a"/>
<circle cx="820.6" cy="101.8" r="2.5" fill="#16a34a"/>
<circle cx="833.8" cy="115" r="2.5" fill="#16a34a"/>
<circle cx="846.9" cy="101.8" r="2.5" fill="#16a34a"/>
</svg>
</div>
</div>
</div>
<div class="verdict">
<div class="verdict-q">f<sub>s</sub> ≥ 2 · f<sub>max</sub>. So einfach. So endgültig.</div>
<div class="verdict-a">Das Ohr hört bis <strong>20 kHz</strong>. 2 × 20 = 40 kHz. Die CD nimmt <code>44,1 kHz</code> — die 4,1 sind Sicherheits-Marge.</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

@@ -0,0 +1,173 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Wir haben gelernt zu lesen — jetzt: wie kommt es rein?</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
--soft: #f8fafc;
--border: #cbd5e1;
--hl: #d63384;
--done: #94a3b8;
--next: #d63384;
--bytes: #0891b2;
}
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 32px 40px; }
h1 { text-align: center; margin: 0 0 6px; font-size: 1.7rem; }
.sub { text-align: center; color: var(--muted); margin-bottom: 36px; font-size: 1.05rem; }
.sub strong { color: var(--dark); }
.pivot {
display: grid;
grid-template-columns: 200px 1fr 240px 1fr 200px;
gap: 8px;
max-width: 1200px;
margin: 0 auto;
align-items: center;
}
.station {
border: 2px solid var(--border);
border-radius: 12px;
padding: 18px 14px;
background: #fff;
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
}
.station.bytes { border-color: var(--bytes); background: #0f0f23; color: #fff; }
.station-tag {
font-size: 0.7rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.12em;
color: var(--muted);
}
.station.bytes .station-tag { color: #94a3b8; }
.station-name { font-size: 1.3rem; font-weight: 700; }
.station.bytes .station-name { color: #67e8f9; }
.station-detail { font-size: 0.85rem; color: var(--muted); }
.station.bytes .station-detail { color: #94a3b8; font-family: ui-monospace, monospace; font-size: 0.78rem; line-height: 1.4; }
.station-art { display: flex; align-items: center; justify-content: center; height: 70px; }
.station-art svg { width: 80%; height: 100%; }
.strang {
display: flex;
flex-direction: column;
align-items: center;
gap: 6px;
padding: 0 6px;
}
.strang-arrow svg { display: block; width: 100%; height: 28px; }
.strang-label {
font-size: 0.95rem;
font-weight: 700;
text-align: center;
line-height: 1.3;
}
.strang.next .strang-label { color: var(--next); }
.strang.done .strang-label { color: var(--done); text-decoration: line-through; text-decoration-color: var(--done); text-decoration-thickness: 1.5px; }
.strang-tag {
font-size: 0.72rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.12em;
text-align: center;
}
.strang.next .strang-tag { color: var(--next); }
.strang.done .strang-tag { color: var(--done); }
.verdict {
margin-top: 28px;
max-width: 1100px;
margin-left: auto;
margin-right: auto;
text-align: center;
border: 2px solid var(--hl);
border-radius: 12px;
padding: 14px 22px;
}
.verdict-q { font-size: 1.1rem; font-weight: 700; color: var(--hl); }
.verdict-a { font-size: 0.95rem; color: var(--dark); margin-top: 4px; }
.verdict-a strong { color: var(--hl); }
</style>
</head>
<body>
<h1>Wir haben gelernt zu <strong>lesen</strong>. Jetzt: wie kommt es <strong>rein</strong>?</h1>
<div class="sub">Die rechte Seite haben wir abgearbeitet. Die linke ist die nächste Stunde.</div>
<div class="pivot">
<div class="station">
<div class="station-tag">Quelle</div>
<div class="station-name">Welt</div>
<div class="station-art">
<svg viewBox="0 0 120 70" preserveAspectRatio="xMidYMid meet">
<path d="M5,35 Q15,10 25,35 T45,35 T65,35 T85,35 T105,35 T115,35"
stroke="#d63384" stroke-width="2.5" fill="none"/>
<circle cx="115" cy="35" r="3" fill="#d63384"/>
</svg>
</div>
<div class="station-detail">Schallwelle · Lichtwelle<br>kontinuierlich · analog</div>
</div>
<div class="strang next">
<div class="strang-tag">jetzt dran</div>
<div class="strang-arrow">
<svg viewBox="0 0 220 28" preserveAspectRatio="none">
<line x1="6" y1="14" x2="200" y2="14" stroke="#d63384" stroke-width="2.5"/>
<path d="M195,7 L208,14 L195,21" stroke="#d63384" stroke-width="2.5" fill="none"/>
</svg>
</div>
<div class="strang-label">Sampling + Quantisierung</div>
</div>
<div class="station bytes">
<div class="station-tag">Mitte</div>
<div class="station-name">Datei</div>
<div class="station-detail">
89 50 4E 47<br>
0D 0A 1A 0A<br>
00 00 00 0D
</div>
</div>
<div class="strang done">
<div class="strang-tag">schon durch</div>
<div class="strang-arrow">
<svg viewBox="0 0 220 28" preserveAspectRatio="none">
<line x1="6" y1="14" x2="200" y2="14" stroke="#94a3b8" stroke-width="2"/>
<path d="M195,7 L208,14 L195,21" stroke="#94a3b8" stroke-width="2" fill="none"/>
</svg>
</div>
<div class="strang-label">Notation · Encoding · Format</div>
</div>
<div class="station">
<div class="station-tag">Ziel</div>
<div class="station-name">Mensch</div>
<div class="station-art">
<svg viewBox="0 0 120 70" preserveAspectRatio="xMidYMid meet">
<rect x="14" y="14" width="92" height="14" rx="2" fill="#1a1a2e"/>
<rect x="14" y="34" width="68" height="6" rx="1" fill="#cbd5e1"/>
<rect x="14" y="44" width="78" height="6" rx="1" fill="#cbd5e1"/>
<rect x="14" y="54" width="56" height="6" rx="1" fill="#cbd5e1"/>
</svg>
</div>
<div class="station-detail">Text · Bild · Klang<br>Bedeutung</div>
</div>
</div>
<div class="verdict">
<div class="verdict-q">Die Datei ist die Mitte. Beide Wege führen durch sie hindurch.</div>
<div class="verdict-a"><strong>Rechts:</strong> aus Byte wird Bedeutung — gerade gelernt. &nbsp;&nbsp; <strong>Links:</strong> aus Welt wird Byte — jetzt.</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

@@ -0,0 +1,159 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Psychoakustik — was MP3 weglässt</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
--soft: #f8fafc;
--border: #cbd5e1;
--hl: #d63384;
--kept: #16a34a;
--tossed: #94a3b8;
--masker: #2563eb;
--threshold: #ea580c;
}
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 30px 40px; }
h1 { text-align: center; margin: 0 0 6px; font-size: 1.75rem; }
.sub { text-align: center; color: var(--muted); margin-bottom: 22px; font-size: 1.05rem; }
.sub strong { color: var(--dark); }
.chart-wrap {
max-width: 1180px;
margin: 0 auto;
background: #fff;
border: 1.5px solid var(--border);
border-radius: 12px;
padding: 16px 20px;
}
.chart-head {
display: flex;
justify-content: space-between;
align-items: baseline;
margin-bottom: 8px;
}
.chart-title { font-size: 1rem; font-weight: 700; }
.legend {
display: flex;
gap: 16px;
font-size: 0.78rem;
color: var(--muted);
}
.legend-item { display: flex; align-items: center; gap: 4px; }
.legend-swatch {
width: 14px;
height: 14px;
border-radius: 3px;
display: inline-block;
}
.legend-swatch.kept { background: var(--kept); }
.legend-swatch.tossed { background: var(--tossed); }
.legend-swatch.masker { background: var(--masker); }
.legend-swatch.threshold {
background: transparent;
border-top: 2px dashed var(--threshold);
height: 8px;
margin-top: 5px;
}
.verdict {
margin-top: 22px;
max-width: 1180px;
margin-left: auto;
margin-right: auto;
text-align: center;
border: 2px solid var(--hl);
border-radius: 12px;
padding: 14px 22px;
}
.verdict-q { font-size: 1.1rem; font-weight: 700; color: var(--hl); }
.verdict-a { font-size: 0.93rem; color: var(--dark); margin-top: 4px; }
.verdict-a strong { color: var(--hl); }
</style>
</head>
<body>
<h1>Psychoakustik — was MP3 wegwirft</h1>
<div class="sub">Ein lauter Ton macht leise Nachbarn <strong>unhörbar</strong>. Was nicht hörbar ist, muss man nicht speichern.</div>
<div class="chart-wrap">
<div class="chart-head">
<div class="chart-title">Lautstärke (dB SPL) über Frequenz (Hz, logarithmisch)</div>
<div class="legend">
<span class="legend-item"><span class="legend-swatch masker"></span>lauter Ton (Masker)</span>
<span class="legend-item"><span class="legend-swatch kept"></span>hörbar · bleibt</span>
<span class="legend-item"><span class="legend-swatch tossed"></span>maskiert · raus</span>
<span class="legend-item"><span class="legend-swatch threshold"></span>Hörschwelle</span>
</div>
</div>
<svg viewBox="0 0 1100 380" width="100%" height="380">
<line x1="80" y1="340" x2="1060" y2="340" stroke="#1a1a2e" stroke-width="1.5"/>
<line x1="80" y1="20" x2="80" y2="340" stroke="#1a1a2e" stroke-width="1.5"/>
<text x="20" y="30" font-size="11" fill="#6b7280">dB</text>
<text x="40" y="50" font-size="10" fill="#6b7280" text-anchor="end">100</text>
<text x="40" y="125" font-size="10" fill="#6b7280" text-anchor="end">75</text>
<text x="40" y="200" font-size="10" fill="#6b7280" text-anchor="end">50</text>
<text x="40" y="275" font-size="10" fill="#6b7280" text-anchor="end">25</text>
<text x="40" y="345" font-size="10" fill="#6b7280" text-anchor="end">0</text>
<line x1="75" y1="50" x2="80" y2="50" stroke="#1a1a2e"/>
<line x1="75" y1="125" x2="80" y2="125" stroke="#1a1a2e"/>
<line x1="75" y1="200" x2="80" y2="200" stroke="#1a1a2e"/>
<line x1="75" y1="275" x2="80" y2="275" stroke="#1a1a2e"/>
<text x="100" y="360" font-size="10" fill="#6b7280">20</text>
<text x="260" y="360" font-size="10" fill="#6b7280">100</text>
<text x="420" y="360" font-size="10" fill="#6b7280">500</text>
<text x="580" y="360" font-size="10" fill="#6b7280">1k</text>
<text x="740" y="360" font-size="10" fill="#6b7280">5k</text>
<text x="900" y="360" font-size="10" fill="#6b7280">10k</text>
<text x="1040" y="360" font-size="10" fill="#6b7280">20k</text>
<text x="540" y="378" font-size="11" fill="#6b7280" text-anchor="middle">Frequenz [Hz]</text>
<path d="M100,80 Q170,130 260,200 Q350,290 420,310 Q500,335 580,330 Q670,310 740,295 Q820,280 900,250 Q970,200 1040,80"
stroke="#ea580c" stroke-width="2" stroke-dasharray="5,5" fill="none"/>
<path d="M460,340 L460,210 Q480,165 580,80 Q680,165 700,210 L700,340 Z"
fill="#2563eb" opacity="0.15"/>
<path d="M460,340 L460,210 Q480,165 580,80 Q680,165 700,210 L700,340"
stroke="#2563eb" stroke-width="2" fill="none" stroke-dasharray="2,3"/>
<rect x="572" y="80" width="16" height="260" fill="#2563eb"/>
<circle cx="240" cy="270" r="6" fill="#16a34a"/>
<text x="240" y="260" font-size="10" fill="#16a34a" text-anchor="middle" font-weight="700">bleibt</text>
<circle cx="420" cy="240" r="6" fill="#16a34a"/>
<text x="420" y="230" font-size="10" fill="#16a34a" text-anchor="middle" font-weight="700">bleibt</text>
<circle cx="510" cy="180" r="6" fill="#94a3b8"/>
<text x="510" y="170" font-size="10" fill="#94a3b8" text-anchor="middle">raus</text>
<circle cx="660" cy="200" r="6" fill="#94a3b8"/>
<text x="660" y="190" font-size="10" fill="#94a3b8" text-anchor="middle">raus</text>
<circle cx="640" cy="155" r="6" fill="#94a3b8"/>
<text x="640" y="145" font-size="10" fill="#94a3b8" text-anchor="middle">raus</text>
<circle cx="860" cy="220" r="6" fill="#16a34a"/>
<text x="860" y="210" font-size="10" fill="#16a34a" text-anchor="middle" font-weight="700">bleibt</text>
<circle cx="960" cy="170" r="6" fill="#16a34a"/>
<text x="960" y="160" font-size="10" fill="#16a34a" text-anchor="middle" font-weight="700">bleibt</text>
<text x="595" y="76" font-size="11" fill="#2563eb" font-weight="700">1 kHz · 90 dB · "Masker"</text>
<text x="780" y="105" font-size="11" fill="#ea580c" font-weight="700">Hörschwelle (in Ruhe)</text>
<text x="540" y="160" font-size="11" fill="#2563eb" font-weight="700" text-anchor="middle">Maskierungs-Bereich</text>
</svg>
</div>
<div class="verdict">
<div class="verdict-q">MP3 kodiert nur, was über der <strong>kombinierten Schwelle</strong> liegt.</div>
<div class="verdict-a">Alles unterhalb wird weggeworfen — das Ohr hört es ohnehin nicht. So spart MP3 typischerweise <strong>~90 % der Daten</strong>, ohne dass der Mensch im Alltag etwas vermisst.</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

@@ -0,0 +1,222 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Psychovisualität — Luminanz vor Chrominanz</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
--soft: #f8fafc;
--border: #cbd5e1;
--hl: #d63384;
--full: #2563eb;
--reduced: #7c3aed;
--y: #1a1a2e;
--cb: #2563eb;
--cr: #ef4444;
--bar-bg: #e2e8f0;
}
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 30px 40px; }
h1 { text-align: center; margin: 0 0 6px; font-size: 1.75rem; }
.sub { text-align: center; color: var(--muted); margin-bottom: 24px; font-size: 1.05rem; }
.sub strong { color: var(--dark); }
.compare {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 22px;
max-width: 1180px;
margin: 0 auto;
}
.col {
border: 2px solid;
border-radius: 12px;
padding: 16px 20px;
background: #fff;
display: flex;
flex-direction: column;
gap: 12px;
}
.col.full { border-color: var(--full); }
.col.reduced { border-color: var(--reduced); }
.col-head { display: flex; justify-content: space-between; align-items: baseline; }
.col-tag {
font-size: 0.72rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.12em;
color: var(--muted);
}
.col-name { font-size: 1.25rem; font-weight: 700; }
.col.full .col-name { color: var(--full); }
.col.reduced .col-name { color: var(--reduced); }
.col-format {
font-family: ui-monospace, monospace;
font-size: 0.82rem;
color: var(--muted);
}
.preview {
border-radius: 8px;
overflow: hidden;
border: 1px solid var(--border);
}
.preview svg { display: block; }
.channels {
display: flex;
flex-direction: column;
gap: 6px;
}
.channel { display: grid; grid-template-columns: 90px 1fr 60px; gap: 8px; align-items: center; font-size: 0.85rem; }
.channel-label {
font-family: ui-monospace, monospace;
font-weight: 700;
}
.channel-bar { height: 14px; background: var(--bar-bg); border-radius: 3px; overflow: hidden; }
.channel-bar .fill { height: 100%; border-radius: 3px; }
.channel-bar .fill.y { background: var(--y); }
.channel-bar .fill.cb { background: var(--cb); }
.channel-bar .fill.cr { background: var(--cr); }
.channel-pct {
font-family: ui-monospace, monospace;
font-size: 0.78rem;
color: var(--muted);
text-align: right;
}
.summary-line {
display: flex;
justify-content: space-between;
background: var(--soft);
border-radius: 6px;
padding: 6px 12px;
font-family: ui-monospace, monospace;
font-size: 0.85rem;
color: var(--dark);
}
.summary-line strong { color: var(--hl); }
.verdict {
margin-top: 22px;
max-width: 1180px;
margin-left: auto;
margin-right: auto;
text-align: center;
border: 2px solid var(--hl);
border-radius: 12px;
padding: 14px 22px;
}
.verdict-q { font-size: 1.1rem; font-weight: 700; color: var(--hl); }
.verdict-a { font-size: 0.93rem; color: var(--dark); margin-top: 4px; }
.verdict-a strong { color: var(--hl); }
</style>
</head>
<body>
<h1>Psychovisualität — Luminanz vor Chrominanz</h1>
<div class="sub">Das Auge sieht <strong>Helligkeit</strong> scharf. <strong>Farbe</strong> darf grob bleiben — und das Bild sieht trotzdem identisch aus.</div>
<div class="compare">
<div class="col full">
<div class="col-head">
<span class="col-name">Ohne Subsampling</span>
<span class="col-tag">4:4:4</span>
</div>
<div class="col-format">jedes Pixel speichert Y · Cb · Cr in voller Auflösung</div>
<svg class="preview" viewBox="0 0 320 130" preserveAspectRatio="xMidYMid slice">
<defs>
<linearGradient id="full-sky" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#fde68a"/>
<stop offset="55%" stop-color="#fb923c"/>
<stop offset="100%" stop-color="#7c3aed"/>
</linearGradient>
</defs>
<rect x="0" y="0" width="320" height="130" fill="url(#full-sky)"/>
<circle cx="230" cy="50" r="22" fill="#fef3c7"/>
<path d="M0,90 L40,75 L90,87 L140,68 L190,82 L240,66 L290,80 L320,72 L320,130 L0,130 Z" fill="#1e1b4b"/>
<path d="M0,108 L60,100 L120,108 L180,98 L240,106 L300,98 L320,103 L320,130 L0,130 Z" fill="#0f172a" opacity="0.7"/>
</svg>
<div class="channels">
<div class="channel">
<span class="channel-label">Y</span>
<div class="channel-bar"><div class="fill y" style="width:100%"></div></div>
<span class="channel-pct">100 %</span>
</div>
<div class="channel">
<span class="channel-label">Cb</span>
<div class="channel-bar"><div class="fill cb" style="width:100%"></div></div>
<span class="channel-pct">100 %</span>
</div>
<div class="channel">
<span class="channel-label">Cr</span>
<div class="channel-bar"><div class="fill cr" style="width:100%"></div></div>
<span class="channel-pct">100 %</span>
</div>
</div>
<div class="summary-line">
<span>Datenmenge:</span>
<span><strong>100 %</strong></span>
</div>
</div>
<div class="col reduced">
<div class="col-head">
<span class="col-name">JPEG · H.264 Standard</span>
<span class="col-tag">4:2:0</span>
</div>
<div class="col-format">Y voll · Cb &amp; Cr nur in 2×2-Pixel-Blöcken</div>
<svg class="preview" viewBox="0 0 320 130" preserveAspectRatio="xMidYMid slice">
<defs>
<linearGradient id="red-sky" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#fde68a"/>
<stop offset="55%" stop-color="#fb923c"/>
<stop offset="100%" stop-color="#7c3aed"/>
</linearGradient>
</defs>
<rect x="0" y="0" width="320" height="130" fill="url(#red-sky)"/>
<circle cx="230" cy="50" r="22" fill="#fef3c7"/>
<path d="M0,90 L40,75 L90,87 L140,68 L190,82 L240,66 L290,80 L320,72 L320,130 L0,130 Z" fill="#1e1b4b"/>
<path d="M0,108 L60,100 L120,108 L180,98 L240,106 L300,98 L320,103 L320,130 L0,130 Z" fill="#0f172a" opacity="0.7"/>
</svg>
<div class="channels">
<div class="channel">
<span class="channel-label">Y</span>
<div class="channel-bar"><div class="fill y" style="width:100%"></div></div>
<span class="channel-pct">100 %</span>
</div>
<div class="channel">
<span class="channel-label">Cb</span>
<div class="channel-bar"><div class="fill cb" style="width:25%"></div></div>
<span class="channel-pct">25 %</span>
</div>
<div class="channel">
<span class="channel-label">Cr</span>
<div class="channel-bar"><div class="fill cr" style="width:25%"></div></div>
<span class="channel-pct">25 %</span>
</div>
</div>
<div class="summary-line">
<span>Datenmenge:</span>
<span><strong>50 %</strong></span>
</div>
</div>
</div>
<div class="verdict">
<div class="verdict-q">Halbe Datenmenge. Identisches Bild — für dein Auge.</div>
<div class="verdict-a">JPEG, H.264, H.265, WebP — alle reduzieren die Farb-Auflösung auf <strong>ein Viertel</strong>. Das ist Psychovisualität: was wir nicht scharf sehen, muss man nicht scharf speichern.</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

@@ -0,0 +1,212 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Raster vs. Vektor — Pixel oder Anweisung?</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
--soft: #f8fafc;
--border: #cbd5e1;
--hl: #d63384;
--raster: #ea580c;
--vektor: #2563eb;
}
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 30px 40px; }
h1 { text-align: center; margin: 0 0 6px; font-size: 1.75rem; }
.sub { text-align: center; color: var(--muted); margin-bottom: 24px; font-size: 1.05rem; }
.sub strong { color: var(--dark); }
.pair {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 22px;
max-width: 1180px;
margin: 0 auto;
}
.col {
border: 2px solid;
border-radius: 12px;
padding: 16px 18px;
background: #fff;
display: flex;
flex-direction: column;
gap: 10px;
}
.col.raster { border-color: var(--raster); }
.col.vektor { border-color: var(--vektor); }
.col-head { display: flex; justify-content: space-between; align-items: baseline; }
.col-name { font-size: 1.3rem; font-weight: 700; }
.col.raster .col-name { color: var(--raster); }
.col.vektor .col-name { color: var(--vektor); }
.col-tag {
font-size: 0.72rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.12em;
color: var(--muted);
}
.col-desc { font-size: 0.85rem; color: var(--muted); line-height: 1.4; }
.views {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px;
}
.view { display: flex; flex-direction: column; gap: 4px; }
.view-label {
font-size: 0.68rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.1em;
color: var(--muted);
text-align: center;
}
.view-canvas {
background: var(--soft);
border: 1px solid var(--border);
border-radius: 6px;
aspect-ratio: 1.4;
overflow: hidden;
}
.view-canvas svg { display: block; width: 100%; height: 100%; }
.stats {
background: var(--soft);
border-radius: 6px;
padding: 8px 12px;
font-family: ui-monospace, monospace;
font-size: 0.82rem;
color: var(--dark);
line-height: 1.5;
}
.stats .key { color: var(--muted); }
.stats .val { font-weight: 700; }
.verdict {
margin-top: 22px;
max-width: 1180px;
margin-left: auto;
margin-right: auto;
text-align: center;
border: 2px solid var(--hl);
border-radius: 12px;
padding: 14px 22px;
}
.verdict-q { font-size: 1.1rem; font-weight: 700; color: var(--hl); }
.verdict-a { font-size: 0.93rem; color: var(--dark); margin-top: 4px; }
.verdict-a strong { color: var(--hl); }
</style>
</head>
<body>
<h1>Raster vs. Vektor — Pixel oder Anweisung?</h1>
<div class="sub">Beide zeigen ein Häkchen. Wenn man <strong>reinzoomt</strong>, kommt die Wahrheit raus.</div>
<div class="pair">
<div class="col raster">
<div class="col-head">
<span class="col-name">Raster</span>
<span class="col-tag">PNG · JPEG · GIF</span>
</div>
<div class="col-desc">Ein Gitter aus Pixel-Farbwerten. Jede Position ist festgelegt.</div>
<div class="views">
<div class="view">
<div class="view-label">Original (32 × 22 px)</div>
<div class="view-canvas">
<svg viewBox="0 0 320 220" preserveAspectRatio="xMidYMid meet">
<rect x="0" y="0" width="320" height="220" fill="#f8fafc"/>
<g shape-rendering="crispEdges">
<rect x="20" y="120" width="20" height="20" fill="#ea580c"/>
<rect x="40" y="140" width="20" height="20" fill="#ea580c"/>
<rect x="60" y="160" width="20" height="20" fill="#ea580c"/>
<rect x="80" y="180" width="20" height="20" fill="#ea580c"/>
<rect x="100" y="160" width="20" height="20" fill="#ea580c"/>
<rect x="120" y="140" width="20" height="20" fill="#ea580c"/>
<rect x="140" y="120" width="20" height="20" fill="#ea580c"/>
<rect x="160" y="100" width="20" height="20" fill="#ea580c"/>
<rect x="180" y="80" width="20" height="20" fill="#ea580c"/>
<rect x="200" y="60" width="20" height="20" fill="#ea580c"/>
<rect x="220" y="40" width="20" height="20" fill="#ea580c"/>
<rect x="240" y="20" width="20" height="20" fill="#ea580c"/>
</g>
</svg>
</div>
</div>
<div class="view">
<div class="view-label">4× Zoom</div>
<div class="view-canvas">
<svg viewBox="80 60 160 160" preserveAspectRatio="xMidYMid meet">
<rect x="0" y="0" width="320" height="220" fill="#f8fafc"/>
<g shape-rendering="crispEdges">
<rect x="20" y="120" width="20" height="20" fill="#ea580c"/>
<rect x="40" y="140" width="20" height="20" fill="#ea580c"/>
<rect x="60" y="160" width="20" height="20" fill="#ea580c"/>
<rect x="80" y="180" width="20" height="20" fill="#ea580c"/>
<rect x="100" y="160" width="20" height="20" fill="#ea580c"/>
<rect x="120" y="140" width="20" height="20" fill="#ea580c"/>
<rect x="140" y="120" width="20" height="20" fill="#ea580c"/>
<rect x="160" y="100" width="20" height="20" fill="#ea580c"/>
<rect x="180" y="80" width="20" height="20" fill="#ea580c"/>
<rect x="200" y="60" width="20" height="20" fill="#ea580c"/>
<rect x="220" y="40" width="20" height="20" fill="#ea580c"/>
<rect x="240" y="20" width="20" height="20" fill="#ea580c"/>
</g>
</svg>
</div>
</div>
</div>
<div class="stats">
<div><span class="key">Speicher:</span> <span class="val">32 × 22 × 3 Byte = 2 112 Byte</span></div>
<div><span class="key">Beim Zoom:</span> <span class="val">pixelig — Information ist erschöpft</span></div>
</div>
</div>
<div class="col vektor">
<div class="col-head">
<span class="col-name">Vektor</span>
<span class="col-tag">SVG · PDF · Schriftarten</span>
</div>
<div class="col-desc">Mathematische Anweisungen: <code style="background:#0f0f23;color:#5fb3e4;padding:0 4px;border-radius:3px;">polyline 30,110 → 90,170 → 250,30</code></div>
<div class="views">
<div class="view">
<div class="view-label">Original</div>
<div class="view-canvas">
<svg viewBox="0 0 320 220" preserveAspectRatio="xMidYMid meet">
<rect x="0" y="0" width="320" height="220" fill="#f8fafc"/>
<polyline points="30,130 90,190 270,30" stroke="#2563eb" stroke-width="14" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</div>
</div>
<div class="view">
<div class="view-label">4× Zoom</div>
<div class="view-canvas">
<svg viewBox="80 60 160 160" preserveAspectRatio="xMidYMid meet">
<rect x="0" y="0" width="320" height="220" fill="#f8fafc"/>
<polyline points="30,130 90,190 270,30" stroke="#2563eb" stroke-width="14" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</div>
</div>
</div>
<div class="stats">
<div><span class="key">Speicher:</span> <span class="val">3 Punkte + Strichbreite = ~80 Byte</span></div>
<div><span class="key">Beim Zoom:</span> <span class="val">scharf — wird neu berechnet</span></div>
</div>
</div>
</div>
<div class="verdict">
<div class="verdict-q">Pixel sind festgenagelt. Vektoren werden bei jedem Zoom <strong>neu berechnet</strong>.</div>
<div class="verdict-a">Faustregel: <strong>Foto → Raster</strong> (kann nicht „neu berechnet" werden). <strong>Logo, Icon, Schrift → Vektor</strong> (skalierbar ohne Verlust).</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

@@ -0,0 +1,189 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Was wir über Kompression gelernt haben</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
--soft: #f8fafc;
--border: #cbd5e1;
--hl: #d63384;
--lossless: #16a34a;
--lossy: #ef4444;
}
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 30px 40px; }
h1 { text-align: center; margin: 0 0 6px; font-size: 1.75rem; }
.sub { text-align: center; color: var(--muted); margin-bottom: 26px; font-size: 1.05rem; }
.sub strong { color: var(--dark); }
.compare {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 22px;
max-width: 1180px;
margin: 0 auto;
}
.col {
border: 2px solid;
border-radius: 12px;
padding: 18px 22px;
background: #fff;
display: flex;
flex-direction: column;
gap: 12px;
}
.col.lossless { border-color: var(--lossless); }
.col.lossy { border-color: var(--lossy); }
.col-head { display: flex; justify-content: space-between; align-items: baseline; }
.col-name { font-size: 1.4rem; font-weight: 700; }
.col.lossless .col-name { color: var(--lossless); }
.col.lossy .col-name { color: var(--lossy); }
.col-tag {
font-size: 0.72rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.12em;
color: var(--muted);
}
.row { display: grid; grid-template-columns: 120px 1fr; gap: 10px 14px; }
.row-key {
font-size: 0.72rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--muted);
padding-top: 3px;
}
.row-val { font-size: 0.92rem; line-height: 1.5; color: var(--dark); }
.row-val strong {
font-family: ui-monospace, monospace;
background: var(--soft);
padding: 1px 6px;
border-radius: 4px;
}
.matrix {
margin-top: 22px;
max-width: 1180px;
margin-left: auto;
margin-right: auto;
background: var(--soft);
border: 1.5px solid var(--border);
border-radius: 10px;
padding: 14px 22px;
}
.matrix-head {
font-size: 0.78rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.1em;
color: var(--muted);
margin-bottom: 8px;
}
.matrix-grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
gap: 8px 16px;
font-size: 0.88rem;
}
.matrix-grid .scenario { font-weight: 700; color: var(--dark); }
.matrix-grid .answer {
font-family: ui-monospace, monospace;
color: var(--dark);
}
.matrix-grid .answer.lossless { color: var(--lossless); font-weight: 700; }
.matrix-grid .answer.lossy { color: var(--lossy); font-weight: 700; }
.verdict {
margin-top: 18px;
max-width: 1180px;
margin-left: auto;
margin-right: auto;
text-align: center;
border: 2px solid var(--hl);
border-radius: 12px;
padding: 14px 22px;
}
.verdict-q { font-size: 1.1rem; font-weight: 700; color: var(--hl); }
.verdict-a { font-size: 0.93rem; color: var(--dark); margin-top: 4px; }
.verdict-a strong { color: var(--hl); }
</style>
</head>
<body>
<h1>Was wir über Kompression gelernt haben</h1>
<div class="sub">Zwei fundamental verschiedene Wege, dasselbe Ziel: <strong>Daten kleiner machen.</strong></div>
<div class="compare">
<div class="col lossless">
<div class="col-head">
<span class="col-name">Verlustfrei</span>
<span class="col-tag">Lossless</span>
</div>
<div class="row">
<div class="row-key">Was passiert</div>
<div class="row-val">Redundanz raus — Wiederholungen kürzer schreiben</div>
<div class="row-key">Umkehrbar</div>
<div class="row-val">Ja. Aus der komprimierten Datei wird das <strong>exakte</strong> Original wieder.</div>
<div class="row-key">Verfahren</div>
<div class="row-val">RLE, Huffman, Deflate, LZ77/LZ78</div>
<div class="row-key">Formate</div>
<div class="row-val">ZIP · PNG · FLAC · TIFF · RAW</div>
<div class="row-key">Faktor</div>
<div class="row-val">2× – 5× (typisch)</div>
</div>
</div>
<div class="col lossy">
<div class="col-head">
<span class="col-name">Verlustbehaftet</span>
<span class="col-tag">Lossy</span>
</div>
<div class="row">
<div class="row-key">Was passiert</div>
<div class="row-val">Irrelevanz raus — was Mensch nicht wahrnimmt, wird weggeworfen</div>
<div class="row-key">Umkehrbar</div>
<div class="row-val">Nein. Einmal weg, für immer weg.</div>
<div class="row-key">Trick</div>
<div class="row-val">Psychoakustik (MP3) · Psychovisualität (JPEG)</div>
<div class="row-key">Formate</div>
<div class="row-val">MP3 · AAC · JPEG · WebP · H.264 · H.265</div>
<div class="row-key">Faktor</div>
<div class="row-val">10× – 100× (typisch)</div>
</div>
</div>
</div>
<div class="matrix">
<div class="matrix-head">Entscheidungsmatrix — wann nehme ich welches?</div>
<div class="matrix-grid">
<div class="scenario">Foto-Archiv (RAW)</div>
<div class="answer lossless">Lossless</div>
<div class="scenario">Spotify-Stream</div>
<div class="answer lossy">Lossy</div>
<div class="scenario">Code-Repository</div>
<div class="answer lossless">Lossless (ZIP)</div>
<div class="scenario">Instagram-Foto</div>
<div class="answer lossy">Lossy (JPEG)</div>
<div class="scenario">Studio-Master-Track</div>
<div class="answer lossless">Lossless (FLAC)</div>
<div class="scenario">YouTube-Video</div>
<div class="answer lossy">Lossy (H.264)</div>
</div>
</div>
<div class="verdict">
<div class="verdict-q">Lossless für Archiv und Code. Lossy für Streaming und Anzeige.</div>
<div class="verdict-a">Faustregel: <strong>Werkzeug</strong> (du arbeitest noch dran) → Lossless. <strong>Konsum</strong> (du schaust/hörst nur) → Lossy.</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

@@ -0,0 +1,188 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Was wir in 90 Minuten gelernt haben</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
--soft: #f8fafc;
--border: #cbd5e1;
--hl: #d63384;
--left: #d63384;
--right: #0891b2;
--bytes: #0891b2;
}
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 30px 40px; }
h1 { text-align: center; margin: 0 0 6px; font-size: 1.75rem; }
.sub { text-align: center; color: var(--muted); margin-bottom: 28px; font-size: 1.05rem; }
.sub strong { color: var(--dark); }
.recap {
display: grid;
grid-template-columns: 160px 1fr 200px 1fr 160px;
gap: 10px;
max-width: 1200px;
margin: 0 auto;
align-items: center;
}
.station {
border: 2px solid var(--border);
border-radius: 10px;
padding: 18px 12px;
background: #fff;
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
gap: 6px;
}
.station.bytes { border-color: var(--bytes); background: #0f0f23; color: #fff; }
.station-tag {
font-size: 0.7rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.12em;
color: var(--muted);
}
.station.bytes .station-tag { color: #94a3b8; }
.station-name { font-size: 1.3rem; font-weight: 700; }
.station.bytes .station-name { color: #67e8f9; }
.station-detail { font-size: 0.78rem; color: var(--muted); line-height: 1.35; }
.station.bytes .station-detail { color: #94a3b8; font-family: ui-monospace, monospace; font-size: 0.76rem; line-height: 1.35; }
.strang {
display: flex;
flex-direction: column;
gap: 6px;
padding: 0 6px;
}
.strang-arrow { text-align: center; }
.strang-arrow svg { width: 100%; height: 18px; }
.strang-title {
font-size: 0.92rem;
font-weight: 700;
text-align: center;
line-height: 1.3;
}
.strang.left .strang-title { color: var(--left); }
.strang.right .strang-title { color: var(--right); }
.strang-list {
display: flex;
flex-direction: column;
gap: 3px;
list-style: none;
margin: 0;
padding: 0;
background: var(--soft);
border: 1px solid var(--border);
border-radius: 8px;
padding: 8px 12px;
}
.strang-list li {
font-size: 0.82rem;
color: var(--dark);
padding-left: 12px;
position: relative;
line-height: 1.4;
}
.strang-list li::before {
content: "·";
position: absolute;
left: 0;
top: 0;
font-weight: 700;
}
.strang.left .strang-list li::before { color: var(--left); }
.strang.right .strang-list li::before { color: var(--right); }
.verdict {
margin-top: 22px;
max-width: 1200px;
margin-left: auto;
margin-right: auto;
text-align: center;
border: 2px solid var(--hl);
border-radius: 12px;
padding: 14px 22px;
}
.verdict-q { font-size: 1.1rem; font-weight: 700; color: var(--hl); }
.verdict-a { font-size: 0.95rem; color: var(--dark); margin-top: 4px; }
.verdict-a strong { color: var(--hl); }
</style>
</head>
<body>
<h1>Was wir in 90 Minuten gelernt haben</h1>
<div class="sub">Beide Wege gehen durch <strong>dieselbe Mitte</strong>. Du kennst jetzt alle Stationen.</div>
<div class="recap">
<div class="station">
<div class="station-tag">Quelle</div>
<div class="station-name">Welt</div>
<div class="station-detail">Schallwelle<br>Lichtwelle<br>kontinuierlich · analog</div>
</div>
<div class="strang left">
<div class="strang-arrow">
<svg viewBox="0 0 200 18" preserveAspectRatio="none">
<line x1="6" y1="9" x2="180" y2="9" stroke="#d63384" stroke-width="2"/>
<path d="M174,3 L188,9 L174,15" stroke="#d63384" stroke-width="2" fill="none"/>
</svg>
</div>
<div class="strang-title">Welt → Byte</div>
<ul class="strang-list">
<li>Sampling-Rate</li>
<li>Bittiefe · Quantisierung</li>
<li>Datenrate-Formel</li>
<li>Nyquist · 2·f<sub>max</sub></li>
<li>Aliasing &amp; Moiré</li>
<li>44,1 kHz = 2·20 kHz + Marge</li>
</ul>
</div>
<div class="station bytes">
<div class="station-tag">Mitte</div>
<div class="station-name">Datei</div>
<div class="station-detail">
Byte-Strom<br>
89 50 4E 47<br>
nichts als Zahlen
</div>
</div>
<div class="strang right">
<div class="strang-arrow">
<svg viewBox="0 0 200 18" preserveAspectRatio="none">
<line x1="6" y1="9" x2="180" y2="9" stroke="#0891b2" stroke-width="2"/>
<path d="M174,3 L188,9 L174,15" stroke="#0891b2" stroke-width="2" fill="none"/>
</svg>
</div>
<div class="strang-title">Byte → Bedeutung</div>
<ul class="strang-list">
<li>Bit · Byte · Hex</li>
<li>8 Bit = 256 Zustände</li>
<li>ASCII · UTF-8</li>
<li>Magic Number</li>
<li>KB vs KiB</li>
<li>Hex im Alltag (CSS, MAC)</li>
</ul>
</div>
<div class="station">
<div class="station-tag">Ziel</div>
<div class="station-name">Mensch</div>
<div class="station-detail">Text · Bild · Klang<br>Bedeutung<br>verstehen</div>
</div>
</div>
<div class="verdict">
<div class="verdict-q">Eine Datei ist kein Mysterium. Es ist eine <strong>Reihe von Zahlen</strong> mit zwei Geschichten dran.</div>
<div class="verdict-a">Eine Geschichte erzählt, <strong>woher</strong> die Zahlen kommen. Die andere, <strong>was</strong> sie bedeuten. Beide kennst du jetzt.</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

@@ -0,0 +1,217 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>USB-C — drei Achsen, eine Verwirrung</title>
<style>
:root {
--dark: #1a1a2e;
--muted: #6b7280;
--soft: #f8fafc;
--border: #cbd5e1;
--hl: #d63384;
--stecker: #2563eb;
--kabel: #ea580c;
--protokoll: #7c3aed;
}
html, body { margin: 0; padding: 0; background: #fff; font-family: system-ui, -apple-system, sans-serif; color: var(--dark); }
body { padding: 28px 40px; }
h1 { text-align: center; margin: 0 0 6px; font-size: 1.75rem; }
.sub { text-align: center; color: var(--muted); margin-bottom: 22px; font-size: 1.05rem; }
.sub strong { color: var(--dark); }
.axes {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 18px;
max-width: 1200px;
margin: 0 auto;
}
.axis {
border: 2px solid;
border-radius: 12px;
padding: 14px 16px;
background: #fff;
display: flex;
flex-direction: column;
gap: 10px;
}
.axis.stecker { border-color: var(--stecker); }
.axis.kabel { border-color: var(--kabel); }
.axis.protokoll { border-color: var(--protokoll); }
.axis-head { display: flex; justify-content: space-between; align-items: baseline; }
.axis-num {
font-family: ui-monospace, monospace;
font-size: 0.72rem;
font-weight: 700;
color: var(--muted);
}
.axis-name { font-size: 1.15rem; font-weight: 700; }
.axis.stecker .axis-name { color: var(--stecker); }
.axis.kabel .axis-name { color: var(--kabel); }
.axis.protokoll .axis-name { color: var(--protokoll); }
.axis-tagline {
font-size: 0.82rem;
color: var(--muted);
line-height: 1.4;
}
.axis-tagline strong { color: var(--dark); }
.icon {
background: var(--soft);
border-radius: 6px;
height: 60px;
display: flex;
align-items: center;
justify-content: center;
}
.icon svg { display: block; }
.options {
font-size: 0.82rem;
line-height: 1.6;
color: var(--dark);
background: var(--soft);
border-radius: 6px;
padding: 10px 14px;
}
.options strong {
font-family: ui-monospace, monospace;
font-size: 0.78rem;
padding: 1px 5px;
border-radius: 3px;
background: #fff;
border: 1px solid var(--border);
}
.axis.stecker .options strong { color: var(--stecker); }
.axis.kabel .options strong { color: var(--kabel); }
.axis.protokoll .options strong { color: var(--protokoll); }
.scenario {
margin-top: 22px;
max-width: 1200px;
margin-left: auto;
margin-right: auto;
background: var(--soft);
border: 1.5px solid var(--border);
border-radius: 10px;
padding: 14px 22px;
}
.scenario-head {
font-size: 0.74rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.1em;
color: var(--muted);
margin-bottom: 6px;
}
.scenario-body {
font-size: 0.92rem;
line-height: 1.5;
}
.scenario-body code {
font-family: ui-monospace, monospace;
background: #fff;
padding: 1px 6px;
border-radius: 4px;
border: 1px solid var(--border);
}
.verdict {
margin-top: 16px;
max-width: 1200px;
margin-left: auto;
margin-right: auto;
text-align: center;
border: 2px solid var(--hl);
border-radius: 12px;
padding: 14px 22px;
}
.verdict-q { font-size: 1.05rem; font-weight: 700; color: var(--hl); }
.verdict-a { font-size: 0.92rem; color: var(--dark); margin-top: 4px; }
.verdict-a strong { color: var(--hl); }
</style>
</head>
<body>
<h1>USB-C — drei Achsen, eine Verwirrung</h1>
<div class="sub">Derselbe Stecker. <strong>Aber Kabel ≠ Kabel.</strong> <strong>Protokoll ≠ Protokoll.</strong></div>
<div class="axes">
<div class="axis stecker">
<div class="axis-head">
<span class="axis-name">Stecker</span>
<span class="axis-num">1 · MECHANIK</span>
</div>
<div class="axis-tagline">Die <strong>Form</strong>. Was reinsteckt, oval, beidseitig.</div>
<div class="icon">
<svg viewBox="0 0 120 30" width="140" height="40">
<rect x="6" y="9" width="108" height="12" rx="6" fill="#2563eb" opacity="0.18" stroke="#2563eb" stroke-width="2"/>
<rect x="22" y="13" width="76" height="4" rx="2" fill="#2563eb"/>
</svg>
</div>
<div class="options">
Nur eine Sorte: <strong>USB-C</strong> (auch USB Type-C). 24 Pins. Beidseitig steckbar. Andere Stecker-Typen: USB-A, USB-B, Micro-USB — nicht mit C kompatibel.
</div>
</div>
<div class="axis kabel">
<div class="axis-head">
<span class="axis-name">Kabel</span>
<span class="axis-num">2 · WAS DURCH-PASST</span>
</div>
<div class="axis-tagline">Die <strong>Adern</strong>. Was elektrisch transportiert werden kann.</div>
<div class="icon">
<svg viewBox="0 0 160 30" width="180" height="40">
<path d="M10,15 L150,15" stroke="#ea580c" stroke-width="3"/>
<rect x="2" y="8" width="14" height="14" rx="3" fill="#ea580c" opacity="0.4" stroke="#ea580c"/>
<rect x="144" y="8" width="14" height="14" rx="3" fill="#ea580c" opacity="0.4" stroke="#ea580c"/>
</svg>
</div>
<div class="options">
<strong>Charge-only</strong> · billig, nur Strom · 5 W<br>
<strong>USB 2.0</strong> · 480 Mbit/s · 60 W (3 A)<br>
<strong>USB 3.2 Gen 2</strong> · 10 Gbit/s · 100 W<br>
<strong>Thunderbolt 4</strong> · 40 Gbit/s · 240 W
</div>
</div>
<div class="axis protokoll">
<div class="axis-head">
<span class="axis-name">Protokoll</span>
<span class="axis-num">3 · WAS LÄUFT</span>
</div>
<div class="axis-tagline">Die <strong>Sprache</strong>. Was die zwei Geräte miteinander reden.</div>
<div class="icon">
<svg viewBox="0 0 160 30" width="180" height="40">
<circle cx="20" cy="15" r="6" fill="#7c3aed"/>
<path d="M30,15 L130,15" stroke="#7c3aed" stroke-width="2" stroke-dasharray="6,4"/>
<circle cx="140" cy="15" r="6" fill="#7c3aed"/>
</svg>
</div>
<div class="options">
<strong>USB-PD</strong> · Power Delivery (Laden)<br>
<strong>USB 2/3/4</strong> · Datenübertragung<br>
<strong>Thunderbolt 3/4</strong> · Daten + Display<br>
<strong>DisplayPort Alt</strong> · Monitor anschließen<br>
<strong>HDMI Alt</strong> · weiter HDMI rausführen
</div>
</div>
</div>
<div class="scenario">
<div class="scenario-head">Konkret: warum lädt der Laptop nicht?</div>
<div class="scenario-body">
USB-C-Port am Laptop ist da (<strong>Stecker</strong> stimmt). Aber der Aldi-Kabel ist <code>Charge-only</code> mit <code>5 W</code> (<strong>Kabel</strong> kann nicht genug Strom liefern). Oder der Port am Laptop unterstützt nur <code>USB-PD</code> mit 100 W, das Netzteil meldet aber nur 65 W (<strong>Protokoll</strong>-Handshake scheitert). <em>Eine der drei Achsen passt nicht.</em>
</div>
</div>
<div class="verdict">
<div class="verdict-q">Drei Achsen. Drei unabhängige Fragen. Drei Gründe, warum's nicht funktioniert.</div>
<div class="verdict-a">Beim nächsten „USB-C-Kabel funktioniert nicht": <strong>Stecker passt → Kabel-Spec checken → Protokoll-Support prüfen.</strong> In dieser Reihenfolge.</div>
</div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 KiB

+76 -67
View File
@@ -91,6 +91,9 @@ section.erklaerung p {
section.erklaerung table { section.erklaerung table {
font-size: 0.9rem; font-size: 0.9rem;
} }
section.dimmed {
opacity: 0.2;
}
</style> </style>
<!-- _class: invert --> <!-- _class: invert -->
@@ -197,26 +200,14 @@ SPEAKER NOTES:
Das Web folgt dem **Client-Server-Modell**: Ein Client (Browser) sendet einen **Request**, ein Server liefert eine **Response** – nach den Regeln eines **Protokolls**. Das Web folgt dem **Client-Server-Modell**: Ein Client (Browser) sendet einen **Request**, ein Server liefert eine **Response** – nach den Regeln eines **Protokolls**.
| Begriff | Was ist das? | Analogie | | Begriff | Was ist das? |
|---------|--------------|----------| |---------------|--------------------------------------------------------------------------|
| **Host** | Ein Rechner im Netz | Ein Haus mit Adresse | | **Host** | Ein netzwerkfähiger Rechner (Laptop, Smartphone, Display in S-Bahn etc.) |
| **Client** | Der, der fragt (Browser) | Gast im Restaurant | | **Client** | Host bzw. Anwendung mit einer Anfrage (bspw. Browser) |
| **Server** | Der, der antwortet | Küche im Restaurant | | **Server** | Host bzw. Anwendung mit der Antwort (bspw. Webserver) |
| **Request** | Die Anfrage | Bestellung | | **Request** | Die Anfrage des Clients |
| **Response** | Die Antwort | Das Essen | | **Response** | Die Antwort des Servers |
| **Protokoll** | Regeln für Kommunikation (z. B. TCP, HTTP) | Speisekarte + Bestellablauf | | **Protokoll** | Regeln für Kommunikation (z. B. TCP, HTTP) |
<!--
SPEAKER NOTES:
- 6 Grundbegriffe – tauchen überall auf
- Client/Server = Grundstruktur des Webs
- Browser = Client
- Google/HdM/Netflix = Server
- Request/Response = Kommunikationsmuster
- Protokoll = Regelwerk
- Analogie: Restaurant in Japan ohne Regeln zu kennen
- Host = Rechner mit Adresse im Netz
-->
--- ---
@@ -253,13 +244,15 @@ SPEAKER NOTES:
Daten werden Schicht für Schicht verpackt — jede Schicht fügt einen eigenen **Header** hinzu und erzeugt so eine neue Dateneinheit. Daten werden Schicht für Schicht verpackt — jede Schicht fügt einen eigenen **Header** hinzu und erzeugt so eine neue Dateneinheit.
| Begriff | Was ist das? | Schicht | | Begriff | Was ist das? | Schicht |
|---------|--------------|---------| |-------------|-------------------------------------------------------|--------------------------|
| **Paket** | Daten + IP-Header | Internet (Layer 3) | | **Payload** | Die eigentlichen Nutzdaten (bspw. Request, Response) | Anwendung |
| **Segment** | Daten + TCP-Header | Transport (Layer 4) | | **Header** | Metadaten vor und nach dem Payload | Jedes Layer |
| **Frame** | Daten + MAC-Header | Netzzugang (Layer 2) | | **Segment** | Payload + TCP-Header (Anwendungsport) | Transport (Layer 4) |
| **Header** | Metadaten am Anfang | Jede Schicht | | **Paket** | Payload + IP-Header (WLAN-Router) | Internet (Layer 3) |
| **Payload** | Die eigentlichen Nutzdaten | Der Inhalt | | **Frame** | Payload + MAC-Header (Netzwerkkarte) | Netzzugang (Layer 2) |
| **Bit** | Abfolge von Signalen (Licht, Strom, Kabel, Mobilfunk) | Bitübertragung (Layer 1) |
<!-- <!--
SPEAKER NOTES: SPEAKER NOTES:
@@ -268,7 +261,6 @@ SPEAKER NOTES:
- Header = Metadaten (wer, wohin, wie groß) - Header = Metadaten (wer, wohin, wie groß)
- Paket/Segment/Frame = gleiche Daten, verschiedene Verpackung - Paket/Segment/Frame = gleiche Daten, verschiedene Verpackung
- Wie Matroschka: Schicht packt Schicht ein - Wie Matroschka: Schicht packt Schicht ein
- Wird klarer beim Schichtenmodell gleich
--> -->
--- ---
@@ -279,13 +271,13 @@ SPEAKER NOTES:
**Latenz** und **Bandbreite** bestimmen, wie schnell Daten ankommen — Latenz misst die Verzögerung, Bandbreite die Kapazität. **Latenz** und **Bandbreite** bestimmen, wie schnell Daten ankommen — Latenz misst die Verzögerung, Bandbreite die Kapazität.
| Begriff | Was ist das? | Einheit | | Begriff | Was ist das? | Einheit |
|---------|--------------|---------| |----------------|-------------------------------------------------|--------------------|
| **Latenz** | Verzögerung (hin + zurück) | Millisekunden | | **Latenz** | Verzögerung (hin + zurück) | Millisekunden (ms) |
| **Bandbreite** | Datenmenge pro Zeiteinheit | Mbit/s | | **Bandbreite** | Datenmenge pro Zeiteinheit | Mbit/s |
| **Hop** | Ein Sprung zum nächsten Router | – | | **Hop** | Ein Sprung zum nächsten Router (im Internet) | – |
| **Round-Trip** | Hin- und Rückweg | – | | **Round-Trip** | Hin- und Rückweg | – |
| **Ping** | "Bist du da?" + Antwort | ms | | **Ping** | Client sendet "ping", bekommt von Server "pong" | ms |
<!-- <!--
SPEAKER NOTES: SPEAKER NOTES:
@@ -309,14 +301,17 @@ SPEAKER NOTES:
Protokolle regeln die Kommunikation auf jeder Schicht — von der Anwendung (HTTP) über den Transport (TCP/UDP) bis zum Routing (IP). Protokolle regeln die Kommunikation auf jeder Schicht — von der Anwendung (HTTP) über den Transport (TCP/UDP) bis zum Routing (IP).
| Protokoll | Wofür? | Port | Schicht | | Protokoll | Wofür? | Port | Schicht |
|-----------|--------|------|---------| |-----------|--------------------------------|------|---------------------|
| **HTTP** | Webseiten übertragen | 80 | Anwendung | | **HTTP** | Webseiten + Inhalte übertragen | 80 | Anwendung (Layer 4) |
| **HTTPS** | HTTP + Verschlüsselung | 443 | Anwendung | | **HTTPS** | HTTP + Verschlüsselung | 443 | Anwendung (Layer 4) |
| **TCP** | Zuverlässige Übertragung | – | Transport | | **DNS** | Namen → IP-Adressen | 53 | Anwendung (Layer 4) |
| **UDP** | Schnelle Übertragung | – | Transport | | **TCP** | Zuverlässige Übertragung | – | Transport (Layer 4) |
| **IP** | Routing durchs Internet | – | Internet | | **UDP** | Schnelle Übertragung | – | Transport (Layer 4) |
| **DNS** | Namen → IP-Adressen | 53 | Anwendung | | **IP** | Routing durchs Internet | – | Internet (Layer 3) |
<i><small>HTTP(S) = Hypertext Transfer Protocol (Secure)</small> · <small>DNS = Domain Name System</small> · <small>TCP = Transmission Control Protocol</small> · <small>UDP = User Datagram Protocol</small> · <small>IP = Internet Protocol</small>
</i>
<!-- <!--
SPEAKER NOTES: SPEAKER NOTES:
@@ -402,12 +397,12 @@ SPEAKER NOTES:
# Das TCP/IP-Modell # Das TCP/IP-Modell
| Schicht | Name | Aufgabe | Protokolle | | Schicht | Name | Aufgabe | Protokolle |
|---------|------|---------|------------| |---------|------|------------------------------------------|-------------------|
| **4** | Anwendung | Was? Welcher Dienst? | HTTP, DNS, SMTP | | **4** | Anwendung | Dienste steuern, Daten austauschen etc. | HTTP, DNS, SMTP |
| **3** | Transport | Zuverlässigkeit, Ports | TCP, UDP | | **3** | Transport | Zuverlässige Verbindung aufbauen (Ports) | TCP, UDP |
| **2** | Internet | Routing, globale Adressen | IP | | **2** | Internet | Routing, global eindeutige Adressen | IP |
| **1** | Netzzugang | Lokale Übertragung | Ethernet, WLAN | | **1** | Netzzugang | Lokale Übertragung | Ethernet, WLAN |
Jede Schicht hat genau eine Aufgabe und nutzt nur die Schicht direkt darunter. Jede Schicht hat genau eine Aufgabe und nutzt nur die Schicht direkt darunter.
@@ -419,12 +414,11 @@ SPEAKER NOTES:
- Transport: Kommt an? Welches Programm? (TCP, UDP) - Transport: Kommt an? Welches Programm? (TCP, UDP)
- Internet: Wie zum Zielrechner? (IP) - Internet: Wie zum Zielrechner? (IP)
- Netzzugang: Wie zum nächsten Gerät? (Ethernet, WLAN) - Netzzugang: Wie zum nächsten Gerät? (Ethernet, WLAN)
- KLAUSUR: Welches Protokoll → welche Schicht
--> -->
--- ---
<!-- _class: erklaerung --> <!-- _class: "erklaerung dimmed" -->
<!-- _header: '' --> <!-- _header: '' -->
<!-- _footer: '' --> <!-- _footer: '' -->
@@ -1009,7 +1003,7 @@ SPEAKER NOTES:
# Was Ihr Browser sendet # Was Ihr Browser sendet
```http ```http
GET / HTTP/1.1 GET / HTTP/2.0
Host: www.hdm-stuttgart.de Host: www.hdm-stuttgart.de
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Accept: text/html Accept: text/html
@@ -1109,6 +1103,9 @@ SPEAKER NOTES:
--- ---
<!-- _class: dimmed -->
# Woher kennt Ihr Laptop die Router-MAC? # Woher kennt Ihr Laptop die Router-MAC?
**ARP** – Address Resolution Protocol **ARP** – Address Resolution Protocol
@@ -1441,6 +1438,8 @@ SPEAKER NOTES:
--- ---
<!-- _class: dimmed -->
# MTU & Fragmentierung # MTU & Fragmentierung
**MTU** = Maximum Transmission Unit **MTU** = Maximum Transmission Unit
@@ -1465,21 +1464,24 @@ SPEAKER NOTES:
--- ---
<!-- _class: klausur -->
<!-- _header: '' -->
<!-- _footer: '' -->
# HTTP-Methoden # HTTP-Methoden
HTTP-Methoden beschreiben, **was** der Client mit einer Ressource tun will. HTTP-Methoden beschreiben, **was** der Client mit einer Ressource tun will.
| Methode | Bedeutung | Beispiel | | Methode | Bedeutung | Beispiel |
|---------|-----------|----------| |---------|-----------|-----------------------------------------------|
| **GET** | Daten abrufen | Seite laden | | **GET** | Daten abrufen | Seite laden `GET /index.html HTTP/2.0` |
| **POST** | Daten senden | Formular absenden | | **POST** | Daten senden | Formular absenden `POST /login HTTP/2.0` |
| **PUT** | Daten ersetzen | Profil aktualisieren | | **PUT** | Daten ersetzen | Profil aktualisieren `PUT /users/42 HTTP/2.0` |
| **DELETE** | Daten löschen | Account löschen | | **DELETE** | Daten löschen | Account löschen `DELETE /users/42 HTTP/2.0` |
<small>CRUD = Create, Read, Update, Delete</small>
```http
GET /index.html HTTP/1.1
POST /login HTTP/1.1
```
<!-- <!--
SPEAKER NOTES: SPEAKER NOTES:
@@ -1528,14 +1530,18 @@ POST /users → Neuen Benutzer erstellen
--- ---
<!-- _class: klausur -->
<!-- _header: '' -->
<!-- _footer: '' -->
# HTTP Status-Codes # HTTP Status-Codes
Jede HTTP-Response enthält einen dreistelligen Status-Code — die erste Ziffer verrät die Kategorie. Jede HTTP-Response enthält einen dreistelligen Status-Code — die erste Ziffer verrät die Kategorie.
```http ```http
HTTP/1.1 200 OK HTTP/2.0 200 OK
HTTP/1.1 404 Not Found HTTP/2.0 404 Not Found
HTTP/1.1 500 Internal Server Error HTTP/2.0 500 Internal Server Error
``` ```
| Code-Bereich | Bedeutung | | Code-Bereich | Bedeutung |
@@ -1586,6 +1592,9 @@ Die erste Ziffer kategorisiert die Antwort:
--- ---
<!-- _class: dimmed -->
# Zusammenfassung Teil 1 # Zusammenfassung Teil 1
**Der Ablauf:** **Der Ablauf:**
@@ -1632,11 +1641,11 @@ Die vier Kernkonzepte für Web-Entwickelnde:
- Caching auf jeder Ebene (TTL = Time To Live) - Caching auf jeder Ebene (TTL = Time To Live)
**2. TCP-Verbindungsaufbau:** **2. TCP-Verbindungsaufbau:**
- 3-Way-Handshake vor jeder HTTP-Anfrage (HTTP/1.1) - 3-Way-Handshake vor jeder HTTP(S)-Anfrage (HTTP/2.0)
- Keep-Alive: Verbindung bleibt offen für mehrere Requests - Keep-Alive: Verbindung bleibt offen für mehrere Requests
- HTTP/2: Multiplexing – viele Requests über eine Verbindung - HTTP/2: Multiplexing – viele Requests über eine Verbindung
**3. HTTP Request/Response:** **3. HTTP(S) Request/Response:**
``` ```
Request: Methode + URL + Header + (Body) Request: Methode + URL + Header + (Body)
Response: Status + Header + Body Response: Status + Header + Body
+666
View File
@@ -0,0 +1,666 @@
---
marp: true
theme: gaia
paginate: true
backgroundColor: #fff
header: "Web Engineering – DHBW Stuttgart"
footer: "Michael Czechowski – SoSe 2026"
title: Intro
---
<style>
:root {
--color-foreground: #1a1a2e;
--color-highlight: #d63384;
--color-dimmed: #4a4a6a;
}
section.invert {
--color-foreground: #fff;
}
section {
font-size: 1.4rem;
}
h1 {
color: #a02060;
}
section.invert h1 {
color: #fff;
}
h2 {
color: #1f2937;
}
section.invert h2 {
color: #f48fb1;
}
pre {
background: #0f0f23;
color: #f48fb1;
border-radius: 8px;
border-left: 3px solid #d63384;
}
pre code {
background: transparent;
color: inherit;
}
code {
background: #1a1a2e;
color: #f48fb1;
padding: 0.15em 0.4em;
border-radius: 4px;
}
a {
color: var(--color-highlight);
}
</style>
<!-- _class: invert -->
<!-- _header: '' -->
<!-- _backgroundColor: #000 -->
![bg cover opacity:0.2](./assets/background.png)
# Web Engineering
**DHBW Stuttgart** · Informatik / Wirtschaftsinformatik
**Sommersemester 2026**
[https://librete.ch/dhbw/](https://librete.ch/dhbw/)
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/qr/slides-dhbw.png)
---
# Ressourcen zum Selbstlernen
- **CODE CRISPIES** — [codecrispi.es](https://codecrispi.es/)
- **Online Code-Editor** — [codepen.io](https://codepen.io/pen/)
- **MDN** (Mozilla Developer Network) — [developer.mozilla.org/de/](https://developer.mozilla.org/de/)
- **Flexbox-Spiel** — [flexboxfroggy.com](https://flexboxfroggy.com/)
- **Grid-Spiel** — [cssgridgarden.com](https://cssgridgarden.com/)
---
<!-- _class: lead -->
# Herzlich Willkommen!
## 1. Sitzung: 08.05.2026
---
# Über mich
![bg right:33% fit](./assets/logos/collage.png)
**Michael Werner Czechowski**
- Systems and Platform Engineer
- Schwerpunkte:
- Web-Technologien, Barriere-Armut, Open Source
- Hintergrund:
- Philosophie (Uni Stuttgart)
- Wirtschaftsinformatik (Leibniz-FH Hannover)
- Honorardozent (DHBW Stuttgart, HdM Stuttgart, Leibniz-FH)
- Kontakt: michael.czechowski@lehre.dhbw-stuttgart.de
---
# Vorstellungsrunde
## Wer bist du, was machst du?
> Ich bin \_\_\_, mache bei \_\_\_ \_\_\_ und ein Fun Fact über mich ist, dass ich ...
- ... sämtliche One Piece Bände gelesen habe.
- ... alle XKCD Comics mit Titel kenne.
- ... irgendwann bei \_\_\_ arbeiten möchte.
- ... Paulaner Spezi im Blindtest herausschmecken kann.
---
# Vorlesungsplan
<style scoped>
.lp-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 10px;
margin-top: 0.5rem;
}
.lp-card {
border: 1px solid #d63384;
border-radius: 8px;
padding: 10px 12px;
background: #fff;
font-size: 0.95em;
display: flex;
flex-direction: column;
gap: 4px;
}
.lp-card .head {
font-weight: bold;
color: #a02060;
display: flex;
justify-content: space-between;
align-items: baseline;
font-size: 0.85em;
}
.lp-card .head .num {
font-size: 1.1em;
}
.lp-card .topic {
color: #1a1a2e;
line-height: 1.25;
}
.lp-card.milestone {
background: #fce4ec;
border-color: #a02060;
border-width: 2px;
}
.lp-card.milestone .topic {
font-weight: bold;
}
</style>
<div class="lp-grid">
<div class="lp-card"><div class="head"><span class="num">1</span><span>08.05.</span></div><div class="topic">Intro · Projektgruppen · Internet 101</div></div>
<div class="lp-card"><div class="head"><span class="num">2</span><span>15.05.</span></div><div class="topic">HTML und CSS (Frameworks)</div></div>
<div class="lp-card"><div class="head"><span class="num">3</span><span>22.05.</span></div><div class="topic">JS (Frameworks) und npm</div></div>
<div class="lp-card"><div class="head"><span class="num">4</span><span>29.05.</span></div><div class="topic">nodeJS: Scripting, Running, Building</div></div>
<div class="lp-card"><div class="head"><span class="num">5</span><span>05.06.</span></div><div class="topic">Express API, CRUD, Middlewares</div></div>
<div class="lp-card milestone"><div class="head"><span class="num">6</span><span>12.06.</span></div><div class="topic">Projektwerkstattbericht</div></div>
<div class="lp-card"><div class="head"><span class="num">7</span><span>19.06.</span></div><div class="topic">Testing (Unit · Integration · E2E)</div></div>
<div class="lp-card"><div class="head"><span class="num">8</span><span>26.06.</span></div><div class="topic">TypeScript</div></div>
<div class="lp-card"><div class="head"><span class="num">9</span><span>03.07.</span></div><div class="topic">Docker · Proxies · DBs</div></div>
<div class="lp-card"><div class="head"><span class="num">10</span><span>10.07.</span></div><div class="topic">Wrap-up & Projektsupport</div></div>
<div class="lp-card milestone"><div class="head"><span class="num">11</span><span>17.07.</span></div><div class="topic">Präsentation</div></div>
</div>
---
# Erwartungen und Wünsche
- Was haben wir bisher gelernt?
- Was kennen wir bereits aus dem Arbeitskontext?
- Welche Technologien nutzen wir bereits?
- Was möchte ich hier lernen: Frontend, Backend, DevOps?
- Eigene FOSS entwickeln?
- CLI-Skills verbessern?
- Cloud, Cloud, Cloud?
---
# Prüfungsleistung – Übersicht
Eigenes Projekt: **Web-Applikation** XOR **Backend** (API/CLI).
| Punkte | Bereich |
|--------|---------|
| 30 | Grundanforderungen (Projektgrundlagen + Präsentation) |
| 25 | Clean Code Prinzipien |
| 25 | Accessibility & UX |
| 20 | Technische Umsetzung |
| **100** | **Basispunkte** |
| +15 | Bonuspunkte (max. 3 Features a 5 P.) |
---
# Prüfungsleistung – Grundanforderungen (30 P.)
**Projektgrundlagen (15 P.)**
- Funktionsfähige Anwendung (8 P.)
- Repository mit Versionskontrolle (4 P.)
- Projektdokumentation / README (3 P.)
**Präsentation (15 P.)**
- Elevator Pitch (5 P.)
- Technische Präsentation (5 P.)
- Projektevolution: wie hat sich das Projekt vs. Ursprungsidee verändert? (5 P.)
---
# Prüfungsleistung – Clean Code (25 P.)
**Projektstruktur (10 P.)**
- Ordnerstruktur (5 P.)
- Datei-Organisation (5 P.)
**Code-Qualität (10 P.)**
- KISS – Keep It Simple, Stupid (3 P.)
- Beschreibende Namen (3 P.)
- Funktionsverantwortlichkeiten (4 P.)
**Kommentierung & Dokumentation (5 P.)**
---
# Prüfungsleistung – Accessibility & UX (25 P.)
**Web Accessibility (15 P.)**
- Semantisches HTML (5 P.)
- ARIA Labels & Alt-Texte (5 P.)
- Tastaturnavigation (5 P.)
**Responsive Design (10 P.)**
- Mobile First Approach (5 P.)
- Flexbox/Grid Layout (5 P.)
---
# Prüfungsleistung – Technische Umsetzung (20 P.)
- Plattformunabhängigkeit (5 P.)
- Package Management (5 P.)
- Build Tools & Optimierung (5 P.)
- Live-Demo (5 P.)
---
# Prüfungsleistung – Bonuspunkte (max. 15 P.)
Mindestens 2 Bereiche wählen, je 5 Punkte:
- API Integration
- Local Storage / State Management
- Progressive Web App Features
- Testing
- Erweiterte Responsive Features (3+ Breakpoints)
- Security Features
---
# Prüfungsleistung – Abgabe & Termine
- **Code-Upload:** bis 27.07.
- **Präsentation:** 17.07. (Gruppen, ~10 Min.)
Details: https://git.librete.ch/DHBW/pruefungsleistung
---
<!-- _class: invert -->
<!-- _header: '' -->
<!-- _backgroundColor: #000 -->
# Was ist (k)eine Web Applikation?
## Exkurs
---
# Was ist (k)eine Web Applikation?
**Keine Web Applikation ist:**
* Betriebssystem (GNU/Linux, Windows, macOS, iOS, Android)
* Desktop-Applikation
* Mobile-Applikation
* Embedded System (Microcontroller, IoT)
**Eine Web Applikation ist:**
* plattformunabhängig (läuft im Browser)
* nutzt in der Regel HTTP-Requests
* keine Installation nötig — serverseitig aktualisiert
* gebaut in Web-Technologien (HTML, CSS, JS/TS)
* skalierbar durch verteilte Architektur
---
# Internet-Timeline
| Jahr | Meilenstein |
|------|-------------|
| **1966** | ARPANET-Projekt startet (DARPA) |
| **1969** | Erste Verbindung zwischen UCLA und Stanford |
| **1974** | TCP/IP-Protokoll entwickelt |
| **1989** | Tim Berners-Lee erfindet das WWW (CERN) |
| **1993** | Mosaic — erster grafischer Browser |
| **1994** | W3C gegründet (HTML, CSS, SVG, WCAG) |
| **1995** | ECMAScript / JavaScript wird Standard |
| **2008** | V8 JavaScript Engine (Chrome / Node.js) |
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/arpanet.jpg)
---
# Das WWW (1989)
**Tim Berners-Lee** am **CERN** (Genf)
**Problem:** Wissenschaftler:innen können Forschungsdokumente nicht verlinken — Inkompatible Systeme, kein gemeinsames Format.
**Lösung — drei Bausteine:**
- **HTML** — Auszeichnungssprache für Dokumente
- **HTTP** — Protokoll zur Übertragung
- **URL** — eindeutige Adressen
**1991:** erste Webseite geht online · 1993 vom CERN gemeinfrei freigegeben.
→ WWW ≠ Internet. Das WWW ist eine **Anwendung auf** dem Internet.
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/mosaic.jpg)
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg cover](./assets/img_633d7b91366e0-1025x538-768x403.jpg)
---
# Heute: Physische Infrastruktur
- **5,5 Milliarden** Menschen online
- **> 400 Unterseekabel**, ca. **1,3 Mio. km** Glasfaser
- Daten reisen mit **Lichtgeschwindigkeit**
- Latenz Frankfurt — New York: ~80 ms
→ Keine "Cloud" ohne Kabel. Das Internet ist **physische** Infrastruktur — und damit angreifbar.
**Geopolitik:** Five-Eyes-Allianz (USA, UK, CA, AU, NZ) zapft Unterseekabel ab (Programm "Tempora", aufgedeckt 2013 durch Snowden). DE ist Teil der Fourteen Eyes.
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/demos/browser-server-sequence.png)
---
# HTTP – Hypertext Transfer Protocol
**Request:**
```
GET /products HTTP/1.1
Host: localhost:8080
```
**Response:**
```
HTTP/1.1 200 OK
Content-Type: application/json
[{"id": 1, "name": "Produkt A"}, ...]
```
---
<!-- _class: invert -->
<!-- _header: '' -->
<!-- _backgroundColor: #000 -->
# Onboarding
## Tools, Runtimes, Workflows
---
# Werkzeuge & Betriebssystem
**Erforderliche Werkzeuge:**
- **Terminal** (zsh / bash / fish / pwsh) — Kommandozeile
- **Editor** (siehe folgende Folie)
- **JavaScript-Runtime** (Node.js / Bun / Deno)
- **Browser mit DevTools** (Chromium / Firefox / Safari)
- **Git** — verteiltes Versionskontrollsystem (Stand der Industrie)
**OS-Empfehlung:**
| OS | Status |
|----|--------|
| **macOS** | First-class, viele Tools "just work" |
| **Linux** | First-class, beste Server-Parität |
| **Windows + WSL2** | Empfohlen — Windows-CLI hat Edge Cases |
| **Windows nativ** (PowerShell) | Funktioniert, aber holpriger Pfad |
---
# Node.js installieren – macOS
Empfohlen: **LTS** (aktuell **Node.js 24** — Stand 2026).
Paketmanager: **[Homebrew](https://brew.sh)**
```bash
# Homebrew installieren (falls nicht vorhanden)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# Node.js LTS installieren
brew install node@24
# Version prüfen
node --version
npm --version
```
Alternative: Installer von [nodejs.org](https://nodejs.org)
---
# Node.js installieren – Linux
Empfohlen: **LTS** (aktuell **Node.js 24**).
**Debian / Ubuntu** ([NodeSource](https://github.com/nodesource/distributions)):
```bash
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
sudo apt install -y nodejs
```
**Arch / Manjaro:**
```bash
sudo pacman -S nodejs npm
```
**Fedora / RHEL:**
```bash
sudo dnf module install nodejs:24/common
```
→ Distro-Pakete sind oft **veraltet**. Versionsmanager (folgende Folie) bevorzugen.
---
# Node.js installieren – Windows
Empfohlen: **LTS** (aktuell **Node.js 24**).
**Option 1: winget** (empfohlen, Win 10/11):
```powershell
winget install OpenJS.NodeJS.LTS
```
**Option 2: Chocolatey** ([chocolatey.org](https://chocolatey.org)):
```powershell
choco install nodejs-lts
```
**Option 3: Scoop** ([scoop.sh](https://scoop.sh)):
```powershell
scoop install nodejs-lts
```
**Option 4:** Installer von [nodejs.org](https://nodejs.org)
→ **Empfehlung:** WSL2 + Linux-Workflow nutzen.
---
# Direkt-Install: Wenn es eng wird
**Typisches Szenario** — drei parallele Projekte mit unterschiedlichen Anforderungen:
| Projekt | Stack | Node-Version |
|---------|-------|--------------|
| Praktikums-API | Express (Legacy) | 18.x (LTS Hydrogen) |
| Studienarbeit | Next.js 15 | 22.x (LTS Jod) |
| Aktuelles Lab-Projekt | neueste Features | 24.x (Iron, current LTS) |
System-Install kennt nur **eine** Node-Version global → Konflikt.
---
# Symptome im Alltag
- `npm install` bricht mit `engines`-Warning ab
- native Module (z. B. `node-sass`) bauen nicht
- CI-Pipeline ist grün, lokal rot — oder umgekehrt
- erheblicher Zeitverlust beim Debuggen von Versions-Konflikten
→ Lösung: **Versionsmanager** und Node-Version pro Projekt pinnen.
---
# Node-Versionsmanager
Verschiedene Projekte brauchen oft verschiedene Node-Versionen. **Lösung:** Versionsmanager.
| Tool | Sprache | Geschwindigkeit | Plattform |
|------|---------|-----------------|-----------|
| **nvm** | Bash | langsam (Shell-Funktion) | macOS, Linux |
| **fnm** | Rust | sehr schnell | macOS, Linux, Windows |
| **asdf** | Bash | mittel, multi-language | macOS, Linux |
| **volta** | Rust | schnell, pinning per `package.json` | alle |
```bash
# fnm
curl -fsSL https://fnm.vercel.app/install | bash
fnm install --lts # aktuell Node 24
fnm use lts-latest
# .nvmrc / .node-version automatisch
echo "lts/*" > .nvmrc
fnm use # liest .nvmrc
```
---
# Alternative Runtimes
| Runtime | Erschienen | Engine | USP |
|---------|------------|--------|-----|
| **Node.js** | 2009 | V8 (C++) | Standard, größtes Ökosystem |
| **Deno** | 2020 | V8 (Rust) | Sicherheit, TypeScript nativ, Std-Lib |
| **Bun** | 2022 | JavaScriptCore (Zig) | Geschwindigkeit, all-in-one |
```bash
# Deno
curl -fsSL https://deno.land/install.sh | sh
deno run main.ts
# Bun
curl -fsSL https://bun.sh/install | bash
bun install
bun run dev
```
→ Im Kurs primär **Node.js**. Bun und Deno sind ebenfalls zulässig.
---
# Editor (IDE)
- **VS Code** (empfohlen) — kostenlos, große Plugin-Auswahl
- **JetBrains WebStorm** — sehr mächtig, kostenpflichtig
- kostenlos für Studierende via [JetBrains Education](https://www.jetbrains.com/community/education/#students)
- **Vim / Neovim / Emacs** — für CLI-Profis
- **Zed** — modern, schnell
---
# Browser DevTools
Chromium / Firefox / Safari — `F12` oder `Cmd+Opt+I`
<small>Chromium = Open-Source-Basis von Chrome, Edge, Brave, Opera, Vivaldi etc.</small>
**Wichtigste Panels:**
- **Network** — HTTP-Requests, Responses, Timing
- **Console** — `console.log`, JS-Errors, REPL
- **Elements** — DOM-Inspektor, Live-CSS-Editor
- **Sources** — Debugger, Breakpoints, Source-Maps
- **Performance** — Profiling, Frame-Rate, FPS
- **Application** — LocalStorage, Cookies, Service Workers
---
# HTTP-Clients
- **Bruno** ([usebruno.com](https://usebruno.com)) — open source, git-friendly
- **Hoppscotch** ([hoppscotch.io](https://hoppscotch.io)) — open source, browser-basiert (vormals Postwoman)
- **Insomnia** / **Postman** — etabliert, freemium
- **curl** / **httpie** — CLI (Command-Line Interface, scriptbar)
---
# Git Setup & Workflow
**Einmalige Konfiguration:**
```bash
git config --global user.name "Vorname Nachname"
git config --global user.email "vorname.nachname@example.com"
git config --global init.defaultBranch main
git config --global pull.rebase true
```
**SSH-Key für GitHub/GitLab:**
```bash
ssh-keygen -t ed25519 -C "vorname.nachname@example.com"
cat ~/.ssh/id_ed25519.pub # → in GitHub-Settings einfügen
```
**Tägliche Befehle:**
```bash
git status # was hat sich geändert?
git add <file> # für Commit vormerken
git commit -m "feat: ..." # Conventional Commits
git push # hochladen
git pull --rebase # neueste Änderungen holen
```
---
# Projekt-Skeleton
```bash
mkdir mein-projekt && cd mein-projekt
git init
npm init -y # erzeugt package.json
echo "node_modules" > .gitignore
echo ".env" >> .gitignore
npm install express
```
**`package.json` minimal:**
```json
{
"name": "mein-projekt",
"version": "0.1.0",
"type": "module",
"scripts": {
"start": "node index.js",
"dev": "node --watch index.js"
}
}
```
`.env` für Secrets (nie committen!), `.env.example` mit Dummy-Werten committen.
---
File diff suppressed because it is too large. Load diff
-292
View File
@@ -1,292 +0,0 @@
---
marp: true
theme: gaia
paginate: true
backgroundColor: #fff
header: "Web Engineering – DHBW Stuttgart"
footer: "Michael Czechowski – SoSe 2026"
---
<style>
:root {
--color-foreground: #1a1a2e;
--color-highlight: #d63384;
--color-dimmed: #4a4a6a;
}
section.invert {
--color-foreground: #fff;
}
section {
font-size: 1.4rem;
}
h1 {
color: #a02060;
}
section.invert h1 {
color: #fff;
}
h2 {
color: #1f2937;
}
section.invert h2 {
color: #f48fb1;
}
pre {
background: #0f0f23;
color: #f48fb1;
border-radius: 8px;
border-left: 3px solid #d63384;
}
pre code {
background: transparent;
color: inherit;
}
code {
background: #1a1a2e;
color: #f48fb1;
padding: 0.15em 0.4em;
border-radius: 4px;
}
a {
color: var(--color-highlight);
}
</style>
<!-- _class: invert -->
<!-- _header: '' -->
<!-- _backgroundColor: #000 -->
# Web Engineering
**DHBW Stuttgart** · Informatik / Wirtschaftsinformatik
**Sommersemester 2026** · Sitzung 2 — HTML & CSS (Frameworks)
---
# Ressourcen zum Selbstlernen
- **CODE CRISPIES** — [codecrispi.es](https://codecrispi.es/)
- **Online Code-Editor** — [codepen.io](https://codepen.io/pen/)
- **MDN** (Mozilla Developer Network) — [developer.mozilla.org/de/](https://developer.mozilla.org/de/)
- **Flexbox-Spiel** — [flexboxfroggy.com](https://flexboxfroggy.com/)
- **Grid-Spiel** — [cssgridgarden.com](https://cssgridgarden.com/)
---
# Inhalt
Aufbauend auf den Grundlagen aus Sitzung 1.
1. Attribut-Selektoren
2. Combinators (vertieft)
3. Pseudo-Klassen — erweitert
4. Shorthand Properties
5. Flexbox-Shorthands
6. Custom Properties (Variables)
7. CSS Functions (`calc`, `clamp`, ...)
8. Transition & Animation
9. CSS Frameworks (Tailwind & Co.)
---
<!-- _class: invert -->
<!-- _backgroundColor: #000 -->
# CSS: Extended
---
# CSS Selectors – Attribut-Selektoren
```css
/* presence */
[disabled] { opacity: 0.5; }
/* exact value */
[type="email"] { border-color: blue; }
/* contains word */
[class~="btn"] { cursor: pointer; }
/* starts with */
[href^="https"] { color: green; }
/* ends with */
[src$=".png"] { border: 1px solid #ccc; }
/* contains substring */
[class*="icon"] { padding-left: 20px; }
```
---
# CSS Combinators
```css
/* Child (direkt) */
div > p { margin: 0; }
/* Descendant (Nachkomme) */
div p { margin: 0; }
/* Next Sibling */
h1 + p { font-size: 1.2em; }
/* Subsequent Sibling */
h1 ~ p { color: #666; }
/* Selector List */
h1, h2, h3 { font-weight: bold; }
```
---
# Pseudo Classes – Erweitert
```css
/* Form States */
:valid { border-color: green; }
:invalid { border-color: red; }
:placeholder-shown { color: #999; }
/* Content */
:before { content: "→ "; }
:after { content: " [Wichtig]"; }
:first-letter { font-size: 2em; }
:first-line { font-weight: bold; }
/* NOT */
:not(.disabled) { pointer-events: auto; }
:not(:last-child) { border-bottom: 1px solid #ccc; }
```
---
# Shorthand Properties
```css
/* margin: top right bottom left */
margin: 10px 20px 10px 20px;
/* centering */
margin: 0 auto;
/* padding same */
padding: 20px;
/* border: width style color */
border: 1px solid #333;
/* background: color image position/size repeat */
background: #fff url(logo.png) 0 0 no-repeat;
/* font: style variant weight size/line-height family */
font: italic normal bold 16px/1.5 Arial, sans-serif;
```
---
# Flexbox Shorthands
```css
/* flex: grow shrink basis */
flex: 1 0 auto;
/* place-items: align-items justify-items */
place-items: center stretch;
/* place-content: align-content justify-content */
place-content: space-between center;
/* gap: row-gap column-gap */
gap: 20px 40px;
```
---
# CSS Custom Properties (Variables)
```css
:root {
--primary-color: #d63384;
--spacing: 20px;
--radius: 8px;
}
.button {
background: var(--primary-color);
padding: var(--spacing);
border-radius: var(--radius);
}
```
---
# CSS Functions
```css
/* calc */
width: calc(100% - 40px);
/* min/max/clamp */
width: min(100%, 600px);
font-size: clamp(14px, 2vw, 20px);
/* var with fallback */
color: var(--text-color, #333);
/* rgb/rgba/hsl/hsla */
color: hsl(200, 100%, 50%);
background: rgba(0, 0, 0, 0.5);
```
---
# Transition & Animation
```css
/* transition: property duration timing-function */
transition: all 0.3s ease-in-out;
transition: background 0.2s, transform 0.1s;
/* animation */
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.fade-in {
animation: fadeIn 0.5s ease-out;
}
```
---
# CSS Frameworks
| Framework | Stil |
|-----------|------|
| **Bootstrap** | Komponenten + Grid, opinionated |
| **Tailwind CSS** | Utility-First, atomar |
| **Bulma** | klassisch, ohne JS |
| **shadcn/ui** | kopierbare Komponenten (Tailwind-basiert) |
| **Flowbite** | Tailwind-Komponentenbib. |
---
# Tailwind CSS – Beispiel
```html
<button class="bg-blue-600 hover:bg-blue-700
text-white font-semibold
px-4 py-2 rounded-lg
transition shadow-sm">
Klick mich
</button>
```
- Keine eigenen CSS-Klassen mehr
- JIT-Compiler erzeugt nur genutzte Klassen
- Design-System via `tailwind.config.js`
+412
View File
@@ -0,0 +1,412 @@
---
marp: true
theme: gaia
paginate: true
backgroundColor: #fff
header: "Web Engineering – DHBW Stuttgart"
footer: "Michael Czechowski – SoSe 2026"
title: JavaScript & Frameworks
---
<style>
:root {
--color-foreground: #1a1a2e;
--color-highlight: #d63384;
--color-dimmed: #4a4a6a;
}
section.invert {
--color-foreground: #fff;
}
section {
font-size: 1.4rem;
}
h1 {
color: #a02060;
}
section.invert h1 {
color: #fff;
}
h2 {
color: #1f2937;
}
section.invert h2 {
color: #f48fb1;
}
pre {
background: #0f0f23;
color: #f48fb1;
border-radius: 8px;
border-left: 3px solid #d63384;
}
pre code {
background: transparent;
color: inherit;
}
code {
background: #1a1a2e;
color: #f48fb1;
padding: 0.15em 0.4em;
border-radius: 4px;
}
a {
color: var(--color-highlight);
}
</style>
<!-- _class: invert -->
<!-- _header: '' -->
<!-- _backgroundColor: #000 -->
![bg cover opacity:0.2](./assets/background.png)
# Web Engineering
**DHBW Stuttgart** · Informatik / Wirtschaftsinformatik
**Sommersemester 2026** · Sitzung 3 — JS, Frameworks & Build Tools
[https://librete.ch/dhbw/](https://librete.ch/dhbw/)
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/qr/slides-dhbw.png)
---
# Ressourcen zum Selbstlernen
- **CODE CRISPIES** — [codecrispi.es](https://codecrispi.es/)
- **Online Code-Editor** — [codepen.io](https://codepen.io/pen/)
- **MDN** (Mozilla Developer Network) — [developer.mozilla.org/de/](https://developer.mozilla.org/de/)
- **Flexbox-Spiel** — [flexboxfroggy.com](https://flexboxfroggy.com/)
- **Grid-Spiel** — [cssgridgarden.com](https://cssgridgarden.com/)
<!-- _class: invert -->
<!-- _header: '' -->
<!-- _backgroundColor: #000 -->
# JavaScript
---
# ECMAScript
- **Ecma International** — European Computer Manufacturers Association
- Seit **1997** standardisiert als **ECMA-262**
- Implementierungen: **JavaScript** (Netscape, später Mozilla), **JScript** (Microsoft), **ActionScript** (Adobe Flash) etc.
- Aktuelle Version: **ECMAScript 2024 (ES15)**, jährliche Releases
**Browser-Kompatibilität:**
- Faustregel: **ES2017+** läuft in allen modernen Browsern
- Ältere Targets via Transpiler (Babel, esbuild, swc, tsc)
- Kompatibilitätstabelle: [kangax.github.io/compat-table](https://kangax.github.io/compat-table/)
---
# JavaScript Grundlagen
```javascript
// Variablen
let name = "Welt";
const alter = 25;
// Funktionen
function gruss(name) {
return `Hallo, ${name}!`;
}
// Arrow Functions
const add = (a, b) => a + b;
// Arrays
const arr = [1, 2, 3];
arr.map(x => x * 2); // [2, 4, 6]
```
---
# DOM Manipulation
```javascript
// Element auswählen
const title = document.querySelector('h1');
// Inhalt ändern
title.textContent = 'Neue Überschrift';
// Event Listener
button.addEventListener('click', () => {
alert('Geklickt!');
});
```
---
# Fetch API
```javascript
fetch('/api/products')
.then(res => res.json())
.then(data => {
console.log(data);
})
.catch(err => console.error(err));
```
---
# Async/Await
```javascript
async function loadProducts() {
try {
const res = await fetch('/api/products');
const data = await res.json();
return data;
} catch (err) {
console.error('Fehler:', err);
}
}
```
---
<!-- _header: '' -->
<!-- _footer: '' -->
<!-- _backgroundColor: #050517 -->
![bg fit](./assets/demos/web-engineering-mandala.png)
---
<!-- _backgroundColor: #050517 -->
<!-- _color: #e2e8f0 -->
# Web Engineering Mandala
Interaktive version: [nextlevelshit.github.io/web-engineering-mandala](https://nextlevelshit.github.io/web-engineering-mandala/)
3 Schichten:
- **Core Layer** — JS, HTML, CSS (vanilla)
- **Build Layer** — bundlers, runtimes, template engines, pre/post processors
- **Application Layer** — frontend, backend, frameworks, SSR, CSS-utilities
3 Segmente: HTML (blau) · JavaScript (rot) · CSS (grün) · Mittelpunkt: `package.json`
---
# JavaScript Frameworks – Kategorien
| Kategorie | Beispiele |
|-----------|-----------|
| **CSS Frameworks** | Tailwind, Bootstrap, shadcn/ui |
| **Frontend Frameworks** | React, Vue, Svelte, Astro |
| **Rendering / Meta** | Next.js, Nuxt, Gatsby |
| **Build Tools / Bundler** | Webpack, Vite, Parcel, esbuild |
| **Backend Frameworks** | Express, Fastify, NestJS |
---
# Vanilla JS – Counter
```html
<button id="myButton">Clicked 0 times</button>
<script>
let count = 0;
const btn = document.getElementById('myButton');
btn.addEventListener('click', () => {
count++;
btn.textContent = `Clicked ${count} times`;
});
</script>
```
**Pro:** hohe Kompatibilität, simpel
**Contra:** State-Management und Re-Rendering werden schnell komplex
---
# React – Counter (JSX)
![bg right:25% fit](./assets/logos/frameworks/react.svg)
```jsx
import { useState } from "react";
function MyButton() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
Clicked {count} times
</button>
);
}
```
- **Component-Based** Architecture
- **Virtual DOM**, JSX, Hooks
- großes Ökosystem (React Router, Redux, …)
---
# Vue 3 – Composition API
![bg right:25% fit](./assets/logos/frameworks/vue.svg)
```vue
<script setup>
import { ref } from "vue";
const count = ref(0);
</script>
<template>
<button @click="count++">
Clicked {{ count }} times
</button>
</template>
```
- **Reactive Data Binding**
- Single-File Components (`.vue`)
- Vue Router, Pinia (State)
---
# Svelte – Counter
![bg right:25% fit](./assets/logos/frameworks/svelte.svg)
```svelte
<script>
let count = 0;
</script>
<button on:click={() => count += 1}>
Clicked {count} {count === 1 ? 'time' : 'times'}
</button>
```
- **Compiler-Based** – kein Runtime-Framework
- Reactive Assignments (`let`)
- Built-in Animationen
---
# Astro – Content-First
![bg right:25% fit](./assets/logos/frameworks/astro.svg)
```astro
---
const greeting = "Hallo DHBW";
---
<html>
<body>
<h1>{greeting}</h1>
<MyReactButton client:load />
</body>
</html>
```
- **Islands Architecture** – Komponenten mehrerer Frameworks mischen
- Default: kein JS im Output (nur statisches HTML)
- Hydration on demand (`client:load`, `client:visible`)
---
# Rendering Frameworks
| | Frontend | SSR | SSG | File Routing |
|---|---|---|---|---|
| **Next.js** | React | ja | ja | `/app/page.js` |
| **Nuxt** | Vue | ja | ja | `/pages/*.vue` |
| **Gatsby** | React | nein | ja | GraphQL Data |
---
# Build Tools – Webpack
![bg right:25% fit](./assets/logos/frameworks/webpack.svg)
- Module Bundling (JS, CSS, Images)
- Module Loaders + großes Plugin-Ökosystem
- Code Splitting, HMR
- Konfigurations-lastig (`webpack.config.js`)
→ Standard für viele Legacy-Setups.
---
# Build Tools – Vite
![bg right:25% fit](./assets/logos/frameworks/vite.svg)
```javascript
// vite.config.js
import { defineConfig } from "vite";
export default defineConfig({
server: {
proxy: {
"/api": {
target: "http://localhost:4567",
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, "")
}
}
}
});
```
- Rollup unter der Haube, **HMR mit ES Modules**
- Tree-Shaking, Code Splitting, React + Vue out-of-the-box
---
# Build Tools – Parcel
![bg right:25% fit](./assets/logos/frameworks/parcel.png)
```json
{
"name": "my-project",
"source": "src/index.html",
"browserslist": "> 0.5%, last 2 versions, not dead",
"scripts": {
"start": "parcel",
"build": "parcel build"
},
"devDependencies": {
"parcel": "latest"
}
}
```
- **Zero-Config**
- Auto-Resolution, HMR
- TS / CSS-Preprocessors out-of-the-box
---
# Microfrontends
- Mehrere unabhängige Frontend-Apps in einer Page
- Module Federation (Webpack 5)
- **single-spa**: https://single-spa.js.org/
- Anwendungsfall: große Teams, unterschiedliche Tech-Stacks pro Domain
→ Komplexitätskosten: nur bei echtem Skalierungsbedarf.
---
# Demo-Repos
- https://github.com/nextlevelshit/dhbw-client-js (Counter, multi-framework)
- https://github.com/nextlevelshit/node-cache-api (API + Tests)
- https://github.com/nextlevelshit/dhbw-docker (Compose-Stack)
@@ -62,6 +62,15 @@ a {
**Sommersemester 2026** · Sitzung 4 — Node.js: Scripting, Running and Building **Sommersemester 2026** · Sitzung 4 — Node.js: Scripting, Running and Building
[https://librete.ch/dhbw/](https://librete.ch/dhbw/)
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/qr/slides-dhbw.png)
--- ---
# Ressourcen zum Selbstlernen # Ressourcen zum Selbstlernen
@@ -62,6 +62,15 @@ a {
**Sommersemester 2026** · Sitzung 5 — Express API, CRUD und Middlewares **Sommersemester 2026** · Sitzung 5 — Express API, CRUD und Middlewares
[https://librete.ch/dhbw/](https://librete.ch/dhbw/)
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/qr/slides-dhbw.png)
--- ---
# Ressourcen zum Selbstlernen # Ressourcen zum Selbstlernen
@@ -63,6 +63,15 @@ a {
**Sommersemester 2026** · Sitzung 7 — Testing **Sommersemester 2026** · Sitzung 7 — Testing
[https://librete.ch/dhbw/](https://librete.ch/dhbw/)
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/qr/slides-dhbw.png)
--- ---
# Ressourcen zum Selbstlernen # Ressourcen zum Selbstlernen
@@ -63,6 +63,15 @@ a {
**Sommersemester 2026** · Sitzung 8 — TypeScript **Sommersemester 2026** · Sitzung 8 — TypeScript
[https://librete.ch/dhbw/](https://librete.ch/dhbw/)
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/qr/slides-dhbw.png)
--- ---
<!-- _class: invert --> <!-- _class: invert -->
@@ -63,6 +63,15 @@ a {
**Sommersemester 2026** · Sitzung 9 — Docker, Proxies and DBs **Sommersemester 2026** · Sitzung 9 — Docker, Proxies and DBs
[https://librete.ch/dhbw/](https://librete.ch/dhbw/)
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/qr/slides-dhbw.png)
--- ---
<!-- _class: invert --> <!-- _class: invert -->
@@ -63,6 +63,15 @@ a {
**Sommersemester 2026** · Sitzung 10 — Wrap-up & Projektsupport **Sommersemester 2026** · Sitzung 10 — Wrap-up & Projektsupport
[https://librete.ch/dhbw/](https://librete.ch/dhbw/)
---
<!-- _header: '' -->
<!-- _footer: '' -->
![bg fit](./assets/qr/slides-dhbw.png)
--- ---
<!-- _class: invert --> <!-- _class: invert -->
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

+15
View File
@@ -0,0 +1,15 @@
<svg id="Ebene_1" data-name="Ebene 1" xmlns="http://www.w3.org/2000/svg" width="433" height="97" viewBox="0 0 433 97">
<g>
<g id="logotype">
<path id="logotype-b-47" d="M185.2,46.88a13.77,13.77,0,0,0,8.8-13c0-11.7-8.3-17.5-19.7-17.5H144.4V80h32.5c10,0,19.8-7,19.8-17.7C196.7,49.58,185.2,47,185.2,46.88ZM160,29.58h11.6a5.66,5.66,0,0,1,6,5.31q0,.34,0,.69a5.93,5.93,0,0,1-6,5.81H159.9Zm11.7,37.1H160.1V54.18h11.3c5.7,0,8.4,2.5,8.4,6.2C179.8,65,176.4,66.68,171.7,66.68Z" style="fill: #ed0007;fill-rule: evenodd"/>
<path id="logotype-o-47" d="M231.1,14.78c-18.4,0-29.2,14.7-29.2,33.3s10.8,33.3,29.2,33.3,29.2-14.6,29.2-33.3S249.6,14.78,231.1,14.78Zm0,51.4c-9,0-13.5-8.1-13.5-18.1s4.5-18,13.5-18,13.6,8.1,13.6,18C244.7,58.18,240.1,66.18,231.1,66.18Z" style="fill: #ed0007;fill-rule: evenodd"/>
<path id="logotype-s-47" d="M294.2,41.38l-2.2-.5c-5.4-1.1-9.7-2.5-9.7-6.4,0-4.2,4.1-5.9,7.7-5.9a17.86,17.86,0,0,1,13,5.9l9.9-9.8c-4.5-5.1-11.8-10-23.2-10-13.4,0-23.6,7.5-23.6,20,0,11.4,8.2,17,18.2,19.1l2.2.5c8.3,1.7,11.4,3,11.4,7,0,3.8-3.4,6.3-8.6,6.3-6.2,0-11.8-2.7-16.1-8.2l-10.1,10c5.6,6.7,12.7,11.9,26.4,11.9,11.9,0,24.6-6.8,24.6-20.7C314.3,46.08,303.3,43.28,294.2,41.38Z" style="fill: #ed0007;fill-rule: evenodd"/>
<path id="logotype-c-47" d="M349.7,66.18c-7,0-14.3-5.8-14.3-18.5,0-11.3,6.8-17.6,13.9-17.6,5.6,0,8.9,2.6,11.5,7.1l12.8-8.5c-6.4-9.7-14-13.8-24.5-13.8-19.2,0-29.6,14.9-29.6,32.9,0,18.9,11.5,33.7,29.4,33.7,12.6,0,18.6-4.4,25.1-13.8L361.1,59C358.5,63.18,355.7,66.18,349.7,66.18Z" style="fill: #ed0007;fill-rule: evenodd"/>
<polygon id="logotype-h-47" points="416.3 16.38 416.3 39.78 397 39.78 397 16.38 380.3 16.38 380.3 79.98 397 79.98 397 54.88 416.3 54.88 416.3 79.98 433 79.98 433 16.38 416.3 16.38" style="fill: #ed0007;fill-rule: evenodd"/>
</g>
<g id="symbol">
<path d="M48.2.18a48.2,48.2,0,1,0,48.2,48.2A48.2,48.2,0,0,0,48.2.18Zm0,91.9a43.7,43.7,0,1,1,43.7-43.7,43.71,43.71,0,0,1-43.7,43.7Z"/>
<path d="M68.1,18.28H64.8v16.5H31.7V18.28H28.3a36.06,36.06,0,0,0,0,60.2h3.4V62H64.8v16.5h3.3a36.05,36.05,0,0,0,0-60.2ZM27.1,72A31.59,31.59,0,0,1,24.47,27.4a32.51,32.51,0,0,1,2.63-2.62Zm37.7-14.6H31.7V39.28H64.8Zm4.5,14.5v-10h0V34.78h0v-10a31.65,31.65,0,0,1,2.39,44.71A33.68,33.68,0,0,1,69.3,71.88Z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 167 KiB

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 911 KiB

+1
View File
@@ -0,0 +1 @@
<svg width="189" height="45" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M-46-32h1440V68H-46z"/><g fill-rule="nonzero"><g fill="#0E1111"><path d="M133.298 34.907v-1.509L142.48 20.1h-8.71v-1.982h11.44v1.513l-9.183 13.296h9.494v1.981h-12.222M129.365 35.163c-2.235 0-2.145-.927-2.145-3.611V18.117h2.132V31.82l.013 3.343M120.61 34.907v-12.19c0-2.181-1.192-2.854-3.135-2.854-2.037 0-3.071.371-4.23 1.075v13.97h-2.194v-16.79h1.223l.471 1.41c1.472-1.175 3.07-1.746 4.73-1.746 3.728 0 5.327 1.812 5.327 5.039v12.086h-2.193M100.87 33.163c-2.038 0-3.168-.37-4.389-1.075v-11.15c1.221-.704 2.351-1.075 4.388-1.075 3.76 0 4.229 3.325 4.229 6.65s-.47 6.65-4.229 6.65zm0-15.381a7.795 7.795 0 00-4.389 1.376V9.723h-2.193v25.184h1.221l.47-1.377c1.63 1.109 3.196 1.714 4.89 1.714 5.045 0 6.422-3.896 6.422-8.731s-1.377-8.731-6.422-8.731zM89.417 35.24c-2.256 0-2.148-1.004-2.148-3.688V18.117h2.13V31.82l.018 3.42M72.667 25.674c.092-3.023.751-5.811 4.387-5.811 3.603 0 3.76 2.822 3.76 5.81h-8.147zm10.34.839c0-4.835-.627-8.731-5.953-8.731-5.297 0-6.581 3.896-6.581 8.73 0 4.836 1.284 8.732 6.581 8.732 1.534 0 3.413-.168 5.17-1.008v-2.013c-1.535.704-2.914.94-5.17.94-3.542 0-4.263-2.653-4.387-5.574h10.34v-1.076zM54.492 34.907V9.723h2.131v23.07h10.874v2.114H54.492M188.975 34.9V9.723h-2.12v11.011h-11.658V9.724h-2.119V34.9h2.12V22.848h11.657V34.9h2.12M158.053 11.837h11.128V9.723h-13.248V34.9h2.12V22.848h10.037v-2.114h-10.037v-8.897M87.261 15.025h2.142v-2.24h-2.142zM127.222 15.025h2.142v-2.24h-2.142z"/></g><path d="M.195 1.476l9.617-.42v43.75L.2 42.284C.2 23.158.197 8.006.195 1.476M39.777 43.49l-9.655.422V.162l9.65 2.953c0 19.392.002 34.192.005 40.375" fill="#0288d1"/><path fill="#74BEE6" d="M9.812 34.613v10.193l15.285-.67V33.888l-15.285.725M15.11.837v10.285l15.012-.724V.161L15.11.837"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

+78
View File
@@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.0" width="123.1184" height="38" id="svg2">
<defs id="defs4"/>
<g transform="translate(-4.113659e-8,-8.1875909)" id="g2881">
<g transform="matrix(0.8227318,0,0,0.8227318,0,8.1875911)" id="g3725">
<path d="m 5.9058686,3.5864545 c 0,1.6289778 -1.3205475,2.9495254 -2.9495254,2.9495254 -1.628978,0 -2.9495254,-1.3205476 -2.9495254,-2.9495254 0,-1.6289779 1.3205474,-2.94952547 2.9495254,-2.94952547 1.6289779,0 2.9495254,1.32054757 2.9495254,2.94952547 l 0,0 z" id="path2492" style="fill:#022d6f;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"/>
<use transform="translate(123.33173,0.52756266)" id="use2494" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(12.995121,0.24968358)" id="use3266" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(-0.0021669,6.4942292)" id="use3268" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(-0.00100324,13.007016)" id="use3270" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(1.6068057e-4,19.515151)" id="use3272" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(5.6386012,22.744639)" id="use3274" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(-0.00681775,26.008952)" id="use3276" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(12.102606,22.633932)" id="use3278" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(19.117759,2.4186714)" id="use3280" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(22.403372,8.0486075)" id="use3282" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(18.008113,19.840656)" id="use3284" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(21.756631,14.51843)" id="use3286" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(-0.00100325,32.490405)" id="use3290" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(0.00132398,38.988066)" id="use3292" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(37.905739,3.6984537)" id="use3294" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(65.078186,33.204228)" id="use3296" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(33.398214,8.5473695)" id="use3298" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(30.724945,14.638897)" id="use3300" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(30.159334,21.213576)" id="use3302" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(31.812768,27.679762)" id="use3304" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(35.421974,33.202782)" id="use3306" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(40.652784,37.299478)" id="use3308" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(43.733988,0.5434759)" id="use3310" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(50.271054,-0.58340514)" id="use3312" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(56.815356,0.50441766)" id="use3314" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(46.959848,39.447642)" id="use3316" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(62.637816,3.6608425)" id="use3318" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(53.579391,39.44039)" id="use3320" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(67.139555,8.5531567)" id="use3322" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(69.779551,14.64179)" id="use3324" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(70.340823,21.210681)" id="use3326" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(79.933056,19.51385)" id="use3328" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(59.8575,37.257529)" id="use3330" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(68.722105,27.673974)" id="use3332" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(6.4702426,5.7452075e-4)" id="use3334" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(79.938844,13.014391)" id="use3336" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(79.933047,0.00245617)" id="use3338" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(79.934503,6.494682)" id="use3340" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(85.563127,3.2586948)" id="use3342" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(89.846429,8.1177379)" id="use3344" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(94.152881,13.004267)" id="use3346" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(79.938841,26.013309)" id="use3348" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(98.462222,17.886454)" id="use3350" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(102.76578,22.745497)" id="use3352" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(79.930164,32.496854)" id="use3354" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(108.40887,26.016202)" id="use3356" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(108.40597,0.00390394)" id="use3358" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(108.40887,6.4888947)" id="use3360" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(108.40742,13.012946)" id="use3362" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(108.41031,19.509501)" id="use3364" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(79.933058,38.984738)" id="use3366" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(108.40308,32.498301)" id="use3368" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(108.40308,38.98329)" id="use3370" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(118.86037,5.2694337)" id="use3372" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(118.33815,11.771784)" id="use3374" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(122.73574,16.555607)" id="use3376" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(129.72991,-0.63692924)" id="use3378" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(136.11652,0.46102075)" id="use3380" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(128.89236,18.606849)" id="use3382" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(135.21099,20.106946)" id="use3384" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(142.06329,3.0879996)" id="use3386" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(141.06815,22.998648)" id="use3388" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(118.41627,34.426578)" id="use3390" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(143.73998,28.915145)" id="use3392" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(123.96821,37.788408)" id="use3394" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(130.21596,39.651611)" id="use3396" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(136.68652,38.987622)" id="use3398" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
<use transform="translate(141.93608,35.149863)" id="use3400" style="fill:#022d6f;fill-opacity:1" x="0" y="0" width="117" height="36" xlink:href="#path2492"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 441 B