diff --git a/src/config.js b/src/config.js index 463b1cd..7803625 100644 --- a/src/config.js +++ b/src/config.js @@ -1,6 +1,6 @@ const config = { stickerPacksDir: "stickerpacks", - outDir: "sticker", + outDir: "", homeserverUrl: "https://synapse.wah.su/__thumbnail/" }; diff --git a/src/hotreload.js b/src/hotreload.js index 7027f36..f9de754 100644 --- a/src/hotreload.js +++ b/src/hotreload.js @@ -1,4 +1,4 @@ -let webSocket = new WebSocket('ws://127.0.0.1:3001'); +let webSocket = new WebSocket(`ws://${window.location.hostname}:3001`); webSocket.onmessage = function(e) { if (e.data == "RELOAD") { console.log("Reloading page after build") diff --git a/src/index.js b/src/index.js index e214111..e8fe6ac 100644 --- a/src/index.js +++ b/src/index.js @@ -1,11 +1,9 @@ const config = require("./config"); const fs = require("fs"); const path = require("path"); -const { log } = require("./utils"); +const { log, CreateImageURL, CreatePackDescription } = require("./utils"); let ejs = require("ejs"); -// const _CreatePackPage = require("./templates/pack"); - let PackIndex = null; let Packs = []; @@ -52,8 +50,31 @@ if (OutPath != ParPath) { PackIndex.packs.forEach((pack) => { const packFile = JSON.parse(fs.readFileSync(`${InpPath}${pack}`)); - // if (!fs.existsSync(`${OutPath}${packFile.id}`)) fs.mkdirSync(`${OutPath}${packFile.id}`); - // fs.writeFileSync(`${OutPath}${packFile.id}/index.html`, _CreatePackPage(PackIndex, packFile, isDev)); + const Template = fs.readFileSync( + path.join(ParPath, "src/templates/Base.ejs") + ); + const html = ejs.render( + Template.toString(), + { + title: packFile.title, + description: CreatePackDescription(packFile), + image: { + url: CreateImageURL(config.homeserverUrl, packFile.stickers[0].id), + mimetype: packFile.stickers[0].info.mimetype, + w: packFile.stickers[0].info.w, + h: packFile.stickers[0].info.h, + alt: packFile.stickers[0].info.alt, + }, + path: config.outDir ? `/${config.outDir}` : "", + isDev, + stickerset: packFile, + page: "stickerset", + homeserverUrl: config.homeserverUrl, + }, + { root: path.join(ParPath, "src/templates") } + ); + if (!fs.existsSync(`${OutPath}${packFile.id}`)) fs.mkdirSync(`${OutPath}${packFile.id}`); + fs.writeFileSync(`${OutPath}${packFile.id}/index.html`, html); Packs.push({ id: packFile.id, name: packFile.title, @@ -86,7 +107,7 @@ const html = ejs.render( h: "96", alt: "", }, - path: config.OutPath, + path: config.outDir ? `/${config.outDir}` : "", isDev, stickerset: null, page: "index", @@ -95,6 +116,5 @@ const html = ejs.render( }, { root: path.join(ParPath, "src/templates") } ); -log("LOG", `\n\n${html}\n\n`); fs.writeFileSync(`${OutPath}index.html`, html); log("INFO", "Generation complete"); diff --git a/src/templates/Base.ejs b/src/templates/Base.ejs index 944d39c..c148b2e 100644 --- a/src/templates/Base.ejs +++ b/src/templates/Base.ejs @@ -1,28 +1,100 @@ - <%- include('/components/Head', {title, description, image, path, isDev}); %> +<%- include('/components/Head', {title, description, image, path, isDev}); %> <%- include("/components/Header", {path, stickerset}) %> -
-
-
- <% if (page == "index") { %> -
- <% packs.forEach(function(pack){ %> - <%- include('/components/Link/Stickerset', {path, homeserverUrl, pack}); %> - <% }); %> -
- <% }; %> - -
- by @radiquum -
-

Find us on:

- github - website -
+
+
+
+ <% if (page=="index" ) { %> +
+ <% packs.forEach(function(pack){ %> + <%- include('/components/Link/Stickerset', {path, homeserverUrl, pack}); %> + <% }); %> +
+ <%- include('/components/Footer'); %> + <% }; %> + <% if (page=="stickerset" ) { %> +
+
+ <%- include('/components/Pack/Description', {homeserverUrl, stickerset}); %> + <%- include('/components/Pack/Links', {stickerset}); %> + + +
+
+ <%- include('/components/Pack/Preview', {homeserverUrl, stickerset}); %> +
+
+ <%- include('/components/Footer'); %> +
+
+ <% }; %>
-
- + + <% if (page=="stickerset" ) { %> + + <% }; %> \ No newline at end of file diff --git a/src/templates/components/Footer.ejs b/src/templates/components/Footer.ejs new file mode 100644 index 0000000..6688028 --- /dev/null +++ b/src/templates/components/Footer.ejs @@ -0,0 +1,18 @@ +
+ + by + @radiquum +
+

Find us on:

+ github + website +
+
\ No newline at end of file diff --git a/src/templates/components/Head.ejs b/src/templates/components/Head.ejs index 2948b9b..5bfebdd 100644 --- a/src/templates/components/Head.ejs +++ b/src/templates/components/Head.ejs @@ -14,7 +14,7 @@ <% if (isDev) { %> - + <% }; %> \ No newline at end of file diff --git a/src/templates/components/Header.ejs b/src/templates/components/Header.ejs index 670ea03..cfbe8d2 100644 --- a/src/templates/components/Header.ejs +++ b/src/templates/components/Header.ejs @@ -1,12 +1,15 @@ -
-
- index page +<% include('/functions') %> +
+
+ index page <% if (stickerset) { %> -

STICKERSET

+
+ +

<%- stickerset.title %>

+
<% }; %> -
\ No newline at end of file diff --git a/src/templates/components/Link/AddLink.ejs b/src/templates/components/Link/AddLink.ejs new file mode 100644 index 0000000..abda97e --- /dev/null +++ b/src/templates/components/Link/AddLink.ejs @@ -0,0 +1,4 @@ + + +

<%- text %>

+
\ No newline at end of file diff --git a/src/templates/components/Link/Stickerset.ejs b/src/templates/components/Link/Stickerset.ejs index a9415a0..26ba4d7 100644 --- a/src/templates/components/Link/Stickerset.ejs +++ b/src/templates/components/Link/Stickerset.ejs @@ -1,5 +1,5 @@ <% include('/functions') %> - +
+
+
+ + +
+
+

<%- stickerset.title %>

+ <% if (stickerset.hasOwnProperty("author") && stickerset.author.hasOwnProperty("name") && stickerset.author.name) { %> + <% if (stickerset.author.hasOwnProperty("url") && stickerset.author.url) { %> +
<%- stickerset.author.name %> + <% } else { %> +

<%- stickerset.author.name %>

+ <% }; %> + <% }; %> + <% if (stickerset.hasOwnProperty("rating") && stickerset.rating) { %> +

<%- stickerset.rating %>

+ <% }; %> +
+
\ No newline at end of file diff --git a/src/templates/components/Pack/Links.ejs b/src/templates/components/Pack/Links.ejs new file mode 100644 index 0000000..bdebca9 --- /dev/null +++ b/src/templates/components/Pack/Links.ejs @@ -0,0 +1,5 @@ +<%- include ("/components/Link/AddLink", {name: "telegram", text: "Telegram", image: "telegram.png", link: "https://t.me/addstickers/" + stickerset.id, color: "#2f7ca3"} ) %> +<% if (stickerset.hasOwnProperty("room_id") && stickerset.room_id) { %> + <%- include ("/components/Link/AddLink", {name: "cinny.png", text: "Cinny", image: "cinny.png", link: "https://matrix.to/#/" + stickerset.room_id, color: "#373737"} ) %> + <%- include ("/components/Link/AddLink", {name: "fluffychat.png", text: "FluffyChat", image: "fluffychat.png", link: "https://matrix.to/#/" + stickerset.room_id, color: "#282443"} ) %> +<% }; %> \ No newline at end of file diff --git a/src/templates/components/Pack/Preview.ejs b/src/templates/components/Pack/Preview.ejs new file mode 100644 index 0000000..4793bc1 --- /dev/null +++ b/src/templates/components/Pack/Preview.ejs @@ -0,0 +1,30 @@ +<% include('/functions') %> +
+

<%- stickerset.stickers.length %> stickers

+
+ <% stickerset.stickers.forEach(function(sticker){ %> +
+ + +
+ <% }); %> +
+ +
\ No newline at end of file diff --git a/src/templates/components/packCard.js b/src/templates/components/packCard.js deleted file mode 100644 index f3bba4c..0000000 --- a/src/templates/components/packCard.js +++ /dev/null @@ -1,71 +0,0 @@ -const { CreateImageURL } = require("../../utils"); - -function _packName(pack) { - let string = ""; - string += `

${pack.title}

`; - - if (pack.hasOwnProperty("author") && pack.author) { - let author_string = `

by: ${pack.author.name}

`; - if (pack.author.url) { - author_string = `

by: ${pack.author.name}

`; - } - string += author_string; - } - - if (pack.hasOwnProperty("rating") && pack.rating) { - switch (pack.rating.toLowerCase()) { - case "safe": - string += `

safe

`; - break; - case "questionable": - string += `

questionable

`; - break; - case "explicit": - string += `

explicit

`; - break; - default: - break; - } - } - - return string; -} - -function _packCard(index, pack) { - return ` -
-
-
- - Loading... -
- -
-
- ${_packName(pack)} -
-
-`; -} - -module.exports = _packCard; diff --git a/src/templates/components/packHead.js b/src/templates/components/packHead.js deleted file mode 100644 index 0ceb6fb..0000000 --- a/src/templates/components/packHead.js +++ /dev/null @@ -1,20 +0,0 @@ -const {CreateImageURL, CreatePackDescription} = require("../../utils"); - -function _CreateHead(index, pack) { - return ` - - -${pack.title} - - - - - - - - - - -`} - -module.exports = _CreateHead \ No newline at end of file diff --git a/src/templates/components/packLinks.js b/src/templates/components/packLinks.js deleted file mode 100644 index 7d4c7ba..0000000 --- a/src/templates/components/packLinks.js +++ /dev/null @@ -1,26 +0,0 @@ -function PackLinks(pack) { - return ` - - -

Telegram

-
- - ${(pack.hasOwnProperty("room_id") && pack.room_id) ? ( - ` - - -

FluffyChat

-
- - -

Cinny

-
- ` - ) - : ""} -`} - -module.exports = PackLinks \ No newline at end of file diff --git a/src/templates/components/packPreview.js b/src/templates/components/packPreview.js deleted file mode 100644 index 14072d3..0000000 --- a/src/templates/components/packPreview.js +++ /dev/null @@ -1,48 +0,0 @@ -const { CreateImageURL } = require("../../utils"); - -function _addSticker(index, sticker) { - return ` -
-
- - Loading... -
- -
-`}; - -function _packPreview(index, pack) { - - let stickers = []; - pack.stickers.forEach((sticker) => stickers.push(_addSticker(index, sticker))); - - return ` -
-

Pack Preview (${pack.stickers.length} stickers)

-
- ${stickers.join("\n")} -
-
-`}; - -module.exports = _packPreview; diff --git a/src/templates/pack.js b/src/templates/pack.js deleted file mode 100644 index 8581553..0000000 --- a/src/templates/pack.js +++ /dev/null @@ -1,68 +0,0 @@ -const PackHead = require("./components/packHead"); -const PackCard = require("./components/packCard"); -const PackLinks = require("./components/packLinks"); -const PackPreview = require("./components/packPreview"); -const { InjectWSConnection } = require("../utils") - -function _CreatePackPage(index, pack, isDev) { - return ` - - - - - ${PackHead(index, pack)} - ${isDev ? InjectWSConnection() : ""} - - - - -
-
- -
- ${PackCard(index, pack)} -
- ${PackLinks(pack)} -
- ${PackPreview(index, pack)} -
- - - - - - - - - ` -} - -module.exports = _CreatePackPage \ No newline at end of file diff --git a/src/utils.js b/src/utils.js index 4ef9484..68cc965 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,3 +1,7 @@ +CreateImageURL = function (homeserverUrl, id) { + return `${homeserverUrl}${id.slice(0, 2)}/${id.slice(2, 4)}/${id.slice(4)}`; +}; + function CreatePackDescription(pack) { let description = []; @@ -30,11 +34,15 @@ function CreatePackDescription(pack) { return description.join(" | "); } -function log(level = "INFO" | "ERROR" | "WARN" | "LOG", message, connected = false) { - const date = new Date; - const time = date.toLocaleTimeString() +function log( + level = "INFO" | "ERROR" | "WARN" | "LOG", + message, + connected = false +) { + const date = new Date(); + const time = date.toLocaleTimeString(); if (connected) { - message = `↳${message}` + message = `↳${message}`; } switch (level.toUpperCase()) { case "INFO": @@ -54,5 +62,6 @@ function log(level = "INFO" | "ERROR" | "WARN" | "LOG", message, connected = fal module.exports = { log, - CreatePackDescription + CreatePackDescription, + CreateImageURL }; diff --git a/src/watch.js b/src/watch.js index b7c9a29..2418555 100644 --- a/src/watch.js +++ b/src/watch.js @@ -10,6 +10,7 @@ const { log } = require("./utils"); let triggered = 0; const delay = 1000; let SIGINTCount = 0; +let WSclients = []; const InpPath = path .join(__dirname, "../", config.stickerPacksDir, "./") @@ -20,7 +21,7 @@ log("INFO", `Sticker sets directory: ${InpPath}`); log("INFO", `Output directory: ${OutPath}`); log("INFO", `Working directory: ${ParPath}`); -function onChange(wss) { +function onChange() { if (triggered != 0 && Date.now() - triggered < delay) { log("WARN", `Rebuild was triggered less than a ${delay}ms ago!`, true); return; @@ -38,9 +39,9 @@ function onChange(wss) { return; } log("INFO", stdout); - if (wss) { + if (WSclients.length > 0) { log("INFO", "Reloading web page..."); - wss.send("RELOAD"); + WSclients.forEach((ws) => ws.send("RELOAD")); } }); } @@ -86,18 +87,19 @@ function startServerWithRebuild() { const folder = path.join(__dirname, ".."); const wss = new WebSocket.Server({ port: 3001 }); - let WSclient = null; wss.on("connection", (ws) => { - WSclient = ws; + WSclients.push(ws); + log("INFO", `Client ${WSclients.length} connected`) ws.send("CONNECTED"); }); + process.on("SIGINT", () => { SIGINTCount += 1; - if (WSclient) { + if (WSclients.length > 0) { async function _closeWS() { - await WSclient.close(); + WSclients.forEach(async (ws) => await ws.close()) } _closeWS(); } @@ -118,15 +120,15 @@ function startServerWithRebuild() { watcher .on("add", (path) => { log("INFO", `File ${path} has been added, rebuilding...`); - onChange(WSclient); + onChange(); }) .on("change", (path) => { log("INFO", `File ${path} has been changed, rebuilding...`); - onChange(WSclient); + onChange(); }) .on("unlink", (path) => { log("INFO", `File ${path} has been removed, rebuilding...`); - onChange(WSclient); + onChange(); }); }); } diff --git a/static/OpenPopUp.js b/static/OpenPopUp.js deleted file mode 100644 index 6fbdfb4..0000000 --- a/static/OpenPopUp.js +++ /dev/null @@ -1,13 +0,0 @@ -const ElementInstructionOV = document.getElementById( - "preview_sticker_pack_add_to_element_overlay" -); -const ElementInstruction = document.getElementById( - "preview_sticker_pack_add_to_element" -); - -function toggleElementInstruction() { - ElementInstructionOV.classList.toggle("hidden"); - ElementInstruction.classList.toggle("hidden"); - - ElementInstruction.classList.toggle("flex"); -} diff --git a/static/RenderImages.js b/static/RenderImages.js index 57509a1..b26f0e8 100644 --- a/static/RenderImages.js +++ b/static/RenderImages.js @@ -1,26 +1,26 @@ const images = document.querySelectorAll("[data-image-id]"); images.forEach((image, i) => { + if (i < 4) { + image.setAttribute("loading", "eager"); + } - if (i < 4) { - image.setAttribute("loading", "eager") - } + const spinner = document.querySelector( + `[data-spinner-id="${image.getAttribute("data-image-id")}"]` + ); - const spinner = document.querySelector(`[data-spinner-id="${image.getAttribute("data-image-id")}"]`) + if (image.height > 0 && image.complete) { + image.classList.remove("invisible"); + spinner.classList.add("invisible"); + return; + } else { + image.classList.add("invisible"); + spinner.classList.remove("invisible"); + } - if (image.height > 0 && image.complete) { - image.classList.remove("invisible"); - spinner.classList.add("invisible"); - return - } else { - image.classList.add("invisible"); - spinner.classList.remove("invisible"); - } - - image.addEventListener("load", () => { - console.log("image " + image.getAttribute("data-image-id") + " loaded"); - image.classList.remove("invisible"); - spinner.classList.add("invisible"); - image.removeEventListener("load", this); - }); - -}); \ No newline at end of file + image.addEventListener("load", () => { + console.log("image " + image.getAttribute("data-image-id") + " loaded"); + image.classList.remove("invisible"); + spinner.classList.add("invisible"); + image.removeEventListener("load", this); + }); +}); diff --git a/static/tailwind.css b/static/tailwind.css index 4409599..b54ece5 100644 --- a/static/tailwind.css +++ b/static/tailwind.css @@ -588,18 +588,6 @@ video { } } -.sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - white-space: nowrap; - border-width: 0; -} - .invisible { visibility: hidden; } @@ -620,10 +608,6 @@ video { left: 0px; } -.left-1\/2 { - left: 50%; -} - .right-0 { right: 0px; } @@ -632,10 +616,6 @@ video { top: 0px; } -.top-8 { - top: 2rem; -} - .-z-10 { z-index: -10; } @@ -648,15 +628,15 @@ video { z-index: 10; } -.z-20 { - z-index: 20; -} - .mx-auto { margin-left: auto; margin-right: auto; } +.mb-4 { + margin-bottom: 1rem; +} + .line-clamp-1 { overflow: hidden; display: -webkit-box; @@ -664,6 +644,10 @@ video { -webkit-line-clamp: 1; } +.block { + display: block; +} + .inline { display: inline; } @@ -684,26 +668,23 @@ video { aspect-ratio: 1 / 1; } -.h-16 { - height: 4rem; -} - -.h-24 { - height: 6rem; -} - -.h-48 { - height: 12rem; -} - .h-6 { height: 1.5rem; } +.h-fit { + height: -moz-fit-content; + height: fit-content; +} + .h-full { height: 100%; } +.min-h-16 { + min-height: 4rem; +} + .min-h-screen { min-height: 100vh; } @@ -720,10 +701,6 @@ video { width: 6rem; } -.w-48 { - width: 12rem; -} - .w-8 { width: 2rem; } @@ -732,8 +709,8 @@ video { width: 100%; } -.-translate-x-1\/2 { - --tw-translate-x: -50%; +.translate-y-\[var\(--tw-translate-y\)\] { + --tw-translate-y: var(--tw-translate-y); transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } @@ -751,6 +728,10 @@ video { grid-template-columns: repeat(1, minmax(0, 1fr)); } +.grid-cols-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); +} + .grid-rows-1 { grid-template-rows: repeat(1, minmax(0, 1fr)); } @@ -787,6 +768,10 @@ video { overflow-x: hidden; } +.whitespace-pre { + white-space: pre; +} + .rounded-full { border-radius: 9999px; } @@ -804,39 +789,22 @@ video { border-bottom-left-radius: 0.5rem; } +.border-b { + border-bottom-width: 1px; +} + +.border-slate-400 { + --tw-border-opacity: 1; + border-color: rgb(148 163 184 / var(--tw-border-opacity, 1)); +} + .bg-\[\#1d1f3d\] { --tw-bg-opacity: 1; background-color: rgb(29 31 61 / var(--tw-bg-opacity, 1)); } -.bg-\[\#259d7b\] { - --tw-bg-opacity: 1; - background-color: rgb(37 157 123 / var(--tw-bg-opacity, 1)); -} - -.bg-\[\#282443\] { - --tw-bg-opacity: 1; - background-color: rgb(40 36 67 / var(--tw-bg-opacity, 1)); -} - -.bg-\[\#2f7ca3\] { - --tw-bg-opacity: 1; - background-color: rgb(47 124 163 / var(--tw-bg-opacity, 1)); -} - -.bg-\[\#373737\] { - --tw-bg-opacity: 1; - background-color: rgb(55 55 55 / var(--tw-bg-opacity, 1)); -} - -.bg-black { - --tw-bg-opacity: 1; - background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1)); -} - -.bg-red-600 { - --tw-bg-opacity: 1; - background-color: rgb(220 38 38 / var(--tw-bg-opacity, 1)); +.bg-\[var\(--bg-color\)\] { + background-color: var(--bg-color); } .bg-slate-800 { @@ -844,16 +812,6 @@ video { background-color: rgb(30 41 59 / var(--tw-bg-opacity, 1)); } -.bg-stone-800 { - --tw-bg-opacity: 1; - background-color: rgb(41 37 36 / var(--tw-bg-opacity, 1)); -} - -.bg-stone-900 { - --tw-bg-opacity: 1; - background-color: rgb(28 25 23 / var(--tw-bg-opacity, 1)); -} - .bg-gradient-to-b { background-image: linear-gradient(to bottom, var(--tw-gradient-stops)); } @@ -901,21 +859,11 @@ video { padding-bottom: 1rem; } -.py-8 { - padding-top: 2rem; - padding-bottom: 2rem; -} - .text-2xl { font-size: 1.5rem; line-height: 2rem; } -.text-4xl { - font-size: 2.25rem; - line-height: 2.5rem; -} - .text-lg { font-size: 1.125rem; line-height: 1.75rem; @@ -926,11 +874,20 @@ video { line-height: 1.25rem; } +.text-xl { + font-size: 1.25rem; + line-height: 1.75rem; +} + .text-xs { font-size: 0.75rem; line-height: 1rem; } +.font-bold { + font-weight: 700; +} + .text-gray-200 { --tw-text-opacity: 1; color: rgb(229 231 235 / var(--tw-text-opacity, 1)); @@ -961,25 +918,10 @@ video { color: rgb(234 179 8 / var(--tw-text-opacity, 1)); } -.text-zinc-100 { - --tw-text-opacity: 1; - color: rgb(244 244 245 / var(--tw-text-opacity, 1)); -} - .underline { text-decoration-line: underline; } -.opacity-40 { - opacity: 0.4; -} - -.shadow-lg { - --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); - --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color); - box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); -} - .transition-transform { transition-property: transform; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); @@ -994,10 +936,6 @@ video { grid-row: 1; } -.\[grid-template-columns\:repeat\(auto-fill\2c 96px\)\] { - grid-template-columns: repeat(auto-fill,96px); -} - .tiledBackground { background-image: url('images/background-white.png'); background-repeat: repeat; @@ -1019,8 +957,8 @@ video { } @media (min-width: 640px) { - .sm\:inline { - display: inline; + .sm\:flex { + display: flex; } .sm\:h-10 { @@ -1035,10 +973,19 @@ video { width: 8rem; } + .sm\:grid-cols-4 { + grid-template-columns: repeat(4, minmax(0, 1fr)); + } + .sm\:gap-4 { gap: 1rem; } + .sm\:px-8 { + padding-left: 2rem; + padding-right: 2rem; + } + .sm\:text-2xl { font-size: 1.5rem; line-height: 2rem; @@ -1061,37 +1008,52 @@ video { } @media (min-width: 768px) { - .md\:top-32 { - top: 8rem; + .md\:block { + display: block; } - .md\:w-\[768px\] { - width: 768px; - } - - .md\:max-w-\[768px\] { - max-width: 768px; - } - - .md\:flex-row { - flex-direction: row; - } - - .md\:whitespace-pre { - white-space: pre; + .md\:text-2xl { + font-size: 1.5rem; + line-height: 2rem; } } @media (min-width: 1024px) { + .lg\:block { + display: block; + } + + .lg\:hidden { + display: none; + } + + .lg\:w-\[49\%\] { + width: 49%; + } + .lg\:grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } + + .lg\:grid-cols-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } +} + +@media (min-width: 1280px) { + .xl\:grid-cols-4 { + grid-template-columns: repeat(4, minmax(0, 1fr)); + } } @media (min-width: 1536px) { .\32xl\:grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); } + + .\32xl\:grid-cols-5 { + grid-template-columns: repeat(5, minmax(0, 1fr)); + } } @media (prefers-color-scheme: dark) {