commit 124524482b090bed83111e5476092c2a973915c7 Author: dejancosic Date: Sat Aug 1 18:36:18 2026 +0200 HiveGrid Social: Design-Library und Post-Generator Autarke Werkbank für Social-Grafiken: Slides als HTML, Bearbeitung im Canvas, Export als Instagram-taugliche PNGs. - Assets nach brand/partner/mockups/screens sortiert, Karteileichen entfernt - G-Marke als eigene Datei statt nur als Polygon im Code - Partner-Logos und Geerkens-Logo ergänzt - Keine externen Referenzen: Schrift, Bibliotheken und Bilder liegen lokal diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e43b0f9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.DS_Store diff --git a/README.md b/README.md new file mode 100644 index 0000000..6601bfb --- /dev/null +++ b/README.md @@ -0,0 +1,67 @@ +# HiveGrid Social — Design-Library & Post-Generator + +Eigenständige Werkbank für HiveGrid-Social-Grafiken. Slides werden im Browser +als HTML gebaut, im Canvas bearbeitet und pixelgenau als Instagram-taugliche +PNGs exportiert. + +**Das Repo ist bewusst autark.** Keine CDN-Verweise, keine Google-Fonts zur +Laufzeit, keine Pfade in andere Repos. Alles, was ein Post braucht — Schrift, +Logos, Mockups, Screenshots, Bibliotheken — liegt hier. + +## Starten + +```sh +./serve.sh # http://127.0.0.1:4321 +``` + +Downloads landen direkt in `~/Downloads`, ohne Browser-Dialog. + +## Projekte + +| Projekt | Datei | Inhalt | +|---|---|---| +| Post 1 · Lösung | `post1.html` | Carousel, 5 Slides | +| Post 2 · Statement | `index.html` | Einzelbild | + +Oben im Bedienfeld wechselt man zwischen ihnen. **Jedes Projekt speichert +seinen Stand** — Einstellungen, Layouts, Muster und alle Verschiebungen aus dem +Canvas überleben einen Reload. „Projekt zurücksetzen" wirft ihn weg. + +## Bedienung + +| Taste | Wirkung | +|---|---| +| `←` `→` | Slide wechseln (im Bearbeiten-Modus: Element verschieben) | +| `E` | Bearbeiten an/aus | +| `W` | Streifen ⇄ Einzelansicht | +| `V` | Variante hell/dunkel | +| `L` `M` `I` | Layout · Muster · Intensität | +| `C` `G` `T` | Durchgehend · Tag-Ausrückung · Perspektive | +| `D` `A` | Slide laden · alle als ZIP | + +Im Bearbeiten-Modus lassen sich Elemente ziehen, mit den Pfeiltasten +pixelweise schieben (`⇧` = 10 px) und über `A−`/`A+` in der Größe ändern. + +## Aufbau + +``` +assets/ +├── brand/ Wortmarke hell/dunkel, G-Marke (SVG + PNG), Wabe, Geerkens +├── partner/ DATEV, KWP, Google Calendar, Google Drive, MS Outlook, MS Teams +├── mockups/ Geräte-Mockups (Display ausgeknockt, Screenshot liegt dahinter) +├── screens/ Software-Screenshots +└── fonts/ Manrope 400–800, lokal +vendor/ html-to-image, JSZip +serve.py Statischer Server + /save-Endpunkt +rules.md Gestaltungsregeln, Farbwerte, Export-Wissen +``` + +## Regeln + +**`rules.md` ist die Arbeitsgrundlage.** Farbwerte, Geometrie, Typografie, +Layout-Template, Instagram-Export und die Liste der Fallen, in die wir schon +getappt sind. Vor jeder Änderung an der Gestaltung dort nachsehen. + +Marken-Werte stammen aus der Website (`HiveGrid-Website`) und sind hier +**gespiegelt**, nicht verlinkt. Ändert sich dort etwas, muss es hier +nachgezogen werden. diff --git a/assets/brand/cta-honeycomb.svg b/assets/brand/cta-honeycomb.svg new file mode 100644 index 0000000..5920ed5 --- /dev/null +++ b/assets/brand/cta-honeycomb.svg @@ -0,0 +1,2654 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/brand/g-mark.png b/assets/brand/g-mark.png new file mode 100644 index 0000000..aa39d44 Binary files /dev/null and b/assets/brand/g-mark.png differ diff --git a/assets/brand/g-mark.svg b/assets/brand/g-mark.svg new file mode 100644 index 0000000..ce00718 --- /dev/null +++ b/assets/brand/g-mark.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/brand/geerkens-logo.png b/assets/brand/geerkens-logo.png new file mode 100644 index 0000000..5c93747 Binary files /dev/null and b/assets/brand/geerkens-logo.png differ diff --git a/assets/brand/hivegrid-logo.png b/assets/brand/hivegrid-logo.png new file mode 100644 index 0000000..2c0213f Binary files /dev/null and b/assets/brand/hivegrid-logo.png differ diff --git a/assets/brand/logo-white.svg b/assets/brand/logo-white.svg new file mode 100644 index 0000000..d1e3eb2 --- /dev/null +++ b/assets/brand/logo-white.svg @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/brand/logo.svg b/assets/brand/logo.svg new file mode 100644 index 0000000..cdbd696 --- /dev/null +++ b/assets/brand/logo.svg @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/fonts/manrope.css b/assets/fonts/manrope.css new file mode 100644 index 0000000..6b04909 --- /dev/null +++ b/assets/fonts/manrope.css @@ -0,0 +1,270 @@ +/* cyrillic-ext */ +@font-face { + font-family: 'Manrope'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(./xn7gYHE41ni1AdIRggqxSvfedN62Zw.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Manrope'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(./xn7gYHE41ni1AdIRggOxSvfedN62Zw.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek */ +@font-face { + font-family: 'Manrope'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(./xn7gYHE41ni1AdIRggSxSvfedN62Zw.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Manrope'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(./xn7gYHE41ni1AdIRggixSvfedN62Zw.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Manrope'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(./xn7gYHE41ni1AdIRggmxSvfedN62Zw.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Manrope'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(./xn7gYHE41ni1AdIRggexSvfedN4.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Manrope'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url(./xn7gYHE41ni1AdIRggqxSvfedN62Zw.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Manrope'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url(./xn7gYHE41ni1AdIRggOxSvfedN62Zw.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek */ +@font-face { + font-family: 'Manrope'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url(./xn7gYHE41ni1AdIRggSxSvfedN62Zw.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Manrope'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url(./xn7gYHE41ni1AdIRggixSvfedN62Zw.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Manrope'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url(./xn7gYHE41ni1AdIRggmxSvfedN62Zw.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Manrope'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url(./xn7gYHE41ni1AdIRggexSvfedN4.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Manrope'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(./xn7gYHE41ni1AdIRggqxSvfedN62Zw.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Manrope'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(./xn7gYHE41ni1AdIRggOxSvfedN62Zw.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek */ +@font-face { + font-family: 'Manrope'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(./xn7gYHE41ni1AdIRggSxSvfedN62Zw.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Manrope'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(./xn7gYHE41ni1AdIRggixSvfedN62Zw.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Manrope'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(./xn7gYHE41ni1AdIRggmxSvfedN62Zw.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Manrope'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(./xn7gYHE41ni1AdIRggexSvfedN4.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Manrope'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(./xn7gYHE41ni1AdIRggqxSvfedN62Zw.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Manrope'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(./xn7gYHE41ni1AdIRggOxSvfedN62Zw.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek */ +@font-face { + font-family: 'Manrope'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(./xn7gYHE41ni1AdIRggSxSvfedN62Zw.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Manrope'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(./xn7gYHE41ni1AdIRggixSvfedN62Zw.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Manrope'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(./xn7gYHE41ni1AdIRggmxSvfedN62Zw.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Manrope'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(./xn7gYHE41ni1AdIRggexSvfedN4.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +/* cyrillic-ext */ +@font-face { + font-family: 'Manrope'; + font-style: normal; + font-weight: 800; + font-display: swap; + src: url(./xn7gYHE41ni1AdIRggqxSvfedN62Zw.woff2) format('woff2'); + unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} +/* cyrillic */ +@font-face { + font-family: 'Manrope'; + font-style: normal; + font-weight: 800; + font-display: swap; + src: url(./xn7gYHE41ni1AdIRggOxSvfedN62Zw.woff2) format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +/* greek */ +@font-face { + font-family: 'Manrope'; + font-style: normal; + font-weight: 800; + font-display: swap; + src: url(./xn7gYHE41ni1AdIRggSxSvfedN62Zw.woff2) format('woff2'); + unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF; +} +/* vietnamese */ +@font-face { + font-family: 'Manrope'; + font-style: normal; + font-weight: 800; + font-display: swap; + src: url(./xn7gYHE41ni1AdIRggixSvfedN62Zw.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; +} +/* latin-ext */ +@font-face { + font-family: 'Manrope'; + font-style: normal; + font-weight: 800; + font-display: swap; + src: url(./xn7gYHE41ni1AdIRggmxSvfedN62Zw.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +/* latin */ +@font-face { + font-family: 'Manrope'; + font-style: normal; + font-weight: 800; + font-display: swap; + src: url(./xn7gYHE41ni1AdIRggexSvfedN4.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} diff --git a/assets/fonts/xn7gYHE41ni1AdIRggOxSvfedN62Zw.woff2 b/assets/fonts/xn7gYHE41ni1AdIRggOxSvfedN62Zw.woff2 new file mode 100644 index 0000000..1cece61 Binary files /dev/null and b/assets/fonts/xn7gYHE41ni1AdIRggOxSvfedN62Zw.woff2 differ diff --git a/assets/fonts/xn7gYHE41ni1AdIRggSxSvfedN62Zw.woff2 b/assets/fonts/xn7gYHE41ni1AdIRggSxSvfedN62Zw.woff2 new file mode 100644 index 0000000..29a1a72 Binary files /dev/null and b/assets/fonts/xn7gYHE41ni1AdIRggSxSvfedN62Zw.woff2 differ diff --git a/assets/fonts/xn7gYHE41ni1AdIRggexSvfedN4.woff2 b/assets/fonts/xn7gYHE41ni1AdIRggexSvfedN4.woff2 new file mode 100644 index 0000000..9d7abb1 Binary files /dev/null and b/assets/fonts/xn7gYHE41ni1AdIRggexSvfedN4.woff2 differ diff --git a/assets/fonts/xn7gYHE41ni1AdIRggixSvfedN62Zw.woff2 b/assets/fonts/xn7gYHE41ni1AdIRggixSvfedN62Zw.woff2 new file mode 100644 index 0000000..3eca77a Binary files /dev/null and b/assets/fonts/xn7gYHE41ni1AdIRggixSvfedN62Zw.woff2 differ diff --git a/assets/fonts/xn7gYHE41ni1AdIRggmxSvfedN62Zw.woff2 b/assets/fonts/xn7gYHE41ni1AdIRggmxSvfedN62Zw.woff2 new file mode 100644 index 0000000..bdade6d Binary files /dev/null and b/assets/fonts/xn7gYHE41ni1AdIRggmxSvfedN62Zw.woff2 differ diff --git a/assets/fonts/xn7gYHE41ni1AdIRggqxSvfedN62Zw.woff2 b/assets/fonts/xn7gYHE41ni1AdIRggqxSvfedN62Zw.woff2 new file mode 100644 index 0000000..fc82004 Binary files /dev/null and b/assets/fonts/xn7gYHE41ni1AdIRggqxSvfedN62Zw.woff2 differ diff --git a/assets/mockups/laptop.png b/assets/mockups/laptop.png new file mode 100644 index 0000000..968fd9f Binary files /dev/null and b/assets/mockups/laptop.png differ diff --git a/assets/partner/datev.png b/assets/partner/datev.png new file mode 100644 index 0000000..5e44e80 Binary files /dev/null and b/assets/partner/datev.png differ diff --git a/assets/partner/google-calendar.svg b/assets/partner/google-calendar.svg new file mode 100644 index 0000000..c32c0c7 --- /dev/null +++ b/assets/partner/google-calendar.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + diff --git a/assets/partner/google-drive.svg b/assets/partner/google-drive.svg new file mode 100644 index 0000000..a8cefd5 --- /dev/null +++ b/assets/partner/google-drive.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/assets/partner/kwp.png b/assets/partner/kwp.png new file mode 100644 index 0000000..b96428b Binary files /dev/null and b/assets/partner/kwp.png differ diff --git a/assets/partner/ms-outlook.svg b/assets/partner/ms-outlook.svg new file mode 100644 index 0000000..586f39f --- /dev/null +++ b/assets/partner/ms-outlook.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/partner/ms-teams.svg b/assets/partner/ms-teams.svg new file mode 100644 index 0000000..3409e6c --- /dev/null +++ b/assets/partner/ms-teams.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/screens/chat.png b/assets/screens/chat.png new file mode 100644 index 0000000..2085244 Binary files /dev/null and b/assets/screens/chat.png differ diff --git a/assets/screens/form-builder.png b/assets/screens/form-builder.png new file mode 100644 index 0000000..17da99f Binary files /dev/null and b/assets/screens/form-builder.png differ diff --git a/assets/screens/pipelines.png b/assets/screens/pipelines.png new file mode 100644 index 0000000..4163a2a Binary files /dev/null and b/assets/screens/pipelines.png differ diff --git a/assets/screens/workflow.png b/assets/screens/workflow.png new file mode 100644 index 0000000..bc6fb65 Binary files /dev/null and b/assets/screens/workflow.png differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..1b2b1b1 --- /dev/null +++ b/index.html @@ -0,0 +1,564 @@ + + + + + +HiveGrid Post-Generator + + + + + + + +
+
+
+ + +
+ + + + + +
+

Vom Handwerker für den Handwerker

+ + + + + + +
+ +

Verbinden
statt ersetzen

+
+
+ + +
+
+

Vorschau 45 %, Export in voller Auflösung

+
+ + + + + + diff --git a/post1.html b/post1.html new file mode 100644 index 0000000..1e62ba4 --- /dev/null +++ b/post1.html @@ -0,0 +1,1634 @@ + + + + + +HiveGrid Post 1 (Lösung, Carousel) + + + + + + + +
+
+
+
+

Vorschau 45 %, Export in voller Auflösung

+
+ + + + + + diff --git a/rules.md b/rules.md new file mode 100644 index 0000000..eb18053 --- /dev/null +++ b/rules.md @@ -0,0 +1,561 @@ +# Post-Generator — Regeln & Konventionen + +Arbeitsgrundlage für alles, was in diesem Repo an Social-Grafiken entsteht. +**Stand:** 31.07.2026 + +Der Generator läuft lokal: `./serve.sh` → +(Post 1, Carousel) bzw. `/index.html` (Post 2, Statement). + +--- + +## 1. Wo die Wahrheit steht + +Alle Marken-Werte stammen aus der Website, nicht aus diesem Repo. Bei Zweifel +**dort nachschauen, nicht hier raten**: + +| Was | Quelle | +|---|---| +| Farben, Radien, Abstände | `HiveGrid-Website/app/globals.css` (`:root`) | +| Chamfer-Form | `HiveGrid-Website/lib/chamfer.ts` | +| Schrift | `HiveGrid-Website/app/layout.tsx` | +| Badge-Styling | `HiveGrid-Website/components/sections/ScreenshotAccordion.tsx` | +| Feature-Texte | `HiveGrid-Website/app/playground/PlaygroundClient.tsx` → `solutionModules` | + +Die Werte sind hier gespiegelt, weil der Export keine Tailwind-/oklch-Farben +verträgt (siehe §7). Ändert sich die Website, müssen sie **hier nachgezogen +werden** — das passiert nicht automatisch. + +--- + +## 2. Farben + +### Marke + +| Token | Wert | Verwendung | +|---|---|---| +| `--accent-yellow` | `#F1B729` | Primärer Akzent, Marker, G-Marke | +| `--accent-yellow-light` | `#FFE082` | Badge-Hintergrund | +| `--accent-yellow-dark` | `#3E2C0A` | Badge-Text | +| `--accent-teal` | `#0D6E6E` | Sekundär, aktuell ungenutzt | +| `--dark-bg` | `#30313D` | Dunkle Variante + Formen-Ebene | + +### Flächen & Text + +| Token | Wert | +|---|---| +| `--surface` | `#FFFFFF` | +| `--bg-primary` | `#FAFAFA` | +| `--text-primary` | `#1A1A1A` | +| `--text-secondary` | `#555555` | +| `--text-on-dark` | `#C8D0DC` | + +### Pro Variante + +**Hell** (Grund `#FFFFFF`) + +``` +--head-color #1A1A1A --frame-bg #E8EBF0 +--body-color #555555 --shape-fill #30313D (deckend!) +--accent-on #C8901A --shape-line rgba(48,49,61,.13) +--marker #F1B729 --shape-accent #F1B729 +--pat-color #30313D --gmark-color rgba(48,49,61,.16) +``` + +**Dunkel** (Grund `#30313D`) + +``` +--head-color #FFFFFF --frame-bg rgba(255,255,255,.11) +--body-color #B9BDC9 --shape-fill #414252 +--accent-on #F1B729 --shape-line rgba(255,255,255,.10) +--marker #F1B729 --shape-accent #F1B729 +--pat-color #FFFFFF --gmark-color rgba(255,255,255,.13) +``` + +> **`--accent-on` ist nicht `#F1B729`, sondern `#C8901A` auf Hell.** Reines +> Markengelb trägt auf Weiß bei kleinem Text nicht. Der abgedunkelte Ton ist +> Absicht, kein Fehler. + +> **Der Block oben rechts ist auf Hell deckendes `#30313D`.** Das ist derselbe +> Wert wie die dunkle Story-Sektion der Website. Er darf **nicht** über die +> Intensitätsstufe aufgehellt werden, sonst ist es nicht mehr die Markenfarbe +> (siehe §5). + +--- + +## 3. Geometrie + +### Chamfer + +Die Marken-Form: abgeschnittene Ecken, Echo der Honigwabe. Auf der Website +16 px, hier hochskaliert, weil die Fläche viermal so groß ist. + +```css +clip-path: polygon( + Xpx 0, calc(100% - Xpx) 0, 100% Xpx, 100% calc(100% - Xpx), + calc(100% - Xpx) 100%, Xpx 100%, 0 calc(100% - Xpx), 0 Xpx +); +``` + +| Element | X | +|---|---| +| Badge | 11 px | +| Mockup-Rahmen außen | 22 px | +| Mockup-Rahmen innen | 14 px | + +**Drei Fallstricke** (stehen auch in `chamfer.ts`): + +- `clip-path` beschneidet **auch den Schatten** → Tiefe über `filter: drop-shadow()`, nie `box-shadow` +- `clip-path` beschneidet **auch den Rahmen** → Rand über eine Hintergrundfläche lösen, nicht über `border` +- Kinder, die aus der Box ragen (Popups, Tooltips), werden abgeschnitten → solche Elemente nicht chamfern + +### Hexagon + +Flat-Top, also flache Ober- und Unterkante mit Spitzen links und rechts: + +```css +clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%); +``` + +**Seitenverhältnis 384,5 : 332,9 = 1,155 (= 2/√3).** Aus der Logomarke +abgeleitet, nicht geschätzt. Wer davon abweicht, staucht das Sechseck. + +### G-Marke + +Ein einziges Polygon, aus `logo.svg` extrahiert (dort die einzige Fläche mit +`class="st3"`), auf 0,0 normalisiert: + +``` +384.5,166.5 336.4,83.2 192.2,166.5 288.3,166.5 240.3,249.7 144.2,249.7 +96.1,166.5 144.2,83.2 336.4,83.2 298,16.8 288.3,0 96.1,0 0,166.5 +96.1,332.9 288.3,332.9 +``` + +Immer **inline** als SVG einsetzen, nie als `` — nur so lässt sie sich per +`currentColor` pro Variante umfärben, und nur so überlebt sie den Export +zuverlässig (§7). + +### Wabenraster + +Nahtlose Kachel aus derselben G-Form. Bei Flat-Top-Hexagonen springen die +Spalten um ¾ der Breite, benachbarte Spalten sitzen eine halbe Reihe versetzt. +Eine Kachel = zwei Spalten breit, eine Reihe hoch. **Die über den Kachelrand +hinausragenden Kopien sind Pflicht** — ohne sie sieht man die Nähte. + +--- + +## 4. Typografie + +### Die Schrift + +**Manrope** — dieselbe wie auf der Website. Bewusst nicht Inter: Der Kommentar in +`app/layout.tsx` nennt Inter „the default AI/website-builder font"; Manrope ist +eine Spur wärmer und geometrischer. + +```css +font-family: 'Manrope', system-ui, sans-serif; +``` + +| | | +|---|---| +| Schnitte | 400, 500, 600, 700, 800 | +| Ablage | `assets/fonts/manrope.css` + 6 `.woff2` | +| Subsets | latin, latin-ext, cyrillic, cyrillic-ext, greek, vietnamese | +| Herkunft | Google Fonts, einmalig heruntergeladen | + +**Warum lokal und nicht per CDN:** Der Export darf zur Laufzeit an keiner +fremden Origin hängen. Ein Font von `fonts.gstatic.com` wäre cross-origin, würde +den Export vom Netz abhängig machen und im Zweifel den Canvas verunreinigen. Die +URLs in `manrope.css` sind deshalb auf relative Pfade umgeschrieben. + +> **Vor jedem Export auf `document.fonts.ready` warten.** Sonst rendert der erste +> Durchgang still in einer System-Fallback-Schrift, und man sieht es erst in der +> fertigen Datei. Der Download-Button bleibt bis dahin deaktiviert. + +### Größen + +| Element | Größe | Weight | Sonstiges | +|---|---|---|---| +| Headline | 74 px | 800 | `line-height: 1.06`, `letter-spacing: -0.03em` | +| Titel-Tagline | 74 px | 800 | identisch zur Headline, bewusst | +| Fließtext | 30 px | 500 | `line-height: 1.48`, `max-width: 830px` | +| Badge | 26 px | 600 | `letter-spacing: 0.1em` | +| Claim (Titel) | 31 px | 500 | `line-height: 1.44` | + +### Akzent-Wörter + +Zwei Behandlungen, **nie beide im selben Textblock**: + +- **Marker** — handgezeichneter SVG-Strich als `background-image`, wellige + Kanten, angeschrägtes linkes Ende. Für Headlines und Payoffs. + Ein CSS-Verlauf ist hier **verboten**: er kann geometrisch nur ein perfektes + Rechteck erzeugen und sieht gedruckt statt gemalt aus. +- **Farbe** (`--accent-on`) — für kleinere Zeilen. + +Pro Slide höchstens **ein** markiertes Wort. Zwei Marker in einem Block waren +schon zweimal zu viel. + +### Sprache + +- Alles Sichtbare auf **Deutsch**, Code-Kommentare auf **Englisch** +- **Keine Em-Dashes (—)** in sichtbaren Texten. Komma, Punkt oder `·` +- Feature-Texte wortgleich von der Website. Headlines dürfen gekürzt und + umgestellt werden, aber **keine neuen Wörter erfinden** + +--- + +## 5. Aufbau der Slides + +### Formate + +**1080 × 1350 px (4:5)** — das hochkantigste offiziell unterstützte +Feed-Format. Belegt: Instagram unterstützt 1.91:1 bis 4:5, Breiten 320–1080 +behalten die Originalauflösung, alles außerhalb wird beschnitten. + +- **Alle Slides eines Carousels müssen dasselbe Seitenverhältnis haben** — die + erste Slide setzt es, der Rest wird hart darauf beschnitten +- Safe Zone: nichts Lesbares näher als ~92 px an den Rand +- Der **Profil-Grid** zeigt seit 2025 Hochformat und beschneidet auf 3:4 — + im Grid fehlen links und rechts je ~33 px. Für die drei angepinnten Cover + relevant, im Feed nicht + +### Layout-Template: Tag, Überschrift, Beschreibung, Bild + +Jede Feature-Slide besteht aus denselben vier Bausteinen in derselben Reihenfolge. +Das ist keine Geschmacksfrage — Wiedererkennung über fünf Slides entsteht genau +dadurch, dass sich das Gerüst nicht bewegt. + +``` + 92 ┌──────────────────────────────────────┐ + │ ▌ TAG │ ← ausgerückt (siehe unten) + │ │ + │ Überschrift, zwei Zeilen │ ← dominiert die Slide + │ mit einem markierten Wort │ + │ │ + │ Beschreibung, zwei bis drei │ ← kürzer als man denkt + │ Zeilen Fließtext │ + │ │ + │ ┌────────────────────────────────── │ + │ │ Bild │ ← ein dominanter Blickfang + │ │ │ + └──┴───────────────────────────────────┘ +``` + +**Größenverhältnisse.** Die Hierarchie muss ohne Nachdenken lesbar sein — was +zuerst, was zweitens, was drittens. Bei uns: Überschrift 74 px, Fließtext 30 px, +Tag 26 px. Das Verhältnis Überschrift zu Fließtext liegt bei rund **2,5 : 1**; +gängige Empfehlungen für Carousels nennen Überschrift 48–72 pt gegen Fließtext +24–36 pt, also dieselbe Größenordnung. Weniger Abstand als Faktor 2 und die +Hierarchie kippt. + +**Ein Blickfang pro Slide.** Genau ein Element, auf das das Auge sofort springt — +bei uns die Überschrift, danach das Bild. Zwei gleich starke Elemente lassen den +Betrachter raten und wegwischen. + +**Weißraum ist kein verschenkter Platz**, sondern das, was die Blöcke trennt. +Der Abstand zwischen Tag und Überschrift ist deshalb größer als der zwischen +Überschrift und Beschreibung: getrennte Gedanken brauchen mehr Luft als +zusammengehörige. + +#### Das Tag wird ausgerückt + +Der Tag hat 20 px Innenabstand. Steht sein **Kasten** bündig zur Inhaltskante, +beginnt sein **Text** 20 px weiter rechts als die Überschrift — und genau das +sieht man: + +``` +vorher nachher + 92 │▌ WORKFLOW-ENGINE 72 │▌ WORKFLOW-ENGINE + 92 │Wenn-dann 92 │Wenn-dann + └ Kasten bündig, └ Text bündig, + Text 20 px versetzt Kasten ragt aus +``` + +Gelöst über `margin-left: -20px`, also genau den Innenabstand. Das ist dasselbe +Prinzip wie hängende Interpunktion im Satz: Ausgerichtet wird nach der +**wahrgenommenen** Kante, nicht nach der geometrischen. Der Kasten steht dann bei +x 72 — immer noch weit innerhalb der Safe Zone. + +> Wer die Innenabstände des Tags ändert, muss das negative Margin mitziehen. +> Die beiden Werte gehören zusammen. + +### Ebenen (von hinten nach vorn) + +| z-index | Ebene | +|---|---| +| 0 | Hintergrund: Formen, Wabenraster, Punkte, Raster, G-Marke | +| 1 | Mockup | +| 2 | Inhalt: Badge, Headline, Fließtext | +| 3 | Swipe-Hinweis | + +### Was global gilt und was pro Slide + +| Einstellung | Geltung | Warum | +|---|---|---| +| Variante (Hell/Dunkel) | **global** | gemischt fällt das Carousel auseinander | +| Mockup-Perspektive | **global** | dito | +| Renderqualität | **global** | Exportstufe, kein Gestaltungsmittel (§7) | +| Layout | pro Slide | jede Slide hat einen eigenen Katalog | +| Muster | pro Slide | | +| Intensität | pro Slide | | + +### Durchgehendes Carousel (Panorama) + +Der Post ist dann kein Stapel von fünf Bildern mehr, sondern **ein einziges +Blatt von 5400 × 1350 px**, das in fünf 1080er Fenster geschnitten wird. Wer +swipet, sieht Elemente über die Kante hinauslaufen und auf der nächsten Slide +weitergehen. + +``` + Slide 1 │ Slide 2 │ Slide 3 │ Slide 4 │ Slide 5 +0 ─────── 1080 ────── 2160 ────── 3240 ────── 4320 ────── 5400 + ↑ ↑ ↑ ↑ + die vier Nähte +``` + +**Technisch:** Eine Ebene von 5400 px Breite liegt in jeder Slide, verschoben um +`index × -1080 px`. Jede Slide zeigt dadurch ihr Fenster desselben Blatts. Kein +Zuschneiden von Hand, kein Splitter-Tool — die Slides *sind* die Schnitte. + +**Regeln, die dabei zählen:** + +1. **Slide 1 muss allein funktionieren.** Sie ist das Cover im Profil-Grid. Sie + darf nicht wie „das linke Fünftel von etwas" wirken +2. **Die Naht ist nie unsichtbar.** Instagram zeigt beim Swipen ein paar Pixel + Abstand zwischen den Slides. Das lässt sich nicht abstellen und ist auch nicht + schlimm — der Effekt trägt trotzdem +3. **Nichts Wichtiges auf die Naht legen.** Keine Schrift, kein Gesicht, kein + Logo. Der Schnitt gehört in ruhige Zonen +4. **Aber etwas Auffälliges über die Naht laufen lassen.** Eine halbierte Form + zieht das Auge weiter und lenkt vom Spalt ab. Genau dafür sitzen unsere + Sechsecke **mittig auf 1080 / 2160 / 3240 / 4320** — je zur Hälfte links und + rechts der Naht +5. **Nur Standbilder.** Ein Video mitten im Carousel bricht den Fluss + +**Was bei uns auf dem Blatt liegt:** vier Sechsecke auf den vier Nähten +(abwechselnd massiv und Kontur, unterschiedliche Höhen), die G-Marke auf der Naht +2|3, und ein durchgehendes Band über die volle Breite als Klammer. + +Das ist ein **globaler** Schalter, kein Muster pro Slide — er wirkt naturgemäß +auf alle fünf. Die Muster pro Slide bleiben zusätzlich verfügbar; für den reinen +Panorama-Look überall auf „Aus" stellen. + +> Gängige Empfehlung sind 2–4 Slides fürs Panorama. Wir haben fünf. Das +> funktioniert, verlangt aber eine ruhigere Gestaltung — bei fünf Fenstern wird +> jede zusätzliche Form schnell unruhig. + +### Intensität + +Die Stufe „Dezent" (Faktor 0,55) wirkt **nur auf Nebenelemente** — Hexagon-Kontur, +Waben, Punkt- und Linienraster, G-Marke. Der große Block oben rechts bleibt +immer deckend, sonst wäre er nicht mehr exakt `#30313D`. + +--- + +## 6. Mockups + +Kein fotorealistischer Laptop-Rahmen für die Feature-Slides: Die Website rahmt +jeden Screenshot mit dem Chamfer (`.screenshot-frame` in `globals.css`). Das ist +die markeneigene Mockup-Form und verbindet die Posts mit der Seite. + +Der Laptop auf der Titel-Slide ist die Ausnahme und bewusst ein Blickfang. + +### Geometrie pro Slide + +Breite, Seitenverhältnis und Position sind CSS-Variablen mit Defaults: + +``` +--mock-w 1090px (ragt ~100 px über die rechte Kante) +--mock-ar 1.6 (16:10) +--mock-left 92px +``` + +**Regel: Das Format des Rahmens folgt dem Inhalt des Screenshots, nicht +umgekehrt.** Der Form Builder ist eine schmale, zentrierte Spalte mit breiten +leeren Rändern — in einem 16:10-Rahmen zeigt er vor allem Leere. Er bekommt +deshalb 540 × 720 (3:4), mittig gesetzt, und einen Zoom von 3,8 direkt auf die +Spalte. + +### Screenshots zuschneiden + +Quellen sind ~2000 px breit und im Vollbild unlesbar. Jeder Screen wird auf +seinen aussagekräftigen Bereich gezoomt. Die Werte sind gerechnet, nicht geraten: + +``` +Rahmenbreite = 1 Einheit, Bild bei scale 1 = 1 Einheit breit +Bildhöhe = 1/BildAR Rahmenhöhe = 1/RahmenAR + +Punkt fx horizontal mittig: tx = 0.5/s − fx +Punkt fy vertikal mittig: ty = (RahmenH/2)/(s · BildH) − fy +``` + +Mindest-Zoom zum Füllen: `RahmenH / BildH`. Darunter entstehen Lücken. + +**Ausnahme Titel-Slide:** Der Laptop zeigt den Screen **1:1**, ohne Zoom. Dort +soll ein Bildschirm zeigen, was ein Bildschirm zeigt. Die Displayfläche misst +739 × 489 (AR 1,511), `workflow.png` hat 1,504 — passt praktisch deckungsgleich. + +### Neue Geräte-Mockups einbauen + +1. Braucht **echte Transparenz**. Ein Screenshot eines transparenten PNGs ist + keine Transparenz — das Karomuster steckt dann als Pixel drin und lässt sich + nicht sauber entfernen (einmal versucht, Ergebnis unbrauchbar) +2. Ist die Displayfläche deckend, muss sie **ausgeknockt** werden, damit der + Screenshot dahinter liegen kann. Nur so bleiben Notch und Rundungen oben +3. Displayfläche ausmessen und als Prozentwerte eintragen — sie hängt am + konkreten Bild +4. Schatten über `filter: drop-shadow()` auf dem Container, nicht im PNG + +--- + +## 7. Export & Bildqualität + +### Die zwei Regeln, aus denen alles folgt + +**1. Genau 1080 px breit hochladen.** Instagram behält bei Breiten von 320 bis +1080 die Originalauflösung. Alles darüber wird **von Instagram selbst** +verkleinert und danach neu komprimiert — Qualitätsverlust in zwei Runden statt +einer. Ein 4000-px-Upload ist deshalb schlechter als ein 1080-px-Upload, nicht +besser. + +**2. Trotzdem größer rendern.** Wir rastern intern bei **2×** (2160 × 2700) und +skalieren selbst auf exakt 1080 × 1350 herunter. Das ist kein Widerspruch zu +Regel 1, sondern der eigentliche Trick: Wir kontrollieren das Downsampling, +statt es Instagram zu überlassen. + +``` +2160 × 2700 → Halbierung → 1080 × 1350 → Upload + render exakt +``` + +### Warum das Supersampling hier hilft + +Nicht wegen des Textes — den rastert der Browser bei nativer Größe ohnehin +sauber, teils sogar schärfer als supersampled. Der Gewinn liegt woanders: + +- **Transformationen** — der gekippte Laptop, gedrehte Formen, Chamfer-Kanten + und Hexagon-Clips werden bei doppelter Auflösung gerastert und danach + gemittelt. Das ist echtes Anti-Aliasing statt Treppenkanten +- **Screenshots** — unsere Quellen sind ~2000 px breit und werden auf ~1090 px + gezeigt. Bei 2× zeichnet der Browser sie näher an ihrer nativen Auflösung, das + anschließende Downsampling ist unser eigenes und damit besser +- **Marker und Wabenraster** — SVG-Kanten profitieren identisch + +> Bei reinen Textslides ohne Mockup ist der Unterschied gering bis null. Deshalb +> ist die Stufe umschaltbar (1× / 2× / 3×), nicht fest verdrahtet. **2× ist der +> Standard**, 3× kostet spürbar Zeit und Speicher bei kaum sichtbarem Gewinn. + +### Warum stufenweises Halbieren + +Browser skalieren Canvas standardmäßig schnell statt gut: Pixel werden direkt +übernommen, Nachbarinformationen gehen verloren, das Ergebnis rauscht. Zwei +Gegenmaßnahmen, beide nötig: + +```js +ctx.imageSmoothingEnabled = true; +ctx.imageSmoothingQuality = "high"; // Default ist "low" +``` + +Und: **in Halbierungsschritten** verkleinern statt in einem Sprung. Ein direkter +Sprung von 3240 auf 1080 überspringt Zwischenpixel; zweimal halbieren mittelt +jeweils über 2 × 2 und kommt einer echten Flächenmittelung nahe. + +`createImageBitmap()` mit `resizeQuality` wäre der elegantere Weg, ist aber in +Browsern uneinheitlich umgesetzt — teils wird die Option ignoriert. `drawImage` +mit `imageSmoothingQuality` ist der verlässliche Pfad. + +### Format + +**PNG, nicht JPEG.** Instagram konvertiert am Ende ohnehin zu JPEG — aber unsere +Slides sind Text, flache Flächen und UI-Screenshots mit harten Kanten. Genau die +zerlegt JPEG-Kompression zuerst. Wer als PNG hochlädt, gibt Instagram ein +verlustfreies Original und zahlt nur **einmal** Kompression statt zweimal. + +Für Fotoinhalte wäre JPEG bei 85–95 % die bessere Wahl. Haben wir hier nicht. + +### Farbraum + +**sRGB, ausschließlich.** Instagram wirft andere Profile weg und konvertiert +nach sRGB. Wer in Adobe RGB oder P3 exportiert, bekommt Farbverschiebungen bei +dieser Konvertierung. Canvas-Exporte aus dem Browser sind standardmäßig sRGB — +also nichts zu tun, solange niemand ein Farbprofil anfasst. + +### Weiteres + +- Auf `document.fonts.ready` warten, sonst rendert der erste Export in einer + Fallback-Schrift +- Dateinamen mit `01-`…`05-` präfixen: Instagram übernimmt beim Hochladen die + Dateisortierung +- Dateigröße im Auge behalten. Für JPEG gilt die Faustregel „unter 1 MB", sonst + komprimiert Instagram härter. Für unsere PNGs mit Screenshots ist das nicht zu + halten und auch nicht nötig +- Vom Desktop hochladen, wenn möglich — gilt als schonender als der mobile Upload + +### Quellenlage, ehrlich + +**Von Meta dokumentiert:** die unterstützten Seitenverhältnisse (1.91:1 bis 4:5), +die Auflösungsgrenze 320–1080, der Beschnitt außerhalb, und dass alle +Carousel-Slides auf die erste beschnitten werden. + +**Community-Konsens, nicht offiziell:** die konkreten Kompressionsprozente, die +1-MB-Faustregel, Desktop-vs-Mobile, und PNG-vs-JPEG-Empfehlungen. Plausibel und +breit reproduziert, aber von Meta nirgends bestätigt. Im Zweifel selbst +gegentesten: dieselbe Slide in zwei Varianten hochladen und vergleichen. + +### Vier Dinge, die den Export brechen + +**1. Tailwind- und `oklch()`-Farben.** Die Export-Bibliothek kann sie nicht +serialisieren. Der Slide-Baum benutzt deshalb ausschließlich Hex und `rgba()`. + +**2. PNGs im `foreignObject`.** Der Export serialisiert die Slide in eine +`data:image/svg+xml`-URL und malt sie als **ein** Bild. Raster-Kinder dekodieren +asynchron und verpassen diesen Paint regelmäßig — der Screenshot fehlt dann, +während der Rest stimmt. SVGs dekodieren synchron und sind immer da. + +> Deshalb ist der Export **verifiziert statt gehofft**: Jede Screenshot-Fläche +> wird nach dem Rendern abgetastet. Eine solche Fläche ist nie glatt, sie trägt +> UI und Farbe. Liegt die Luminanz-Spanne unter 12, fehlt das Bild und es wird +> neu gerendert, bis zu fünf Versuche. + +**3. Browser-Downloads.** `data:`-URLs öffneten einen leeren Tab, `blob:`-URLs +das Bild im Tab — das `download`-Attribut wurde beide Male ignoriert. Der +Generator schickt die Bytes deshalb per POST an **`/save`**, und `serve.py` +schreibt direkt nach `~/Downloads`. + +**4. Stille Skriptfehler.** Ein Fehler auf oberster Ebene (Syntax, Temporal Dead +Zone) tötet das ganze Skript: Das Panel rendert aus statischem HTML weiter, aber +nichts wird gebaut. Beide Seiten haben einen globalen `error`-Listener, der so +etwas ins Statusfeld schreibt. **Nicht entfernen.** + +--- + +## 8. Fallen, in die wir schon getappt sind + +| Symptom | Ursache | +|---|---| +| Logo unsichtbar auf Weiß | Sichtbarkeitsregel vertauscht — auf Hell wurde `logo-white.svg` gezeigt | +| Logo bildschirmbreit statt zentriert | `.laptop-screen img` galt auch fürs Logo und hat es überschrieben. Solche Regeln **immer auf eine Klasse eingrenzen** | +| Element eine Zeile zu tief | `max-width` erzwang einen zusätzlichen Umbruch. Bei gesetzten `
` gehört `white-space: nowrap` dazu | +| Farbe „stimmt nicht" | Deckkraft der Ebene lag darüber. Eine Farbe ist nur exakt, wenn nichts sie multipliziert | +| Muster wirkt zufällig hingeworfen | Formen liefen quer durch den Text. Dekoration bleibt in den Rändern, verankert und angeschnitten | +| Nichts lädt, Bühne leer | Konstante vor ihrer Deklaration benutzt (TDZ) | + +--- + +## 9. Ordner + +``` +posts/ +├── serve.py / serve.sh Statischer Server + /save-Endpunkt (Port 4321) +├── post1.html Post 1 · Lösung (Carousel, 5 Slides) +├── index.html Post 2 · Statement (Einzelbild) +├── rules.md diese Datei +├── assets/ +│ ├── logo.svg, logo-white.svg, cta-honeycomb.svg +│ ├── laptop.png Mockup, Display ausgeknockt +│ ├── fonts/ Manrope, lokal +│ └── screens/ Software-Screenshots +└── vendor/ html-to-image, JSZip (lokal, kein CDN) +``` + +Alles läuft **offline**. Keine CDN-Verweise, keine Google-Fonts zur Laufzeit — +sonst hängt der Export an einer Netzwerkverbindung und an fremden Origins. diff --git a/serve.py b/serve.py new file mode 100755 index 0000000..43ea388 --- /dev/null +++ b/serve.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python3 +"""Static server for the post generator, plus a save endpoint. + +The browser download route turned out to be unreliable here: with a data: URL it +opened a blank tab, with a blob: URL it opened the image in a tab. Both times the +download attribute was ignored. Since this only ever runs locally, the generator +now POSTs the rendered bytes to /save and the file is written straight to the +Downloads folder. No browser download machinery involved. +""" + +import http.server +import os +import re +import socketserver +from pathlib import Path + +PORT = 4321 +ROOT = Path(__file__).resolve().parent +TARGET = Path.home() / "Downloads" +SAFE_NAME = re.compile(r"^[A-Za-z0-9._-]{1,120}$") + + +class Handler(http.server.SimpleHTTPRequestHandler): + def __init__(self, *a, **kw): + super().__init__(*a, directory=str(ROOT), **kw) + + def do_POST(self): + if self.path.split("?")[0] != "/save": + self.send_error(404) + return + + name = self.headers.get("X-Filename", "") + # The filename comes from the page, so it is never trusted: no paths, no + # traversal, plain basename only. + name = os.path.basename(name) + if not SAFE_NAME.match(name): + self._json(400, '{"error":"ungueltiger Dateiname"}') + return + + length = int(self.headers.get("Content-Length", 0)) + if length <= 0 or length > 80 * 1024 * 1024: + self._json(400, '{"error":"ungueltige Groesse"}') + return + + data = self.rfile.read(length) + TARGET.mkdir(parents=True, exist_ok=True) + dest = TARGET / name + stem, suffix = dest.stem, dest.suffix + n = 1 + while dest.exists(): + dest = TARGET / f"{stem}-{n}{suffix}" + n += 1 + dest.write_bytes(data) + print(f"gespeichert: {dest} ({len(data)/1024:.0f} KB)") + self._json(200, '{"path":"%s"}' % dest) + + def _json(self, code, body): + payload = body.encode() + self.send_response(code) + self.send_header("Content-Type", "application/json") + self.send_header("Content-Length", str(len(payload))) + self.end_headers() + self.wfile.write(payload) + + def log_message(self, fmt, *args): + if "POST" in (args[0] if args else ""): + super().log_message(fmt, *args) + + +class Server(socketserver.ThreadingTCPServer): + allow_reuse_address = True + + +if __name__ == "__main__": + print(f"Generator: http://127.0.0.1:{PORT}/post1.html") + print(f"Speichert nach: {TARGET}") + with Server(("127.0.0.1", PORT), Handler) as httpd: + httpd.serve_forever() diff --git a/serve.sh b/serve.sh new file mode 100755 index 0000000..f0f6499 --- /dev/null +++ b/serve.sh @@ -0,0 +1,3 @@ +#!/bin/sh +# Serve the generator on a free port, with the /save endpoint. +cd "$(dirname "$0")" && exec python3 serve.py diff --git a/vendor/html-to-image.js b/vendor/html-to-image.js new file mode 100644 index 0000000..b448f79 --- /dev/null +++ b/vendor/html-to-image.js @@ -0,0 +1,2 @@ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).htmlToImage={})}(this,(function(t){"use strict";function e(t,e,n,r){return new(n||(n=Promise))((function(i,o){function u(t){try{a(r.next(t))}catch(t){o(t)}}function c(t){try{a(r.throw(t))}catch(t){o(t)}}function a(t){var e;t.done?i(t.value):(e=t.value,e instanceof n?e:new n((function(t){t(e)}))).then(u,c)}a((r=r.apply(t,e||[])).next())}))}function n(t,e){var n,r,i,o,u={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:c(0),throw:c(1),return:c(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function c(c){return function(a){return function(c){if(n)throw new TypeError("Generator is already executing.");for(;o&&(o=0,c[0]&&(u=0)),u;)try{if(n=1,r&&(i=2&c[0]?r.return:c[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,c[1])).done)return i;switch(r=0,i&&(c=[2&c[0],i.value]),c[0]){case 0:case 1:i=c;break;case 4:return u.label++,{value:c[1],done:!1};case 5:u.label++,r=c[1],c=[0];continue;case 7:c=u.ops.pop(),u.trys.pop();continue;default:if(!(i=u.trys,(i=i.length>0&&i[i.length-1])||6!==c[0]&&2!==c[0])){u=0;continue}if(3===c[0]&&(!i||c[1]>i[0]&&c[1]l||t.height>l)&&(t.width>l&&t.height>l?t.width>t.height?(t.height*=l/t.width,t.width=l):(t.width*=l/t.height,t.height=l):t.width>l?(t.height*=l/t.width,t.width=l):(t.width*=l/t.height,t.height=l))}(c),c.style.width="".concat(d),c.style.height="".concat(v),r.backgroundColor&&(a.fillStyle=r.backgroundColor,a.fillRect(0,0,c.width,c.height)),a.drawImage(u,0,0,c.width,c.height),[2,c]}}))}))}t.getFontEmbedCSS=function(t,r){return void 0===r&&(r={}),e(this,void 0,void 0,(function(){return n(this,(function(e){return[2,Y(t,r)]}))}))},t.toBlob=function(t,r){return void 0===r&&(r={}),e(this,void 0,void 0,(function(){return n(this,(function(e){switch(e.label){case 0:return[4,et(t,r)];case 1:return[4,f(e.sent())];case 2:return[2,e.sent()]}}))}))},t.toCanvas=et,t.toJpeg=function(t,r){return void 0===r&&(r={}),e(this,void 0,void 0,(function(){return n(this,(function(e){switch(e.label){case 0:return[4,et(t,r)];case 1:return[2,e.sent().toDataURL("image/jpeg",r.quality||1)]}}))}))},t.toPixelData=function(t,r){return void 0===r&&(r={}),e(this,void 0,void 0,(function(){var e,i,o,u;return n(this,(function(n){switch(n.label){case 0:return e=s(t,r),i=e.width,o=e.height,[4,et(t,r)];case 1:return u=n.sent(),[2,u.getContext("2d").getImageData(0,0,i,o).data]}}))}))},t.toPng=function(t,r){return void 0===r&&(r={}),e(this,void 0,void 0,(function(){return n(this,(function(e){switch(e.label){case 0:return[4,et(t,r)];case 1:return[2,e.sent().toDataURL()]}}))}))},t.toSvg=tt})); +//# sourceMappingURL=html-to-image.js.map diff --git a/vendor/jszip.min.js b/vendor/jszip.min.js new file mode 100644 index 0000000..ff4cfd5 --- /dev/null +++ b/vendor/jszip.min.js @@ -0,0 +1,13 @@ +/*! + +JSZip v3.10.1 - A JavaScript class for generating and reading zip files + + +(c) 2009-2016 Stuart Knightley +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip/main/LICENSE.markdown. + +JSZip uses the library pako released under the MIT license : +https://github.com/nodeca/pako/blob/main/LICENSE +*/ + +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).JSZip=e()}}(function(){return function s(a,o,h){function u(r,e){if(!o[r]){if(!a[r]){var t="function"==typeof require&&require;if(!e&&t)return t(r,!0);if(l)return l(r,!0);var n=new Error("Cannot find module '"+r+"'");throw n.code="MODULE_NOT_FOUND",n}var i=o[r]={exports:{}};a[r][0].call(i.exports,function(e){var t=a[r][1][e];return u(t||e)},i,i.exports,s,a,o,h)}return o[r].exports}for(var l="function"==typeof require&&require,e=0;e>2,s=(3&t)<<4|r>>4,a=1>6:64,o=2>4,r=(15&i)<<4|(s=p.indexOf(e.charAt(o++)))>>2,n=(3&s)<<6|(a=p.indexOf(e.charAt(o++))),l[h++]=t,64!==s&&(l[h++]=r),64!==a&&(l[h++]=n);return l}},{"./support":30,"./utils":32}],2:[function(e,t,r){"use strict";var n=e("./external"),i=e("./stream/DataWorker"),s=e("./stream/Crc32Probe"),a=e("./stream/DataLengthProbe");function o(e,t,r,n,i){this.compressedSize=e,this.uncompressedSize=t,this.crc32=r,this.compression=n,this.compressedContent=i}o.prototype={getContentWorker:function(){var e=new i(n.Promise.resolve(this.compressedContent)).pipe(this.compression.uncompressWorker()).pipe(new a("data_length")),t=this;return e.on("end",function(){if(this.streamInfo.data_length!==t.uncompressedSize)throw new Error("Bug : uncompressed data size mismatch")}),e},getCompressedWorker:function(){return new i(n.Promise.resolve(this.compressedContent)).withStreamInfo("compressedSize",this.compressedSize).withStreamInfo("uncompressedSize",this.uncompressedSize).withStreamInfo("crc32",this.crc32).withStreamInfo("compression",this.compression)}},o.createWorkerFrom=function(e,t,r){return e.pipe(new s).pipe(new a("uncompressedSize")).pipe(t.compressWorker(r)).pipe(new a("compressedSize")).withStreamInfo("compression",t)},t.exports=o},{"./external":6,"./stream/Crc32Probe":25,"./stream/DataLengthProbe":26,"./stream/DataWorker":27}],3:[function(e,t,r){"use strict";var n=e("./stream/GenericWorker");r.STORE={magic:"\0\0",compressWorker:function(){return new n("STORE compression")},uncompressWorker:function(){return new n("STORE decompression")}},r.DEFLATE=e("./flate")},{"./flate":7,"./stream/GenericWorker":28}],4:[function(e,t,r){"use strict";var n=e("./utils");var o=function(){for(var e,t=[],r=0;r<256;r++){e=r;for(var n=0;n<8;n++)e=1&e?3988292384^e>>>1:e>>>1;t[r]=e}return t}();t.exports=function(e,t){return void 0!==e&&e.length?"string"!==n.getTypeOf(e)?function(e,t,r,n){var i=o,s=n+r;e^=-1;for(var a=n;a>>8^i[255&(e^t[a])];return-1^e}(0|t,e,e.length,0):function(e,t,r,n){var i=o,s=n+r;e^=-1;for(var a=n;a>>8^i[255&(e^t.charCodeAt(a))];return-1^e}(0|t,e,e.length,0):0}},{"./utils":32}],5:[function(e,t,r){"use strict";r.base64=!1,r.binary=!1,r.dir=!1,r.createFolders=!0,r.date=null,r.compression=null,r.compressionOptions=null,r.comment=null,r.unixPermissions=null,r.dosPermissions=null},{}],6:[function(e,t,r){"use strict";var n=null;n="undefined"!=typeof Promise?Promise:e("lie"),t.exports={Promise:n}},{lie:37}],7:[function(e,t,r){"use strict";var n="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Uint32Array,i=e("pako"),s=e("./utils"),a=e("./stream/GenericWorker"),o=n?"uint8array":"array";function h(e,t){a.call(this,"FlateWorker/"+e),this._pako=null,this._pakoAction=e,this._pakoOptions=t,this.meta={}}r.magic="\b\0",s.inherits(h,a),h.prototype.processChunk=function(e){this.meta=e.meta,null===this._pako&&this._createPako(),this._pako.push(s.transformTo(o,e.data),!1)},h.prototype.flush=function(){a.prototype.flush.call(this),null===this._pako&&this._createPako(),this._pako.push([],!0)},h.prototype.cleanUp=function(){a.prototype.cleanUp.call(this),this._pako=null},h.prototype._createPako=function(){this._pako=new i[this._pakoAction]({raw:!0,level:this._pakoOptions.level||-1});var t=this;this._pako.onData=function(e){t.push({data:e,meta:t.meta})}},r.compressWorker=function(e){return new h("Deflate",e)},r.uncompressWorker=function(){return new h("Inflate",{})}},{"./stream/GenericWorker":28,"./utils":32,pako:38}],8:[function(e,t,r){"use strict";function A(e,t){var r,n="";for(r=0;r>>=8;return n}function n(e,t,r,n,i,s){var a,o,h=e.file,u=e.compression,l=s!==O.utf8encode,f=I.transformTo("string",s(h.name)),c=I.transformTo("string",O.utf8encode(h.name)),d=h.comment,p=I.transformTo("string",s(d)),m=I.transformTo("string",O.utf8encode(d)),_=c.length!==h.name.length,g=m.length!==d.length,b="",v="",y="",w=h.dir,k=h.date,x={crc32:0,compressedSize:0,uncompressedSize:0};t&&!r||(x.crc32=e.crc32,x.compressedSize=e.compressedSize,x.uncompressedSize=e.uncompressedSize);var S=0;t&&(S|=8),l||!_&&!g||(S|=2048);var z=0,C=0;w&&(z|=16),"UNIX"===i?(C=798,z|=function(e,t){var r=e;return e||(r=t?16893:33204),(65535&r)<<16}(h.unixPermissions,w)):(C=20,z|=function(e){return 63&(e||0)}(h.dosPermissions)),a=k.getUTCHours(),a<<=6,a|=k.getUTCMinutes(),a<<=5,a|=k.getUTCSeconds()/2,o=k.getUTCFullYear()-1980,o<<=4,o|=k.getUTCMonth()+1,o<<=5,o|=k.getUTCDate(),_&&(v=A(1,1)+A(B(f),4)+c,b+="up"+A(v.length,2)+v),g&&(y=A(1,1)+A(B(p),4)+m,b+="uc"+A(y.length,2)+y);var E="";return E+="\n\0",E+=A(S,2),E+=u.magic,E+=A(a,2),E+=A(o,2),E+=A(x.crc32,4),E+=A(x.compressedSize,4),E+=A(x.uncompressedSize,4),E+=A(f.length,2),E+=A(b.length,2),{fileRecord:R.LOCAL_FILE_HEADER+E+f+b,dirRecord:R.CENTRAL_FILE_HEADER+A(C,2)+E+A(p.length,2)+"\0\0\0\0"+A(z,4)+A(n,4)+f+b+p}}var I=e("../utils"),i=e("../stream/GenericWorker"),O=e("../utf8"),B=e("../crc32"),R=e("../signature");function s(e,t,r,n){i.call(this,"ZipFileWorker"),this.bytesWritten=0,this.zipComment=t,this.zipPlatform=r,this.encodeFileName=n,this.streamFiles=e,this.accumulate=!1,this.contentBuffer=[],this.dirRecords=[],this.currentSourceOffset=0,this.entriesCount=0,this.currentFile=null,this._sources=[]}I.inherits(s,i),s.prototype.push=function(e){var t=e.meta.percent||0,r=this.entriesCount,n=this._sources.length;this.accumulate?this.contentBuffer.push(e):(this.bytesWritten+=e.data.length,i.prototype.push.call(this,{data:e.data,meta:{currentFile:this.currentFile,percent:r?(t+100*(r-n-1))/r:100}}))},s.prototype.openedSource=function(e){this.currentSourceOffset=this.bytesWritten,this.currentFile=e.file.name;var t=this.streamFiles&&!e.file.dir;if(t){var r=n(e,t,!1,this.currentSourceOffset,this.zipPlatform,this.encodeFileName);this.push({data:r.fileRecord,meta:{percent:0}})}else this.accumulate=!0},s.prototype.closedSource=function(e){this.accumulate=!1;var t=this.streamFiles&&!e.file.dir,r=n(e,t,!0,this.currentSourceOffset,this.zipPlatform,this.encodeFileName);if(this.dirRecords.push(r.dirRecord),t)this.push({data:function(e){return R.DATA_DESCRIPTOR+A(e.crc32,4)+A(e.compressedSize,4)+A(e.uncompressedSize,4)}(e),meta:{percent:100}});else for(this.push({data:r.fileRecord,meta:{percent:0}});this.contentBuffer.length;)this.push(this.contentBuffer.shift());this.currentFile=null},s.prototype.flush=function(){for(var e=this.bytesWritten,t=0;t=this.index;t--)r=(r<<8)+this.byteAt(t);return this.index+=e,r},readString:function(e){return n.transformTo("string",this.readData(e))},readData:function(){},lastIndexOfSignature:function(){},readAndCheckSignature:function(){},readDate:function(){var e=this.readInt(4);return new Date(Date.UTC(1980+(e>>25&127),(e>>21&15)-1,e>>16&31,e>>11&31,e>>5&63,(31&e)<<1))}},t.exports=i},{"../utils":32}],19:[function(e,t,r){"use strict";var n=e("./Uint8ArrayReader");function i(e){n.call(this,e)}e("../utils").inherits(i,n),i.prototype.readData=function(e){this.checkOffset(e);var t=this.data.slice(this.zero+this.index,this.zero+this.index+e);return this.index+=e,t},t.exports=i},{"../utils":32,"./Uint8ArrayReader":21}],20:[function(e,t,r){"use strict";var n=e("./DataReader");function i(e){n.call(this,e)}e("../utils").inherits(i,n),i.prototype.byteAt=function(e){return this.data.charCodeAt(this.zero+e)},i.prototype.lastIndexOfSignature=function(e){return this.data.lastIndexOf(e)-this.zero},i.prototype.readAndCheckSignature=function(e){return e===this.readData(4)},i.prototype.readData=function(e){this.checkOffset(e);var t=this.data.slice(this.zero+this.index,this.zero+this.index+e);return this.index+=e,t},t.exports=i},{"../utils":32,"./DataReader":18}],21:[function(e,t,r){"use strict";var n=e("./ArrayReader");function i(e){n.call(this,e)}e("../utils").inherits(i,n),i.prototype.readData=function(e){if(this.checkOffset(e),0===e)return new Uint8Array(0);var t=this.data.subarray(this.zero+this.index,this.zero+this.index+e);return this.index+=e,t},t.exports=i},{"../utils":32,"./ArrayReader":17}],22:[function(e,t,r){"use strict";var n=e("../utils"),i=e("../support"),s=e("./ArrayReader"),a=e("./StringReader"),o=e("./NodeBufferReader"),h=e("./Uint8ArrayReader");t.exports=function(e){var t=n.getTypeOf(e);return n.checkSupport(t),"string"!==t||i.uint8array?"nodebuffer"===t?new o(e):i.uint8array?new h(n.transformTo("uint8array",e)):new s(n.transformTo("array",e)):new a(e)}},{"../support":30,"../utils":32,"./ArrayReader":17,"./NodeBufferReader":19,"./StringReader":20,"./Uint8ArrayReader":21}],23:[function(e,t,r){"use strict";r.LOCAL_FILE_HEADER="PK",r.CENTRAL_FILE_HEADER="PK",r.CENTRAL_DIRECTORY_END="PK",r.ZIP64_CENTRAL_DIRECTORY_LOCATOR="PK",r.ZIP64_CENTRAL_DIRECTORY_END="PK",r.DATA_DESCRIPTOR="PK\b"},{}],24:[function(e,t,r){"use strict";var n=e("./GenericWorker"),i=e("../utils");function s(e){n.call(this,"ConvertWorker to "+e),this.destType=e}i.inherits(s,n),s.prototype.processChunk=function(e){this.push({data:i.transformTo(this.destType,e.data),meta:e.meta})},t.exports=s},{"../utils":32,"./GenericWorker":28}],25:[function(e,t,r){"use strict";var n=e("./GenericWorker"),i=e("../crc32");function s(){n.call(this,"Crc32Probe"),this.withStreamInfo("crc32",0)}e("../utils").inherits(s,n),s.prototype.processChunk=function(e){this.streamInfo.crc32=i(e.data,this.streamInfo.crc32||0),this.push(e)},t.exports=s},{"../crc32":4,"../utils":32,"./GenericWorker":28}],26:[function(e,t,r){"use strict";var n=e("../utils"),i=e("./GenericWorker");function s(e){i.call(this,"DataLengthProbe for "+e),this.propName=e,this.withStreamInfo(e,0)}n.inherits(s,i),s.prototype.processChunk=function(e){if(e){var t=this.streamInfo[this.propName]||0;this.streamInfo[this.propName]=t+e.data.length}i.prototype.processChunk.call(this,e)},t.exports=s},{"../utils":32,"./GenericWorker":28}],27:[function(e,t,r){"use strict";var n=e("../utils"),i=e("./GenericWorker");function s(e){i.call(this,"DataWorker");var t=this;this.dataIsReady=!1,this.index=0,this.max=0,this.data=null,this.type="",this._tickScheduled=!1,e.then(function(e){t.dataIsReady=!0,t.data=e,t.max=e&&e.length||0,t.type=n.getTypeOf(e),t.isPaused||t._tickAndRepeat()},function(e){t.error(e)})}n.inherits(s,i),s.prototype.cleanUp=function(){i.prototype.cleanUp.call(this),this.data=null},s.prototype.resume=function(){return!!i.prototype.resume.call(this)&&(!this._tickScheduled&&this.dataIsReady&&(this._tickScheduled=!0,n.delay(this._tickAndRepeat,[],this)),!0)},s.prototype._tickAndRepeat=function(){this._tickScheduled=!1,this.isPaused||this.isFinished||(this._tick(),this.isFinished||(n.delay(this._tickAndRepeat,[],this),this._tickScheduled=!0))},s.prototype._tick=function(){if(this.isPaused||this.isFinished)return!1;var e=null,t=Math.min(this.max,this.index+16384);if(this.index>=this.max)return this.end();switch(this.type){case"string":e=this.data.substring(this.index,t);break;case"uint8array":e=this.data.subarray(this.index,t);break;case"array":case"nodebuffer":e=this.data.slice(this.index,t)}return this.index=t,this.push({data:e,meta:{percent:this.max?this.index/this.max*100:0}})},t.exports=s},{"../utils":32,"./GenericWorker":28}],28:[function(e,t,r){"use strict";function n(e){this.name=e||"default",this.streamInfo={},this.generatedError=null,this.extraStreamInfo={},this.isPaused=!0,this.isFinished=!1,this.isLocked=!1,this._listeners={data:[],end:[],error:[]},this.previous=null}n.prototype={push:function(e){this.emit("data",e)},end:function(){if(this.isFinished)return!1;this.flush();try{this.emit("end"),this.cleanUp(),this.isFinished=!0}catch(e){this.emit("error",e)}return!0},error:function(e){return!this.isFinished&&(this.isPaused?this.generatedError=e:(this.isFinished=!0,this.emit("error",e),this.previous&&this.previous.error(e),this.cleanUp()),!0)},on:function(e,t){return this._listeners[e].push(t),this},cleanUp:function(){this.streamInfo=this.generatedError=this.extraStreamInfo=null,this._listeners=[]},emit:function(e,t){if(this._listeners[e])for(var r=0;r "+e:e}},t.exports=n},{}],29:[function(e,t,r){"use strict";var h=e("../utils"),i=e("./ConvertWorker"),s=e("./GenericWorker"),u=e("../base64"),n=e("../support"),a=e("../external"),o=null;if(n.nodestream)try{o=e("../nodejs/NodejsStreamOutputAdapter")}catch(e){}function l(e,o){return new a.Promise(function(t,r){var n=[],i=e._internalType,s=e._outputType,a=e._mimeType;e.on("data",function(e,t){n.push(e),o&&o(t)}).on("error",function(e){n=[],r(e)}).on("end",function(){try{var e=function(e,t,r){switch(e){case"blob":return h.newBlob(h.transformTo("arraybuffer",t),r);case"base64":return u.encode(t);default:return h.transformTo(e,t)}}(s,function(e,t){var r,n=0,i=null,s=0;for(r=0;r>>6:(r<65536?t[s++]=224|r>>>12:(t[s++]=240|r>>>18,t[s++]=128|r>>>12&63),t[s++]=128|r>>>6&63),t[s++]=128|63&r);return t}(e)},s.utf8decode=function(e){return h.nodebuffer?o.transformTo("nodebuffer",e).toString("utf-8"):function(e){var t,r,n,i,s=e.length,a=new Array(2*s);for(t=r=0;t>10&1023,a[r++]=56320|1023&n)}return a.length!==r&&(a.subarray?a=a.subarray(0,r):a.length=r),o.applyFromCharCode(a)}(e=o.transformTo(h.uint8array?"uint8array":"array",e))},o.inherits(a,n),a.prototype.processChunk=function(e){var t=o.transformTo(h.uint8array?"uint8array":"array",e.data);if(this.leftOver&&this.leftOver.length){if(h.uint8array){var r=t;(t=new Uint8Array(r.length+this.leftOver.length)).set(this.leftOver,0),t.set(r,this.leftOver.length)}else t=this.leftOver.concat(t);this.leftOver=null}var n=function(e,t){var r;for((t=t||e.length)>e.length&&(t=e.length),r=t-1;0<=r&&128==(192&e[r]);)r--;return r<0?t:0===r?t:r+u[e[r]]>t?r:t}(t),i=t;n!==t.length&&(h.uint8array?(i=t.subarray(0,n),this.leftOver=t.subarray(n,t.length)):(i=t.slice(0,n),this.leftOver=t.slice(n,t.length))),this.push({data:s.utf8decode(i),meta:e.meta})},a.prototype.flush=function(){this.leftOver&&this.leftOver.length&&(this.push({data:s.utf8decode(this.leftOver),meta:{}}),this.leftOver=null)},s.Utf8DecodeWorker=a,o.inherits(l,n),l.prototype.processChunk=function(e){this.push({data:s.utf8encode(e.data),meta:e.meta})},s.Utf8EncodeWorker=l},{"./nodejsUtils":14,"./stream/GenericWorker":28,"./support":30,"./utils":32}],32:[function(e,t,a){"use strict";var o=e("./support"),h=e("./base64"),r=e("./nodejsUtils"),u=e("./external");function n(e){return e}function l(e,t){for(var r=0;r>8;this.dir=!!(16&this.externalFileAttributes),0==e&&(this.dosPermissions=63&this.externalFileAttributes),3==e&&(this.unixPermissions=this.externalFileAttributes>>16&65535),this.dir||"/"!==this.fileNameStr.slice(-1)||(this.dir=!0)},parseZIP64ExtraField:function(){if(this.extraFields[1]){var e=n(this.extraFields[1].value);this.uncompressedSize===s.MAX_VALUE_32BITS&&(this.uncompressedSize=e.readInt(8)),this.compressedSize===s.MAX_VALUE_32BITS&&(this.compressedSize=e.readInt(8)),this.localHeaderOffset===s.MAX_VALUE_32BITS&&(this.localHeaderOffset=e.readInt(8)),this.diskNumberStart===s.MAX_VALUE_32BITS&&(this.diskNumberStart=e.readInt(4))}},readExtraFields:function(e){var t,r,n,i=e.index+this.extraFieldsLength;for(this.extraFields||(this.extraFields={});e.index+4>>6:(r<65536?t[s++]=224|r>>>12:(t[s++]=240|r>>>18,t[s++]=128|r>>>12&63),t[s++]=128|r>>>6&63),t[s++]=128|63&r);return t},r.buf2binstring=function(e){return l(e,e.length)},r.binstring2buf=function(e){for(var t=new h.Buf8(e.length),r=0,n=t.length;r>10&1023,o[n++]=56320|1023&i)}return l(o,n)},r.utf8border=function(e,t){var r;for((t=t||e.length)>e.length&&(t=e.length),r=t-1;0<=r&&128==(192&e[r]);)r--;return r<0?t:0===r?t:r+u[e[r]]>t?r:t}},{"./common":41}],43:[function(e,t,r){"use strict";t.exports=function(e,t,r,n){for(var i=65535&e|0,s=e>>>16&65535|0,a=0;0!==r;){for(r-=a=2e3>>1:e>>>1;t[r]=e}return t}();t.exports=function(e,t,r,n){var i=o,s=n+r;e^=-1;for(var a=n;a>>8^i[255&(e^t[a])];return-1^e}},{}],46:[function(e,t,r){"use strict";var h,c=e("../utils/common"),u=e("./trees"),d=e("./adler32"),p=e("./crc32"),n=e("./messages"),l=0,f=4,m=0,_=-2,g=-1,b=4,i=2,v=8,y=9,s=286,a=30,o=19,w=2*s+1,k=15,x=3,S=258,z=S+x+1,C=42,E=113,A=1,I=2,O=3,B=4;function R(e,t){return e.msg=n[t],t}function T(e){return(e<<1)-(4e.avail_out&&(r=e.avail_out),0!==r&&(c.arraySet(e.output,t.pending_buf,t.pending_out,r,e.next_out),e.next_out+=r,t.pending_out+=r,e.total_out+=r,e.avail_out-=r,t.pending-=r,0===t.pending&&(t.pending_out=0))}function N(e,t){u._tr_flush_block(e,0<=e.block_start?e.block_start:-1,e.strstart-e.block_start,t),e.block_start=e.strstart,F(e.strm)}function U(e,t){e.pending_buf[e.pending++]=t}function P(e,t){e.pending_buf[e.pending++]=t>>>8&255,e.pending_buf[e.pending++]=255&t}function L(e,t){var r,n,i=e.max_chain_length,s=e.strstart,a=e.prev_length,o=e.nice_match,h=e.strstart>e.w_size-z?e.strstart-(e.w_size-z):0,u=e.window,l=e.w_mask,f=e.prev,c=e.strstart+S,d=u[s+a-1],p=u[s+a];e.prev_length>=e.good_match&&(i>>=2),o>e.lookahead&&(o=e.lookahead);do{if(u[(r=t)+a]===p&&u[r+a-1]===d&&u[r]===u[s]&&u[++r]===u[s+1]){s+=2,r++;do{}while(u[++s]===u[++r]&&u[++s]===u[++r]&&u[++s]===u[++r]&&u[++s]===u[++r]&&u[++s]===u[++r]&&u[++s]===u[++r]&&u[++s]===u[++r]&&u[++s]===u[++r]&&sh&&0!=--i);return a<=e.lookahead?a:e.lookahead}function j(e){var t,r,n,i,s,a,o,h,u,l,f=e.w_size;do{if(i=e.window_size-e.lookahead-e.strstart,e.strstart>=f+(f-z)){for(c.arraySet(e.window,e.window,f,f,0),e.match_start-=f,e.strstart-=f,e.block_start-=f,t=r=e.hash_size;n=e.head[--t],e.head[t]=f<=n?n-f:0,--r;);for(t=r=f;n=e.prev[--t],e.prev[t]=f<=n?n-f:0,--r;);i+=f}if(0===e.strm.avail_in)break;if(a=e.strm,o=e.window,h=e.strstart+e.lookahead,u=i,l=void 0,l=a.avail_in,u=x)for(s=e.strstart-e.insert,e.ins_h=e.window[s],e.ins_h=(e.ins_h<=x&&(e.ins_h=(e.ins_h<=x)if(n=u._tr_tally(e,e.strstart-e.match_start,e.match_length-x),e.lookahead-=e.match_length,e.match_length<=e.max_lazy_match&&e.lookahead>=x){for(e.match_length--;e.strstart++,e.ins_h=(e.ins_h<=x&&(e.ins_h=(e.ins_h<=x&&e.match_length<=e.prev_length){for(i=e.strstart+e.lookahead-x,n=u._tr_tally(e,e.strstart-1-e.prev_match,e.prev_length-x),e.lookahead-=e.prev_length-1,e.prev_length-=2;++e.strstart<=i&&(e.ins_h=(e.ins_h<e.pending_buf_size-5&&(r=e.pending_buf_size-5);;){if(e.lookahead<=1){if(j(e),0===e.lookahead&&t===l)return A;if(0===e.lookahead)break}e.strstart+=e.lookahead,e.lookahead=0;var n=e.block_start+r;if((0===e.strstart||e.strstart>=n)&&(e.lookahead=e.strstart-n,e.strstart=n,N(e,!1),0===e.strm.avail_out))return A;if(e.strstart-e.block_start>=e.w_size-z&&(N(e,!1),0===e.strm.avail_out))return A}return e.insert=0,t===f?(N(e,!0),0===e.strm.avail_out?O:B):(e.strstart>e.block_start&&(N(e,!1),e.strm.avail_out),A)}),new M(4,4,8,4,Z),new M(4,5,16,8,Z),new M(4,6,32,32,Z),new M(4,4,16,16,W),new M(8,16,32,32,W),new M(8,16,128,128,W),new M(8,32,128,256,W),new M(32,128,258,1024,W),new M(32,258,258,4096,W)],r.deflateInit=function(e,t){return Y(e,t,v,15,8,0)},r.deflateInit2=Y,r.deflateReset=K,r.deflateResetKeep=G,r.deflateSetHeader=function(e,t){return e&&e.state?2!==e.state.wrap?_:(e.state.gzhead=t,m):_},r.deflate=function(e,t){var r,n,i,s;if(!e||!e.state||5>8&255),U(n,n.gzhead.time>>16&255),U(n,n.gzhead.time>>24&255),U(n,9===n.level?2:2<=n.strategy||n.level<2?4:0),U(n,255&n.gzhead.os),n.gzhead.extra&&n.gzhead.extra.length&&(U(n,255&n.gzhead.extra.length),U(n,n.gzhead.extra.length>>8&255)),n.gzhead.hcrc&&(e.adler=p(e.adler,n.pending_buf,n.pending,0)),n.gzindex=0,n.status=69):(U(n,0),U(n,0),U(n,0),U(n,0),U(n,0),U(n,9===n.level?2:2<=n.strategy||n.level<2?4:0),U(n,3),n.status=E);else{var a=v+(n.w_bits-8<<4)<<8;a|=(2<=n.strategy||n.level<2?0:n.level<6?1:6===n.level?2:3)<<6,0!==n.strstart&&(a|=32),a+=31-a%31,n.status=E,P(n,a),0!==n.strstart&&(P(n,e.adler>>>16),P(n,65535&e.adler)),e.adler=1}if(69===n.status)if(n.gzhead.extra){for(i=n.pending;n.gzindex<(65535&n.gzhead.extra.length)&&(n.pending!==n.pending_buf_size||(n.gzhead.hcrc&&n.pending>i&&(e.adler=p(e.adler,n.pending_buf,n.pending-i,i)),F(e),i=n.pending,n.pending!==n.pending_buf_size));)U(n,255&n.gzhead.extra[n.gzindex]),n.gzindex++;n.gzhead.hcrc&&n.pending>i&&(e.adler=p(e.adler,n.pending_buf,n.pending-i,i)),n.gzindex===n.gzhead.extra.length&&(n.gzindex=0,n.status=73)}else n.status=73;if(73===n.status)if(n.gzhead.name){i=n.pending;do{if(n.pending===n.pending_buf_size&&(n.gzhead.hcrc&&n.pending>i&&(e.adler=p(e.adler,n.pending_buf,n.pending-i,i)),F(e),i=n.pending,n.pending===n.pending_buf_size)){s=1;break}s=n.gzindexi&&(e.adler=p(e.adler,n.pending_buf,n.pending-i,i)),0===s&&(n.gzindex=0,n.status=91)}else n.status=91;if(91===n.status)if(n.gzhead.comment){i=n.pending;do{if(n.pending===n.pending_buf_size&&(n.gzhead.hcrc&&n.pending>i&&(e.adler=p(e.adler,n.pending_buf,n.pending-i,i)),F(e),i=n.pending,n.pending===n.pending_buf_size)){s=1;break}s=n.gzindexi&&(e.adler=p(e.adler,n.pending_buf,n.pending-i,i)),0===s&&(n.status=103)}else n.status=103;if(103===n.status&&(n.gzhead.hcrc?(n.pending+2>n.pending_buf_size&&F(e),n.pending+2<=n.pending_buf_size&&(U(n,255&e.adler),U(n,e.adler>>8&255),e.adler=0,n.status=E)):n.status=E),0!==n.pending){if(F(e),0===e.avail_out)return n.last_flush=-1,m}else if(0===e.avail_in&&T(t)<=T(r)&&t!==f)return R(e,-5);if(666===n.status&&0!==e.avail_in)return R(e,-5);if(0!==e.avail_in||0!==n.lookahead||t!==l&&666!==n.status){var o=2===n.strategy?function(e,t){for(var r;;){if(0===e.lookahead&&(j(e),0===e.lookahead)){if(t===l)return A;break}if(e.match_length=0,r=u._tr_tally(e,0,e.window[e.strstart]),e.lookahead--,e.strstart++,r&&(N(e,!1),0===e.strm.avail_out))return A}return e.insert=0,t===f?(N(e,!0),0===e.strm.avail_out?O:B):e.last_lit&&(N(e,!1),0===e.strm.avail_out)?A:I}(n,t):3===n.strategy?function(e,t){for(var r,n,i,s,a=e.window;;){if(e.lookahead<=S){if(j(e),e.lookahead<=S&&t===l)return A;if(0===e.lookahead)break}if(e.match_length=0,e.lookahead>=x&&0e.lookahead&&(e.match_length=e.lookahead)}if(e.match_length>=x?(r=u._tr_tally(e,1,e.match_length-x),e.lookahead-=e.match_length,e.strstart+=e.match_length,e.match_length=0):(r=u._tr_tally(e,0,e.window[e.strstart]),e.lookahead--,e.strstart++),r&&(N(e,!1),0===e.strm.avail_out))return A}return e.insert=0,t===f?(N(e,!0),0===e.strm.avail_out?O:B):e.last_lit&&(N(e,!1),0===e.strm.avail_out)?A:I}(n,t):h[n.level].func(n,t);if(o!==O&&o!==B||(n.status=666),o===A||o===O)return 0===e.avail_out&&(n.last_flush=-1),m;if(o===I&&(1===t?u._tr_align(n):5!==t&&(u._tr_stored_block(n,0,0,!1),3===t&&(D(n.head),0===n.lookahead&&(n.strstart=0,n.block_start=0,n.insert=0))),F(e),0===e.avail_out))return n.last_flush=-1,m}return t!==f?m:n.wrap<=0?1:(2===n.wrap?(U(n,255&e.adler),U(n,e.adler>>8&255),U(n,e.adler>>16&255),U(n,e.adler>>24&255),U(n,255&e.total_in),U(n,e.total_in>>8&255),U(n,e.total_in>>16&255),U(n,e.total_in>>24&255)):(P(n,e.adler>>>16),P(n,65535&e.adler)),F(e),0=r.w_size&&(0===s&&(D(r.head),r.strstart=0,r.block_start=0,r.insert=0),u=new c.Buf8(r.w_size),c.arraySet(u,t,l-r.w_size,r.w_size,0),t=u,l=r.w_size),a=e.avail_in,o=e.next_in,h=e.input,e.avail_in=l,e.next_in=0,e.input=t,j(r);r.lookahead>=x;){for(n=r.strstart,i=r.lookahead-(x-1);r.ins_h=(r.ins_h<>>=y=v>>>24,p-=y,0===(y=v>>>16&255))C[s++]=65535&v;else{if(!(16&y)){if(0==(64&y)){v=m[(65535&v)+(d&(1<>>=y,p-=y),p<15&&(d+=z[n++]<>>=y=v>>>24,p-=y,!(16&(y=v>>>16&255))){if(0==(64&y)){v=_[(65535&v)+(d&(1<>>=y,p-=y,(y=s-a)>3,d&=(1<<(p-=w<<3))-1,e.next_in=n,e.next_out=s,e.avail_in=n>>24&255)+(e>>>8&65280)+((65280&e)<<8)+((255&e)<<24)}function s(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new I.Buf16(320),this.work=new I.Buf16(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function a(e){var t;return e&&e.state?(t=e.state,e.total_in=e.total_out=t.total=0,e.msg="",t.wrap&&(e.adler=1&t.wrap),t.mode=P,t.last=0,t.havedict=0,t.dmax=32768,t.head=null,t.hold=0,t.bits=0,t.lencode=t.lendyn=new I.Buf32(n),t.distcode=t.distdyn=new I.Buf32(i),t.sane=1,t.back=-1,N):U}function o(e){var t;return e&&e.state?((t=e.state).wsize=0,t.whave=0,t.wnext=0,a(e)):U}function h(e,t){var r,n;return e&&e.state?(n=e.state,t<0?(r=0,t=-t):(r=1+(t>>4),t<48&&(t&=15)),t&&(t<8||15=s.wsize?(I.arraySet(s.window,t,r-s.wsize,s.wsize,0),s.wnext=0,s.whave=s.wsize):(n<(i=s.wsize-s.wnext)&&(i=n),I.arraySet(s.window,t,r-n,i,s.wnext),(n-=i)?(I.arraySet(s.window,t,r-n,n,0),s.wnext=n,s.whave=s.wsize):(s.wnext+=i,s.wnext===s.wsize&&(s.wnext=0),s.whave>>8&255,r.check=B(r.check,E,2,0),l=u=0,r.mode=2;break}if(r.flags=0,r.head&&(r.head.done=!1),!(1&r.wrap)||(((255&u)<<8)+(u>>8))%31){e.msg="incorrect header check",r.mode=30;break}if(8!=(15&u)){e.msg="unknown compression method",r.mode=30;break}if(l-=4,k=8+(15&(u>>>=4)),0===r.wbits)r.wbits=k;else if(k>r.wbits){e.msg="invalid window size",r.mode=30;break}r.dmax=1<>8&1),512&r.flags&&(E[0]=255&u,E[1]=u>>>8&255,r.check=B(r.check,E,2,0)),l=u=0,r.mode=3;case 3:for(;l<32;){if(0===o)break e;o--,u+=n[s++]<>>8&255,E[2]=u>>>16&255,E[3]=u>>>24&255,r.check=B(r.check,E,4,0)),l=u=0,r.mode=4;case 4:for(;l<16;){if(0===o)break e;o--,u+=n[s++]<>8),512&r.flags&&(E[0]=255&u,E[1]=u>>>8&255,r.check=B(r.check,E,2,0)),l=u=0,r.mode=5;case 5:if(1024&r.flags){for(;l<16;){if(0===o)break e;o--,u+=n[s++]<>>8&255,r.check=B(r.check,E,2,0)),l=u=0}else r.head&&(r.head.extra=null);r.mode=6;case 6:if(1024&r.flags&&(o<(d=r.length)&&(d=o),d&&(r.head&&(k=r.head.extra_len-r.length,r.head.extra||(r.head.extra=new Array(r.head.extra_len)),I.arraySet(r.head.extra,n,s,d,k)),512&r.flags&&(r.check=B(r.check,n,d,s)),o-=d,s+=d,r.length-=d),r.length))break e;r.length=0,r.mode=7;case 7:if(2048&r.flags){if(0===o)break e;for(d=0;k=n[s+d++],r.head&&k&&r.length<65536&&(r.head.name+=String.fromCharCode(k)),k&&d>9&1,r.head.done=!0),e.adler=r.check=0,r.mode=12;break;case 10:for(;l<32;){if(0===o)break e;o--,u+=n[s++]<>>=7&l,l-=7&l,r.mode=27;break}for(;l<3;){if(0===o)break e;o--,u+=n[s++]<>>=1)){case 0:r.mode=14;break;case 1:if(j(r),r.mode=20,6!==t)break;u>>>=2,l-=2;break e;case 2:r.mode=17;break;case 3:e.msg="invalid block type",r.mode=30}u>>>=2,l-=2;break;case 14:for(u>>>=7&l,l-=7&l;l<32;){if(0===o)break e;o--,u+=n[s++]<>>16^65535)){e.msg="invalid stored block lengths",r.mode=30;break}if(r.length=65535&u,l=u=0,r.mode=15,6===t)break e;case 15:r.mode=16;case 16:if(d=r.length){if(o>>=5,l-=5,r.ndist=1+(31&u),u>>>=5,l-=5,r.ncode=4+(15&u),u>>>=4,l-=4,286>>=3,l-=3}for(;r.have<19;)r.lens[A[r.have++]]=0;if(r.lencode=r.lendyn,r.lenbits=7,S={bits:r.lenbits},x=T(0,r.lens,0,19,r.lencode,0,r.work,S),r.lenbits=S.bits,x){e.msg="invalid code lengths set",r.mode=30;break}r.have=0,r.mode=19;case 19:for(;r.have>>16&255,b=65535&C,!((_=C>>>24)<=l);){if(0===o)break e;o--,u+=n[s++]<>>=_,l-=_,r.lens[r.have++]=b;else{if(16===b){for(z=_+2;l>>=_,l-=_,0===r.have){e.msg="invalid bit length repeat",r.mode=30;break}k=r.lens[r.have-1],d=3+(3&u),u>>>=2,l-=2}else if(17===b){for(z=_+3;l>>=_)),u>>>=3,l-=3}else{for(z=_+7;l>>=_)),u>>>=7,l-=7}if(r.have+d>r.nlen+r.ndist){e.msg="invalid bit length repeat",r.mode=30;break}for(;d--;)r.lens[r.have++]=k}}if(30===r.mode)break;if(0===r.lens[256]){e.msg="invalid code -- missing end-of-block",r.mode=30;break}if(r.lenbits=9,S={bits:r.lenbits},x=T(D,r.lens,0,r.nlen,r.lencode,0,r.work,S),r.lenbits=S.bits,x){e.msg="invalid literal/lengths set",r.mode=30;break}if(r.distbits=6,r.distcode=r.distdyn,S={bits:r.distbits},x=T(F,r.lens,r.nlen,r.ndist,r.distcode,0,r.work,S),r.distbits=S.bits,x){e.msg="invalid distances set",r.mode=30;break}if(r.mode=20,6===t)break e;case 20:r.mode=21;case 21:if(6<=o&&258<=h){e.next_out=a,e.avail_out=h,e.next_in=s,e.avail_in=o,r.hold=u,r.bits=l,R(e,c),a=e.next_out,i=e.output,h=e.avail_out,s=e.next_in,n=e.input,o=e.avail_in,u=r.hold,l=r.bits,12===r.mode&&(r.back=-1);break}for(r.back=0;g=(C=r.lencode[u&(1<>>16&255,b=65535&C,!((_=C>>>24)<=l);){if(0===o)break e;o--,u+=n[s++]<>v)])>>>16&255,b=65535&C,!(v+(_=C>>>24)<=l);){if(0===o)break e;o--,u+=n[s++]<>>=v,l-=v,r.back+=v}if(u>>>=_,l-=_,r.back+=_,r.length=b,0===g){r.mode=26;break}if(32&g){r.back=-1,r.mode=12;break}if(64&g){e.msg="invalid literal/length code",r.mode=30;break}r.extra=15&g,r.mode=22;case 22:if(r.extra){for(z=r.extra;l>>=r.extra,l-=r.extra,r.back+=r.extra}r.was=r.length,r.mode=23;case 23:for(;g=(C=r.distcode[u&(1<>>16&255,b=65535&C,!((_=C>>>24)<=l);){if(0===o)break e;o--,u+=n[s++]<>v)])>>>16&255,b=65535&C,!(v+(_=C>>>24)<=l);){if(0===o)break e;o--,u+=n[s++]<>>=v,l-=v,r.back+=v}if(u>>>=_,l-=_,r.back+=_,64&g){e.msg="invalid distance code",r.mode=30;break}r.offset=b,r.extra=15&g,r.mode=24;case 24:if(r.extra){for(z=r.extra;l>>=r.extra,l-=r.extra,r.back+=r.extra}if(r.offset>r.dmax){e.msg="invalid distance too far back",r.mode=30;break}r.mode=25;case 25:if(0===h)break e;if(d=c-h,r.offset>d){if((d=r.offset-d)>r.whave&&r.sane){e.msg="invalid distance too far back",r.mode=30;break}p=d>r.wnext?(d-=r.wnext,r.wsize-d):r.wnext-d,d>r.length&&(d=r.length),m=r.window}else m=i,p=a-r.offset,d=r.length;for(hd?(m=R[T+a[v]],A[I+a[v]]):(m=96,0),h=1<>S)+(u-=h)]=p<<24|m<<16|_|0,0!==u;);for(h=1<>=1;if(0!==h?(E&=h-1,E+=h):E=0,v++,0==--O[b]){if(b===w)break;b=t[r+a[v]]}if(k>>7)]}function U(e,t){e.pending_buf[e.pending++]=255&t,e.pending_buf[e.pending++]=t>>>8&255}function P(e,t,r){e.bi_valid>d-r?(e.bi_buf|=t<>d-e.bi_valid,e.bi_valid+=r-d):(e.bi_buf|=t<>>=1,r<<=1,0<--t;);return r>>>1}function Z(e,t,r){var n,i,s=new Array(g+1),a=0;for(n=1;n<=g;n++)s[n]=a=a+r[n-1]<<1;for(i=0;i<=t;i++){var o=e[2*i+1];0!==o&&(e[2*i]=j(s[o]++,o))}}function W(e){var t;for(t=0;t>1;1<=r;r--)G(e,s,r);for(i=h;r=e.heap[1],e.heap[1]=e.heap[e.heap_len--],G(e,s,1),n=e.heap[1],e.heap[--e.heap_max]=r,e.heap[--e.heap_max]=n,s[2*i]=s[2*r]+s[2*n],e.depth[i]=(e.depth[r]>=e.depth[n]?e.depth[r]:e.depth[n])+1,s[2*r+1]=s[2*n+1]=i,e.heap[1]=i++,G(e,s,1),2<=e.heap_len;);e.heap[--e.heap_max]=e.heap[1],function(e,t){var r,n,i,s,a,o,h=t.dyn_tree,u=t.max_code,l=t.stat_desc.static_tree,f=t.stat_desc.has_stree,c=t.stat_desc.extra_bits,d=t.stat_desc.extra_base,p=t.stat_desc.max_length,m=0;for(s=0;s<=g;s++)e.bl_count[s]=0;for(h[2*e.heap[e.heap_max]+1]=0,r=e.heap_max+1;r<_;r++)p<(s=h[2*h[2*(n=e.heap[r])+1]+1]+1)&&(s=p,m++),h[2*n+1]=s,u>=7;n>>=1)if(1&r&&0!==e.dyn_ltree[2*t])return o;if(0!==e.dyn_ltree[18]||0!==e.dyn_ltree[20]||0!==e.dyn_ltree[26])return h;for(t=32;t>>3,(s=e.static_len+3+7>>>3)<=i&&(i=s)):i=s=r+5,r+4<=i&&-1!==t?J(e,t,r,n):4===e.strategy||s===i?(P(e,2+(n?1:0),3),K(e,z,C)):(P(e,4+(n?1:0),3),function(e,t,r,n){var i;for(P(e,t-257,5),P(e,r-1,5),P(e,n-4,4),i=0;i>>8&255,e.pending_buf[e.d_buf+2*e.last_lit+1]=255&t,e.pending_buf[e.l_buf+e.last_lit]=255&r,e.last_lit++,0===t?e.dyn_ltree[2*r]++:(e.matches++,t--,e.dyn_ltree[2*(A[r]+u+1)]++,e.dyn_dtree[2*N(t)]++),e.last_lit===e.lit_bufsize-1},r._tr_align=function(e){P(e,2,3),L(e,m,z),function(e){16===e.bi_valid?(U(e,e.bi_buf),e.bi_buf=0,e.bi_valid=0):8<=e.bi_valid&&(e.pending_buf[e.pending++]=255&e.bi_buf,e.bi_buf>>=8,e.bi_valid-=8)}(e)}},{"../utils/common":41}],53:[function(e,t,r){"use strict";t.exports=function(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0}},{}],54:[function(e,t,r){(function(e){!function(r,n){"use strict";if(!r.setImmediate){var i,s,t,a,o=1,h={},u=!1,l=r.document,e=Object.getPrototypeOf&&Object.getPrototypeOf(r);e=e&&e.setTimeout?e:r,i="[object process]"==={}.toString.call(r.process)?function(e){process.nextTick(function(){c(e)})}:function(){if(r.postMessage&&!r.importScripts){var e=!0,t=r.onmessage;return r.onmessage=function(){e=!1},r.postMessage("","*"),r.onmessage=t,e}}()?(a="setImmediate$"+Math.random()+"$",r.addEventListener?r.addEventListener("message",d,!1):r.attachEvent("onmessage",d),function(e){r.postMessage(a+e,"*")}):r.MessageChannel?((t=new MessageChannel).port1.onmessage=function(e){c(e.data)},function(e){t.port2.postMessage(e)}):l&&"onreadystatechange"in l.createElement("script")?(s=l.documentElement,function(e){var t=l.createElement("script");t.onreadystatechange=function(){c(e),t.onreadystatechange=null,s.removeChild(t),t=null},s.appendChild(t)}):function(e){setTimeout(c,0,e)},e.setImmediate=function(e){"function"!=typeof e&&(e=new Function(""+e));for(var t=new Array(arguments.length-1),r=0;r