Add issue No. 02 "Obsession" + reusable image pipeline

Content
- 100 new plates under content/posts/02/ — one recurring red-haired model
  across 10 editorial registers (Haute Couture, Film Noir, Boudoir,
  Avant-Garde, Minimalism, Baroque, Street Style, Surrealism, Monochrome,
  Nocturne), generated with flux-1.1-pro, face-swapped to a consistent
  identity (FaceFusion), and upscaled (Upscayl + Remacri, 3328x4992).
- content/issues/02/_index.md; issue 01 -> status archived; hugo.toml params
  (issueIds newest-first, issueNumber/Name/Season/Blurb).

Structure
- Plate bundles grouped by issue: content/posts/<issue>/<slug>/, with
  build.render:never stubs so /posts/<issue>/ isn't emitted. nginx 301s the
  legacy flat /posts/<slug>/ URLs to /posts/01/<slug>/. The /posts/ archive
  uses .RegularPagesRecursive.

Image pipeline (scripts/, data/ gitignored)
- generate-images.py  — Replicate flux-1.1-pro, 960x1440, idempotent.
- faceswap-images.py  — FaceFusion batch-run, one consistent face.
- upscale-images.py   — Upscayl + remacri-4x, long edge clamped to 4992.
- build-issue.py      — prompts JSON -> content/posts/<issue>/*/index.md.

Build
- CSS now compiled by Hugo's css.TailwindCSS (partials/css.html +
  templates.Defer); dropped the standalone Tailwind CLI step, concurrently,
  and the gitignored static/css/main.css. Requires Hugo >= 0.161; Dockerfile
  collapsed to a single hugomods/hugo:debian-node build stage.
  pnpm-workspace.yaml: preferSymlinkedExecutables + allowBuilds.

Front end
- Pagination 8 per page.
- Lightbox: brand mark and category link out; robust SPA back/forward
  (fetch before startViewTransition, single-flight guard, swallow the
  transition abort rejection, popstate re-renders / reopens the viewer).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DZPmxGywFnAhmYJB1eh9fm
This commit is contained in:
2026-08-29 21:11:24 +02:00
co-authored by Claude Sonnet 5
parent 1480f73a8f
commit 2dc7a0063f
432 changed files with 3195 additions and 830 deletions
+3 -1
View File
@@ -2,4 +2,6 @@ public/
resources/ resources/
node_modules/ node_modules/
.hugo_build.lock .hugo_build.lock
static/css/main.css hugo_stats.json
__pycache__/
data/
+40 -18
View File
@@ -5,16 +5,17 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## Commands ## Commands
```bash ```bash
pnpm dev # Tailwind watch + Hugo dev server in parallel pnpm install # installs @tailwindcss/cli; Hugo shells out to it
pnpm build # build:css then hugo --minify → public/ pnpm dev # hugo server -D (Hugo compiles Tailwind + hot-reloads)
pnpm build:css # Tailwind only → static/css/main.css pnpm build # hugo --minify → public/
pnpm watch:css # Tailwind watch (CSS only) python3 scripts/import-posts.py # Import issue 01 from ~/projects/ginger/posts.csv → content/posts/01/
hugo server -D # Hugo dev server (drafts included) python3 scripts/generate-images.py --prompts data/prompts/issue-NN.json --issue NN # Replicate flux-1.1-pro → content/posts/NN/<slug>/<slug>.png
hugo --minify # Production build python3 scripts/faceswap-images.py --issue NN --source ~/Bilder/palina.webp # FaceFusion: swap one consistent face into every plate (in place)
python3 scripts/import-posts.py # Import posts from ~/projects/ginger/posts.csv python3 scripts/upscale-images.py --issue NN # Upscayl + Remacri 4x → clamp to 4992px long edge (in place)
python3 scripts/build-issue.py --issue NN --prompts data/prompts/issue-NN.json # write content/posts/NN/<slug>/index.md
``` ```
CSS must be compiled before Hugo runs. `pnpm build` does both in order. In dev, `pnpm dev` runs both concurrently. Hugo (≥ 0.161) compiles Tailwind itself during the build — no separate CSS step.
## Architecture ## Architecture
@@ -22,12 +23,26 @@ CSS must be compiled before Hugo runs. `pnpm build` does both in order. In dev,
### CSS pipeline ### CSS pipeline
Tailwind reads `assets/css/main.css` and writes to `static/css/main.css` (gitignored — build artefact). The `@theme {}` block defines all design tokens (`--color-paper`, `--color-roux`, `--font-display`, etc.). Global resets are in `@layer base` so Tailwind utility classes correctly override them. `layouts/partials/css.html` runs `resources.Get "css/main.css" | css.TailwindCSS`
inside a `templates.Defer` block (invoked from `head.html`). Hugo shells out to
`node_modules/.bin/tailwindcss`, which scans `hugo_stats.json` (written each build
by `[build.buildStats]`, `@source`'d in `main.css`, mounted to
`assets/notwatching/` and cache-busted per `hugo.toml`). Dev serves unminified
`/css/main.css`; production emits a fingerprinted, SRI-hashed file.
`assets/css/main.css``@theme {}` defines all design tokens (`--color-paper`,
`--color-roux`, `--font-display`, …); global resets are in `@layer base` so
Tailwind utilities override them.
`pnpm-workspace.yaml` sets `preferSymlinkedExecutables: true` (Hugo rejects pnpm's
default shell shim for `tailwindcss`) and `allowBuilds` for `@parcel/watcher` (so
`pnpm run` doesn't fail on the ignored native build).
### Content model ### Content model
- `content/posts/<slug>/index.md` — page bundles; each has a `plate` number, `issues`, `categories` (single item), `tags`, `featured` flag, and a `.png` image resource. - `content/posts/<issue>/<slug>/index.md` — page bundles grouped by issue dir (`01/`, `02/`, …); each has a `plate` number, `issues`, `categories` (single item), `tags`, `featured` flag, and a `.png` image resource. Permalink is `/posts/<issue>/<slug>/`.
- `content/issues/<id>/_index.md`branch bundle for an issue; metadata (`title`, `description`, `issueNumber`, `season`, `status`) drives the homepage hero and issue list page. - `content/posts/<issue>/_index.md``build.render: never`; suppresses the intermediate `/posts/<issue>/` list page (the per-issue landing page is the taxonomy term `/issues/<issue>/`).
- `content/issues/<id>/_index.md` — branch bundle for an issue; metadata (`title`, `description`, `issueNumber`, `season`, `status`) drives the homepage hero and issue list page. Only one issue should have `status: "current"`.
- `content/imprint.md` — standalone page using `layout: imprint`. - `content/imprint.md` — standalone page using `layout: imprint`.
Taxonomies: `categories`, `tags`, `issues` (defined in `hugo.toml`). Taxonomies: `categories`, `tags`, `issues` (defined in `hugo.toml`).
@@ -36,7 +51,7 @@ Taxonomies: `categories`, `tags`, `issues` (defined in `hugo.toml`).
``` ```
layouts/baseof.html ← shell: head, header, main, footer, lightbox, roux-data JSON layouts/baseof.html ← shell: head, header, main, footer, lightbox, roux-data JSON
layouts/index.html ← homepage: current-issue hero + 5 featured plates layouts/index.html ← homepage: current-issue hero + up to 5 featured plates from that issue
layouts/_default/list.html ← two branches: kind="taxonomy" (term cards) | kind="term"/section (paginated post grid) layouts/_default/list.html ← two branches: kind="taxonomy" (term cards) | kind="term"/section (paginated post grid)
layouts/_default/single.html ← post plate page (triggers lightbox via window.__ROUX_OPEN_SLUG) layouts/_default/single.html ← post plate page (triggers lightbox via window.__ROUX_OPEN_SLUG)
layouts/_default/imprint.html← prose page layout layouts/_default/imprint.html← prose page layout
@@ -45,7 +60,7 @@ layouts/issues/terms.html ← issue index, reads issueIds from hugo.toml para
layouts/404.html ← editorial 404 page layouts/404.html ← editorial 404 page
``` ```
Key partials: `header.html`, `footer.html`, `card.html` (reusable post card), `lightbox.html`, `pagination.html`, `logo.html`. Key partials: `head.html`, `css.html` (Tailwind build, see CSS pipeline), `header.html`, `footer.html`, `card.html` (reusable post card), `lightbox.html`, `pagination.html`, `logo.html`.
### JavaScript (`static/js/app.js`) ### JavaScript (`static/js/app.js`)
@@ -58,16 +73,23 @@ Responsibilities:
### Data flow: homepage featured plates ### Data flow: homepage featured plates
The homepage shows exactly the posts with `featured: true` in frontmatter. Mark posts via `featured: true`; the template filters with `where .Site.RegularPages ".Params.featured" true`. The homepage hero resolves the current issue via `.Site.Params.issueNumber``GetPage "/issues/<num>"`. The featured grid shows up to 5 posts with `featured: true` **within that current issue** (`where $plates ".Params.featured" true | first 5`), so each issue's prompts file flags its own 5.
### Content import ### Content pipeline
`scripts/import-posts.py` reads `~/projects/ginger/posts.csv` and `~/projects/ginger/images/final/selected/`. It creates/updates page bundles deterministically (sorted by filename → stable plate numbers). Run it from the repo root after updating the upstream CSV or image set. - `scripts/import-posts.py` — issue 01 only; reads `~/projects/ginger/posts.csv` + `~/projects/ginger/images/final/selected/`, writes `content/posts/01/` deterministically (sorted by filename → stable plate numbers).
- `scripts/generate-images.py` — reusable Replicate generator. `--prompts <json> --issue NN`; token from `$REPLICATE_API_TOKEN` or `~/.env`; default model `black-forest-labs/flux-1.1-pro`, 960×1440 PNG (custom aspect); idempotent (skips existing), writes a `<prompts>.generated.json` provenance manifest.
- `scripts/faceswap-images.py``--issue NN --source <face>` (default `~/Bilder/palina.webp`). Runs FaceFusion `batch-run` (via `~/Projekte/facefusion/.venv`) once over the whole issue, swapping in one consistent face; writes back in place. `--enhance` adds the face_enhancer pass. Idempotent via `issue-NN.faceswap.json` keyed on the source hash.
- `scripts/upscale-images.py``--issue NN`. Runs `upscayl-bin` (`/usr/share/upscayl/bin`) with the `remacri-4x` model once over the issue, then clamps the long edge to `--max-edge` (default 4992 ≈ issue-01 sources) with ImageMagick; writes back in place. Idempotent via `issue-NN.upscale.json`.
- `scripts/build-issue.py` — generic; reads the same prompts JSON, writes `content/posts/NN/<slug>/index.md` (plate numbers by stable slug sort), `featured` sourced from the JSON.
- `data/prompts/issue-NN.json` — array of `{slug, title, category, tags, description, prompt, featured?}`. `data/` is gitignored: the prompts file and the `*.generated/faceswap/upscale.json` manifests are local pipeline scratch, not committed. The plate bundles under `content/posts/NN/` are the tracked output.
Full pipeline order: `generate-images``faceswap-images``upscale-images``build-issue`. All four operate on `content/posts/NN/<slug>/<slug>.png` in place and are individually idempotent; pass `--out DIR` to any of the image scripts to stage results without touching the bundles (that run is then untracked).
### Hugo params (hugo.toml) ### Hugo params (hugo.toml)
`issueNumber`, `issueName`, `issueSeason`, `issueBlurb` are fallback values used when `$.Site.GetPage "/issues/01"` returns nil. `issueIds` drives the issues terms page. `umamiSrc`/`umamiId` are injected only in production (`hugo.IsProduction`). `issueNumber`, `issueName`, `issueSeason`, `issueBlurb` are fallback values used when `$.Site.GetPage "/issues/<issueNumber>"` returns nil. `issueIds` (newest-first) drives the issues terms page order. `umamiSrc`/`umamiId` are injected only in production (`hugo.IsProduction`).
### nginx ### nginx
`nginx.conf` at repo root is the production server config (used in Docker). `error_page 404 /404.html` is already wired. `nginx.conf` at repo root is the production server config (used in Docker). `error_page 404 /404.html` is already wired. A `location ~ ^/posts/(?!0[12]/)…` block 301-redirects the legacy flat issue-01 plate URLs (`/posts/<slug>/`) to their new home under `/posts/01/<slug>/`; extend the negative-lookahead when adding issue 03+.
+12 -17
View File
@@ -1,23 +1,18 @@
### Stage 1: Build CSS with Tailwind v4 ### Stage 1: Build the site with Hugo Extended + Node (Tailwind runs inside Hugo)
FROM node:20-alpine AS tailwind FROM hugomods/hugo:debian-node-0.165.0 AS hugo
WORKDIR /build
COPY package.json pnpm-lock.yaml* ./
RUN npm install -g pnpm && pnpm install --frozen-lockfile
COPY assets/css ./assets/css
COPY layouts ./layouts
RUN pnpm build:css
### Stage 2: Build site with Hugo Extended
FROM hugomods/hugo:exts-0.154.3 AS hugo
WORKDIR /site WORKDIR /site
# Copy everything EXCEPT node_modules # Install JS deps first so this layer caches independently of content changes.
COPY . . # Hugo's css.TailwindCSS execs node_modules/.bin/tailwindcss during the build;
COPY --from=tailwind /build/static/css/main.css static/css/main.css # pnpm-workspace.yaml sets preferSymlinkedExecutables so that shim is a symlink
# Content images are baked in via the import script; make sure they exist # Hugo accepts.
RUN hugo --minify --environment production COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
RUN npm install -g pnpm && pnpm install --frozen-lockfile
### Stage 3: Serve with nginx COPY . .
RUN hugo --minify --gc --environment production
### Stage 2: Serve with nginx
FROM nginx:1.27-alpine FROM nginx:1.27-alpine
COPY --from=hugo /site/public /usr/share/nginx/html COPY --from=hugo /site/public /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf COPY nginx.conf /etc/nginx/conf.d/default.conf
+54 -12
View File
@@ -11,8 +11,8 @@ Editorial, couture, beauty and backstage plates.
| Layer | Tool | | Layer | Tool |
|---|---| |---|---|
| Static site generator | Hugo Extended | | Static site generator | Hugo Extended (≥ 0.161) |
| CSS | Tailwind CSS v4 | | CSS | Tailwind CSS v4, compiled by Hugo's `css.TailwindCSS` |
| JavaScript | Vanilla (no framework) | | JavaScript | Vanilla (no framework) |
| Package manager | pnpm | | Package manager | pnpm |
| Server | nginx (Docker) | | Server | nginx (Docker) |
@@ -20,32 +20,66 @@ Editorial, couture, beauty and backstage plates.
## Development ## Development
```bash ```bash
pnpm install pnpm install # installs @tailwindcss/cli (Hugo shells out to it)
pnpm dev # Tailwind watch + Hugo dev server (http://localhost:1313) pnpm dev # hugo server -D → http://localhost:1313
``` ```
Hugo builds the CSS itself via `css.TailwindCSS` (see `layouts/partials/css.html`),
watches `assets/`, and hot-reloads. There is no separate CSS build step or watcher.
Requires `node` on `PATH` — Hugo execs `node_modules/.bin/tailwindcss`.
## Build ## Build
```bash ```bash
pnpm build # compile CSS → hugo --minify → public/ pnpm build # hugo --minify → public/
``` ```
The compiled CSS at `static/css/main.css` is a build artefact and gitignored. Always run `pnpm build:css` (or `pnpm build`) before committing changes that affect Tailwind output. CSS is emitted as a fingerprinted, integrity-hashed resource under `public/css/`;
`hugo_stats.json` (the class list Tailwind scans) is generated on every build and
gitignored.
`pnpm-workspace.yaml` sets `preferSymlinkedExecutables: true` so pnpm links
`node_modules/.bin/tailwindcss` as a symlink — Hugo rejects pnpm's default shell
shim (`binary "tailwindcss" is not a Node.js script`).
## Content ## Content
Posts live in `content/posts/<slug>/` as Hugo page bundles. Each bundle contains: Posts live in `content/posts/<issue>/<slug>/` as Hugo page bundles (e.g.
`content/posts/01/…`, `content/posts/02/…`). Each bundle contains:
- `index.md` — frontmatter with `plate`, `title`, `description`, `categories`, `tags`, `issues`, optional `featured: true` - `index.md` — frontmatter with `plate`, `title`, `description`, `categories`, `tags`, `issues`, optional `featured: true`
- `<slug>.png` — the plate image (used for thumbnails, lightbox, og:image) - `<slug>.png` — the plate image (used for thumbnails, lightbox, og:image)
Issues are defined in `content/issues/<id>/_index.md`. `content/posts/<issue>/_index.md` carries `build.render: never` so only `/posts/<issue>/<slug>/`
pages are emitted — the per-issue landing page is the taxonomy term at `/issues/<issue>/`.
Issue membership is the `issues` taxonomy; each issue also has a branch bundle at
`content/issues/<id>/_index.md` (`title`, `description`, `issueNumber`, `season`, `status`).
### Importing posts ### Adding a new issue
Content is sourced from `~/projects/ginger/posts.csv` and matching images in `~/projects/ginger/images/final/selected/`: 1. Write `data/prompts/issue-NN.json` — an array of `{slug, title, category, tags, description, prompt, featured?}`.
2. Generate images: `python3 scripts/generate-images.py --prompts data/prompts/issue-NN.json --issue NN`
(Replicate `flux-1.1-pro` by default; token from `$REPLICATE_API_TOKEN` or `~/.env`).
3. Face-swap one consistent model into every plate:
`python3 scripts/faceswap-images.py --issue NN --source ~/Bilder/palina.webp`
(FaceFusion at `~/Projekte/facefusion`; add `--enhance` for a sharper face pass).
4. Upscale: `python3 scripts/upscale-images.py --issue NN`
(Upscayl + the `remacri-4x` model, then clamped to a 4992 px long edge; `--scale 2` or
`--max-edge 2880` keeps the committed PNGs lean).
5. Build the bundles: `python3 scripts/build-issue.py --issue NN --prompts data/prompts/issue-NN.json`
6. Add `content/issues/NN/_index.md`, add `content/posts/NN/_index.md` (`build.render: never`),
flip the previous issue's `status` away from `current`, and update `hugo.toml` `[params]`
(`issueIds`, `issueNumber`, `issueName`, `issueSeason`, `issueBlurb`).
Steps 24 all write `content/posts/NN/<slug>/<slug>.png` in place and are each idempotent
(re-run to finish a failed batch; `--force` to redo). Pass `--out DIR` to stage instead.
### Importing issue 01
Issue 01 is sourced from `~/projects/ginger/posts.csv` and matching images in
`~/projects/ginger/images/final/selected/`:
```bash ```bash
python3 scripts/import-posts.py python3 scripts/import-posts.py # writes content/posts/01/
``` ```
This creates or updates page bundles, assigns plate numbers (sorted alphabetically by filename for stability), normalises descriptions, and copies images. This creates or updates page bundles, assigns plate numbers (sorted alphabetically by filename for stability), normalises descriptions, and copies images.
@@ -58,7 +92,15 @@ Key tokens: `--color-paper` `--color-ink` `--color-roux` `--font-display` `--fon
## Deployment ## Deployment
The repo includes `nginx.conf` and a `Dockerfile` for containerised deployment. Build the image and serve `public/` via nginx. Analytics (Umami) are injected only when `HUGO_ENVIRONMENT=production`. `Dockerfile` is a two-stage build: `hugomods/hugo:debian-node-*` runs
`pnpm install` then `hugo --minify --environment production` (Hugo compiles
Tailwind in-process — no pre-build CSS step), and `nginx:alpine` serves the
result with `nginx.conf`. Analytics (Umami) are injected only in the production
environment.
`nginx.conf` also 301-redirects the legacy flat issue-01 plate URLs
(`/posts/<slug>/``/posts/01/<slug>/`); widen its negative-lookahead when
adding issue 03+.
## License ## License
+5 -1
View File
@@ -1,4 +1,5 @@
@import "tailwindcss"; @import "tailwindcss";
@source "hugo_stats.json";
@custom-variant hover (&:hover); @custom-variant hover (&:hover);
@@ -138,7 +139,8 @@ mark.hl { background: color-mix(in oklab, var(--roux) 22%, transparent); color:
.lb { grid-template-columns: 1fr; grid-template-rows: auto 1fr auto auto; grid-template-areas: "topbar" "stage" "meta" "thumbs"; } .lb { grid-template-columns: 1fr; grid-template-rows: auto 1fr auto auto; grid-template-areas: "topbar" "stage" "meta" "thumbs"; }
} }
.lb-topbar { grid-area: topbar; display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 14px 22px; border-bottom: 1px solid rgba(236,231,221,.08); } .lb-topbar { grid-area: topbar; display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 14px 22px; border-bottom: 1px solid rgba(236,231,221,.08); }
.lb-brand { display: flex; align-items: center; gap: 14px; font: 500 11px/1 var(--sans); letter-spacing: .2em; text-transform: uppercase; color: #c8c0b1; min-width: 0; overflow: hidden; } .lb-brand { display: flex; align-items: center; gap: 14px; font: 500 11px/1 var(--sans); letter-spacing: .2em; text-transform: uppercase; color: #c8c0b1; min-width: 0; overflow: hidden; transition: opacity .2s; }
.lb-brand:hover { opacity: .7; }
.lb-brand svg { height: 18px; } .lb-brand svg { height: 18px; }
.lb-index { font: 500 11px/1 var(--mono); letter-spacing: .14em; color: #c8c0b1; font-variant-numeric: tabular-nums; } .lb-index { font: 500 11px/1 var(--mono); letter-spacing: .14em; color: #c8c0b1; font-variant-numeric: tabular-nums; }
.lb-index b { color: #ece7dd; } .lb-index b { color: #ece7dd; }
@@ -156,6 +158,8 @@ mark.hl { background: color-mix(in oklab, var(--roux) 22%, transparent); color:
.lb-meta { grid-area: meta; padding: 28px 28px 22px; border-left: 1px solid rgba(236,231,221,.08); display: flex; flex-direction: column; gap: 18px; overflow: auto; } .lb-meta { grid-area: meta; padding: 28px 28px 22px; border-left: 1px solid rgba(236,231,221,.08); display: flex; flex-direction: column; gap: 18px; overflow: auto; }
@media (max-width: 920px) { .lb-meta { border-left: 0; border-top: 1px solid rgba(236,231,221,.08); padding: 18px 22px; max-height: 38vh; } } @media (max-width: 920px) { .lb-meta { border-left: 0; border-top: 1px solid rgba(236,231,221,.08); padding: 18px 22px; max-height: 38vh; } }
.lb-cat { font: 500 11px/1 var(--sans); letter-spacing: .22em; text-transform: uppercase; color: var(--roux); } .lb-cat { font: 500 11px/1 var(--sans); letter-spacing: .22em; text-transform: uppercase; color: var(--roux); }
.lb-cat a { transition: opacity .2s; }
.lb-cat a:hover { opacity: .65; }
.lb-cat::after { content: ""; display: block; height: 1px; width: 30px; background: var(--roux); margin-top: 8px; } .lb-cat::after { content: ""; display: block; height: 1px; width: 30px; background: var(--roux); margin-top: 8px; }
.lb-title { margin: 0; font: 400 clamp(32px,3vw,44px)/1 var(--display); letter-spacing: -0.005em; color: #f5f0e6; } .lb-title { margin: 0; font: 400 clamp(32px,3vw,44px)/1 var(--display); letter-spacing: -0.005em; color: #f5f0e6; }
.lb-title em { font-family: var(--serif); font-style: italic; color: #d99e8e; font-weight: 300; } .lb-title em { font-family: var(--serif); font-style: italic; color: #d99e8e; font-weight: 300; }
+1 -1
View File
@@ -3,5 +3,5 @@ title: "Devotion"
description: "One hundred plates devoted to a single presence — photographed across worlds, light, and time." description: "One hundred plates devoted to a single presence — photographed across worlds, light, and time."
issueNumber: "№ 01" issueNumber: "№ 01"
season: "Spring MMXXVI" season: "Spring MMXXVI"
status: "current" status: "archived"
--- ---
+7
View File
@@ -0,0 +1,7 @@
---
title: "Obsession"
description: "One hundred plates in thrall to a single body — a bared shoulder, a parted mouth, silk slipping loose."
issueNumber: "№ 02"
season: "Autumn MMXXVI"
status: "current"
---
+6
View File
@@ -0,0 +1,6 @@
---
title: "Issue № 01 — Devotion"
build:
render: never
list: never
---

Before

Width:  |  Height:  |  Size: 11 MiB

After

Width:  |  Height:  |  Size: 11 MiB

Before

Width:  |  Height:  |  Size: 13 MiB

After

Width:  |  Height:  |  Size: 13 MiB

Before

Width:  |  Height:  |  Size: 13 MiB

After

Width:  |  Height:  |  Size: 13 MiB

Before

Width:  |  Height:  |  Size: 14 MiB

After

Width:  |  Height:  |  Size: 14 MiB

Before

Width:  |  Height:  |  Size: 12 MiB

After

Width:  |  Height:  |  Size: 12 MiB

Before

Width:  |  Height:  |  Size: 12 MiB

After

Width:  |  Height:  |  Size: 12 MiB

Before

Width:  |  Height:  |  Size: 11 MiB

After

Width:  |  Height:  |  Size: 11 MiB

Before

Width:  |  Height:  |  Size: 11 MiB

After

Width:  |  Height:  |  Size: 11 MiB

Before

Width:  |  Height:  |  Size: 10 MiB

After

Width:  |  Height:  |  Size: 10 MiB

Before

Width:  |  Height:  |  Size: 12 MiB

After

Width:  |  Height:  |  Size: 12 MiB

Before

Width:  |  Height:  |  Size: 12 MiB

After

Width:  |  Height:  |  Size: 12 MiB

Before

Width:  |  Height:  |  Size: 12 MiB

After

Width:  |  Height:  |  Size: 12 MiB

Before

Width:  |  Height:  |  Size: 14 MiB

After

Width:  |  Height:  |  Size: 14 MiB

Before

Width:  |  Height:  |  Size: 11 MiB

After

Width:  |  Height:  |  Size: 11 MiB

Before

Width:  |  Height:  |  Size: 12 MiB

After

Width:  |  Height:  |  Size: 12 MiB

Before

Width:  |  Height:  |  Size: 14 MiB

After

Width:  |  Height:  |  Size: 14 MiB

Before

Width:  |  Height:  |  Size: 14 MiB

After

Width:  |  Height:  |  Size: 14 MiB

Before

Width:  |  Height:  |  Size: 12 MiB

After

Width:  |  Height:  |  Size: 12 MiB

Before

Width:  |  Height:  |  Size: 11 MiB

After

Width:  |  Height:  |  Size: 11 MiB

Before

Width:  |  Height:  |  Size: 10 MiB

After

Width:  |  Height:  |  Size: 10 MiB

Before

Width:  |  Height:  |  Size: 13 MiB

After

Width:  |  Height:  |  Size: 13 MiB

Before

Width:  |  Height:  |  Size: 12 MiB

After

Width:  |  Height:  |  Size: 12 MiB

Before

Width:  |  Height:  |  Size: 13 MiB

After

Width:  |  Height:  |  Size: 13 MiB

Before

Width:  |  Height:  |  Size: 16 MiB

After

Width:  |  Height:  |  Size: 16 MiB

Before

Width:  |  Height:  |  Size: 15 MiB

After

Width:  |  Height:  |  Size: 15 MiB

Before

Width:  |  Height:  |  Size: 9.5 MiB

After

Width:  |  Height:  |  Size: 9.5 MiB

Before

Width:  |  Height:  |  Size: 12 MiB

After

Width:  |  Height:  |  Size: 12 MiB

Before

Width:  |  Height:  |  Size: 15 MiB

After

Width:  |  Height:  |  Size: 15 MiB

Before

Width:  |  Height:  |  Size: 13 MiB

After

Width:  |  Height:  |  Size: 13 MiB

Before

Width:  |  Height:  |  Size: 13 MiB

After

Width:  |  Height:  |  Size: 13 MiB

Before

Width:  |  Height:  |  Size: 12 MiB

After

Width:  |  Height:  |  Size: 12 MiB

Before

Width:  |  Height:  |  Size: 12 MiB

After

Width:  |  Height:  |  Size: 12 MiB

Some files were not shown because too many files have changed in this diff Show More