diff --git a/README.md b/README.md
index 7addd95..d380b96 100644
--- a/README.md
+++ b/README.md
@@ -5,3 +5,7 @@ This project contains my hand-written HTML homepage for the world-wide-web.
It's meant to be deployed as a simple set of files on a server, and doesn't
use anything fancy beyond what can be done with a normal text editor and an
HTTP file server.
+
+To develop it locally, it can help to run a local server, so for that, I've
+included `local-server.d`, a D script you can run to boot up a server on
+`http://localhost:8080`.
diff --git a/garden-data-gen/.gitignore b/garden-data-gen/.gitignore
new file mode 100644
index 0000000..1706ba0
--- /dev/null
+++ b/garden-data-gen/.gitignore
@@ -0,0 +1,16 @@
+.dub
+docs.json
+__dummy.html
+docs/
+/garden-data-gen
+garden-data-gen.so
+garden-data-gen.dylib
+garden-data-gen.dll
+garden-data-gen.a
+garden-data-gen.lib
+garden-data-gen-test-*
+*.exe
+*.pdb
+*.o
+*.obj
+*.lst
diff --git a/garden-data-gen/dub.json b/garden-data-gen/dub.json
new file mode 100644
index 0000000..cd1852b
--- /dev/null
+++ b/garden-data-gen/dub.json
@@ -0,0 +1,13 @@
+{
+ "authors": [
+ "Andrew Lalis"
+ ],
+ "copyright": "Copyright © 2024, Andrew Lalis",
+ "dependencies": {
+ "archive": "~>0.7.1",
+ "dxml": "~>0.4.4"
+ },
+ "description": "Small app for dynamically generating garden site HTML from data.",
+ "license": "proprietary",
+ "name": "garden-data-gen"
+}
\ No newline at end of file
diff --git a/garden-data-gen/dub.selections.json b/garden-data-gen/dub.selections.json
new file mode 100644
index 0000000..6e1b9e6
--- /dev/null
+++ b/garden-data-gen/dub.selections.json
@@ -0,0 +1,7 @@
+{
+ "fileVersion": 1,
+ "versions": {
+ "archive": "0.7.1",
+ "dxml": "0.4.4"
+ }
+}
diff --git a/garden-data-gen/source/app.d b/garden-data-gen/source/app.d
new file mode 100644
index 0000000..65a6c39
--- /dev/null
+++ b/garden-data-gen/source/app.d
@@ -0,0 +1,29 @@
+import std.stdio;
+
+import plant_data;
+import content_gen;
+
+import std.algorithm;
+import std.array;
+import std.path;
+import std.file;
+
+const PLANT_DATA_FILE = "garden-plant-data.ods";
+
+void main() {
+ // Navigate to the project root for all tasks, for simplicity.
+ while (!exists("index.html") && !exists("upload.sh")) {
+ string prev = getcwd();
+ chdir("..");
+ if (getcwd == prev) throw new Exception("Couldn't navigate to the project root.");
+ }
+
+ writeln("Parsing plant data from " ~ PLANT_DATA_FILE ~ "...");
+ PlantData data = parsePlantData(PLANT_DATA_FILE);
+ writefln!"Read %d species and %d plants."(data.species.length, data.plants.length);
+ ensureDirectories(data);
+ writeln("Generating thumbnails for all images...");
+ generateAllThumbnails(false);
+ writeln("Rendering HTML components...");
+ renderHTML(data);
+}
diff --git a/garden-data-gen/source/content_gen.d b/garden-data-gen/source/content_gen.d
new file mode 100644
index 0000000..f2ca108
--- /dev/null
+++ b/garden-data-gen/source/content_gen.d
@@ -0,0 +1,142 @@
+module content_gen;
+
+import plant_data;
+import dom_utils;
+
+import dxml.writer;
+import dxml.util;
+
+import std.stdio;
+import std.path;
+import std.array;
+import std.algorithm;
+import std.file;
+import std.conv;
+
+void renderHTML(PlantData data) {
+ renderSpeciesCards(data);
+ renderSpeciesPages(data);
+}
+
+private void injectContent(string filename, string startTag, string endTag, string newContent) {
+ import std.file;
+ string data = std.file.readText(filename);
+ ptrdiff_t startIdx = indexOfStr(data, startTag);
+ if (startIdx == -1) throw new Exception("Couldn't find start tag " ~ startTag);
+ ptrdiff_t endIdx = indexOfStr(data, endTag);
+ if (endIdx == -1) throw new Exception("Couldn't find end tag " ~ endTag);
+ string prefix = data[0..(startIdx + startTag.length)];
+ string suffix = data[endIdx..$];
+ string newData = prefix ~ newContent ~ suffix;
+ std.file.write(filename, newData);
+}
+
+private void renderSpeciesCards(PlantData data) {
+ string tpl = std.file.readText(buildPath(
+ "garden-data-gen", "templates", "species-card.html"
+ ));
+ Appender!string htmlApp;
+ foreach (s; data.species) {
+ string card = replaceAll(tpl, [
+ "!NAME!": s.name,
+ "!SCIENTIFIC_NAME!": s.scientificName,
+ "!DESCRIPTION!": s.description,
+ "!LINK!": "garden/species/" ~ s.id ~ ".html",
+ "!REF_LINK!": s.referenceLink,
+ "!REF_LINK_TEXT!": s.referenceLink
+ ]);
+ ImageFilePair[] imagePairs = getSpeciesImages(s.id);
+ if (imagePairs.length > 0) {
+ string imageFile = imagePairs[0].filename;
+ string thumbnailFile = imagePairs[0].thumbnailFilename;
+ string imgTag = " ";
+ card = replaceFirst(card, "!IMAGE!", imgTag);
+ } else {
+ card = replaceFirst(card, "!IMAGE!", "");
+ }
+ htmlApp ~= "\n" ~ card;
+ }
+ injectContent(
+ "garden.html",
+ "",
+ "",
+ htmlApp[]
+ );
+}
+
+private void renderSpeciesPages(PlantData data) {
+ string tpl = std.file.readText(buildPath(
+ "garden-data-gen", "templates", "species-page.html"
+ ));
+ string plantCardTpl = std.file.readText(buildPath(
+ "garden-data-gen", "templates", "plant-card.html"
+ ));
+ string speciesPagesDir = buildPath("garden", "species");
+ if (!exists(speciesPagesDir)) mkdirRecurse(speciesPagesDir);
+ foreach (species; data.species) {
+ Appender!string plantDivsApp;
+ foreach (plant; data.plantsInSpecies(species)) {
+ string card = replaceAll(plantCardTpl, [
+ "!IDENTIFIER!": plant.identifier,
+ "!GENERATION!": "F" ~ plant.generation.to!string,
+ "!DESCRIPTION!": plant.description,
+ "!PLANTING_INFO!": plant.plantingInfo
+ ]);
+ ImageFilePair[] imagePairs = getPlantImages(plant.identifier);
+ Appender!string imagesApp;
+ foreach (imagePair; imagePairs) {
+ import std.format;
+ const imgTpl = "\n" ~
+ " \n" ~
+ " \n";
+ imagesApp ~= format!(imgTpl)(
+ "../../" ~ imagePair.filename,
+ imagePair.width, imagePair.height,
+ "../../" ~ imagePair.thumbnailFilename,
+ );
+ }
+ card = replaceFirst(card, "!IMAGES!", imagesApp[]);
+ plantDivsApp ~= card;
+ }
+
+ string page = replaceAll(tpl, [
+ "!HEAD_TITLE!": species.name,
+ "!PAGE_TITLE!": species.scientificName,
+ "!ABOUT_TITLE!": "About " ~ species.name,
+ "!ABOUT_TEXT!": species.description,
+ "!REF_LINK!": species.referenceLink,
+ "!REF_LINK_TEXT!": species.referenceLink,
+ "!PLANTS_DIVS!": plantDivsApp[]
+ ]);
+ string pagePath = buildPath(speciesPagesDir, species.id ~ ".html");
+ std.file.write(pagePath, page);
+ }
+}
+
+ptrdiff_t indexOfStr(string source, string target) {
+ for (size_t i = 0; i < source.length - target.length; i++) {
+ if (source[i..i+target.length] == target) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+string replaceFirst(string source, string from, string to) {
+ ptrdiff_t idx = indexOfStr(source, from);
+ if (idx == -1) return source;
+ string pre = idx == 0 ? "" : source[0..idx];
+ string post = source[idx+from.length..$];
+ return pre ~ to ~ post;
+}
+
+unittest {
+ assert(replaceFirst("
!TEST
", "!TEST", "test") == "test
");
+}
+
+string replaceAll(string source, string[string] values) {
+ foreach (k, v; values) {
+ source = replaceFirst(source, k, v);
+ }
+ return source;
+}
diff --git a/garden-data-gen/source/dom_utils.d b/garden-data-gen/source/dom_utils.d
new file mode 100644
index 0000000..be3bf1a
--- /dev/null
+++ b/garden-data-gen/source/dom_utils.d
@@ -0,0 +1,77 @@
+module dom_utils;
+
+import dxml.dom;
+import dxml.writer;
+import dxml.util;
+
+import std.array;
+import std.algorithm;
+
+DOMEntity!string findDOMChild(
+ DOMEntity!string parent,
+ string elementName,
+ string[string] attributes = string[string].init
+) {
+ foreach (child; parent.children) {
+ if (child.type == EntityType.elementStart && child.name == elementName) {
+ if (attributes.length == 0) return child;
+ bool attributesMatch = true;
+ foreach (attrName, attrValue; attributes) {
+ bool hasValue = false;
+ foreach (attr; child.attributes) {
+ if (attr.name == attrName && attr.value == attrValue) {
+ hasValue = true;
+ break;
+ }
+ }
+ if (!hasValue) {
+ attributesMatch = false;
+ break;
+ }
+ }
+ if (attributesMatch) return child;
+ }
+ }
+ throw new Exception("Could not find child element " ~ elementName ~ " in " ~ parent.name);
+}
+
+DOMEntity!string[] findDOMChildren(DOMEntity!string parent, string name) {
+ DOMEntity!string[] matches;
+ auto app = appender(&matches);
+ foreach (child; parent.children) {
+ if (child.type == EntityType.elementStart && child.name == name) {
+ app ~= child;
+ }
+ }
+ return matches;
+}
+
+string readTableCellText(DOMEntity!string cell) {
+ if (
+ cell.type == EntityType.elementStart &&
+ cell.children.length > 0 &&
+ cell.children[0].type == EntityType.elementStart &&
+ cell.children[0].children.length == 1 &&
+ cell.children[0].children[0].type == EntityType.text
+ ) {
+ return cell.children[0].children[0].text.decodeXML;
+ }
+ return null;
+}
+
+void writeStartTagWithAttrs(O)(
+ ref XMLWriter!O writer,
+ string tag,
+ string[string] attributes,
+ EmptyTag emptyTag = EmptyTag.no
+) {
+ writer.openStartTag(tag);
+ foreach (k, v; attributes) {
+ writer.writeAttr(k, v);
+ }
+ writer.closeStartTag(emptyTag);
+}
+
+void writeStartTagWithClass(O)(ref XMLWriter!O writer, string tag, string classValue) {
+ writer.writeStartTagWithAttrs(tag, ["class": classValue]);
+}
diff --git a/garden-data-gen/source/plant_data.d b/garden-data-gen/source/plant_data.d
new file mode 100644
index 0000000..fc302d9
--- /dev/null
+++ b/garden-data-gen/source/plant_data.d
@@ -0,0 +1,270 @@
+module plant_data;
+
+import dom_utils;
+
+import std.stdio;
+import std.array;
+import std.algorithm;
+import std.path;
+import std.file;
+import std.datetime;
+import std.typecons;
+
+import dxml.dom;
+
+struct Species {
+ string id;
+ string name;
+ string scientificName;
+ string description;
+ string referenceLink;
+}
+
+struct Plant {
+ string speciesScientificName;
+ string identifier;
+ uint generation;
+ string plantingInfo;
+ string description;
+}
+
+string speciesId(string scientificName) {
+ import std.string;
+ import std.regex;
+ return scientificName
+ .replaceAll(ctRegex!(`\s+`), "-")
+ .replaceAll(ctRegex!(`ñ`), "n")
+ .replaceAll(ctRegex!(`["“”\.]`), "")
+ .toLower;
+}
+
+struct PlantData {
+ Species[] species;
+ Plant[] plants;
+
+ Plant[] plantsInSpecies(Species speciesItem) {
+ Appender!(Plant[]) app;
+ foreach (plant; plants) {
+ if (plant.speciesScientificName == speciesItem.scientificName) {
+ app ~= plant;
+ }
+ }
+ Plant[] results = app[];
+ sort!((a, b) => a.identifier < b.identifier)(results);
+ return results;
+ }
+
+ Species getSpecies(string name) {
+ foreach (s; species) {
+ if (s.scientificName == name) return s;
+ }
+ throw new Exception("No species with name " ~ name);
+ }
+
+ Plant getPlant(string identifier) {
+ foreach (p; plants) {
+ if (p.identifier == identifier) return p;
+ }
+ throw new Exception("No plant with identifier " ~ identifier);
+ }
+}
+
+struct ImageFilePair {
+ string filename;
+ uint width, height;
+ string thumbnailFilename;
+ uint thumbnailWidth, thumbnailHeight;
+}
+
+PlantData parsePlantData(string filename) {
+ import archive.zip;
+ ZipArchive zip = new ZipArchive(std.file.read(filename));
+ auto contentZipEntry = zip.getFile("content.xml");
+ if (contentZipEntry is null) throw new Exception("Couldn't find content.xml in " ~ filename);
+ DOMEntity!string dom = parseDOM(cast(string) contentZipEntry.data());
+ DOMEntity!string spreadsheet = dom.findDOMChild("office:document-content")
+ .findDOMChild("office:body")
+ .findDOMChild("office:spreadsheet");
+ DOMEntity!string speciesTable = spreadsheet.findDOMChild("table:table", ["table:name": "Species"]);
+ DOMEntity!string[] speciesRows = speciesTable.findDOMChildren("table:table-row")[1..$];
+ DOMEntity!string plantsTable = spreadsheet.findDOMChild("table:table", ["table:name": "Plants"]);
+ DOMEntity!string[] plantRows = plantsTable.findDOMChildren("table:table-row")[1..$];
+
+ PlantData result;
+ auto speciesAppender = appender(&result.species);
+ foreach (row; speciesRows) {
+ if (row.children.length < 4) continue;
+ Species species;
+ species.name = readTableCellText(row.children[0]);
+ species.scientificName = readTableCellText(row.children[1]);
+ species.description = readTableCellText(row.children[2]);
+ species.referenceLink = readTableCellText(row.children[3]);
+ species.id = speciesId(species.scientificName);
+ speciesAppender ~= species;
+ }
+ sort!((a, b) => a.name < b.name)(result.species);
+
+ auto plantAppender = appender(&result.plants);
+ foreach (row; plantRows) {
+ if (row.children.length < 4) continue;
+ Plant plant;
+ plant.speciesScientificName = readTableCellText(row.children[0]);
+ plant.identifier = readTableCellText(row.children[1]);
+ string fGenStr = readTableCellText(row.children[2]);
+ import std.conv : to;
+ plant.generation = fGenStr[1..$].to!uint;
+ plant.plantingInfo = readTableCellText(row.children[3]);
+ if (row.children.length > 4) {
+ plant.description = readTableCellText(row.children[4]);
+ }
+ plantAppender ~= plant;
+ }
+ sort!((a, b) => a.identifier < b.identifier)(result.plants);
+
+ return result;
+}
+
+void ensureDirectories(PlantData data) {
+ string basePath = buildPath("images", "garden");
+ if (!exists(basePath)) mkdirRecurse(basePath);
+ string speciesDir = buildPath(basePath, "species");
+ if (!exists(speciesDir)) mkdir(speciesDir);
+ foreach (s; data.species) {
+ string thisSpeciesDir = buildPath(speciesDir, s.id);
+ if (!exists(thisSpeciesDir)) mkdir(thisSpeciesDir);
+ }
+ string plantsDir = buildPath(basePath, "plants");
+ if (!exists(plantsDir)) mkdir(plantsDir);
+ foreach (p; data.plants) {
+ string thisPlantDir = buildPath(plantsDir, p.identifier);
+ if (!exists(thisPlantDir)) mkdir(thisPlantDir);
+ }
+}
+
+ImageFilePair[] getPlantImages(string identifier) {
+ string plantDir = buildPath("images", "garden", "plants", identifier);
+ if (!exists(plantDir)) return [];
+ Appender!(ImageFilePair[]) app;
+ foreach (entry; dirEntries(plantDir, SpanMode.shallow, false)) {
+ if (entry.name.endsWith(".jpg") && !entry.name.endsWith(".thumb.jpg")) {
+ ImageFilePair pair;
+ pair.filename = entry.name;
+ getImageSize(entry.name, pair.width, pair.height);
+ string thumbnailFilename = buildPath(plantDir, baseName(entry.name, ".jpg") ~ ".thumb.jpg");
+ if (exists(thumbnailFilename)) {
+ pair.thumbnailFilename = thumbnailFilename;
+ getImageSize(thumbnailFilename, pair.thumbnailWidth, pair.thumbnailHeight);
+ }
+ app ~= pair;
+ }
+ }
+ ImageFilePair[] images = app[];
+ sort!((a, b) {
+ Nullable!DateTime tsA = getImageTimestamp(a.filename);
+ Nullable!DateTime tsB = getImageTimestamp(b.filename);
+ if (tsA.isNull && tsB.isNull) return a.filename < b.filename;
+ if (tsA.isNull) return true;
+ if (tsB.isNull) return false;
+ return tsA.get < tsB.get;
+ })(images);
+ return images;
+}
+
+ImageFilePair[] getSpeciesImages(string speciesId) {
+ string speciesDir = buildPath("images", "garden", "species", speciesId);
+ if (!exists(speciesDir)) return [];
+ Appender!(ImageFilePair[]) app;
+ foreach (entry; dirEntries(speciesDir, SpanMode.shallow, false)) {
+ if (entry.name.endsWith(".jpg") && !entry.name.endsWith(".thumb.jpg")) {
+ ImageFilePair pair;
+ pair.filename = entry.name;
+ getImageSize(entry.name, pair.width, pair.height);
+ string thumbnailFilename = buildPath(speciesDir, baseName(entry.name, ".jpg") ~ ".thumb.jpg");
+ if (exists(thumbnailFilename)) {
+ pair.thumbnailFilename = thumbnailFilename;
+ getImageSize(thumbnailFilename, pair.thumbnailWidth, pair.thumbnailHeight);
+ }
+ app ~= pair;
+ }
+ }
+ ImageFilePair[] images = app[];
+ sort!((a, b) {
+ Nullable!DateTime tsA = getImageTimestamp(a.filename);
+ Nullable!DateTime tsB = getImageTimestamp(b.filename);
+ if (tsA.isNull && tsB.isNull) return a.filename < b.filename;
+ if (tsA.isNull) return true;
+ if (tsB.isNull) return false;
+ return tsA.get < tsB.get;
+ })(images);
+ return images;
+}
+
+void getImageSize(string filePath, out uint width, out uint height) {
+ import std.process;
+ import std.format;
+ auto result = execute(["identify", "-ping", "-format", "'%w %h'", filePath]);
+ if (result.status != 0) throw new Exception("Failed to get image size of " ~ filePath);
+ formattedRead!"'%d %d'"(result.output, width, height);
+}
+
+Nullable!DateTime getImageTimestamp(string filePath) {
+ import std.regex;
+ import std.conv;
+ auto r = ctRegex!(`\d{8}_\d{6}`);
+ auto cap = matchFirst(baseName(filePath), r);
+ if (cap.empty) return Nullable!DateTime.init;
+ string text = cap[0];
+ return nullable(DateTime(
+ text[0..4].to!int,
+ text[4..6].to!int,
+ text[6..8].to!int,
+ text[9..11].to!int,
+ text[11..13].to!int,
+ text[13..15].to!int
+ ));
+}
+
+void generateAllThumbnails(bool regen = false) {
+ string plantsDir = buildPath("images", "garden", "plants");
+ foreach (entry; dirEntries(plantsDir, SpanMode.shallow, false)) {
+ generateThumbnails(entry.name, regen);
+ }
+ string speciesDir = buildPath("images", "garden", "species");
+ foreach (entry; dirEntries(speciesDir, SpanMode.shallow, false)) {
+ generateThumbnails(entry.name, regen);
+ }
+}
+
+void generateThumbnails(string dir, bool regen) {
+ import std.process;
+ if (regen) {
+ // Remove all thumbnails first.
+ foreach (entry; dirEntries(dir, SpanMode.shallow, false)) {
+ if (entry.name.endsWith(".thumb.jpg")) {
+ std.file.remove(entry.name);
+ }
+ }
+ }
+ foreach (entry; dirEntries(dir, SpanMode.shallow, false)) {
+ if (entry.name.endsWith(".jpg") && !entry.name.endsWith(".thumb.jpg")) {
+ string filenameWithoutExt = baseName(entry.name, ".jpg");
+ string outputFilePath = buildPath(dir, filenameWithoutExt ~ ".thumb.jpg");
+ if (exists(outputFilePath)) continue;
+ Pid pid = spawnProcess(
+ [
+ "convert",
+ entry.name,
+ "-strip",
+ "-interlace", "JPEG",
+ "-sampling-factor", "4:2:0",
+ "-colorspace", "RGB",
+ "-quality", "85%",
+ "-geometry", "x200",
+ outputFilePath
+ ]
+ );
+ int exitCode = wait(pid);
+ if (exitCode != 0) throw new Exception("Thumbnail generation process failed.");
+ }
+ }
+}
diff --git a/garden-data-gen/templates/plant-card.html b/garden-data-gen/templates/plant-card.html
new file mode 100644
index 0000000..05f01e4
--- /dev/null
+++ b/garden-data-gen/templates/plant-card.html
@@ -0,0 +1,14 @@
+
+
+ !IDENTIFIER!
+ Generation !GENERATION!
+ !DESCRIPTION!
+ !PLANTING_INFO!
+
+
+ Images
+
+ !IMAGES!
+
+
+
\ No newline at end of file
diff --git a/garden-data-gen/templates/species-card.html b/garden-data-gen/templates/species-card.html
new file mode 100644
index 0000000..9c5ca52
--- /dev/null
+++ b/garden-data-gen/templates/species-card.html
@@ -0,0 +1,19 @@
+
+
+
+
+ !SCIENTIFIC_NAME!
+
+ !DESCRIPTION!
+
+
+ !IMAGE!
+
\ No newline at end of file
diff --git a/garden-data-gen/templates/species-page.html b/garden-data-gen/templates/species-page.html
new file mode 100644
index 0000000..14b6fec
--- /dev/null
+++ b/garden-data-gen/templates/species-page.html
@@ -0,0 +1,71 @@
+
+
+
+
+ Andrew's Garden: !HEAD_TITLE!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ !ABOUT_TITLE!
+ !ABOUT_TEXT!
+
+
+ !REF_LINK_TEXT!
+
+
+
+
+ Plants
+
+ Here's a detailed list of all plants I have of this species.
+
+ !PLANTS_DIVS!
+
+
+
diff --git a/garden-plant-data.ods b/garden-plant-data.ods
new file mode 100644
index 0000000..b300ef3
Binary files /dev/null and b/garden-plant-data.ods differ
diff --git a/garden.html b/garden.html
index 8c88609..f36e397 100644
--- a/garden.html
+++ b/garden.html
@@ -12,6 +12,18 @@
+
+
+
@@ -43,7 +55,16 @@
My garden is just a small patch of land outside the condo my wife and I call home. It's located in USDA hardiness zone 10a (actually, right on the border of 9b and 10a) in Florida, USA, and I've been trying to beautify the space with a mixture of native and non-invasive ornamental shrubs, herbs, and other plants. While currently there are quite a few non-native species, I'm trying to slowly migrate to entirely native plants and non-invasive food crops, especially those that can help rebuild the soil quality; it's pretty much just sandy clay here.
-
+
+
+
+
+
+
If you'd like to leave feedback about the garden, or to request seeds, cuttings, please do contact me via the info on my contact page . I generally try to keep a supply of seeds for as many of my plants as possible, but as always, it depends.
@@ -53,253 +74,360 @@
Table of Contents
- Plants
+ Species
Hardscaping
- Plants
+ Species
- Here's a detailed list of all the plants I've got in my garden. For each plant, I try to include its scientific name, place of origin, and a small description, usually taken from Wikipedia or other sources listed at the bottom of each plant's info.
+ Here's a detailed list of all the species I've got in my garden. For each species, I try to include its scientific name, place of origin, and a small description, usually taken from Wikipedia or other sources listed at the bottom of each species' info.
-
-
-
- Bird Pepper
- Capsicum annuum var. glabriusculum
- A small chili pepper variety native to southern North America and northern South America. It's the only pepper species native to the Floridian peninsula.
- Transplanted from a 1 gallon pot, on February 10th, 2024.
-
-
-
-
-
-
-
- Blue Pacific Juniper
- Juniperus conferta
- A species of Juniper native to Japan, that grows on sand dunes and other acidic/alkaline soils with good drainage. It forms a groundcover if left unattended.
- Transplanted on the 2nd of March, 2024.
-
-
-
-
-
-
-
- Browne's Savory
- Clinopodium brownei
- A sprawling perennial herb found natively in the coastal plains and marshes of the southeastern United States.
- Transplanted on the 10th of February, 2024.
-
-
-
-
-
-
-
- Catnip
- Nepeta cataria
- Species of mint that about 2/3rds of cats are attracted to.
- Native to southern and eastern Europe, the Middle East, Central Asia, and parts of China.
- Transplanted from a small pot bought at a pet store, sometime in October, 2023.
-
-
-
-
-
-
-
- Garlic Chives
- Allium tuberosum
- A clump-forming perennial herb native to the Chinese province of Shanxi, but now found pretty much worldwide.
- Planted from seed on the 2nd of March, 2024.
-
-
-
-
-
-
-
- Cilantro
- Coriandrum sativum
- Also known as Coriander, this is an annual herb that most people enjoy has having a tart, lemon/lime taste. It's native to the mediterranean basin, but is grown worldwide.
-
-
-
-
-
-
-
- Creeping Sage
- Salvia misella
- Also known as tropical sage, it is an annual herb growing throughout the tropical Americas.
- Transplanted on the 9th of March, 2024.
-
-
-
-
-
-
-
- Dwarf Shiny-Leaf Coffee
- Psychotria nervosa
- A small shrub with shiny evergreen leaves that produces beans similar to coffee, but without any caffeine. Native to the southeastern United States.
- Transplanted on the 10th of February, 2024.
-
-
-
-
-
-
-
- Kimberley Queen Fern
- Nephrolepis obliterata
- A species of fern originating from Australia, but grown worldwide.
- Transplanted on the 2nd of March, 2024.
-
-
-
-
-
-
-
- Foxtail Fern
- Asparagus aethiopicus
- A plant native to South Africa that's grown ornamentally in many places. Its roots form water-storage tubers.
- Transplanted in February, 2024.
-
-
-
-
-
-
-
- Inchplant
- Tradescantia zebrina
- A species of creeping vine plant that forms a dense groundcover in shaded areas. It's native to Mexico, Central America, and Colombia.
- Transplanted on the 8th of March, 2024.
-
-
-
-
-
-
-
- Jalapeño
- Capsicum annuum var. jalapeño
- A medium-sized chili pepper species with relatively mild pungency. It's commonly picked and consumed while still green, and were originally cultivated by the Aztecs.
- Transplanted on the 2nd of March, 2024.
-
-
-
-
-
-
-
- Marigold
- Tagetes erecta
- A species of flowering plant native to the Americas that is widely used as an ornamental flower, and was originally called by its Nahuatl name, cempoalxóchitl.
- Planted from seed in February, 2024.
-
-
-
-
-
-
-
- Perennial Petunia
- Ruellia caroliniensis
- A wild petunia with blue or violet flowers that's native to the southeastern United States.
- Transplanted on the 10th of February, 2024.
-
-
-
-
-
-
-
- Mona Lavender
- Plectranthus "Mona Lavender"
- A hybrid of Plectranthus saccatus and Plectranthus hilliardiae , this is a broadleaf evergreen shrub in the mint family, which produces many small purple flowers.
- Transplanted in February, 2024.
-
-
-
-
-
-
-
- English Thyme
- Thymus vulgaris
- A flowering plant in the mint family, native to southern Europe, that's commonly used as an herb.
- Planted from seed in March, 2024.
-
-
-
-
-
-
-
- Tropical Milkweed
- Asclepias curassavica
- A flowering milkweed species native to the American tropics which is a food source for Monarch butterflies.
- Note: Research suggests that this plant may disrupt migratory patterns in butterflies when planted in northern United States habitats. I'm working on replacing it with native milkweed variants.
- Transplanted in February, 2024.
-
-
-
-
-
-
-
- Wood Sage
- Teucrium canadense
- A perennial herb native to North America, growing in moist grasslands, forest edges, marshes, and on roadsides.
- Transplanted on the 9th of March, 2024.
-
-
-
-
-
+
+
+
+
+
+ Capsicum annuum var. glabriusculum
+
+ A small chili pepper variety native to southern North America and northern South America. It's the only pepper species native to the Floridian peninsula.
+
+
+
+
+
+
+
+
+ Juniperus conferta
+
+ A species of Juniper native to Japan, that grows on sand dunes and other acidic/alkaline soils with good drainage. It forms a groundcover if left unattended.
+
+
+
+
+
+
+
+
+ Clinopodium brownei
+
+ A sprawling perennial herb found natively in the coastal plains and marshes of the southeastern United States.
+
+
+
+
+
+
+
+
+ Nepeta cataria
+
+ Species of mint that about 2/3rds of cats are attracted to. Native to southern and eastern Europe, the Middle East, Central Asia, and parts of China.
+
+
+
+
+
+
+
+
+ Coriandrum sativum
+
+ Also known as Coriander, this is an annual herb that most people enjoy has having a tart, lemon/lime taste. It's native to the Mediterranean basin, but is grown worldwide.
+
+
+
+
+
+
+
+
+ Salvia misella
+
+ Also known as tropical sage, it is an annual herb growing throughout the tropical Americas.
+
+
+
+
+
+
+
+
+ Psychotria nervosa
+
+ A small shrub with shiny evergreen leaves that produces beans similar to coffee, but without any caffeine. Native to the southeastern United States.
+
+
+
+
+
+
+
+
+ Thymus vulgaris
+
+ A flowering plant in the mint family, native to southern Europe, that's commonly used as an herb.
+
+
+
+
+
+
+
+
+ Asparagus aethiopicus
+
+ A plant native to South Africa that's grown ornamentally in many places. Its roots form water-storage tubers.
+
+
+
+
+
+
+
+
+ Allium tuberosum
+
+ A clump-forming perennial herb native to the Chinese province of Shanxi, but now found pretty much worldwide.
+
+
+
+
+
+
+
+
+ Trandescantia zebrina
+
+ A species of creeping vine plant that forms a dense groundcover in shaded areas. It's native to Mexico, Central America, and Colombia.
+
+
+
+
+
+
+
+
+ Capsicum annuum var. jalapeño
+
+ A medium-sized chili pepper species with relatively mild pungency. It's commonly picked and consumed while still green, and were originally cultivated by the Aztecs.
+
+
+
+
+
+
+
+
+ Nephrolepis obliterata
+
+ A species of fern originating from Australia, but grown worldwide.
+
+
+
+
+
+
+
+
+ Tagetes erecta
+
+ A species of flowering plant native to the Americas that is widely used as an ornamental flower, and was originally called by its Nahuatl name, cempoalxóchitl.
+
+
+
+
+
+
+
+
+ Plectranthus “Mona Lavender”
+
+ A hybrid of Plectranthus saccatus and Plectranthus hilliardiae, this is a broadleaf evergreen shrub in the mint family, which produces many small purple flowers.
+
+
+
+
+
+
+
+
+ Ruellia caroliniensis
+
+ A wild petunia with blue or violet flowers that's native to the southeastern United States.
+
+
+
+
+
+
+
+
+ Asclepias curassavica
+
+ A flowering milkweed species native to the American tropics which is a food source for Monarch butterflies. Note: Research suggests that this plant may disrupt migratory patterns in butterflies when planted in northern United States habitats. I'm working on replacing it with native milkweed variants.
+
+
+
+
+
+
+
+
+ Teucrium canadense
+
+ A perennial herb native to North America, growing in moist grasslands, forest edges, marshes, and on roadsides.
+
+
+
+
diff --git a/garden/species/allium-tuberosum.html b/garden/species/allium-tuberosum.html
new file mode 100644
index 0000000..096ded8
--- /dev/null
+++ b/garden/species/allium-tuberosum.html
@@ -0,0 +1,87 @@
+
+
+
+
+ Andrew's Garden: Garlic Chives
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ About Garlic Chives
+ A clump-forming perennial herb native to the Chinese province of Shanxi, but now found pretty much worldwide.
+
+
+ https://en.wikipedia.org/wiki/Allium_tuberosum
+
+
+
+
+ Plants
+
+ Here's a detailed list of all plants I have of this species.
+
+
+
+ garlic-chives-001
+ Generation F1
+
+ Planted from seed on the 2nd of March, 2024.
+
+
+
+
+
+
diff --git a/garden/species/asclepias-curassavica.html b/garden/species/asclepias-curassavica.html
new file mode 100644
index 0000000..f6acd00
--- /dev/null
+++ b/garden/species/asclepias-curassavica.html
@@ -0,0 +1,87 @@
+
+
+
+
+ Andrew's Garden: Tropical Milkweed
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ About Tropical Milkweed
+ A flowering milkweed species native to the American tropics which is a food source for Monarch butterflies. Note: Research suggests that this plant may disrupt migratory patterns in butterflies when planted in northern United States habitats. I'm working on replacing it with native milkweed variants.
+
+
+ https://en.wikipedia.org/wiki/Asclepias_curassavica
+
+
+
+
+ Plants
+
+ Here's a detailed list of all plants I have of this species.
+
+
+
+ tropical-milkweed-001
+ Generation F1
+
+ Transplanted in February, 2024.
+
+
+
+
+
+
diff --git a/garden/species/asparagus-aethiopicus.html b/garden/species/asparagus-aethiopicus.html
new file mode 100644
index 0000000..7fcad54
--- /dev/null
+++ b/garden/species/asparagus-aethiopicus.html
@@ -0,0 +1,100 @@
+
+
+
+
+ Andrew's Garden: Foxtail Fern
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ About Foxtail Fern
+ A plant native to South Africa that's grown ornamentally in many places. Its roots form water-storage tubers.
+
+
+ https://en.wikipedia.org/wiki/Asparagus_aethiopicus
+
+
+
+
+ Plants
+
+ Here's a detailed list of all plants I have of this species.
+
+
+
+ foxtail-fern-001
+ Generation F1
+ The foxtail fern in the bottom-left corner of the garden, when looking from the front. It’s right by the sidewalk.
+ Transplanted in February, 2024.
+
+
+
+
+ foxtail-fern-002
+ Generation F1
+ The foxtail fern that’s situated right in the middle of the garden, nearby the first bird-pepper plant.
+ Transplanted in February, 2024.
+
+
+
+
+
+
diff --git a/garden/species/capsicum-annuum-var-glabriusculum.html b/garden/species/capsicum-annuum-var-glabriusculum.html
new file mode 100644
index 0000000..d73a109
--- /dev/null
+++ b/garden/species/capsicum-annuum-var-glabriusculum.html
@@ -0,0 +1,87 @@
+
+
+
+
+ Andrew's Garden: Bird Pepper
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ About Bird Pepper
+ A small chili pepper variety native to southern North America and northern South America. It's the only pepper species native to the Floridian peninsula.
+
+
+ https://en.wikipedia.org/wiki/Capsicum_annuum_var._glabriusculum
+
+
+
+
+ Plants
+
+ Here's a detailed list of all plants I have of this species.
+
+
+
+ bird-pepper-001
+ Generation F1
+ My first bird pepper plant, acquired from a local nursery.
+ Transplanted from a 1 gallon pot, on February 10th, 2024.
+
+
+
+
+
+
diff --git a/garden/species/capsicum-annuum-var-jalapeno.html b/garden/species/capsicum-annuum-var-jalapeno.html
new file mode 100644
index 0000000..5b916e9
--- /dev/null
+++ b/garden/species/capsicum-annuum-var-jalapeno.html
@@ -0,0 +1,87 @@
+
+
+
+
+ Andrew's Garden: Jalapeño
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ About Jalapeño
+ A medium-sized chili pepper species with relatively mild pungency. It's commonly picked and consumed while still green, and were originally cultivated by the Aztecs.
+
+
+ https://en.wikipedia.org/wiki/Jalape%C3%B1o
+
+
+
+
+ Plants
+
+ Here's a detailed list of all plants I have of this species.
+
+
+
+ jalapeno-001
+ Generation F1
+
+ Transplanted on the 2nd of March, 2024.
+
+
+
+
+
+
diff --git a/garden/species/clinopodium-brownei.html b/garden/species/clinopodium-brownei.html
new file mode 100644
index 0000000..ac3a179
--- /dev/null
+++ b/garden/species/clinopodium-brownei.html
@@ -0,0 +1,87 @@
+
+
+
+
+ Andrew's Garden: Browne’s Savory
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ About Browne’s Savory
+ A sprawling perennial herb found natively in the coastal plains and marshes of the southeastern United States.
+
+
+ https://en.wikipedia.org/wiki/Clinopodium_brownei
+
+
+
+
+ Plants
+
+ Here's a detailed list of all plants I have of this species.
+
+
+
+ brownes-savory-001
+ Generation F1
+
+ Transplanted on the 10th of February, 2024.
+
+
+
+
+
+
diff --git a/garden/species/coriandrum-sativum.html b/garden/species/coriandrum-sativum.html
new file mode 100644
index 0000000..5e602ea
--- /dev/null
+++ b/garden/species/coriandrum-sativum.html
@@ -0,0 +1,87 @@
+
+
+
+
+ Andrew's Garden: Cilantro
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ About Cilantro
+ Also known as Coriander, this is an annual herb that most people enjoy has having a tart, lemon/lime taste. It's native to the Mediterranean basin, but is grown worldwide.
+
+
+ https://en.wikipedia.org/wiki/Coriander
+
+
+
+
+ Plants
+
+ Here's a detailed list of all plants I have of this species.
+
+
+
+ coriander-001
+ Generation F1
+
+ Planted from seed on the 2nd of March, 2024.
+
+
+
+
+
+
diff --git a/garden/species/juniperus-conferta.html b/garden/species/juniperus-conferta.html
new file mode 100644
index 0000000..f1a6ee5
--- /dev/null
+++ b/garden/species/juniperus-conferta.html
@@ -0,0 +1,87 @@
+
+
+
+
+ Andrew's Garden: Blue Pacific Juniper
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ About Blue Pacific Juniper
+ A species of Juniper native to Japan, that grows on sand dunes and other acidic/alkaline soils with good drainage. It forms a groundcover if left unattended.
+
+
+ https://en.wikipedia.org/wiki/Juniperus_conferta
+
+
+
+
+ Plants
+
+ Here's a detailed list of all plants I have of this species.
+
+
+
+ blue-juniper-001
+ Generation F1
+ A nice-looking juniper shrub I got at Lowe’s. It’s located right on the corner of my garden.
+ Transplanted on the 2nd of March, 2024.
+
+
+
+
+
+
diff --git a/garden/species/nepeta-cataria.html b/garden/species/nepeta-cataria.html
new file mode 100644
index 0000000..5c130bf
--- /dev/null
+++ b/garden/species/nepeta-cataria.html
@@ -0,0 +1,87 @@
+
+
+
+
+ Andrew's Garden: Catnip
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ About Catnip
+ Species of mint that about 2/3rds of cats are attracted to. Native to southern and eastern Europe, the Middle East, Central Asia, and parts of China.
+
+
+ https://en.wikipedia.org/wiki/Catnip
+
+
+
+
+ Plants
+
+ Here's a detailed list of all plants I have of this species.
+
+
+
+ catnip-001
+ Generation F1
+
+ Transplanted from a small pot bought at a pet store, sometime in October, 2023.
+
+
+
+
+
+
diff --git a/garden/species/nephrolepis-obliterata.html b/garden/species/nephrolepis-obliterata.html
new file mode 100644
index 0000000..939de46
--- /dev/null
+++ b/garden/species/nephrolepis-obliterata.html
@@ -0,0 +1,87 @@
+
+
+
+
+ Andrew's Garden: Kimberley Queen Fern
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ About Kimberley Queen Fern
+ A species of fern originating from Australia, but grown worldwide.
+
+
+ https://en.wikipedia.org/wiki/Nephrolepis_obliterata
+
+
+
+
+ Plants
+
+ Here's a detailed list of all plants I have of this species.
+
+
+
+ kimberley-fern-001
+ Generation F1
+
+ Transplanted on the 2nd of March, 2024.
+
+
+
+
+
+
diff --git a/garden/species/plectranthus-mona-lavender.html b/garden/species/plectranthus-mona-lavender.html
new file mode 100644
index 0000000..3fe4463
--- /dev/null
+++ b/garden/species/plectranthus-mona-lavender.html
@@ -0,0 +1,87 @@
+
+
+
+
+ Andrew's Garden: Mona Lavender
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ About Mona Lavender
+ A hybrid of Plectranthus saccatus and Plectranthus hilliardiae, this is a broadleaf evergreen shrub in the mint family, which produces many small purple flowers.
+
+
+ https://plants.ces.ncsu.edu/plants/plectranthus-mona-lavender/
+
+
+
+
+ Plants
+
+ Here's a detailed list of all plants I have of this species.
+
+
+
+ mona-lavender-001
+ Generation F1
+ The mona lavender that’s on the right side of the tree.
+ Transplanted in February, 2024.
+
+
+
+
+
+
diff --git a/garden/species/psychotria-nervosa.html b/garden/species/psychotria-nervosa.html
new file mode 100644
index 0000000..b885ba2
--- /dev/null
+++ b/garden/species/psychotria-nervosa.html
@@ -0,0 +1,87 @@
+
+
+
+
+ Andrew's Garden: Dwarf Shiny-Leaf Coffee
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ About Dwarf Shiny-Leaf Coffee
+ A small shrub with shiny evergreen leaves that produces beans similar to coffee, but without any caffeine. Native to the southeastern United States.
+
+
+ https://gardeningsolutions.ifas.ufl.edu/plants/trees-and-shrubs/shrubs/wild-coffee.html
+
+
+
+
+ Plants
+
+ Here's a detailed list of all plants I have of this species.
+
+
+
+ dwarf-coffee-001
+ Generation F1
+
+ Transplanted on the 10th of February, 2024.
+
+
+
+
+
+
diff --git a/garden/species/ruellia-caroliniensis.html b/garden/species/ruellia-caroliniensis.html
new file mode 100644
index 0000000..00fc4fb
--- /dev/null
+++ b/garden/species/ruellia-caroliniensis.html
@@ -0,0 +1,87 @@
+
+
+
+
+ Andrew's Garden: Perennial Petunia
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ About Perennial Petunia
+ A wild petunia with blue or violet flowers that's native to the southeastern United States.
+
+
+ https://en.wikipedia.org/wiki/Ruellia_caroliniensis
+
+
+
+
+ Plants
+
+ Here's a detailed list of all plants I have of this species.
+
+
+
+ carolina-petunia-001
+ Generation F1
+
+ Transplanted on the 10th of February, 2024.
+
+
+
+
+
+
diff --git a/garden/species/salvia-misella.html b/garden/species/salvia-misella.html
new file mode 100644
index 0000000..50ba31a
--- /dev/null
+++ b/garden/species/salvia-misella.html
@@ -0,0 +1,87 @@
+
+
+
+
+ Andrew's Garden: Creeping Sage
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ About Creeping Sage
+ Also known as tropical sage, it is an annual herb growing throughout the tropical Americas.
+
+
+ https://en.wikipedia.org/wiki/Salvia_misella
+
+
+
+
+ Plants
+
+ Here's a detailed list of all plants I have of this species.
+
+
+
+ creeping-sage-001
+ Generation F1
+
+ Transplanted on the 9th of March, 2024.
+
+
+
+
+
+
diff --git a/garden/species/tagetes-erecta.html b/garden/species/tagetes-erecta.html
new file mode 100644
index 0000000..cb16dcf
--- /dev/null
+++ b/garden/species/tagetes-erecta.html
@@ -0,0 +1,87 @@
+
+
+
+
+ Andrew's Garden: Marigold
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ About Marigold
+ A species of flowering plant native to the Americas that is widely used as an ornamental flower, and was originally called by its Nahuatl name, cempoalxóchitl.
+
+
+ https://en.wikipedia.org/wiki/Tagetes_erecta
+
+
+
+
+ Plants
+
+ Here's a detailed list of all plants I have of this species.
+
+
+
+ marigold-001
+ Generation F1
+ The second marigold from the left, when viewing the garden from the front.
+ Planted from seed in February, 2024.
+
+
+
+
+
+
diff --git a/garden/species/teucrium-canadense.html b/garden/species/teucrium-canadense.html
new file mode 100644
index 0000000..23cf64c
--- /dev/null
+++ b/garden/species/teucrium-canadense.html
@@ -0,0 +1,87 @@
+
+
+
+
+ Andrew's Garden: Wood Sage
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ About Wood Sage
+ A perennial herb native to North America, growing in moist grasslands, forest edges, marshes, and on roadsides.
+
+
+ https://en.wikipedia.org/wiki/Teucrium_canadense
+
+
+
+
+ Plants
+
+ Here's a detailed list of all plants I have of this species.
+
+
+
+ wood-sage-001
+ Generation F1
+
+ Transplanted on the 9th of March, 2024.
+
+
+
+
+
+
diff --git a/garden/species/thymus-vulgaris.html b/garden/species/thymus-vulgaris.html
new file mode 100644
index 0000000..4714b17
--- /dev/null
+++ b/garden/species/thymus-vulgaris.html
@@ -0,0 +1,87 @@
+
+
+
+
+ Andrew's Garden: English Thyme
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ About English Thyme
+ A flowering plant in the mint family, native to southern Europe, that's commonly used as an herb.
+
+
+ https://en.wikipedia.org/wiki/Thymus_vulgaris
+
+
+
+
+ Plants
+
+ Here's a detailed list of all plants I have of this species.
+
+
+
+ thyme-001
+ Generation F1
+
+ Planted from seed in March, 2024.
+
+
+
+
+
+
diff --git a/garden/species/trandescantia-zebrina.html b/garden/species/trandescantia-zebrina.html
new file mode 100644
index 0000000..d5c508f
--- /dev/null
+++ b/garden/species/trandescantia-zebrina.html
@@ -0,0 +1,87 @@
+
+
+
+
+ Andrew's Garden: Inchplant
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ About Inchplant
+ A species of creeping vine plant that forms a dense groundcover in shaded areas. It's native to Mexico, Central America, and Colombia.
+
+
+ https://en.wikipedia.org/wiki/Tradescantia_zebrina
+
+
+
+
+ Plants
+
+ Here's a detailed list of all plants I have of this species.
+
+
+
+ inchplant-001
+ Generation F1
+
+ Transplanted on the 8th of March, 2024.
+
+
+
+
+
+
diff --git a/images/garden/bird-pepper_20240310_113310.jpg b/images/garden/plants/bird-pepper-001/bird-pepper_20240310_113310.jpg
similarity index 100%
rename from images/garden/bird-pepper_20240310_113310.jpg
rename to images/garden/plants/bird-pepper-001/bird-pepper_20240310_113310.jpg
diff --git a/images/garden/plants/bird-pepper-001/bird-pepper_20240310_113310.thumb.jpg b/images/garden/plants/bird-pepper-001/bird-pepper_20240310_113310.thumb.jpg
new file mode 100644
index 0000000..14dee19
Binary files /dev/null and b/images/garden/plants/bird-pepper-001/bird-pepper_20240310_113310.thumb.jpg differ
diff --git a/images/garden/blue-juniper_20240310_113334.jpg b/images/garden/plants/blue-juniper-001/blue-juniper_20240310_113334.jpg
similarity index 100%
rename from images/garden/blue-juniper_20240310_113334.jpg
rename to images/garden/plants/blue-juniper-001/blue-juniper_20240310_113334.jpg
diff --git a/images/garden/plants/blue-juniper-001/blue-juniper_20240310_113334.thumb.jpg b/images/garden/plants/blue-juniper-001/blue-juniper_20240310_113334.thumb.jpg
new file mode 100644
index 0000000..1b72f4b
Binary files /dev/null and b/images/garden/plants/blue-juniper-001/blue-juniper_20240310_113334.thumb.jpg differ
diff --git a/images/garden/browns-savory_20240310_113313.jpg b/images/garden/plants/brownes-savory-001/browns-savory_20240310_113313.jpg
similarity index 100%
rename from images/garden/browns-savory_20240310_113313.jpg
rename to images/garden/plants/brownes-savory-001/browns-savory_20240310_113313.jpg
diff --git a/images/garden/plants/brownes-savory-001/browns-savory_20240310_113313.thumb.jpg b/images/garden/plants/brownes-savory-001/browns-savory_20240310_113313.thumb.jpg
new file mode 100644
index 0000000..1262fa7
Binary files /dev/null and b/images/garden/plants/brownes-savory-001/browns-savory_20240310_113313.thumb.jpg differ
diff --git a/images/garden/perennial-petunia_20240310_113346.jpg b/images/garden/plants/carolina-petunia-001/perennial-petunia_20240310_113346.jpg
similarity index 100%
rename from images/garden/perennial-petunia_20240310_113346.jpg
rename to images/garden/plants/carolina-petunia-001/perennial-petunia_20240310_113346.jpg
diff --git a/images/garden/plants/carolina-petunia-001/perennial-petunia_20240310_113346.thumb.jpg b/images/garden/plants/carolina-petunia-001/perennial-petunia_20240310_113346.thumb.jpg
new file mode 100644
index 0000000..d143dde
Binary files /dev/null and b/images/garden/plants/carolina-petunia-001/perennial-petunia_20240310_113346.thumb.jpg differ
diff --git a/images/garden/catnip_20240310_113153.jpg b/images/garden/plants/catnip-001/catnip_20240310_113153.jpg
similarity index 100%
rename from images/garden/catnip_20240310_113153.jpg
rename to images/garden/plants/catnip-001/catnip_20240310_113153.jpg
diff --git a/images/garden/plants/catnip-001/catnip_20240310_113153.thumb.jpg b/images/garden/plants/catnip-001/catnip_20240310_113153.thumb.jpg
new file mode 100644
index 0000000..940fe59
Binary files /dev/null and b/images/garden/plants/catnip-001/catnip_20240310_113153.thumb.jpg differ
diff --git a/images/garden/cilantro_20240310_113220.jpg b/images/garden/plants/coriander-001/cilantro_20240310_113220.jpg
similarity index 100%
rename from images/garden/cilantro_20240310_113220.jpg
rename to images/garden/plants/coriander-001/cilantro_20240310_113220.jpg
diff --git a/images/garden/plants/coriander-001/cilantro_20240310_113220.thumb.jpg b/images/garden/plants/coriander-001/cilantro_20240310_113220.thumb.jpg
new file mode 100644
index 0000000..9a1f2a4
Binary files /dev/null and b/images/garden/plants/coriander-001/cilantro_20240310_113220.thumb.jpg differ
diff --git a/images/garden/creeping-sage_20240310_113303.jpg b/images/garden/plants/creeping-sage-001/creeping-sage_20240310_113303.jpg
similarity index 100%
rename from images/garden/creeping-sage_20240310_113303.jpg
rename to images/garden/plants/creeping-sage-001/creeping-sage_20240310_113303.jpg
diff --git a/images/garden/plants/creeping-sage-001/creeping-sage_20240310_113303.thumb.jpg b/images/garden/plants/creeping-sage-001/creeping-sage_20240310_113303.thumb.jpg
new file mode 100644
index 0000000..7b0c3a6
Binary files /dev/null and b/images/garden/plants/creeping-sage-001/creeping-sage_20240310_113303.thumb.jpg differ
diff --git a/images/garden/dwarf-coffee_20240310_113259.jpg b/images/garden/plants/dwarf-coffee-001/dwarf-coffee_20240310_113259.jpg
similarity index 100%
rename from images/garden/dwarf-coffee_20240310_113259.jpg
rename to images/garden/plants/dwarf-coffee-001/dwarf-coffee_20240310_113259.jpg
diff --git a/images/garden/plants/dwarf-coffee-001/dwarf-coffee_20240310_113259.thumb.jpg b/images/garden/plants/dwarf-coffee-001/dwarf-coffee_20240310_113259.thumb.jpg
new file mode 100644
index 0000000..f6ce599
Binary files /dev/null and b/images/garden/plants/dwarf-coffee-001/dwarf-coffee_20240310_113259.thumb.jpg differ
diff --git a/images/garden/foxtail-fern_20240310_113229.jpg b/images/garden/plants/foxtail-fern-001/foxtail-fern_20240310_113229.jpg
similarity index 100%
rename from images/garden/foxtail-fern_20240310_113229.jpg
rename to images/garden/plants/foxtail-fern-001/foxtail-fern_20240310_113229.jpg
diff --git a/images/garden/plants/foxtail-fern-001/foxtail-fern_20240310_113229.thumb.jpg b/images/garden/plants/foxtail-fern-001/foxtail-fern_20240310_113229.thumb.jpg
new file mode 100644
index 0000000..c790b83
Binary files /dev/null and b/images/garden/plants/foxtail-fern-001/foxtail-fern_20240310_113229.thumb.jpg differ
diff --git a/images/garden/chives_20240310_113216.jpg b/images/garden/plants/garlic-chives-001/chives_20240310_113216.jpg
similarity index 100%
rename from images/garden/chives_20240310_113216.jpg
rename to images/garden/plants/garlic-chives-001/chives_20240310_113216.jpg
diff --git a/images/garden/plants/garlic-chives-001/chives_20240310_113216.thumb.jpg b/images/garden/plants/garlic-chives-001/chives_20240310_113216.thumb.jpg
new file mode 100644
index 0000000..34b1290
Binary files /dev/null and b/images/garden/plants/garlic-chives-001/chives_20240310_113216.thumb.jpg differ
diff --git a/images/garden/inchplant_20240310_113409.jpg b/images/garden/plants/inchplant-001/inchplant_20240310_113409.jpg
similarity index 100%
rename from images/garden/inchplant_20240310_113409.jpg
rename to images/garden/plants/inchplant-001/inchplant_20240310_113409.jpg
diff --git a/images/garden/plants/inchplant-001/inchplant_20240310_113409.thumb.jpg b/images/garden/plants/inchplant-001/inchplant_20240310_113409.thumb.jpg
new file mode 100644
index 0000000..18dd060
Binary files /dev/null and b/images/garden/plants/inchplant-001/inchplant_20240310_113409.thumb.jpg differ
diff --git a/images/garden/jalapeno_20240310_113329.jpg b/images/garden/plants/jalapeno-001/jalapeno_20240310_113329.jpg
similarity index 100%
rename from images/garden/jalapeno_20240310_113329.jpg
rename to images/garden/plants/jalapeno-001/jalapeno_20240310_113329.jpg
diff --git a/images/garden/plants/jalapeno-001/jalapeno_20240310_113329.thumb.jpg b/images/garden/plants/jalapeno-001/jalapeno_20240310_113329.thumb.jpg
new file mode 100644
index 0000000..fd921c9
Binary files /dev/null and b/images/garden/plants/jalapeno-001/jalapeno_20240310_113329.thumb.jpg differ
diff --git a/images/garden/fern_20240310_113359.jpg b/images/garden/plants/kimberley-fern-001/fern_20240310_113359.jpg
similarity index 100%
rename from images/garden/fern_20240310_113359.jpg
rename to images/garden/plants/kimberley-fern-001/fern_20240310_113359.jpg
diff --git a/images/garden/plants/kimberley-fern-001/fern_20240310_113359.thumb.jpg b/images/garden/plants/kimberley-fern-001/fern_20240310_113359.thumb.jpg
new file mode 100644
index 0000000..b1ab2ff
Binary files /dev/null and b/images/garden/plants/kimberley-fern-001/fern_20240310_113359.thumb.jpg differ
diff --git a/images/garden/marigold_20240310_113234.jpg b/images/garden/plants/marigold-001/marigold_20240310_113234.jpg
similarity index 100%
rename from images/garden/marigold_20240310_113234.jpg
rename to images/garden/plants/marigold-001/marigold_20240310_113234.jpg
diff --git a/images/garden/plants/marigold-001/marigold_20240310_113234.thumb.jpg b/images/garden/plants/marigold-001/marigold_20240310_113234.thumb.jpg
new file mode 100644
index 0000000..9182ead
Binary files /dev/null and b/images/garden/plants/marigold-001/marigold_20240310_113234.thumb.jpg differ
diff --git a/images/garden/plectranthus_20240310_113255.jpg b/images/garden/plants/mona-lavender-001/plectranthus_20240310_113255.jpg
similarity index 100%
rename from images/garden/plectranthus_20240310_113255.jpg
rename to images/garden/plants/mona-lavender-001/plectranthus_20240310_113255.jpg
diff --git a/images/garden/plants/mona-lavender-001/plectranthus_20240310_113255.thumb.jpg b/images/garden/plants/mona-lavender-001/plectranthus_20240310_113255.thumb.jpg
new file mode 100644
index 0000000..9d4a22a
Binary files /dev/null and b/images/garden/plants/mona-lavender-001/plectranthus_20240310_113255.thumb.jpg differ
diff --git a/images/garden/thyme_20240310_113210.jpg b/images/garden/plants/thyme-001/thyme_20240310_113210.jpg
similarity index 100%
rename from images/garden/thyme_20240310_113210.jpg
rename to images/garden/plants/thyme-001/thyme_20240310_113210.jpg
diff --git a/images/garden/plants/thyme-001/thyme_20240310_113210.thumb.jpg b/images/garden/plants/thyme-001/thyme_20240310_113210.thumb.jpg
new file mode 100644
index 0000000..6f0f890
Binary files /dev/null and b/images/garden/plants/thyme-001/thyme_20240310_113210.thumb.jpg differ
diff --git a/images/garden/tropical-milkweed_20240310_113353.jpg b/images/garden/plants/tropical-milkweed-001/tropical-milkweed_20240310_113353.jpg
similarity index 100%
rename from images/garden/tropical-milkweed_20240310_113353.jpg
rename to images/garden/plants/tropical-milkweed-001/tropical-milkweed_20240310_113353.jpg
diff --git a/images/garden/plants/tropical-milkweed-001/tropical-milkweed_20240310_113353.thumb.jpg b/images/garden/plants/tropical-milkweed-001/tropical-milkweed_20240310_113353.thumb.jpg
new file mode 100644
index 0000000..1dbb38a
Binary files /dev/null and b/images/garden/plants/tropical-milkweed-001/tropical-milkweed_20240310_113353.thumb.jpg differ
diff --git a/images/garden/woody-sage_20240310_113339.jpg b/images/garden/plants/wood-sage-001/woody-sage_20240310_113339.jpg
similarity index 100%
rename from images/garden/woody-sage_20240310_113339.jpg
rename to images/garden/plants/wood-sage-001/woody-sage_20240310_113339.jpg
diff --git a/images/garden/plants/wood-sage-001/woody-sage_20240310_113339.thumb.jpg b/images/garden/plants/wood-sage-001/woody-sage_20240310_113339.thumb.jpg
new file mode 100644
index 0000000..8904d7d
Binary files /dev/null and b/images/garden/plants/wood-sage-001/woody-sage_20240310_113339.thumb.jpg differ
diff --git a/images/garden/species/allium-tuberosum/Allium_tuberosum-ingarden1.jpg b/images/garden/species/allium-tuberosum/Allium_tuberosum-ingarden1.jpg
new file mode 100644
index 0000000..7e9701e
Binary files /dev/null and b/images/garden/species/allium-tuberosum/Allium_tuberosum-ingarden1.jpg differ
diff --git a/images/garden/species/allium-tuberosum/Allium_tuberosum-ingarden1.thumb.jpg b/images/garden/species/allium-tuberosum/Allium_tuberosum-ingarden1.thumb.jpg
new file mode 100644
index 0000000..bd6dfdc
Binary files /dev/null and b/images/garden/species/allium-tuberosum/Allium_tuberosum-ingarden1.thumb.jpg differ
diff --git a/images/garden/species/asclepias-curassavica/Asclepias_curassavica-Thekkady-2016-12-03-001.jpg b/images/garden/species/asclepias-curassavica/Asclepias_curassavica-Thekkady-2016-12-03-001.jpg
new file mode 100644
index 0000000..f98256e
Binary files /dev/null and b/images/garden/species/asclepias-curassavica/Asclepias_curassavica-Thekkady-2016-12-03-001.jpg differ
diff --git a/images/garden/species/asclepias-curassavica/Asclepias_curassavica-Thekkady-2016-12-03-001.thumb.jpg b/images/garden/species/asclepias-curassavica/Asclepias_curassavica-Thekkady-2016-12-03-001.thumb.jpg
new file mode 100644
index 0000000..bc0c149
Binary files /dev/null and b/images/garden/species/asclepias-curassavica/Asclepias_curassavica-Thekkady-2016-12-03-001.thumb.jpg differ
diff --git a/images/garden/species/asparagus-aethiopicus/foxtail_fern_asparagus_meyeri.jpg b/images/garden/species/asparagus-aethiopicus/foxtail_fern_asparagus_meyeri.jpg
new file mode 100644
index 0000000..8dd0309
Binary files /dev/null and b/images/garden/species/asparagus-aethiopicus/foxtail_fern_asparagus_meyeri.jpg differ
diff --git a/images/garden/species/asparagus-aethiopicus/foxtail_fern_asparagus_meyeri.thumb.jpg b/images/garden/species/asparagus-aethiopicus/foxtail_fern_asparagus_meyeri.thumb.jpg
new file mode 100644
index 0000000..324cc88
Binary files /dev/null and b/images/garden/species/asparagus-aethiopicus/foxtail_fern_asparagus_meyeri.thumb.jpg differ
diff --git a/images/garden/species/capsicum-annuum-var-glabriusculum/Capsicum_annuum-FWF.jpg b/images/garden/species/capsicum-annuum-var-glabriusculum/Capsicum_annuum-FWF.jpg
new file mode 100644
index 0000000..5c5d03d
Binary files /dev/null and b/images/garden/species/capsicum-annuum-var-glabriusculum/Capsicum_annuum-FWF.jpg differ
diff --git a/images/garden/species/capsicum-annuum-var-glabriusculum/Capsicum_annuum-FWF.thumb.jpg b/images/garden/species/capsicum-annuum-var-glabriusculum/Capsicum_annuum-FWF.thumb.jpg
new file mode 100644
index 0000000..245c445
Binary files /dev/null and b/images/garden/species/capsicum-annuum-var-glabriusculum/Capsicum_annuum-FWF.thumb.jpg differ
diff --git a/images/garden/species/capsicum-annuum-var-jalapeno/jalapeno.jpg b/images/garden/species/capsicum-annuum-var-jalapeno/jalapeno.jpg
new file mode 100644
index 0000000..450ad1a
Binary files /dev/null and b/images/garden/species/capsicum-annuum-var-jalapeno/jalapeno.jpg differ
diff --git a/images/garden/species/capsicum-annuum-var-jalapeno/jalapeno.thumb.jpg b/images/garden/species/capsicum-annuum-var-jalapeno/jalapeno.thumb.jpg
new file mode 100644
index 0000000..5bed81c
Binary files /dev/null and b/images/garden/species/capsicum-annuum-var-jalapeno/jalapeno.thumb.jpg differ
diff --git a/images/garden/species/clinopodium-brownei/clinopodium_brownei-keim2-1-e1602619542587.jpg b/images/garden/species/clinopodium-brownei/clinopodium_brownei-keim2-1-e1602619542587.jpg
new file mode 100644
index 0000000..33363c3
Binary files /dev/null and b/images/garden/species/clinopodium-brownei/clinopodium_brownei-keim2-1-e1602619542587.jpg differ
diff --git a/images/garden/species/clinopodium-brownei/clinopodium_brownei-keim2-1-e1602619542587.thumb.jpg b/images/garden/species/clinopodium-brownei/clinopodium_brownei-keim2-1-e1602619542587.thumb.jpg
new file mode 100644
index 0000000..1e0e77a
Binary files /dev/null and b/images/garden/species/clinopodium-brownei/clinopodium_brownei-keim2-1-e1602619542587.thumb.jpg differ
diff --git a/images/garden/species/coriandrum-sativum/Coriandrum_sativum--Forest-and-Kim-Starr--CC-BY.jpg b/images/garden/species/coriandrum-sativum/Coriandrum_sativum--Forest-and-Kim-Starr--CC-BY.jpg
new file mode 100644
index 0000000..a5451c8
Binary files /dev/null and b/images/garden/species/coriandrum-sativum/Coriandrum_sativum--Forest-and-Kim-Starr--CC-BY.jpg differ
diff --git a/images/garden/species/coriandrum-sativum/Coriandrum_sativum--Forest-and-Kim-Starr--CC-BY.thumb.jpg b/images/garden/species/coriandrum-sativum/Coriandrum_sativum--Forest-and-Kim-Starr--CC-BY.thumb.jpg
new file mode 100644
index 0000000..ab789db
Binary files /dev/null and b/images/garden/species/coriandrum-sativum/Coriandrum_sativum--Forest-and-Kim-Starr--CC-BY.thumb.jpg differ
diff --git a/images/garden/species/juniperus-conferta/Juniperus_conferta_blue_pacific--Javier-Alejandro--CC-BY-NC-ND.jpg b/images/garden/species/juniperus-conferta/Juniperus_conferta_blue_pacific--Javier-Alejandro--CC-BY-NC-ND.jpg
new file mode 100644
index 0000000..c2dd3a0
Binary files /dev/null and b/images/garden/species/juniperus-conferta/Juniperus_conferta_blue_pacific--Javier-Alejandro--CC-BY-NC-ND.jpg differ
diff --git a/images/garden/species/juniperus-conferta/Juniperus_conferta_blue_pacific--Javier-Alejandro--CC-BY-NC-ND.thumb.jpg b/images/garden/species/juniperus-conferta/Juniperus_conferta_blue_pacific--Javier-Alejandro--CC-BY-NC-ND.thumb.jpg
new file mode 100644
index 0000000..9cb2a2e
Binary files /dev/null and b/images/garden/species/juniperus-conferta/Juniperus_conferta_blue_pacific--Javier-Alejandro--CC-BY-NC-ND.thumb.jpg differ
diff --git a/images/garden/catnip-test.jpg b/images/garden/species/nepeta-cataria/catnip-test.jpg
similarity index 100%
rename from images/garden/catnip-test.jpg
rename to images/garden/species/nepeta-cataria/catnip-test.jpg
diff --git a/images/garden/species/nepeta-cataria/catnip-test.thumb.jpg b/images/garden/species/nepeta-cataria/catnip-test.thumb.jpg
new file mode 100644
index 0000000..9c639fa
Binary files /dev/null and b/images/garden/species/nepeta-cataria/catnip-test.thumb.jpg differ
diff --git a/images/garden/species/nephrolepis-obliterata/nephrolepis-obliterata.jpg b/images/garden/species/nephrolepis-obliterata/nephrolepis-obliterata.jpg
new file mode 100644
index 0000000..e2ecc07
Binary files /dev/null and b/images/garden/species/nephrolepis-obliterata/nephrolepis-obliterata.jpg differ
diff --git a/images/garden/species/nephrolepis-obliterata/nephrolepis-obliterata.thumb.jpg b/images/garden/species/nephrolepis-obliterata/nephrolepis-obliterata.thumb.jpg
new file mode 100644
index 0000000..b882100
Binary files /dev/null and b/images/garden/species/nephrolepis-obliterata/nephrolepis-obliterata.thumb.jpg differ
diff --git a/images/garden/species/plectranthus-mona-lavender/plectranthus-0773400934.jpg b/images/garden/species/plectranthus-mona-lavender/plectranthus-0773400934.jpg
new file mode 100644
index 0000000..5ce95cb
Binary files /dev/null and b/images/garden/species/plectranthus-mona-lavender/plectranthus-0773400934.jpg differ
diff --git a/images/garden/species/plectranthus-mona-lavender/plectranthus-0773400934.thumb.jpg b/images/garden/species/plectranthus-mona-lavender/plectranthus-0773400934.thumb.jpg
new file mode 100644
index 0000000..bbb3030
Binary files /dev/null and b/images/garden/species/plectranthus-mona-lavender/plectranthus-0773400934.thumb.jpg differ
diff --git a/images/garden/species/psychotria-nervosa/Psychotria_nervosa-JennyEvans_CCBY-NC2.0.jpg b/images/garden/species/psychotria-nervosa/Psychotria_nervosa-JennyEvans_CCBY-NC2.0.jpg
new file mode 100644
index 0000000..ab8fec2
Binary files /dev/null and b/images/garden/species/psychotria-nervosa/Psychotria_nervosa-JennyEvans_CCBY-NC2.0.jpg differ
diff --git a/images/garden/species/psychotria-nervosa/Psychotria_nervosa-JennyEvans_CCBY-NC2.0.thumb.jpg b/images/garden/species/psychotria-nervosa/Psychotria_nervosa-JennyEvans_CCBY-NC2.0.thumb.jpg
new file mode 100644
index 0000000..3e601cc
Binary files /dev/null and b/images/garden/species/psychotria-nervosa/Psychotria_nervosa-JennyEvans_CCBY-NC2.0.thumb.jpg differ
diff --git a/images/garden/species/ruellia-caroliniensis/Ruellia-carolinensis-Carolina-Wild-Petunia-by-Marti-Webster-e1525962513541.jpg b/images/garden/species/ruellia-caroliniensis/Ruellia-carolinensis-Carolina-Wild-Petunia-by-Marti-Webster-e1525962513541.jpg
new file mode 100644
index 0000000..1648ba5
Binary files /dev/null and b/images/garden/species/ruellia-caroliniensis/Ruellia-carolinensis-Carolina-Wild-Petunia-by-Marti-Webster-e1525962513541.jpg differ
diff --git a/images/garden/species/ruellia-caroliniensis/Ruellia-carolinensis-Carolina-Wild-Petunia-by-Marti-Webster-e1525962513541.thumb.jpg b/images/garden/species/ruellia-caroliniensis/Ruellia-carolinensis-Carolina-Wild-Petunia-by-Marti-Webster-e1525962513541.thumb.jpg
new file mode 100644
index 0000000..7fcd060
Binary files /dev/null and b/images/garden/species/ruellia-caroliniensis/Ruellia-carolinensis-Carolina-Wild-Petunia-by-Marti-Webster-e1525962513541.thumb.jpg differ
diff --git a/images/garden/species/salvia-misella/salvia-misella.jpg b/images/garden/species/salvia-misella/salvia-misella.jpg
new file mode 100644
index 0000000..a787354
Binary files /dev/null and b/images/garden/species/salvia-misella/salvia-misella.jpg differ
diff --git a/images/garden/species/salvia-misella/salvia-misella.thumb.jpg b/images/garden/species/salvia-misella/salvia-misella.thumb.jpg
new file mode 100644
index 0000000..e98f103
Binary files /dev/null and b/images/garden/species/salvia-misella/salvia-misella.thumb.jpg differ
diff --git a/images/garden/species/tagetes-erecta/tagetes-erecta.jpg b/images/garden/species/tagetes-erecta/tagetes-erecta.jpg
new file mode 100644
index 0000000..94e8e18
Binary files /dev/null and b/images/garden/species/tagetes-erecta/tagetes-erecta.jpg differ
diff --git a/images/garden/species/tagetes-erecta/tagetes-erecta.thumb.jpg b/images/garden/species/tagetes-erecta/tagetes-erecta.thumb.jpg
new file mode 100644
index 0000000..5019aa7
Binary files /dev/null and b/images/garden/species/tagetes-erecta/tagetes-erecta.thumb.jpg differ
diff --git a/images/garden/species/teucrium-canadense/teucrium-canadense-perennials-20a__49095.jpg b/images/garden/species/teucrium-canadense/teucrium-canadense-perennials-20a__49095.jpg
new file mode 100644
index 0000000..7664f3c
Binary files /dev/null and b/images/garden/species/teucrium-canadense/teucrium-canadense-perennials-20a__49095.jpg differ
diff --git a/images/garden/species/teucrium-canadense/teucrium-canadense-perennials-20a__49095.thumb.jpg b/images/garden/species/teucrium-canadense/teucrium-canadense-perennials-20a__49095.thumb.jpg
new file mode 100644
index 0000000..253c89a
Binary files /dev/null and b/images/garden/species/teucrium-canadense/teucrium-canadense-perennials-20a__49095.thumb.jpg differ
diff --git a/images/garden/species/thymus-vulgaris/Thymus-vulgaris--CT-Arzneimittel-GmbH--CC-BY-ND.jpg b/images/garden/species/thymus-vulgaris/Thymus-vulgaris--CT-Arzneimittel-GmbH--CC-BY-ND.jpg
new file mode 100644
index 0000000..65eaedd
Binary files /dev/null and b/images/garden/species/thymus-vulgaris/Thymus-vulgaris--CT-Arzneimittel-GmbH--CC-BY-ND.jpg differ
diff --git a/images/garden/species/thymus-vulgaris/Thymus-vulgaris--CT-Arzneimittel-GmbH--CC-BY-ND.thumb.jpg b/images/garden/species/thymus-vulgaris/Thymus-vulgaris--CT-Arzneimittel-GmbH--CC-BY-ND.thumb.jpg
new file mode 100644
index 0000000..b122866
Binary files /dev/null and b/images/garden/species/thymus-vulgaris/Thymus-vulgaris--CT-Arzneimittel-GmbH--CC-BY-ND.thumb.jpg differ
diff --git a/images/garden/species/trandescantia-zebrina/Tradescantia-zebrina_AdobeStock_492957504_1200px.jpg b/images/garden/species/trandescantia-zebrina/Tradescantia-zebrina_AdobeStock_492957504_1200px.jpg
new file mode 100644
index 0000000..dabe0c4
Binary files /dev/null and b/images/garden/species/trandescantia-zebrina/Tradescantia-zebrina_AdobeStock_492957504_1200px.jpg differ
diff --git a/images/garden/species/trandescantia-zebrina/Tradescantia-zebrina_AdobeStock_492957504_1200px.thumb.jpg b/images/garden/species/trandescantia-zebrina/Tradescantia-zebrina_AdobeStock_492957504_1200px.thumb.jpg
new file mode 100644
index 0000000..0bf9804
Binary files /dev/null and b/images/garden/species/trandescantia-zebrina/Tradescantia-zebrina_AdobeStock_492957504_1200px.thumb.jpg differ
diff --git a/local-server.d b/local-server.d
new file mode 100755
index 0000000..7dcd2c1
--- /dev/null
+++ b/local-server.d
@@ -0,0 +1,20 @@
+#!/usr/bin/env dub
+/+ dub.sdl:
+ dependency "handy-httpd" version="~>8"
++/
+
+/**
+ * Run "./local-server.d" in your command-line to start up a server that simply
+ * serves these files on http://localhost:8080. This can be helpful when you
+ * need to simulate actual website behavior.
+ */
+module local_server;
+
+import handy_httpd;
+import handy_httpd.handlers.file_resolving_handler;
+
+void main() {
+ ServerConfig cfg;
+ cfg.workerPoolSize = 5;
+ new HttpServer(new FileResolvingHandler("./"), cfg).start();
+}
diff --git a/styles/garden.css b/styles/garden.css
index a33d490..1ef79ac 100644
--- a/styles/garden.css
+++ b/styles/garden.css
@@ -1,4 +1,4 @@
-.plant-card {
+.species-card {
background-color: var(--background-color-2);
padding: 0.5em;
display: flex;
@@ -6,32 +6,57 @@
gap: 1%;
}
-.plant-card + .plant-card {
+.species-card + .species-card {
margin-top: 1em;
}
-.plant-card > section {
+.species-card > section {
flex-grow: 1;
max-width: 49.5%;
}
-.plant-card > section > h2 {
+.species-card > section > h2 {
margin: 0;
}
-.plant-card > section > .sci {
+.species-card > section > .sci {
margin: 0;
font-style: italic;
font-family: serif;
font-size: smaller;
}
-.plant-card > section > p {
+.species-card > section > p {
margin: 0.5em 0;
}
-.plant-card > img {
+.species-card > img {
max-width: 49.5%;
object-fit: scale-down;
flex-grow: 0;
}
+
+
+
+.plant-card {
+ background-color: var(--background-color-2);
+ padding: 0.5em;
+}
+
+.plant-card + .plant-card {
+ margin-top: 1em;
+}
+
+.plant-card > section > h2 {
+ margin: 0;
+}
+
+.plant-card > section > .gen {
+ margin: 0;
+ font-family: monospace;
+ font-size: medium;
+}
+
+.plant-card > section > p {
+ margin: 0.5em 0;
+}
diff --git a/upload.sh b/upload.sh
index 8b3815c..8fc2b9f 100755
--- a/upload.sh
+++ b/upload.sh
@@ -3,7 +3,10 @@
# Helper script that copies files to the server.
# You need to have authenticated access to the server via SSH to use this.
+# Note: Quite a few files are excluded from being uploaded to the website.
+# These are denoted with an "--exclude" parameter.
+
rsync -rav -e ssh --delete \
---exclude .git/ --exclude *.sh --exclude README.md \
+--exclude .git/ --exclude *.sh --exclude README.md --exclude *.d --exclude *.ods --exclude garden-data-gen/* \
./ \
root@andrewlalis.com:/var/www/andrewlalis.com/html
diff --git a/vendor/photoswipe/photoswipe-lightbox.esm.min.js b/vendor/photoswipe/photoswipe-lightbox.esm.min.js
new file mode 100644
index 0000000..16b01d5
--- /dev/null
+++ b/vendor/photoswipe/photoswipe-lightbox.esm.min.js
@@ -0,0 +1,5 @@
+/*!
+ * PhotoSwipe Lightbox 5.4.3 - https://photoswipe.com
+ * (c) 2023 Dmytro Semenov
+ */
+function t(t,i,s){const h=document.createElement(i);return t&&(h.className=t),s&&s.appendChild(h),h}function i(t,i,s){t.style.width="number"==typeof i?`${i}px`:i,t.style.height="number"==typeof s?`${s}px`:s}const s="idle",h="loading",e="loaded",n="error";function o(t,i,s=document){let h=[];if(t instanceof Element)h=[t];else if(t instanceof NodeList||Array.isArray(t))h=Array.from(t);else{const e="string"==typeof t?t:i;e&&(h=Array.from(s.querySelectorAll(e)))}return h}function r(){return!(!navigator.vendor||!navigator.vendor.match(/apple/i))}class l{constructor(t,i){this.type=t,this.defaultPrevented=!1,i&&Object.assign(this,i)}preventDefault(){this.defaultPrevented=!0}}class a{constructor(i,s){if(this.element=t("pswp__img pswp__img--placeholder",i?"img":"div",s),i){const t=this.element;t.decoding="async",t.alt="",t.src=i,t.setAttribute("role","presentation")}this.element.setAttribute("aria-hidden","true")}setDisplayedSize(t,s){this.element&&("IMG"===this.element.tagName?(i(this.element,250,"auto"),this.element.style.transformOrigin="0 0",this.element.style.transform=function(t,i,s){let h=`translate3d(${t}px,${i||0}px,0)`;return void 0!==s&&(h+=` scale3d(${s},${s},1)`),h}(0,0,t/250)):i(this.element,t,s))}destroy(){var t;null!==(t=this.element)&&void 0!==t&&t.parentNode&&this.element.remove(),this.element=null}}class d{constructor(t,i,h){this.instance=i,this.data=t,this.index=h,this.element=void 0,this.placeholder=void 0,this.slide=void 0,this.displayedImageWidth=0,this.displayedImageHeight=0,this.width=Number(this.data.w)||Number(this.data.width)||0,this.height=Number(this.data.h)||Number(this.data.height)||0,this.isAttached=!1,this.hasSlide=!1,this.isDecoding=!1,this.state=s,this.data.type?this.type=this.data.type:this.data.src?this.type="image":this.type="html",this.instance.dispatch("contentInit",{content:this})}removePlaceholder(){this.placeholder&&!this.keepPlaceholder()&&setTimeout((()=>{this.placeholder&&(this.placeholder.destroy(),this.placeholder=void 0)}),1e3)}load(i,s){if(this.slide&&this.usePlaceholder())if(this.placeholder){const t=this.placeholder.element;t&&!t.parentElement&&this.slide.container.prepend(t)}else{const t=this.instance.applyFilters("placeholderSrc",!(!this.data.msrc||!this.slide.isFirstSlide)&&this.data.msrc,this);this.placeholder=new a(t,this.slide.container)}this.element&&!s||this.instance.dispatch("contentLoad",{content:this,isLazy:i}).defaultPrevented||(this.isImageContent()?(this.element=t("pswp__img","img"),this.displayedImageWidth&&this.loadImage(i)):(this.element=t("pswp__content","div"),this.element.innerHTML=this.data.html||""),s&&this.slide&&this.slide.updateContentSize(!0))}loadImage(t){var i,s;if(!this.isImageContent()||!this.element||this.instance.dispatch("contentLoadImage",{content:this,isLazy:t}).defaultPrevented)return;const e=this.element;this.updateSrcsetSizes(),this.data.srcset&&(e.srcset=this.data.srcset),e.src=null!==(i=this.data.src)&&void 0!==i?i:"",e.alt=null!==(s=this.data.alt)&&void 0!==s?s:"",this.state=h,e.complete?this.onLoaded():(e.onload=()=>{this.onLoaded()},e.onerror=()=>{this.onError()})}setSlide(t){this.slide=t,this.hasSlide=!0,this.instance=t.pswp}onLoaded(){this.state=e,this.slide&&this.element&&(this.instance.dispatch("loadComplete",{slide:this.slide,content:this}),this.slide.isActive&&this.slide.heavyAppended&&!this.element.parentNode&&(this.append(),this.slide.updateContentSize(!0)),this.state!==e&&this.state!==n||this.removePlaceholder())}onError(){this.state=n,this.slide&&(this.displayError(),this.instance.dispatch("loadComplete",{slide:this.slide,isError:!0,content:this}),this.instance.dispatch("loadError",{slide:this.slide,content:this}))}isLoading(){return this.instance.applyFilters("isContentLoading",this.state===h,this)}isError(){return this.state===n}isImageContent(){return"image"===this.type}setDisplayedSize(t,s){if(this.element&&(this.placeholder&&this.placeholder.setDisplayedSize(t,s),!this.instance.dispatch("contentResize",{content:this,width:t,height:s}).defaultPrevented&&(i(this.element,t,s),this.isImageContent()&&!this.isError()))){const i=!this.displayedImageWidth&&t;this.displayedImageWidth=t,this.displayedImageHeight=s,i?this.loadImage(!1):this.updateSrcsetSizes(),this.slide&&this.instance.dispatch("imageSizeChange",{slide:this.slide,width:t,height:s,content:this})}}isZoomable(){return this.instance.applyFilters("isContentZoomable",this.isImageContent()&&this.state!==n,this)}updateSrcsetSizes(){if(!this.isImageContent()||!this.element||!this.data.srcset)return;const t=this.element,i=this.instance.applyFilters("srcsetSizesWidth",this.displayedImageWidth,this);(!t.dataset.largestUsedSize||i>parseInt(t.dataset.largestUsedSize,10))&&(t.sizes=i+"px",t.dataset.largestUsedSize=String(i))}usePlaceholder(){return this.instance.applyFilters("useContentPlaceholder",this.isImageContent(),this)}lazyLoad(){this.instance.dispatch("contentLazyLoad",{content:this}).defaultPrevented||this.load(!0)}keepPlaceholder(){return this.instance.applyFilters("isKeepingPlaceholder",this.isLoading(),this)}destroy(){this.hasSlide=!1,this.slide=void 0,this.instance.dispatch("contentDestroy",{content:this}).defaultPrevented||(this.remove(),this.placeholder&&(this.placeholder.destroy(),this.placeholder=void 0),this.isImageContent()&&this.element&&(this.element.onload=null,this.element.onerror=null,this.element=void 0))}displayError(){if(this.slide){var i,s;let h=t("pswp__error-msg","div");h.innerText=null!==(i=null===(s=this.instance.options)||void 0===s?void 0:s.errorMsg)&&void 0!==i?i:"",h=this.instance.applyFilters("contentErrorElement",h,this),this.element=t("pswp__content pswp__error-msg-container","div"),this.element.appendChild(h),this.slide.container.innerText="",this.slide.container.appendChild(this.element),this.slide.updateContentSize(!0),this.removePlaceholder()}}append(){if(this.isAttached||!this.element)return;if(this.isAttached=!0,this.state===n)return void this.displayError();if(this.instance.dispatch("contentAppend",{content:this}).defaultPrevented)return;const t="decode"in this.element;this.isImageContent()?t&&this.slide&&(!this.slide.isActive||r())?(this.isDecoding=!0,this.element.decode().catch((()=>{})).finally((()=>{this.isDecoding=!1,this.appendImage()}))):this.appendImage():this.slide&&!this.element.parentNode&&this.slide.container.appendChild(this.element)}activate(){!this.instance.dispatch("contentActivate",{content:this}).defaultPrevented&&this.slide&&(this.isImageContent()&&this.isDecoding&&!r()?this.appendImage():this.isError()&&this.load(!1,!0),this.slide.holderElement&&this.slide.holderElement.setAttribute("aria-hidden","false"))}deactivate(){this.instance.dispatch("contentDeactivate",{content:this}),this.slide&&this.slide.holderElement&&this.slide.holderElement.setAttribute("aria-hidden","true")}remove(){this.isAttached=!1,this.instance.dispatch("contentRemove",{content:this}).defaultPrevented||(this.element&&this.element.parentNode&&this.element.remove(),this.placeholder&&this.placeholder.element&&this.placeholder.element.remove())}appendImage(){this.isAttached&&(this.instance.dispatch("contentAppendImage",{content:this}).defaultPrevented||(this.slide&&this.element&&!this.element.parentNode&&this.slide.container.appendChild(this.element),this.state!==e&&this.state!==n||this.removePlaceholder()))}}function c(t,i,s,h,e){let n=0;if(i.paddingFn)n=i.paddingFn(s,h,e)[t];else if(i.padding)n=i.padding[t];else{const s="padding"+t[0].toUpperCase()+t.slice(1);i[s]&&(n=i[s])}return Number(n)||0}class u{constructor(t,i,s,h){this.pswp=h,this.options=t,this.itemData=i,this.index=s,this.panAreaSize=null,this.elementSize=null,this.fit=1,this.fill=1,this.vFill=1,this.initial=1,this.secondary=1,this.max=1,this.min=1}update(t,i,s){const h={x:t,y:i};this.elementSize=h,this.panAreaSize=s;const e=s.x/h.x,n=s.y/h.y;this.fit=Math.min(1,en?e:n),this.vFill=Math.min(1,n),this.initial=this.t(),this.secondary=this.i(),this.max=Math.max(this.initial,this.secondary,this.o()),this.min=Math.min(this.fit,this.initial,this.secondary),this.pswp&&this.pswp.dispatch("zoomLevelsUpdate",{zoomLevels:this,slideData:this.itemData})}l(t){const i=t+"ZoomLevel",s=this.options[i];if(s)return"function"==typeof s?s(this):"fill"===s?this.fill:"fit"===s?this.fit:Number(s)}i(){let t=this.l("secondary");return t||(t=Math.min(1,3*this.fit),this.elementSize&&t*this.elementSize.x>4e3&&(t=4e3/this.elementSize.x),t)}t(){return this.l("initial")||this.fit}o(){return this.l("max")||Math.max(1,4*this.fit)}}function p(t,i,s){const h=i.createContentFromData(t,s);let e;const{options:n}=i;if(n){let o;e=new u(n,t,-1),o=i.pswp?i.pswp.viewportSize:function(t,i){if(t.getViewportSizeFn){const s=t.getViewportSizeFn(t,i);if(s)return s}return{x:document.documentElement.clientWidth,y:window.innerHeight}}(n,i);const r=function(t,i,s,h){return{x:i.x-c("left",t,i,s,h)-c("right",t,i,s,h),y:i.y-c("top",t,i,s,h)-c("bottom",t,i,s,h)}}(n,o,t,s);e.update(h.width,h.height,r)}return h.lazyLoad(),e&&h.setDisplayedSize(Math.ceil(h.width*e.initial),Math.ceil(h.height*e.initial)),h}class v extends class extends class{constructor(){this.u={},this.p={},this.pswp=void 0,this.options=void 0}addFilter(t,i,s=100){var h,e,n;this.p[t]||(this.p[t]=[]),null===(h=this.p[t])||void 0===h||h.push({fn:i,priority:s}),null===(e=this.p[t])||void 0===e||e.sort(((t,i)=>t.priority-i.priority)),null===(n=this.pswp)||void 0===n||n.addFilter(t,i,s)}removeFilter(t,i){this.p[t]&&(this.p[t]=this.p[t].filter((t=>t.fn!==i))),this.pswp&&this.pswp.removeFilter(t,i)}applyFilters(t,...i){var s;return null===(s=this.p[t])||void 0===s||s.forEach((t=>{i[0]=t.fn.apply(this,i)})),i[0]}on(t,i){var s,h;this.u[t]||(this.u[t]=[]),null===(s=this.u[t])||void 0===s||s.push(i),null===(h=this.pswp)||void 0===h||h.on(t,i)}off(t,i){var s;this.u[t]&&(this.u[t]=this.u[t].filter((t=>i!==t))),null===(s=this.pswp)||void 0===s||s.off(t,i)}dispatch(t,i){var s;if(this.pswp)return this.pswp.dispatch(t,i);const h=new l(t,i);return null===(s=this.u[t])||void 0===s||s.forEach((t=>{t.call(this,h)})),h}}{getNumItems(){var t;let i=0;const s=null===(t=this.options)||void 0===t?void 0:t.dataSource;s&&"length"in s?i=s.length:s&&"gallery"in s&&(s.items||(s.items=this.v(s.gallery)),s.items&&(i=s.items.length));const h=this.dispatch("numItems",{dataSource:s,numItems:i});return this.applyFilters("numItems",h.numItems,s)}createContentFromData(t,i){return new d(t,this,i)}getItemData(t){var i;const s=null===(i=this.options)||void 0===i?void 0:i.dataSource;let h={};Array.isArray(s)?h=s[t]:s&&"gallery"in s&&(s.items||(s.items=this.v(s.gallery)),h=s.items[t]);let e=h;e instanceof Element&&(e=this.m(e));const n=this.dispatch("itemData",{itemData:e||{},index:t});return this.applyFilters("itemData",n.itemData,t)}v(t){var i,s;return null!==(i=this.options)&&void 0!==i&&i.children||null!==(s=this.options)&&void 0!==s&&s.childSelector?o(this.options.children,this.options.childSelector,t)||[]:[t]}m(t){const i={element:t},s="A"===t.tagName?t:t.querySelector("a");if(s){i.src=s.dataset.pswpSrc||s.href,s.dataset.pswpSrcset&&(i.srcset=s.dataset.pswpSrcset),i.width=s.dataset.pswpWidth?parseInt(s.dataset.pswpWidth,10):0,i.height=s.dataset.pswpHeight?parseInt(s.dataset.pswpHeight,10):0,i.w=i.width,i.h=i.height,s.dataset.pswpType&&(i.type=s.dataset.pswpType);const e=t.querySelector("img");var h;if(e)i.msrc=e.currentSrc||e.src,i.alt=null!==(h=e.getAttribute("alt"))&&void 0!==h?h:"";(s.dataset.pswpCropped||s.dataset.cropped)&&(i.thumbCropped=!0)}return this.applyFilters("domItemData",i,t,s)}lazyLoadData(t,i){return p(t,this,i)}}{constructor(t){super(),this.options=t||{},this.g=0,this.shouldOpen=!1,this._=void 0,this.onThumbnailsClick=this.onThumbnailsClick.bind(this)}init(){o(this.options.gallery,this.options.gallerySelector).forEach((t=>{t.addEventListener("click",this.onThumbnailsClick,!1)}))}onThumbnailsClick(t){if(function(t){return"button"in t&&1===t.button||t.ctrlKey||t.metaKey||t.altKey||t.shiftKey}(t)||window.pswp)return;let i={x:t.clientX,y:t.clientY};i.x||i.y||(i=null);let s=this.getClickedIndex(t);s=this.applyFilters("clickedIndex",s,t,this);const h={gallery:t.currentTarget};s>=0&&(t.preventDefault(),this.loadAndOpen(s,h,i))}getClickedIndex(t){if(this.options.getClickedIndexFn)return this.options.getClickedIndexFn.call(this,t);const i=t.target,s=o(this.options.children,this.options.childSelector,t.currentTarget).findIndex((t=>t===i||t.contains(i)));return-1!==s?s:this.options.children||this.options.childSelector?-1:0}loadAndOpen(t,i,s){if(window.pswp||!this.options)return!1;if(!i&&this.options.gallery&&this.options.children){const t=o(this.options.gallery);t[0]&&(i={gallery:t[0]})}return this.options.index=t,this.options.initialPointerPos=s,this.shouldOpen=!0,this.preload(t,i),!0}preload(t,i){const{options:s}=this;i&&(s.dataSource=i);const h=[],e=typeof s.pswpModule;if("function"==typeof(n=s.pswpModule)&&n.prototype&&n.prototype.goTo)h.push(Promise.resolve(s.pswpModule));else{if("string"===e)throw new Error("pswpModule as string is no longer supported");if("function"!==e)throw new Error("pswpModule is not valid");h.push(s.pswpModule())}var n;"function"==typeof s.openPromise&&h.push(s.openPromise()),!1!==s.preloadFirstSlide&&t>=0&&(this._=function(t,i){const s=i.getItemData(t);if(!i.dispatch("lazyLoadSlide",{index:t,itemData:s}).defaultPrevented)return p(s,i,t)}(t,this));const o=++this.g;Promise.all(h).then((t=>{if(this.shouldOpen){const i=t[0];this.I(i,o)}}))}I(t,i){if(i!==this.g&&this.shouldOpen)return;if(this.shouldOpen=!1,window.pswp)return;const s="object"==typeof t?new t.default(this.options):new t(this.options);this.pswp=s,window.pswp=s,Object.keys(this.u).forEach((t=>{var i;null===(i=this.u[t])||void 0===i||i.forEach((i=>{s.on(t,i)}))})),Object.keys(this.p).forEach((t=>{var i;null===(i=this.p[t])||void 0===i||i.forEach((i=>{s.addFilter(t,i.fn,i.priority)}))})),this._&&(s.contentLoader.addToCache(this._),this._=void 0),s.on("destroy",(()=>{this.pswp=void 0,delete window.pswp})),s.init()}destroy(){var t;null===(t=this.pswp)||void 0===t||t.destroy(),this.shouldOpen=!1,this.u={},o(this.options.gallery,this.options.gallerySelector).forEach((t=>{t.removeEventListener("click",this.onThumbnailsClick,!1)}))}}export{v as default};
diff --git a/vendor/photoswipe/photoswipe.css b/vendor/photoswipe/photoswipe.css
new file mode 100644
index 0000000..686dfc3
--- /dev/null
+++ b/vendor/photoswipe/photoswipe.css
@@ -0,0 +1,420 @@
+/*! PhotoSwipe main CSS by Dmytro Semenov | photoswipe.com */
+
+.pswp {
+ --pswp-bg: #000;
+ --pswp-placeholder-bg: #222;
+
+
+ --pswp-root-z-index: 100000;
+
+ --pswp-preloader-color: rgba(79, 79, 79, 0.4);
+ --pswp-preloader-color-secondary: rgba(255, 255, 255, 0.9);
+
+ /* defined via js:
+ --pswp-transition-duration: 333ms; */
+
+ --pswp-icon-color: #fff;
+ --pswp-icon-color-secondary: #4f4f4f;
+ --pswp-icon-stroke-color: #4f4f4f;
+ --pswp-icon-stroke-width: 2px;
+
+ --pswp-error-text-color: var(--pswp-icon-color);
+}
+
+
+/*
+ Styles for basic PhotoSwipe (pswp) functionality (sliding area, open/close transitions)
+*/
+
+.pswp {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ z-index: var(--pswp-root-z-index);
+ display: none;
+ touch-action: none;
+ outline: 0;
+ opacity: 0.003;
+ contain: layout style size;
+ -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+}
+
+/* Prevents focus outline on the root element,
+ (it may be focused initially) */
+.pswp:focus {
+ outline: 0;
+}
+
+.pswp * {
+ box-sizing: border-box;
+}
+
+.pswp img {
+ max-width: none;
+}
+
+.pswp--open {
+ display: block;
+}
+
+.pswp,
+.pswp__bg {
+ transform: translateZ(0);
+ will-change: opacity;
+}
+
+.pswp__bg {
+ opacity: 0.005;
+ background: var(--pswp-bg);
+}
+
+.pswp,
+.pswp__scroll-wrap {
+ overflow: hidden;
+}
+
+.pswp__scroll-wrap,
+.pswp__bg,
+.pswp__container,
+.pswp__item,
+.pswp__content,
+.pswp__img,
+.pswp__zoom-wrap {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+}
+
+.pswp__img,
+.pswp__zoom-wrap {
+ width: auto;
+ height: auto;
+}
+
+.pswp--click-to-zoom.pswp--zoom-allowed .pswp__img {
+ cursor: -webkit-zoom-in;
+ cursor: -moz-zoom-in;
+ cursor: zoom-in;
+}
+
+.pswp--click-to-zoom.pswp--zoomed-in .pswp__img {
+ cursor: move;
+ cursor: -webkit-grab;
+ cursor: -moz-grab;
+ cursor: grab;
+}
+
+.pswp--click-to-zoom.pswp--zoomed-in .pswp__img:active {
+ cursor: -webkit-grabbing;
+ cursor: -moz-grabbing;
+ cursor: grabbing;
+}
+
+/* :active to override grabbing cursor */
+.pswp--no-mouse-drag.pswp--zoomed-in .pswp__img,
+.pswp--no-mouse-drag.pswp--zoomed-in .pswp__img:active,
+.pswp__img {
+ cursor: -webkit-zoom-out;
+ cursor: -moz-zoom-out;
+ cursor: zoom-out;
+}
+
+
+/* Prevent selection and tap highlights */
+.pswp__container,
+.pswp__img,
+.pswp__button,
+.pswp__counter {
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.pswp__item {
+ /* z-index for fade transition */
+ z-index: 1;
+ overflow: hidden;
+}
+
+.pswp__hidden {
+ display: none !important;
+}
+
+/* Allow to click through pswp__content element, but not its children */
+.pswp__content {
+ pointer-events: none;
+}
+.pswp__content > * {
+ pointer-events: auto;
+}
+
+
+/*
+
+ PhotoSwipe UI
+
+*/
+
+/*
+ Error message appears when image is not loaded
+ (JS option errorMsg controls markup)
+*/
+.pswp__error-msg-container {
+ display: grid;
+}
+.pswp__error-msg {
+ margin: auto;
+ font-size: 1em;
+ line-height: 1;
+ color: var(--pswp-error-text-color);
+}
+
+/*
+class pswp__hide-on-close is applied to elements that
+should hide (for example fade out) when PhotoSwipe is closed
+and show (for example fade in) when PhotoSwipe is opened
+ */
+.pswp .pswp__hide-on-close {
+ opacity: 0.005;
+ will-change: opacity;
+ transition: opacity var(--pswp-transition-duration) cubic-bezier(0.4, 0, 0.22, 1);
+ z-index: 10; /* always overlap slide content */
+ pointer-events: none; /* hidden elements should not be clickable */
+}
+
+/* class pswp--ui-visible is added when opening or closing transition starts */
+.pswp--ui-visible .pswp__hide-on-close {
+ opacity: 1;
+ pointer-events: auto;
+}
+
+/* styles, including css reset */
+.pswp__button {
+ position: relative;
+ display: block;
+ width: 50px;
+ height: 60px;
+ padding: 0;
+ margin: 0;
+ overflow: hidden;
+ cursor: pointer;
+ background: none;
+ border: 0;
+ box-shadow: none;
+ opacity: 0.85;
+ -webkit-appearance: none;
+ -webkit-touch-callout: none;
+}
+
+.pswp__button:hover,
+.pswp__button:active,
+.pswp__button:focus {
+ transition: none;
+ padding: 0;
+ background: none;
+ border: 0;
+ box-shadow: none;
+ opacity: 1;
+}
+
+.pswp__button:disabled {
+ opacity: 0.3;
+ cursor: auto;
+}
+
+.pswp__icn {
+ fill: var(--pswp-icon-color);
+ color: var(--pswp-icon-color-secondary);
+}
+
+.pswp__icn {
+ position: absolute;
+ top: 14px;
+ left: 9px;
+ width: 32px;
+ height: 32px;
+ overflow: hidden;
+ pointer-events: none;
+}
+
+.pswp__icn-shadow {
+ stroke: var(--pswp-icon-stroke-color);
+ stroke-width: var(--pswp-icon-stroke-width);
+ fill: none;
+}
+
+.pswp__icn:focus {
+ outline: 0;
+}
+
+/*
+ div element that matches size of large image,
+ large image loads on top of it,
+ used when msrc is not provided
+*/
+div.pswp__img--placeholder,
+.pswp__img--with-bg {
+ background: var(--pswp-placeholder-bg);
+}
+
+.pswp__top-bar {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 100%;
+ height: 60px;
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-end;
+ z-index: 10;
+
+ /* allow events to pass through top bar itself */
+ pointer-events: none !important;
+}
+.pswp__top-bar > * {
+ pointer-events: auto;
+ /* this makes transition significantly more smooth,
+ even though inner elements are not animated */
+ will-change: opacity;
+}
+
+
+/*
+
+ Close button
+
+*/
+.pswp__button--close {
+ margin-right: 6px;
+}
+
+
+/*
+
+ Arrow buttons
+
+*/
+.pswp__button--arrow {
+ position: absolute;
+ top: 0;
+ width: 75px;
+ height: 100px;
+ top: 50%;
+ margin-top: -50px;
+}
+
+.pswp__button--arrow:disabled {
+ display: none;
+ cursor: default;
+}
+
+.pswp__button--arrow .pswp__icn {
+ top: 50%;
+ margin-top: -30px;
+ width: 60px;
+ height: 60px;
+ background: none;
+ border-radius: 0;
+}
+
+.pswp--one-slide .pswp__button--arrow {
+ display: none;
+}
+
+/* hide arrows on touch screens */
+.pswp--touch .pswp__button--arrow {
+ visibility: hidden;
+}
+
+/* show arrows only after mouse was used */
+.pswp--has_mouse .pswp__button--arrow {
+ visibility: visible;
+}
+
+.pswp__button--arrow--prev {
+ right: auto;
+ left: 0px;
+}
+
+.pswp__button--arrow--next {
+ right: 0px;
+}
+.pswp__button--arrow--next .pswp__icn {
+ left: auto;
+ right: 14px;
+ /* flip horizontally */
+ transform: scale(-1, 1);
+}
+
+/*
+
+ Zoom button
+
+*/
+.pswp__button--zoom {
+ display: none;
+}
+
+.pswp--zoom-allowed .pswp__button--zoom {
+ display: block;
+}
+
+/* "+" => "-" */
+.pswp--zoomed-in .pswp__zoom-icn-bar-v {
+ display: none;
+}
+
+
+/*
+
+ Loading indicator
+
+*/
+.pswp__preloader {
+ position: relative;
+ overflow: hidden;
+ width: 50px;
+ height: 60px;
+ margin-right: auto;
+}
+
+.pswp__preloader .pswp__icn {
+ opacity: 0;
+ transition: opacity 0.2s linear;
+ animation: pswp-clockwise 600ms linear infinite;
+}
+
+.pswp__preloader--active .pswp__icn {
+ opacity: 0.85;
+}
+
+@keyframes pswp-clockwise {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(360deg); }
+}
+
+
+/*
+
+ "1 of 10" counter
+
+*/
+.pswp__counter {
+ height: 30px;
+ margin-top: 15px;
+ margin-inline-start: 20px;
+ font-size: 14px;
+ line-height: 30px;
+ color: var(--pswp-icon-color);
+ text-shadow: 1px 1px 3px var(--pswp-icon-color-secondary);
+ opacity: 0.85;
+}
+
+.pswp--one-slide .pswp__counter {
+ display: none;
+}
diff --git a/vendor/photoswipe/photoswipe.esm.min.js b/vendor/photoswipe/photoswipe.esm.min.js
new file mode 100644
index 0000000..30fbb15
--- /dev/null
+++ b/vendor/photoswipe/photoswipe.esm.min.js
@@ -0,0 +1,5 @@
+/*!
+ * PhotoSwipe 5.4.3 - https://photoswipe.com
+ * (c) 2023 Dmytro Semenov
+ */
+function t(t,i,s){const h=document.createElement(i);return t&&(h.className=t),s&&s.appendChild(h),h}function i(t,i){return t.x=i.x,t.y=i.y,void 0!==i.id&&(t.id=i.id),t}function s(t){t.x=Math.round(t.x),t.y=Math.round(t.y)}function h(t,i){const s=Math.abs(t.x-i.x),h=Math.abs(t.y-i.y);return Math.sqrt(s*s+h*h)}function e(t,i){return t.x===i.x&&t.y===i.y}function n(t,i,s){return Math.min(Math.max(t,i),s)}function o(t,i,s){let h=`translate3d(${t}px,${i||0}px,0)`;return void 0!==s&&(h+=` scale3d(${s},${s},1)`),h}function r(t,i,s,h){t.style.transform=o(i,s,h)}function a(t,i,s,h){t.style.transition=i?`${i} ${s}ms ${h||"cubic-bezier(.4,0,.22,1)"}`:"none"}function l(t,i,s){t.style.width="number"==typeof i?`${i}px`:i,t.style.height="number"==typeof s?`${s}px`:s}const c="idle",d="loading",u="loaded",p="error";function m(){return!(!navigator.vendor||!navigator.vendor.match(/apple/i))}let v=!1;try{window.addEventListener("test",null,Object.defineProperty({},"passive",{get:()=>{v=!0}}))}catch(t){}class f{constructor(){this.t=[]}add(t,i,s,h){this.i(t,i,s,h)}remove(t,i,s,h){this.i(t,i,s,h,!0)}removeAll(){this.t.forEach((t=>{this.i(t.target,t.type,t.listener,t.passive,!0,!0)})),this.t=[]}i(t,i,s,h,e,n){if(!t)return;const o=e?"removeEventListener":"addEventListener";i.split(" ").forEach((i=>{if(i){n||(e?this.t=this.t.filter((h=>h.type!==i||h.listener!==s||h.target!==t)):this.t.push({target:t,type:i,listener:s,passive:h}));const r=!!v&&{passive:h||!1};t[o](i,s,r)}}))}}function w(t,i){if(t.getViewportSizeFn){const s=t.getViewportSizeFn(t,i);if(s)return s}return{x:document.documentElement.clientWidth,y:window.innerHeight}}function g(t,i,s,h,e){let n=0;if(i.paddingFn)n=i.paddingFn(s,h,e)[t];else if(i.padding)n=i.padding[t];else{const s="padding"+t[0].toUpperCase()+t.slice(1);i[s]&&(n=i[s])}return Number(n)||0}function y(t,i,s,h){return{x:i.x-g("left",t,i,s,h)-g("right",t,i,s,h),y:i.y-g("top",t,i,s,h)-g("bottom",t,i,s,h)}}class _{constructor(t){this.slide=t,this.currZoomLevel=1,this.center={x:0,y:0},this.max={x:0,y:0},this.min={x:0,y:0}}update(t){this.currZoomLevel=t,this.slide.width?(this.o("x"),this.o("y"),this.slide.pswp.dispatch("calcBounds",{slide:this.slide})):this.reset()}o(t){const{pswp:i}=this.slide,s=this.slide["x"===t?"width":"height"]*this.currZoomLevel,h=g("x"===t?"left":"top",i.options,i.viewportSize,this.slide.data,this.slide.index),e=this.slide.panAreaSize[t];this.center[t]=Math.round((e-s)/2)+h,this.max[t]=s>e?Math.round(e-s)+h:this.center[t],this.min[t]=s>e?h:this.center[t]}reset(){this.center.x=0,this.center.y=0,this.max.x=0,this.max.y=0,this.min.x=0,this.min.y=0}correctPan(t,i){return n(i,this.max[t],this.min[t])}}class x{constructor(t,i,s,h){this.pswp=h,this.options=t,this.itemData=i,this.index=s,this.panAreaSize=null,this.elementSize=null,this.fit=1,this.fill=1,this.vFill=1,this.initial=1,this.secondary=1,this.max=1,this.min=1}update(t,i,s){const h={x:t,y:i};this.elementSize=h,this.panAreaSize=s;const e=s.x/h.x,n=s.y/h.y;this.fit=Math.min(1,en?e:n),this.vFill=Math.min(1,n),this.initial=this.l(),this.secondary=this.u(),this.max=Math.max(this.initial,this.secondary,this.p()),this.min=Math.min(this.fit,this.initial,this.secondary),this.pswp&&this.pswp.dispatch("zoomLevelsUpdate",{zoomLevels:this,slideData:this.itemData})}m(t){const i=t+"ZoomLevel",s=this.options[i];if(s)return"function"==typeof s?s(this):"fill"===s?this.fill:"fit"===s?this.fit:Number(s)}u(){let t=this.m("secondary");return t||(t=Math.min(1,3*this.fit),this.elementSize&&t*this.elementSize.x>4e3&&(t=4e3/this.elementSize.x),t)}l(){return this.m("initial")||this.fit}p(){return this.m("max")||Math.max(1,4*this.fit)}}class b{constructor(i,s,h){this.data=i,this.index=s,this.pswp=h,this.isActive=s===h.currIndex,this.currentResolution=0,this.panAreaSize={x:0,y:0},this.pan={x:0,y:0},this.isFirstSlide=this.isActive&&!h.opener.isOpen,this.zoomLevels=new x(h.options,i,s,h),this.pswp.dispatch("gettingData",{slide:this,data:this.data,index:s}),this.content=this.pswp.contentLoader.getContentBySlide(this),this.container=t("pswp__zoom-wrap","div"),this.holderElement=null,this.currZoomLevel=1,this.width=this.content.width,this.height=this.content.height,this.heavyAppended=!1,this.bounds=new _(this),this.prevDisplayedWidth=-1,this.prevDisplayedHeight=-1,this.pswp.dispatch("slideInit",{slide:this})}setIsActive(t){t&&!this.isActive?this.activate():!t&&this.isActive&&this.deactivate()}append(t){this.holderElement=t,this.container.style.transformOrigin="0 0",this.data&&(this.calculateSize(),this.load(),this.updateContentSize(),this.appendHeavy(),this.holderElement.appendChild(this.container),this.zoomAndPanToInitial(),this.pswp.dispatch("firstZoomPan",{slide:this}),this.applyCurrentZoomPan(),this.pswp.dispatch("afterSetContent",{slide:this}),this.isActive&&this.activate())}load(){this.content.load(!1),this.pswp.dispatch("slideLoad",{slide:this})}appendHeavy(){const{pswp:t}=this;!this.heavyAppended&&t.opener.isOpen&&!t.mainScroll.isShifted()&&(this.isActive,1)&&(this.pswp.dispatch("appendHeavy",{slide:this}).defaultPrevented||(this.heavyAppended=!0,this.content.append(),this.pswp.dispatch("appendHeavyContent",{slide:this})))}activate(){this.isActive=!0,this.appendHeavy(),this.content.activate(),this.pswp.dispatch("slideActivate",{slide:this})}deactivate(){this.isActive=!1,this.content.deactivate(),this.currZoomLevel!==this.zoomLevels.initial&&this.calculateSize(),this.currentResolution=0,this.zoomAndPanToInitial(),this.applyCurrentZoomPan(),this.updateContentSize(),this.pswp.dispatch("slideDeactivate",{slide:this})}destroy(){this.content.hasSlide=!1,this.content.remove(),this.container.remove(),this.pswp.dispatch("slideDestroy",{slide:this})}resize(){this.currZoomLevel!==this.zoomLevels.initial&&this.isActive?(this.calculateSize(),this.bounds.update(this.currZoomLevel),this.panTo(this.pan.x,this.pan.y)):(this.calculateSize(),this.currentResolution=0,this.zoomAndPanToInitial(),this.applyCurrentZoomPan(),this.updateContentSize())}updateContentSize(t){const i=this.currentResolution||this.zoomLevels.initial;if(!i)return;const s=Math.round(this.width*i)||this.pswp.viewportSize.x,h=Math.round(this.height*i)||this.pswp.viewportSize.y;(this.sizeChanged(s,h)||t)&&this.content.setDisplayedSize(s,h)}sizeChanged(t,i){return(t!==this.prevDisplayedWidth||i!==this.prevDisplayedHeight)&&(this.prevDisplayedWidth=t,this.prevDisplayedHeight=i,!0)}getPlaceholderElement(){var t;return null===(t=this.content.placeholder)||void 0===t?void 0:t.element}zoomTo(t,i,h,e){const{pswp:o}=this;if(!this.isZoomable()||o.mainScroll.isShifted())return;o.dispatch("beforeZoomTo",{destZoomLevel:t,centerPoint:i,transitionDuration:h}),o.animations.stopAllPan();const r=this.currZoomLevel;e||(t=n(t,this.zoomLevels.min,this.zoomLevels.max)),this.setZoomLevel(t),this.pan.x=this.calculateZoomToPanOffset("x",i,r),this.pan.y=this.calculateZoomToPanOffset("y",i,r),s(this.pan);const a=()=>{this.v(t),this.applyCurrentZoomPan()};h?o.animations.startTransition({isPan:!0,name:"zoomTo",target:this.container,transform:this.getCurrentTransform(),onComplete:a,duration:h,easing:o.options.easing}):a()}toggleZoom(t){this.zoomTo(this.currZoomLevel===this.zoomLevels.initial?this.zoomLevels.secondary:this.zoomLevels.initial,t,this.pswp.options.zoomAnimationDuration)}setZoomLevel(t){this.currZoomLevel=t,this.bounds.update(this.currZoomLevel)}calculateZoomToPanOffset(t,i,s){if(0===this.bounds.max[t]-this.bounds.min[t])return this.bounds.center[t];i||(i=this.pswp.getViewportCenterPoint()),s||(s=this.zoomLevels.initial);const h=this.currZoomLevel/s;return this.bounds.correctPan(t,(this.pan[t]-i[t])*h+i[t])}panTo(t,i){this.pan.x=this.bounds.correctPan("x",t),this.pan.y=this.bounds.correctPan("y",i),this.applyCurrentZoomPan()}isPannable(){return Boolean(this.width)&&this.currZoomLevel>this.zoomLevels.fit}isZoomable(){return Boolean(this.width)&&this.content.isZoomable()}applyCurrentZoomPan(){this.g(this.pan.x,this.pan.y,this.currZoomLevel),this===this.pswp.currSlide&&this.pswp.dispatch("zoomPanUpdate",{slide:this})}zoomAndPanToInitial(){this.currZoomLevel=this.zoomLevels.initial,this.bounds.update(this.currZoomLevel),i(this.pan,this.bounds.center),this.pswp.dispatch("initialZoomPan",{slide:this})}g(t,i,s){s/=this.currentResolution||this.zoomLevels.initial,r(this.container,t,i,s)}calculateSize(){const{pswp:t}=this;i(this.panAreaSize,y(t.options,t.viewportSize,this.data,this.index)),this.zoomLevels.update(this.width,this.height,this.panAreaSize),t.dispatch("calcSlideSize",{slide:this})}getCurrentTransform(){const t=this.currZoomLevel/(this.currentResolution||this.zoomLevels.initial);return o(this.pan.x,this.pan.y,t)}v(t){t!==this.currentResolution&&(this.currentResolution=t,this.updateContentSize(),this.pswp.dispatch("resolutionChanged"))}}class S{constructor(t){this.gestures=t,this.pswp=t.pswp,this.startPan={x:0,y:0}}start(){this.pswp.currSlide&&i(this.startPan,this.pswp.currSlide.pan),this.pswp.animations.stopAll()}change(){const{p1:t,prevP1:i,dragAxis:h}=this.gestures,{currSlide:e}=this.pswp;if("y"===h&&this.pswp.options.closeOnVerticalDrag&&e&&e.currZoomLevel<=e.zoomLevels.fit&&!this.gestures.isMultitouch){const s=e.pan.y+(t.y-i.y);if(!this.pswp.dispatch("verticalDrag",{panY:s}).defaultPrevented){this._("y",s,.6);const t=1-Math.abs(this.S(e.pan.y));this.pswp.applyBgOpacity(t),e.applyCurrentZoomPan()}}else{this.M("x")||(this.M("y"),e&&(s(e.pan),e.applyCurrentZoomPan()))}}end(){const{velocity:t}=this.gestures,{mainScroll:i,currSlide:s}=this.pswp;let h=0;if(this.pswp.animations.stopAll(),i.isShifted()){const s=(i.x-i.getCurrSlideX())/this.pswp.viewportSize.x;t.x<-.5&&s<0||t.x<.1&&s<-.5?(h=1,t.x=Math.min(t.x,0)):(t.x>.5&&s>0||t.x>-.1&&s>.5)&&(h=-1,t.x=Math.max(t.x,0)),i.moveIndexBy(h,!0,t.x)}s&&s.currZoomLevel>s.zoomLevels.max||this.gestures.isMultitouch?this.gestures.zoomLevels.correctZoomPan(!0):(this.P("x"),this.P("y"))}P(t){const{velocity:i}=this.gestures,{currSlide:s}=this.pswp;if(!s)return;const{pan:h,bounds:e}=s,o=h[t],r=this.pswp.bgOpacity<1&&"y"===t,a=o+function(t,i){return t*i/(1-i)}(i[t],.995);if(r){const t=this.S(o),i=this.S(a);if(t<0&&i<-.4||t>0&&i>.4)return void this.pswp.close()}const l=e.correctPan(t,a);if(o===l)return;const c=l===a?1:.82,d=this.pswp.bgOpacity,u=l-o;this.pswp.animations.startSpring({name:"panGesture"+t,isPan:!0,start:o,end:l,velocity:i[t],dampingRatio:c,onUpdate:i=>{if(r&&this.pswp.bgOpacity<1){const t=1-(l-i)/u;this.pswp.applyBgOpacity(n(d+(1-d)*t,0,1))}h[t]=Math.floor(i),s.applyCurrentZoomPan()}})}M(t){const{p1:i,dragAxis:s,prevP1:h,isMultitouch:e}=this.gestures,{currSlide:n,mainScroll:o}=this.pswp,r=i[t]-h[t],a=o.x+r;if(!r||!n)return!1;if("x"===t&&!n.isPannable()&&!e)return o.moveTo(a,!0),!0;const{bounds:l}=n,c=n.pan[t]+r;if(this.pswp.options.allowPanToNext&&"x"===s&&"x"===t&&!e){const i=o.getCurrSlideX(),s=o.x-i,h=r>0,e=!h;if(c>l.min[t]&&h){if(l.min[t]<=this.startPan[t])return o.moveTo(a,!0),!0;this._(t,c)}else if(c0)return o.moveTo(Math.max(a,i),!0),!0;if(s<0)return o.moveTo(Math.min(a,i),!0),!0}else this._(t,c)}else"y"===t&&(o.isShifted()||l.min.y===l.max.y)||this._(t,c);return!1}S(t){var i,s;return(t-(null!==(i=null===(s=this.pswp.currSlide)||void 0===s?void 0:s.bounds.center.y)&&void 0!==i?i:0))/(this.pswp.viewportSize.y/3)}_(t,i,s){const{currSlide:h}=this.pswp;if(!h)return;const{pan:e,bounds:n}=h;if(n.correctPan(t,i)!==i||s){const h=Math.round(i-e[t]);e[t]+=h*(s||.35)}else e[t]=i}}function z(t,i,s){return t.x=(i.x+s.x)/2,t.y=(i.y+s.y)/2,t}class M{constructor(t){this.gestures=t,this.C={x:0,y:0},this.T={x:0,y:0},this.A={x:0,y:0},this.D=!1,this.I=1}start(){const{currSlide:t}=this.gestures.pswp;t&&(this.I=t.currZoomLevel,i(this.C,t.pan)),this.gestures.pswp.animations.stopAllPan(),this.D=!1}change(){const{p1:t,startP1:i,p2:s,startP2:e,pswp:n}=this.gestures,{currSlide:o}=n;if(!o)return;const r=o.zoomLevels.min,a=o.zoomLevels.max;if(!o.isZoomable()||n.mainScroll.isShifted())return;z(this.T,i,e),z(this.A,t,s);let l=1/h(i,e)*h(t,s)*this.I;if(l>o.zoomLevels.initial+o.zoomLevels.initial/15&&(this.D=!0),la&&(l=a+.05*(l-a));o.pan.x=this.L("x",l),o.pan.y=this.L("y",l),o.setZoomLevel(l),o.applyCurrentZoomPan()}end(){const{pswp:t}=this.gestures,{currSlide:i}=t;(!i||i.currZoomLevelh.zoomLevels.max?r=h.zoomLevels.max:(a=!1,r=o);const l=s.bgOpacity,c=s.bgOpacity<1,d=i({x:0,y:0},h.pan);let u=i({x:0,y:0},d);t&&(this.A.x=0,this.A.y=0,this.T.x=0,this.T.y=0,this.I=o,i(this.C,d)),a&&(u={x:this.L("x",r),y:this.L("y",r)}),h.setZoomLevel(r),u={x:h.bounds.correctPan("x",u.x),y:h.bounds.correctPan("y",u.y)},h.setZoomLevel(o);const p=!e(u,d);if(!p&&!a&&!c)return h.v(r),void h.applyCurrentZoomPan();s.animations.stopAllPan(),s.animations.startSpring({isPan:!0,start:0,end:1e3,velocity:0,dampingRatio:1,naturalFrequency:40,onUpdate:t=>{if(t/=1e3,p||a){if(p&&(h.pan.x=d.x+(u.x-d.x)*t,h.pan.y=d.y+(u.y-d.y)*t),a){const i=o+(r-o)*t;h.setZoomLevel(i)}h.applyCurrentZoomPan()}c&&s.bgOpacity<1&&s.applyBgOpacity(n(l+(1-l)*t,0,1))},onComplete:()=>{h.v(r),h.applyCurrentZoomPan()}})}}function P(t){return!!t.target.closest(".pswp__container")}class C{constructor(t){this.gestures=t}click(t,i){const s=i.target.classList,h=s.contains("pswp__img"),e=s.contains("pswp__item")||s.contains("pswp__zoom-wrap");h?this.k("imageClick",t,i):e&&this.k("bgClick",t,i)}tap(t,i){P(i)&&this.k("tap",t,i)}doubleTap(t,i){P(i)&&this.k("doubleTap",t,i)}k(t,i,s){var h;const{pswp:e}=this.gestures,{currSlide:n}=e,o=t+"Action",r=e.options[o];if(!e.dispatch(o,{point:i,originalEvent:s}).defaultPrevented)if("function"!=typeof r)switch(r){case"close":case"next":e[r]();break;case"zoom":null==n||n.toggleZoom(i);break;case"zoom-or-close":null!=n&&n.isZoomable()&&n.zoomLevels.secondary!==n.zoomLevels.initial?n.toggleZoom(i):e.options.clickToCloseNonZoomable&&e.close();break;case"toggle-controls":null===(h=this.gestures.pswp.element)||void 0===h||h.classList.toggle("pswp--ui-visible")}else r.call(e,i,s)}}class T{constructor(t){this.pswp=t,this.dragAxis=null,this.p1={x:0,y:0},this.p2={x:0,y:0},this.prevP1={x:0,y:0},this.prevP2={x:0,y:0},this.startP1={x:0,y:0},this.startP2={x:0,y:0},this.velocity={x:0,y:0},this.Z={x:0,y:0},this.B={x:0,y:0},this.F=0,this.O=[],this.R="ontouchstart"in window,this.N=!!window.PointerEvent,this.supportsTouch=this.R||this.N&&navigator.maxTouchPoints>1,this.F=0,this.U=0,this.V=!1,this.isMultitouch=!1,this.isDragging=!1,this.isZooming=!1,this.raf=null,this.G=null,this.supportsTouch||(t.options.allowPanToNext=!1),this.drag=new S(this),this.zoomLevels=new M(this),this.tapHandler=new C(this),t.on("bindEvents",(()=>{t.events.add(t.scrollWrap,"click",this.$.bind(this)),this.N?this.q("pointer","down","up","cancel"):this.R?(this.q("touch","start","end","cancel"),t.scrollWrap&&(t.scrollWrap.ontouchmove=()=>{},t.scrollWrap.ontouchend=()=>{})):this.q("mouse","down","up")}))}q(t,i,s,h){const{pswp:e}=this,{events:n}=e,o=h?t+h:"";n.add(e.scrollWrap,t+i,this.onPointerDown.bind(this)),n.add(window,t+"move",this.onPointerMove.bind(this)),n.add(window,t+s,this.onPointerUp.bind(this)),o&&n.add(e.scrollWrap,o,this.onPointerUp.bind(this))}onPointerDown(t){const s="mousedown"===t.type||"mouse"===t.pointerType;if(s&&t.button>0)return;const{pswp:h}=this;h.opener.isOpen?h.dispatch("pointerDown",{originalEvent:t}).defaultPrevented||(s&&(h.mouseDetected(),this.H(t,"down")),h.animations.stopAll(),this.K(t,"down"),1===this.F&&(this.dragAxis=null,i(this.startP1,this.p1)),this.F>1?(this.W(),this.isMultitouch=!0):this.isMultitouch=!1):t.preventDefault()}onPointerMove(t){this.H(t,"move"),this.F&&(this.K(t,"move"),this.pswp.dispatch("pointerMove",{originalEvent:t}).defaultPrevented||(1!==this.F||this.isDragging?this.F>1&&!this.isZooming&&(this.j(),this.isZooming=!0,this.X(),this.zoomLevels.start(),this.Y(),this.J()):(this.dragAxis||this.tt(),this.dragAxis&&!this.isDragging&&(this.isZooming&&(this.isZooming=!1,this.zoomLevels.end()),this.isDragging=!0,this.W(),this.X(),this.U=Date.now(),this.V=!1,i(this.B,this.p1),this.velocity.x=0,this.velocity.y=0,this.drag.start(),this.Y(),this.J()))))}j(){this.isDragging&&(this.isDragging=!1,this.V||this.it(!0),this.drag.end(),this.dragAxis=null)}onPointerUp(t){this.F&&(this.K(t,"up"),this.pswp.dispatch("pointerUp",{originalEvent:t}).defaultPrevented||(0===this.F&&(this.Y(),this.isDragging?this.j():this.isZooming||this.isMultitouch||this.st(t)),this.F<2&&this.isZooming&&(this.isZooming=!1,this.zoomLevels.end(),1===this.F&&(this.dragAxis=null,this.X()))))}J(){(this.isDragging||this.isZooming)&&(this.it(),this.isDragging?e(this.p1,this.prevP1)||this.drag.change():e(this.p1,this.prevP1)&&e(this.p2,this.prevP2)||this.zoomLevels.change(),this.ht(),this.raf=requestAnimationFrame(this.J.bind(this)))}it(t){const s=Date.now(),h=s-this.U;h<50&&!t||(this.velocity.x=this.et("x",h),this.velocity.y=this.et("y",h),this.U=s,i(this.B,this.p1),this.V=!0)}st(t){const{mainScroll:s}=this.pswp;if(s.isShifted())return void s.moveIndexBy(0,!0);if(t.type.indexOf("cancel")>0)return;if("mouseup"===t.type||"mouse"===t.pointerType)return void this.tapHandler.click(this.startP1,t);const e=this.pswp.options.doubleTapAction?300:0;this.G?(this.W(),h(this.Z,this.startP1)<25&&this.tapHandler.doubleTap(this.startP1,t)):(i(this.Z,this.startP1),this.G=setTimeout((()=>{this.tapHandler.tap(this.startP1,t),this.W()}),e))}W(){this.G&&(clearTimeout(this.G),this.G=null)}et(t,i){const s=this.p1[t]-this.B[t];return Math.abs(s)>1&&i>5?s/i:0}Y(){this.raf&&(cancelAnimationFrame(this.raf),this.raf=null)}H(t,i){this.pswp.applyFilters("preventPointerEvent",!0,t,i)&&t.preventDefault()}K(t,s){if(this.N){const h=t,e=this.O.findIndex((t=>t.id===h.pointerId));"up"===s&&e>-1?this.O.splice(e,1):"down"===s&&-1===e?this.O.push(this.nt(h,{x:0,y:0})):e>-1&&this.nt(h,this.O[e]),this.F=this.O.length,this.F>0&&i(this.p1,this.O[0]),this.F>1&&i(this.p2,this.O[1])}else{const i=t;this.F=0,i.type.indexOf("touch")>-1?i.touches&&i.touches.length>0&&(this.nt(i.touches[0],this.p1),this.F++,i.touches.length>1&&(this.nt(i.touches[1],this.p2),this.F++)):(this.nt(t,this.p1),"up"===s?this.F=0:this.F++)}}ht(){i(this.prevP1,this.p1),i(this.prevP2,this.p2)}X(){i(this.startP1,this.p1),i(this.startP2,this.p2),this.ht()}tt(){if(this.pswp.mainScroll.isShifted())this.dragAxis="x";else{const t=Math.abs(this.p1.x-this.startP1.x)-Math.abs(this.p1.y-this.startP1.y);if(0!==t){const i=t>0?"x":"y";Math.abs(this.p1[i]-this.startP1[i])>=10&&(this.dragAxis=i)}}}nt(t,i){return i.x=t.pageX-this.pswp.offset.x,i.y=t.pageY-this.pswp.offset.y,"pointerId"in t?i.id=t.pointerId:void 0!==t.identifier&&(i.id=t.identifier),i}$(t){this.pswp.mainScroll.isShifted()&&(t.preventDefault(),t.stopPropagation())}}class A{constructor(t){this.pswp=t,this.x=0,this.slideWidth=0,this.ot=0,this.rt=0,this.lt=-1,this.itemHolders=[]}resize(t){const{pswp:i}=this,s=Math.round(i.viewportSize.x+i.viewportSize.x*i.options.spacing),h=s!==this.slideWidth;h&&(this.slideWidth=s,this.moveTo(this.getCurrSlideX())),this.itemHolders.forEach(((i,s)=>{h&&r(i.el,(s+this.lt)*this.slideWidth),t&&i.slide&&i.slide.resize()}))}resetPosition(){this.ot=0,this.rt=0,this.slideWidth=0,this.lt=-1}appendHolders(){this.itemHolders=[];for(let i=0;i<3;i++){const s=t("pswp__item","div",this.pswp.container);s.setAttribute("role","group"),s.setAttribute("aria-roledescription","slide"),s.setAttribute("aria-hidden","true"),s.style.display=1===i?"block":"none",this.itemHolders.push({el:s})}}canBeSwiped(){return this.pswp.getNumItems()>1}moveIndexBy(t,i,s){const{pswp:h}=this;let e=h.potentialIndex+t;const n=h.getNumItems();if(h.canLoop()){e=h.getLoopedIndex(e);const i=(t+n)%n;t=i<=n/2?i:i-n}else e<0?e=0:e>=n&&(e=n-1),t=e-h.potentialIndex;h.potentialIndex=e,this.ot-=t,h.animations.stopMainScroll();const o=this.getCurrSlideX();if(i){h.animations.startSpring({isMainScroll:!0,start:this.x,end:o,velocity:s||0,naturalFrequency:30,dampingRatio:1,onUpdate:t=>{this.moveTo(t)},onComplete:()=>{this.updateCurrItem(),h.appendHeavy()}});let t=h.potentialIndex-h.currIndex;if(h.canLoop()){const i=(t+n)%n;t=i<=n/2?i:i-n}Math.abs(t)>1&&this.updateCurrItem()}else this.moveTo(o),this.updateCurrItem();return Boolean(t)}getCurrSlideX(){return this.slideWidth*this.ot}isShifted(){return this.x!==this.getCurrSlideX()}updateCurrItem(){var t;const{pswp:i}=this,s=this.rt-this.ot;if(!s)return;this.rt=this.ot,i.currIndex=i.potentialIndex;let h,e=Math.abs(s);e>=3&&(this.lt+=s+(s>0?-3:3),e=3);for(let t=0;t0?(h=this.itemHolders.shift(),h&&(this.itemHolders[2]=h,this.lt++,r(h.el,(this.lt+2)*this.slideWidth),i.setContent(h,i.currIndex-e+t+2))):(h=this.itemHolders.pop(),h&&(this.itemHolders.unshift(h),this.lt--,r(h.el,this.lt*this.slideWidth),i.setContent(h,i.currIndex+e-t-2)));Math.abs(this.lt)>50&&!this.isShifted()&&(this.resetPosition(),this.resize()),i.animations.stopAllPan(),this.itemHolders.forEach(((t,i)=>{t.slide&&t.slide.setIsActive(1===i)})),i.currSlide=null===(t=this.itemHolders[1])||void 0===t?void 0:t.slide,i.contentLoader.updateLazy(s),i.currSlide&&i.currSlide.applyCurrentZoomPan(),i.dispatch("change")}moveTo(t,i){if(!this.pswp.canLoop()&&i){let i=(this.slideWidth*this.ot-t)/this.slideWidth;i+=this.pswp.currIndex;const s=Math.round(t-this.x);(i<0&&s>0||i>=this.pswp.getNumItems()-1&&s<0)&&(t=this.x+.35*s)}this.x=t,this.pswp.container&&r(this.pswp.container,t),this.pswp.dispatch("moveMainScroll",{x:t,dragging:null!=i&&i})}}const D={Escape:27,z:90,ArrowLeft:37,ArrowUp:38,ArrowRight:39,ArrowDown:40,Tab:9},I=(t,i)=>i?t:D[t];class E{constructor(t){this.pswp=t,this.ct=!1,t.on("bindEvents",(()=>{t.options.trapFocus&&(t.options.initialPointerPos||this.dt(),t.events.add(document,"focusin",this.ut.bind(this))),t.events.add(document,"keydown",this.vt.bind(this))}));const i=document.activeElement;t.on("destroy",(()=>{t.options.returnFocus&&i&&this.ct&&i.focus()}))}dt(){!this.ct&&this.pswp.element&&(this.pswp.element.focus(),this.ct=!0)}vt(t){const{pswp:i}=this;if(i.dispatch("keydown",{originalEvent:t}).defaultPrevented)return;if(function(t){return"button"in t&&1===t.button||t.ctrlKey||t.metaKey||t.altKey||t.shiftKey}(t))return;let s,h,e=!1;const n="key"in t;switch(n?t.key:t.keyCode){case I("Escape",n):i.options.escKey&&(s="close");break;case I("z",n):s="toggleZoom";break;case I("ArrowLeft",n):h="x";break;case I("ArrowUp",n):h="y";break;case I("ArrowRight",n):h="x",e=!0;break;case I("ArrowDown",n):e=!0,h="y";break;case I("Tab",n):this.dt()}if(h){t.preventDefault();const{currSlide:n}=i;i.options.arrowKeys&&"x"===h&&i.getNumItems()>1?s=e?"next":"prev":n&&n.currZoomLevel>n.zoomLevels.fit&&(n.pan[h]+=e?-80:80,n.panTo(n.pan.x,n.pan.y))}s&&(t.preventDefault(),i[s]())}ut(t){const{template:i}=this.pswp;i&&document!==t.target&&i!==t.target&&!i.contains(t.target)&&i.focus()}}const L="cubic-bezier(.4,0,.22,1)";class k{constructor(t){var i;this.props=t;const{target:s,onComplete:h,transform:e,onFinish:n=(()=>{}),duration:o=333,easing:r=L}=t;this.onFinish=n;const l=e?"transform":"opacity",c=null!==(i=t[l])&&void 0!==i?i:"";this.ft=s,this.wt=h,this.gt=!1,this.yt=this.yt.bind(this),this._t=setTimeout((()=>{a(s,l,o,r),this._t=setTimeout((()=>{s.addEventListener("transitionend",this.yt,!1),s.addEventListener("transitioncancel",this.yt,!1),this._t=setTimeout((()=>{this.xt()}),o+500),s.style[l]=c}),30)}),0)}yt(t){t.target===this.ft&&this.xt()}xt(){this.gt||(this.gt=!0,this.onFinish(),this.wt&&this.wt())}destroy(){this._t&&clearTimeout(this._t),a(this.ft),this.ft.removeEventListener("transitionend",this.yt,!1),this.ft.removeEventListener("transitioncancel",this.yt,!1),this.gt||this.xt()}}class Z{constructor(t,i,s){this.velocity=1e3*t,this.bt=i||.75,this.St=s||12,this.zt=this.St,this.bt<1&&(this.zt*=Math.sqrt(1-this.bt*this.bt))}easeFrame(t,i){let s,h=0;i/=1e3;const e=Math.E**(-this.bt*this.St*i);if(1===this.bt)s=this.velocity+this.St*t,h=(t+s*i)*e,this.velocity=h*-this.St+s*e;else if(this.bt<1){s=1/this.zt*(this.bt*this.St*t+this.velocity);const n=Math.cos(this.zt*i),o=Math.sin(this.zt*i);h=e*(t*n+s*o),this.velocity=h*-this.St*this.bt+e*(-this.zt*t*o+this.zt*s*n)}return h}}class B{constructor(t){this.props=t,this.Mt=0;const{start:i,end:s,velocity:h,onUpdate:e,onComplete:n,onFinish:o=(()=>{}),dampingRatio:r,naturalFrequency:a}=t;this.onFinish=o;const l=new Z(h,r,a);let c=Date.now(),d=i-s;const u=()=>{this.Mt&&(d=l.easeFrame(d,Date.now()-c),Math.abs(d)<1&&Math.abs(l.velocity)<50?(e(s),n&&n(),this.onFinish()):(c=Date.now(),e(d+s),this.Mt=requestAnimationFrame(u)))};this.Mt=requestAnimationFrame(u)}destroy(){this.Mt>=0&&cancelAnimationFrame(this.Mt),this.Mt=0}}class F{constructor(){this.activeAnimations=[]}startSpring(t){this.Pt(t,!0)}startTransition(t){this.Pt(t)}Pt(t,i){const s=i?new B(t):new k(t);return this.activeAnimations.push(s),s.onFinish=()=>this.stop(s),s}stop(t){t.destroy();const i=this.activeAnimations.indexOf(t);i>-1&&this.activeAnimations.splice(i,1)}stopAll(){this.activeAnimations.forEach((t=>{t.destroy()})),this.activeAnimations=[]}stopAllPan(){this.activeAnimations=this.activeAnimations.filter((t=>!t.props.isPan||(t.destroy(),!1)))}stopMainScroll(){this.activeAnimations=this.activeAnimations.filter((t=>!t.props.isMainScroll||(t.destroy(),!1)))}isPanRunning(){return this.activeAnimations.some((t=>t.props.isPan))}}class O{constructor(t){this.pswp=t,t.events.add(t.element,"wheel",this.Ct.bind(this))}Ct(t){t.preventDefault();const{currSlide:i}=this.pswp;let{deltaX:s,deltaY:h}=t;if(i&&!this.pswp.dispatch("wheel",{originalEvent:t}).defaultPrevented)if(t.ctrlKey||this.pswp.options.wheelToZoom){if(i.isZoomable()){let s=-h;1===t.deltaMode?s*=.05:s*=t.deltaMode?1:.002,s=2**s;const e=i.currZoomLevel*s;i.zoomTo(e,{x:t.clientX,y:t.clientY})}}else i.isPannable()&&(1===t.deltaMode&&(s*=18,h*=18),i.panTo(i.pan.x-s,i.pan.y-h))}}class R{constructor(i,s){var h;const e=s.name||s.className;let n=s.html;if(!1===i.options[e])return;"string"==typeof i.options[e+"SVG"]&&(n=i.options[e+"SVG"]),i.dispatch("uiElementCreate",{data:s});let o="";s.isButton?(o+="pswp__button ",o+=s.className||`pswp__button--${s.name}`):o+=s.className||`pswp__${s.name}`;let r=s.isButton?s.tagName||"button":s.tagName||"div";r=r.toLowerCase();const a=t(o,r);if(s.isButton){"button"===r&&(a.type="button");let{title:t}=s;const{ariaLabel:h}=s;"string"==typeof i.options[e+"Title"]&&(t=i.options[e+"Title"]),t&&(a.title=t);const n=h||t;n&&a.setAttribute("aria-label",n)}a.innerHTML=function(t){if("string"==typeof t)return t;if(!t||!t.isCustomSVG)return"";const i=t;let s='';return s=s.split("%d").join(i.size||32),i.outlineID&&(s+=' '),s+=i.inner,s+=" ",s}(n),s.onInit&&s.onInit(a,i),s.onClick&&(a.onclick=t=>{"string"==typeof s.onClick?i[s.onClick]():"function"==typeof s.onClick&&s.onClick(t,a,i)});const l=s.appendTo||"bar";let c=i.element;"bar"===l?(i.topBar||(i.topBar=t("pswp__top-bar pswp__hide-on-close","div",i.scrollWrap)),c=i.topBar):(a.classList.add("pswp__hide-on-close"),"wrapper"===l&&(c=i.scrollWrap)),null===(h=c)||void 0===h||h.appendChild(i.applyFilters("uiElement",a,s))}}function N(t,i,s){t.classList.add("pswp__button--arrow"),t.setAttribute("aria-controls","pswp__items"),i.on("change",(()=>{i.options.loop||(t.disabled=s?!(i.currIndex0))}))}const U={name:"arrowPrev",className:"pswp__button--arrow--prev",title:"Previous",order:10,isButton:!0,appendTo:"wrapper",html:{isCustomSVG:!0,size:60,inner:' ',outlineID:"pswp__icn-arrow"},onClick:"prev",onInit:N},V={name:"arrowNext",className:"pswp__button--arrow--next",title:"Next",order:11,isButton:!0,appendTo:"wrapper",html:{isCustomSVG:!0,size:60,inner:' ',outlineID:"pswp__icn-arrow"},onClick:"next",onInit:(t,i)=>{N(t,i,!0)}},G={name:"close",title:"Close",order:20,isButton:!0,html:{isCustomSVG:!0,inner:' ',outlineID:"pswp__icn-close"},onClick:"close"},$={name:"zoom",title:"Zoom",order:10,isButton:!0,html:{isCustomSVG:!0,inner:' ',outlineID:"pswp__icn-zoom"},onClick:"toggleZoom"},q={name:"preloader",appendTo:"bar",order:7,html:{isCustomSVG:!0,inner:' ',outlineID:"pswp__icn-loading"},onInit:(t,i)=>{let s,h=null;const e=i=>{var h,e;s!==i&&(s=i,h="active",e=i,t.classList.toggle("pswp__preloader--"+h,e))},n=()=>{var t;if(null===(t=i.currSlide)||void 0===t||!t.content.isLoading())return e(!1),void(h&&(clearTimeout(h),h=null));h||(h=setTimeout((()=>{var t;e(Boolean(null===(t=i.currSlide)||void 0===t?void 0:t.content.isLoading())),h=null}),i.options.preloaderDelay))};i.on("change",n),i.on("loadComplete",(t=>{i.currSlide===t.slide&&n()})),i.ui&&(i.ui.updatePreloaderVisibility=n)}},H={name:"counter",order:5,onInit:(t,i)=>{i.on("change",(()=>{t.innerText=i.currIndex+1+i.options.indexIndicatorSep+i.getNumItems()}))}};function K(t,i){t.classList.toggle("pswp--zoomed-in",i)}class W{constructor(t){this.pswp=t,this.isRegistered=!1,this.uiElementsData=[],this.items=[],this.updatePreloaderVisibility=()=>{},this.Tt=void 0}init(){const{pswp:t}=this;this.isRegistered=!1,this.uiElementsData=[G,U,V,$,q,H],t.dispatch("uiRegister"),this.uiElementsData.sort(((t,i)=>(t.order||0)-(i.order||0))),this.items=[],this.isRegistered=!0,this.uiElementsData.forEach((t=>{this.registerElement(t)})),t.on("change",(()=>{var i;null===(i=t.element)||void 0===i||i.classList.toggle("pswp--one-slide",1===t.getNumItems())})),t.on("zoomPanUpdate",(()=>this.At()))}registerElement(t){this.isRegistered?this.items.push(new R(this.pswp,t)):this.uiElementsData.push(t)}At(){const{template:t,currSlide:i,options:s}=this.pswp;if(this.pswp.opener.isClosing||!t||!i)return;let{currZoomLevel:h}=i;if(this.pswp.opener.isOpen||(h=i.zoomLevels.initial),h===this.Tt)return;this.Tt=h;const e=i.zoomLevels.initial-i.zoomLevels.secondary;if(Math.abs(e)<.01||!i.isZoomable())return K(t,!1),void t.classList.remove("pswp--zoom-allowed");t.classList.add("pswp--zoom-allowed");K(t,(h===i.zoomLevels.initial?i.zoomLevels.secondary:i.zoomLevels.initial)<=h),"zoom"!==s.imageClickAction&&"zoom-or-close"!==s.imageClickAction||t.classList.add("pswp--click-to-zoom")}}class j{constructor(t,i){this.type=t,this.defaultPrevented=!1,i&&Object.assign(this,i)}preventDefault(){this.defaultPrevented=!0}}class X{constructor(i,s){if(this.element=t("pswp__img pswp__img--placeholder",i?"img":"div",s),i){const t=this.element;t.decoding="async",t.alt="",t.src=i,t.setAttribute("role","presentation")}this.element.setAttribute("aria-hidden","true")}setDisplayedSize(t,i){this.element&&("IMG"===this.element.tagName?(l(this.element,250,"auto"),this.element.style.transformOrigin="0 0",this.element.style.transform=o(0,0,t/250)):l(this.element,t,i))}destroy(){var t;null!==(t=this.element)&&void 0!==t&&t.parentNode&&this.element.remove(),this.element=null}}class Y{constructor(t,i,s){this.instance=i,this.data=t,this.index=s,this.element=void 0,this.placeholder=void 0,this.slide=void 0,this.displayedImageWidth=0,this.displayedImageHeight=0,this.width=Number(this.data.w)||Number(this.data.width)||0,this.height=Number(this.data.h)||Number(this.data.height)||0,this.isAttached=!1,this.hasSlide=!1,this.isDecoding=!1,this.state=c,this.data.type?this.type=this.data.type:this.data.src?this.type="image":this.type="html",this.instance.dispatch("contentInit",{content:this})}removePlaceholder(){this.placeholder&&!this.keepPlaceholder()&&setTimeout((()=>{this.placeholder&&(this.placeholder.destroy(),this.placeholder=void 0)}),1e3)}load(i,s){if(this.slide&&this.usePlaceholder())if(this.placeholder){const t=this.placeholder.element;t&&!t.parentElement&&this.slide.container.prepend(t)}else{const t=this.instance.applyFilters("placeholderSrc",!(!this.data.msrc||!this.slide.isFirstSlide)&&this.data.msrc,this);this.placeholder=new X(t,this.slide.container)}this.element&&!s||this.instance.dispatch("contentLoad",{content:this,isLazy:i}).defaultPrevented||(this.isImageContent()?(this.element=t("pswp__img","img"),this.displayedImageWidth&&this.loadImage(i)):(this.element=t("pswp__content","div"),this.element.innerHTML=this.data.html||""),s&&this.slide&&this.slide.updateContentSize(!0))}loadImage(t){var i,s;if(!this.isImageContent()||!this.element||this.instance.dispatch("contentLoadImage",{content:this,isLazy:t}).defaultPrevented)return;const h=this.element;this.updateSrcsetSizes(),this.data.srcset&&(h.srcset=this.data.srcset),h.src=null!==(i=this.data.src)&&void 0!==i?i:"",h.alt=null!==(s=this.data.alt)&&void 0!==s?s:"",this.state=d,h.complete?this.onLoaded():(h.onload=()=>{this.onLoaded()},h.onerror=()=>{this.onError()})}setSlide(t){this.slide=t,this.hasSlide=!0,this.instance=t.pswp}onLoaded(){this.state=u,this.slide&&this.element&&(this.instance.dispatch("loadComplete",{slide:this.slide,content:this}),this.slide.isActive&&this.slide.heavyAppended&&!this.element.parentNode&&(this.append(),this.slide.updateContentSize(!0)),this.state!==u&&this.state!==p||this.removePlaceholder())}onError(){this.state=p,this.slide&&(this.displayError(),this.instance.dispatch("loadComplete",{slide:this.slide,isError:!0,content:this}),this.instance.dispatch("loadError",{slide:this.slide,content:this}))}isLoading(){return this.instance.applyFilters("isContentLoading",this.state===d,this)}isError(){return this.state===p}isImageContent(){return"image"===this.type}setDisplayedSize(t,i){if(this.element&&(this.placeholder&&this.placeholder.setDisplayedSize(t,i),!this.instance.dispatch("contentResize",{content:this,width:t,height:i}).defaultPrevented&&(l(this.element,t,i),this.isImageContent()&&!this.isError()))){const s=!this.displayedImageWidth&&t;this.displayedImageWidth=t,this.displayedImageHeight=i,s?this.loadImage(!1):this.updateSrcsetSizes(),this.slide&&this.instance.dispatch("imageSizeChange",{slide:this.slide,width:t,height:i,content:this})}}isZoomable(){return this.instance.applyFilters("isContentZoomable",this.isImageContent()&&this.state!==p,this)}updateSrcsetSizes(){if(!this.isImageContent()||!this.element||!this.data.srcset)return;const t=this.element,i=this.instance.applyFilters("srcsetSizesWidth",this.displayedImageWidth,this);(!t.dataset.largestUsedSize||i>parseInt(t.dataset.largestUsedSize,10))&&(t.sizes=i+"px",t.dataset.largestUsedSize=String(i))}usePlaceholder(){return this.instance.applyFilters("useContentPlaceholder",this.isImageContent(),this)}lazyLoad(){this.instance.dispatch("contentLazyLoad",{content:this}).defaultPrevented||this.load(!0)}keepPlaceholder(){return this.instance.applyFilters("isKeepingPlaceholder",this.isLoading(),this)}destroy(){this.hasSlide=!1,this.slide=void 0,this.instance.dispatch("contentDestroy",{content:this}).defaultPrevented||(this.remove(),this.placeholder&&(this.placeholder.destroy(),this.placeholder=void 0),this.isImageContent()&&this.element&&(this.element.onload=null,this.element.onerror=null,this.element=void 0))}displayError(){if(this.slide){var i,s;let h=t("pswp__error-msg","div");h.innerText=null!==(i=null===(s=this.instance.options)||void 0===s?void 0:s.errorMsg)&&void 0!==i?i:"",h=this.instance.applyFilters("contentErrorElement",h,this),this.element=t("pswp__content pswp__error-msg-container","div"),this.element.appendChild(h),this.slide.container.innerText="",this.slide.container.appendChild(this.element),this.slide.updateContentSize(!0),this.removePlaceholder()}}append(){if(this.isAttached||!this.element)return;if(this.isAttached=!0,this.state===p)return void this.displayError();if(this.instance.dispatch("contentAppend",{content:this}).defaultPrevented)return;const t="decode"in this.element;this.isImageContent()?t&&this.slide&&(!this.slide.isActive||m())?(this.isDecoding=!0,this.element.decode().catch((()=>{})).finally((()=>{this.isDecoding=!1,this.appendImage()}))):this.appendImage():this.slide&&!this.element.parentNode&&this.slide.container.appendChild(this.element)}activate(){!this.instance.dispatch("contentActivate",{content:this}).defaultPrevented&&this.slide&&(this.isImageContent()&&this.isDecoding&&!m()?this.appendImage():this.isError()&&this.load(!1,!0),this.slide.holderElement&&this.slide.holderElement.setAttribute("aria-hidden","false"))}deactivate(){this.instance.dispatch("contentDeactivate",{content:this}),this.slide&&this.slide.holderElement&&this.slide.holderElement.setAttribute("aria-hidden","true")}remove(){this.isAttached=!1,this.instance.dispatch("contentRemove",{content:this}).defaultPrevented||(this.element&&this.element.parentNode&&this.element.remove(),this.placeholder&&this.placeholder.element&&this.placeholder.element.remove())}appendImage(){this.isAttached&&(this.instance.dispatch("contentAppendImage",{content:this}).defaultPrevented||(this.slide&&this.element&&!this.element.parentNode&&this.slide.container.appendChild(this.element),this.state!==u&&this.state!==p||this.removePlaceholder()))}}function J(t,i,s){const h=i.createContentFromData(t,s);let e;const{options:n}=i;if(n){let o;e=new x(n,t,-1),o=i.pswp?i.pswp.viewportSize:w(n,i);const r=y(n,o,t,s);e.update(h.width,h.height,r)}return h.lazyLoad(),e&&h.setDisplayedSize(Math.ceil(h.width*e.initial),Math.ceil(h.height*e.initial)),h}class Q{constructor(t){this.pswp=t,this.limit=Math.max(t.options.preload[0]+t.options.preload[1]+1,5),this.Dt=[]}updateLazy(t){const{pswp:i}=this;if(i.dispatch("lazyLoad").defaultPrevented)return;const{preload:s}=i.options,h=void 0===t||t>=0;let e;for(e=0;e<=s[1];e++)this.loadSlideByIndex(i.currIndex+(h?e:-e));for(e=1;e<=s[0];e++)this.loadSlideByIndex(i.currIndex+(h?-e:e))}loadSlideByIndex(t){const i=this.pswp.getLoopedIndex(t);let s=this.getContentByIndex(i);s||(s=function(t,i){const s=i.getItemData(t);if(!i.dispatch("lazyLoadSlide",{index:t,itemData:s}).defaultPrevented)return J(s,i,t)}(i,this.pswp),s&&this.addToCache(s))}getContentBySlide(t){let i=this.getContentByIndex(t.index);return i||(i=this.pswp.createContentFromData(t.data,t.index),this.addToCache(i)),i.setSlide(t),i}addToCache(t){if(this.removeByIndex(t.index),this.Dt.push(t),this.Dt.length>this.limit){const t=this.Dt.findIndex((t=>!t.isAttached&&!t.hasSlide));if(-1!==t){this.Dt.splice(t,1)[0].destroy()}}}removeByIndex(t){const i=this.Dt.findIndex((i=>i.index===t));-1!==i&&this.Dt.splice(i,1)}getContentByIndex(t){return this.Dt.find((i=>i.index===t))}destroy(){this.Dt.forEach((t=>t.destroy())),this.Dt=[]}}class tt{constructor(t){this.pswp=t,this.isClosed=!0,this.isOpen=!1,this.isClosing=!1,this.isOpening=!1,this.It=void 0,this.Et=!1,this.Lt=!1,this.kt=!1,this.Zt=!1,this.Bt=void 0,this.Ft=void 0,this.Ot=void 0,this.Rt=void 0,this.Nt=void 0,this.Ut=this.Ut.bind(this),t.on("firstZoomPan",this.Ut)}open(){this.Ut(),this.Pt()}close(){if(this.isClosed||this.isClosing||this.isOpening)return;const t=this.pswp.currSlide;this.isOpen=!1,this.isOpening=!1,this.isClosing=!0,this.It=this.pswp.options.hideAnimationDuration,t&&t.currZoomLevel*t.width>=this.pswp.options.maxWidthToAnimate&&(this.It=0),this.Vt(),setTimeout((()=>{this.Pt()}),this.Lt?30:0)}Ut(){if(this.pswp.off("firstZoomPan",this.Ut),!this.isOpening){const t=this.pswp.currSlide;this.isOpening=!0,this.isClosing=!1,this.It=this.pswp.options.showAnimationDuration,t&&t.zoomLevels.initial*t.width>=this.pswp.options.maxWidthToAnimate&&(this.It=0),this.Vt()}}Vt(){const{pswp:t}=this,i=this.pswp.currSlide,{options:s}=t;var h,e;("fade"===s.showHideAnimationType?(s.showHideOpacity=!0,this.Nt=void 0):"none"===s.showHideAnimationType?(s.showHideOpacity=!1,this.It=0,this.Nt=void 0):this.isOpening&&t.Gt?this.Nt=t.Gt:this.Nt=this.pswp.getThumbBounds(),this.Bt=null==i?void 0:i.getPlaceholderElement(),t.animations.stopAll(),this.Et=Boolean(this.It&&this.It>50),this.$t=Boolean(this.Nt)&&(null==i?void 0:i.content.usePlaceholder())&&(!this.isClosing||!t.mainScroll.isShifted()),this.$t)?this.kt=null!==(h=s.showHideOpacity)&&void 0!==h&&h:(this.kt=!0,this.isOpening&&i&&(i.zoomAndPanToInitial(),i.applyCurrentZoomPan()));if(this.Zt=!this.kt&&this.pswp.options.bgOpacity>.003,this.Ft=this.kt?t.element:t.bg,!this.Et)return this.It=0,this.$t=!1,this.Zt=!1,this.kt=!0,void(this.isOpening&&(t.element&&(t.element.style.opacity=String(.003)),t.applyBgOpacity(1)));this.$t&&this.Nt&&this.Nt.innerRect?(this.Lt=!0,this.Ot=this.pswp.container,this.Rt=null===(e=this.pswp.currSlide)||void 0===e?void 0:e.holderElement,t.container&&(t.container.style.overflow="hidden",t.container.style.width=t.viewportSize.x+"px")):this.Lt=!1;this.isOpening?(this.kt?(t.element&&(t.element.style.opacity=String(.003)),t.applyBgOpacity(1)):(this.Zt&&t.bg&&(t.bg.style.opacity=String(.003)),t.element&&(t.element.style.opacity="1")),this.$t&&(this.qt(),this.Bt&&(this.Bt.style.willChange="transform",this.Bt.style.opacity=String(.003)))):this.isClosing&&(t.mainScroll.itemHolders[0]&&(t.mainScroll.itemHolders[0].el.style.display="none"),t.mainScroll.itemHolders[2]&&(t.mainScroll.itemHolders[2].el.style.display="none"),this.Lt&&0!==t.mainScroll.x&&(t.mainScroll.resetPosition(),t.mainScroll.resize()))}Pt(){this.isOpening&&this.Et&&this.Bt&&"IMG"===this.Bt.tagName?new Promise((t=>{let i=!1,s=!0;var h;(h=this.Bt,"decode"in h?h.decode().catch((()=>{})):h.complete?Promise.resolve(h):new Promise(((t,i)=>{h.onload=()=>t(h),h.onerror=i}))).finally((()=>{i=!0,s||t(!0)})),setTimeout((()=>{s=!1,i&&t(!0)}),50),setTimeout(t,250)})).finally((()=>this.Ht())):this.Ht()}Ht(){var t,i;null===(t=this.pswp.element)||void 0===t||t.style.setProperty("--pswp-transition-duration",this.It+"ms"),this.pswp.dispatch(this.isOpening?"openingAnimationStart":"closingAnimationStart"),this.pswp.dispatch("initialZoom"+(this.isOpening?"In":"Out")),null===(i=this.pswp.element)||void 0===i||i.classList.toggle("pswp--ui-visible",this.isOpening),this.isOpening?(this.Bt&&(this.Bt.style.opacity="1"),this.Kt()):this.isClosing&&this.Wt(),this.Et||this.jt()}jt(){const{pswp:t}=this;if(this.isOpen=this.isOpening,this.isClosed=this.isClosing,this.isOpening=!1,this.isClosing=!1,t.dispatch(this.isOpen?"openingAnimationEnd":"closingAnimationEnd"),t.dispatch("initialZoom"+(this.isOpen?"InEnd":"OutEnd")),this.isClosed)t.destroy();else if(this.isOpen){var i;this.$t&&t.container&&(t.container.style.overflow="visible",t.container.style.width="100%"),null===(i=t.currSlide)||void 0===i||i.applyCurrentZoomPan()}}Kt(){const{pswp:t}=this;this.$t&&(this.Lt&&this.Ot&&this.Rt&&(this.Xt(this.Ot,"transform","translate3d(0,0,0)"),this.Xt(this.Rt,"transform","none")),t.currSlide&&(t.currSlide.zoomAndPanToInitial(),this.Xt(t.currSlide.container,"transform",t.currSlide.getCurrentTransform()))),this.Zt&&t.bg&&this.Xt(t.bg,"opacity",String(t.options.bgOpacity)),this.kt&&t.element&&this.Xt(t.element,"opacity","1")}Wt(){const{pswp:t}=this;this.$t&&this.qt(!0),this.Zt&&t.bgOpacity>.01&&t.bg&&this.Xt(t.bg,"opacity","0"),this.kt&&t.element&&this.Xt(t.element,"opacity","0")}qt(t){if(!this.Nt)return;const{pswp:s}=this,{innerRect:h}=this.Nt,{currSlide:e,viewportSize:n}=s;if(this.Lt&&h&&this.Ot&&this.Rt){const i=-n.x+(this.Nt.x-h.x)+h.w,s=-n.y+(this.Nt.y-h.y)+h.h,e=n.x-h.w,a=n.y-h.h;t?(this.Xt(this.Ot,"transform",o(i,s)),this.Xt(this.Rt,"transform",o(e,a))):(r(this.Ot,i,s),r(this.Rt,e,a))}e&&(i(e.pan,h||this.Nt),e.currZoomLevel=this.Nt.w/e.width,t?this.Xt(e.container,"transform",e.getCurrentTransform()):e.applyCurrentZoomPan())}Xt(t,i,s){if(!this.It)return void(t.style[i]=s);const{animations:h}=this.pswp,e={duration:this.It,easing:this.pswp.options.easing,onComplete:()=>{h.activeAnimations.length||this.jt()},target:t};e[i]=s,h.startTransition(e)}}const it={allowPanToNext:!0,spacing:.1,loop:!0,pinchToClose:!0,closeOnVerticalDrag:!0,hideAnimationDuration:333,showAnimationDuration:333,zoomAnimationDuration:333,escKey:!0,arrowKeys:!0,trapFocus:!0,returnFocus:!0,maxWidthToAnimate:4e3,clickToCloseNonZoomable:!0,imageClickAction:"zoom-or-close",bgClickAction:"close",tapAction:"toggle-controls",doubleTapAction:"zoom",indexIndicatorSep:" / ",preloaderDelay:2e3,bgOpacity:.8,index:0,errorMsg:"The image cannot be loaded",preload:[1,2],easing:"cubic-bezier(.4,0,.22,1)"};class st extends class extends class{constructor(){this.Yt={},this.Jt={},this.pswp=void 0,this.options=void 0}addFilter(t,i,s=100){var h,e,n;this.Jt[t]||(this.Jt[t]=[]),null===(h=this.Jt[t])||void 0===h||h.push({fn:i,priority:s}),null===(e=this.Jt[t])||void 0===e||e.sort(((t,i)=>t.priority-i.priority)),null===(n=this.pswp)||void 0===n||n.addFilter(t,i,s)}removeFilter(t,i){this.Jt[t]&&(this.Jt[t]=this.Jt[t].filter((t=>t.fn!==i))),this.pswp&&this.pswp.removeFilter(t,i)}applyFilters(t,...i){var s;return null===(s=this.Jt[t])||void 0===s||s.forEach((t=>{i[0]=t.fn.apply(this,i)})),i[0]}on(t,i){var s,h;this.Yt[t]||(this.Yt[t]=[]),null===(s=this.Yt[t])||void 0===s||s.push(i),null===(h=this.pswp)||void 0===h||h.on(t,i)}off(t,i){var s;this.Yt[t]&&(this.Yt[t]=this.Yt[t].filter((t=>i!==t))),null===(s=this.pswp)||void 0===s||s.off(t,i)}dispatch(t,i){var s;if(this.pswp)return this.pswp.dispatch(t,i);const h=new j(t,i);return null===(s=this.Yt[t])||void 0===s||s.forEach((t=>{t.call(this,h)})),h}}{getNumItems(){var t;let i=0;const s=null===(t=this.options)||void 0===t?void 0:t.dataSource;s&&"length"in s?i=s.length:s&&"gallery"in s&&(s.items||(s.items=this.Qt(s.gallery)),s.items&&(i=s.items.length));const h=this.dispatch("numItems",{dataSource:s,numItems:i});return this.applyFilters("numItems",h.numItems,s)}createContentFromData(t,i){return new Y(t,this,i)}getItemData(t){var i;const s=null===(i=this.options)||void 0===i?void 0:i.dataSource;let h={};Array.isArray(s)?h=s[t]:s&&"gallery"in s&&(s.items||(s.items=this.Qt(s.gallery)),h=s.items[t]);let e=h;e instanceof Element&&(e=this.ti(e));const n=this.dispatch("itemData",{itemData:e||{},index:t});return this.applyFilters("itemData",n.itemData,t)}Qt(t){var i,s;return null!==(i=this.options)&&void 0!==i&&i.children||null!==(s=this.options)&&void 0!==s&&s.childSelector?function(t,i,s=document){let h=[];if(t instanceof Element)h=[t];else if(t instanceof NodeList||Array.isArray(t))h=Array.from(t);else{const e="string"==typeof t?t:i;e&&(h=Array.from(s.querySelectorAll(e)))}return h}(this.options.children,this.options.childSelector,t)||[]:[t]}ti(t){const i={element:t},s="A"===t.tagName?t:t.querySelector("a");if(s){i.src=s.dataset.pswpSrc||s.href,s.dataset.pswpSrcset&&(i.srcset=s.dataset.pswpSrcset),i.width=s.dataset.pswpWidth?parseInt(s.dataset.pswpWidth,10):0,i.height=s.dataset.pswpHeight?parseInt(s.dataset.pswpHeight,10):0,i.w=i.width,i.h=i.height,s.dataset.pswpType&&(i.type=s.dataset.pswpType);const e=t.querySelector("img");var h;if(e)i.msrc=e.currentSrc||e.src,i.alt=null!==(h=e.getAttribute("alt"))&&void 0!==h?h:"";(s.dataset.pswpCropped||s.dataset.cropped)&&(i.thumbCropped=!0)}return this.applyFilters("domItemData",i,t,s)}lazyLoadData(t,i){return J(t,this,i)}}{constructor(t){super(),this.options=this.ii(t||{}),this.offset={x:0,y:0},this.si={x:0,y:0},this.viewportSize={x:0,y:0},this.bgOpacity=1,this.currIndex=0,this.potentialIndex=0,this.isOpen=!1,this.isDestroying=!1,this.hasMouse=!1,this.hi={},this.Gt=void 0,this.topBar=void 0,this.element=void 0,this.template=void 0,this.container=void 0,this.scrollWrap=void 0,this.currSlide=void 0,this.events=new f,this.animations=new F,this.mainScroll=new A(this),this.gestures=new T(this),this.opener=new tt(this),this.keyboard=new E(this),this.contentLoader=new Q(this)}init(){if(this.isOpen||this.isDestroying)return!1;this.isOpen=!0,this.dispatch("init"),this.dispatch("beforeOpen"),this.ei();let t="pswp--open";return this.gestures.supportsTouch&&(t+=" pswp--touch"),this.options.mainClass&&(t+=" "+this.options.mainClass),this.element&&(this.element.className+=" "+t),this.currIndex=this.options.index||0,this.potentialIndex=this.currIndex,this.dispatch("firstUpdate"),this.scrollWheel=new O(this),(Number.isNaN(this.currIndex)||this.currIndex<0||this.currIndex>=this.getNumItems())&&(this.currIndex=0),this.gestures.supportsTouch||this.mouseDetected(),this.updateSize(),this.offset.y=window.pageYOffset,this.hi=this.getItemData(this.currIndex),this.dispatch("gettingData",{index:this.currIndex,data:this.hi,slide:void 0}),this.Gt=this.getThumbBounds(),this.dispatch("initialLayout"),this.on("openingAnimationEnd",(()=>{const{itemHolders:t}=this.mainScroll;t[0]&&(t[0].el.style.display="block",this.setContent(t[0],this.currIndex-1)),t[2]&&(t[2].el.style.display="block",this.setContent(t[2],this.currIndex+1)),this.appendHeavy(),this.contentLoader.updateLazy(),this.events.add(window,"resize",this.ni.bind(this)),this.events.add(window,"scroll",this.oi.bind(this)),this.dispatch("bindEvents")})),this.mainScroll.itemHolders[1]&&this.setContent(this.mainScroll.itemHolders[1],this.currIndex),this.dispatch("change"),this.opener.open(),this.dispatch("afterInit"),!0}getLoopedIndex(t){const i=this.getNumItems();return this.options.loop&&(t>i-1&&(t-=i),t<0&&(t+=i)),n(t,0,i-1)}appendHeavy(){this.mainScroll.itemHolders.forEach((t=>{var i;null===(i=t.slide)||void 0===i||i.appendHeavy()}))}goTo(t){this.mainScroll.moveIndexBy(this.getLoopedIndex(t)-this.potentialIndex)}next(){this.goTo(this.potentialIndex+1)}prev(){this.goTo(this.potentialIndex-1)}zoomTo(...t){var i;null===(i=this.currSlide)||void 0===i||i.zoomTo(...t)}toggleZoom(){var t;null===(t=this.currSlide)||void 0===t||t.toggleZoom()}close(){this.opener.isOpen&&!this.isDestroying&&(this.isDestroying=!0,this.dispatch("close"),this.events.removeAll(),this.opener.close())}destroy(){var t;if(!this.isDestroying)return this.options.showHideAnimationType="none",void this.close();this.dispatch("destroy"),this.Yt={},this.scrollWrap&&(this.scrollWrap.ontouchmove=null,this.scrollWrap.ontouchend=null),null===(t=this.element)||void 0===t||t.remove(),this.mainScroll.itemHolders.forEach((t=>{var i;null===(i=t.slide)||void 0===i||i.destroy()})),this.contentLoader.destroy(),this.events.removeAll()}refreshSlideContent(t){this.contentLoader.removeByIndex(t),this.mainScroll.itemHolders.forEach(((i,s)=>{var h,e;let n=(null!==(h=null===(e=this.currSlide)||void 0===e?void 0:e.index)&&void 0!==h?h:0)-1+s;var o;(this.canLoop()&&(n=this.getLoopedIndex(n)),n===t)&&(this.setContent(i,t,!0),1===s&&(this.currSlide=i.slide,null===(o=i.slide)||void 0===o||o.setIsActive(!0)))})),this.dispatch("change")}setContent(t,i,s){if(this.canLoop()&&(i=this.getLoopedIndex(i)),t.slide){if(t.slide.index===i&&!s)return;t.slide.destroy(),t.slide=void 0}if(!this.canLoop()&&(i<0||i>=this.getNumItems()))return;const h=this.getItemData(i);t.slide=new b(h,i,this),i===this.currIndex&&(this.currSlide=t.slide),t.slide.append(t.el)}getViewportCenterPoint(){return{x:this.viewportSize.x/2,y:this.viewportSize.y/2}}updateSize(t){if(this.isDestroying)return;const s=w(this.options,this);!t&&e(s,this.si)||(i(this.si,s),this.dispatch("beforeResize"),i(this.viewportSize,this.si),this.oi(),this.dispatch("viewportSize"),this.mainScroll.resize(this.opener.isOpen),!this.hasMouse&&window.matchMedia("(any-hover: hover)").matches&&this.mouseDetected(),this.dispatch("resize"))}applyBgOpacity(t){this.bgOpacity=Math.max(t,0),this.bg&&(this.bg.style.opacity=String(this.bgOpacity*this.options.bgOpacity))}mouseDetected(){var t;this.hasMouse||(this.hasMouse=!0,null===(t=this.element)||void 0===t||t.classList.add("pswp--has_mouse"))}ni(){this.updateSize(),/iPhone|iPad|iPod/i.test(window.navigator.userAgent)&&setTimeout((()=>{this.updateSize()}),500)}oi(){this.setScrollOffset(0,window.pageYOffset)}setScrollOffset(t,i){this.offset.x=t,this.offset.y=i,this.dispatch("updateScrollOffset")}ei(){this.element=t("pswp","div"),this.element.setAttribute("tabindex","-1"),this.element.setAttribute("role","dialog"),this.template=this.element,this.bg=t("pswp__bg","div",this.element),this.scrollWrap=t("pswp__scroll-wrap","section",this.element),this.container=t("pswp__container","div",this.scrollWrap),this.scrollWrap.setAttribute("aria-roledescription","carousel"),this.container.setAttribute("aria-live","off"),this.container.setAttribute("id","pswp__items"),this.mainScroll.appendHolders(),this.ui=new W(this),this.ui.init(),(this.options.appendToEl||document.body).appendChild(this.element)}getThumbBounds(){return function(t,i,s){const h=s.dispatch("thumbBounds",{index:t,itemData:i,instance:s});if(h.thumbBounds)return h.thumbBounds;const{element:e}=i;let n,o;if(e&&!1!==s.options.thumbSelector){const t=s.options.thumbSelector||"img";o=e.matches(t)?e:e.querySelector(t)}return o=s.applyFilters("thumbEl",o,i,t),o&&(n=i.thumbCropped?function(t,i,s){const h=t.getBoundingClientRect(),e=h.width/i,n=h.height/s,o=e>n?e:n,r=(h.width-i*o)/2,a=(h.height-s*o)/2,l={x:h.left+r,y:h.top+a,w:i*o};return l.innerRect={w:h.width,h:h.height,x:r,y:a},l}(o,i.width||i.w||0,i.height||i.h||0):function(t){const i=t.getBoundingClientRect();return{x:i.left,y:i.top,w:i.width}}(o)),s.applyFilters("thumbBounds",n,i,t)}(this.currIndex,this.currSlide?this.currSlide.data:this.hi,this)}canLoop(){return this.options.loop&&this.getNumItems()>2}ii(t){return window.matchMedia("(prefers-reduced-motion), (update: slow)").matches&&(t.showHideAnimationType="none",t.zoomAnimationDuration=0),{...it,...t}}}export{st as default};