commit 8242fdbbb30c1d36a729a763e00aabd22c267f33 Author: bakonpancakz Date: Sun May 24 19:52:45 2026 -0700 Initial Release diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9e5e365 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.development \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..becc7c8 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,6 @@ +{ + "recommendations": [ + "esbenp.prettier-vscode", + "golang.go" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..22144ff --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,26 @@ +{ + "editor.tabSize": 4, + "editor.insertSpaces": true, + "editor.formatOnSave": true, + "editor.rulers": [ + 120 + ], + "files.trimTrailingWhitespace": true, + "files.insertFinalNewline": true, + "files.associations": {}, + "[css]": { + "editor.defaultFormatter": "vscode.css-language-features" + }, + "[javascript]": { + "editor.defaultFormatter": "vscode.typescript-language-features" + }, + "[typescript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[javascriptreact]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[typescriptreact]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + } +} diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..df11ce5 --- /dev/null +++ b/README.txt @@ -0,0 +1,25 @@ +------------------------------------------------------------------------------- +ABOUT +------------------------------------------------------------------------------- + +Creating websites is a fun way to refine my skills and practice UI/UX. + +Each version represents my psyche at the current time alongside which tooling +and aesthetics interested me. + +I tend to change homepage regularly, and I don't attempt to make each version +better than the last these things just tend to happen naturally. + +------------------------------------------------------------------------------- +HISTORY +------------------------------------------------------------------------------- + +* pancakz-v1-caution: + Caution Tape Design, inspired by txt.osk.sh + +* pancakz-v2-crossroads: + Every aesthetic, inspired by a lost twitter post + +* pancakz-v3-beam: + Natural Evolution of V2. Uses a static site instead of a + webserver. Inspired by Dance Delightful. diff --git a/pancakz-v1-caution/.gitignore b/pancakz-v1-caution/.gitignore new file mode 100644 index 0000000..d70ad07 --- /dev/null +++ b/pancakz-v1-caution/.gitignore @@ -0,0 +1,2 @@ +.env +data \ No newline at end of file diff --git a/pancakz-v1-caution/Dockerfile b/pancakz-v1-caution/Dockerfile new file mode 100644 index 0000000..9918320 --- /dev/null +++ b/pancakz-v1-caution/Dockerfile @@ -0,0 +1,15 @@ +# Build +FROM golang:1.25.2-alpine3.22 AS build +WORKDIR /app +COPY . . +RUN go build -o homepage.elf main.go + +# Runtime +FROM alpine:latest AS runtime +WORKDIR /app +COPY --from=build /app/homepage.elf . + +ENV HTTP_ADDRESS="0.0.0.0:8080" +EXPOSE 8080 + +CMD ["./homepage.elf"] \ No newline at end of file diff --git a/pancakz-v1-caution/env/Configuration.go b/pancakz-v1-caution/env/Configuration.go new file mode 100644 index 0000000..a0f5744 --- /dev/null +++ b/pancakz-v1-caution/env/Configuration.go @@ -0,0 +1,68 @@ +package env + +import ( + "crypto/tls" + "crypto/x509" + "fmt" + "log" + "os" + "time" +) + +const ( + FILE_MODE = os.FileMode(0770) +) + +var ( + HTTP_TLS *tls.Config // http: TLS Configuration + HTTP_ADDRESS = envString("HTTP_ADDRESS", "localhost:8080") // http: Address to Listen for Requests on + TLS_ENABLED = envString("TLS_ENABLED", "false") == "true" // http: Enable TLS? + TLS_CERT = envString("TLS_CERT", "tls_crt.pem") // http: Path to TLS Certificate + TLS_KEY = envString("TLS_KEY", "tls_key.pem") // http: Path to TLS Key + TLS_CA = envString("TLS_CA", "tls_ca.pem") // http: Path to TLS CA Bundle + VERSION = fmt.Sprintf("%X", time.Now().Unix()) +) + +func init() { + log.Println("[env] Using Version Hash:", VERSION) + + // Load and Parse TLS Configuration from Disk + if TLS_ENABLED { + cert, err := tls.LoadX509KeyPair(TLS_CERT, TLS_KEY) + if err != nil { + log.Fatalln("[env/tls] Cannot Load Keypair", err) + } + caBytes, err := os.ReadFile(TLS_CA) + if err != nil { + log.Fatalln("[env/tls] Cannot Read CA File", err) + } + caPool := x509.NewCertPool() + if !caPool.AppendCertsFromPEM(caBytes) { + log.Fatalln("[env/tls] Cannot Append Certificates") + } + HTTP_TLS = &tls.Config{ + Certificates: []tls.Certificate{cert}, + ClientCAs: caPool, + MinVersion: tls.VersionTLS13, + MaxVersion: tls.VersionTLS13, + CipherSuites: []uint16{ + tls.TLS_AES_128_GCM_SHA256, + tls.TLS_AES_256_GCM_SHA384, + tls.TLS_CHACHA20_POLY1305_SHA256, + }, + } + } +} + +// Reads String from Environment +func envString(key, defaultValue string) string { + systemValue := os.Getenv(key) + if systemValue == "" { + if defaultValue == "\x00" { + fmt.Printf("[env] Environment Variable '%s' is undefined\n", key) + os.Exit(2) + } + return defaultValue + } + return systemValue +} diff --git a/pancakz-v1-caution/env/Database.go b/pancakz-v1-caution/env/Database.go new file mode 100644 index 0000000..29dcd45 --- /dev/null +++ b/pancakz-v1-caution/env/Database.go @@ -0,0 +1,48 @@ +package env + +import ( + _ "embed" + "encoding/json" + "log" + "time" +) + +type databaseRoot struct { + Site databaseSite `json:"site"` + Articles []databaseArticle `json:"articles"` +} + +type databaseSite struct { + Host string `json:"host"` + Name string `json:"name"` + Description string `json:"description"` + Category string `json:"category"` + Locale string `json:"locale"` + Owner string `json:"owner"` + Color string `json:"color"` +} + +type databaseArticle struct { + BaseTemplate string `json:"base_template"` + BaseResources string `json:"base_resources"` + BaseBanner string `json:"base_banner"` + Color string `json:"color"` + Slug string `json:"slug"` + Date time.Time `json:"date"` + Title string `json:"title"` + Description string `json:"description"` + Author string `json:"author"` + Tags []string `json:"tags"` +} + +var ( + //go:embed database.json + embedDatabase []byte + Database databaseRoot +) + +func init() { + if err := json.Unmarshal(embedDatabase, &Database); err != nil { + log.Fatalln("[env/db] Parse Database Error:", err) + } +} diff --git a/pancakz-v1-caution/env/database.json b/pancakz-v1-caution/env/database.json new file mode 100644 index 0000000..5cb30dc --- /dev/null +++ b/pancakz-v1-caution/env/database.json @@ -0,0 +1,28 @@ +{ + "site": { + "host": "https://panca.kz", + "name": "pancakz", + "description": "Tech, Chunibyo \u0026 Other Delusions", + "category": "Personal Blogs", + "locale": "en-US", + "owner": "bakonpancakz", + "color": "77, 88, 255" + }, + "articles": [ + { + "base_template": "001-personal-email-server.html", + "base_resources": "setting-up-an-email-api", + "base_banner": "banner.gif", + "color": "94, 167, 1", + "slug": "setting-up-an-email-api", + "date": "2024-11-06T19:26:40Z", + "title": "Setting Up an Email API", + "description": "Freaking emails, how do they work?", + "author": "bakonpancakz", + "tags": [ + "PERSONAL", + "GO" + ] + } + ] +} \ No newline at end of file diff --git a/pancakz-v1-caution/go.mod b/pancakz-v1-caution/go.mod new file mode 100644 index 0000000..f7427fc --- /dev/null +++ b/pancakz-v1-caution/go.mod @@ -0,0 +1,5 @@ +module bakonpancakz/homepage + +go 1.25.2 + +require github.com/joho/godotenv v1.5.1 diff --git a/pancakz-v1-caution/go.sum b/pancakz-v1-caution/go.sum new file mode 100644 index 0000000..d61b19e --- /dev/null +++ b/pancakz-v1-caution/go.sum @@ -0,0 +1,2 @@ +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= diff --git a/pancakz-v1-caution/include/Embed.go b/pancakz-v1-caution/include/Embed.go new file mode 100644 index 0000000..71ca4d1 --- /dev/null +++ b/pancakz-v1-caution/include/Embed.go @@ -0,0 +1,59 @@ +package include + +import ( + "embed" + "io" + "io/fs" + "log" + "os" + "path" + "strings" +) + +var ( + //go:embed public/* + embedPublic embed.FS + //go:embed templates/* + embedTemplates embed.FS + + Embedded = true + Templates fs.FS + Public fs.FS +) + +func init() { + if strings.Contains(os.Args[0], "go-build") { + Embedded = false + } + if Embedded { + Templates = embedTemplates + Public = embedPublic + } else { + log.Println("[include] In Debug Mode, using local filesystem!") + Templates = os.DirFS("include/templates") + Public = os.DirFS("include/public") + } +} + +func PreparePath(fsys fs.FS, filepath string) string { + filepath = path.Clean(filepath) + if Embedded { + // If using embed, prepend the folder name automatically if missing + switch { + case fsys == Public && !strings.HasPrefix(filepath, "public/"): + filepath = path.Join("public", filepath) + case fsys == Templates && !strings.HasPrefix(filepath, "templates/"): + filepath = path.Join("templates", filepath) + } + } + return filepath +} + +func ReadFile(fsys fs.FS, filepath string) ([]byte, error) { + f, err := fsys.Open(PreparePath(fsys, filepath)) + if err != nil { + return nil, err + } + defer f.Close() + return io.ReadAll(f) +} diff --git a/pancakz-v1-caution/include/public/anchors.gif b/pancakz-v1-caution/include/public/anchors.gif new file mode 100644 index 0000000..014bf06 Binary files /dev/null and b/pancakz-v1-caution/include/public/anchors.gif differ diff --git a/pancakz-v1-caution/include/public/articles/setting-up-an-email-api/banner.gif b/pancakz-v1-caution/include/public/articles/setting-up-an-email-api/banner.gif new file mode 100644 index 0000000..56c6622 Binary files /dev/null and b/pancakz-v1-caution/include/public/articles/setting-up-an-email-api/banner.gif differ diff --git a/pancakz-v1-caution/include/public/banner_blog.gif b/pancakz-v1-caution/include/public/banner_blog.gif new file mode 100644 index 0000000..4387dd9 Binary files /dev/null and b/pancakz-v1-caution/include/public/banner_blog.gif differ diff --git a/pancakz-v1-caution/include/public/banner_home.gif b/pancakz-v1-caution/include/public/banner_home.gif new file mode 100644 index 0000000..ec25d02 Binary files /dev/null and b/pancakz-v1-caution/include/public/banner_home.gif differ diff --git a/pancakz-v1-caution/include/public/divider.svg b/pancakz-v1-caution/include/public/divider.svg new file mode 100644 index 0000000..36a59c7 --- /dev/null +++ b/pancakz-v1-caution/include/public/divider.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/pancakz-v1-caution/include/public/favicon.ico b/pancakz-v1-caution/include/public/favicon.ico new file mode 100644 index 0000000..c1b2d33 Binary files /dev/null and b/pancakz-v1-caution/include/public/favicon.ico differ diff --git a/pancakz-v1-caution/include/public/fonts/pxiByp8kv8JHgFVrLCz7Z11lFc-K.woff2 b/pancakz-v1-caution/include/public/fonts/pxiByp8kv8JHgFVrLCz7Z11lFc-K.woff2 new file mode 100644 index 0000000..77bd0a9 Binary files /dev/null and b/pancakz-v1-caution/include/public/fonts/pxiByp8kv8JHgFVrLCz7Z11lFc-K.woff2 differ diff --git a/pancakz-v1-caution/include/public/fonts/pxiByp8kv8JHgFVrLCz7Z1JlFc-K.woff2 b/pancakz-v1-caution/include/public/fonts/pxiByp8kv8JHgFVrLCz7Z1JlFc-K.woff2 new file mode 100644 index 0000000..bc847e9 Binary files /dev/null and b/pancakz-v1-caution/include/public/fonts/pxiByp8kv8JHgFVrLCz7Z1JlFc-K.woff2 differ diff --git a/pancakz-v1-caution/include/public/fonts/pxiByp8kv8JHgFVrLCz7Z1xlFQ.woff2 b/pancakz-v1-caution/include/public/fonts/pxiByp8kv8JHgFVrLCz7Z1xlFQ.woff2 new file mode 100644 index 0000000..bf022fc Binary files /dev/null and b/pancakz-v1-caution/include/public/fonts/pxiByp8kv8JHgFVrLCz7Z1xlFQ.woff2 differ diff --git a/pancakz-v1-caution/include/public/fonts/pxiByp8kv8JHgFVrLEj6Z11lFc-K.woff2 b/pancakz-v1-caution/include/public/fonts/pxiByp8kv8JHgFVrLEj6Z11lFc-K.woff2 new file mode 100644 index 0000000..b146403 Binary files /dev/null and b/pancakz-v1-caution/include/public/fonts/pxiByp8kv8JHgFVrLEj6Z11lFc-K.woff2 differ diff --git a/pancakz-v1-caution/include/public/fonts/pxiByp8kv8JHgFVrLEj6Z1JlFc-K.woff2 b/pancakz-v1-caution/include/public/fonts/pxiByp8kv8JHgFVrLEj6Z1JlFc-K.woff2 new file mode 100644 index 0000000..8ec78f5 Binary files /dev/null and b/pancakz-v1-caution/include/public/fonts/pxiByp8kv8JHgFVrLEj6Z1JlFc-K.woff2 differ diff --git a/pancakz-v1-caution/include/public/fonts/pxiByp8kv8JHgFVrLEj6Z1xlFQ.woff2 b/pancakz-v1-caution/include/public/fonts/pxiByp8kv8JHgFVrLEj6Z1xlFQ.woff2 new file mode 100644 index 0000000..921e962 Binary files /dev/null and b/pancakz-v1-caution/include/public/fonts/pxiByp8kv8JHgFVrLEj6Z1xlFQ.woff2 differ diff --git a/pancakz-v1-caution/include/public/fonts/pxiByp8kv8JHgFVrLGT9Z11lFc-K.woff2 b/pancakz-v1-caution/include/public/fonts/pxiByp8kv8JHgFVrLGT9Z11lFc-K.woff2 new file mode 100644 index 0000000..58bfa97 Binary files /dev/null and b/pancakz-v1-caution/include/public/fonts/pxiByp8kv8JHgFVrLGT9Z11lFc-K.woff2 differ diff --git a/pancakz-v1-caution/include/public/fonts/pxiByp8kv8JHgFVrLGT9Z1JlFc-K.woff2 b/pancakz-v1-caution/include/public/fonts/pxiByp8kv8JHgFVrLGT9Z1JlFc-K.woff2 new file mode 100644 index 0000000..d59af06 Binary files /dev/null and b/pancakz-v1-caution/include/public/fonts/pxiByp8kv8JHgFVrLGT9Z1JlFc-K.woff2 differ diff --git a/pancakz-v1-caution/include/public/fonts/pxiByp8kv8JHgFVrLGT9Z1xlFQ.woff2 b/pancakz-v1-caution/include/public/fonts/pxiByp8kv8JHgFVrLGT9Z1xlFQ.woff2 new file mode 100644 index 0000000..c660336 Binary files /dev/null and b/pancakz-v1-caution/include/public/fonts/pxiByp8kv8JHgFVrLGT9Z1xlFQ.woff2 differ diff --git a/pancakz-v1-caution/include/public/fonts/pxiEyp8kv8JHgFVrJJbecmNE.woff2 b/pancakz-v1-caution/include/public/fonts/pxiEyp8kv8JHgFVrJJbecmNE.woff2 new file mode 100644 index 0000000..1ad5724 Binary files /dev/null and b/pancakz-v1-caution/include/public/fonts/pxiEyp8kv8JHgFVrJJbecmNE.woff2 differ diff --git a/pancakz-v1-caution/include/public/fonts/pxiEyp8kv8JHgFVrJJfecg.woff2 b/pancakz-v1-caution/include/public/fonts/pxiEyp8kv8JHgFVrJJfecg.woff2 new file mode 100644 index 0000000..b69e009 Binary files /dev/null and b/pancakz-v1-caution/include/public/fonts/pxiEyp8kv8JHgFVrJJfecg.woff2 differ diff --git a/pancakz-v1-caution/include/public/fonts/pxiEyp8kv8JHgFVrJJnecmNE.woff2 b/pancakz-v1-caution/include/public/fonts/pxiEyp8kv8JHgFVrJJnecmNE.woff2 new file mode 100644 index 0000000..63f4711 Binary files /dev/null and b/pancakz-v1-caution/include/public/fonts/pxiEyp8kv8JHgFVrJJnecmNE.woff2 differ diff --git a/pancakz-v1-caution/include/public/robots.txt b/pancakz-v1-caution/include/public/robots.txt new file mode 100644 index 0000000..7ba8e1b --- /dev/null +++ b/pancakz-v1-caution/include/public/robots.txt @@ -0,0 +1,5 @@ +# \_/ +# ()o_o) <( beep boop ) + +User-agent: * +Disallow: \ No newline at end of file diff --git a/pancakz-v1-caution/include/public/scripts/blog_article.js b/pancakz-v1-caution/include/public/scripts/blog_article.js new file mode 100644 index 0000000..559ee21 --- /dev/null +++ b/pancakz-v1-caution/include/public/scripts/blog_article.js @@ -0,0 +1,115 @@ +// @ts-check + +(() => { // Table of Content Highlights + + /** @type {HTMLDivElement | null} */ + const parentChapter = document.querySelector("div.article-chapters") + /** @type {HTMLDivElement | null} */ + const parentArticle = document.querySelector("div.article-content") + + if (!parentChapter || !parentArticle) return + + /** @type {Array<{ o: number; e: Array }>} */ + let scrollSections = [] + let scrollHeader = null + let scrollOffset = 0 + + // Generate Table of Contents + for (const child of parentArticle.children) { + const offset = (child.getBoundingClientRect().top + window.scrollY + scrollOffset) | 0 + const normal = child.textContent.toString().toLocaleLowerCase().replaceAll(" ", "-") + + if (child.classList.contains("element-header")) { + const anchor = document.createElement("a") + anchor.classList.add("chapter") + anchor.textContent = child.textContent + anchor.href = "#" + normal + child.id = normal + parentChapter.appendChild(anchor) + + scrollSections.push({ o: offset, e: [anchor] }) + scrollHeader = anchor + scrollOffset += 36 // bandaid fix for desync + } + + if (child.classList.contains("element-subheader")) { + const anchor = document.createElement("a") + anchor.classList.add("section") + anchor.textContent = child.textContent + anchor.href = "#" + normal + child.id = normal + parentChapter.appendChild(anchor) + + scrollSections.push({ o: offset, e: [scrollHeader, anchor] }) + } + } + + // Update Highlight when Page Scrolls + function pageScroll() { + const winoffset = window.innerHeight / 5 + const position = window.scrollY + winoffset + let closest = null + let closestDist = Infinity + + // Find Closest Header + for (const section of scrollSections) { + const dist = Math.abs(position - section.o) + if (dist < closestDist) { + closestDist = dist + closest = section + } + for (const elem of section.e) { + // Reset Styling + elem && elem.removeAttribute("selected") + } + } + + // Apply Header Styling + if (closest) { + for (const elem of closest.e) { + elem && elem.setAttribute("selected", "") + } + } + } + window.addEventListener("scroll", pageScroll) + pageScroll() + +})(); + +(() => { // Share Button + + /** @type {HTMLButtonElement | null} */ + const shareButton = document.querySelector("a#button-share") + /** @type {HTMLDialogElement | null} */ + const shareModal = document.querySelector("dialog.layout-dialog") + + // UX: Close Modal if Background is clicked or pressed + shareModal && shareModal.addEventListener("click", ev => { + if (ev.target === shareModal) { + shareModal.close() + } + }) + + // UX: Open Native Modal on Mobile, Custom Modal on Desktop + shareButton && shareButton.addEventListener("click", ev => { + ev.preventDefault() + + // Use Native Modal + const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent) + if (isMobile) { + const metaTitle = document.querySelector(`meta[property="og:title"]`)?.getAttribute("content") + const metaURL = document.querySelector(`meta[property="og:url"]`)?.getAttribute("content") + if (typeof (metaURL) !== "string" || typeof (metaTitle) !== "string") { + alert("Missing Required Metadata") + return + } + navigator.share({ title: metaTitle, url: metaURL }) + return + } + + // Use Desktop Modal + if (shareModal) { + shareModal.showModal() + } + }) +})(); \ No newline at end of file diff --git a/pancakz-v1-caution/include/public/styles/blog_article.css b/pancakz-v1-caution/include/public/styles/blog_article.css new file mode 100644 index 0000000..8721568 --- /dev/null +++ b/pancakz-v1-caution/include/public/styles/blog_article.css @@ -0,0 +1,240 @@ +div.layout-content { + margin-bottom: 50vw; +} + +/* Modal */ +dialog.layout-dialog { + position: fixed; + z-index: 999; + width: 100%; + height: 100%; + background-color: rgba(var(--rgb-background), .5); +} + +div.layout-modal { + width: 480px; + height: fit-content; + position: relative; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); + padding: 16px; + box-sizing: border-box; +} + +div.modal-header { + display: flex; + justify-content: space-between; + align-items: start; + margin-bottom: 16px; +} + +div.modal-header>p { + color: rgba(var(--rgb-accent), 1); + font-size: x-large; + font-weight: 600; +} + +div.modal-header>form>button { + background: transparent; + color: rgba(var(--rgb-text), 1); + font-size: x-large; + border: none; +} + +div.modal-header>form>button:hover, +div.modal-header>form>button:focus-visible { + color: rgba(var(--rgb-accent), 1); + cursor: pointer; +} + +div.modal-content { + display: flex; + gap: 8px; + justify-content: center; +} + +div.modal-content>input { + height: 40px; + padding: 0 8px; + box-sizing: border-box; + border: 1px solid rgba(var(--rgb-accent), 1); + background: transparent; + flex-basis: 100%; + font-family: monospace; + color: rgba(var(--rgb-text), 1); +} + +div.modal-content>a { + fill: rgba(var(--rgb-text), 1); + border: 1px solid rgba(var(--rgb-accent), 1); + box-sizing: border-box; + padding: 8px 0; + flex-basis: 100%; + max-width: 40px; + height: 40px; + line-height: 24px; +} + +div.modal-content>a:hover, +div.modal-content>a:focus-visible { + background: rgba(var(--rgb-accent), 1); +} + +div.modal-content>a>svg { + fill: rgba(var(--rgb-accent), 1); + display: block; + margin: auto; + height: 24px; +} + +div.modal-content>a:hover>svg, +div.modal-content>a:focus-visible>svg { + fill: rgba(var(--rgb-text), 1); +} + +/* Navigation */ +div.article-actions { + display: flex; + justify-content: center; + gap: 8px; + margin-bottom: 8px; +} + +div.article-actions>a { + border: 2px solid rgba(var(--rgb-accent), 1); + box-sizing: border-box; + flex-basis: 100%; + padding: 8px 0; +} + +div.article-actions>a>svg { + fill: rgba(var(--rgb-accent), 1); + display: block; + margin: auto; + height: 16px; +} + +div.article-actions>a:hover, +div.article-actions>a:focus-visible { + background: rgba(var(--rgb-accent), 1); +} + +div.article-actions>a:hover>svg, +div.article-actions>a:focus-visible>svg { + fill: rgba(var(--rgb-text), 1); +} + +div.article-chapters { + display: grid; +} + +div.article-chapters>a.chapter, +div.article-chapters>a.section { + transition: var(--transition-time) ease-in-out all; + text-decoration: none; +} + +div.article-chapters>a.chapter { + margin-left: 16px; + transform: skew(0deg); +} + +div.article-chapters>a.chapter:hover, +div.article-chapters>a.chapter:focus-visible { + text-decoration: underline; +} + +div.article-chapters>a.chapter[selected] { + position: relative; + letter-spacing: 1px; +} + +div.article-chapters>a.chapter[selected]::before { + content: '>'; + color: rgba(var(--rgb-accent), 1); + font-size: 24px; + font-weight: bold; + position: absolute; + left: -16px; +} + +div.article-chapters>a.section { + margin-left: 32px; + font-size: small; +} + +div.article-chapters>a.section:hover, +div.article-chapters>a.section:focus-visible { + text-decoration: underline; +} + +div.article-chapters>a.section[selected] { + color: rgba(var(--rgb-accent), 1); + letter-spacing: 1px; +} + +/* Article */ +div.article-header { + width: 100%; + height: fit-content; + display: grid; + justify-items: center; +} + +img.header-banner { + width: 100%; + object-fit: cover; + aspect-ratio: 3/1; + border-bottom: 4px solid rgba(var(--rgb-accent), 1); +} + +p.header-title { + word-wrap: break-word; + overflow: hidden; + margin: 16px 0 24px 0; +} + +div.header-chevrons { + display: flex; + justify-content: space-between; + width: 100%; +} + +div.article-content { + padding: 16px; + display: grid; + gap: 8px; +} + +/* Elements */ +div.element-divider { + position: relative; + background-color: rgba(var(--rgb-accent), 1); + height: 2px; + margin: 16px 0; +} + +div.element-divider::before { + content: ''; + transform: translate(-50%, -50%); + position: absolute; + height: 16px; + width: 24px; + left: 50%; + top: 50%; + background: url('/public/divider.svg') rgba(var(--rgb-background), 1) no-repeat center; + padding: 0 4px; +} + +p.element-header { + font-size: x-large; + font-weight: 500; + color: rgb(var(--rgb-accent)); +} + +p.element-subheader { + text-decoration: underline; + font-weight: 500; + color: rgb(var(--rgb-accent)); +} \ No newline at end of file diff --git a/pancakz-v1-caution/include/public/styles/blog_browser.css b/pancakz-v1-caution/include/public/styles/blog_browser.css new file mode 100644 index 0000000..64ff03c --- /dev/null +++ b/pancakz-v1-caution/include/public/styles/blog_browser.css @@ -0,0 +1,82 @@ +/* Section: Introduction */ +div.browser-introduction { + display: grid; + padding: 16px; + box-sizing: border-box; + gap: 8px; +} + +p.intro-header { + font-size: large; + text-align: center; +} + +img.intro-banner { + margin: auto; + image-rendering: pixelated; +} + +p.intro-disclaimer { + font-size: small; + text-align: center; + color: rgba(var(--rgb-text), 0.8); +} + +div.intro-dots { + display: flex; + justify-content: center; + font-size: small; +} + +/* Section: Items */ +/* div.browser-content {} */ + +a.browser-item { + display: grid; + text-decoration: none; +} + +a.browser-item:not(:hover) .effect-rhombus-animated { + animation: none; +} + +div.item-background, +div.item-foreground, +a.item-redirect { + grid-row: 1; + grid-column: 1; +} + +div.item-background { + width: 100%; + height: 48px; + background-image: var(--background); + background-size: cover; + background-position: center; + filter: grayscale(1) brightness(0.5); +} + +div.item-foreground { + display: flex; + align-items: center; + justify-content: space-between; + padding-left: 8px; +} + +p.item-description { + font-size: small; + font-style: italic; +} + +/* Section: Footer */ +div.browser-footer { + padding: 16px; + box-sizing: border-box; +} + +div.browser-footer>p { + width: 100%; + text-align: center; + font-family: monospace; + color: rgba(var(--rgb-text), 0.8); +} \ No newline at end of file diff --git a/pancakz-v1-caution/include/public/styles/default.css b/pancakz-v1-caution/include/public/styles/default.css new file mode 100644 index 0000000..50b40d1 --- /dev/null +++ b/pancakz-v1-caution/include/public/styles/default.css @@ -0,0 +1,270 @@ +:root { + --transition-time: 200ms; + --rgb-background: 0, 0, 0; + --rgb-text: 240, 240, 240; + --rgb-accent: 70, 70, 70; +} + +body { + background-color: rgba(var(--rgb-background), 1); + margin: 0; + padding: 0; +} + +::-webkit-scrollbar { + display: none; +} + +a, +p, +span { + display: inline-block; + font-family: "Poppins", sans-serif; + line-height: 1.5em; + font-weight: 400; + color: rgba(var(--rgb-text), 1); + padding: 0; + margin: 0; +} + +/* Global Effects */ +.effect-caution { + position: relative; + border: 4px solid rgba(var(--rgb-accent), 1); + background-color: rgba(var(--rgb-background), 1); + margin-bottom: 12px; + margin-right: 12px; +} + +.effect-caution::before { + content: ''; + position: absolute; + left: 0; + top: 0; + right: -16px; + bottom: -16px; + box-sizing: border-box; + filter: brightness(0.5); + background: repeating-linear-gradient(45deg, rgba(var(--rgb-accent), 1) 0, rgba(var(--rgb-accent), 1) 8px, rgba(var(--rgb-background), 1) 8px, rgba(var(--rgb-background), 1) 16px); + clip-path: polygon(calc(100% - 11px) 0, 100% 0, 100% 100%, 0 100%, 0 calc(100% - 11px), calc(100% - 11px) calc(100% - 11px)); +} + +.effect-docked { + font-size: 2em; + font-weight: 700; + text-align: center; + position: relative; + padding: 0 16px; + z-index: 1; +} + +.effect-docked::before { + position: absolute; + content: ''; + height: 100%; + width: 100%; + top: 0; + left: 0; + box-sizing: border-box; + background: rgba(var(--rgb-accent), 0.7); + clip-path: polygon(12px 60%, calc(100% - 12px) 60%, 100% 100%, 0 100%); + z-index: -1; +} + +.effect-rhombus-animated, +.effect-rhombus-left, +.effect-rhombus-right { + position: relative; + font-weight: 500; + padding: 0 16px; + z-index: 1; +} + +.effect-rhombus-animated::before, +.effect-rhombus-left::before, +.effect-rhombus-right::before { + position: absolute; + content: ''; + height: 100%; + width: 100%; + top: 0; + left: 0; + box-sizing: border-box; + background: rgba(var(--rgb-accent), .8); + z-index: -1; +} + +.effect-rhombus-left { + clip-path: polygon(0 0, calc(100% - 8px) 0, 100% 100%, 8px 100%); +} + +.effect-rhombus-right { + clip-path: polygon(8px 0, 100% 0, calc(100% - 8px) 100%, 0 100%); +} + +.effect-rhombus-animated { + animation: kf-rhombus 1s ease-in-out infinite alternate; +} + +@keyframes kf-rhombus { + 0% { + clip-path: polygon(0 0, calc(100% - 8px) 0, 100% 100%, 8px 100%); + } + + 100% { + clip-path: polygon(8px 0, 100% 0, calc(100% - 8px) 100%, 0 100%); + } +} + +div.effect-chevron-container { + align-items: end; +} + +.effect-chevron-point-left, +.effect-chevron-point-right { + display: inline-block; + background-color: rgba(var(--rgb-accent), 1); + text-decoration: none; + font-weight: 500; + height: 24px; + width: fit-content; + padding: 0 16px; +} + +.effect-chevron-point-right { + margin-right: -4px; + clip-path: polygon(0 0, calc(100% - 8px) 0, 100% 50%, calc(100% - 8px) 100%, 0 100%, 8px 50%); +} + +div.effect-chevron-container>.effect-chevron-point-right:first-child { + padding-left: 8px; + clip-path: polygon(0 0, calc(100% - 8px) 0, 100% 50%, calc(100% - 8px) 100%, 0 100%); +} + +.effect-chevron-point-left { + margin-left: -4px; + clip-path: polygon(8px 0, 100% 0, calc(100% - 8px) 50%, 100% 100%, 8px 100%, 0 50%); +} + +div.effect-chevron-container>.effect-chevron-point-left:last-child { + padding-right: 8px; + clip-path: polygon(8px 0, 100% 0, 100% 100%, 8px 100%, 0 50%); +} + +span.effect-dot { + height: 16px; + width: 16px; + position: relative; + align-self: center; + border-radius: 100%; + background-color: rgba(var(--color), 0.8); + margin: 0 8px; +} + +span.effect-dot::before { + content: ''; + height: 10px; + width: 10px; + border-radius: 100%; + position: absolute; + background-color: rgba(var(--color), 1); + transform: translate(-50%, -50%); + left: 50%; + top: 50%; +} + +/* Page Layout */ +div.layout-wrapper { + display: flex; + gap: 16px; + min-width: 1024px; + max-width: 1024px; + width: 1024px; + margin: 16px auto; +} + +div.layout-navigation { + min-width: 286px; + max-width: 286px; + width: 100%; + height: fit-content; + position: sticky; + top: 16px; +} + +div.layout-content { + width: 100%; + height: fit-content; +} + +/* Layout: Navigation */ +div.navigation-header { + padding: 16px; +} + +a.navigation-title { + width: 100%; + box-sizing: border-box; +} + +p.navigation-description { + width: 100%; + padding: 8px 0; + text-align: center; + box-sizing: border-box; + font-size: small; +} + +/* div.navigation-links {} */ + +a.navigation-item { + width: 100%; + padding: 8px 16px; + box-sizing: border-box; + border-bottom: 4px solid rgba(var(--rgb-accent), 1); + text-decoration: none; + font-size: 20px; + font-weight: 500; + background-size: 100% 300%; + background-repeat: no-repeat; + background-image: var(--background); +} + +a.navigation-item:first-child { + border-top: 4px solid rgba(var(--rgb-accent), 1); +} + +div.navigation-content { + padding: 16px; + padding-bottom: 0; +} + +div.navigation-footer { + display: flex; + padding: 16px; + justify-content: center; + align-items: center; + gap: 4px; +} + +a.footer-item { + color: rgba(var(--rgb-accent), 1); + text-decoration: none; +} + +a.footer-item:hover, +a.footer-item:focus-visible { + text-decoration: underline; +} + +div.footer-views { + width: 100%; + display: flex; + justify-content: center; + gap: 4px; +} + +div.footer-views img { + height: 24px; + image-rendering: pixelated; +} \ No newline at end of file diff --git a/pancakz-v1-caution/include/public/styles/font_poppins.css b/pancakz-v1-caution/include/public/styles/font_poppins.css new file mode 100644 index 0000000..24b20fc --- /dev/null +++ b/pancakz-v1-caution/include/public/styles/font_poppins.css @@ -0,0 +1,122 @@ +/* Local Version of following stylesheet to save on bandwidth while developing locally :3 */ +/* https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap */ + +/* devanagari */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(/public/fonts/pxiEyp8kv8JHgFVrJJbecmNE.woff2) format('woff2'); + unicode-range: U+0900-097F, U+1CD0-1CF9, U+200C-200D, U+20A8, U+20B9, U+20F0, U+25CC, U+A830-A839, U+A8E0-A8FF, U+11B00-11B09; +} + +/* latin-ext */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(/public/fonts/pxiEyp8kv8JHgFVrJJnecmNE.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} + +/* latin */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(/public/fonts/pxiEyp8kv8JHgFVrJJfecg.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} + +/* devanagari */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url(/public/fonts/pxiByp8kv8JHgFVrLGT9Z11lFc-K.woff2) format('woff2'); + unicode-range: U+0900-097F, U+1CD0-1CF9, U+200C-200D, U+20A8, U+20B9, U+20F0, U+25CC, U+A830-A839, U+A8E0-A8FF, U+11B00-11B09; +} + +/* latin-ext */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url(/public/fonts/pxiByp8kv8JHgFVrLGT9Z1JlFc-K.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} + +/* latin */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url(/public/fonts/pxiByp8kv8JHgFVrLGT9Z1xlFQ.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} + +/* devanagari */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(/public/fonts/pxiByp8kv8JHgFVrLEj6Z11lFc-K.woff2) format('woff2'); + unicode-range: U+0900-097F, U+1CD0-1CF9, U+200C-200D, U+20A8, U+20B9, U+20F0, U+25CC, U+A830-A839, U+A8E0-A8FF, U+11B00-11B09; +} + +/* latin-ext */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(/public/fonts/pxiByp8kv8JHgFVrLEj6Z1JlFc-K.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} + +/* latin */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(/public/fonts/pxiByp8kv8JHgFVrLEj6Z1xlFQ.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} + +/* devanagari */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(/public/fonts/pxiByp8kv8JHgFVrLCz7Z11lFc-K.woff2) format('woff2'); + unicode-range: U+0900-097F, U+1CD0-1CF9, U+200C-200D, U+20A8, U+20B9, U+20F0, U+25CC, U+A830-A839, U+A8E0-A8FF, U+11B00-11B09; +} + +/* latin-ext */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(/public/fonts/pxiByp8kv8JHgFVrLCz7Z1JlFc-K.woff2) format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} + +/* latin */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(/public/fonts/pxiByp8kv8JHgFVrLCz7Z1xlFQ.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} \ No newline at end of file diff --git a/pancakz-v1-caution/include/templates/articles/001-personal-email-server.html b/pancakz-v1-caution/include/templates/articles/001-personal-email-server.html new file mode 100644 index 0000000..028f691 --- /dev/null +++ b/pancakz-v1-caution/include/templates/articles/001-personal-email-server.html @@ -0,0 +1,84 @@ +{{ define "ArticleContent" }} + +

Introduction

+

+ If you're reading this... I haven't written the article yet :P +

+

+ Luctus montes donec mauris. Vehicula suspendisse condimentum massa fringilla at conubia. + Senectus laoreet praesent in, porttitor sollicitudin luctus orci scelerisque egestas malesuada faucibus a. + Arcu imperdiet libero imperdiet nulla libero natoque eu fusce ultricies vehicula nisi. + Torquent lacus sodales inceptos dignissim sed, mauris feugiat erat. + Phasellus at tincidunt sociosqu potenti risus aliquam non litora. + Commodo mi fermentum, id arcu dictum convallis. + Vehicula convallis, proin fames molestie potenti congue penatibus feugiat porttitor. + Habitant justo lacinia, curabitur nascetur! + Dolor nunc accumsan imperdiet penatibus? + Amet cursus faucibus dui vestibulum nascetur quam. +

+
+ +

Prerequisites

+

+ Praesent augue ligula amet nisl. Litora lectus consectetur aliquet. + Sociis iaculis dolor nostra pulvinar felis condimentum netus. + Suscipit enim habitant sed eros etiam, ut odio sed. + Fringilla quam tempus nisl natoque parturient dolor curabitur tellus. + Lacus conubia quis inceptos tristique ultricies cum consequat. + Consequat phasellus proin dolor molestie nec quam cursus mollis vel? + Eros tempor sollicitudin tortor litora nunc. + Sem scelerisque semper id ac auctor fusce quis erat imperdiet convallis donec eget! + Pellentesque tempor nunc ipsum imperdiet quam ipsum habitant feugiat. +

+ +

Hosting

+

+ Odio nibh penatibus erat sociosqu eget iaculis. Ante curabitur bibendum ligula? + Netus aliquet cursus interdum pharetra. Magnis elementum nunc luctus eu nam sit habitant etiam vestibulum in. + Lacus nisl ullamcorper molestie! Dignissim, vulputate porta pulvinar duis posuere. +

+ +

Domains

+

+ Curae; laoreet cum duis turpis, feugiat per integer. + Sit in blandit himenaeos. Penatibus fringilla imperdiet, luctus dapibus elementum. + Felis senectus pulvinar a natoque risus. +

+ +

Credentials

+

+ Mauris habitasse nulla accumsan fermentum fermentum. + Magnis amet amet risus senectus in curae;. + Elementum ac montes sagittis vivamus malesuada elementum senectus ultrices scelerisque fusce. + In nulla platea. +

+ +
+ +

Setup DNS

+

+ Nisi vitae vehicula etiam nam auctor, accumsan purus ridiculus molestie. + Ante malesuada condimentum aliquam etiam auctor arcu porttitor parturient nullam accumsan bibendum? + Vitae arcu at mattis. Volutpat himenaeos class vitae elit, luctus sociosqu semper? + Praesent taciti lobortis tortor laoreet magnis tortor sagittis porta facilisi vivamus dictum scelerisque. + Consectetur elit enim malesuada commodo proin facilisi sagittis! + Malesuada quam duis non elit himenaeos sem. + Luctus suspendisse senectus mollis aliquet aliquam pellentesque conubia condimentum suspendisse aptent litora potenti. + Curabitur sociis lacus turpis, laoreet ligula consequat luctus eu auctor auctor sagittis. + Turpis nibh feugiat lorem donec quis bibendum. + Himenaeos sapien interdum aptent. +

+ +

Setup Linux

+

+ Convallis pharetra vitae tincidunt phasellus bibendum porta, praesent dictum aliquet volutpat. + Lobortis semper eget consectetur elementum elit hendrerit natoque mauris taciti ante ac augue. + Ullamcorper viverra vestibulum vehicula nisi metus vestibulum curabitur vehicula et. + Phasellus ligula vitae posuere penatibus ullamcorper lorem phasellus metus. + Scelerisque ac lobortis gravida primis? + Lacus porttitor ullamcorper quisque viverra molestie. + Lacinia bibendum facilisi tempor cubilia felis eros! + Etiam blandit lacinia leo urna. +

+ +{{ end }} \ No newline at end of file diff --git a/pancakz-v1-caution/include/templates/base.html b/pancakz-v1-caution/include/templates/base.html new file mode 100644 index 0000000..0b90b41 --- /dev/null +++ b/pancakz-v1-caution/include/templates/base.html @@ -0,0 +1,48 @@ + + + + + + + + + + + {{ block "PageStyles" . }}{{ end }} + {{ .Title }} - {{ .Site.Name }} + + {{ block "PageHead" . }}{{ end }} + + + +
+ + +
+ + + + +
+ + +
+ {{ block "PageContent" . }}{{ end }} +
+ +
+ {{ block "PageBody" . }}{{ end }} + + + \ No newline at end of file diff --git a/pancakz-v1-caution/include/templates/blog_article.html b/pancakz-v1-caution/include/templates/blog_article.html new file mode 100644 index 0000000..7a1c243 --- /dev/null +++ b/pancakz-v1-caution/include/templates/blog_article.html @@ -0,0 +1,82 @@ +{{ define "PageStyles" }} + +{{ end }} + +{{ define "PageHead" }} + + + + + +{{ end }} + +{{ define "PageBody" }} + + + + +{{ end }} + +{{ define "NavContent" }} +
+ + {{ template "icon_home.svg" . }} + + + {{ template "icon_top.svg" . }} + + + {{ template "icon_share.svg" . }} + +
+ +
+ +
+{{ end }} + +{{ define "PageContent" }} +

+ +
+ Article Banner +

{{ .Article.Title }}

+
+
+ {{ .Article.Author }} + {{ .Article.Date.Format "Jan 02 2006" }} +
+
+ {{ range .Article.Tags }} + {{ . }} + {{ end }} +
+
+
+ +
+ {{ block "ArticleContent" . }}{{ end }} +
+{{ end }} \ No newline at end of file diff --git a/pancakz-v1-caution/include/templates/blog_browser.html b/pancakz-v1-caution/include/templates/blog_browser.html new file mode 100644 index 0000000..d5f2900 --- /dev/null +++ b/pancakz-v1-caution/include/templates/blog_browser.html @@ -0,0 +1,71 @@ +{{ template "base.html" . }} + +{{ define "PageStyles" }} + + +{{ end }} + +{{ define "PageContent" }} + + +
+

Welcome to my blog!

+ Blog Banner +

+ This corner of the internet contains ramblings about random experiments + that more than likely occured on a bright sunday afternoon. Nothing here + is meant to be perfect, but I do hope to provide the odd spark of insight. +

+ I assume no responsibility for bodily harm, wasted time, or raised eyebrows + that may result from consuming these articles. Enjoy in Moderation! Have fun! +

+
+
+ +

Personal

+ +

Update

+ +

Guide

+
+
+ + + + + + + +{{ end }} \ No newline at end of file diff --git a/pancakz-v1-caution/include/templates/generate_404.html b/pancakz-v1-caution/include/templates/generate_404.html new file mode 100644 index 0000000..221c6f2 --- /dev/null +++ b/pancakz-v1-caution/include/templates/generate_404.html @@ -0,0 +1,76 @@ + + + + + + + + Page Not Found + + + + +
+

404: Page Not Found

+
+

.-.

+
+ Go BackHomepage +
+ + + + \ No newline at end of file diff --git a/pancakz-v1-caution/include/templates/generate_rss.html b/pancakz-v1-caution/include/templates/generate_rss.html new file mode 100644 index 0000000..2d52d76 --- /dev/null +++ b/pancakz-v1-caution/include/templates/generate_rss.html @@ -0,0 +1,26 @@ + + + + + {{ .Site.Host }} + <![CDATA[{{ .Site.Name }}]]> + + {{ .Site.Category }} + {{ .Site.Locale }} + teto + Copyright 2025 {{ .Site.Owner }} + {{ .BuildDate.UTC.Format .RFC1123 }} + + {{ range $index, $elem := .Articles }} + + {{ $.Site.Host }}/{{ $elem.Slug }} + {{ $.Site.Host }}/{{ $elem.Slug }} + <![CDATA[{{ $elem.Title }}]]> + + {{ $elem.Date.UTC.Format $.RFC1123 }} + {{ range $i, $tag := $elem.Tags }} + {{ $tag }} + {{ end }} + + {{ end }} + \ No newline at end of file diff --git a/pancakz-v1-caution/include/templates/homepage.html b/pancakz-v1-caution/include/templates/homepage.html new file mode 100644 index 0000000..3c1f2f3 --- /dev/null +++ b/pancakz-v1-caution/include/templates/homepage.html @@ -0,0 +1,21 @@ +{{ template "base.html" . }} + +{{ define "PageContent" }} + +
+ Lost Sprite +

I intended to put something here, but I couldn't come up with anything....

+

So check out my blog, code or stickerboard!

+
+{{ end }} \ No newline at end of file diff --git a/pancakz-v1-caution/include/templates/icons/icon_home.svg b/pancakz-v1-caution/include/templates/icons/icon_home.svg new file mode 100644 index 0000000..ea6b246 --- /dev/null +++ b/pancakz-v1-caution/include/templates/icons/icon_home.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/pancakz-v1-caution/include/templates/icons/icon_share.svg b/pancakz-v1-caution/include/templates/icons/icon_share.svg new file mode 100644 index 0000000..3fe5fd9 --- /dev/null +++ b/pancakz-v1-caution/include/templates/icons/icon_share.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/pancakz-v1-caution/include/templates/icons/icon_stack.svg b/pancakz-v1-caution/include/templates/icons/icon_stack.svg new file mode 100644 index 0000000..b61eeb2 --- /dev/null +++ b/pancakz-v1-caution/include/templates/icons/icon_stack.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pancakz-v1-caution/include/templates/icons/icon_top.svg b/pancakz-v1-caution/include/templates/icons/icon_top.svg new file mode 100644 index 0000000..07b0d53 --- /dev/null +++ b/pancakz-v1-caution/include/templates/icons/icon_top.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/pancakz-v1-caution/include/templates/icons/logo_facebook.svg b/pancakz-v1-caution/include/templates/icons/logo_facebook.svg new file mode 100644 index 0000000..2f06392 --- /dev/null +++ b/pancakz-v1-caution/include/templates/icons/logo_facebook.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/pancakz-v1-caution/include/templates/icons/logo_linkedin.svg b/pancakz-v1-caution/include/templates/icons/logo_linkedin.svg new file mode 100644 index 0000000..0d4b404 --- /dev/null +++ b/pancakz-v1-caution/include/templates/icons/logo_linkedin.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/pancakz-v1-caution/include/templates/icons/logo_x.svg b/pancakz-v1-caution/include/templates/icons/logo_x.svg new file mode 100644 index 0000000..c3f9c05 --- /dev/null +++ b/pancakz-v1-caution/include/templates/icons/logo_x.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/pancakz-v1-caution/main.go b/pancakz-v1-caution/main.go new file mode 100644 index 0000000..b2b8492 --- /dev/null +++ b/pancakz-v1-caution/main.go @@ -0,0 +1,122 @@ +package main + +import ( + "context" + "log" + "net/http" + "os" + "os/signal" + "path" + "sync" + "syscall" + "time" + + "bakonpancakz/homepage/env" + "bakonpancakz/homepage/include" + "bakonpancakz/homepage/routes" + + _ "github.com/joho/godotenv/autoload" +) + +func main() { + // Startup Services + var stopCtx, stop = context.WithCancel(context.Background()) + var stopWg sync.WaitGroup + go SetupHTTP(stopCtx, &stopWg) + + // Await Shutdown Signal + cancel := make(chan os.Signal, 1) + signal.Notify(cancel, syscall.SIGINT, syscall.SIGTERM) + <-cancel + stop() + + // Begin Shutdown Process + timeout, finish := context.WithTimeout(context.Background(), time.Minute) + defer finish() + go func() { + <-timeout.Done() + if timeout.Err() == context.DeadlineExceeded { + log.Fatalln("[main] Cleanup timeout! Exiting now.") + } + }() + stopWg.Wait() + log.Println("[main] All done, bye bye!") + os.Exit(0) +} + +func SetupHTTP(stop context.Context, await *sync.WaitGroup) { + + notFoundHandler := routes.ServeStaticTemplate(&routes.ServeTemplateInfo{ + FileSystem: include.Templates, + FilePaths: []string{"generate_404.html"}, + Filename: "generate_404.html", + Literals: map[string]any{ + "Site": env.Database.Site, + }, + }) + + mux := http.NewServeMux() + mux.HandleFunc("/", routes.GET_Index(notFoundHandler)) + mux.HandleFunc("/blog", routes.ServeStaticTemplate(&routes.ServeTemplateInfo{ + FileSystem: include.Templates, + FilePaths: []string{"base.html", "blog_browser.html"}, + Filename: "blog_browser.html", + Literals: map[string]any{ + "Title": "Browser", + "Version": env.VERSION, + "Site": env.Database.Site, + "Articles": env.Database.Articles, + }, + })) + mux.HandleFunc("/rss.xml", routes.ServeStaticTemplate(&routes.ServeTemplateInfo{ + FileSystem: include.Templates, + FilePaths: []string{"generate_rss.html"}, + Filename: "generate_rss.html", + ContentType: "application/rss+xml", + Literals: map[string]any{ + "Site": env.Database.Site, + "Articles": env.Database.Articles, + "RFC1123": time.RFC1123, + "BuildDate": time.Now(), + }, + })) + mux.HandleFunc("/blog/{slug}", routes.PrepareBlogArticles(notFoundHandler)) + mux.HandleFunc("/favicon.ico", routes.ServeStaticFile("favicon.ico")) + mux.HandleFunc("/robots.txt", routes.ServeStaticFile("robots.txt")) + mux.HandleFunc("/public/{path...}", func(w http.ResponseWriter, r *http.Request) { + routes.ServePublicFile(w, r, path.Clean(r.PathValue("path"))) + }) + + svr := http.Server{ + Handler: mux, + Addr: env.HTTP_ADDRESS, + TLSConfig: env.HTTP_TLS, + MaxHeaderBytes: 4096, + IdleTimeout: 5 * time.Second, + ReadHeaderTimeout: 5 * time.Second, + WriteTimeout: 30 * time.Second, + ReadTimeout: 30 * time.Second, + } + + // Shutdown Logic + await.Add(1) + go func() { + defer await.Done() + <-stop.Done() + svr.Shutdown(context.Background()) + log.Println("[http] Cleaned up HTTP") + }() + + // Server Startup + var err error + if env.TLS_ENABLED { + log.Printf("[http] Bound HTTPS - %s\n", svr.Addr) + err = svr.ListenAndServeTLS("", "") + } else { + log.Printf("[http] Bound HTTP - %s\n", svr.Addr) + err = svr.ListenAndServe() + } + if err != http.ErrServerClosed { + log.Fatalln("[http] Listen Error:", err) + } +} diff --git a/pancakz-v1-caution/routes/GET_Blog_Slug.go b/pancakz-v1-caution/routes/GET_Blog_Slug.go new file mode 100644 index 0000000..db6f18c --- /dev/null +++ b/pancakz-v1-caution/routes/GET_Blog_Slug.go @@ -0,0 +1,105 @@ +package routes + +import ( + "bakonpancakz/homepage/env" + "bakonpancakz/homepage/include" + "bytes" + "compress/gzip" + "fmt" + "log" + "net/http" + "strings" + "sync" + "text/template" +) + +var articleCache sync.Map + +func PrepareBlogArticles(notFoundHandler HttpHandler) HttpHandler { + return func(w http.ResponseWriter, r *http.Request) { + for _, art := range env.Database.Articles { + if strings.Compare(art.Slug, r.PathValue("slug")) == 0 { + + compress := strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") + cacheKeyStandard := fmt.Sprintf("art_%s_%t", art.Slug, true) + cacheKeyCompress := fmt.Sprintf("art_%s_%t", art.Slug, false) + + // Check Browser Cache + if r.Header.Get("If-None-Match") == env.VERSION { + w.WriteHeader(http.StatusNotModified) + return + } + + // Check Template Cache + w.Header().Set("ETag", env.VERSION) + w.Header().Set("Content-Type", "text/html") + w.Header().Set("Cache-Control", "public, max-age=3600, must-revalidate") + if compress { + if v, ok := articleCache.Load(cacheKeyCompress); ok { + w.Header().Set("Content-Encoding", "gzip") + w.Write(v.([]byte)) + return + } + } else { + if v, ok := articleCache.Load(cacheKeyStandard); ok { + w.Write(v.([]byte)) + return + } + } + + // Render Document + tmpl, err := template.ParseFS( + include.Templates, + include.PreparePath(include.Templates, "base.html"), + include.PreparePath(include.Templates, "blog_article.html"), + include.PreparePath(include.Templates, fmt.Sprint("articles/", art.BaseTemplate)), + include.PreparePath(include.Templates, "icons/logo_facebook.svg"), + include.PreparePath(include.Templates, "icons/logo_linkedin.svg"), + include.PreparePath(include.Templates, "icons/logo_x.svg"), + include.PreparePath(include.Templates, "icons/icon_top.svg"), + include.PreparePath(include.Templates, "icons/icon_home.svg"), + include.PreparePath(include.Templates, "icons/icon_share.svg"), + include.PreparePath(include.Templates, "icons/icon_stack.svg"), + ) + if err != nil { + log.Println("[routes/blog] Template Error:", err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + var b bytes.Buffer + if err = tmpl.ExecuteTemplate(&b, "base.html", map[string]any{ + "Title": art.Title, + "Version": env.VERSION, + "Site": env.Database.Site, + "Article": art, + }); err != nil { + log.Println("[routes/blog] Template Error:", err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + // Compress Document + var c bytes.Buffer + g := gzip.NewWriter(&c) + g.Write(b.Bytes()) + g.Close() + + if include.Embedded { + articleCache.Store(cacheKeyStandard, b.Bytes()) + articleCache.Store(cacheKeyCompress, c.Bytes()) + } + + // Send Document + if compress { + w.Header().Set("Content-Encoding", "gzip") + w.Write(c.Bytes()) + } else { + w.Write(b.Bytes()) + } + return + } + } + notFoundHandler(w, r) + } +} diff --git a/pancakz-v1-caution/routes/GET_Index.go b/pancakz-v1-caution/routes/GET_Index.go new file mode 100644 index 0000000..a4dbcb8 --- /dev/null +++ b/pancakz-v1-caution/routes/GET_Index.go @@ -0,0 +1,33 @@ +package routes + +import ( + "bakonpancakz/homepage/env" + "bakonpancakz/homepage/include" + "net/http" +) + +func GET_Index(notFoundHandler HttpHandler) HttpHandler { + + handler := ServeStaticTemplate(&ServeTemplateInfo{ + FileSystem: include.Templates, + FilePaths: []string{"base.html", "homepage.html"}, + Filename: "homepage.html", + Literals: map[string]any{ + "Title": "Home", + "Version": env.VERSION, + "Site": env.Database.Site, + }, + }) + + return func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path == "/" { + handler(w, r) + return + } + if r.Method == http.MethodGet { + notFoundHandler(w, r) + return + } + w.WriteHeader(http.StatusMethodNotAllowed) + } +} diff --git a/pancakz-v1-caution/routes/ServeFunctions.go b/pancakz-v1-caution/routes/ServeFunctions.go new file mode 100644 index 0000000..4496c84 --- /dev/null +++ b/pancakz-v1-caution/routes/ServeFunctions.go @@ -0,0 +1,197 @@ +package routes + +import ( + "bakonpancakz/homepage/include" + "bytes" + "compress/gzip" + "crypto/md5" + "fmt" + "io/fs" + "log" + "mime" + "net/http" + "os" + "path" + "strings" + "sync" + "text/template" +) + +type HttpHandler func(w http.ResponseWriter, r *http.Request) + +var hashTable sync.Map + +type ServeTemplateInfo struct { + FileSystem fs.FS + FilePaths []string + Filename string + Literals map[string]any + StatusCode int + ContentType string +} + +func prepareStaticTemplate(info *ServeTemplateInfo, ds *[]byte, dc *[]byte, dh *string) error { + + // Render Document + tmpl, err := template.ParseFS(info.FileSystem, info.FilePaths...) + if err != nil { + return err + } + var b bytes.Buffer + if err := tmpl.ExecuteTemplate(&b, info.Filename, info.Literals); err != nil { + return err + } + + // Compress Document + var c bytes.Buffer + g := gzip.NewWriter(&c) + g.Write(b.Bytes()) + g.Close() + + // Store Document + *ds = b.Bytes() + *dc = c.Bytes() + *dh = fmt.Sprintf("%X", md5.Sum(b.Bytes())) + + return nil +} + +func ServeStaticTemplate(info *ServeTemplateInfo) func(w http.ResponseWriter, r *http.Request) { + + // Defaults + if info.StatusCode == 0 { + info.StatusCode = http.StatusOK + } + if info.ContentType == "" { + info.ContentType = "text/html" + } + for i, p := range info.FilePaths { + info.FilePaths[i] = include.PreparePath(info.FileSystem, p) + } + + // Render Document + var ( + documentStandard []byte + documentCompress []byte + documentHash string + ) + if err := prepareStaticTemplate(info, &documentStandard, &documentCompress, &documentHash); err != nil { + log.Fatalln("[routes/template] Cannot Prepare Template:", err) + } + + // Serve Function + return func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + w.WriteHeader(http.StatusMethodNotAllowed) + return + } + if !include.Embedded { + if err := prepareStaticTemplate(info, &documentStandard, &documentCompress, &documentHash); err != nil { + log.Println("[routes/template] Refresh Error:", err) + w.WriteHeader(http.StatusInternalServerError) + return + } + } + + // Check Browser Cache + if r.Header.Get("If-None-Match") == documentHash { + w.WriteHeader(http.StatusNotModified) + return + } + + // Send Document + w.Header().Set("ETag", documentHash) + w.Header().Set("Content-Type", info.ContentType) + w.Header().Set("Cache-Control", "public, max-age=3600, must-revalidate") + if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") { + w.Header().Set("Content-Encoding", "gzip") + w.Write(documentCompress) + } else { + w.Write(documentStandard) + } + } +} + +func ServeStaticFile(filepath string) HttpHandler { + var ( + fileHash string + fileData []byte + fileMime string + ) + + // Prepare File + b, err := include.ReadFile(include.Public, filepath) + if err != nil { + log.Fatalln("[routes/static] Cannot Prepare File:", filepath, err) + } + fileMime = mime.TypeByExtension(path.Ext(filepath)) + fileHash = fmt.Sprintf("%X", md5.Sum(b)) + fileData = b + + return func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + w.WriteHeader(http.StatusMethodNotAllowed) + return + } + if r.Header.Get("If-None-Match") == fileHash { + w.WriteHeader(http.StatusNotModified) + return + } + w.Header().Add("ETag", fileHash) + w.Header().Add("X-Robots-Tag", "noindex") + w.Header().Add("Content-Type", fileMime) + w.Header().Add("Cache-Control", "public, max-age=604800, immutable") + w.Write(fileData) + } +} + +func ServePublicFile(w http.ResponseWriter, r *http.Request, filepath string) { + if r.Method != http.MethodGet { + w.WriteHeader(http.StatusMethodNotAllowed) + return + } + + // Check Cache Hash + if hash, ok := hashTable.Load(filepath); ok { + if r.Header.Get("If-None-Match") == hash.(string) { + w.WriteHeader(http.StatusNotModified) + return + } + } + + // Read File Contents + filedata, err := include.ReadFile(include.Public, filepath) + if err != nil { + if os.IsNotExist(err) { + w.WriteHeader(http.StatusNotFound) + return + } + log.Println("[http] Read Asset Error:", err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + // Generate Cache Hash + filehash := fmt.Sprintf("%X", md5.Sum(filedata)) + hashTable.Store(filepath, filehash) + fileMime := mime.TypeByExtension(path.Ext(filepath)) + + // Send Contents + w.Header().Add("ETag", filehash) + w.Header().Add("X-Robots-Tag", "noindex") + w.Header().Add("Content-Type", fileMime) + w.Header().Add("Cache-Control", "public, max-age=604800, immutable") + + if len(filedata) < (1<<20) && + !strings.Contains(fileMime, "image") && + !strings.Contains(fileMime, "audio") && + !strings.Contains(fileMime, "video") && + strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") { + w.Header().Set("Content-Encoding", "gzip") + g := gzip.NewWriter(w) + g.Write(filedata) + g.Close() + } else { + w.Write(filedata) + } +} diff --git a/pancakz-v2-crossroads/Dockerfile b/pancakz-v2-crossroads/Dockerfile new file mode 100644 index 0000000..8cafbf2 --- /dev/null +++ b/pancakz-v2-crossroads/Dockerfile @@ -0,0 +1,18 @@ +# Build +FROM golang:1.25.2-alpine3.22 AS build +WORKDIR /app +COPY . . +RUN go build -o homepage.elf main.go +#RUN touch homepage.elf + +# Runtime +FROM alpine:latest AS runtime +WORKDIR /app +COPY --from=build /app/homepage.elf . +COPY --from=build /app/templates ./templates +COPY --from=build /app/public ./public + +ENV HTTP_ADDRESS="0.0.0.0:8080" +EXPOSE 8080 + +CMD ["./homepage.elf"] diff --git a/pancakz-v2-crossroads/main.go b/pancakz-v2-crossroads/main.go new file mode 100644 index 0000000..0df0525 --- /dev/null +++ b/pancakz-v2-crossroads/main.go @@ -0,0 +1,309 @@ +package main + +import ( + "bytes" + "compress/gzip" + "context" + "crypto/md5" + "encoding/json" + "fmt" + "html" + "io" + "log" + "mime" + "net/http" + "os" + "os/signal" + "path" + "strings" + "sync" + "syscall" + "text/template" + "time" +) + +type ManifestArticle struct { + ID string `json:"id"` + BannerMain string `json:"banner_main"` + BannerList string `json:"banner_list"` + BannerDescription string `json:"banner_description"` + Date time.Time `json:"date"` + Title string `json:"title"` + Description string `json:"description"` + Author string `json:"author"` + Tags []string `json:"tags"` +} + +type ManifestNode struct { + ID string `json:"id"` + Icon string `json:"icon"` + Name string `json:"name"` + Description string `json:"description"` +} + +type Manifest struct { + Links []ManifestNode `json:"links"` + Authors []ManifestNode `json:"authors"` + Tags []ManifestNode `json:"tags"` + Articles []ManifestArticle `json:"articles"` +} + +type CacheInfo struct { + HeaderETag string + HeaderContentType string + ContentPlainText []byte + ContentCompressed []byte +} + +var ( + MANIFEST Manifest + MANIFEST_RAW string + HTTP_ADDRESS = os.Getenv("HTTP_ADDRESS") + CACHE_VERSION = fmt.Sprintf("%X", time.Now().Unix()) +) + +func init() { + // Default Values + if HTTP_ADDRESS == "" { + HTTP_ADDRESS = "127.0.0.1:8080" + } + + // Manifest Parsing + data, err := os.ReadFile("public/blog/manifest.json") + if err != nil { + log.Fatalln("Cannot Read Manifest JSON:", err) + } + if err := json.Unmarshal(data, &MANIFEST); err != nil { + log.Fatalln("Cannot Parse Manifest JSON:", err) + } + MANIFEST_RAW = string(data) +} + +func main() { + // Startup Services + var stopCtx, stop = context.WithCancel(context.Background()) + var stopWg sync.WaitGroup + go SetupHTTP(stopCtx, &stopWg) + + // Await Shutdown Signal + cancel := make(chan os.Signal, 1) + signal.Notify(cancel, syscall.SIGINT, syscall.SIGTERM) + <-cancel + stop() + + // Begin Shutdown Process + timeout, finish := context.WithTimeout(context.Background(), time.Minute) + defer finish() + go func() { + <-timeout.Done() + if timeout.Err() == context.DeadlineExceeded { + log.Fatalln("[main] Cleanup timeout! Exiting now.") + } + }() + stopWg.Wait() + log.Println("[main] All done, bye bye!") + os.Exit(0) +} + +func SetupHTTP(stop context.Context, await *sync.WaitGroup) { + mux := http.NewServeMux() + loc := map[string]any{ + "Version": CACHE_VERSION, + } + + // Webpage Endpoints // + mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path == "/" { + ServeTemplate(w, r, "templates/home.html", loc) + return + } + if r.Method == http.MethodGet { + ServeTemplate(w, r, "templates/404.html", loc) + return + } + w.WriteHeader(http.StatusMethodNotAllowed) + }) + mux.HandleFunc("/blog/{slug...}", func(w http.ResponseWriter, r *http.Request) { + + // Although this is a SPA, we still need to render + // the OG meta tags for SEO / Social Media Sites + + var article *ManifestArticle + for _, art := range MANIFEST.Articles { + if strings.EqualFold(art.ID, r.PathValue("slug")) { + article = &art + break + } + } + ServeTemplate(w, r, "templates/blog.html", map[string]any{ + "Version": CACHE_VERSION, + "ManifestRaw": html.EscapeString(MANIFEST_RAW), + "Manifest": MANIFEST, + "Article": article, + }) + }) + + // Secret Endpoints // + mux.HandleFunc("/secret/sprites", func(w http.ResponseWriter, r *http.Request) { + ServeTemplate(w, r, "templates/secret_sprites.html", loc) + }) + mux.HandleFunc("/secret/picross", func(w http.ResponseWriter, r *http.Request) { + ServeTemplate(w, r, "templates/secret_picross_board.html", loc) + }) + mux.HandleFunc("/secret/picross/award", func(w http.ResponseWriter, r *http.Request) { + ServeTemplate(w, r, "templates/secret_picross_award.html", loc) + }) + + // Special Endpoints // + mux.HandleFunc("/blog/rss.xml", func(w http.ResponseWriter, r *http.Request) { + ServeTemplate(w, r, "templates/rss.xml", map[string]any{ + "Version": CACHE_VERSION, + "Manifest": MANIFEST, + "Date": time.Now().UTC().Format(time.RFC1123), + "RFC1123": time.RFC1123, + }) + }) + mux.HandleFunc("/sitemap.xml", func(w http.ResponseWriter, r *http.Request) { + ServeTemplate(w, r, "templates/sitemap.xml", map[string]any{ + "Version": CACHE_VERSION, + "Manifest": MANIFEST, + "Date": time.Now().UTC().Format("2006-01-02"), + "Locations": []string{ + "https://panca.kz/", + "https://panca.kz/blog", + }, + }) + }) + mux.HandleFunc("/qr", func(w http.ResponseWriter, r *http.Request) { + redirects := []string{ + "https://www.youtube.com/watch?v=dQw4w9WgXcQ", // Risk Astley - Never Gonna Give You Up + "https://www.youtube.com/watch?v=DnmHG3mJv1o", // Masayoshi Takanaka - Tropic Birds + "https://www.youtube.com/watch?v=ZZCt92zLmLI", // Blur - Intermission + "https://www.twitch.tv/robcdee", // awesome sauce + "https://piapro.net/intl/en.html", // mikudayooo + } + index := int(time.Now().Unix()/60) % len(redirects) // rotate every minute + http.Redirect(w, r, redirects[index], http.StatusTemporaryRedirect) + }) + + // Resource Endpoints // + mux.HandleFunc("/favicon.ico", func(w http.ResponseWriter, r *http.Request) { + ServeFile(w, r, "favicon.ico") + }) + mux.HandleFunc("/robots.txt", func(w http.ResponseWriter, r *http.Request) { + ServeFile(w, r, "robots.txt") + }) + mux.HandleFunc("/public/{path...}", func(w http.ResponseWriter, r *http.Request) { + ServeFile(w, r, path.Clean(r.PathValue("path"))) + }) + + // Create HTTP Server // + svr := http.Server{ + Handler: mux, + Addr: HTTP_ADDRESS, + MaxHeaderBytes: 4096, + IdleTimeout: 5 * time.Second, + ReadHeaderTimeout: 5 * time.Second, + WriteTimeout: 30 * time.Second, + ReadTimeout: 30 * time.Second, + } + + await.Add(1) + go func() { + defer await.Done() + <-stop.Done() + svr.Shutdown(context.Background()) + log.Println("[http] Cleaned up HTTP") + }() + + log.Printf("[http] Listening @ %s\n", svr.Addr) + if err := svr.ListenAndServe(); err != http.ErrServerClosed { + log.Fatalln("[http] Listen Error:", err) + } + +} + +func ServeTemplate(w http.ResponseWriter, r *http.Request, filepath string, locals any) { + if r.Method != http.MethodGet { + w.WriteHeader(http.StatusMethodNotAllowed) + return + } + clientCacheKey := r.Header.Get("If-None-Match") + clientCompress := strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") + + // Render Template // + html := bytes.Buffer{} + tmpl, err := template.ParseFiles(filepath) + if err != nil { + log.Printf("[http] Cannot parse template '%s': %s\n", filepath, err) + return + } + if err := tmpl.Execute(&html, locals); err != nil { + log.Printf("[http] Cannot render template '%s': %s \n", filepath, err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + // Cache Validation // + serverCacheKey := fmt.Sprintf("%x", md5.Sum(html.Bytes())) + serverFileType := mime.TypeByExtension(path.Ext(filepath)) + if strings.EqualFold(clientCacheKey, serverCacheKey) { + w.WriteHeader(http.StatusNotModified) + return + } + + // Stream Contents // + w.Header().Set("ETag", serverCacheKey) + w.Header().Set("Content-Type", serverFileType) + // w.Header().Set("Cache-Control", "public, max-age=3600, must-revalidate") + + if clientCompress { + w.Header().Set("Content-Encoding", "gzip") + pack := gzip.NewWriter(w) + pack.Write(html.Bytes()) + pack.Close() + } else { + w.Write(html.Bytes()) + } +} + +func ServeFile(w http.ResponseWriter, r *http.Request, filepath string) { + if r.Method != http.MethodGet { + w.WriteHeader(http.StatusMethodNotAllowed) + return + } + + // Open File // + file, err := os.Open("./public/" + filepath) + if err != nil { + if os.IsNotExist(err) { + w.WriteHeader(http.StatusNotFound) + return + } + log.Printf("[http] Cannot open file '%s': %s\n", filepath, err) + w.WriteHeader(http.StatusInternalServerError) + return + } + defer file.Close() + + // Skip Compression on Large/Media Files // + serverFileType := mime.TypeByExtension(path.Ext(filepath)) + clientCompress := strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") && + !strings.Contains(serverFileType, "image") && + !strings.Contains(serverFileType, "audio") && + !strings.Contains(serverFileType, "video") + + // Stream Contents // + w.Header().Set("Content-Type", serverFileType) + w.Header().Set("X-Robots-Tag", "noindex") + w.Header().Set("Cache-Control", "public, max-age=31536000, immutable") + + if clientCompress { + w.Header().Set("Content-Encoding", "gzip") + pack := gzip.NewWriter(w) + io.Copy(pack, file) + pack.Close() + } else { + io.Copy(w, file) + } +} diff --git a/pancakz-v2-crossroads/public/blog/favicon.svg b/pancakz-v2-crossroads/public/blog/favicon.svg new file mode 100644 index 0000000..b22acde --- /dev/null +++ b/pancakz-v2-crossroads/public/blog/favicon.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pancakz-v2-crossroads/public/blog/main.css b/pancakz-v2-crossroads/public/blog/main.css new file mode 100644 index 0000000..1bb3261 --- /dev/null +++ b/pancakz-v2-crossroads/public/blog/main.css @@ -0,0 +1,541 @@ +:root { + --corner-thickness: 1px; + --corner-margin: -16px; + --corner-color: #606060; + --glass-tint: rgba(255, 255, 255, .075); + --glass-blur: 4px; + --color-accent: #323232; + --color-background: #000; + --color-text-default: #f0f0f0; + --color-text-hidden: #a0a0a0; +} + +::-webkit-scrollbar { + width: 0; +} + +body { + padding: 0; + margin: 0; + background-color: var(--color-background); +} + +button, +span, +h1, +h2, +h3, +h4, +h5, +h6, +p, +a { + font-family: 'Terminus', sans-serif; + font-weight: normal; + font-size: 1em; + line-height: 1.5em; + text-decoration: none; + color: var(--color-text-default); + padding: 0; + margin: 0; +} + +a:hover, +a:focus-visible { + text-decoration: underline; +} + +/* Layout */ + +div.layout-wrapper { + display: grid; + width: 100%; + height: 100%; +} + +div.layout-background { + position: fixed; +} + +div.layout-foreground { + margin: auto; + width: 100%; + max-width: 1024px; + display: flex; + gap: 16px; + justify-content: center; + padding: 16px 0; + box-sizing: border-box; +} + +div.layout-pane { + grid-row: 1; + grid-column: 1; + height: fit-content; +} + +/* Navigation Links */ + +nav.section-navigation { + width: 300px; + overflow-y: scroll; + overflow-x: hidden; + max-height: calc(100vh - 64px); + padding: 8px; + box-sizing: border-box; +} + +button.nav-header { + position: relative; + text-align: left; + width: 100%; + padding: 4px; + padding-right: 16px; + background: transparent; + border: none; + border-bottom: 1px solid transparent; + cursor: pointer; +} + +button.nav-header.open { + border-color: var(--color-text-hidden); +} + +button.nav-header img { + height: 16px; + width: 16px; + position: absolute; + right: 16px; +} + +p.nav-message { + color: var(--color-text-hidden); + text-align: center; + padding: 8px; +} + +a.item-nav { + width: 100%; + display: flex; + padding: 12px 8px 12px 4px; + box-sizing: border-box; +} + +div.item-nav-text { + flex-basis: 100%; +} + +div.item-nav-text p.item-nav-text-anchor, +div.item-nav-text p.item-nav-text-content { + font-family: 'Terminus', serif; + color: var(--color-text-default); + line-height: 1em; + font-size: 1em; +} + +div.item-nav-text p.item-nav-text-content { + color: var(--color-text-hidden); +} + +div.item-nav-icon { + display: grid; +} + +div.item-nav-icon div.item-nav-icon-background, +div.item-nav-icon img.item-nav-icon-foreground { + grid-row: 1; + grid-column: 1; + margin: auto; +} + +div.item-nav-icon div.item-nav-icon-background { + background-color: var(--color-accent); + transform: rotate(45deg); + z-index: -1; + height: 32px; + width: 32px; +} + +div.item-nav-icon img.item-nav-icon-foreground { + width: 16px; + height: auto; +} + +/* Navigation Chapters */ + +div.nav-list#chapters { + display: grid; + padding: 4px; +} + +div.nav-list#chapters a.section { + font-size: small; + padding-left: 8px; +} + +/* Article List */ + +div.item-article-count { + width: 100%; + background-color: var(--color-accent); +} + +div.item-article-count p.item-article-count-text { + display: block; + width: 100%; + height: 32px; + padding: 0 8px; + line-height: 32px; + box-sizing: border-box; + color: var(--color-text-hidden); + +} + +div.item-article-count span.item-article-count-cursor { + color: var(--color-text-hidden); +} + +a.item-article { + display: grid; + height: 80px; +} + +div.item-article-layer { + width: 100%; + height: 100%; + grid-row: 1; + grid-column: 1; +} + +div.item-article-meta { + padding: 8px 0; + box-sizing: border-box; +} + +p.item-article-meta-title { + padding-left: 10px; +} + +p.item-article-meta-description { + color: var(--color-text-hidden); + padding-left: 10px; + font-size: small; +} + +div.item-article-meta-tags { + display: flex; + padding-left: 4px; + gap: 4px; +} + +div.item-article-meta-tags>span { + color: var(--color-text-hidden); + padding: 0 6px; + font-size: small; +} + +img.item-article-banner { + position: absolute; + right: 0; + height: 80px; + object-fit: cover; + aspect-ratio: 3 / 1; + mask-image: linear-gradient(-90deg, rgba(0, 0, 0, .5) 0%, transparent 100%); +} + +/* Article Header */ + +article.section-article { + width: 600px; + max-height: calc(100vh - 64px); + overflow-y: scroll; + box-sizing: border-box; +} + +div.article-header { + width: 100%; + height: fit-content; + display: grid; + justify-items: center; +} + +div.header-chevrons { + display: flex; + justify-content: space-between; + width: 100%; +} + +div.article-content:has(*) { + display: grid; + gap: 8px; + padding: 16px; + box-sizing: border-box; +} + +img#header-banner { + width: 100%; + object-fit: cover; + aspect-ratio: 3 / 1; +} + +h1#header-title { + word-wrap: break-word; + overflow: hidden; + margin: 16px 0 24px 0; +} + +/* Article Elements */ + +h2.element-header { + font-size: x-large; + font-weight: bold; + border-bottom: 1px solid; + margin-bottom: 8px; + padding-bottom: 8px 0; + padding-top: 16px; +} + +h3.element-subheader { + font-weight: bold; + text-decoration: underline; + padding-bottom: 8px; + padding-top: 16px; +} + +p.element-paragraph { + line-height: 1.25; + text-align: justify; +} + +/* Animations */ + +.animation-blink { + animation: kf-blink 1s infinite step-start; +} + +@keyframes kf-blink { + 50% { + opacity: 0; + } +} + +.animation-scrollin { + box-sizing: border-box; + overflow: hidden; + text-wrap-mode: nowrap; + animation: kf-scrollin 750ms forwards linear; +} + +@keyframes kf-scrollin { + 0% { + width: 0%; + } + + 100% { + width: 100%; + } +} + +.animation-fadein { + animation: kf-fadein 500ms forwards linear; +} + +@keyframes kf-fadein { + 0% { + opacity: 0; + } + + 100% { + opacity: 1; + } +} + +/* Effects */ + +.effect-glass-wrapper { + position: relative; + margin: 16px; +} + +.effect-docked { + font-size: 2em; + font-weight: bold; + text-align: center; + position: relative; + padding: 0 16px; + z-index: 1; +} + +.effect-docked::before { + position: absolute; + content: ''; + height: 100%; + width: 100%; + top: 0; + left: 0; + box-sizing: border-box; + background: var(--color-accent); + clip-path: polygon(12px 60%, calc(100% - 12px) 60%, 100% 100%, 0 100%); + z-index: -1; +} + +div.effect-chevron-container { + align-items: end; +} + +.effect-chevron-point-left, +.effect-chevron-point-right { + display: inline-block; + background-color: var(--color-accent); + text-decoration: none; + font-weight: bold; + height: 24px; + width: fit-content; + padding: 0 16px; +} + +.effect-chevron-point-right { + margin-right: -4px; + clip-path: polygon(0 0, calc(100% - 8px) 0, 100% 50%, calc(100% - 8px) 100%, 0 100%, 8px 50%); +} + +div.effect-chevron-container>.effect-chevron-point-right:first-child { + padding-left: 8px; + clip-path: polygon(0 0, calc(100% - 8px) 0, 100% 50%, calc(100% - 8px) 100%, 0 100%); +} + +.effect-chevron-point-left { + margin-left: -4px; + clip-path: polygon(8px 0, 100% 0, calc(100% - 8px) 50%, 100% 100%, 8px 100%, 0 50%); +} + +div.effect-chevron-container>.effect-chevron-point-left:last-child { + padding-right: 8px; + clip-path: polygon(8px 0, 100% 0, 100% 100%, 8px 100%, 0 50%); +} + +.effect-glass-container { + background: var(--glass-tint); + backdrop-filter: blur(var(--glass-blur)); +} + +.effect-glass-corner { + position: absolute; + width: 24px; + height: 24px; + pointer-events: none; + z-index: 999; +} + +.effect-glass-corner:nth-child(1) { + /* Top-left */ + top: var(--corner-margin); + left: var(--corner-margin); + border-top: var(--corner-thickness) solid var(--corner-color); + border-left: var(--corner-thickness) solid var(--corner-color); +} + +.effect-glass-corner:nth-child(2) { + /* Top-right */ + top: var(--corner-margin); + right: var(--corner-margin); + border-top: var(--corner-thickness) solid var(--corner-color); + border-right: var(--corner-thickness) solid var(--corner-color); +} + +.effect-glass-corner:nth-child(3) { + /* Bottom-left */ + bottom: var(--corner-margin); + left: var(--corner-margin); + border-bottom: var(--corner-thickness) solid var(--corner-color); + border-left: var(--corner-thickness) solid var(--corner-color); +} + +.effect-glass-corner:nth-child(4) { + /* Bottom-right */ + bottom: var(--corner-margin); + right: var(--corner-margin); + border-bottom: var(--corner-thickness) solid var(--corner-color); + border-right: var(--corner-thickness) solid var(--corner-color); +} + +/* Mobile */ +@media only screen and (max-width: 600px) { + + div.layout-foreground { + display: block; + padding: 0; + } + + nav.section-navigation { + width: 100%; + max-height: unset; + } + + article.section-article { + width: 100%; + max-height: unset; + box-sizing: border-box; + } + + /* Make Header Slightly Smaller */ + h1#header-title { + font-size: 1.5em; + } + + div.header-chevrons { + display: grid; + justify-content: center; + } + + div.effect-chevron-container { + text-align: center; + } + + .effect-chevron-point-left, + .effect-chevron-point-right { + margin: 2px 0; + } + + .effect-chevron-point-right { + margin-right: unset; + clip-path: unset; + } + + div.effect-chevron-container>.effect-chevron-point-right:first-child { + padding-left: 16px; + clip-path: unset; + } + + .effect-chevron-point-left { + margin-left: unset; + clip-path: unset; + } + + div.effect-chevron-container>.effect-chevron-point-left:last-child { + padding-right: 16px; + clip-path: unset; + } + + /* Remove Filters from Navigation */ + button.nav-header[for='authors'], + button.nav-header[for='tags'], + div.nav-list#authors, + div.nav-list#tags { + display: none; + } + + .effect-glass-wrapper { + margin: unset; + } + + .effect-glass-corner { + display: none; + } + + .effect-glass-container { + padding: 0; + background: transparent; + } + +} diff --git a/pancakz-v2-crossroads/public/blog/manifest.json b/pancakz-v2-crossroads/public/blog/manifest.json new file mode 100644 index 0000000..bb12d7a --- /dev/null +++ b/pancakz-v2-crossroads/public/blog/manifest.json @@ -0,0 +1,59 @@ +{ + "links": [ + { + "id": "/blog/", + "icon": "script:icon_top", + "name": "LATEST", + "description": "BROWSE ARTICLES" + }, + { + "id": "/blog/rss.xml", + "icon": "script:icon_rss", + "name": "RSS", + "description": "FOR NERDS WITH READERS" + }, + { + "id": "/", + "icon": "script:icon_cross", + "name": "EXIT", + "description": "RETURN TO HOMEPAGE" + } + ], + "authors": [ + { + "id": "bakonpancakz", + "icon": "script:author_bakonpancakz", + "name": "BAKONPANCAKZ", + "description": "THE BOSS" + } + ], + "tags": [ + { + "id": "development", + "icon": "script:tags_development", + "name": "DEVELOPMENT", + "description": "BINARY MAGIC / SPELLS" + }, + { + "id": "personal", + "icon": "script:tags_personal", + "name": "PERSONAL", + "description": "PROJECTS AND TIDBITS" + } + ], + "articles": [ + { + "id": "setting-up-an-email-server", + "banner_main": "/public/blog/setting-up-an-email-server/banner_main.gif", + "banner_list": "/public/blog/setting-up-an-email-server/banner_list.gif", + "date": "2024-11-06T00:00:00Z", + "title": "Setting Up an Email API", + "description": "Freaking emails, how do they work?", + "author": "bakonpancakz", + "tags": [ + "development", + "personal" + ] + } + ] +} \ No newline at end of file diff --git a/pancakz-v2-crossroads/public/blog/scripts/background.js b/pancakz-v2-crossroads/public/blog/scripts/background.js new file mode 100644 index 0000000..f25a123 --- /dev/null +++ b/pancakz-v2-crossroads/public/blog/scripts/background.js @@ -0,0 +1,357 @@ +document.querySelector("div.layout-background").appendChild((() => { + + const COLOR_PARTICLE = 0x363636 + const COLOR_FOREGROUND = 0x282828 + const COLOR_BACKGROUND = 0x000000 + const PARTICLE_COUNT = 320 + const FRAME_TIME = 1000 / 15 + + let gl, canvas + let planeProg, particleProg + let planeBuf, planeIdxBuf, planeOrigBuf + let particlePosBuf, particleColorBuf + let planeVerts, planeOrig, planeIdx + let particlePos, particleColor, particleData = [] + let lastTime = 0, lastFrame = 0, time = 0 + let planeW, planeH, planeSegX, planeSegY + let uTimePlane, uMVPPlane, uFogColorPlane, uFogNearPlane, uFogFarPlane + let uMVPParticle, uFogColorParticle, uFogNearParticle, uFogFarParticle + + // --- Math helpers --- + function mat4() { return new Float32Array(16) } + function mat4Identity(m) { + m[0] = 1; m[1] = 0; m[2] = 0; m[3] = 0; + m[4] = 0; m[5] = 1; m[6] = 0; m[7] = 0; + m[8] = 0; m[9] = 0; m[10] = 1; m[11] = 0; + m[12] = 0; m[13] = 0; m[14] = 0; m[15] = 1; + return m + } + function mat4Multiply(out, a, b) { + for (let i = 0; i < 4; i++) + for (let j = 0; j < 4; j++) { + out[j * 4 + i] = 0 + for (let k = 0; k < 4; k++) out[j * 4 + i] += a[k * 4 + i] * b[j * 4 + k] + } + return out + } + function mat4Perspective(m, fovY, aspect, near, far) { + const f = 1.0 / Math.tan(fovY / 2) + m[0] = f / aspect; m[1] = 0; m[2] = 0; m[3] = 0 + m[4] = 0; m[5] = f; m[6] = 0; m[7] = 0 + m[8] = 0; m[9] = 0; m[10] = (far + near) / (near - far); m[11] = -1 + m[12] = 0; m[13] = 0; m[14] = (2 * far * near) / (near - far); m[15] = 0 + return m + } + function mat4RotateX(m, angle) { + const c = Math.cos(angle), s = Math.sin(angle) + const t = mat4Identity(mat4()) + t[5] = c; t[6] = s; t[9] = -s; t[10] = c + return mat4Multiply(mat4(), t, m) + } + function mat4Translate(m, x, y, z) { + const t = mat4Identity(mat4()) + t[12] = x; t[13] = y; t[14] = z + return mat4Multiply(mat4(), t, m) + } + function randFloat(lo, hi) { return lo + Math.random() * (hi - lo) } + function randFloatSpread(range) { return randFloat(-range / 2, range / 2) } + function degToRad(d) { return d * Math.PI / 180 } + function intToRGB(i) { + return [ + ((i >> 16) & 0xFF) / 255, + ((i >> 8) & 0xFF) / 255, + ((i >> 0) & 0xFF) / 255 + ] + } + + // --- Shader sources --- + const PLANE_VERT = ` + attribute vec3 aPosition; + uniform mat4 uMVP; + uniform float uTime; + varying float vDist; + void main() { + float dist = sqrt(aPosition.x*aPosition.x + aPosition.z*aPosition.z); + float wave = sin(dist * 0.5 - uTime); + float cave = -exp(-dist * 0.1) * 3.5; + vec3 pos = vec3(aPosition.x, aPosition.y + wave + cave, aPosition.z); + vDist = length((uMVP * vec4(pos, 1.0)).xyz); + gl_Position = uMVP * vec4(pos, 1.0); + } + ` + const PLANE_FRAG = ` + precision mediump float; + uniform vec3 uFogColor; + uniform float uFogNear; + uniform float uFogFar; + varying float vDist; + void main() { + float fog = clamp((vDist - uFogNear) / (uFogFar - uFogNear), 0.0, 1.0); + vec3 color = mix(vec3(${intToRGB(COLOR_FOREGROUND).join(',')}), uFogColor, fog); + gl_FragColor = vec4(color, 1.0); + } + ` + const PARTICLE_VERT = ` + attribute vec3 aPosition; + attribute vec4 aColor; + uniform mat4 uMVP; + varying vec4 vColor; + varying float vDist; + void main() { + vec4 pos = uMVP * vec4(aPosition, 1.0); + vDist = length(pos.xyz); + vColor = aColor; + gl_PointSize = 3.0; + gl_Position = pos; + } + ` + const PARTICLE_FRAG = ` + precision mediump float; + uniform vec3 uFogColor; + uniform float uFogNear; + uniform float uFogFar; + varying vec4 vColor; + varying float vDist; + void main() { + float fog = clamp((vDist - uFogNear) / (uFogFar - uFogNear), 0.0, 1.0); + float alpha = vColor.a * (1.0 - fog); + gl_FragColor = vec4(mix(vColor.rgb, uFogColor, fog), alpha); + } + ` + + function compileShader(src, type) { + const s = gl.createShader(type) + gl.shaderSource(s, src) + gl.compileShader(s) + return s + } + function createProgram(vert, frag) { + const p = gl.createProgram() + gl.attachShader(p, compileShader(vert, gl.VERTEX_SHADER)) + gl.attachShader(p, compileShader(frag, gl.FRAGMENT_SHADER)) + gl.linkProgram(p) + return p + } + + function buildPlane(ratio) { + const scale = 24 + planeSegX = Math.round(12 * ratio) + planeSegY = 12 + planeW = scale * ratio + planeH = scale + + const nx = planeSegX + 1, ny = planeSegY + 1 + planeVerts = new Float32Array(nx * ny * 3) + planeOrig = new Float32Array(nx * ny * 3) + + let vi = 0 + for (let iy = 0; iy < ny; iy++) { + for (let ix = 0; ix < nx; ix++) { + const x = (ix / planeSegX - 0.5) * planeW + const z = (iy / planeSegY - 0.5) * planeH + planeVerts[vi] = x + planeVerts[vi + 1] = 0 + planeVerts[vi + 2] = z + planeOrig[vi] = x + planeOrig[vi + 1] = 0 + planeOrig[vi + 2] = z + vi += 3 + } + } + + // Wireframe indices — two triangles per quad + const lines = [] + for (let iy = 0; iy < ny; iy++) { + for (let ix = 0; ix < nx; ix++) { + const idx = iy * nx + ix + if (ix < planeSegX) { lines.push(idx, idx + 1) } + if (iy < planeSegY) { lines.push(idx, idx + nx) } + if (ix < planeSegX && iy < planeSegY) { lines.push(idx, idx + nx + 1) } + } + } + planeIdx = new Uint16Array(lines) + } + + function spawnParticle(i) { + const x = randFloat(-planeW, planeW) + const z = randFloat(-planeH, planeH) + particleData[i] = { + x, y: 0, z, + vx: randFloatSpread(0.05), + vy: randFloat(0.02, 0.05), + vz: randFloatSpread(0.05), + life: randFloat(3.0, 6.0), + maxLife: 0 + } + particleData[i].maxLife = particleData[i].life + const p = i * 3 + particlePos[p] = x; particlePos[p + 1] = 0; particlePos[p + 2] = z + const c = i * 4 + const [r, g, b] = intToRGB(COLOR_PARTICLE) + particleColor[c + 0] = r + particleColor[c + 1] = g + particleColor[c + 2] = b + particleColor[c + 3] = 0 + } + + function init() { + canvas.width = Math.floor(window.innerWidth * 0.25) + canvas.height = Math.floor(window.innerHeight * 0.25) + canvas.style.width = window.innerWidth + 'px' + canvas.style.height = window.innerHeight + 'px' + canvas.style.imageRendering = 'pixelated' + + const ratio = canvas.width / canvas.height + + gl.viewport(0, 0, canvas.width, canvas.height) + gl.clearColor(...intToRGB(COLOR_BACKGROUND), 1) + gl.enable(gl.BLEND) + gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) + + buildPlane(ratio) + + // Upload plane buffers + gl.bindBuffer(gl.ARRAY_BUFFER, planeBuf) + gl.bufferData(gl.ARRAY_BUFFER, planeVerts, gl.DYNAMIC_DRAW) + gl.bindBuffer(gl.ARRAY_BUFFER, planeOrigBuf) + gl.bufferData(gl.ARRAY_BUFFER, planeOrig, gl.STATIC_DRAW) + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, planeIdxBuf) + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, planeIdx, gl.STATIC_DRAW) + + // Init particles if first time + if (particleData.length === 0) { + particlePos = new Float32Array(PARTICLE_COUNT * 3) + particleColor = new Float32Array(PARTICLE_COUNT * 4) + for (let i = 0; i < PARTICLE_COUNT; i++) spawnParticle(i) + } + gl.bindBuffer(gl.ARRAY_BUFFER, particlePosBuf) + gl.bufferData(gl.ARRAY_BUFFER, particlePos, gl.DYNAMIC_DRAW) + gl.bindBuffer(gl.ARRAY_BUFFER, particleColorBuf) + gl.bufferData(gl.ARRAY_BUFFER, particleColor, gl.DYNAMIC_DRAW) + + // Build MVP + const proj = mat4Perspective(mat4(), degToRad(70), ratio, 0.1, 100) + let view = mat4Identity(mat4()) + view = mat4Translate(view, 0, -7.5, -15) + view = mat4RotateX(view, degToRad(33.75)) + const mvp = mat4Multiply(mat4(), proj, view) + + gl.useProgram(planeProg) + gl.uniformMatrix4fv(uMVPPlane, false, mvp) + gl.uniform3f(uFogColorPlane, ...intToRGB(COLOR_BACKGROUND)) + gl.uniform1f(uFogNearPlane, 2) + gl.uniform1f(uFogFarPlane, 22) + + gl.useProgram(particleProg) + gl.uniformMatrix4fv(uMVPParticle, false, mvp) + gl.uniform3f(uFogColorParticle, ...intToRGB(COLOR_BACKGROUND)) + gl.uniform1f(uFogNearParticle, 6) + gl.uniform1f(uFogFarParticle, 22) + } + + function updatePlane() { + for (let i = 0; i < planeVerts.length; i += 3) { + const x = planeOrig[i], z = planeOrig[i + 2] + const dist = Math.sqrt(x * x + z * z) + planeVerts[i] = x + planeVerts[i + 1] = Math.sin(dist * 0.5 - time) * 0.5 + (-Math.exp(-dist * 0.1) * 3.5) + planeVerts[i + 2] = z + } + gl.bindBuffer(gl.ARRAY_BUFFER, planeBuf) + gl.bufferSubData(gl.ARRAY_BUFFER, 0, planeVerts) + } + + function updateParticles(delta) { + for (let i = 0; i < PARTICLE_COUNT; i++) { + const p = particleData[i] + p.life -= delta + if (p.life <= 0) { spawnParticle(i); continue } + const t = p.life / p.maxLife + p.x += p.vx * delta * 20 + p.y += p.vy * delta * 20 + p.z += p.vz * delta * 20 + const pi = i * 3 + particlePos[pi] = p.x; particlePos[pi + 1] = p.y; particlePos[pi + 2] = p.z + particleColor[i * 4 + 3] = Math.min(t * 1.2, 1) + } + gl.bindBuffer(gl.ARRAY_BUFFER, particlePosBuf) + gl.bufferSubData(gl.ARRAY_BUFFER, 0, particlePos) + gl.bindBuffer(gl.ARRAY_BUFFER, particleColorBuf) + gl.bufferSubData(gl.ARRAY_BUFFER, 0, particleColor) + } + + function drawPlane() { + gl.useProgram(planeProg) + gl.uniform1f(uTimePlane, time) + + const aPos = gl.getAttribLocation(planeProg, 'aPosition') + gl.bindBuffer(gl.ARRAY_BUFFER, planeBuf) + gl.enableVertexAttribArray(aPos) + gl.vertexAttribPointer(aPos, 3, gl.FLOAT, false, 0, 0) + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, planeIdxBuf) + gl.drawElements(gl.LINES, planeIdx.length, gl.UNSIGNED_SHORT, 0) + } + + function drawParticles() { + gl.useProgram(particleProg) + + const aPos = gl.getAttribLocation(particleProg, 'aPosition') + const aCol = gl.getAttribLocation(particleProg, 'aColor') + + gl.bindBuffer(gl.ARRAY_BUFFER, particlePosBuf) + gl.enableVertexAttribArray(aPos) + gl.vertexAttribPointer(aPos, 3, gl.FLOAT, false, 0, 0) + + gl.bindBuffer(gl.ARRAY_BUFFER, particleColorBuf) + gl.enableVertexAttribArray(aCol) + gl.vertexAttribPointer(aCol, 4, gl.FLOAT, false, 0, 0) + + gl.drawArrays(gl.POINTS, 0, PARTICLE_COUNT) + } + + function animate(now) { + requestAnimationFrame(animate) + if (now - lastFrame < FRAME_TIME) return + const delta = (now - lastTime) * 0.00008 || 0 + lastFrame = now; lastTime = now; time += delta + gl.clear(gl.COLOR_BUFFER_BIT) + updatePlane() + updateParticles(delta) + drawPlane() + drawParticles() + } + + // --- Bootstrap --- + canvas = document.createElement('canvas') + gl = canvas.getContext('webgl') + + planeProg = createProgram(PLANE_VERT, PLANE_FRAG) + particleProg = createProgram(PARTICLE_VERT, PARTICLE_FRAG) + + planeBuf = gl.createBuffer() + planeOrigBuf = gl.createBuffer() + planeIdxBuf = gl.createBuffer() + particlePosBuf = gl.createBuffer() + particleColorBuf = gl.createBuffer() + + uTimePlane = gl.getUniformLocation(planeProg, 'uTime') + uMVPPlane = gl.getUniformLocation(planeProg, 'uMVP') + uFogColorPlane = gl.getUniformLocation(planeProg, 'uFogColor') + uFogNearPlane = gl.getUniformLocation(planeProg, 'uFogNear') + uFogFarPlane = gl.getUniformLocation(planeProg, 'uFogFar') + uMVPParticle = gl.getUniformLocation(particleProg, 'uMVP') + uFogColorParticle = gl.getUniformLocation(particleProg, 'uFogColor') + uFogNearParticle = gl.getUniformLocation(particleProg, 'uFogNear') + uFogFarParticle = gl.getUniformLocation(particleProg, 'uFogFar') + + if (window.outerWidth >= 1024) { + window.addEventListener('resize', init) + init() + animate(0) + } else { + init() + } + + return canvas +})()) diff --git a/pancakz-v2-crossroads/public/blog/scripts/foreground.js b/pancakz-v2-crossroads/public/blog/scripts/foreground.js new file mode 100644 index 0000000..846d440 --- /dev/null +++ b/pancakz-v2-crossroads/public/blog/scripts/foreground.js @@ -0,0 +1,344 @@ +(() => { + const encodeSVG /**/ = svg => "data:image/svg+xml;base64," + btoa(svg) + const formatDate /**/ = str => new Date(str).toDateString().slice(4).toUpperCase() + const icons = { + // NOTE: External Images should have the version parameter appended to them. + // e.g. /public/.../image.png?v=${dataVersion} + diamond_fill: /**/ encodeSVG(``), + diamond_empty: /**/ encodeSVG(``), + icon_cross: /**/ encodeSVG(``), + icon_rss: /**/ encodeSVG(``), + icon_top: /**/ encodeSVG(``), + tags_development: /**/ encodeSVG(``), + tags_personal: /**/ encodeSVG(``), + author_bakonpancakz: /**/ `data:image/gif;base64,R0lGODlhRABOAPAAAAAAAMDAwCH5BAUKAAAALAAAAABEAE4AAAL/hI+pF+0P45p0uQqi3hD79CjcSF6fZzLlyp1iCrKy5KphPOe3SyP6D0N1fMBioGYxKpFE5ZKZcTqR0urxZM0Ks9Utd1r5WimksFgzKWNy5FHavZ61W0m6eeXt4TYfVp9fBxhX8of2AjeoVrjTZHenmNcQKPiIGHm1RzkHmRhkQHhp2Mlo47hpeUr66TeJV6kadaaZCSurdSjVmIsLtjrG++TbBQzUamT887arWxQqR1s8qkOcLM0GXR0rWRqNbZvN/N3NLd7sXf4cjn59vg7a7o4qHJ+uTs85f+8Krz/E3+9JG0B8AgeaymdQlL2EnhgSdCivIMSAE2dJrIgMI7mKPow4OvJICaRCkXpI+rvokdpEZezSTYvyj5SMjWq20ZS3D6Ggjjkz2sy05RwVPTxgQTk6NCDSpYt+Mn2aB0EBADs=`, + } + + // Parse Data from Webpage // + const dataVersion /**/ = document.querySelector("data[key='version']").value + const dataManifest /**/ = JSON.parse(document.querySelector("data[key='manifest']").value) + { + // Additional Validation // + if (!dataManifest.articles) /**/ throw "Missing Key: .articles" // Type: Metadata + if (!dataManifest.authors) /**/ throw "Missing Key: .authors" // Type: Filter + if (!dataManifest.links) /**/ throw "Missing Key: .links" // Type: Metadata + if (!dataManifest.tags) /**/ throw "Missing Key: .tags" // Type: Filter + + const lookupAuthor /**/ = new Set(dataManifest.authors.map(t => t.id)) + const lookupTags /**/ = new Set(dataManifest.tags.map(t => t.id)) + console.info("Authors IDs:", [...lookupAuthor].join(", ")) + console.info("Tags IDs: ", [...lookupTags].join(", ")) + + dataManifest.articles = dataManifest.articles.filter((a, i) => { + if (!a.date) { + console.warn(`Article '${a.id}' has no date and will be hidden.`) + return false + } + for (const t of a.tags) { + if (!lookupTags.has(t)) { + console.warn(`Article '${a.id}' has an unknown tag id (${t})`) + return false + } + } + if (!lookupAuthor.has(a.author)) { + console.warn(`Article '${a.id}' has an unknown author id (${a.author})`) + return false + } + + console.info(`Article OK: ${a.id}`) + return true + }) + } + + // Render Functions // + let articleHeader /**/ = document.querySelector("div.article-header") + let articleContent /**/ = document.querySelector("div.article-content") + let navigation /**/ = document.querySelector("nav.section-navigation") + let listArticles /**/ = document.querySelector("div.article-list") + let listChapters /**/ = null + + function updateNavigation() { + + function templateLink(link, name, description, icon) { + const image = icon.startsWith("script:") + ? icons[icon.slice(7)] + : icon // use uri + const html = ` + +
+

${name}

+

${description}

+
+
+
+ Icon for ${name} +
+
+ ` + return html + } + + function templateList(name) { + let htmlKey /**/ = name.toLocaleLowerCase() + let dataKey /**/ = `blog_togglestate_${htmlKey}` + let result /**/ = localStorage.getItem(dataKey) + let active /**/ = (result === null) ? true : (result === "true") + + // Create Toggle Buttons // + navigation.insertAdjacentHTML("beforeend", ` + + + `) + const list /**/ = navigation.querySelector(`div.nav-list#${htmlKey}`) + const header /**/ = navigation.querySelector(`button.nav-header[for="${htmlKey}"]`) + const icon /**/ = header.querySelector("img") + + function update() { + localStorage.setItem(dataKey, active) + list.style.display = active + ? "" // reset + : "none" + icon.src = active + ? icons.diamond_fill + : icons.diamond_empty + active + ? header.classList.add("open") + : header.classList.remove("open") + } + header.onclick = () => { + active = !active + update() + } + update() + + return list + } + + // Render Nav Links // + templateList("LINKS").innerHTML = dataManifest.links + .map(l => templateLink(l.id, l.name, l.description, l.icon)) + .join("\n") + templateList("TAGS").innerHTML = dataManifest.tags + .map(t => templateLink(`/blog/?filter[tag]=${t.id}`, t.name, t.description, t.icon)) + .join("\n") + templateList("AUTHORS").innerHTML = dataManifest.authors + .map(a => templateLink(`/blog/?filter[author]=${a.id}`, a.name, a.description, a.icon)) + .join("\n") + listChapters = templateList("CHAPTERS") + + } + updateNavigation() + + function updateArticle() { + articleContent.replaceChildren() + articleHeader.replaceChildren() + listArticles.replaceChildren() + listChapters.replaceChildren() + + const slug /**/ = new URL(window.location.href).pathname.slice("/blog/".length) + const article /**/ = dataManifest.articles.find(a => a.id == slug) + + if (article) { + + // Display Article // + document.title = `panca.kz - Blog - ${article.title}` + + // Download Article Content [ASYNC] // + fetch(`/public/blog/${slug}/content.html?v=${dataVersion}`) + .then(async resp => { + + // Insert Article Content // + // Yes, we are exploiting ourselves (safely). But I want the ability to + // implement custom elements and features to specific articles in the future. + if (!resp.ok) { + throw `Server responded with ${resp.status} ${resp.statusText}` + } + articleContent.insertAdjacentHTML("beforeend", await resp.text()) + articleContent.querySelectorAll("script").forEach(s => { + eval(s.innerHTML) + }) + + // Generate Article Chapters // + let chapterHTML = "" + for (const item of articleContent.children) { + const normalize = c => { + const v = c.textContent.toLocaleLowerCase().replaceAll(" ", "-") + c.id = v + return v + } + if (item.classList.contains("element-header")) { + chapterHTML += `${item.textContent}\n` + } + if (item.classList.contains("element-subheader")) { + chapterHTML += `${item.textContent}\n` + } + } + listChapters.innerHTML = chapterHTML + + }) + .catch(err => { + // Generic Fetch Error // + console.error("", err) + articleContent.innerHTML += ` + + ` + }) + + // Render Article Header (Metadata) // + const author /**/ = dataManifest.authors.find(a => a.id === article.author) + const tags /**/ = article.tags.map(id => dataManifest.tags.find(t => t.id === id)) + + listChapters.innerHTML += ` + + ` + articleHeader.innerHTML += ` + Banner for ${article.title} + +

+ ${article.title} +

+ +
+
+ + ${author.name} + + + ${formatDate(article.date)} + +
+
+ ${tags.map(t => `${t.name}`).join("\n")} +
+
+ ` + + } else { + + // Display Search // + document.title = `panca.kz - Blog` + + // Collect Filters and Articles // + const params = new URLSearchParams(window.location.search) + const filterTags = new Set(params + .getAll("filter[tag]") + .filter(s => dataManifest.tags.findIndex(t => t.id.localeCompare(s) === 0) > -1) + ) + const filterAuthor = new Set(params + .getAll("filter[author]") + .filter(s => dataManifest.authors.findIndex(t => t.id.localeCompare(s) === 0) > -1) + ) + const results = dataManifest.articles + .sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime()) + .filter(a => { + + // Need Requested Author // + if (filterAuthor.size > 0) { + if (!filterAuthor.has(a.author)) return false + } + + // Need Requested Tags // + if (filterTags.size > 0) { + let missedTag = false + filterTags.forEach(t => { + if (a.tags.findIndex(s => s === t) === -1) { + missedTag = true + } + }) + if (missedTag) { + return false + } + } + + return true + }) + + // Render Results // + listChapters.innerHTML += ` + + ` + listArticles.innerHTML += ` +
+

+ ${results.length} RESULT${results.length === 1 ? "" : "s"} + ${new Array(...filterTags.values()).map(s => `<TAG:${s.toUpperCase()}>`).join(" ")} + ${new Array(...filterAuthor.values()).map(s => `<AUTHOR:${s.toUpperCase()}>`).join(" ")} + + _ + +

+
+ ` + listArticles.innerHTML += results.map((a, i) => ` + +
+ Banner for ${a.title} +
+ +
+ `) + .join("\n") + } + } + updateArticle() + + + // History Overrides // + window.addEventListener("popstate", () => { + updateArticle() + }) + document.addEventListener("click", (e) => { + const link = e.target.closest("a") + if (!link) return + + const url = new URL(link.href) + + // Ignore non-blog links + if (!url.pathname.startsWith("/blog/")) return + if (url.pathname.startsWith("/blog/rss.xml")) return + + // Handle chapter links + const current = new URL(window.location.href) + if ( + url.pathname === current.pathname && + url.search === current.search && + url.hash + ) { + // Smooth scroll into section + e.preventDefault() + const target = document.querySelector(url.hash) + if (target) { + target.scrollIntoView({ behavior: "smooth" }) + } + return + } + + // Update Application + e.preventDefault() + history.pushState(null, "", url.pathname + url.search + url.hash) + updateArticle() + }) + + +})() \ No newline at end of file diff --git a/pancakz-v2-crossroads/public/blog/setting-up-an-email-server/banner_list.gif b/pancakz-v2-crossroads/public/blog/setting-up-an-email-server/banner_list.gif new file mode 100644 index 0000000..c6a40c6 Binary files /dev/null and b/pancakz-v2-crossroads/public/blog/setting-up-an-email-server/banner_list.gif differ diff --git a/pancakz-v2-crossroads/public/blog/setting-up-an-email-server/banner_main.gif b/pancakz-v2-crossroads/public/blog/setting-up-an-email-server/banner_main.gif new file mode 100644 index 0000000..c6a40c6 Binary files /dev/null and b/pancakz-v2-crossroads/public/blog/setting-up-an-email-server/banner_main.gif differ diff --git a/pancakz-v2-crossroads/public/blog/setting-up-an-email-server/content.html b/pancakz-v2-crossroads/public/blog/setting-up-an-email-server/content.html new file mode 100644 index 0000000..96d49f6 --- /dev/null +++ b/pancakz-v2-crossroads/public/blog/setting-up-an-email-server/content.html @@ -0,0 +1,80 @@ +

Introduction

+

+ If you're reading this... I haven't written the article yet :P +

+

+ Luctus montes donec mauris. Vehicula suspendisse condimentum massa fringilla at conubia. + Senectus laoreet praesent in, porttitor sollicitudin luctus orci scelerisque egestas malesuada faucibus a. + Arcu imperdiet libero imperdiet nulla libero natoque eu fusce ultricies vehicula nisi. + Torquent lacus sodales inceptos dignissim sed, mauris feugiat erat. + Phasellus at tincidunt sociosqu potenti risus aliquam non litora. + Commodo mi fermentum, id arcu dictum convallis. + Vehicula convallis, proin fames molestie potenti congue penatibus feugiat porttitor. + Habitant justo lacinia, curabitur nascetur! + Dolor nunc accumsan imperdiet penatibus? + Amet cursus faucibus dui vestibulum nascetur quam. +

+
+ +

Prerequisites

+

+ Praesent augue ligula amet nisl. Litora lectus consectetur aliquet. + Sociis iaculis dolor nostra pulvinar felis condimentum netus. + Suscipit enim habitant sed eros etiam, ut odio sed. + Fringilla quam tempus nisl natoque parturient dolor curabitur tellus. + Lacus conubia quis inceptos tristique ultricies cum consequat. + Consequat phasellus proin dolor molestie nec quam cursus mollis vel? + Eros tempor sollicitudin tortor litora nunc. + Sem scelerisque semper id ac auctor fusce quis erat imperdiet convallis donec eget! + Pellentesque tempor nunc ipsum imperdiet quam ipsum habitant feugiat. +

+ +

Hosting

+

+ Odio nibh penatibus erat sociosqu eget iaculis. Ante curabitur bibendum ligula? + Netus aliquet cursus interdum pharetra. Magnis elementum nunc luctus eu nam sit habitant etiam vestibulum in. + Lacus nisl ullamcorper molestie! Dignissim, vulputate porta pulvinar duis posuere. +

+ +

Domains

+

+ Curae; laoreet cum duis turpis, feugiat per integer. + Sit in blandit himenaeos. Penatibus fringilla imperdiet, luctus dapibus elementum. + Felis senectus pulvinar a natoque risus. +

+ +

Credentials

+

+ Mauris habitasse nulla accumsan fermentum fermentum. + Magnis amet amet risus senectus in curae;. + Elementum ac montes sagittis vivamus malesuada elementum senectus ultrices scelerisque fusce. + In nulla platea. +

+ +
+ +

Setup DNS

+

+ Nisi vitae vehicula etiam nam auctor, accumsan purus ridiculus molestie. + Ante malesuada condimentum aliquam etiam auctor arcu porttitor parturient nullam accumsan bibendum? + Vitae arcu at mattis. Volutpat himenaeos class vitae elit, luctus sociosqu semper? + Praesent taciti lobortis tortor laoreet magnis tortor sagittis porta facilisi vivamus dictum scelerisque. + Consectetur elit enim malesuada commodo proin facilisi sagittis! + Malesuada quam duis non elit himenaeos sem. + Luctus suspendisse senectus mollis aliquet aliquam pellentesque conubia condimentum suspendisse aptent litora potenti. + Curabitur sociis lacus turpis, laoreet ligula consequat luctus eu auctor auctor sagittis. + Turpis nibh feugiat lorem donec quis bibendum. + Himenaeos sapien interdum aptent. +

+ +

Setup Linux

+

+ Convallis pharetra vitae tincidunt phasellus bibendum porta, praesent dictum aliquet volutpat. + Lobortis semper eget consectetur elementum elit hendrerit natoque mauris taciti ante ac augue. + Ullamcorper viverra vestibulum vehicula nisi metus vestibulum curabitur vehicula et. + Phasellus ligula vitae posuere penatibus ullamcorper lorem phasellus metus. + Scelerisque ac lobortis gravida primis? + Lacus porttitor ullamcorper quisque viverra molestie. + Lacinia bibendum facilisi tempor cubilia felis eros! + Etiam blandit lacinia leo urna. +

\ No newline at end of file diff --git a/pancakz-v2-crossroads/public/favicon.ico b/pancakz-v2-crossroads/public/favicon.ico new file mode 100644 index 0000000..c1b2d33 Binary files /dev/null and b/pancakz-v2-crossroads/public/favicon.ico differ diff --git a/pancakz-v2-crossroads/public/fonts/poppins.css b/pancakz-v2-crossroads/public/fonts/poppins.css new file mode 100644 index 0000000..47f66cb --- /dev/null +++ b/pancakz-v2-crossroads/public/fonts/poppins.css @@ -0,0 +1,152 @@ +/* Poppins Thin */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 100; + font-display: swap; + src: url(/public/fonts/poppins/PoppinsThin.woff2); +} + +@font-face { + font-family: 'Poppins'; + font-style: italic; + font-weight: 100; + font-display: swap; + src: url(/public/fonts/poppins/PoppinsThinItalic.woff2); +} + +/* Poppins ExtraLight */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 200; + font-display: swap; + src: url(/public/fonts/poppins/PoppinsExtraLight.woff2); +} + +@font-face { + font-family: 'Poppins'; + font-style: italic; + font-weight: 200; + font-display: swap; + src: url(/public/fonts/poppins/PoppinsExtraLightItalic.woff2); +} + +/* Poppins Light */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url(/public/fonts/poppins/PoppinsLight.woff2); +} + +@font-face { + font-family: 'Poppins'; + font-style: italic; + font-weight: 300; + font-display: swap; + src: url(/public/fonts/poppins/PoppinsLightItalic.woff2); +} + +/* Poppins Regular */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(/public/fonts/poppins/PoppinsRegular.woff2); +} + +@font-face { + font-family: 'Poppins'; + font-style: italic; + font-weight: 400; + font-display: swap; + src: url(/public/fonts/poppins/PoppinsItalic.woff2); +} + +/* Poppins Medium */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url(/public/fonts/poppins/PoppinsMedium.woff2); +} + +@font-face { + font-family: 'Poppins'; + font-style: italic; + font-weight: 500; + font-display: swap; + src: url(/public/fonts/poppins/PoppinsMediumItalic.woff2); +} + +/* Poppins SemiBold */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(/public/fonts/poppins/PoppinsSemiBold.woff2); +} + +@font-face { + font-family: 'Poppins'; + font-style: italic; + font-weight: 600; + font-display: swap; + src: url(/public/fonts/poppins/PoppinsSemiBoldItalic.woff2); +} + +/* Poppins Bold */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(/public/fonts/poppins/PoppinsBold.woff2); +} + +@font-face { + font-family: 'Poppins'; + font-style: italic; + font-weight: 700; + font-display: swap; + src: url(/public/fonts/poppins/PoppinsBoldItalic.woff2); +} + +/* Poppins ExtraBold */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 800; + font-display: swap; + src: url(/public/fonts/poppins/PoppinsExtraBold.woff2); +} + +@font-face { + font-family: 'Poppins'; + font-style: italic; + font-weight: 800; + font-display: swap; + src: url(/public/fonts/poppins/PoppinsExtraBoldItalic.woff2); +} + +/* Poppins Black */ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 900; + font-display: swap; + src: url(/public/fonts/poppins/PoppinsBlack.woff2); +} + +@font-face { + font-family: 'Poppins'; + font-style: italic; + font-weight: 900; + font-display: swap; + src: url(/public/fonts/poppins/PoppinsBlackItalic.woff2); +} \ No newline at end of file diff --git a/pancakz-v2-crossroads/public/fonts/poppins/OFL.txt b/pancakz-v2-crossroads/public/fonts/poppins/OFL.txt new file mode 100644 index 0000000..da31af0 --- /dev/null +++ b/pancakz-v2-crossroads/public/fonts/poppins/OFL.txt @@ -0,0 +1,93 @@ +Copyright 2020 The Poppins Project Authors (https://github.com/itfoundry/Poppins) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://openfontlicense.org + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/pancakz-v2-crossroads/public/fonts/poppins/PoppinsBlack.woff2 b/pancakz-v2-crossroads/public/fonts/poppins/PoppinsBlack.woff2 new file mode 100644 index 0000000..2dfde80 Binary files /dev/null and b/pancakz-v2-crossroads/public/fonts/poppins/PoppinsBlack.woff2 differ diff --git a/pancakz-v2-crossroads/public/fonts/poppins/PoppinsBlackItalic.woff2 b/pancakz-v2-crossroads/public/fonts/poppins/PoppinsBlackItalic.woff2 new file mode 100644 index 0000000..c53e44b Binary files /dev/null and b/pancakz-v2-crossroads/public/fonts/poppins/PoppinsBlackItalic.woff2 differ diff --git a/pancakz-v2-crossroads/public/fonts/poppins/PoppinsBold.woff2 b/pancakz-v2-crossroads/public/fonts/poppins/PoppinsBold.woff2 new file mode 100644 index 0000000..13e0e28 Binary files /dev/null and b/pancakz-v2-crossroads/public/fonts/poppins/PoppinsBold.woff2 differ diff --git a/pancakz-v2-crossroads/public/fonts/poppins/PoppinsBoldItalic.woff2 b/pancakz-v2-crossroads/public/fonts/poppins/PoppinsBoldItalic.woff2 new file mode 100644 index 0000000..9787af0 Binary files /dev/null and b/pancakz-v2-crossroads/public/fonts/poppins/PoppinsBoldItalic.woff2 differ diff --git a/pancakz-v2-crossroads/public/fonts/poppins/PoppinsExtraBold.woff2 b/pancakz-v2-crossroads/public/fonts/poppins/PoppinsExtraBold.woff2 new file mode 100644 index 0000000..ad86d02 Binary files /dev/null and b/pancakz-v2-crossroads/public/fonts/poppins/PoppinsExtraBold.woff2 differ diff --git a/pancakz-v2-crossroads/public/fonts/poppins/PoppinsExtraBoldItalic.woff2 b/pancakz-v2-crossroads/public/fonts/poppins/PoppinsExtraBoldItalic.woff2 new file mode 100644 index 0000000..a07bab0 Binary files /dev/null and b/pancakz-v2-crossroads/public/fonts/poppins/PoppinsExtraBoldItalic.woff2 differ diff --git a/pancakz-v2-crossroads/public/fonts/poppins/PoppinsExtraLight.woff2 b/pancakz-v2-crossroads/public/fonts/poppins/PoppinsExtraLight.woff2 new file mode 100644 index 0000000..89a440b Binary files /dev/null and b/pancakz-v2-crossroads/public/fonts/poppins/PoppinsExtraLight.woff2 differ diff --git a/pancakz-v2-crossroads/public/fonts/poppins/PoppinsExtraLightItalic.woff2 b/pancakz-v2-crossroads/public/fonts/poppins/PoppinsExtraLightItalic.woff2 new file mode 100644 index 0000000..8b7c5ef Binary files /dev/null and b/pancakz-v2-crossroads/public/fonts/poppins/PoppinsExtraLightItalic.woff2 differ diff --git a/pancakz-v2-crossroads/public/fonts/poppins/PoppinsItalic.woff2 b/pancakz-v2-crossroads/public/fonts/poppins/PoppinsItalic.woff2 new file mode 100644 index 0000000..0f4fa9b Binary files /dev/null and b/pancakz-v2-crossroads/public/fonts/poppins/PoppinsItalic.woff2 differ diff --git a/pancakz-v2-crossroads/public/fonts/poppins/PoppinsLight.woff2 b/pancakz-v2-crossroads/public/fonts/poppins/PoppinsLight.woff2 new file mode 100644 index 0000000..7eba2c4 Binary files /dev/null and b/pancakz-v2-crossroads/public/fonts/poppins/PoppinsLight.woff2 differ diff --git a/pancakz-v2-crossroads/public/fonts/poppins/PoppinsLightItalic.woff2 b/pancakz-v2-crossroads/public/fonts/poppins/PoppinsLightItalic.woff2 new file mode 100644 index 0000000..5a891d4 Binary files /dev/null and b/pancakz-v2-crossroads/public/fonts/poppins/PoppinsLightItalic.woff2 differ diff --git a/pancakz-v2-crossroads/public/fonts/poppins/PoppinsMedium.woff2 b/pancakz-v2-crossroads/public/fonts/poppins/PoppinsMedium.woff2 new file mode 100644 index 0000000..406acb6 Binary files /dev/null and b/pancakz-v2-crossroads/public/fonts/poppins/PoppinsMedium.woff2 differ diff --git a/pancakz-v2-crossroads/public/fonts/poppins/PoppinsMediumItalic.woff2 b/pancakz-v2-crossroads/public/fonts/poppins/PoppinsMediumItalic.woff2 new file mode 100644 index 0000000..df0fd40 Binary files /dev/null and b/pancakz-v2-crossroads/public/fonts/poppins/PoppinsMediumItalic.woff2 differ diff --git a/pancakz-v2-crossroads/public/fonts/poppins/PoppinsRegular.woff2 b/pancakz-v2-crossroads/public/fonts/poppins/PoppinsRegular.woff2 new file mode 100644 index 0000000..964d6d2 Binary files /dev/null and b/pancakz-v2-crossroads/public/fonts/poppins/PoppinsRegular.woff2 differ diff --git a/pancakz-v2-crossroads/public/fonts/poppins/PoppinsSemiBold.woff2 b/pancakz-v2-crossroads/public/fonts/poppins/PoppinsSemiBold.woff2 new file mode 100644 index 0000000..9e4d0c0 Binary files /dev/null and b/pancakz-v2-crossroads/public/fonts/poppins/PoppinsSemiBold.woff2 differ diff --git a/pancakz-v2-crossroads/public/fonts/poppins/PoppinsSemiBoldItalic.woff2 b/pancakz-v2-crossroads/public/fonts/poppins/PoppinsSemiBoldItalic.woff2 new file mode 100644 index 0000000..acc345f Binary files /dev/null and b/pancakz-v2-crossroads/public/fonts/poppins/PoppinsSemiBoldItalic.woff2 differ diff --git a/pancakz-v2-crossroads/public/fonts/poppins/PoppinsThin.woff2 b/pancakz-v2-crossroads/public/fonts/poppins/PoppinsThin.woff2 new file mode 100644 index 0000000..f98239a Binary files /dev/null and b/pancakz-v2-crossroads/public/fonts/poppins/PoppinsThin.woff2 differ diff --git a/pancakz-v2-crossroads/public/fonts/poppins/PoppinsThinItalic.woff2 b/pancakz-v2-crossroads/public/fonts/poppins/PoppinsThinItalic.woff2 new file mode 100644 index 0000000..86ee4fd Binary files /dev/null and b/pancakz-v2-crossroads/public/fonts/poppins/PoppinsThinItalic.woff2 differ diff --git a/pancakz-v2-crossroads/public/fonts/terminus.css b/pancakz-v2-crossroads/public/fonts/terminus.css new file mode 100644 index 0000000..152e6b3 --- /dev/null +++ b/pancakz-v2-crossroads/public/fonts/terminus.css @@ -0,0 +1,33 @@ +/* Terminus Regular */ +@font-face { + font-family: 'Terminus'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(/public/fonts/terminus/TerminusRegular.woff2); +} + +@font-face { + font-family: 'Terminus'; + font-style: italic; + font-weight: 400; + font-display: swap; + src: url(/public/fonts/terminus/TerminusItalic.woff2); +} + +/* Terminus Bold */ +@font-face { + font-family: 'Terminus'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(/public/fonts/terminus/TerminusBold.woff2); +} + +@font-face { + font-family: 'Terminus'; + font-style: italic; + font-weight: 700; + font-display: swap; + src: url(/public/fonts/terminus/TerminusBoldItalic.woff2); +} \ No newline at end of file diff --git a/pancakz-v2-crossroads/public/fonts/terminus/COPYING b/pancakz-v2-crossroads/public/fonts/terminus/COPYING new file mode 100644 index 0000000..07ae98f --- /dev/null +++ b/pancakz-v2-crossroads/public/fonts/terminus/COPYING @@ -0,0 +1,97 @@ +Copyright (c) 2010 Dimitar Toshkov Zhekov, +with Reserved Font Name "Terminus Font". + +Copyright (c) 2011-2023 Tilman Blumenbach, +with Reserved Font Name "Terminus (TTF)". + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/pancakz-v2-crossroads/public/fonts/terminus/TerminusBold.woff2 b/pancakz-v2-crossroads/public/fonts/terminus/TerminusBold.woff2 new file mode 100644 index 0000000..4eea832 Binary files /dev/null and b/pancakz-v2-crossroads/public/fonts/terminus/TerminusBold.woff2 differ diff --git a/pancakz-v2-crossroads/public/fonts/terminus/TerminusBoldItalic.woff2 b/pancakz-v2-crossroads/public/fonts/terminus/TerminusBoldItalic.woff2 new file mode 100644 index 0000000..41a0858 Binary files /dev/null and b/pancakz-v2-crossroads/public/fonts/terminus/TerminusBoldItalic.woff2 differ diff --git a/pancakz-v2-crossroads/public/fonts/terminus/TerminusItalic.woff2 b/pancakz-v2-crossroads/public/fonts/terminus/TerminusItalic.woff2 new file mode 100644 index 0000000..ef74c3d Binary files /dev/null and b/pancakz-v2-crossroads/public/fonts/terminus/TerminusItalic.woff2 differ diff --git a/pancakz-v2-crossroads/public/fonts/terminus/TerminusRegular.woff2 b/pancakz-v2-crossroads/public/fonts/terminus/TerminusRegular.woff2 new file mode 100644 index 0000000..1430a36 Binary files /dev/null and b/pancakz-v2-crossroads/public/fonts/terminus/TerminusRegular.woff2 differ diff --git a/pancakz-v2-crossroads/public/home/banner.gif b/pancakz-v2-crossroads/public/home/banner.gif new file mode 100644 index 0000000..da36068 Binary files /dev/null and b/pancakz-v2-crossroads/public/home/banner.gif differ diff --git a/pancakz-v2-crossroads/public/home/barcode.gif b/pancakz-v2-crossroads/public/home/barcode.gif new file mode 100644 index 0000000..2f000f2 Binary files /dev/null and b/pancakz-v2-crossroads/public/home/barcode.gif differ diff --git a/pancakz-v2-crossroads/public/home/logo.gif b/pancakz-v2-crossroads/public/home/logo.gif new file mode 100644 index 0000000..64186c7 Binary files /dev/null and b/pancakz-v2-crossroads/public/home/logo.gif differ diff --git a/pancakz-v2-crossroads/public/home/main.css b/pancakz-v2-crossroads/public/home/main.css new file mode 100644 index 0000000..c7716df --- /dev/null +++ b/pancakz-v2-crossroads/public/home/main.css @@ -0,0 +1,130 @@ +body { + background-color: black; + padding: 0; + margin: 0; +} + +p, +a { + display: inline-block; + font-family: 'Poppins', sans-serif; + font-weight: 400; + font-size: 1em; + text-decoration: none; + line-height: 1.5em; + color: white; + padding: 0; + margin: 0; +} + +a:hover, +a:focus-visible { + text-decoration: underline; +} + +div.homepage-wrapper { + width: 1024px; + margin: auto; +} + +div.block-links { + position: relative; + display: flex; + padding: 0 8px; + z-index: 1; +} + +div.block-links a { + padding: 16px; + letter-spacing: 2px; +} + +div.block-banner { + background-size: contain; + position: relative; + width: 1024px; + height: 340px; + margin: -25px 0; +} + +div.block-banner #banner-link-picross { + position: absolute; + /* ~80px box */ + height: 23.5%; + width: 7.8%; + left: 63.75%; + top: 46.5%; + opacity: 0.5; +} + + +div.block-footer { + position: relative; + display: flex; + padding: 16px; + z-index: 1; +} + +img.footer-barcode { + height: 64px; + width: 64px; + padding: 8px 16px 8px 0; + border-right: 1px solid grey; + margin-right: 16px; + image-rendering: pixelated; +} + +div.footer-quotes { + flex-basis: 100%; + font-size: small; + min-width: 400px; + display: grid; +} + +div.footer-spacer { + flex-basis: 100%; +} + +p#footer-motd { + font-size: x-small; + padding-top: 8px; + color: grey; +} + +a#footer-logo { + width: fit-content; +} + +/* Mobile */ +@media only screen and (max-width: 600px) { + + div.homepage-wrapper { + width: 100%; + } + + div.block-links { + justify-content: space-evenly; + } + + div.block-banner { + height: 100%; + aspect-ratio: 1024 / 340; + width: 100%; + margin: 0; + } + + img.footer-barcode { + display: none; + } + + div.footer-quotes { + min-width: 0; + } + + div.block-footer { + display: grid; + padding: 0 16px; + gap: 16px; + justify-items: center; + } +} \ No newline at end of file diff --git a/pancakz-v2-crossroads/public/robots.txt b/pancakz-v2-crossroads/public/robots.txt new file mode 100644 index 0000000..9871219 --- /dev/null +++ b/pancakz-v2-crossroads/public/robots.txt @@ -0,0 +1,7 @@ +# \_/ +# ()o_o) <( beep boop ) + +Sitemap: https://panca.kz/sitemap.xml + +User-agent: * +Disallow: /public/ diff --git a/pancakz-v2-crossroads/public/secret/picross/award.css b/pancakz-v2-crossroads/public/secret/picross/award.css new file mode 100644 index 0000000..78ee37d --- /dev/null +++ b/pancakz-v2-crossroads/public/secret/picross/award.css @@ -0,0 +1,73 @@ +body { + margin: 32px; + padding: 0; +} + +/* Layout */ + +div.layout-buttons { + margin: 32px 0; +} + +div.layout-document { + position: relative; + width: 11in; + height: 8.5in; + border: 2px solid black; +} + +img.page-background { + position: absolute; + height: 100%; + width: 100%; + z-index: -1; +} + +/* Certificate */ + +span { + position: absolute; + background-color: white; + color: red; +} + +span#name { + left: 3.75in; + top: 3in; + font-size: 2em; + width: 3.5in; + text-align: center; +} + +span#cheat { + left: 3.95in; + top: 1in; + font-size: 3em; +} + +span#time { + left: 6in; + top: 4in; +} + +span#date { + left: 4.8in; + top: 3.67in; + padding: 0 32px; +} + +/* Printing Fixup */ +@media print { + @page { + size: letter landscape; + margin: 0; + } + + body { + margin: 0; + } + + .no-print { + display: none !important; + } +} \ No newline at end of file diff --git a/pancakz-v2-crossroads/public/secret/picross/award.js b/pancakz-v2-crossroads/public/secret/picross/award.js new file mode 100644 index 0000000..8f2f253 --- /dev/null +++ b/pancakz-v2-crossroads/public/secret/picross/award.js @@ -0,0 +1,26 @@ +(() => { + + // SUPER SOPHISTICATED ANTICHEAT // + const search = new URLSearchParams(document.location.search) + let field_name, field_time, field_cheat + + if (localStorage.getItem("secret_picross_complete")) { + // Normal Ending :3 + field_name = search.get("name") + field_time = search.get("time") + + } else { + // Cheater Ending... + alert("i know what you are...") + field_name = "cheater mccheater pants" + field_time = "whatever" + field_cheat = "CHEATED" + } + + document.querySelector("span#date").textContent = new Date().toDateString() + document.querySelector("span#time").textContent =field_time + document.querySelector("span#name").textContent = field_name + document.querySelector("span#cheat").textContent = field_cheat + document.querySelector("div.layout-document").style.opacity = '1' + +})() \ No newline at end of file diff --git a/pancakz-v2-crossroads/public/secret/picross/board.css b/pancakz-v2-crossroads/public/secret/picross/board.css new file mode 100644 index 0000000..ada75b1 --- /dev/null +++ b/pancakz-v2-crossroads/public/secret/picross/board.css @@ -0,0 +1,110 @@ +:root { + --transition-time: 200ms; + --animation-time: 200ms; + --color-background: #1d1e2e; + --color-text-default: #f0f0f0; + --color-text-hint: #d0d0d0; + --color-disabled: #212335; + --color-inactive: #2d2f47; + --color-active: #a1a8ff; +} + +body { + background-color: var(--color-background); + padding: 0; + margin: 0; +} + +p, +a { + display: inline-block; + color: var(--color-text-default); + font-family: 'Poppins', sans-serif; + font-size: 1em; + font-weight: normal; + padding: 0; + margin: 0; +} + +a { + border-radius: 8px; + border: 2px solid var(--color-inactive); + padding: 4px 8px; + min-width: 120px; + cursor: pointer; + margin: 0 8px; +} + +a:hover, +a:focus-visible { + border-color: var(--color-active); +} + +.text-tip { + font-size: small; +} + +.text-hidden { + color: var(--color-text-hint); +} + +/* Layout */ + +div.layout-container { + margin: auto; + width: fit-content; + padding: 32px 16px; + box-sizing: border-box; +} + +div.layout-header { + display: grid; + text-align: center; + gap: 8px; +} + +div.picross-row { + display: flex; + gap: 4px; +} + +div.layout-content { + display: grid; + gap: 4px; + padding: 32px 0; + justify-content: center; + /* visually centered */ + margin-left: -32px; +} + +p.picross-hint { + color: var(--color-text-hint); + width: 24px; + height: 24px; + line-height: 24px; + text-align: center; +} + +button.picross-button { + transition: var(--animation-time) ease-in-out background-color; + background-color: var(--color-inactive); + width: 24px; + height: 24px; + border: none; +} + +button.state-active { + background-color: var(--color-active) !important; +} + +button.state-ignore { + background-color: var(--color-disabled) !important; +} + +div.layout-footer { + text-align: center; +} + +p.layout-timer { + padding: 16px 0; +} \ No newline at end of file diff --git a/pancakz-v2-crossroads/public/secret/picross/board.js b/pancakz-v2-crossroads/public/secret/picross/board.js new file mode 100644 index 0000000..30b4496 --- /dev/null +++ b/pancakz-v2-crossroads/public/secret/picross/board.js @@ -0,0 +1,74 @@ +(() => { + const correctAnswer = 2560660350 + const soundSet = document.querySelector("audio#audio-set"); soundSet.volume = 0.5 + const soundDel = document.querySelector("audio#audio-del"); soundDel.volume = 0.5 + document. + querySelector("div.layout-content") + .addEventListener( + // Prevent annoying context menu popup whenever you miss a grid tile by 1 pixel + "contextmenu", + e => e.preventDefault() + ) + + // Setup Board // + document.querySelectorAll("button.picross-button").forEach(e => { + e.addEventListener("click", () => { + e.classList.remove("state-ignore") + e.classList.toggle("state-active") + ? soundSet.play() + : soundDel.play() + }) + e.addEventListener("contextmenu", ev => { + ev.preventDefault() + e.classList.remove("state-active") + e.classList.toggle("state-ignore") + soundDel.play() + }) + }) + + // Setup Timer // + function getTime() { + const f = s => s.toString().padStart(2, "0") + const h = Math.floor(t / 3600) + const m = Math.floor(t % 3600 / 60) + const s = Math.floor(t % 60) + return `Time Spent: ${f(h)}:${f(m)}:${f(s)}` + } + let t = 0 + const timerElement = document.querySelector("p.layout-timer") + setInterval(() => { + t++ + timerElement.textContent = getTime() + }, 1000) + + // Action: Submit // + document.querySelector("a#action-send").addEventListener("click", () => { + + // Check Answer + let givenAnswer = 0 + document.querySelectorAll('div.picross-row').forEach((childRow, rowIndex) => { + let childIndex = 0 + for (const child of childRow.children) { + if (child.nodeName === 'BUTTON') { + if (child.classList.contains('state-active')) { + givenAnswer += 1 << ((rowIndex - 3) * 9) + childIndex + } + childIndex++ + } + } + }) + if (correctAnswer !== givenAnswer) { + alert("Nope! Try Again") + return + } + + // Redirect to Certificate + localStorage.setItem("secret_picross_complete", "true") + const time = getTime() + const name = prompt("Congratulations you win! Please enter your name for your certificate:", "Anon") + window.location.assign( + `/secret/picross/award?name=${encodeURIComponent(name)}&time=${encodeURIComponent(time)}` + ) + }) + +})() \ No newline at end of file diff --git a/pancakz-v2-crossroads/public/secret/picross/del.mp3 b/pancakz-v2-crossroads/public/secret/picross/del.mp3 new file mode 100644 index 0000000..53d3c8c Binary files /dev/null and b/pancakz-v2-crossroads/public/secret/picross/del.mp3 differ diff --git a/pancakz-v2-crossroads/public/secret/picross/never_give_up.mp4 b/pancakz-v2-crossroads/public/secret/picross/never_give_up.mp4 new file mode 100644 index 0000000..24e639d Binary files /dev/null and b/pancakz-v2-crossroads/public/secret/picross/never_give_up.mp4 differ diff --git a/pancakz-v2-crossroads/public/secret/picross/set.mp3 b/pancakz-v2-crossroads/public/secret/picross/set.mp3 new file mode 100644 index 0000000..aee4f01 Binary files /dev/null and b/pancakz-v2-crossroads/public/secret/picross/set.mp3 differ diff --git a/pancakz-v2-crossroads/public/secret/picross/template.png b/pancakz-v2-crossroads/public/secret/picross/template.png new file mode 100644 index 0000000..fbb047d Binary files /dev/null and b/pancakz-v2-crossroads/public/secret/picross/template.png differ diff --git a/pancakz-v2-crossroads/public/secret/sprites/banner.gif b/pancakz-v2-crossroads/public/secret/sprites/banner.gif new file mode 100644 index 0000000..5d8b12d Binary files /dev/null and b/pancakz-v2-crossroads/public/secret/sprites/banner.gif differ diff --git a/pancakz-v2-crossroads/public/secret/sprites/main.css b/pancakz-v2-crossroads/public/secret/sprites/main.css new file mode 100644 index 0000000..a031711 --- /dev/null +++ b/pancakz-v2-crossroads/public/secret/sprites/main.css @@ -0,0 +1,94 @@ +:root { + --accent: #4d58ff; +} + +body { + background-color: black; + padding: 0; + margin: 0; +} + +a, +p { + display: inline-block; + font-family: 'Poppins', sans-serif; + line-height: 1.5em; + font-weight: 400; + color: #f0f0f0; + padding: 0 16px; + margin: 0; + text-align: justify; + box-sizing: border-box; +} + +/* Layout */ + +div.layout-section { + width: 100%; + max-width: 640px; + margin: 16px auto; + padding: 16px; + box-sizing: border-box; + display: grid; + gap: 16px; +} + +img.article-banner { + width: 100%; + image-rendering: pixelated; + aspect-ratio: 3.4; +} + +/* Effects */ + +.effect-caution { + position: relative; + border: 4px solid var(--accent); + background-color: black; + margin-bottom: 12px; + margin-right: 12px; +} + +.effect-caution::before { + content: ''; + position: absolute; + left: 0; + top: 0; + right: -16px; + bottom: -16px; + box-sizing: border-box; + filter: brightness(0.5); + background: repeating-linear-gradient(45deg, var(--accent) 0, var(--accent) 8px, black 8px, black 16px); + clip-path: polygon(calc(100% - 11px) 0, 100% 0, 100% 100%, 0 100%, 0 calc(100% - 11px), calc(100% - 11px) calc(100% - 11px)); +} + +.effect-rhombus { + position: relative; + font-weight: 500; + padding: 0 16px; + z-index: 1; + clip-path: polygon(0 0, calc(100% - 8px) 0, 100% 100%, 8px 100%); +} + +.effect-rhombus::before { + position: absolute; + content: ''; + height: 100%; + width: 100%; + top: 0; + left: 0; + box-sizing: border-box; + background: var(--accent); + z-index: -1; +} + +/* Mobile */ +@media only screen and (max-width: 600px) { + div.layout-section { + margin: 0; + } + + .effect-caution::before { + display: none; + } +} \ No newline at end of file diff --git a/pancakz-v2-crossroads/public/secret/sprites/main.js b/pancakz-v2-crossroads/public/secret/sprites/main.js new file mode 100644 index 0000000..273a8d1 --- /dev/null +++ b/pancakz-v2-crossroads/public/secret/sprites/main.js @@ -0,0 +1,69 @@ +(() => { + /** @type {HTMLAudioElement | null} */ + const soundActive = document.querySelector('audio#active') + /** @type {HTMLAudioElement | null} */ + const soundBounce = document.querySelector('audio#bounce') + /** @type {HTMLCanvasElement | null} */ + const canvas = document.querySelector('canvas#sprites') + + if (canvas && soundActive && soundBounce) { + + const RENDER_WIDTH = 256, RENDER_HEIGHT = 256, GRAVITY = 0.67, BOUNCE = 0.75, JUMP = 8, COUNT = 3 + const TEXTURE_WIDTH = 68, TEXTURE_HEIGHT = 78, TEXTURE_SCALE = 0.5 + const TEXTURE = new Image() + const SPRITES = new Array() + const OFFSET = (RENDER_WIDTH - (COUNT * (TEXTURE_WIDTH * TEXTURE_SCALE))) / COUNT + + for (let i = 0; i < COUNT; i++) { + SPRITES.push({ + x: (OFFSET / 2) + (OFFSET * i) + ((TEXTURE_WIDTH * TEXTURE_SCALE) * i), + v: 0, + y: 0 + }) + } + + const ctx = canvas.getContext('2d') + TEXTURE.src = `data:image/gif;base64,R0lGODlhRABOAPAAAAAAAFJSUiH5BAUKAAAALAAAAABEAE4AAAL/hI+pF+0P45p0uQqi3hD79CjcSF6fZzLlyp1iCrKy5KphPOe3SyP6D0N1fMBioGYxKpFE5ZKZcTqR0urxZM0Ks9Utd1r5WimksFgzKWNy5FHavZ61W0m6eeXt4TYfVp9fBxhX8of2AjeoVrjTZHenmNcQKPiIGHm1RzkHmRhkQHhp2Mlo47hpeUr66TeJV6kadaaZCSurdSjVmIsLtjrG++TbBQzUamT887arWxQqR1s8qkOcLM0GXR0rWRqNbZvN/N3NLd7sXf4cjn59vg7a7o4qHJ+uTs85f+8Krz/E3+9JG0B8AgeaymdQlL2EnhgSdCivIMSAE2dJrIgMI7mKPow4OvJICaRCkXpI+rvokdpEZezSTYvyj5SMjWq20ZS3D6Ggjjkz2sy05RwVPTxgQTk6NCDSpYt+Mn2aB0EBADs=` + canvas.style.imageRendering = 'pixelated' + canvas.style.width = `${RENDER_WIDTH}px` + canvas.style.height = `${RENDER_HEIGHT}px` + canvas.width = RENDER_WIDTH + canvas.height = RENDER_HEIGHT + soundBounce.playbackRate = 2 + soundBounce.volume = 0.5 + + canvas.addEventListener('click', () => { + for (let i = 0; i < COUNT; i++) { + SPRITES[i].v += JUMP + (Math.random() * (JUMP / 2)) + } + }) + + setInterval(() => { + ctx.clearRect(0, 0, RENDER_WIDTH, RENDER_HEIGHT) + for (let i = 0; i < SPRITES.length; i++) { + let oy = (RENDER_HEIGHT - (TEXTURE_HEIGHT * TEXTURE_SCALE)) + let s = SPRITES[i] + s.v -= GRAVITY + s.y += s.v + + if (s.y < 0) { + s.y = 0 + s.v = -s.v * BOUNCE + if (Math.abs(s.v) < 0.8) { + s.v = 0 + } else { + soundBounce.currentTime = 0 + soundBounce.play() + } + } + + ctx.drawImage(TEXTURE, s.x, + oy - s.y, + TEXTURE_WIDTH * TEXTURE_SCALE, + TEXTURE_HEIGHT * TEXTURE_SCALE + ) + } + }, 1000 / 60); + + } +})() \ No newline at end of file diff --git a/pancakz-v2-crossroads/templates/404.html b/pancakz-v2-crossroads/templates/404.html new file mode 100644 index 0000000..3fdf1f1 --- /dev/null +++ b/pancakz-v2-crossroads/templates/404.html @@ -0,0 +1,131 @@ + + + + + + + + + Page Not Found + + + + + + + + + + + + \ No newline at end of file diff --git a/pancakz-v2-crossroads/templates/blog.html b/pancakz-v2-crossroads/templates/blog.html new file mode 100644 index 0000000..af4f4ce --- /dev/null +++ b/pancakz-v2-crossroads/templates/blog.html @@ -0,0 +1,77 @@ + + + + + + + + + + + {{ if .Article }} + + + + + + + panca.kz - Blog - {{ .Article.Title }} + {{ else }} + + panca.kz - Blog + {{ end }} + + + + +
+
+
+ +
+
+
+
+
+ + +
+ +
+
+
+
+
+ +
+

+
+
+
+ +
+
+
+ +
+
+ + + + + + + + + + \ No newline at end of file diff --git a/pancakz-v2-crossroads/templates/home.html b/pancakz-v2-crossroads/templates/home.html new file mode 100644 index 0000000..692eefb --- /dev/null +++ b/pancakz-v2-crossroads/templates/home.html @@ -0,0 +1,63 @@ + + + + + + + + + panca.kz - Home + + + + + +
+ + + +
+ +
+ + + +
+ + + \ No newline at end of file diff --git a/pancakz-v2-crossroads/templates/rss.xml b/pancakz-v2-crossroads/templates/rss.xml new file mode 100644 index 0000000..c41b836 --- /dev/null +++ b/pancakz-v2-crossroads/templates/rss.xml @@ -0,0 +1,26 @@ + + + + + https://panca.kz/blog + pancakz Blog + Tech, Chunibyo & Other Delusions + Personal Blogs + en-US + teto + Copyright 2026 bakonpancakz + {{ .Date }} + + {{ range $index, $elem := .Manifest.Articles }} + + https://panca.kz/blog/{{ $elem.ID }} + https://panca.kz/blog/{{ $elem.ID}} + <![CDATA[{{ $elem.Title }}]]> + + {{ $elem.Date.UTC.Format $.RFC1123 }} + {{ range $i, $tag := $elem.Tags }} + {{ $tag }} + {{ end }} + + {{ end }} + \ No newline at end of file diff --git a/pancakz-v2-crossroads/templates/secret_picross_award.html b/pancakz-v2-crossroads/templates/secret_picross_award.html new file mode 100644 index 0000000..c959f38 --- /dev/null +++ b/pancakz-v2-crossroads/templates/secret_picross_award.html @@ -0,0 +1,32 @@ + + + + + + + + + panca.kz - Boo Picross (Secret #2) + + + + + + +
+ + +
+
+ + + + + +
+ + + + + + \ No newline at end of file diff --git a/pancakz-v2-crossroads/templates/secret_picross_board.html b/pancakz-v2-crossroads/templates/secret_picross_board.html new file mode 100644 index 0000000..ee63ef5 --- /dev/null +++ b/pancakz-v2-crossroads/templates/secret_picross_board.html @@ -0,0 +1,222 @@ + + + + + + + + + panca.kz - Boo Picross (Secret #2) + + + + + + + + + + + + + +
+ +
+

Secret Picross Challenge!

+

Complete this puzzle to prove you can do picross puzzles!

+

Controls: Left click to fill, right click to mark.

+
+ +
+ +
+

+

+

+

+

+

1

+

+

1

+

+

+

+

+
+
+

+

+

+

+

+

1

+

3

+

1

+

+

1

+

+

+
+
+

+

+

+

1

+

7

+

5

+

5

+

4

+

8

+

3

+

2

+

2

+
+
+

+

+

3

+ + + + + + + + + +
+
+

1

+

1

+

1

+ + + + + + + + + +
+
+

+

+

5

+ + + + + + + + + +
+
+

+

2

+

2

+ + + + + + + + + +
+
+

+

3

+

1

+ + + + + + + + + +
+
+

+

5

+

1

+ + + + + + + + + +
+
+

+

+

8

+ + + + + + + + + +
+
+

+

+

7

+ + + + + + + + + +
+
+

+

+

5

+ + + + + + + + + +
+
+ + + +
+ + + + + + \ No newline at end of file diff --git a/pancakz-v2-crossroads/templates/secret_sprites.html b/pancakz-v2-crossroads/templates/secret_sprites.html new file mode 100644 index 0000000..e9a1965 --- /dev/null +++ b/pancakz-v2-crossroads/templates/secret_sprites.html @@ -0,0 +1,48 @@ + + + + + + + + + panca.kz - About Sprites (Secret #1) + + + + + + + +
+

A Trip to the Zoo

+ A group of sprites +

+ Welcome to the Sprite Garden, everyone! Please do watch your step! +

+

+ This domain is inhabited by spiritual creatures known as Sprites, most likely + nicknamed for their small stature. At first glance they may seem unimpressive, + but in reality, they’re bursting with creative energy! They are the souls + of the creative, unable to properly express their artistic desires they reside here. + Under the protection of Boo, the grand entity, they are free to chase their hyperfixations + until satisfied, after which they’ll reincarnate having discovered another dream to chase. +

+

+ They’re mostly harmless, if a little mischievous! Now come along, little ones, + we have much more to see today! +

+ < Go Home +
+ + + + + + + \ No newline at end of file diff --git a/pancakz-v2-crossroads/templates/sitemap.xml b/pancakz-v2-crossroads/templates/sitemap.xml new file mode 100644 index 0000000..facc041 --- /dev/null +++ b/pancakz-v2-crossroads/templates/sitemap.xml @@ -0,0 +1,18 @@ + + + +{{ range .Locations }} + + {{ . }} + {{ $.Date }} + +{{ end }} + +{{ range .Manifest.Articles }} + + https://panca.kz/blog/{{ .ID }} + {{ .Date.UTC.Format "2006-01-02" }} + +{{ end }} + + \ No newline at end of file diff --git a/pancakz-v3-beam/.gitignore b/pancakz-v3-beam/.gitignore new file mode 100644 index 0000000..f06235c --- /dev/null +++ b/pancakz-v3-beam/.gitignore @@ -0,0 +1,2 @@ +node_modules +dist diff --git a/pancakz-v3-beam/.prettierrc b/pancakz-v3-beam/.prettierrc new file mode 100644 index 0000000..9d973d0 --- /dev/null +++ b/pancakz-v3-beam/.prettierrc @@ -0,0 +1,15 @@ +{ + "tabWidth": 4, + "useTabs": false, + "printWidth": 120, + "singleQuote": true, + "semi": false, + "endOfLine": "lf", + "arrowParens": "always", + "bracketSameLine": true, + "bracketSpacing": true, + "trailingComma": "all", + "plugins": [ + "prettier-plugin-css-order" + ] +} diff --git a/pancakz-v3-beam/application/about.html b/pancakz-v3-beam/application/about.html new file mode 100644 index 0000000..e07ddb6 --- /dev/null +++ b/pancakz-v3-beam/application/about.html @@ -0,0 +1,56 @@ + + + + + + + + + About • pancakz.net + + {{ include-tag 'style' '/include/fonts/poppins.css' }} + {{ include-tag 'style' '/include/about/main.css' }} + + + + +
+
+ +
+ < Go Home +
+ +
+ +

Notice

+

+ pancakz.net contains no references to pancakes. +

+ +

About

+

+ This website serves projects developed by bakonpancakz in their spare time. + They vary in usability and completeness but generally strive for some general level of quality. + In laymans terms: "i do what i want :P" +

+ +

Legal

+

+ Each project provides it's own Terms of Service and Privacy Policy if applicable. + If you have a legal issue please send a complaint to the email address below. +

+ +

Contact

+

+ Feel free to send any curious or businessy inquiries to my email! -> + bakon@pancakz.net +

+ +
+ +
+ + + + diff --git a/pancakz-v3-beam/application/include/about/main.css b/pancakz-v3-beam/application/include/about/main.css new file mode 100644 index 0000000..a15b554 --- /dev/null +++ b/pancakz-v3-beam/application/include/about/main.css @@ -0,0 +1,89 @@ +::-webkit-scrollbar { + width: 0; +} + +html, +body { + margin: 0; + background: black; + padding: 0; +} + +p, +a { + display: block; + margin: 0; + padding: 0; + color: white; + font-size: 1em; + line-height: 1.5em; + font-family: 'Poppins', sans-serif; +} + +a { + display: inline-block; +} + +div.background { + position: fixed; + bottom: 32px; + background-image: url('/about/banner_large.webp'); + background-size: cover; + image-rendering: pixelated; + width: 900px; + height: 600px; +} + +div.foreground { + position: relative; + backdrop-filter: blur(2px); + margin: auto; + margin-top: 32px; + width: 480px; + max-width: 100%; +} + +div.foreground div.header { + display: flex; + justify-content: space-between; + box-sizing: border-box; + margin-bottom: 16px; + border-bottom: 1px solid #fff; + padding: 8px; + width: 100%; +} + +div.foreground div.article { + width: 100%; +} + +div.foreground div.article p.header { + margin-bottom: 8px; + width: fit-content; + font-weight: 600; + font-size: large; +} + +div.foreground div.article p.content { + margin-bottom: 16px; + text-align: justify; +} + +/* Mobile */ +@media only screen and (max-width: 600px) { + div.foreground { + transform: none; + box-sizing: border-box; + margin-top: 0; + inset: 0; + padding: 16px; + width: 100%; + max-width: unset; + height: fit-content; + } + + img.background { + bottom: 10%; + left: 0; + } +} diff --git a/pancakz-v3-beam/application/include/articles/setting-up-an-email-server.html b/pancakz-v3-beam/application/include/articles/setting-up-an-email-server.html new file mode 100644 index 0000000..86be8c6 --- /dev/null +++ b/pancakz-v3-beam/application/include/articles/setting-up-an-email-server.html @@ -0,0 +1,80 @@ +

Introduction

+

+ If you're reading this... I haven't written the article yet :P +

+

+ Luctus montes donec mauris. Vehicula suspendisse condimentum massa fringilla at conubia. + Senectus laoreet praesent in, porttitor sollicitudin luctus orci scelerisque egestas malesuada faucibus a. + Arcu imperdiet libero imperdiet nulla libero natoque eu fusce ultricies vehicula nisi. + Torquent lacus sodales inceptos dignissim sed, mauris feugiat erat. + Phasellus at tincidunt sociosqu potenti risus aliquam non litora. + Commodo mi fermentum, id arcu dictum convallis. + Vehicula convallis, proin fames molestie potenti congue penatibus feugiat porttitor. + Habitant justo lacinia, curabitur nascetur! + Dolor nunc accumsan imperdiet penatibus? + Amet cursus faucibus dui vestibulum nascetur quam. +

+
+ +

Prerequisites

+

+ Praesent augue ligula amet nisl. Litora lectus consectetur aliquet. + Sociis iaculis dolor nostra pulvinar felis condimentum netus. + Suscipit enim habitant sed eros etiam, ut odio sed. + Fringilla quam tempus nisl natoque parturient dolor curabitur tellus. + Lacus conubia quis inceptos tristique ultricies cum consequat. + Consequat phasellus proin dolor molestie nec quam cursus mollis vel? + Eros tempor sollicitudin tortor litora nunc. + Sem scelerisque semper id ac auctor fusce quis erat imperdiet convallis donec eget! + Pellentesque tempor nunc ipsum imperdiet quam ipsum habitant feugiat. +

+ +

Hosting

+

+ Odio nibh penatibus erat sociosqu eget iaculis. Ante curabitur bibendum ligula? + Netus aliquet cursus interdum pharetra. Magnis elementum nunc luctus eu nam sit habitant etiam vestibulum in. + Lacus nisl ullamcorper molestie! Dignissim, vulputate porta pulvinar duis posuere. +

+ +

Domains

+

+ Curae; laoreet cum duis turpis, feugiat per integer. + Sit in blandit himenaeos. Penatibus fringilla imperdiet, luctus dapibus elementum. + Felis senectus pulvinar a natoque risus. +

+ +

Credentials

+

+ Mauris habitasse nulla accumsan fermentum fermentum. + Magnis amet amet risus senectus in curae;. + Elementum ac montes sagittis vivamus malesuada elementum senectus ultrices scelerisque fusce. + In nulla platea. +

+ +
+ +

Setup DNS

+

+ Nisi vitae vehicula etiam nam auctor, accumsan purus ridiculus molestie. + Ante malesuada condimentum aliquam etiam auctor arcu porttitor parturient nullam accumsan bibendum? + Vitae arcu at mattis. Volutpat himenaeos class vitae elit, luctus sociosqu semper? + Praesent taciti lobortis tortor laoreet magnis tortor sagittis porta facilisi vivamus dictum scelerisque. + Consectetur elit enim malesuada commodo proin facilisi sagittis! + Malesuada quam duis non elit himenaeos sem. + Luctus suspendisse senectus mollis aliquet aliquam pellentesque conubia condimentum suspendisse aptent litora potenti. + Curabitur sociis lacus turpis, laoreet ligula consequat luctus eu auctor auctor sagittis. + Turpis nibh feugiat lorem donec quis bibendum. + Himenaeos sapien interdum aptent. +

+ +

Setup Linux

+

+ Convallis pharetra vitae tincidunt phasellus bibendum porta, praesent dictum aliquet volutpat. + Lobortis semper eget consectetur elementum elit hendrerit natoque mauris taciti ante ac augue. + Ullamcorper viverra vestibulum vehicula nisi metus vestibulum curabitur vehicula et. + Phasellus ligula vitae posuere penatibus ullamcorper lorem phasellus metus. + Scelerisque ac lobortis gravida primis? + Lacus porttitor ullamcorper quisque viverra molestie. + Lacinia bibendum facilisi tempor cubilia felis eros! + Etiam blandit lacinia leo urna. +

diff --git a/pancakz-v3-beam/application/include/favicon.png b/pancakz-v3-beam/application/include/favicon.png new file mode 100644 index 0000000..3df34a0 Binary files /dev/null and b/pancakz-v3-beam/application/include/favicon.png differ diff --git a/pancakz-v3-beam/application/include/fonts/poppins.css b/pancakz-v3-beam/application/include/fonts/poppins.css new file mode 100644 index 0000000..39f8336 --- /dev/null +++ b/pancakz-v3-beam/application/include/fonts/poppins.css @@ -0,0 +1,152 @@ +/* Poppins Thin */ +@font-face { + font-style: normal; + font-weight: 100; + src: url(/fonts/poppins/PoppinsThin.woff2); + font-family: 'Poppins'; + font-display: swap; +} + +@font-face { + font-style: italic; + font-weight: 100; + src: url(/fonts/poppins/PoppinsThinItalic.woff2); + font-family: 'Poppins'; + font-display: swap; +} + +/* Poppins ExtraLight */ +@font-face { + font-style: normal; + font-weight: 200; + src: url(/fonts/poppins/PoppinsExtraLight.woff2); + font-family: 'Poppins'; + font-display: swap; +} + +@font-face { + font-style: italic; + font-weight: 200; + src: url(/fonts/poppins/PoppinsExtraLightItalic.woff2); + font-family: 'Poppins'; + font-display: swap; +} + +/* Poppins Light */ +@font-face { + font-style: normal; + font-weight: 300; + src: url(/fonts/poppins/PoppinsLight.woff2); + font-family: 'Poppins'; + font-display: swap; +} + +@font-face { + font-style: italic; + font-weight: 300; + src: url(/fonts/poppins/PoppinsLightItalic.woff2); + font-family: 'Poppins'; + font-display: swap; +} + +/* Poppins Regular */ +@font-face { + font-style: normal; + font-weight: 400; + src: url(/fonts/poppins/PoppinsRegular.woff2); + font-family: 'Poppins'; + font-display: swap; +} + +@font-face { + font-style: italic; + font-weight: 400; + src: url(/fonts/poppins/PoppinsItalic.woff2); + font-family: 'Poppins'; + font-display: swap; +} + +/* Poppins Medium */ +@font-face { + font-style: normal; + font-weight: 500; + src: url(/fonts/poppins/PoppinsMedium.woff2); + font-family: 'Poppins'; + font-display: swap; +} + +@font-face { + font-style: italic; + font-weight: 500; + src: url(/fonts/poppins/PoppinsMediumItalic.woff2); + font-family: 'Poppins'; + font-display: swap; +} + +/* Poppins SemiBold */ +@font-face { + font-style: normal; + font-weight: 600; + src: url(/fonts/poppins/PoppinsSemiBold.woff2); + font-family: 'Poppins'; + font-display: swap; +} + +@font-face { + font-style: italic; + font-weight: 600; + src: url(/fonts/poppins/PoppinsSemiBoldItalic.woff2); + font-family: 'Poppins'; + font-display: swap; +} + +/* Poppins Bold */ +@font-face { + font-style: normal; + font-weight: 700; + src: url(/fonts/poppins/PoppinsBold.woff2); + font-family: 'Poppins'; + font-display: swap; +} + +@font-face { + font-style: italic; + font-weight: 700; + src: url(/fonts/poppins/PoppinsBoldItalic.woff2); + font-family: 'Poppins'; + font-display: swap; +} + +/* Poppins ExtraBold */ +@font-face { + font-style: normal; + font-weight: 800; + src: url(/fonts/poppins/PoppinsExtraBold.woff2); + font-family: 'Poppins'; + font-display: swap; +} + +@font-face { + font-style: italic; + font-weight: 800; + src: url(/fonts/poppins/PoppinsExtraBoldItalic.woff2); + font-family: 'Poppins'; + font-display: swap; +} + +/* Poppins Black */ +@font-face { + font-style: normal; + font-weight: 900; + src: url(/fonts/poppins/PoppinsBlack.woff2); + font-family: 'Poppins'; + font-display: swap; +} + +@font-face { + font-style: italic; + font-weight: 900; + src: url(/fonts/poppins/PoppinsBlackItalic.woff2); + font-family: 'Poppins'; + font-display: swap; +} diff --git a/pancakz-v3-beam/application/include/fonts/terminus.css b/pancakz-v3-beam/application/include/fonts/terminus.css new file mode 100644 index 0000000..17473d5 --- /dev/null +++ b/pancakz-v3-beam/application/include/fonts/terminus.css @@ -0,0 +1,33 @@ +/* Terminus Regular */ +@font-face { + font-style: normal; + font-weight: 400; + src: url(/fonts/terminus/TerminusRegular.woff2); + font-family: 'Terminus'; + font-display: swap; +} + +@font-face { + font-style: italic; + font-weight: 400; + src: url(/fonts/terminus/TerminusItalic.woff2); + font-family: 'Terminus'; + font-display: swap; +} + +/* Terminus Bold */ +@font-face { + font-style: normal; + font-weight: 700; + src: url(/fonts/terminus/TerminusBold.woff2); + font-family: 'Terminus'; + font-display: swap; +} + +@font-face { + font-style: italic; + font-weight: 700; + src: url(/fonts/terminus/TerminusBoldItalic.woff2); + font-family: 'Terminus'; + font-display: swap; +} diff --git a/pancakz-v3-beam/application/include/index/logo.png b/pancakz-v3-beam/application/include/index/logo.png new file mode 100644 index 0000000..6cba1b2 Binary files /dev/null and b/pancakz-v3-beam/application/include/index/logo.png differ diff --git a/pancakz-v3-beam/application/include/index/main.css b/pancakz-v3-beam/application/include/index/main.css new file mode 100644 index 0000000..13a408d --- /dev/null +++ b/pancakz-v3-beam/application/include/index/main.css @@ -0,0 +1,173 @@ +:root { + --animation-duration: 200ms; + --color-accent: hsl(236, 100%, 80%); + --color-background: hsl(0, 0%, 0%); + --color-font-primary: hsl(0, 0%, 95%); + --color-font-secondary: hsl(0, 0%, 65%); +} + +::-webkit-scrollbar { + width: 0; +} + +html, +body { + margin: 0; + background-color: var(--color-background); + padding: 0; +} + +p, +a, +span, +button { + display: block; + transition: var(--animation-duration) ease-in-out color; + margin: 0; + border: none; + background-color: transparent; + padding: 0; + color: var(--color-font-primary); + font-style: normal; + font-weight: normal; + font-size: 1em; + line-height: 1.5em; + font-family: 'Poppins', monospace; + text-decoration: none; +} + +button:hover, +button:focus-visible, +a[href]:hover, +a[href]:focus-visible { + cursor: pointer; + color: var(--color-accent); + text-decoration: underline; +} + +div.layout-wrapper { + margin: auto; + width: 1024px; +} + +.layout-section { + display: flex; + align-items: center; + box-sizing: border-box; + width: 100%; + max-width: 1024px; + height: fit-content; +} + +div.layout-navigation { + display: flex; + margin-top: 16px; + padding: 0 32px; +} + +div.layout-navigation div.section { + display: flex; + align-items: center; + margin-top: 16px; +} + +div.layout-navigation div.section a { + padding: 0 16px; + letter-spacing: 2px; + text-align: center; + text-decoration: none; +} + +div.layout-navigation div.section span { + padding: 0 16px; + color: var(--color-font-secondary); + font-size: x-small; +} + +div.layout-navigation div.divider { + flex-basis: 100%; +} + +p.layout-message { + display: flex; + justify-content: center; + align-items: center; + gap: 4px; + width: 100%; + color: var(--color-font-secondary); + font-size: x-small; + line-height: 2em; + text-align: center; +} + +div.layout-footer { + display: flex; + gap: 16px; + padding: 0 64px; +} + +div.layout-footer img.barcode { + border-right: 1px solid var(--color-font-secondary); + padding: 8px 16px 8px 0; + image-rendering: pixelated; + width: 64px; + height: 64px; +} + +div.layout-footer div.tooltip { + display: grid; + flex-basis: 100%; + min-width: 400px; + font-size: small; +} + +div.layout-footer div.tooltip p.header { + font-weight: bold; +} +div.layout-footer div.tooltip p.description { + height: 3em; + overflow: hidden; + line-height: 1.5em; +} + +div.layout-footer div.tooltip a.redirect { + opacity: 0; + padding-top: 8px; + pointer-events: none; + color: var(--color-font-secondary); +} + +/* Mobile */ +@media only screen and (max-width: 600px) { + div.layout-wrapper { + width: 100%; + } + + div.layout-navigation { + flex-wrap: wrap; + justify-content: center; + padding: 0 16px; + } + + canvas.layout-display { + padding: 16px 0; + } + + div.layout-footer { + display: grid; + justify-items: center; + padding: 0 16px; + width: 100%; + } + + div.layout-footer div.tooltip { + min-width: 0; + } + div.layout-footer div.tooltip p.description { + height: fit-content; + } + + div.layout-footer img.barcode { + display: none; + } +} diff --git a/pancakz-v3-beam/application/include/index/main.ts b/pancakz-v3-beam/application/include/index/main.ts new file mode 100644 index 0000000..4ae62c7 --- /dev/null +++ b/pancakz-v3-beam/application/include/index/main.ts @@ -0,0 +1,391 @@ +const elemHeader = document.querySelector('p.header')! +const elemDescription = document.querySelector('p.description')! +const elemRedirect = document.querySelector('a.redirect')! + +function createImage(src: string): HTMLImageElement { + const i = document.createElement('img') + i.src = src + return i +} + +const slides = new Array<{ + image: HTMLImageElement + url?: string | null + tooltip?: string + header: string + description: string +}>({ + image: createImage('/index/slide-1.gif'), + header: 'Tech, Chunibyo & Other Delusions', + url: '/secret-picross.html', + tooltip: 'Picross', + description: + 'Welcome to my personal homepage, use the buttons at the top of the page to visit other sections of the site.', +}) + +const CODE_VERTEX = ` + attribute vec2 p; + varying vec2 uv; + void main(){ + uv = p * 0.5 + 0.5; + gl_Position = vec4(p, 0, 1); + } +` + +const CODE_SHADER = ` + precision highp float; + varying vec2 uv; + uniform vec2 res; + uniform sampler2D texA; + uniform sampler2D texB; + uniform float transition, degauss, time, barrel, scan, mask, chroma, bloom, vig, noise, flicker, jitter, bright, sat, corner; + + float rand(vec2 co){ + return fract(sin(dot(co, vec2(12.9898, 78.233))) * 43758.5453); + } + + vec2 barrelD(vec2 u, float k) { + vec2 c = u - 0.5; + return u + c * dot(c, c) * k; + } + + vec3 sampleChroma(sampler2D t, vec2 u) { + float ca = chroma * (1. + dot(u - .5, u - .5) * 2.); + float r = texture2D(t, barrelD(u + vec2(ca, 0), barrel)).r; + float g = texture2D(t, barrelD(u, barrel)).g; + float b = texture2D(t, barrelD(u - vec2(ca, 0), barrel)).b; + return vec3(r, g, b); + } + + vec3 phosphorBloom(sampler2D t, vec2 u) { + vec3 glow = vec3(0.0); + float w = 0.0; + + // two rings — tight inner glow + wide outer halo + for (int x = -4; x <= 4; x++) { + for (int y = -4; y <= 4; y++) { + vec2 off = vec2(float(x), float(y)) / res * 3.5; + vec3 s = texture2D(t, barrelD(u + off, barrel)).rgb; + + // only bright pixels contribute — threshold at 0.6 luma + float lum = dot(s, vec3(0.299, 0.587, 0.114)); + float thresh = max(lum - 0.55, 0.0) * 2.5; + s *= thresh; + + float wt = exp(-dot(vec2(x, y), vec2(x, y)) * 0.18); + glow += s * wt; + w += wt; + } + } + glow /= w; + + // wide halo pass at 3x the offset + vec3 halo = vec3(0.0); + float hw = 0.0; + for (int x = -3; x <= 3; x++) { + for (int y = -3; y <= 3; y++) { + vec2 off = vec2(float(x), float(y)) / res * 10.0; + vec3 s = texture2D(t, barrelD(u + off, barrel)).rgb; + float lum = dot(s, vec3(0.299, 0.587, 0.114)); + float thresh = max(lum - 0.7, 0.0) * 4.0; + s *= thresh; + float wt = exp(-dot(vec2(x, y), vec2(x, y)) * 0.25); + halo += s * wt; + hw += wt; + } + } + halo /= hw; + + // phosphor tint — warm yellow-green inner, cooler blue outer halo + glow *= vec3(1.1, 1.05, 0.85); + halo *= vec3(0.85, 0.95, 1.15); + + return glow * bloom + halo * bloom * 0.4; + } + + vec3 shadowMask(vec2 u) { + float px = mod(u.x * res.x, 3.); + vec3 m = vec3(step(px, 1.), step(1., px) * step(px, 2.), step(2., px)); + return mix(vec3(1.), m * 1.6 + .15, mask * .5); + } + + float scanlineW(vec2 u) { + return mix(1., max(0., sin(u.y * res.y * 3.14159)) * .5 + .5, scan); + } + + void main() { + vec2 u = uv; + u.x += sin(u.y * 200. + time * 3.) * (jitter * .5) + sin(u.y * 50. + time * 7.) * jitter; + + // degauss + vec2 centered = u - 0.5; + float dist = length(centered); + float wavefront = degauss * 0.9; + float ring = exp(-pow((dist - wavefront) * 12.0, 2.0)); + float push = ring * 0.08 * sin(degauss * 3.14159); + u += normalize(centered + 0.0001) * push; + + vec2 bd = barrelD(u, barrel); + if (bd.x < 0. || bd.x > 1. || bd.y < 0. || bd.y > 1.) { + gl_FragColor = vec4(0, 0, 0, 1); + return; + } + + vec2 cr = vec2(corner * res.y / res.x, corner); + vec2 e = smoothstep(vec2(0.), cr, bd) * smoothstep(vec2(1.), vec2(1.) - cr, bd); + if (e.x * e.y < .01) { + gl_FragColor = vec4(0, 0, 0, 1); + return; + } + + // chroma boost at ring + float ca_boost = chroma + ring * 0.03 * sin(degauss * 3.14159); + + // old texture + float rA = texture2D(texA, barrelD(u + vec2(ca_boost, 0.), barrel)).r; + float gA = texture2D(texA, barrelD(u, barrel)).g; + float bA = texture2D(texA, barrelD(u - vec2(ca_boost, 0.), barrel)).b; + + // new texture + float rB = texture2D(texB, barrelD(u + vec2(ca_boost, 0.), barrel)).r; + float gB = texture2D(texB, barrelD(u, barrel)).g; + float bB = texture2D(texB, barrelD(u - vec2(ca_boost, 0.), barrel)).b; + + // wipe: pixels closer to center than wavefront show new texture + float wipe = smoothstep(wavefront - 0.05, wavefront + 0.05, dist); + vec3 col = mix(vec3(rB, gB, bB), vec3(rA, gA, bA), wipe); + + // rainbow tint at ring + col += ring * 0.4 * vec3( + sin(degauss * 6.28 + 0.0), + sin(degauss * 6.28 + 2.09), + sin(degauss * 6.28 + 4.18) + ) * sin(degauss * 3.14159); + + vec3 bl = mix(phosphorBloom(texB, u), phosphorBloom(texA, u), wipe); + col += bl; + + + float lum = dot(col, vec3(.299, .587, .114)); + col = mix(col, bl, bloom * (lum * lum * .5 + .1)); + col *= shadowMask(bd); col *= scanlineW(bd); + + float v = 1. - dot(bd - .5, bd - .5) * vig * 2.; col *= clamp(v, 0., 1.); + float fl = 1. - flicker * .5 + flicker * sin(time * 73. + bd.y * 100.) * .5; col *= fl; + col += (rand(bd + fract(time * .1)) - .5) * noise; + col *= bright; + + float l2 = dot(col, vec3(.299, .587, .114)); col = mix(vec3(l2), col, sat); + col = pow(max(col, vec3(0.)), vec3(1. / 2.2)); + col *= e.x * e.y; + gl_FragColor = vec4(clamp(col, 0., 1.), 0); + } +` + +const canvas = document.querySelector('canvas')! +const W = canvas.clientWidth +const H = canvas.clientHeight +let degauss = 0, + noise = 0, + slideIndex = -1, + slideCounter = 0 + +canvas.width = W +canvas.height = H + +const gl = canvas.getContext('webgl')! +const program = gl.createProgram() + +function createShader(shaderType: number, shaderCode: string) { + const shader = gl.createShader(shaderType)! + gl.shaderSource(shader, shaderCode) + gl.compileShader(shader) + return shader +} + +gl.attachShader(program, createShader(gl.VERTEX_SHADER, CODE_VERTEX)) +gl.attachShader(program, createShader(gl.FRAGMENT_SHADER, CODE_SHADER)) +gl.linkProgram(program) +gl.useProgram(program) + +const bf = gl.createBuffer() +gl.bindBuffer(gl.ARRAY_BUFFER, bf) +gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW) + +const ap = gl.getAttribLocation(program, 'p') +gl.enableVertexAttribArray(ap) +gl.vertexAttribPointer(ap, 2, gl.FLOAT, false, 0, 0) + +const U = { + transition: gl.getUniformLocation(program, 'transition'), + degauss: /**/ gl.getUniformLocation(program, 'degauss'), + time: /*---*/ gl.getUniformLocation(program, 'time'), + res: /*----*/ gl.getUniformLocation(program, 'res'), + texA: /*---*/ gl.getUniformLocation(program, 'texA'), + texB: /*---*/ gl.getUniformLocation(program, 'texB'), + barrel: /*-*/ gl.getUniformLocation(program, 'barrel'), + scan: /*---*/ gl.getUniformLocation(program, 'scan'), + mask: /*---*/ gl.getUniformLocation(program, 'mask'), + chroma: /*-*/ gl.getUniformLocation(program, 'chroma'), + bloom: /*--*/ gl.getUniformLocation(program, 'bloom'), + vig: /*----*/ gl.getUniformLocation(program, 'vig'), + noise: /*--*/ gl.getUniformLocation(program, 'noise'), + flicker: /**/ gl.getUniformLocation(program, 'flicker'), + jitter: /*-*/ gl.getUniformLocation(program, 'jitter'), + bright: /*-*/ gl.getUniformLocation(program, 'bright'), + sat: /*----*/ gl.getUniformLocation(program, 'sat'), + corner: /*-*/ gl.getUniformLocation(program, 'corner'), +} + +const textureA = gl.createTexture() +const textureCanvasA = document.createElement('canvas') +const textureContextA = textureCanvasA.getContext('2d')! +{ + textureCanvasA.width = W + textureCanvasA.height = H + gl.bindTexture(gl.TEXTURE_2D, textureA) + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) +} + +const textureB = gl.createTexture() +const textureCanvasB = document.createElement('canvas') +const textureContextB = textureCanvasB.getContext('2d')! +{ + textureCanvasB.width = W + textureCanvasB.height = H + gl.bindTexture(gl.TEXTURE_2D, textureB) + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) +} + +// function renderSMPTE() { +// const canvas = textureCanvasA +// const ctx = textureContextA + +// canvas.width = W +// canvas.height = H + +// const bars = [ +// ['#c0c0c0', '#c0c000', '#00c0c0', '#00c000', '#c000c0', '#c00000', '#0000c0'], +// ['#0000c0', '#101010', '#c000c0', '#101010', '#00c0c0', '#101010', '#c0c0c0'], +// ['#001b4b', '#ffffff', '#2e006a', '#0b0b0b', '#0b0b0b', '#0b0b0b'], +// ] +// let bw = W / 7 +// bars[0].forEach((c, i) => { +// ctx.fillStyle = c +// ctx.fillRect(i * bw, 0, bw, H * 0.675) +// }) +// bars[1].forEach((c, i) => { +// ctx.fillStyle = c +// ctx.fillRect(i * bw, H * 0.675, bw, H * 0.125) +// }) +// bw = W / 6 +// bars[2].forEach((c, i) => { +// ctx.fillStyle = c +// ctx.fillRect(i * bw, H * 0.75, bw, H * 0.25) +// }) +// ctx.fillStyle = '#fff' +// ctx.fillRect(W * 0.625, H * 0.8, W * 0.25, H * 0.12) + +// ctx.font = 'bold 24px monospace' +// ctx.fillStyle = '#000' +// ctx.fillText('PLEASE STAND BY', W * 0.65, H * 0.875) + +// gl.activeTexture(gl.TEXTURE0) +// gl.bindTexture(gl.TEXTURE_2D, textureA) +// gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true) +// gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas) +// } + +function renderFrame(t: number) { + gl.uniform1f(U.time, t) + gl.uniform2f(U.res, W, H) + gl.uniform1f(U.degauss, degauss) + gl.uniform1i(U.texA, 0) + gl.uniform1i(U.texB, 1) + gl.uniform1f(U.barrel, /*-*/ 0.25) + gl.uniform1f(U.scan, /*---*/ 0.25) + gl.uniform1f(U.mask, /*---*/ 1) + gl.uniform1f(U.chroma, /*-*/ 0.0025) + gl.uniform1f(U.bloom, /*--*/ 0.5) + gl.uniform1f(U.vig, /*----*/ 1) + gl.uniform1f(U.noise, /*--*/ noise) + gl.uniform1f(U.flicker, /**/ 0.045) + gl.uniform1f(U.jitter, /*-*/ 0.00075) + gl.uniform1f(U.bright, /*-*/ 0.8) + gl.uniform1f(U.sat, /*----*/ 1.0) + gl.uniform1f(U.corner, /*-*/ 0.1) + + gl.viewport(0, 0, W, H) + gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4) + requestAnimationFrame(renderFrame) +} + +async function nextSlide(init = false) { + const duration = 1000 + const nextIndex = slideCounter++ % slides.length + if (nextIndex === slideIndex) return + slideIndex = nextIndex + + const next = slides[nextIndex] + elemHeader.textContent = next.header + elemDescription.textContent = next.description + + if (next.url) { + elemRedirect.href = next.url + elemRedirect.style.opacity = '1' + elemRedirect.style.pointerEvents = 'all' + } else { + elemRedirect.style.opacity = '0' + elemRedirect.style.pointerEvents = 'none' + } + elemRedirect.textContent = `Discover ${next.tooltip || 'More'} >>>` + + function tween(from: number, to: number, ms: number, fn: (v: number) => void) { + return new Promise((resolve) => { + const start = performance.now() + function tick() { + const t = Math.min((performance.now() - start) / ms, 1) + const e = t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t // easing + fn(from + (to - from) * e) + if (t < 1) requestAnimationFrame(tick) + else resolve() + } + requestAnimationFrame(tick) + }) + } + + textureContextB.drawImage(next.image!, 0, 0, W, H) + gl.activeTexture(gl.TEXTURE1) + gl.bindTexture(gl.TEXTURE_2D, textureB) + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true) + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, textureCanvasB) + + if (init) { + tween(0, 0.02, duration, (t) => (noise = t)) + setInterval(nextSlide, duration + 8000) + } + await tween(0, 1, duration, (t) => (degauss = t)) + + textureContextA.drawImage(next.image!, 0, 0, W, H) + gl.activeTexture(gl.TEXTURE0) + gl.bindTexture(gl.TEXTURE_2D, textureA) + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true) + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, textureCanvasA) + + degauss = 0 +} + +// Startup Sequence (Blank Screen) +slides[0].image.onload = () => { + nextSlide(true) + requestAnimationFrame(renderFrame) +} + +gl.activeTexture(gl.TEXTURE0) +gl.bindTexture(gl.TEXTURE_2D, textureA) +gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true) +gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas) diff --git a/pancakz-v3-beam/application/include/index/motd.ts b/pancakz-v3-beam/application/include/index/motd.ts new file mode 100644 index 0000000..aca9e37 --- /dev/null +++ b/pancakz-v3-beam/application/include/index/motd.ts @@ -0,0 +1,11 @@ +const m = [ + /* Sun */ 'Even God rested on the seventh day — are you treating yourself well?', + /* Mon */ "If it's been done before then you know you can do it too! And if they got close, you can get even closer!", + /* Tue */ "It's Tetris Tuesday! Play TETR.IO!", + /* Wed */ 'Bored? Read about the Nintendo 3DS system software. What, too nerdy?', + /* Thu */ "Make sure you clean your keyboard, there's so much nasty gunk in there.", + /* Fri */ 'Did you eat something sweet today? Everyone deserves a treat, especially you sweetheart!', + /* Sat */ 'Your abandoned projects miss you... Maybe give them a visit?', +] + +document.querySelector('p#motd')!.innerHTML = m[new Date().getDay()] diff --git a/pancakz-v3-beam/application/include/index/qrcode.png b/pancakz-v3-beam/application/include/index/qrcode.png new file mode 100644 index 0000000..6c01eaf Binary files /dev/null and b/pancakz-v3-beam/application/include/index/qrcode.png differ diff --git a/pancakz-v3-beam/application/include/noscript.html b/pancakz-v3-beam/application/include/noscript.html new file mode 100644 index 0000000..d6a722b --- /dev/null +++ b/pancakz-v3-beam/application/include/noscript.html @@ -0,0 +1,83 @@ + + +
+
+
+
+
+
+
+

NOTICE: JavaScript is required to view this site.

+
+
+
diff --git a/pancakz-v3-beam/application/include/not-found/main.css b/pancakz-v3-beam/application/include/not-found/main.css new file mode 100644 index 0000000..866e8a9 --- /dev/null +++ b/pancakz-v3-beam/application/include/not-found/main.css @@ -0,0 +1,74 @@ +body { + margin: 0; + background: black; + padding: 0; + overflow: hidden; +} + +body::before { + position: fixed; + mix-blend-mode: multiply; + inset: 0; + background: repeating-linear-gradient( + to bottom, + rgba(255, 0, 0, 0.5) 0px, + rgba(0, 255, 0, 0.25) 2px, + rgba(0, 0, 255, 0.5) 4px + ); + pointer-events: none; + content: ''; +} + +span, +a, +p { + vertical-align: bottom; + margin: 0; + padding: 0; + height: 1.25em; + color: #f0f0f0; + font-size: 1.25em; + line-height: 1.25em; + font-family: 'Terminus', sans-serif; +} + +span { + height: 100%; +} + +a:hover, +a:focus-visible { + text-decoration: underline; +} + +div.layout-content { + box-sizing: border-box; + padding: 16px; +} + +.animation-blink { + animation: kf-blink 500ms infinite step-start; +} + +@keyframes kf-blink { + 50% { + opacity: 0; + } +} + +.animation-scrollin { + animation: kf-scrollin 1s forwards linear; + box-sizing: border-box; + overflow: hidden; + text-wrap-mode: nowrap; +} + +@keyframes kf-scrollin { + 0% { + width: 0%; + } + + 100% { + width: 100%; + } +} diff --git a/pancakz-v3-beam/application/include/not-found/main.ts b/pancakz-v3-beam/application/include/not-found/main.ts new file mode 100644 index 0000000..7632a85 --- /dev/null +++ b/pancakz-v3-beam/application/include/not-found/main.ts @@ -0,0 +1,38 @@ +const container = document.querySelector('div.layout-content')! +const messages = [ + 'ERROR: REALITY NOT FOUND', + 'YOU HAVE FALLEN OUT OF YOUR UNIVERSE.', + '
', + 'DONT PANIC! WE CAN SENSE YOU!', + 'WE ARE BRINGING YOU INTO OURS FOR NOW.', + '
', + 'REDIRECTING IN:', + '3...', + '2...', + '1...', + '
', +] + +let timer = setInterval(tick, 1000) +let line = 0 + +function tick() { + // Render Messages + container.innerHTML = messages + .filter((_, i) => line > i) + .map((_, i) => { + const me = line - 1 === i + const styleP = me ? 'animation-scrollin' : '' + const styleS = me ? 'inline-block' : 'none' + return `

${messages[i]} _

` + }) + .join('') + + // Messages complete, redirect to homepage! + if (line === messages.length) { + window.location.replace('/') + clearInterval(timer) + } + + line++ +} diff --git a/pancakz-v3-beam/application/include/secret-picross/main.css b/pancakz-v3-beam/application/include/secret-picross/main.css new file mode 100644 index 0000000..0b9708e --- /dev/null +++ b/pancakz-v3-beam/application/include/secret-picross/main.css @@ -0,0 +1,160 @@ +:root { + --transition-time: 200ms; + --animation-time: 200ms; + --color-background: #1d1e2e; + --color-text-default: #f0f0f0; + --color-text-hint: #d0d0d0; + --color-disabled: #212335; + --color-inactive: #2d2f47; + --color-active: #a1a8ff; +} + +body { + margin: 0; + background-color: var(--color-background); + padding: 0; +} + +p, +a { + display: inline-block; + margin: 0; + padding: 0; + color: var(--color-text-default); + font-weight: normal; + font-size: 1em; + font-family: 'Poppins', sans-serif; +} + +a { + cursor: pointer; + margin: 0 8px; + border: 2px solid var(--color-inactive); + border-radius: 8px; + padding: 4px 8px; + min-width: 120px; +} + +a:hover, +a:focus-visible { + border-color: var(--color-active); +} + +.text-tip { + font-size: small; +} + +.text-hidden { + color: var(--color-text-hint); +} + +/* Layout */ + +div.layout-container { + box-sizing: border-box; + margin: auto; + padding: 32px 16px; + width: fit-content; +} + +div.layout-header { + display: grid; + gap: 8px; + text-align: center; +} + +div.picross-row { + display: flex; + gap: 4px; +} + +div.layout-content { + display: grid; + justify-content: center; + gap: 4px; + /* visually centered */ + margin-left: -32px; + padding: 32px 0; +} + +p.picross-hint { + width: 24px; + height: 24px; + color: var(--color-text-hint); + line-height: 24px; + text-align: center; +} + +button.picross-button { + transition: var(--animation-time) ease-in-out background-color; + border: none; + background-color: var(--color-inactive); + width: 24px; + height: 24px; +} + +button.state-active { + background-color: var(--color-active) !important; +} + +button.state-ignore { + background-color: var(--color-disabled) !important; +} + +div.layout-footer { + text-align: center; +} + +p.layout-timer { + padding: 16px 0; +} + +/* Certificate */ + +div.layout-document { + position: relative; + width: 11in; + height: 8.5in; + overflow: hidden; +} + +div.layout-document span { + position: absolute; + background-color: white; + color: red; +} + +div.layout-document span#name { + top: 3in; + left: 3.75in; + width: 3.5in; + font-size: 2em; + text-align: center; +} + +div.layout-document span#time { + top: 4in; + left: 6in; +} + +div.layout-document span#date { + top: 3.67in; + left: 4.8in; + padding: 0 32px; +} + +div.layout-document img#background { + width: 100%; + height: 100%; +} + +@media print { + @page { + size: letter landscape; + margin: 0; + } + + .no-print { + display: none !important; + } +} diff --git a/pancakz-v3-beam/application/include/secret-picross/main.ts b/pancakz-v3-beam/application/include/secret-picross/main.ts new file mode 100644 index 0000000..7d5ceaf --- /dev/null +++ b/pancakz-v3-beam/application/include/secret-picross/main.ts @@ -0,0 +1,72 @@ +const elemTimer = document.querySelector('p.layout-timer')! +const elemCheck = document.querySelector('a#action-send')! +const soundSet = document.querySelector('audio#audio-set')! +const soundDel = document.querySelector('audio#audio-del')! +let secondsElapsed = 0 + +function timestamp() { + const f = (s: number) => s.toString().padStart(2, '0') + const h = Math.floor(secondsElapsed / 3600) + const m = Math.floor((secondsElapsed % 3600) / 60) + const s = Math.floor(secondsElapsed % 60) + return `Time Spent: ${f(h)}:${f(m)}:${f(s)}` +} + +setInterval(() => { + secondsElapsed++ + elemTimer.textContent = timestamp() +}, 1000) + +document.querySelector('div.layout-content')!.addEventListener( + // Prevent annoying context menu popup whenever you miss a grid tile by 1 pixel + 'contextmenu', + (e) => e.preventDefault(), +) + +document.querySelectorAll('button.picross-button').forEach((e) => { + // Initialize Buttons + e.addEventListener('click', () => { + e.classList.remove('state-ignore') + e.classList.toggle('state-active') ? soundSet.play() : soundDel.play() + }) + e.addEventListener('contextmenu', (ev) => { + ev.preventDefault() + e.classList.remove('state-active') + e.classList.toggle('state-ignore') + soundDel.play() + }) +}) + +elemCheck.addEventListener('click', () => { + // Calculate Answer + let given = 0 + const rows = document.querySelectorAll('div.picross-row') + + rows.forEach((childRow, rowIndex) => { + let childIndex = 0 + for (const child of childRow.children) { + if (child.nodeName === 'BUTTON') { + if (child.classList.contains('state-active')) { + given += 1 << ((rowIndex - 3) * 9 + childIndex) + } + childIndex++ + } + } + }) + + if (given !== 2560660350) { + alert('Nope! Try Again') + return + } + + // Render Certificate + const time = timestamp() + const name = prompt('Congratulations you won! Please enter the name for your certificate:', 'Anon') + + document.querySelector('div.layout-document')!.style.display = 'block' + document.querySelector('span#date')!.textContent = new Date().toDateString() + document.querySelector('span#time')!.textContent = time + document.querySelector('span#name')!.textContent = name + print() + document.location.assign('/') +}) diff --git a/pancakz-v3-beam/application/include/secret-sprites/banner.ts b/pancakz-v3-beam/application/include/secret-sprites/banner.ts new file mode 100644 index 0000000..a087b66 --- /dev/null +++ b/pancakz-v3-beam/application/include/secret-sprites/banner.ts @@ -0,0 +1,67 @@ +const soundActive = document.querySelector('audio#active')! +const soundBounce = document.querySelector('audio#bounce')! +const canvas = document.querySelector('canvas#sprites')! + +if (canvas && soundActive && soundBounce) { + const C = { + TEXTURE_WIDTH: 68, + TEXTURE_HEIGHT: 78, + TEXTURE_SCALE: 0.5, + RENDER_WIDTH: 256, + RENDER_HEIGHT: 256, + GRAVITY: 0.67, + BOUNCE: 0.75, + JUMP: 8, + COUNT: 3, + } + const TEXTURE = new Image() + const SPRITES = new Array() + const OFFSET = (C.RENDER_WIDTH - C.COUNT * (C.TEXTURE_WIDTH * C.TEXTURE_SCALE)) / C.COUNT + + for (let i = 0; i < C.COUNT; i++) { + SPRITES.push({ + x: OFFSET / 2 + OFFSET * i + C.TEXTURE_WIDTH * C.TEXTURE_SCALE * i, + v: 0, + y: 0, + }) + } + + const ctx = canvas.getContext('2d')! + TEXTURE.src = document.querySelector('link[rel=texture')!.href + canvas.style.imageRendering = 'pixelated' + canvas.style.width = `${C.RENDER_WIDTH}px` + canvas.style.height = `${C.RENDER_HEIGHT}px` + canvas.width = C.RENDER_WIDTH + canvas.height = C.RENDER_HEIGHT + soundBounce.playbackRate = 2 + soundBounce.volume = 0.5 + + canvas.addEventListener('click', () => { + for (let i = 0; i < C.COUNT; i++) { + SPRITES[i].v += C.JUMP + Math.random() * (C.JUMP / 2) + } + }) + + setInterval(() => { + ctx.clearRect(0, 0, C.RENDER_WIDTH, C.RENDER_HEIGHT) + for (let i = 0; i < SPRITES.length; i++) { + let oy = C.RENDER_HEIGHT - C.TEXTURE_HEIGHT * C.TEXTURE_SCALE + let s = SPRITES[i] + s.v -= C.GRAVITY + s.y += s.v + + if (s.y < 0) { + s.y = 0 + s.v = -s.v * C.BOUNCE + if (Math.abs(s.v) < 0.8) { + s.v = 0 + } else { + soundBounce.currentTime = 0 + soundBounce.play() + } + } + + ctx.drawImage(TEXTURE, s.x, oy - s.y, C.TEXTURE_WIDTH * C.TEXTURE_SCALE, C.TEXTURE_HEIGHT * C.TEXTURE_SCALE) + } + }, 1000 / 60) +} diff --git a/pancakz-v3-beam/application/include/secret-sprites/main.css b/pancakz-v3-beam/application/include/secret-sprites/main.css new file mode 100644 index 0000000..a031711 --- /dev/null +++ b/pancakz-v3-beam/application/include/secret-sprites/main.css @@ -0,0 +1,94 @@ +:root { + --accent: #4d58ff; +} + +body { + background-color: black; + padding: 0; + margin: 0; +} + +a, +p { + display: inline-block; + font-family: 'Poppins', sans-serif; + line-height: 1.5em; + font-weight: 400; + color: #f0f0f0; + padding: 0 16px; + margin: 0; + text-align: justify; + box-sizing: border-box; +} + +/* Layout */ + +div.layout-section { + width: 100%; + max-width: 640px; + margin: 16px auto; + padding: 16px; + box-sizing: border-box; + display: grid; + gap: 16px; +} + +img.article-banner { + width: 100%; + image-rendering: pixelated; + aspect-ratio: 3.4; +} + +/* Effects */ + +.effect-caution { + position: relative; + border: 4px solid var(--accent); + background-color: black; + margin-bottom: 12px; + margin-right: 12px; +} + +.effect-caution::before { + content: ''; + position: absolute; + left: 0; + top: 0; + right: -16px; + bottom: -16px; + box-sizing: border-box; + filter: brightness(0.5); + background: repeating-linear-gradient(45deg, var(--accent) 0, var(--accent) 8px, black 8px, black 16px); + clip-path: polygon(calc(100% - 11px) 0, 100% 0, 100% 100%, 0 100%, 0 calc(100% - 11px), calc(100% - 11px) calc(100% - 11px)); +} + +.effect-rhombus { + position: relative; + font-weight: 500; + padding: 0 16px; + z-index: 1; + clip-path: polygon(0 0, calc(100% - 8px) 0, 100% 100%, 8px 100%); +} + +.effect-rhombus::before { + position: absolute; + content: ''; + height: 100%; + width: 100%; + top: 0; + left: 0; + box-sizing: border-box; + background: var(--accent); + z-index: -1; +} + +/* Mobile */ +@media only screen and (max-width: 600px) { + div.layout-section { + margin: 0; + } + + .effect-caution::before { + display: none; + } +} \ No newline at end of file diff --git a/pancakz-v3-beam/application/include/secret-sprites/sprite.gif b/pancakz-v3-beam/application/include/secret-sprites/sprite.gif new file mode 100644 index 0000000..95d3124 Binary files /dev/null and b/pancakz-v3-beam/application/include/secret-sprites/sprite.gif differ diff --git a/pancakz-v3-beam/application/index.html b/pancakz-v3-beam/application/index.html new file mode 100644 index 0000000..f979dd6 --- /dev/null +++ b/pancakz-v3-beam/application/index.html @@ -0,0 +1,64 @@ + + + + + + + + + + pancakz.net + + {{ include-tag 'style' '/include/fonts/poppins.css' }} + {{ include-tag 'style' '/include/index/main.css' }} + {{ include-tag 'script' '/include/index/main.ts' }} + {{ include-tag 'script' '/include/index/motd.ts' }} + + + + {{ include-tag 'noscript' '/include/noscript.html' }} + + +
+ + + + + + +
+ +

© 2026 bakonpancakz. All Rights Reserved.

+

+
+ + + + diff --git a/pancakz-v3-beam/application/not-found.html b/pancakz-v3-beam/application/not-found.html new file mode 100644 index 0000000..955d89f --- /dev/null +++ b/pancakz-v3-beam/application/not-found.html @@ -0,0 +1,27 @@ + + + + + + + + + + Lost & Found • pancakz.net + + {{ include-tag 'style' '/include/fonts/terminus.css' }} + {{ include-tag 'style' '/include/not-found/main.css' }} + {{ include-tag 'script' '/include/not-found/main.ts' }} + + + + + + + diff --git a/pancakz-v3-beam/application/public/about/banner_large.webp b/pancakz-v3-beam/application/public/about/banner_large.webp new file mode 100644 index 0000000..52c849a Binary files /dev/null and b/pancakz-v3-beam/application/public/about/banner_large.webp differ diff --git a/pancakz-v3-beam/application/public/about/banner_original.png b/pancakz-v3-beam/application/public/about/banner_original.png new file mode 100644 index 0000000..d13e515 Binary files /dev/null and b/pancakz-v3-beam/application/public/about/banner_original.png differ diff --git a/pancakz-v3-beam/application/public/fonts/poppins/LICENSE b/pancakz-v3-beam/application/public/fonts/poppins/LICENSE new file mode 100644 index 0000000..da31af0 --- /dev/null +++ b/pancakz-v3-beam/application/public/fonts/poppins/LICENSE @@ -0,0 +1,93 @@ +Copyright 2020 The Poppins Project Authors (https://github.com/itfoundry/Poppins) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://openfontlicense.org + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/pancakz-v3-beam/application/public/fonts/poppins/PoppinsBlack.woff2 b/pancakz-v3-beam/application/public/fonts/poppins/PoppinsBlack.woff2 new file mode 100644 index 0000000..2dfde80 Binary files /dev/null and b/pancakz-v3-beam/application/public/fonts/poppins/PoppinsBlack.woff2 differ diff --git a/pancakz-v3-beam/application/public/fonts/poppins/PoppinsBlackItalic.woff2 b/pancakz-v3-beam/application/public/fonts/poppins/PoppinsBlackItalic.woff2 new file mode 100644 index 0000000..c53e44b Binary files /dev/null and b/pancakz-v3-beam/application/public/fonts/poppins/PoppinsBlackItalic.woff2 differ diff --git a/pancakz-v3-beam/application/public/fonts/poppins/PoppinsBold.woff2 b/pancakz-v3-beam/application/public/fonts/poppins/PoppinsBold.woff2 new file mode 100644 index 0000000..13e0e28 Binary files /dev/null and b/pancakz-v3-beam/application/public/fonts/poppins/PoppinsBold.woff2 differ diff --git a/pancakz-v3-beam/application/public/fonts/poppins/PoppinsBoldItalic.woff2 b/pancakz-v3-beam/application/public/fonts/poppins/PoppinsBoldItalic.woff2 new file mode 100644 index 0000000..9787af0 Binary files /dev/null and b/pancakz-v3-beam/application/public/fonts/poppins/PoppinsBoldItalic.woff2 differ diff --git a/pancakz-v3-beam/application/public/fonts/poppins/PoppinsExtraBold.woff2 b/pancakz-v3-beam/application/public/fonts/poppins/PoppinsExtraBold.woff2 new file mode 100644 index 0000000..ad86d02 Binary files /dev/null and b/pancakz-v3-beam/application/public/fonts/poppins/PoppinsExtraBold.woff2 differ diff --git a/pancakz-v3-beam/application/public/fonts/poppins/PoppinsExtraBoldItalic.woff2 b/pancakz-v3-beam/application/public/fonts/poppins/PoppinsExtraBoldItalic.woff2 new file mode 100644 index 0000000..a07bab0 Binary files /dev/null and b/pancakz-v3-beam/application/public/fonts/poppins/PoppinsExtraBoldItalic.woff2 differ diff --git a/pancakz-v3-beam/application/public/fonts/poppins/PoppinsExtraLight.woff2 b/pancakz-v3-beam/application/public/fonts/poppins/PoppinsExtraLight.woff2 new file mode 100644 index 0000000..89a440b Binary files /dev/null and b/pancakz-v3-beam/application/public/fonts/poppins/PoppinsExtraLight.woff2 differ diff --git a/pancakz-v3-beam/application/public/fonts/poppins/PoppinsExtraLightItalic.woff2 b/pancakz-v3-beam/application/public/fonts/poppins/PoppinsExtraLightItalic.woff2 new file mode 100644 index 0000000..8b7c5ef Binary files /dev/null and b/pancakz-v3-beam/application/public/fonts/poppins/PoppinsExtraLightItalic.woff2 differ diff --git a/pancakz-v3-beam/application/public/fonts/poppins/PoppinsItalic.woff2 b/pancakz-v3-beam/application/public/fonts/poppins/PoppinsItalic.woff2 new file mode 100644 index 0000000..0f4fa9b Binary files /dev/null and b/pancakz-v3-beam/application/public/fonts/poppins/PoppinsItalic.woff2 differ diff --git a/pancakz-v3-beam/application/public/fonts/poppins/PoppinsLight.woff2 b/pancakz-v3-beam/application/public/fonts/poppins/PoppinsLight.woff2 new file mode 100644 index 0000000..7eba2c4 Binary files /dev/null and b/pancakz-v3-beam/application/public/fonts/poppins/PoppinsLight.woff2 differ diff --git a/pancakz-v3-beam/application/public/fonts/poppins/PoppinsLightItalic.woff2 b/pancakz-v3-beam/application/public/fonts/poppins/PoppinsLightItalic.woff2 new file mode 100644 index 0000000..5a891d4 Binary files /dev/null and b/pancakz-v3-beam/application/public/fonts/poppins/PoppinsLightItalic.woff2 differ diff --git a/pancakz-v3-beam/application/public/fonts/poppins/PoppinsMedium.woff2 b/pancakz-v3-beam/application/public/fonts/poppins/PoppinsMedium.woff2 new file mode 100644 index 0000000..406acb6 Binary files /dev/null and b/pancakz-v3-beam/application/public/fonts/poppins/PoppinsMedium.woff2 differ diff --git a/pancakz-v3-beam/application/public/fonts/poppins/PoppinsMediumItalic.woff2 b/pancakz-v3-beam/application/public/fonts/poppins/PoppinsMediumItalic.woff2 new file mode 100644 index 0000000..df0fd40 Binary files /dev/null and b/pancakz-v3-beam/application/public/fonts/poppins/PoppinsMediumItalic.woff2 differ diff --git a/pancakz-v3-beam/application/public/fonts/poppins/PoppinsRegular.woff2 b/pancakz-v3-beam/application/public/fonts/poppins/PoppinsRegular.woff2 new file mode 100644 index 0000000..964d6d2 Binary files /dev/null and b/pancakz-v3-beam/application/public/fonts/poppins/PoppinsRegular.woff2 differ diff --git a/pancakz-v3-beam/application/public/fonts/poppins/PoppinsSemiBold.woff2 b/pancakz-v3-beam/application/public/fonts/poppins/PoppinsSemiBold.woff2 new file mode 100644 index 0000000..9e4d0c0 Binary files /dev/null and b/pancakz-v3-beam/application/public/fonts/poppins/PoppinsSemiBold.woff2 differ diff --git a/pancakz-v3-beam/application/public/fonts/poppins/PoppinsSemiBoldItalic.woff2 b/pancakz-v3-beam/application/public/fonts/poppins/PoppinsSemiBoldItalic.woff2 new file mode 100644 index 0000000..acc345f Binary files /dev/null and b/pancakz-v3-beam/application/public/fonts/poppins/PoppinsSemiBoldItalic.woff2 differ diff --git a/pancakz-v3-beam/application/public/fonts/poppins/PoppinsThin.woff2 b/pancakz-v3-beam/application/public/fonts/poppins/PoppinsThin.woff2 new file mode 100644 index 0000000..f98239a Binary files /dev/null and b/pancakz-v3-beam/application/public/fonts/poppins/PoppinsThin.woff2 differ diff --git a/pancakz-v3-beam/application/public/fonts/poppins/PoppinsThinItalic.woff2 b/pancakz-v3-beam/application/public/fonts/poppins/PoppinsThinItalic.woff2 new file mode 100644 index 0000000..86ee4fd Binary files /dev/null and b/pancakz-v3-beam/application/public/fonts/poppins/PoppinsThinItalic.woff2 differ diff --git a/pancakz-v3-beam/application/public/fonts/terminus/LICENSE b/pancakz-v3-beam/application/public/fonts/terminus/LICENSE new file mode 100644 index 0000000..07ae98f --- /dev/null +++ b/pancakz-v3-beam/application/public/fonts/terminus/LICENSE @@ -0,0 +1,97 @@ +Copyright (c) 2010 Dimitar Toshkov Zhekov, +with Reserved Font Name "Terminus Font". + +Copyright (c) 2011-2023 Tilman Blumenbach, +with Reserved Font Name "Terminus (TTF)". + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/pancakz-v3-beam/application/public/fonts/terminus/TerminusBold.woff2 b/pancakz-v3-beam/application/public/fonts/terminus/TerminusBold.woff2 new file mode 100644 index 0000000..4eea832 Binary files /dev/null and b/pancakz-v3-beam/application/public/fonts/terminus/TerminusBold.woff2 differ diff --git a/pancakz-v3-beam/application/public/fonts/terminus/TerminusBoldItalic.woff2 b/pancakz-v3-beam/application/public/fonts/terminus/TerminusBoldItalic.woff2 new file mode 100644 index 0000000..41a0858 Binary files /dev/null and b/pancakz-v3-beam/application/public/fonts/terminus/TerminusBoldItalic.woff2 differ diff --git a/pancakz-v3-beam/application/public/fonts/terminus/TerminusItalic.woff2 b/pancakz-v3-beam/application/public/fonts/terminus/TerminusItalic.woff2 new file mode 100644 index 0000000..ef74c3d Binary files /dev/null and b/pancakz-v3-beam/application/public/fonts/terminus/TerminusItalic.woff2 differ diff --git a/pancakz-v3-beam/application/public/fonts/terminus/TerminusRegular.woff2 b/pancakz-v3-beam/application/public/fonts/terminus/TerminusRegular.woff2 new file mode 100644 index 0000000..1430a36 Binary files /dev/null and b/pancakz-v3-beam/application/public/fonts/terminus/TerminusRegular.woff2 differ diff --git a/pancakz-v3-beam/application/public/index/slide-1-old.gif b/pancakz-v3-beam/application/public/index/slide-1-old.gif new file mode 100644 index 0000000..166a493 Binary files /dev/null and b/pancakz-v3-beam/application/public/index/slide-1-old.gif differ diff --git a/pancakz-v3-beam/application/public/index/slide-1.gif b/pancakz-v3-beam/application/public/index/slide-1.gif new file mode 100644 index 0000000..f2b8a07 Binary files /dev/null and b/pancakz-v3-beam/application/public/index/slide-1.gif differ diff --git a/pancakz-v3-beam/application/public/robots.txt b/pancakz-v3-beam/application/public/robots.txt new file mode 100644 index 0000000..98c8383 --- /dev/null +++ b/pancakz-v3-beam/application/public/robots.txt @@ -0,0 +1,5 @@ +# \_/ +# ()o_o) <( beep boop ) + +User-agent: * +Disallow: diff --git a/pancakz-v3-beam/application/public/secret-picross/del.mp3 b/pancakz-v3-beam/application/public/secret-picross/del.mp3 new file mode 100644 index 0000000..53d3c8c Binary files /dev/null and b/pancakz-v3-beam/application/public/secret-picross/del.mp3 differ diff --git a/pancakz-v3-beam/application/public/secret-picross/set.mp3 b/pancakz-v3-beam/application/public/secret-picross/set.mp3 new file mode 100644 index 0000000..aee4f01 Binary files /dev/null and b/pancakz-v3-beam/application/public/secret-picross/set.mp3 differ diff --git a/pancakz-v3-beam/application/public/secret-picross/template.jpeg b/pancakz-v3-beam/application/public/secret-picross/template.jpeg new file mode 100644 index 0000000..f600ac6 Binary files /dev/null and b/pancakz-v3-beam/application/public/secret-picross/template.jpeg differ diff --git a/pancakz-v3-beam/application/public/secret-sprites/banner.gif b/pancakz-v3-beam/application/public/secret-sprites/banner.gif new file mode 100644 index 0000000..5d8b12d Binary files /dev/null and b/pancakz-v3-beam/application/public/secret-sprites/banner.gif differ diff --git a/pancakz-v3-beam/application/public/secret-sprites/pop.webm b/pancakz-v3-beam/application/public/secret-sprites/pop.webm new file mode 100644 index 0000000..e1bfddb Binary files /dev/null and b/pancakz-v3-beam/application/public/secret-sprites/pop.webm differ diff --git a/pancakz-v3-beam/application/qr-code.html b/pancakz-v3-beam/application/qr-code.html new file mode 100644 index 0000000..4f5cef2 --- /dev/null +++ b/pancakz-v3-beam/application/qr-code.html @@ -0,0 +1,21 @@ + + + + + + + + + diff --git a/pancakz-v3-beam/application/secret-picross.html b/pancakz-v3-beam/application/secret-picross.html new file mode 100644 index 0000000..ea9e3a3 --- /dev/null +++ b/pancakz-v3-beam/application/secret-picross.html @@ -0,0 +1,226 @@ + + + + + + + + + Picross • pancakz.net + + {{ include-tag 'style' '/include/fonts/poppins.css' }} + {{ include-tag 'style' '/include/secret-picross/main.css' }} + {{ include-tag 'script' '/include/secret-picross/main.ts' }} + + + + + + + + + + +
+ +
+

Secret Picross Challenge!

+

Complete this puzzle to prove you can do picross puzzles!

+

Controls: Left click to fill, right click to mark.

+
+ +
+ +
+

+

+

+

+

+

1

+

+

1

+

+

+

+

+
+
+

+

+

+

+

+

1

+

3

+

1

+

+

1

+

+

+
+
+

+

+

+

1

+

7

+

5

+

5

+

4

+

8

+

3

+

2

+

2

+
+
+

+

+

3

+ + + + + + + + + +
+
+

1

+

1

+

1

+ + + + + + + + + +
+
+

+

+

5

+ + + + + + + + + +
+
+

+

2

+

2

+ + + + + + + + + +
+
+

+

3

+

1

+ + + + + + + + + +
+
+

+

5

+

1

+ + + + + + + + + +
+
+

+

+

8

+ + + + + + + + + +
+
+

+

+

7

+ + + + + + + + + +
+
+

+

+

5

+ + + + + + + + + +
+
+ + + + +
+ + + + + + diff --git a/pancakz-v3-beam/application/secret-sprites.html b/pancakz-v3-beam/application/secret-sprites.html new file mode 100644 index 0000000..8f750d2 --- /dev/null +++ b/pancakz-v3-beam/application/secret-sprites.html @@ -0,0 +1,50 @@ + + + + + + + + + + Sprites • pancakz.net + + {{ include-tag 'style' '/include/fonts/poppins.css' }} + {{ include-tag 'style' '/include/secret-sprites/main.css' }} + + + + + +
+

A Trip to the Zoo

+ A group of sprites +

+ Welcome to the Sprite Garden, everyone! Please do watch your step! +

+

+ This domain is inhabited by spiritual creatures known as Sprites, most likely + nicknamed for their small stature. At first glance they may seem unimpressive, + but in reality, they’re bursting with creative energy! They are the souls + of the creative, unable to properly express their artistic desires they reside here. + Under the protection of Boo, the grand entity, they are free to chase their hyperfixations + until satisfied, after which they’ll reincarnate having discovered another dream to chase. +

+

+ They’re mostly harmless, if a little mischievous! Now come along, little ones, + we have much more to see today! +

+ < Go Home +
+ + + + + + + diff --git a/pancakz-v3-beam/package-lock.json b/pancakz-v3-beam/package-lock.json new file mode 100644 index 0000000..ec01c8a --- /dev/null +++ b/pancakz-v3-beam/package-lock.json @@ -0,0 +1,2427 @@ +{ + "name": "@bakonpancakz/homepage", + "version": "2.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@bakonpancakz/homepage", + "version": "2.1.0", + "devDependencies": { + "@types/node": "^24.6.0", + "esbuild": "^0.28.0", + "html-minifier-next": "^5.2.2", + "prettier": "^3.8.1", + "prettier-plugin-css-order": "^2.2.0", + "typescript": "~5.9.3", + "vite": "^7.1.7" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.0.tgz", + "integrity": "sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.0.tgz", + "integrity": "sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.0.tgz", + "integrity": "sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.0.tgz", + "integrity": "sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.0.tgz", + "integrity": "sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.0.tgz", + "integrity": "sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.0.tgz", + "integrity": "sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.0.tgz", + "integrity": "sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.0.tgz", + "integrity": "sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.0.tgz", + "integrity": "sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.0.tgz", + "integrity": "sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.0.tgz", + "integrity": "sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.0.tgz", + "integrity": "sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.0.tgz", + "integrity": "sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.0.tgz", + "integrity": "sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.0.tgz", + "integrity": "sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.0.tgz", + "integrity": "sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.0.tgz", + "integrity": "sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.0.tgz", + "integrity": "sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.0.tgz", + "integrity": "sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.0.tgz", + "integrity": "sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.0.tgz", + "integrity": "sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.0.tgz", + "integrity": "sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.0.tgz", + "integrity": "sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.0.tgz", + "integrity": "sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.0.tgz", + "integrity": "sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.2.tgz", + "integrity": "sha512-dnlp69efPPg6Uaw2dVqzWRfAWRnYVb1XJ8CyyhIbZeaq4CA5/mLeZ1IEt9QqQxmbdvagjLIm2ZL8BxXv5lH4Yw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.2.tgz", + "integrity": "sha512-OqZTwDRDchGRHHm/hwLOL7uVPB9aUvI0am/eQuWMNyFHf5PSEQmyEeYYheA0EPPKUO/l0uigCp+iaTjoLjVoHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.2.tgz", + "integrity": "sha512-UwRE7CGpvSVEQS8gUMBe1uADWjNnVgP3Iusyda1nSRwNDCsRjnGc7w6El6WLQsXmZTbLZx9cecegumcitNfpmA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.2.tgz", + "integrity": "sha512-gjEtURKLCC5VXm1I+2i1u9OhxFsKAQJKTVB8WvDAHF+oZlq0GTVFOlTlO1q3AlCTE/DF32c16ESvfgqR7343/g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.2.tgz", + "integrity": "sha512-Bcl6CYDeAgE70cqZaMojOi/eK63h5Me97ZqAQoh77VPjMysA/4ORQBRGo3rRy45x4MzVlU9uZxs8Uwy7ZaKnBw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.2.tgz", + "integrity": "sha512-LU+TPda3mAE2QB0/Hp5VyeKJivpC6+tlOXd1VMoXV/YFMvk/MNk5iXeBfB4MQGRWyOYVJ01625vjkr0Az98OJQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.2.tgz", + "integrity": "sha512-2QxQrM+KQ7DAW4o22j+XZ6RKdxjLD7BOWTP0Bv0tmjdyhXSsr2Ul1oJDQqh9Zf5qOwTuTc7Ek83mOFaKnodPjg==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.2.tgz", + "integrity": "sha512-TbziEu2DVsTEOPif2mKWkMeDMLoYjx95oESa9fkQQK7r/Orta0gnkcDpzwufEcAO2BLBsD7mZkXGFqEdMRRwfw==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.2.tgz", + "integrity": "sha512-bO/rVDiDUuM2YfuCUwZ1t1cP+/yqjqz+Xf2VtkdppefuOFS2OSeAfgafaHNkFn0t02hEyXngZkxtGqXcXwO8Rg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.2.tgz", + "integrity": "sha512-hr26p7e93Rl0Za+JwW7EAnwAvKkehh12BU1Llm9Ykiibg4uIr2rbpxG9WCf56GuvidlTG9KiiQT/TXT1yAWxTA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.2.tgz", + "integrity": "sha512-pOjB/uSIyDt+ow3k/RcLvUAOGpysT2phDn7TTUB3n75SlIgZzM6NKAqlErPhoFU+npgY3/n+2HYIQVbF70P9/A==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.2.tgz", + "integrity": "sha512-2/w+q8jszv9Ww1c+6uJT3OwqhdmGP2/4T17cu8WuwyUuuaCDDJ2ojdyYwZzCxx0GcsZBhzi3HmH+J5pZNXnd+Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.2.tgz", + "integrity": "sha512-11+aL5vKheYgczxtPVVRhdptAM2H7fcDR5Gw4/bTcteuZBlH4oP9f5s9zYO9aGZvoGeBpqXI/9TZZihZ609wKw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.2.tgz", + "integrity": "sha512-i16fokAGK46IVZuV8LIIwMdtqhin9hfYkCh8pf8iC3QU3LpwL+1FSFGej+O7l3E/AoknL6Dclh2oTdnRMpTzFQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.2.tgz", + "integrity": "sha512-49FkKS6RGQoriDSK/6E2GkAsAuU5kETFCh7pG4yD/ylj9rKhTmO3elsnmBvRD4PgJPds5W2PkhC82aVwmUcJ7A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.2.tgz", + "integrity": "sha512-mjYNkHPfGpUR00DuM1ZZIgs64Hpf4bWcz9Z41+4Q+pgDx73UwWdAYyf6EG/lRFldmdHHzgrYyge5akFUW0D3mQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.2.tgz", + "integrity": "sha512-ALyvJz965BQk8E9Al/JDKKDLH2kfKFLTGMlgkAbbYtZuJt9LU8DW3ZoDMCtQpXAltZxwBHevXz5u+gf0yA0YoA==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.2.tgz", + "integrity": "sha512-UQjrkIdWrKI626Du8lCQ6MJp/6V1LAo2bOK9OTu4mSn8GGXIkPXk/Vsp4bLHCd9Z9Iz2OTEaokUE90VweJgIYQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.2.tgz", + "integrity": "sha512-bTsRGj6VlSdn/XD4CGyzMnzaBs9bsRxy79eTqTCBsA8TMIEky7qg48aPkvJvFe1HyzQ5oMZdg7AnVlWQSKLTnw==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.2.tgz", + "integrity": "sha512-6d4Z3534xitaA1FcMWP7mQPq5zGwBmGbhphh2DwaA1aNIXUu3KTOfwrWpbwI4/Gr0uANo7NTtaykFyO2hPuFLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.2.tgz", + "integrity": "sha512-NetAg5iO2uN7eB8zE5qrZ3CSil+7IJt4WDFLcC75Ymywq1VZVD6qJ6EvNLjZ3rEm6gB7XW5JdT60c6MN35Z85Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.2.tgz", + "integrity": "sha512-NCYhOotpgWZ5kdxCZsv6Iudx0wX8980Q/oW4pNFNihpBKsDbEA1zpkfxJGC0yugsUuyDZ7gL37dbzwhR0VI7pQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.2.tgz", + "integrity": "sha512-RXsaOqXxfoUBQoOgvmmijVxJnW2IGB0eoMO7F8FAjaj0UTywUO/luSqimWBJn04WNgUkeNhh7fs7pESXajWmkg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.2.tgz", + "integrity": "sha512-qdAzEULD+/hzObedtmV6iBpdL5TIbKVztGiK7O3/KYSf+HIzU257+MX1EXJcyIiDbMAqmbwaufcYPvyRryeZtA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.2.tgz", + "integrity": "sha512-Nd/SgG27WoA9e+/TdK74KnHz852TLa94ovOYySo/yMPuTmpckK/jIF2jSwS3g7ELSKXK13/cVdmg1Z/DaCWKxA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.12.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.2.tgz", + "integrity": "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true, + "license": "ISC" + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/commander": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz", + "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/css-declaration-sorter": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-7.4.0.tgz", + "integrity": "sha512-LTuzjPoyA2vMGKKcaOqKSp7Ub2eGrNfKiZH4LpezxpNrsICGCSFvsQOI29psISxNZtaXibkC2CXzrQ5enMeGGw==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.0.9" + } + }, + "node_modules/css-select": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz", + "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdn-data": "2.27.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/csso": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "css-tree": "~2.2.0" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/esbuild": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.0.tgz", + "integrity": "sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.0", + "@esbuild/android-arm": "0.28.0", + "@esbuild/android-arm64": "0.28.0", + "@esbuild/android-x64": "0.28.0", + "@esbuild/darwin-arm64": "0.28.0", + "@esbuild/darwin-x64": "0.28.0", + "@esbuild/freebsd-arm64": "0.28.0", + "@esbuild/freebsd-x64": "0.28.0", + "@esbuild/linux-arm": "0.28.0", + "@esbuild/linux-arm64": "0.28.0", + "@esbuild/linux-ia32": "0.28.0", + "@esbuild/linux-loong64": "0.28.0", + "@esbuild/linux-mips64el": "0.28.0", + "@esbuild/linux-ppc64": "0.28.0", + "@esbuild/linux-riscv64": "0.28.0", + "@esbuild/linux-s390x": "0.28.0", + "@esbuild/linux-x64": "0.28.0", + "@esbuild/netbsd-arm64": "0.28.0", + "@esbuild/netbsd-x64": "0.28.0", + "@esbuild/openbsd-arm64": "0.28.0", + "@esbuild/openbsd-x64": "0.28.0", + "@esbuild/openharmony-arm64": "0.28.0", + "@esbuild/sunos-x64": "0.28.0", + "@esbuild/win32-arm64": "0.28.0", + "@esbuild/win32-ia32": "0.28.0", + "@esbuild/win32-x64": "0.28.0" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/html-minifier-next": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/html-minifier-next/-/html-minifier-next-5.2.2.tgz", + "integrity": "sha512-oJ9TWgUuLg/7RZeJBQ2JxtG3iCipqu2z4XJjwhy6zYOskK9xCBXoUjHnXNqdohQeiUoDCmcjnrLYc87JmfvXCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "commander": "^14.0.2", + "entities": "^7.0.1", + "lightningcss": "^1.32.0", + "svgo": "^4.0.1", + "terser": "^5.46.0" + }, + "bin": { + "html-minifier-next": "cli.js" + }, + "funding": { + "url": "https://github.com/j9t/html-minifier-next?sponsor=1" + }, + "peerDependencies": { + "@swc/core": "^1.15.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + } + } + }, + "node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/mdn-data": { + "version": "2.27.1", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz", + "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.10", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.10.tgz", + "integrity": "sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-less": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-less/-/postcss-less-6.0.0.tgz", + "integrity": "sha512-FPX16mQLyEjLzEuuJtxA8X3ejDLNGGEG503d2YGZR5Ask1SpDN8KmZUMpzCvyalWRywAn1n1VOA5dcqfCLo5rg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "postcss": "^8.3.5" + } + }, + "node_modules/postcss-scss": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-4.0.9.tgz", + "integrity": "sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss-scss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.4.29" + } + }, + "node_modules/prettier": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.3.tgz", + "integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-plugin-css-order": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/prettier-plugin-css-order/-/prettier-plugin-css-order-2.2.0.tgz", + "integrity": "sha512-GCkwEgQ2roT7le+zpUFQThPDO4x5EXcZmY9Rj6rvO++I/nATTGBWdZdsooha/BlvIBbZclJzXsgJdlKWrys9+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "css-declaration-sorter": "^7.3.0", + "postcss-less": "^6.0.0", + "postcss-scss": "^4.0.9" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "prettier": "3.x" + } + }, + "node_modules/rollup": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.2.tgz", + "integrity": "sha512-J9qZyW++QK/09NyN/zeO0dG/1GdGfyp9lV8ajHnRVLfo/uFsbji5mHnDgn/qYdUHyCkM2N+8VyspgZclfAh0eQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.60.2", + "@rollup/rollup-android-arm64": "4.60.2", + "@rollup/rollup-darwin-arm64": "4.60.2", + "@rollup/rollup-darwin-x64": "4.60.2", + "@rollup/rollup-freebsd-arm64": "4.60.2", + "@rollup/rollup-freebsd-x64": "4.60.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.60.2", + "@rollup/rollup-linux-arm-musleabihf": "4.60.2", + "@rollup/rollup-linux-arm64-gnu": "4.60.2", + "@rollup/rollup-linux-arm64-musl": "4.60.2", + "@rollup/rollup-linux-loong64-gnu": "4.60.2", + "@rollup/rollup-linux-loong64-musl": "4.60.2", + "@rollup/rollup-linux-ppc64-gnu": "4.60.2", + "@rollup/rollup-linux-ppc64-musl": "4.60.2", + "@rollup/rollup-linux-riscv64-gnu": "4.60.2", + "@rollup/rollup-linux-riscv64-musl": "4.60.2", + "@rollup/rollup-linux-s390x-gnu": "4.60.2", + "@rollup/rollup-linux-x64-gnu": "4.60.2", + "@rollup/rollup-linux-x64-musl": "4.60.2", + "@rollup/rollup-openbsd-x64": "4.60.2", + "@rollup/rollup-openharmony-arm64": "4.60.2", + "@rollup/rollup-win32-arm64-msvc": "4.60.2", + "@rollup/rollup-win32-ia32-msvc": "4.60.2", + "@rollup/rollup-win32-x64-gnu": "4.60.2", + "@rollup/rollup-win32-x64-msvc": "4.60.2", + "fsevents": "~2.3.2" + } + }, + "node_modules/sax": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz", + "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/svgo": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-4.0.1.tgz", + "integrity": "sha512-XDpWUOPC6FEibaLzjfe0ucaV0YrOjYotGJO1WpF0Zd+n6ZGEQUsSugaoLq9QkEZtAfQIxT42UChcssDVPP3+/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "commander": "^11.1.0", + "css-select": "^5.1.0", + "css-tree": "^3.0.1", + "css-what": "^6.1.0", + "csso": "^5.0.5", + "picocolors": "^1.1.1", + "sax": "^1.5.0" + }, + "bin": { + "svgo": "bin/svgo.js" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/svgo" + } + }, + "node_modules/svgo/node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/terser": { + "version": "5.46.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.1.tgz", + "integrity": "sha512-vzCjQO/rgUuK9sf8VJZvjqiqiHFaZLnOiimmUuOKODxWL8mm/xua7viT7aqX7dgPY60otQjUotzFMmCB4VdmqQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.15.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", + "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.2.tgz", + "integrity": "sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.27.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/@esbuild/aix-ppc64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz", + "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/android-arm": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz", + "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/android-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz", + "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/android-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz", + "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz", + "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz", + "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz", + "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz", + "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz", + "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz", + "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ia32": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz", + "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-loong64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz", + "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-mips64el": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz", + "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ppc64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz", + "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-riscv64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz", + "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-s390x": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz", + "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz", + "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz", + "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/netbsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz", + "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz", + "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/openbsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz", + "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz", + "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/sunos-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz", + "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz", + "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-ia32": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz", + "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz", + "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/esbuild": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", + "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.7", + "@esbuild/android-arm": "0.27.7", + "@esbuild/android-arm64": "0.27.7", + "@esbuild/android-x64": "0.27.7", + "@esbuild/darwin-arm64": "0.27.7", + "@esbuild/darwin-x64": "0.27.7", + "@esbuild/freebsd-arm64": "0.27.7", + "@esbuild/freebsd-x64": "0.27.7", + "@esbuild/linux-arm": "0.27.7", + "@esbuild/linux-arm64": "0.27.7", + "@esbuild/linux-ia32": "0.27.7", + "@esbuild/linux-loong64": "0.27.7", + "@esbuild/linux-mips64el": "0.27.7", + "@esbuild/linux-ppc64": "0.27.7", + "@esbuild/linux-riscv64": "0.27.7", + "@esbuild/linux-s390x": "0.27.7", + "@esbuild/linux-x64": "0.27.7", + "@esbuild/netbsd-arm64": "0.27.7", + "@esbuild/netbsd-x64": "0.27.7", + "@esbuild/openbsd-arm64": "0.27.7", + "@esbuild/openbsd-x64": "0.27.7", + "@esbuild/openharmony-arm64": "0.27.7", + "@esbuild/sunos-x64": "0.27.7", + "@esbuild/win32-arm64": "0.27.7", + "@esbuild/win32-ia32": "0.27.7", + "@esbuild/win32-x64": "0.27.7" + } + } + } +} diff --git a/pancakz-v3-beam/package.json b/pancakz-v3-beam/package.json new file mode 100644 index 0000000..6d8dcaa --- /dev/null +++ b/pancakz-v3-beam/package.json @@ -0,0 +1,20 @@ +{ + "private": true, + "name": "@bakonpancakz/homepage", + "version": "2.1.0", + "type": "module", + "scripts": { + "dev": "npx vite --host", + "build": "npx tsc --noEmit -p tsconfig.app.json && npx vite build", + "format": "npx prettier --write **/*.tsx **/*.ts **/*.js **/*.css" + }, + "devDependencies": { + "@types/node": "^24.6.0", + "esbuild": "^0.28.0", + "html-minifier-next": "^5.2.2", + "prettier": "^3.8.1", + "prettier-plugin-css-order": "^2.2.0", + "typescript": "~5.9.3", + "vite": "^7.1.7" + } +} diff --git a/pancakz-v3-beam/tsconfig.app.json b/pancakz-v3-beam/tsconfig.app.json new file mode 100644 index 0000000..923b8d7 --- /dev/null +++ b/pancakz-v3-beam/tsconfig.app.json @@ -0,0 +1,40 @@ +{ + "compilerOptions": { + "target": "es2023", + "module": "esnext", + "lib": [ + "ES2023", + "DOM", + "DOM.Iterable" + ], + "types": [ + "vite/client" + ], + "skipLibCheck": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "moduleDetection": "force", + "noEmit": true, + "strict": true, + "alwaysStrict": true, + "useUnknownInCatchVariables": true, + "noImplicitAny": true, + "noImplicitOverride": true, + "noImplicitThis": true, + "strictPropertyInitialization": true, + "strictBindCallApply": true, + "strictBuiltinIteratorReturn": true, + "strictFunctionTypes": true, + "strictNullChecks": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true, + "exactOptionalPropertyTypes": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + }, + "include": [ + "application/include" + ] +} diff --git a/pancakz-v3-beam/tsconfig.json b/pancakz-v3-beam/tsconfig.json new file mode 100644 index 0000000..41ccf0f --- /dev/null +++ b/pancakz-v3-beam/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.node.json" + } + ] +} diff --git a/pancakz-v3-beam/tsconfig.node.json b/pancakz-v3-beam/tsconfig.node.json new file mode 100644 index 0000000..ab87871 --- /dev/null +++ b/pancakz-v3-beam/tsconfig.node.json @@ -0,0 +1,28 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + "target": "ES2023", + "lib": [ + "ES2023" + ], + "module": "ESNext", + "types": [ + "node" + ], + "skipLibCheck": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "moduleDetection": "force", + "noEmit": true, + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "erasableSyntaxOnly": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + }, + "include": [ + "vite.config.ts" + ] +} diff --git a/pancakz-v3-beam/vite.config.ts b/pancakz-v3-beam/vite.config.ts new file mode 100644 index 0000000..4b7799d --- /dev/null +++ b/pancakz-v3-beam/vite.config.ts @@ -0,0 +1,101 @@ +import { defineConfig } from 'vite' +import { readFileSync } from 'fs' +import { basename, extname, join } from 'path' +import { minify } from 'html-minifier-next' +import { buildSync } from 'esbuild' + +const ROOT = join(process.cwd(), 'application') +const DIST = join(ROOT, 'dist') + +export default defineConfig({ + root: ROOT, + build: { + outDir: DIST, + modulePreload: { + polyfill: false, + }, + rollupOptions: { + input: [ + join(ROOT, 'index.html'), + join(ROOT, 'not-found.html'), + join(ROOT, 'qr-code.html'), + join(ROOT, 'secret-sprites.html'), + join(ROOT, 'secret-picross.html'), + join(ROOT, 'about.html'), + ], + output: { + hashCharacters: 'hex', + entryFileNames: 'assets/[name].[hash].js', + chunkFileNames: 'assets/[name].[hash].js', + assetFileNames: 'assets/[name].[hash][extname]', + }, + }, + }, + server: { + strictPort: true, + port: 5173, + }, + plugins: [ + { + name: 'server-uri', + configureServer(server) { + const includeDir = join(ROOT, 'include') + server.watcher.add(includeDir) + server.watcher.on('change', (file) => { + if (file.startsWith(includeDir)) { + server.ws.send({ type: 'full-reload' }) + } + }) + }, + }, + { + name: 'html-generator', + transformIndexHtml(html, _) { + html = html.replaceAll(/{{ include-b64 '(.*?)' '(.*?)' }}/g, (_, mime: string, filepath: string) => { + const content = readFileSync(join(ROOT, filepath), 'base64') + return `data:${mime};base64,${content}` + }) + + html = html.replaceAll(/{{ include-tag '(.*?)' '(.*?)' }}/g, (_, tag: string, filepath: string) => { + if (tag === 'script' && filepath.endsWith('.ts')) { + const result = buildSync({ + entryPoints: [join(ROOT, filepath)], + bundle: true, + write: false, + format: 'esm', + target: 'es2023', + }) + return `` + } else { + const content = readFileSync(join(ROOT, filepath), 'utf8') + return `<${tag}>\n${content}` + } + }) + + html = html.replaceAll(/{{ include-article '(.*?)' }}/g, (_, filepath: string) => { + const id = basename(filepath).slice(0, -extname(filepath).length) + const content = readFileSync(join(ROOT, filepath), 'utf8').replaceAll( + /]*)>\s*\n([\s\S]*?)<\/pre>/g, + (_, attributes, inner) => { + const lines = inner.split('\n') + const indent = lines[0].match(/^(\s*)/)?.[1].length ?? 0 + const trimmed = lines + .map((l: string) => l.slice(indent)) + .join('\n') + .trim() + return `${trimmed}` + }, + ) + return `` + }) + + return minify(html, { + collapseWhitespace: true, + removeComments: true, + minifyCSS: true, + minifyJS: true, + }) + }, + }, + ], +})