diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index 578d48c..83e643c 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -31,6 +31,8 @@ jobs:
with:
ruby-version: '3.1.2'
bundler-cache: true
+ - name: Test gallery items
+ run: bundle exec ruby scripts/tests/gallery_items_test.rb
- name: Build Jekyll
env:
JEKYLL_ENV: production
diff --git a/_plugins/gallery_items.rb b/_plugins/gallery_items.rb
new file mode 100644
index 0000000..0ad0144
--- /dev/null
+++ b/_plugins/gallery_items.rb
@@ -0,0 +1,24 @@
+require 'nokogiri'
+
+module GalleryItems
+ # Uploaded batches share one source document, but each photo is a gallery item.
+ # Keeping this at render time also fixes batches that have already been published.
+ def gallery_items(content)
+ fragment = Nokogiri::HTML::DocumentFragment.parse(content)
+ images = fragment.css('img')
+ return [content] unless images.length > 1 && images.all? { |image|
+ image['src'].to_s.start_with?('/img/arts/uploads/') && image.parent.name == 'p'
+ }
+
+ captions = fragment.css('.image-details').map(&:to_html).join
+ images.each { |image| image.parent.remove }
+ fragment.css('.image-details').each(&:remove)
+ # Preserve the batch's existing anchor exactly once, before the first photo.
+ prefix = fragment.to_html
+ images.each_with_index.map do |image, index|
+ "#{index.zero? ? prefix : ''}
#{image.to_html}
#{captions}"
+ end
+ end
+end
+
+Liquid::Template.register_filter(GalleryItems)
diff --git a/art.html b/art.html
index f1fa5fd..d26c8e0 100644
--- a/art.html
+++ b/art.html
@@ -33,14 +33,17 @@ wide_gallery: true
{% if post.published == false %}
{% continue %}
{% endif %}
+ {% assign items = post.content | markdownify | lazy_images | gallery_items %}
+ {% for item in items %}
- {% if post.anchor %}
+ {% if post.anchor and forloop.first %}
{% endif %}
- {{ post.content | markdownify | lazy_images }}
+ {{ item }}
+ {% endfor %}
{% endfor %}
diff --git a/img/arts/baled-hay.jpg b/img/arts/baled-hay.jpg
index ab6ddb1..a83fcb9 100644
Binary files a/img/arts/baled-hay.jpg and b/img/arts/baled-hay.jpg differ
diff --git a/img/arts/blue-contagious-smile.jpg b/img/arts/blue-contagious-smile.jpg
index d41fc85..bebf7ac 100644
Binary files a/img/arts/blue-contagious-smile.jpg and b/img/arts/blue-contagious-smile.jpg differ
diff --git a/img/arts/boy.jpg b/img/arts/boy.jpg
index d6f5217..ac26529 100644
Binary files a/img/arts/boy.jpg and b/img/arts/boy.jpg differ
diff --git a/img/arts/cemetery.jpg b/img/arts/cemetery.jpg
index a34d62f..e8c15b1 100644
Binary files a/img/arts/cemetery.jpg and b/img/arts/cemetery.jpg differ
diff --git a/img/arts/dark-street-light.jpg b/img/arts/dark-street-light.jpg
index 728eb4b..288a6d9 100644
Binary files a/img/arts/dark-street-light.jpg and b/img/arts/dark-street-light.jpg differ
diff --git a/img/arts/dead-baluga.jpeg b/img/arts/dead-baluga.jpeg
index e986ec8..24c2e4c 100644
Binary files a/img/arts/dead-baluga.jpeg and b/img/arts/dead-baluga.jpeg differ
diff --git a/img/arts/deer-above.jpg b/img/arts/deer-above.jpg
index 54ce32e..aa70998 100644
Binary files a/img/arts/deer-above.jpg and b/img/arts/deer-above.jpg differ
diff --git a/img/arts/deer-silhouette.jpg b/img/arts/deer-silhouette.jpg
index a54efdc..81c5460 100644
Binary files a/img/arts/deer-silhouette.jpg and b/img/arts/deer-silhouette.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/Babataher.jpg b/img/arts/dresden-prague-iran-2024/Babataher.jpg
index 3ac2173..61a8db4 100644
Binary files a/img/arts/dresden-prague-iran-2024/Babataher.jpg and b/img/arts/dresden-prague-iran-2024/Babataher.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/Belfast_000512350018.jpg b/img/arts/dresden-prague-iran-2024/Belfast_000512350018.jpg
index f6f50f7..022cd26 100644
Binary files a/img/arts/dresden-prague-iran-2024/Belfast_000512350018.jpg and b/img/arts/dresden-prague-iran-2024/Belfast_000512350018.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/Belfast_000512350022.jpg b/img/arts/dresden-prague-iran-2024/Belfast_000512350022.jpg
index ebf0b3e..b2935a9 100644
Binary files a/img/arts/dresden-prague-iran-2024/Belfast_000512350022.jpg and b/img/arts/dresden-prague-iran-2024/Belfast_000512350022.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/Belfast_000512350026.jpg b/img/arts/dresden-prague-iran-2024/Belfast_000512350026.jpg
index 8fb235b..d36cd16 100644
Binary files a/img/arts/dresden-prague-iran-2024/Belfast_000512350026.jpg and b/img/arts/dresden-prague-iran-2024/Belfast_000512350026.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/Belfast_000512350027.jpg b/img/arts/dresden-prague-iran-2024/Belfast_000512350027.jpg
index 7ce9adb..879fa3b 100644
Binary files a/img/arts/dresden-prague-iran-2024/Belfast_000512350027.jpg and b/img/arts/dresden-prague-iran-2024/Belfast_000512350027.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/Belfast_000512350032.jpg b/img/arts/dresden-prague-iran-2024/Belfast_000512350032.jpg
index 54134e4..52752dc 100644
Binary files a/img/arts/dresden-prague-iran-2024/Belfast_000512350032.jpg and b/img/arts/dresden-prague-iran-2024/Belfast_000512350032.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/Bobby-Sands.jpg b/img/arts/dresden-prague-iran-2024/Bobby-Sands.jpg
index cec6ff4..b87985a 100644
Binary files a/img/arts/dresden-prague-iran-2024/Bobby-Sands.jpg and b/img/arts/dresden-prague-iran-2024/Bobby-Sands.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/Dresden_000512370016.jpg b/img/arts/dresden-prague-iran-2024/Dresden_000512370016.jpg
index fff7998..f9c2336 100644
Binary files a/img/arts/dresden-prague-iran-2024/Dresden_000512370016.jpg and b/img/arts/dresden-prague-iran-2024/Dresden_000512370016.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/Dresden_000512370017.jpg b/img/arts/dresden-prague-iran-2024/Dresden_000512370017.jpg
index b7fc491..bb458ea 100644
Binary files a/img/arts/dresden-prague-iran-2024/Dresden_000512370017.jpg and b/img/arts/dresden-prague-iran-2024/Dresden_000512370017.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/Dresden_000512370018.jpg b/img/arts/dresden-prague-iran-2024/Dresden_000512370018.jpg
index ad829ef..c93a6a8 100644
Binary files a/img/arts/dresden-prague-iran-2024/Dresden_000512370018.jpg and b/img/arts/dresden-prague-iran-2024/Dresden_000512370018.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/Dresden_000512370019.jpg b/img/arts/dresden-prague-iran-2024/Dresden_000512370019.jpg
index fe495d4..8b89fad 100644
Binary files a/img/arts/dresden-prague-iran-2024/Dresden_000512370019.jpg and b/img/arts/dresden-prague-iran-2024/Dresden_000512370019.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/Dresden_000512370032.jpg b/img/arts/dresden-prague-iran-2024/Dresden_000512370032.jpg
index 214ef4d..ef2ca47 100644
Binary files a/img/arts/dresden-prague-iran-2024/Dresden_000512370032.jpg and b/img/arts/dresden-prague-iran-2024/Dresden_000512370032.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/Dresden_000512370033.jpg b/img/arts/dresden-prague-iran-2024/Dresden_000512370033.jpg
index f7295c2..75f2ce7 100644
Binary files a/img/arts/dresden-prague-iran-2024/Dresden_000512370033.jpg and b/img/arts/dresden-prague-iran-2024/Dresden_000512370033.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/Dresden_000512370034.jpg b/img/arts/dresden-prague-iran-2024/Dresden_000512370034.jpg
index 2b6032d..21e0a96 100644
Binary files a/img/arts/dresden-prague-iran-2024/Dresden_000512370034.jpg and b/img/arts/dresden-prague-iran-2024/Dresden_000512370034.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/Grandmother's-old-room.jpg b/img/arts/dresden-prague-iran-2024/Grandmother's-old-room.jpg
index 173fb0d..7de557d 100644
Binary files a/img/arts/dresden-prague-iran-2024/Grandmother's-old-room.jpg and b/img/arts/dresden-prague-iran-2024/Grandmother's-old-room.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/Home_000512360003.jpg b/img/arts/dresden-prague-iran-2024/Home_000512360003.jpg
index 96ba126..9a85e9c 100644
Binary files a/img/arts/dresden-prague-iran-2024/Home_000512360003.jpg and b/img/arts/dresden-prague-iran-2024/Home_000512360003.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/Let-me-tell-you-a-story_000512370015.jpg b/img/arts/dresden-prague-iran-2024/Let-me-tell-you-a-story_000512370015.jpg
index 7b9103e..65835ed 100644
Binary files a/img/arts/dresden-prague-iran-2024/Let-me-tell-you-a-story_000512370015.jpg and b/img/arts/dresden-prague-iran-2024/Let-me-tell-you-a-story_000512370015.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/Prague_000512360019.jpg b/img/arts/dresden-prague-iran-2024/Prague_000512360019.jpg
index d29cade..0f23e1d 100644
Binary files a/img/arts/dresden-prague-iran-2024/Prague_000512360019.jpg and b/img/arts/dresden-prague-iran-2024/Prague_000512360019.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/Prague_000512360020.jpg b/img/arts/dresden-prague-iran-2024/Prague_000512360020.jpg
index c734338..5c744a9 100644
Binary files a/img/arts/dresden-prague-iran-2024/Prague_000512360020.jpg and b/img/arts/dresden-prague-iran-2024/Prague_000512360020.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/Prague_000512360021.jpg b/img/arts/dresden-prague-iran-2024/Prague_000512360021.jpg
index c98d619..d41025e 100644
Binary files a/img/arts/dresden-prague-iran-2024/Prague_000512360021.jpg and b/img/arts/dresden-prague-iran-2024/Prague_000512360021.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/Prague_000512360027.jpg b/img/arts/dresden-prague-iran-2024/Prague_000512360027.jpg
index d7957b7..4064457 100644
Binary files a/img/arts/dresden-prague-iran-2024/Prague_000512360027.jpg and b/img/arts/dresden-prague-iran-2024/Prague_000512360027.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/Prague_000512360029.jpg b/img/arts/dresden-prague-iran-2024/Prague_000512360029.jpg
index b02791b..0cb4635 100644
Binary files a/img/arts/dresden-prague-iran-2024/Prague_000512360029.jpg and b/img/arts/dresden-prague-iran-2024/Prague_000512360029.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/Prague_000512360030.jpg b/img/arts/dresden-prague-iran-2024/Prague_000512360030.jpg
index 6dcb347..d8446be 100644
Binary files a/img/arts/dresden-prague-iran-2024/Prague_000512360030.jpg and b/img/arts/dresden-prague-iran-2024/Prague_000512360030.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/Prague_000512360031.jpg b/img/arts/dresden-prague-iran-2024/Prague_000512360031.jpg
index fcef1cf..2b762e9 100644
Binary files a/img/arts/dresden-prague-iran-2024/Prague_000512360031.jpg and b/img/arts/dresden-prague-iran-2024/Prague_000512360031.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/Prague_000512370012.jpg b/img/arts/dresden-prague-iran-2024/Prague_000512370012.jpg
index f97c35e..9ea5e50 100644
Binary files a/img/arts/dresden-prague-iran-2024/Prague_000512370012.jpg and b/img/arts/dresden-prague-iran-2024/Prague_000512370012.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/Somewhere-in-Tehran.jpg b/img/arts/dresden-prague-iran-2024/Somewhere-in-Tehran.jpg
index 3724d22..a8e6567 100644
Binary files a/img/arts/dresden-prague-iran-2024/Somewhere-in-Tehran.jpg and b/img/arts/dresden-prague-iran-2024/Somewhere-in-Tehran.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/Somewhere-in-Tehran_2.jpg b/img/arts/dresden-prague-iran-2024/Somewhere-in-Tehran_2.jpg
index 56e14c8..430056a 100644
Binary files a/img/arts/dresden-prague-iran-2024/Somewhere-in-Tehran_2.jpg and b/img/arts/dresden-prague-iran-2024/Somewhere-in-Tehran_2.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/Somewhere-in-tehran.jpg b/img/arts/dresden-prague-iran-2024/Somewhere-in-tehran.jpg
index 3724d22..a8e6567 100644
Binary files a/img/arts/dresden-prague-iran-2024/Somewhere-in-tehran.jpg and b/img/arts/dresden-prague-iran-2024/Somewhere-in-tehran.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/Somewhere-in-tehran_2.jpg b/img/arts/dresden-prague-iran-2024/Somewhere-in-tehran_2.jpg
index 56e14c8..430056a 100644
Binary files a/img/arts/dresden-prague-iran-2024/Somewhere-in-tehran_2.jpg and b/img/arts/dresden-prague-iran-2024/Somewhere-in-tehran_2.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/x_000512350001.jpg b/img/arts/dresden-prague-iran-2024/x_000512350001.jpg
index f35d01d..af33c1c 100644
Binary files a/img/arts/dresden-prague-iran-2024/x_000512350001.jpg and b/img/arts/dresden-prague-iran-2024/x_000512350001.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/x_000512350002.jpg b/img/arts/dresden-prague-iran-2024/x_000512350002.jpg
index dfba97b..397cbe7 100644
Binary files a/img/arts/dresden-prague-iran-2024/x_000512350002.jpg and b/img/arts/dresden-prague-iran-2024/x_000512350002.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/x_000512350003.jpg b/img/arts/dresden-prague-iran-2024/x_000512350003.jpg
index 7964f7a..d5f0cb8 100644
Binary files a/img/arts/dresden-prague-iran-2024/x_000512350003.jpg and b/img/arts/dresden-prague-iran-2024/x_000512350003.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/x_000512350004.jpg b/img/arts/dresden-prague-iran-2024/x_000512350004.jpg
index ce74521..83f6e19 100644
Binary files a/img/arts/dresden-prague-iran-2024/x_000512350004.jpg and b/img/arts/dresden-prague-iran-2024/x_000512350004.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/x_000512350006.jpg b/img/arts/dresden-prague-iran-2024/x_000512350006.jpg
index d549647..24314a4 100644
Binary files a/img/arts/dresden-prague-iran-2024/x_000512350006.jpg and b/img/arts/dresden-prague-iran-2024/x_000512350006.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/x_000512350011.jpg b/img/arts/dresden-prague-iran-2024/x_000512350011.jpg
index ab62e86..1f61c94 100644
Binary files a/img/arts/dresden-prague-iran-2024/x_000512350011.jpg and b/img/arts/dresden-prague-iran-2024/x_000512350011.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/x_000512350012.jpg b/img/arts/dresden-prague-iran-2024/x_000512350012.jpg
index cf6cdb5..d10d224 100644
Binary files a/img/arts/dresden-prague-iran-2024/x_000512350012.jpg and b/img/arts/dresden-prague-iran-2024/x_000512350012.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/x_000512350014.jpg b/img/arts/dresden-prague-iran-2024/x_000512350014.jpg
index 972dfae..e4587e5 100644
Binary files a/img/arts/dresden-prague-iran-2024/x_000512350014.jpg and b/img/arts/dresden-prague-iran-2024/x_000512350014.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/x_000512370003.jpg b/img/arts/dresden-prague-iran-2024/x_000512370003.jpg
index d8c0935..4dda049 100644
Binary files a/img/arts/dresden-prague-iran-2024/x_000512370003.jpg and b/img/arts/dresden-prague-iran-2024/x_000512370003.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/x_000512370005.jpg b/img/arts/dresden-prague-iran-2024/x_000512370005.jpg
index d3b1c9b..dfeff4c 100644
Binary files a/img/arts/dresden-prague-iran-2024/x_000512370005.jpg and b/img/arts/dresden-prague-iran-2024/x_000512370005.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/x_000512370006.jpg b/img/arts/dresden-prague-iran-2024/x_000512370006.jpg
index 3baf7e0..b154f41 100644
Binary files a/img/arts/dresden-prague-iran-2024/x_000512370006.jpg and b/img/arts/dresden-prague-iran-2024/x_000512370006.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/x_000512370013.jpg b/img/arts/dresden-prague-iran-2024/x_000512370013.jpg
index aac3ad0..e32e6ac 100644
Binary files a/img/arts/dresden-prague-iran-2024/x_000512370013.jpg and b/img/arts/dresden-prague-iran-2024/x_000512370013.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/x_000512370022.jpg b/img/arts/dresden-prague-iran-2024/x_000512370022.jpg
index ae74b1d..872ca44 100644
Binary files a/img/arts/dresden-prague-iran-2024/x_000512370022.jpg and b/img/arts/dresden-prague-iran-2024/x_000512370022.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/x_000512370024.jpg b/img/arts/dresden-prague-iran-2024/x_000512370024.jpg
index b2d2612..f063bc9 100644
Binary files a/img/arts/dresden-prague-iran-2024/x_000512370024.jpg and b/img/arts/dresden-prague-iran-2024/x_000512370024.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/x_000512370026.jpg b/img/arts/dresden-prague-iran-2024/x_000512370026.jpg
index 930eb01..6d75d0b 100644
Binary files a/img/arts/dresden-prague-iran-2024/x_000512370026.jpg and b/img/arts/dresden-prague-iran-2024/x_000512370026.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/x_000512370027.jpg b/img/arts/dresden-prague-iran-2024/x_000512370027.jpg
index 6b75da0..8460a63 100644
Binary files a/img/arts/dresden-prague-iran-2024/x_000512370027.jpg and b/img/arts/dresden-prague-iran-2024/x_000512370027.jpg differ
diff --git a/img/arts/dresden-prague-iran-2024/x_000512370028.jpg b/img/arts/dresden-prague-iran-2024/x_000512370028.jpg
index 8a8c9f0..c8ea229 100644
Binary files a/img/arts/dresden-prague-iran-2024/x_000512370028.jpg and b/img/arts/dresden-prague-iran-2024/x_000512370028.jpg differ
diff --git a/img/arts/drought-dead-statue.jpg b/img/arts/drought-dead-statue.jpg
index bb57346..6c12ee7 100644
Binary files a/img/arts/drought-dead-statue.jpg and b/img/arts/drought-dead-statue.jpg differ
diff --git a/img/arts/dublin-chimneys.jpg b/img/arts/dublin-chimneys.jpg
index b23f0ef..a6654b5 100644
Binary files a/img/arts/dublin-chimneys.jpg and b/img/arts/dublin-chimneys.jpg differ
diff --git a/img/arts/galileo.jpg b/img/arts/galileo.jpg
index 05f9e0c..275c3af 100644
Binary files a/img/arts/galileo.jpg and b/img/arts/galileo.jpg differ
diff --git a/img/arts/girl-eye-flowers-1.jpg b/img/arts/girl-eye-flowers-1.jpg
index 06325f1..ae81605 100644
Binary files a/img/arts/girl-eye-flowers-1.jpg and b/img/arts/girl-eye-flowers-1.jpg differ
diff --git a/img/arts/girl-eye-flowers-2.jpg b/img/arts/girl-eye-flowers-2.jpg
index 83920a2..68b3c8b 100644
Binary files a/img/arts/girl-eye-flowers-2.jpg and b/img/arts/girl-eye-flowers-2.jpg differ
diff --git a/img/arts/girl-eye-flowers-3.jpg b/img/arts/girl-eye-flowers-3.jpg
index b7710b0..fbba170 100644
Binary files a/img/arts/girl-eye-flowers-3.jpg and b/img/arts/girl-eye-flowers-3.jpg differ
diff --git a/img/arts/grand.jpg b/img/arts/grand.jpg
index d2a1636..985ffb9 100644
Binary files a/img/arts/grand.jpg and b/img/arts/grand.jpg differ
diff --git a/img/arts/head-wall.jpg b/img/arts/head-wall.jpg
index a2e26de..9324791 100644
Binary files a/img/arts/head-wall.jpg and b/img/arts/head-wall.jpg differ
diff --git a/img/arts/highland-cow-1.jpeg b/img/arts/highland-cow-1.jpeg
index d8fe9e4..d7adb6d 100644
Binary files a/img/arts/highland-cow-1.jpeg and b/img/arts/highland-cow-1.jpeg differ
diff --git a/img/arts/highland-cow-2.jpg b/img/arts/highland-cow-2.jpg
index 9b2881d..5f362c3 100644
Binary files a/img/arts/highland-cow-2.jpg and b/img/arts/highland-cow-2.jpg differ
diff --git a/img/arts/hill-of-tara.jpg b/img/arts/hill-of-tara.jpg
index fa95a51..e687934 100644
Binary files a/img/arts/hill-of-tara.jpg and b/img/arts/hill-of-tara.jpg differ
diff --git a/img/arts/iran-analog-2024/Bazaar-e-Tabriz_000521270009.jpg b/img/arts/iran-analog-2024/Bazaar-e-Tabriz_000521270009.jpg
index c71b715..ee12ba0 100644
Binary files a/img/arts/iran-analog-2024/Bazaar-e-Tabriz_000521270009.jpg and b/img/arts/iran-analog-2024/Bazaar-e-Tabriz_000521270009.jpg differ
diff --git a/img/arts/iran-analog-2024/Bazaar-e-Tabriz_000521270010.jpg b/img/arts/iran-analog-2024/Bazaar-e-Tabriz_000521270010.jpg
index f16f220..14c20fa 100644
Binary files a/img/arts/iran-analog-2024/Bazaar-e-Tabriz_000521270010.jpg and b/img/arts/iran-analog-2024/Bazaar-e-Tabriz_000521270010.jpg differ
diff --git a/img/arts/iran-analog-2024/Bistoon_000521270026.jpg b/img/arts/iran-analog-2024/Bistoon_000521270026.jpg
index 0ea1793..cf627b9 100644
Binary files a/img/arts/iran-analog-2024/Bistoon_000521270026.jpg and b/img/arts/iran-analog-2024/Bistoon_000521270026.jpg differ
diff --git a/img/arts/iran-analog-2024/Bistoon_000521270027.jpg b/img/arts/iran-analog-2024/Bistoon_000521270027.jpg
index 8a3f77d..e6ac296 100644
Binary files a/img/arts/iran-analog-2024/Bistoon_000521270027.jpg and b/img/arts/iran-analog-2024/Bistoon_000521270027.jpg differ
diff --git a/img/arts/iran-analog-2024/Ganjname,-Hamadan_000521270029.jpg b/img/arts/iran-analog-2024/Ganjname,-Hamadan_000521270029.jpg
index 032aef2..980817b 100644
Binary files a/img/arts/iran-analog-2024/Ganjname,-Hamadan_000521270029.jpg and b/img/arts/iran-analog-2024/Ganjname,-Hamadan_000521270029.jpg differ
diff --git a/img/arts/iran-analog-2024/Hamadan_000521270031.jpg b/img/arts/iran-analog-2024/Hamadan_000521270031.jpg
index d6f88a8..6d404cd 100644
Binary files a/img/arts/iran-analog-2024/Hamadan_000521270031.jpg and b/img/arts/iran-analog-2024/Hamadan_000521270031.jpg differ
diff --git a/img/arts/iran-analog-2024/Hamadan_000521270032.jpg b/img/arts/iran-analog-2024/Hamadan_000521270032.jpg
index bc0bb9e..cfa324a 100644
Binary files a/img/arts/iran-analog-2024/Hamadan_000521270032.jpg and b/img/arts/iran-analog-2024/Hamadan_000521270032.jpg differ
diff --git a/img/arts/iran-analog-2024/Hamadan_000521270033.jpg b/img/arts/iran-analog-2024/Hamadan_000521270033.jpg
index 539b06b..b61de8c 100644
Binary files a/img/arts/iran-analog-2024/Hamadan_000521270033.jpg and b/img/arts/iran-analog-2024/Hamadan_000521270033.jpg differ
diff --git a/img/arts/iran-analog-2024/Tabriz_000521270013.jpg b/img/arts/iran-analog-2024/Tabriz_000521270013.jpg
index 0abb58e..16bcd4c 100644
Binary files a/img/arts/iran-analog-2024/Tabriz_000521270013.jpg and b/img/arts/iran-analog-2024/Tabriz_000521270013.jpg differ
diff --git a/img/arts/iran-analog-2024/Taq-e-Bostan_000521270018.jpg b/img/arts/iran-analog-2024/Taq-e-Bostan_000521270018.jpg
index 893ebd5..708cfd5 100644
Binary files a/img/arts/iran-analog-2024/Taq-e-Bostan_000521270018.jpg and b/img/arts/iran-analog-2024/Taq-e-Bostan_000521270018.jpg differ
diff --git a/img/arts/iran-analog-2024/Taq-e-Bostan_000521270019.jpg b/img/arts/iran-analog-2024/Taq-e-Bostan_000521270019.jpg
index f906a7a..9a7f985 100644
Binary files a/img/arts/iran-analog-2024/Taq-e-Bostan_000521270019.jpg and b/img/arts/iran-analog-2024/Taq-e-Bostan_000521270019.jpg differ
diff --git a/img/arts/iran-analog-2024/Taq-e-Bostan_000521270020.jpg b/img/arts/iran-analog-2024/Taq-e-Bostan_000521270020.jpg
index 93fc38f..50f9195 100644
Binary files a/img/arts/iran-analog-2024/Taq-e-Bostan_000521270020.jpg and b/img/arts/iran-analog-2024/Taq-e-Bostan_000521270020.jpg differ
diff --git a/img/arts/iran-girl-2.jpg b/img/arts/iran-girl-2.jpg
index 4df6746..0c98b22 100644
Binary files a/img/arts/iran-girl-2.jpg and b/img/arts/iran-girl-2.jpg differ
diff --git a/img/arts/iran-girl-3.jpg b/img/arts/iran-girl-3.jpg
index 029dc13..7b3bbf8 100644
Binary files a/img/arts/iran-girl-3.jpg and b/img/arts/iran-girl-3.jpg differ
diff --git a/img/arts/iran-girl-4.jpg b/img/arts/iran-girl-4.jpg
index 0511e6b..7fe99fe 100644
Binary files a/img/arts/iran-girl-4.jpg and b/img/arts/iran-girl-4.jpg differ
diff --git a/img/arts/iran-girl-6.jpg b/img/arts/iran-girl-6.jpg
index f6c3928..e363599 100644
Binary files a/img/arts/iran-girl-6.jpg and b/img/arts/iran-girl-6.jpg differ
diff --git a/img/arts/iran-girl.jpg b/img/arts/iran-girl.jpg
index b00a314..5260806 100644
Binary files a/img/arts/iran-girl.jpg and b/img/arts/iran-girl.jpg differ
diff --git a/img/arts/ireland-abandoned.jpg b/img/arts/ireland-abandoned.jpg
index 3d52f41..4d05557 100644
Binary files a/img/arts/ireland-abandoned.jpg and b/img/arts/ireland-abandoned.jpg differ
diff --git a/img/arts/kazakhstan-2024/Kazakhstan_DSC-0865.jpg b/img/arts/kazakhstan-2024/Kazakhstan_DSC-0865.jpg
index efb38f9..654ef43 100644
Binary files a/img/arts/kazakhstan-2024/Kazakhstan_DSC-0865.jpg and b/img/arts/kazakhstan-2024/Kazakhstan_DSC-0865.jpg differ
diff --git a/img/arts/kazakhstan-2024/Kazakhstan_DSC-0870.jpg b/img/arts/kazakhstan-2024/Kazakhstan_DSC-0870.jpg
index d9ea304..12cf6d5 100644
Binary files a/img/arts/kazakhstan-2024/Kazakhstan_DSC-0870.jpg and b/img/arts/kazakhstan-2024/Kazakhstan_DSC-0870.jpg differ
diff --git a/img/arts/kazakhstan-2024/World-Nomad-Games,-Kazakhstan_DSC-0251.jpg b/img/arts/kazakhstan-2024/World-Nomad-Games,-Kazakhstan_DSC-0251.jpg
index a7af52f..1cb37af 100644
Binary files a/img/arts/kazakhstan-2024/World-Nomad-Games,-Kazakhstan_DSC-0251.jpg and b/img/arts/kazakhstan-2024/World-Nomad-Games,-Kazakhstan_DSC-0251.jpg differ
diff --git a/img/arts/kazakhstan-2024/World-Nomad-Games,-Kazakhstan_DSC-0298.jpg b/img/arts/kazakhstan-2024/World-Nomad-Games,-Kazakhstan_DSC-0298.jpg
index 40eaad9..dfe4ca3 100644
Binary files a/img/arts/kazakhstan-2024/World-Nomad-Games,-Kazakhstan_DSC-0298.jpg and b/img/arts/kazakhstan-2024/World-Nomad-Games,-Kazakhstan_DSC-0298.jpg differ
diff --git a/img/arts/kazakhstan-2024/World-Nomad-Games,-Kazakhstan_DSC-0472.jpg b/img/arts/kazakhstan-2024/World-Nomad-Games,-Kazakhstan_DSC-0472.jpg
index a8235a5..492446e 100644
Binary files a/img/arts/kazakhstan-2024/World-Nomad-Games,-Kazakhstan_DSC-0472.jpg and b/img/arts/kazakhstan-2024/World-Nomad-Games,-Kazakhstan_DSC-0472.jpg differ
diff --git a/img/arts/kazakhstan-2024/World-Nomad-Games,-Kazakhstan_DSC-0536.jpg b/img/arts/kazakhstan-2024/World-Nomad-Games,-Kazakhstan_DSC-0536.jpg
index be9ddfe..e0f9bbc 100644
Binary files a/img/arts/kazakhstan-2024/World-Nomad-Games,-Kazakhstan_DSC-0536.jpg and b/img/arts/kazakhstan-2024/World-Nomad-Games,-Kazakhstan_DSC-0536.jpg differ
diff --git a/img/arts/kazakhstan-2024/World-Nomad-Games,-Kazakhstan_DSC-0685.jpg b/img/arts/kazakhstan-2024/World-Nomad-Games,-Kazakhstan_DSC-0685.jpg
index 526b886..5a1d166 100644
Binary files a/img/arts/kazakhstan-2024/World-Nomad-Games,-Kazakhstan_DSC-0685.jpg and b/img/arts/kazakhstan-2024/World-Nomad-Games,-Kazakhstan_DSC-0685.jpg differ
diff --git a/img/arts/kazakhstan-2024/x_DSC-0994.jpg b/img/arts/kazakhstan-2024/x_DSC-0994.jpg
index 4195215..922724e 100644
Binary files a/img/arts/kazakhstan-2024/x_DSC-0994.jpg and b/img/arts/kazakhstan-2024/x_DSC-0994.jpg differ
diff --git a/img/arts/kazakhstan-2024/x_DSC-0999.jpg b/img/arts/kazakhstan-2024/x_DSC-0999.jpg
index 5f17357..2988abe 100644
Binary files a/img/arts/kazakhstan-2024/x_DSC-0999.jpg and b/img/arts/kazakhstan-2024/x_DSC-0999.jpg differ
diff --git a/img/arts/lundy-nature-reserve.jpeg b/img/arts/lundy-nature-reserve.jpeg
index c0595fa..3200095 100644
Binary files a/img/arts/lundy-nature-reserve.jpeg and b/img/arts/lundy-nature-reserve.jpeg differ
diff --git a/img/arts/male-back.jpg b/img/arts/male-back.jpg
index 95479c2..eef5acb 100644
Binary files a/img/arts/male-back.jpg and b/img/arts/male-back.jpg differ
diff --git a/img/arts/nikon-fm/amsterdam-2.jpg b/img/arts/nikon-fm/amsterdam-2.jpg
index 2c1ffc0..b3338c3 100644
Binary files a/img/arts/nikon-fm/amsterdam-2.jpg and b/img/arts/nikon-fm/amsterdam-2.jpg differ
diff --git a/img/arts/nikon-fm/amsterdam-canal.jpg b/img/arts/nikon-fm/amsterdam-canal.jpg
index 6a80b33..bd0eb18 100644
Binary files a/img/arts/nikon-fm/amsterdam-canal.jpg and b/img/arts/nikon-fm/amsterdam-canal.jpg differ
diff --git a/img/arts/nikon-fm/amsterdam-monument.jpg b/img/arts/nikon-fm/amsterdam-monument.jpg
index 629c7b8..09e594f 100644
Binary files a/img/arts/nikon-fm/amsterdam-monument.jpg and b/img/arts/nikon-fm/amsterdam-monument.jpg differ
diff --git a/img/arts/nikon-fm/amsterdam.jpg b/img/arts/nikon-fm/amsterdam.jpg
index e9567a4..d0eae19 100644
Binary files a/img/arts/nikon-fm/amsterdam.jpg and b/img/arts/nikon-fm/amsterdam.jpg differ
diff --git a/img/arts/nikon-fm/banksy.jpg b/img/arts/nikon-fm/banksy.jpg
index 7bce76a..ece27fb 100644
Binary files a/img/arts/nikon-fm/banksy.jpg and b/img/arts/nikon-fm/banksy.jpg differ
diff --git a/img/arts/nikon-fm/batch-1-bw/berlin-dome-2.jpg b/img/arts/nikon-fm/batch-1-bw/berlin-dome-2.jpg
index fb83b3f..2235cc7 100644
Binary files a/img/arts/nikon-fm/batch-1-bw/berlin-dome-2.jpg and b/img/arts/nikon-fm/batch-1-bw/berlin-dome-2.jpg differ
diff --git a/img/arts/nikon-fm/batch-1-bw/berlin-graffiti-1.jpg b/img/arts/nikon-fm/batch-1-bw/berlin-graffiti-1.jpg
index 641ba67..75b2719 100644
Binary files a/img/arts/nikon-fm/batch-1-bw/berlin-graffiti-1.jpg and b/img/arts/nikon-fm/batch-1-bw/berlin-graffiti-1.jpg differ
diff --git a/img/arts/nikon-fm/batch-1-bw/berlin-skate.jpg b/img/arts/nikon-fm/batch-1-bw/berlin-skate.jpg
index ff2aa91..f17c6b3 100644
Binary files a/img/arts/nikon-fm/batch-1-bw/berlin-skate.jpg and b/img/arts/nikon-fm/batch-1-bw/berlin-skate.jpg differ
diff --git a/img/arts/nikon-fm/batch-1-bw/mascot.jpg b/img/arts/nikon-fm/batch-1-bw/mascot.jpg
index da78441..9cfb285 100644
Binary files a/img/arts/nikon-fm/batch-1-bw/mascot.jpg and b/img/arts/nikon-fm/batch-1-bw/mascot.jpg differ
diff --git a/img/arts/nikon-fm/batch-1-bw/see-you-later-mate.jpg b/img/arts/nikon-fm/batch-1-bw/see-you-later-mate.jpg
index 7426bb9..9cf34f9 100644
Binary files a/img/arts/nikon-fm/batch-1-bw/see-you-later-mate.jpg and b/img/arts/nikon-fm/batch-1-bw/see-you-later-mate.jpg differ
diff --git a/img/arts/nikon-fm/batch-1-bw/train.jpg b/img/arts/nikon-fm/batch-1-bw/train.jpg
index 8e1d47c..7fcff56 100644
Binary files a/img/arts/nikon-fm/batch-1-bw/train.jpg and b/img/arts/nikon-fm/batch-1-bw/train.jpg differ
diff --git a/img/arts/nikon-fm/batch-2-colour/birthday.jpg b/img/arts/nikon-fm/batch-2-colour/birthday.jpg
index 22ef4fe..df9ccf2 100644
Binary files a/img/arts/nikon-fm/batch-2-colour/birthday.jpg and b/img/arts/nikon-fm/batch-2-colour/birthday.jpg differ
diff --git a/img/arts/nikon-fm/batch-2-colour/broken-statue.jpg b/img/arts/nikon-fm/batch-2-colour/broken-statue.jpg
index 4a8adec..46f6d6b 100644
Binary files a/img/arts/nikon-fm/batch-2-colour/broken-statue.jpg and b/img/arts/nikon-fm/batch-2-colour/broken-statue.jpg differ
diff --git a/img/arts/nikon-fm/batch-2-colour/famine.jpg b/img/arts/nikon-fm/batch-2-colour/famine.jpg
index 4287418..aa0cfe1 100644
Binary files a/img/arts/nikon-fm/batch-2-colour/famine.jpg and b/img/arts/nikon-fm/batch-2-colour/famine.jpg differ
diff --git a/img/arts/nikon-fm/batch-2-colour/horse.jpg b/img/arts/nikon-fm/batch-2-colour/horse.jpg
index 71325e5..ed30be7 100644
Binary files a/img/arts/nikon-fm/batch-2-colour/horse.jpg and b/img/arts/nikon-fm/batch-2-colour/horse.jpg differ
diff --git a/img/arts/nikon-fm/batch-2-colour/oratory-1.jpg b/img/arts/nikon-fm/batch-2-colour/oratory-1.jpg
index 3b46fd4..04c9d99 100644
Binary files a/img/arts/nikon-fm/batch-2-colour/oratory-1.jpg and b/img/arts/nikon-fm/batch-2-colour/oratory-1.jpg differ
diff --git a/img/arts/nikon-fm/batch-2-colour/oratory-2.jpg b/img/arts/nikon-fm/batch-2-colour/oratory-2.jpg
index 71b8ac4..cb69a16 100644
Binary files a/img/arts/nikon-fm/batch-2-colour/oratory-2.jpg and b/img/arts/nikon-fm/batch-2-colour/oratory-2.jpg differ
diff --git a/img/arts/nikon-fm/batch-2-colour/oratory-3.jpg b/img/arts/nikon-fm/batch-2-colour/oratory-3.jpg
index df5e436..a9f4417 100644
Binary files a/img/arts/nikon-fm/batch-2-colour/oratory-3.jpg and b/img/arts/nikon-fm/batch-2-colour/oratory-3.jpg differ
diff --git a/img/arts/nikon-fm/batch-2-colour/victorsway.jpg b/img/arts/nikon-fm/batch-2-colour/victorsway.jpg
index 7d450ee..2d1c48d 100644
Binary files a/img/arts/nikon-fm/batch-2-colour/victorsway.jpg and b/img/arts/nikon-fm/batch-2-colour/victorsway.jpg differ
diff --git a/img/arts/nikon-fm/boots.jpg b/img/arts/nikon-fm/boots.jpg
index 199b483..c499995 100644
Binary files a/img/arts/nikon-fm/boots.jpg and b/img/arts/nikon-fm/boots.jpg differ
diff --git a/img/arts/nikon-fm/death-bed.jpg b/img/arts/nikon-fm/death-bed.jpg
index 22d785a..7e6920e 100644
Binary files a/img/arts/nikon-fm/death-bed.jpg and b/img/arts/nikon-fm/death-bed.jpg differ
diff --git a/img/arts/nikon-fm/death-kick.jpg b/img/arts/nikon-fm/death-kick.jpg
index 3db3aba..d950d7f 100644
Binary files a/img/arts/nikon-fm/death-kick.jpg and b/img/arts/nikon-fm/death-kick.jpg differ
diff --git a/img/arts/nikon-fm/dont-believe-in-god.jpg b/img/arts/nikon-fm/dont-believe-in-god.jpg
index cb35b73..10ca9fb 100644
Binary files a/img/arts/nikon-fm/dont-believe-in-god.jpg and b/img/arts/nikon-fm/dont-believe-in-god.jpg differ
diff --git a/img/arts/nikon-fm/heads.jpg b/img/arts/nikon-fm/heads.jpg
index 7b215b3..69fe048 100644
Binary files a/img/arts/nikon-fm/heads.jpg and b/img/arts/nikon-fm/heads.jpg differ
diff --git a/img/arts/nikon-fm/mannequin.jpg b/img/arts/nikon-fm/mannequin.jpg
index 9200498..ee616e5 100644
Binary files a/img/arts/nikon-fm/mannequin.jpg and b/img/arts/nikon-fm/mannequin.jpg differ
diff --git a/img/arts/nikon-fm/windmill-inner.jpg b/img/arts/nikon-fm/windmill-inner.jpg
index bdf60ea..9af296a 100644
Binary files a/img/arts/nikon-fm/windmill-inner.jpg and b/img/arts/nikon-fm/windmill-inner.jpg differ
diff --git a/img/arts/nikon-fm/windmill.jpg b/img/arts/nikon-fm/windmill.jpg
index 962f26a..affa27e 100644
Binary files a/img/arts/nikon-fm/windmill.jpg and b/img/arts/nikon-fm/windmill.jpg differ
diff --git a/img/arts/norway-2023/bird.jpg b/img/arts/norway-2023/bird.jpg
index 6ef25d4..882e256 100644
Binary files a/img/arts/norway-2023/bird.jpg and b/img/arts/norway-2023/bird.jpg differ
diff --git a/img/arts/norway-2023/bridge.jpg b/img/arts/norway-2023/bridge.jpg
index fa88563..dcebf69 100644
Binary files a/img/arts/norway-2023/bridge.jpg and b/img/arts/norway-2023/bridge.jpg differ
diff --git a/img/arts/norway-2023/church-top-2.jpg b/img/arts/norway-2023/church-top-2.jpg
index a2198c9..a758a28 100644
Binary files a/img/arts/norway-2023/church-top-2.jpg and b/img/arts/norway-2023/church-top-2.jpg differ
diff --git a/img/arts/norway-2023/church-top.jpg b/img/arts/norway-2023/church-top.jpg
index d65eb3d..1c14c99 100644
Binary files a/img/arts/norway-2023/church-top.jpg and b/img/arts/norway-2023/church-top.jpg differ
diff --git a/img/arts/norway-2023/cyclist-bridge.jpg b/img/arts/norway-2023/cyclist-bridge.jpg
index 7cca595..2a9551e 100644
Binary files a/img/arts/norway-2023/cyclist-bridge.jpg and b/img/arts/norway-2023/cyclist-bridge.jpg differ
diff --git a/img/arts/norway-2023/fjord.jpg b/img/arts/norway-2023/fjord.jpg
index dcce18e..0b6388f 100644
Binary files a/img/arts/norway-2023/fjord.jpg and b/img/arts/norway-2023/fjord.jpg differ
diff --git a/img/arts/norway-2023/grave.jpg b/img/arts/norway-2023/grave.jpg
index e9f0812..496b20d 100644
Binary files a/img/arts/norway-2023/grave.jpg and b/img/arts/norway-2023/grave.jpg differ
diff --git a/img/arts/norway-2023/musk-ox.jpg b/img/arts/norway-2023/musk-ox.jpg
index 8cf4645..85d868a 100644
Binary files a/img/arts/norway-2023/musk-ox.jpg and b/img/arts/norway-2023/musk-ox.jpg differ
diff --git a/img/arts/norway-2023/rocks-2.jpg b/img/arts/norway-2023/rocks-2.jpg
index 84cf72e..ddd2ec7 100644
Binary files a/img/arts/norway-2023/rocks-2.jpg and b/img/arts/norway-2023/rocks-2.jpg differ
diff --git a/img/arts/norway-2023/rocks-3.jpg b/img/arts/norway-2023/rocks-3.jpg
index 54bd3ec..ef095e7 100644
Binary files a/img/arts/norway-2023/rocks-3.jpg and b/img/arts/norway-2023/rocks-3.jpg differ
diff --git a/img/arts/norway-2023/rocks.jpg b/img/arts/norway-2023/rocks.jpg
index f5cc8f2..4153066 100644
Binary files a/img/arts/norway-2023/rocks.jpg and b/img/arts/norway-2023/rocks.jpg differ
diff --git a/img/arts/norway-2023/waterfall-close.jpg b/img/arts/norway-2023/waterfall-close.jpg
index 8748633..d8f2f89 100644
Binary files a/img/arts/norway-2023/waterfall-close.jpg and b/img/arts/norway-2023/waterfall-close.jpg differ
diff --git a/img/arts/norway-2023/waterfall.jpg b/img/arts/norway-2023/waterfall.jpg
index b450787..db07f00 100644
Binary files a/img/arts/norway-2023/waterfall.jpg and b/img/arts/norway-2023/waterfall.jpg differ
diff --git a/img/arts/not-silent.jpg b/img/arts/not-silent.jpg
index 7d8dcf9..f247070 100644
Binary files a/img/arts/not-silent.jpg and b/img/arts/not-silent.jpg differ
diff --git a/img/arts/on-mourra-seul.jpg b/img/arts/on-mourra-seul.jpg
index 736eddb..9a58f16 100644
Binary files a/img/arts/on-mourra-seul.jpg and b/img/arts/on-mourra-seul.jpg differ
diff --git a/img/arts/pelican-of-london.jpeg b/img/arts/pelican-of-london.jpeg
index 239d109..15b4665 100644
Binary files a/img/arts/pelican-of-london.jpeg and b/img/arts/pelican-of-london.jpeg differ
diff --git a/img/arts/puffin.jpeg b/img/arts/puffin.jpeg
index 8ca035c..d728873 100644
Binary files a/img/arts/puffin.jpeg and b/img/arts/puffin.jpeg differ
diff --git a/img/arts/seals.jpeg b/img/arts/seals.jpeg
index 864ae09..2f451d7 100644
Binary files a/img/arts/seals.jpeg and b/img/arts/seals.jpeg differ
diff --git a/img/arts/sigh.jpg b/img/arts/sigh.jpg
index 145a016..92059cf 100644
Binary files a/img/arts/sigh.jpg and b/img/arts/sigh.jpg differ
diff --git a/img/arts/sightings-from-a-dream-1.jpg b/img/arts/sightings-from-a-dream-1.jpg
index 2c04a88..6a0cd37 100644
Binary files a/img/arts/sightings-from-a-dream-1.jpg and b/img/arts/sightings-from-a-dream-1.jpg differ
diff --git a/img/arts/sightings-from-a-dream-2.jpg b/img/arts/sightings-from-a-dream-2.jpg
index ad4f732..297b554 100644
Binary files a/img/arts/sightings-from-a-dream-2.jpg and b/img/arts/sightings-from-a-dream-2.jpg differ
diff --git a/img/arts/sightings-from-a-dream-3.jpg b/img/arts/sightings-from-a-dream-3.jpg
index 4b5086f..45cc6a8 100644
Binary files a/img/arts/sightings-from-a-dream-3.jpg and b/img/arts/sightings-from-a-dream-3.jpg differ
diff --git a/img/arts/sightings-from-a-dream-4.jpg b/img/arts/sightings-from-a-dream-4.jpg
index fb8dfbc..31b73d2 100644
Binary files a/img/arts/sightings-from-a-dream-4.jpg and b/img/arts/sightings-from-a-dream-4.jpg differ
diff --git a/img/arts/sightings-from-a-dream-5.jpg b/img/arts/sightings-from-a-dream-5.jpg
index dcbb345..147d617 100644
Binary files a/img/arts/sightings-from-a-dream-5.jpg and b/img/arts/sightings-from-a-dream-5.jpg differ
diff --git a/img/arts/the-night-has-descended-on-us.jpg b/img/arts/the-night-has-descended-on-us.jpg
index afa5ffe..774fc37 100644
Binary files a/img/arts/the-night-has-descended-on-us.jpg and b/img/arts/the-night-has-descended-on-us.jpg differ
diff --git a/img/arts/the-right-way-is-the-untrodden.jpg b/img/arts/the-right-way-is-the-untrodden.jpg
index 0e67357..807a577 100644
Binary files a/img/arts/the-right-way-is-the-untrodden.jpg and b/img/arts/the-right-way-is-the-untrodden.jpg differ
diff --git a/img/arts/trinity-2.jpg b/img/arts/trinity-2.jpg
index 95c6964..04e2dbb 100644
Binary files a/img/arts/trinity-2.jpg and b/img/arts/trinity-2.jpg differ
diff --git a/img/arts/trinity.jpg b/img/arts/trinity.jpg
index 293471d..afc0cbe 100644
Binary files a/img/arts/trinity.jpg and b/img/arts/trinity.jpg differ
diff --git a/img/arts/uganda/african-kob.jpg b/img/arts/uganda/african-kob.jpg
index cc9fc7f..604a08f 100644
Binary files a/img/arts/uganda/african-kob.jpg and b/img/arts/uganda/african-kob.jpg differ
diff --git a/img/arts/uganda/ape.jpg b/img/arts/uganda/ape.jpg
index cbad0d3..03d28ba 100644
Binary files a/img/arts/uganda/ape.jpg and b/img/arts/uganda/ape.jpg differ
diff --git a/img/arts/uganda/baboon-2.jpg b/img/arts/uganda/baboon-2.jpg
index 789d0cc..a57f78a 100644
Binary files a/img/arts/uganda/baboon-2.jpg and b/img/arts/uganda/baboon-2.jpg differ
diff --git a/img/arts/uganda/baboon-yawn.jpg b/img/arts/uganda/baboon-yawn.jpg
index 7525d21..3873654 100644
Binary files a/img/arts/uganda/baboon-yawn.jpg and b/img/arts/uganda/baboon-yawn.jpg differ
diff --git a/img/arts/uganda/baby-gorilla.jpg b/img/arts/uganda/baby-gorilla.jpg
index e908de5..90f1fdc 100644
Binary files a/img/arts/uganda/baby-gorilla.jpg and b/img/arts/uganda/baby-gorilla.jpg differ
diff --git a/img/arts/uganda/baby-gorillas-fighting.jpg b/img/arts/uganda/baby-gorillas-fighting.jpg
index 4af6e5a..c10473e 100644
Binary files a/img/arts/uganda/baby-gorillas-fighting.jpg and b/img/arts/uganda/baby-gorillas-fighting.jpg differ
diff --git a/img/arts/uganda/bird.jpg b/img/arts/uganda/bird.jpg
index a12e584..af3e9d5 100644
Binary files a/img/arts/uganda/bird.jpg and b/img/arts/uganda/bird.jpg differ
diff --git a/img/arts/uganda/buffalo-mud.jpg b/img/arts/uganda/buffalo-mud.jpg
index 4046058..e27dc6d 100644
Binary files a/img/arts/uganda/buffalo-mud.jpg and b/img/arts/uganda/buffalo-mud.jpg differ
diff --git a/img/arts/uganda/buffalos.jpg b/img/arts/uganda/buffalos.jpg
index 12d3a49..6a73ca6 100644
Binary files a/img/arts/uganda/buffalos.jpg and b/img/arts/uganda/buffalos.jpg differ
diff --git a/img/arts/uganda/egret.jpg b/img/arts/uganda/egret.jpg
index d27938b..c02c2b5 100644
Binary files a/img/arts/uganda/egret.jpg and b/img/arts/uganda/egret.jpg differ
diff --git a/img/arts/uganda/gorilla-1.jpg b/img/arts/uganda/gorilla-1.jpg
index 48707bf..63de9cb 100644
Binary files a/img/arts/uganda/gorilla-1.jpg and b/img/arts/uganda/gorilla-1.jpg differ
diff --git a/img/arts/uganda/gorilla-3.jpg b/img/arts/uganda/gorilla-3.jpg
index 1dd1351..abe3325 100644
Binary files a/img/arts/uganda/gorilla-3.jpg and b/img/arts/uganda/gorilla-3.jpg differ
diff --git a/img/arts/uganda/hippo.jpg b/img/arts/uganda/hippo.jpg
index 995a9f6..b71afca 100644
Binary files a/img/arts/uganda/hippo.jpg and b/img/arts/uganda/hippo.jpg differ
diff --git a/img/arts/uganda/hippos-chilling.jpg b/img/arts/uganda/hippos-chilling.jpg
index 1810bf8..02466fc 100644
Binary files a/img/arts/uganda/hippos-chilling.jpg and b/img/arts/uganda/hippos-chilling.jpg differ
diff --git a/img/arts/uganda/kids.jpg b/img/arts/uganda/kids.jpg
index 105488d..ecac166 100644
Binary files a/img/arts/uganda/kids.jpg and b/img/arts/uganda/kids.jpg differ
diff --git a/img/arts/uganda/leopard.jpg b/img/arts/uganda/leopard.jpg
index 35b27ab..263fda2 100644
Binary files a/img/arts/uganda/leopard.jpg and b/img/arts/uganda/leopard.jpg differ
diff --git a/img/arts/uganda/lizard.jpg b/img/arts/uganda/lizard.jpg
index 5f1507c..dd9fa3e 100644
Binary files a/img/arts/uganda/lizard.jpg and b/img/arts/uganda/lizard.jpg differ
diff --git a/img/arts/uganda/monkey.jpg b/img/arts/uganda/monkey.jpg
index d8b6fab..b276c73 100644
Binary files a/img/arts/uganda/monkey.jpg and b/img/arts/uganda/monkey.jpg differ
diff --git a/img/arts/uganda/mud.jpg b/img/arts/uganda/mud.jpg
index 5250390..f7af092 100644
Binary files a/img/arts/uganda/mud.jpg and b/img/arts/uganda/mud.jpg differ
diff --git a/img/arts/uganda/nile-crocodile.jpg b/img/arts/uganda/nile-crocodile.jpg
index d5da212..d210917 100644
Binary files a/img/arts/uganda/nile-crocodile.jpg and b/img/arts/uganda/nile-crocodile.jpg differ
diff --git a/img/arts/uganda/preparing-sand.jpg b/img/arts/uganda/preparing-sand.jpg
index f31ef39..8a3bb81 100644
Binary files a/img/arts/uganda/preparing-sand.jpg and b/img/arts/uganda/preparing-sand.jpg differ
diff --git a/img/arts/uganda/savannah-elephant.jpg b/img/arts/uganda/savannah-elephant.jpg
index 5414455..f52266b 100644
Binary files a/img/arts/uganda/savannah-elephant.jpg and b/img/arts/uganda/savannah-elephant.jpg differ
diff --git a/img/arts/uganda/stork.jpg b/img/arts/uganda/stork.jpg
index 17e3e7c..08fe8b4 100644
Binary files a/img/arts/uganda/stork.jpg and b/img/arts/uganda/stork.jpg differ
diff --git a/img/arts/uganda/sunrise.jpg b/img/arts/uganda/sunrise.jpg
index bb0acd4..283139e 100644
Binary files a/img/arts/uganda/sunrise.jpg and b/img/arts/uganda/sunrise.jpg differ
diff --git a/img/arts/uganda/truck.jpg b/img/arts/uganda/truck.jpg
index f310888..2faa24c 100644
Binary files a/img/arts/uganda/truck.jpg and b/img/arts/uganda/truck.jpg differ
diff --git a/img/arts/uganda/warthog-together.jpg b/img/arts/uganda/warthog-together.jpg
index efa6975..b745159 100644
Binary files a/img/arts/uganda/warthog-together.jpg and b/img/arts/uganda/warthog-together.jpg differ
diff --git a/img/arts/uganda/warthog.jpg b/img/arts/uganda/warthog.jpg
index 1fb429c..0bc4419 100644
Binary files a/img/arts/uganda/warthog.jpg and b/img/arts/uganda/warthog.jpg differ
diff --git a/img/arts/uganda/woman-walking.jpg b/img/arts/uganda/woman-walking.jpg
index 23ebd08..5732f75 100644
Binary files a/img/arts/uganda/woman-walking.jpg and b/img/arts/uganda/woman-walking.jpg differ
diff --git a/img/arts/uploads/260cc99527c13f256d4ea39d0959f5daa942c888ea882852e73fd94f6c30b7db/00.jpg b/img/arts/uploads/260cc99527c13f256d4ea39d0959f5daa942c888ea882852e73fd94f6c30b7db/00.jpg
index de68f47..f03839d 100644
Binary files a/img/arts/uploads/260cc99527c13f256d4ea39d0959f5daa942c888ea882852e73fd94f6c30b7db/00.jpg and b/img/arts/uploads/260cc99527c13f256d4ea39d0959f5daa942c888ea882852e73fd94f6c30b7db/00.jpg differ
diff --git a/img/arts/uploads/474ab3283ce8801ac6e59b67b65b4169167053873a5a8db4a15b840a3448266c/00.jpg b/img/arts/uploads/474ab3283ce8801ac6e59b67b65b4169167053873a5a8db4a15b840a3448266c/00.jpg
index ece3e5d..bf14515 100644
Binary files a/img/arts/uploads/474ab3283ce8801ac6e59b67b65b4169167053873a5a8db4a15b840a3448266c/00.jpg and b/img/arts/uploads/474ab3283ce8801ac6e59b67b65b4169167053873a5a8db4a15b840a3448266c/00.jpg differ
diff --git a/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/00.jpg b/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/00.jpg
index 71b5bdf..7608c1d 100644
Binary files a/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/00.jpg and b/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/00.jpg differ
diff --git a/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/01.jpg b/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/01.jpg
index a6f7a3a..4a497ca 100644
Binary files a/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/01.jpg and b/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/01.jpg differ
diff --git a/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/02.jpg b/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/02.jpg
index a099401..a7d1641 100644
Binary files a/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/02.jpg and b/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/02.jpg differ
diff --git a/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/03.jpg b/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/03.jpg
index 0cd15fd..9de58a2 100644
Binary files a/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/03.jpg and b/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/03.jpg differ
diff --git a/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/04.jpg b/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/04.jpg
index e0ff275..4c60f3a 100644
Binary files a/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/04.jpg and b/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/04.jpg differ
diff --git a/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/05.jpg b/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/05.jpg
index f5e4e61..47e75d7 100644
Binary files a/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/05.jpg and b/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/05.jpg differ
diff --git a/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/06.jpg b/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/06.jpg
index c9776c1..9e20607 100644
Binary files a/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/06.jpg and b/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/06.jpg differ
diff --git a/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/07.jpg b/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/07.jpg
index 85f29a2..2fb722c 100644
Binary files a/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/07.jpg and b/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/07.jpg differ
diff --git a/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/08.jpg b/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/08.jpg
index 7a14bc4..38c5852 100644
Binary files a/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/08.jpg and b/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/08.jpg differ
diff --git a/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/09.jpg b/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/09.jpg
index f5be2de..e057313 100644
Binary files a/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/09.jpg and b/img/arts/uploads/7c832afa1b73023d8f2391ff40c221be9ffd468a1a96a6bf4900cbf95595d31d/09.jpg differ
diff --git a/img/arts/uploads/b18a2f1c7127077c801160782012cb164759f0b9dd41762205b45e4c9a07d673/00.jpg b/img/arts/uploads/b18a2f1c7127077c801160782012cb164759f0b9dd41762205b45e4c9a07d673/00.jpg
index ae74448..420984e 100644
Binary files a/img/arts/uploads/b18a2f1c7127077c801160782012cb164759f0b9dd41762205b45e4c9a07d673/00.jpg and b/img/arts/uploads/b18a2f1c7127077c801160782012cb164759f0b9dd41762205b45e4c9a07d673/00.jpg differ
diff --git a/img/arts/uploads/c53f20236f166632bff163339c8e789cc09b0d7e63c5b531b1fc20705460975b/00.jpg b/img/arts/uploads/c53f20236f166632bff163339c8e789cc09b0d7e63c5b531b1fc20705460975b/00.jpg
index f73b9d7..24f6325 100644
Binary files a/img/arts/uploads/c53f20236f166632bff163339c8e789cc09b0d7e63c5b531b1fc20705460975b/00.jpg and b/img/arts/uploads/c53f20236f166632bff163339c8e789cc09b0d7e63c5b531b1fc20705460975b/00.jpg differ
diff --git a/img/arts/uploads/c53f20236f166632bff163339c8e789cc09b0d7e63c5b531b1fc20705460975b/01.jpg b/img/arts/uploads/c53f20236f166632bff163339c8e789cc09b0d7e63c5b531b1fc20705460975b/01.jpg
index a84d27c..4533883 100644
Binary files a/img/arts/uploads/c53f20236f166632bff163339c8e789cc09b0d7e63c5b531b1fc20705460975b/01.jpg and b/img/arts/uploads/c53f20236f166632bff163339c8e789cc09b0d7e63c5b531b1fc20705460975b/01.jpg differ
diff --git a/img/arts/uploads/c53f20236f166632bff163339c8e789cc09b0d7e63c5b531b1fc20705460975b/02.jpg b/img/arts/uploads/c53f20236f166632bff163339c8e789cc09b0d7e63c5b531b1fc20705460975b/02.jpg
index 4f8499e..ac162e5 100644
Binary files a/img/arts/uploads/c53f20236f166632bff163339c8e789cc09b0d7e63c5b531b1fc20705460975b/02.jpg and b/img/arts/uploads/c53f20236f166632bff163339c8e789cc09b0d7e63c5b531b1fc20705460975b/02.jpg differ
diff --git a/img/arts/uploads/c53f20236f166632bff163339c8e789cc09b0d7e63c5b531b1fc20705460975b/03.jpg b/img/arts/uploads/c53f20236f166632bff163339c8e789cc09b0d7e63c5b531b1fc20705460975b/03.jpg
index 00f9d0d..f74ba75 100644
Binary files a/img/arts/uploads/c53f20236f166632bff163339c8e789cc09b0d7e63c5b531b1fc20705460975b/03.jpg and b/img/arts/uploads/c53f20236f166632bff163339c8e789cc09b0d7e63c5b531b1fc20705460975b/03.jpg differ
diff --git a/img/arts/uploads/c53f20236f166632bff163339c8e789cc09b0d7e63c5b531b1fc20705460975b/04.jpg b/img/arts/uploads/c53f20236f166632bff163339c8e789cc09b0d7e63c5b531b1fc20705460975b/04.jpg
index 96a6979..8771059 100644
Binary files a/img/arts/uploads/c53f20236f166632bff163339c8e789cc09b0d7e63c5b531b1fc20705460975b/04.jpg and b/img/arts/uploads/c53f20236f166632bff163339c8e789cc09b0d7e63c5b531b1fc20705460975b/04.jpg differ
diff --git a/img/arts/workman-cellar-nov-2022/alvaro.jpg b/img/arts/workman-cellar-nov-2022/alvaro.jpg
index 93cd9d5..0ed39db 100644
Binary files a/img/arts/workman-cellar-nov-2022/alvaro.jpg and b/img/arts/workman-cellar-nov-2022/alvaro.jpg differ
diff --git a/img/arts/workman-cellar-nov-2022/aoss.jpg b/img/arts/workman-cellar-nov-2022/aoss.jpg
index dce7087..0ca98df 100644
Binary files a/img/arts/workman-cellar-nov-2022/aoss.jpg and b/img/arts/workman-cellar-nov-2022/aoss.jpg differ
diff --git a/img/arts/workman-cellar-nov-2022/charlie-guitar-2.jpg b/img/arts/workman-cellar-nov-2022/charlie-guitar-2.jpg
index b65eecb..0abd091 100644
Binary files a/img/arts/workman-cellar-nov-2022/charlie-guitar-2.jpg and b/img/arts/workman-cellar-nov-2022/charlie-guitar-2.jpg differ
diff --git a/img/arts/workman-cellar-nov-2022/charlie-guitar.jpg b/img/arts/workman-cellar-nov-2022/charlie-guitar.jpg
index a4ce693..7ac6761 100644
Binary files a/img/arts/workman-cellar-nov-2022/charlie-guitar.jpg and b/img/arts/workman-cellar-nov-2022/charlie-guitar.jpg differ
diff --git a/img/arts/workman-cellar-nov-2022/pierre-callum.jpg b/img/arts/workman-cellar-nov-2022/pierre-callum.jpg
index 4e8991b..ad2dc9b 100644
Binary files a/img/arts/workman-cellar-nov-2022/pierre-callum.jpg and b/img/arts/workman-cellar-nov-2022/pierre-callum.jpg differ
diff --git a/img/arts/workman-cellar-nov-2022/romeo-red.jpg b/img/arts/workman-cellar-nov-2022/romeo-red.jpg
index d398311..71a79d9 100644
Binary files a/img/arts/workman-cellar-nov-2022/romeo-red.jpg and b/img/arts/workman-cellar-nov-2022/romeo-red.jpg differ
diff --git a/photo-upload/README.md b/photo-upload/README.md
index 25b31e6..678510a 100644
--- a/photo-upload/README.md
+++ b/photo-upload/README.md
@@ -2,7 +2,7 @@
Photos → Share → **Publish to blog** → optional caption and highlight name → upload.
-The authenticated upload service converts photos to JPEG (maximum 2560 px), applies
+The authenticated upload service converts photos to progressive JPEG (maximum 1600 px and 300 KiB), applies
orientation, converts embedded color profiles to sRGB, and strips public metadata.
Originals stay in a private volume. A worker commits optimized images and an `_art`
entry to **github.com/mdibaiee/mahdi.blog**, on `master`.
@@ -150,7 +150,8 @@ Create **Publish to blog**:
only `published` means the deployed site's receipt contains this album.
The ZIP route accepts 1–20 images in archive-entry order and keeps them as one
-album. The first image in that order is the highlight target. Metadata sidecars
+upload. Each photo renders as its own gallery ``, including photos in older
+batches. The caption appears on each photo; the first image is the highlight target. Metadata sidecars
under `__MACOSX/` and `.DS_Store` are ignored. Ordinary API clients can also send
repeated `photos` parts; send either `archive` or `photos`, never both.
Select still photos; videos/Live Photo video components aren't supported. Dates
@@ -158,6 +159,10 @@ are upload time in UTC; captions are plain text. A caption is optional.
An optional highlight name (up to 200 characters) adds one link to **Highlights**,
pointing to the first photo in the batch. Leave it blank for an ordinary upload.
+Gallery images are progressive JPEGs with a maximum edge of 1600 pixels and a
+300 KiB size limit. The uploader tries moderate JPEG quality levels, then reduces
+dimensions further when necessary. Private originals are retained unchanged.
+
The token is visible in the shortcut editor; remove it before sharing the shortcut.
Rotate it by replacing the token file and recreating the upload container with
`podman compose up -d --force-recreate upload`.
@@ -303,9 +308,11 @@ photo anchors so the service does not mistake a successful push for publication.
Back up the private `photo-data` volume (originals and job state) and GitHub's
repository. `photo-work` is disposable. Never expose private data through nginx or
-run `compose down -v`. Originals and deployment releases are retained, so monitor
-disk usage and periodically remove old releases (never `current` or an in-progress
-release). Interrupted uploads may leave files in `photo-data/temporary`; clean that
+run `compose down -v`. Originals are retained, so monitor disk usage. After a
+successful deployment switches `current`, all older releases are automatically
+pruned; newer uploads still in progress are preserved. There are no retained
+server-side rollback copies; rebuild an older Git revision if needed.
+Interrupted uploads may leave files in `photo-data/temporary`; clean that
folder only while the API is stopped. Public Git images are optimized copies.
## Tests
diff --git a/photo-upload/app.py b/photo-upload/app.py
index 1bc24ee..ba2f3ff 100644
--- a/photo-upload/app.py
+++ b/photo-upload/app.py
@@ -22,6 +22,8 @@ from posts import parse_upload
register_heif_opener()
Image.MAX_IMAGE_PIXELS = 60_000_000
+GALLERY_MAX_EDGE = 1600
+GALLERY_MAX_BYTES = 300 * 1024
warnings.simplefilter("error", Image.DecompressionBombWarning)
@@ -47,7 +49,7 @@ def web_image(raw, destination):
if original.format not in {"JPEG", "PNG", "WEBP", "HEIF"}:
raise ValueError("Use JPEG, PNG, WebP, or HEIC photos")
image = ImageOps.exif_transpose(original)
- image.thumbnail((2560, 2560), Image.Resampling.LANCZOS)
+ image.thumbnail((GALLERY_MAX_EDGE, GALLERY_MAX_EDGE), Image.Resampling.LANCZOS)
if image.info.get("icc_profile"):
image = ImageCms.profileToProfile(
image, ImageCms.ImageCmsProfile(io.BytesIO(image.info["icc_profile"])),
@@ -63,7 +65,18 @@ def web_image(raw, destination):
# Copy pixels only; no EXIF, GPS, XMP, comments, or original profile.
clean = Image.new("RGB", image.size)
clean.paste(image)
- clean.save(destination, "JPEG", quality=88, optimize=True)
+ # Keep a useful display size and moderate JPEG quality, even for grainy photos.
+ # If quality alone cannot meet the budget, reduce dimensions instead of
+ # introducing severe compression artifacts. Originals remain untouched.
+ while True:
+ for quality in (82, 78, 74):
+ output = io.BytesIO()
+ clean.save(output, "JPEG", quality=quality, optimize=True, progressive=True)
+ if output.tell() <= GALLERY_MAX_BYTES:
+ Path(destination).write_bytes(output.getvalue())
+ return
+ clean.thumbnail((max(1, int(clean.width * 0.85)), max(1, int(clean.height * 0.85))),
+ Image.Resampling.LANCZOS)
def create_app(data_dir=None, token=None):
diff --git a/photo-upload/tests/test_upload.py b/photo-upload/tests/test_upload.py
index a36b577..93cae9a 100644
--- a/photo-upload/tests/test_upload.py
+++ b/photo-upload/tests/test_upload.py
@@ -62,13 +62,18 @@ def test_validation_is_all_or_nothing(service):
def test_multi_megabyte_multipart_file(service):
- _, client, _ = service
+ _, client, data = service
output = io.BytesIO()
Image.frombytes("RGB", (1800, 1800), random.Random(2).randbytes(1800 * 1800 * 3)).save(
output, "JPEG", quality=95)
assert len(output.getvalue()) > 3 * 1024 * 1024
response = upload(client, [output.getvalue()])
assert response.status_code == 202, response.json
+ path = data / "submissions" / response.json["id"] / "images/00.jpg"
+ assert path.stat().st_size <= 300 * 1024
+ with Image.open(path) as image:
+ assert max(image.size) <= 1600
+ assert image.info.get("progressive")
def test_zip_batch_preserves_all_images_order_and_deduplicates(service):
@@ -137,7 +142,7 @@ def test_orientation_metadata_and_heic(service):
with Image.open(data / "submissions" / response.json["id"] / "images/00.jpg") as image:
assert image.format == "JPEG"
assert not image.getexif()
- assert max(image.size) <= 2560
+ assert max(image.size) <= 1600
if raw[:2] == b"\xff\xd8":
assert image.height > image.width
diff --git a/scripts/deploy-site.sh b/scripts/deploy-site.sh
index 7a35637..7053593 100644
--- a/scripts/deploy-site.sh
+++ b/scripts/deploy-site.sh
@@ -35,7 +35,7 @@ ssh "${ssh_options[@]}" "$target" "mkdir -p '$release'"
# Checksums and hard links avoid retransmitting existing photos on every build.
printf -v transport 'ssh -i %q -p %q -o BatchMode=yes -o IdentitiesOnly=yes -o StrictHostKeyChecking=yes -o UserKnownHostsFile=%q' \
"$credentials/key" "$DEPLOY_PORT" "$credentials/known_hosts"
-rsync -azc --delete --link-dest="$DEPLOY_PATH/current/" -e "$transport" _site/ "$target:$release/"
+rsync -azc --no-times --delete --link-dest="$DEPLOY_PATH/current/" -e "$transport" _site/ "$target:$release/"
ssh "${ssh_options[@]}" "$target" "bash -s -- '$DEPLOY_PATH' '$release' '$GITHUB_RUN_NUMBER'" <<'REMOTE'
set -euo pipefail
destination=$1
@@ -58,5 +58,22 @@ chmod -R a+rX "$release"
temporary="$destination/.current-$run-$$"
ln -s "releases/$(basename "$release")" "$temporary"
mv -Tf "$temporary" "$destination/current"
+python3 - "$destination" "$run" <<'PRUNE'
+from pathlib import Path
+import re
+import shutil
+import sys
+
+root = Path(sys.argv[1])
+current = (root / 'current').resolve(strict=True)
+run = int(sys.argv[2])
+for old in (root / 'releases').iterdir():
+ if not old.is_dir() or old.is_symlink() or old.resolve() == current:
+ continue
+ match = re.fullmatch(r'(\d+)(?:-\d+-[a-f0-9]{40})?', old.name)
+ # A higher-numbered release may still be transferring; it will prune us later.
+ if match and int(match.group(1)) <= run:
+ shutil.rmtree(old)
+PRUNE
echo "Deployed $release"
REMOTE
diff --git a/scripts/tests/gallery_items_test.rb b/scripts/tests/gallery_items_test.rb
new file mode 100644
index 0000000..e21f26b
--- /dev/null
+++ b/scripts/tests/gallery_items_test.rb
@@ -0,0 +1,30 @@
+require 'liquid'
+require 'nokogiri'
+require_relative '../../_plugins/gallery_items'
+require_relative '../../_plugins/lazy_images'
+
+class GalleryRenderer
+ include GalleryItems
+ include LazyImages
+end
+
+renderer = GalleryRenderer.new
+batch = '' +
+ '
' +
+ '
' +
+ 'A & B
Caption'
+items = renderer.gallery_items(renderer.lazy_images(batch))
+raise 'Expected one item per uploaded photo' unless items.length == 2
+items.each_with_index do |item, index|
+ html = Nokogiri::HTML::DocumentFragment.parse(item)
+ raise 'Each item must contain one photo' unless html.css('img').length == 1
+ raise 'Photo order changed' unless html.at_css('img')['src'].end_with?("0#{index}.jpg")
+ raise 'Lazy loading lost' unless html.at_css('img')['loading'] == 'lazy'
+ raise 'Caption lost' unless html.at_css('.image-details').text == 'A & BCaption'
+ raise 'Anchor must occur on the first photo only' unless html.css('#photo-batch').length == (index.zero? ? 1 : 0)
+end
+single = '
'
+raise 'Single photo changed' unless renderer.gallery_items(single) == [single]
+legacy = '
Existing artwork content
'
+raise 'Legacy artwork changed' unless renderer.gallery_items(legacy) == [legacy]
+puts 'Gallery item regression checks passed'
diff --git a/scripts/tests/test_deployment.py b/scripts/tests/test_deployment.py
index 4ecaa15..e1a4db4 100644
--- a/scripts/tests/test_deployment.py
+++ b/scripts/tests/test_deployment.py
@@ -48,6 +48,10 @@ class DeploymentTests(unittest.TestCase):
self.assertEqual((root / 'current/art/index.html').read_text(), '2')
self.assertEqual(activate(4).returncode, 0)
self.assertEqual((root / 'current/art/index.html').read_text(), '4')
+ self.assertEqual([p.name for p in (root / 'releases').iterdir()], ['4'])
+ (root / 'releases/6').mkdir() # A newer upload is still transferring.
+ self.assertEqual(activate(5).returncode, 0)
+ self.assertEqual(sorted(p.name for p in (root / 'releases').iterdir()), ['5', '6'])
if __name__ == '__main__':