aboutsummaryrefslogtreecommitdiffstats
path: root/internal/web/static
diff options
context:
space:
mode:
authorgramanas <grm@eyesin.space>2026-09-12 11:24:17 +0300
committergramanas <grm@eyesin.space>2026-09-12 11:24:17 +0300
commit3eb04b1a2bdf9e53231fe862cfd76327371a9741 (patch)
treeb38b2d82a47233fd8e0bb18c59e4a8f3dd2412d7 /internal/web/static
downloadblogspace-3eb04b1a2bdf9e53231fe862cfd76327371a9741.tar.gz
blogspace-3eb04b1a2bdf9e53231fe862cfd76327371a9741.tar.bz2
blogspace-3eb04b1a2bdf9e53231fe862cfd76327371a9741.zip
Initial multi-tenant blog host
Go + Postgres application serving a management dashboard on the base domain and one public blog per subdomain. Markdown posts organised in pages, form-based theme customisation, image uploads stored in Postgres, JWT cookie sessions with CSRF, superadmin user management, RSS feeds. Docker/compose deployment and a Makefile-driven dev environment with seed data. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Sd8UPWrvyYCLj97JexNw3A
Diffstat (limited to 'internal/web/static')
-rw-r--r--internal/web/static/blog.css50
-rw-r--r--internal/web/static/dashboard.css87
2 files changed, 137 insertions, 0 deletions
diff --git a/internal/web/static/blog.css b/internal/web/static/blog.css
new file mode 100644
index 0000000..b09689b
--- /dev/null
+++ b/internal/web/static/blog.css
@@ -0,0 +1,50 @@
+/* Public blog base styles — colours, fonts and widths come from the inline theme <style>. */
+* { box-sizing: border-box; }
+img { max-width: 100%; height: auto; }
+.wrap { padding: 0 1em; }
+.site-header { padding: 0; }
+.header-image img { display: block; width: 100%; max-height: 320px; object-fit: cover; }
+.header-text { padding: 1.4em 1em; }
+.site-title { margin: 0; font-size: 2em; line-height: 1.2; }
+.site-title a { text-decoration: none; }
+.tagline { margin: 0.3em 0 0; opacity: 0.85; }
+.site-nav { border-bottom: 1px solid rgba(0,0,0,0.1); }
+.nav-inner { padding: 0.3em 1em; }
+.site-nav a { display: inline-block; padding: 0.5em 0.8em; text-decoration: none; font-weight: bold; }
+.site-nav a.active, .site-nav a:hover { text-decoration: underline; }
+.body-wrap { padding: 1.5em 1em; overflow: hidden; }
+.content { padding: 1.5em 2em; border-radius: 6px; box-shadow: 0 1px 3px rgba(0,0,0,0.15); }
+.page-title { margin-top: 0; }
+.intro { padding-bottom: 1em; margin-bottom: 1.5em; border-bottom: 1px solid rgba(0,0,0,0.1); }
+.post { margin-bottom: 2.5em; }
+.post-title { margin: 0 0 0.1em; font-size: 1.5em; line-height: 1.25; }
+.post-title a { text-decoration: none; }
+.post-title a:hover { text-decoration: underline; }
+.post-date { margin: 0 0 0.8em; font-size: 0.85em; opacity: 0.7; }
+.post.single .post-title { font-size: 2em; }
+.post-body blockquote { margin: 1em 0; padding: 0.2em 1em; border-left: 4px solid rgba(0,0,0,0.15); opacity: 0.9; }
+.post-body pre { overflow-x: auto; padding: 0.8em 1em; background: rgba(0,0,0,0.06); border-radius: 4px; }
+.post-body code { background: rgba(0,0,0,0.06); padding: 0 0.25em; border-radius: 3px; font-size: 0.92em; }
+.post-body pre code { background: none; padding: 0; }
+.post-body table { border-collapse: collapse; }
+.post-body th, .post-body td { border: 1px solid rgba(0,0,0,0.15); padding: 0.3em 0.6em; }
+.post-body hr { border: 0; border-top: 1px solid rgba(0,0,0,0.15); }
+.pager { margin-top: 2em; padding-top: 1em; border-top: 1px solid rgba(0,0,0,0.1); text-align: center; }
+.pager a, .pager span { margin: 0 0.8em; }
+.muted { opacity: 0.7; }
+.site-footer { margin-top: 1em; padding: 1.5em 0; text-align: center; }
+.site-footer p { margin: 0.3em 0; }
+.site-footer .small { font-size: 0.85em; opacity: 0.8; }
+
+/* left sidebar layout: float the menu beside the content */
+.nav-left-sidebar .body-wrap .site-nav { float: left; width: 180px; border: 0; border-radius: 6px; padding: 0.5em 0; }
+.nav-left-sidebar .body-wrap .site-nav a { display: block; padding: 0.4em 1em; }
+.nav-left-sidebar .body-wrap .site-nav .nav-inner { padding: 0; }
+.nav-left-sidebar .body-wrap .content { margin-left: 200px; }
+@media (max-width: 700px) {
+ .content { padding: 1em; }
+ .site-title { font-size: 1.5em; }
+ .nav-left-sidebar .body-wrap .site-nav { float: none; width: auto; margin-bottom: 1em; }
+ .nav-left-sidebar .body-wrap .site-nav a { display: inline-block; }
+ .nav-left-sidebar .body-wrap .content { margin-left: 0; }
+}
diff --git a/internal/web/static/dashboard.css b/internal/web/static/dashboard.css
new file mode 100644
index 0000000..48f9eff
--- /dev/null
+++ b/internal/web/static/dashboard.css
@@ -0,0 +1,87 @@
+/* Blogspace dashboard — plain CSS, no JS required, works down to ~320px. */
+* { box-sizing: border-box; }
+body { margin: 0; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 16px; line-height: 1.5; color: #222; background: #f3f4f6; }
+a { color: #1a5fb4; }
+h1 { font-size: 1.6em; margin: 0.4em 0 0.6em; }
+h2 { font-size: 1.2em; margin: 0 0 0.6em; }
+h3 { font-size: 1.05em; margin: 0 0 0.4em; }
+code { background: #eef; padding: 0 0.25em; border-radius: 3px; font-size: 0.95em; }
+.muted { color: #666; }
+.nowrap { white-space: nowrap; }
+.narrow { max-width: 480px; }
+.small { font-size: 0.9em; }
+
+.topbar { background: #1f2933; color: #fff; }
+.topbar a { color: #fff; text-decoration: none; }
+.topbar-inner { max-width: 1100px; margin: 0 auto; padding: 0.6em 1em; overflow: hidden; }
+.brand { font-weight: bold; font-size: 1.1em; margin-right: 1em; }
+.who { color: #b8c2cc; }
+.topbar .links { float: right; }
+.topbar .links a, .topbar .links form { margin-left: 1em; }
+.blogbar { background: #fff; border-bottom: 1px solid #d9dde3; }
+.blogbar .topbar-inner { padding: 0.5em 1em; }
+.blogbar a { display: inline-block; padding: 0.3em 0.6em; text-decoration: none; color: #333; border-radius: 4px; }
+.blogbar a:hover { background: #eef1f5; }
+.blogbar .blogname { margin-right: 0.6em; }
+.blogbar .view { float: right; color: #1a5fb4; font-weight: bold; }
+
+.main { max-width: 1100px; margin: 0 auto; padding: 1em; }
+.card { background: #fff; border: 1px solid #d9dde3; border-radius: 6px; padding: 1em 1.2em; margin-bottom: 1em; }
+.cols { overflow: hidden; }
+.cols .card { float: left; width: 49%; margin-right: 2%; }
+.cols .card + .card { margin-right: 0; }
+.flash { padding: 0.7em 1em; border-radius: 6px; margin-bottom: 1em; }
+.flash.ok { background: #e3f6e8; border: 1px solid #9ad3a8; color: #1c5a2a; }
+.flash.err { background: #fdecec; border: 1px solid #f0a5a5; color: #7a1c1c; }
+.tag { display: inline-block; font-size: 0.75em; background: #eef1f5; color: #555; padding: 0 0.5em; border-radius: 3px; margin-left: 0.4em; vertical-align: middle; }
+
+label { display: block; margin: 0.6em 0; }
+input[type=text], input[type=password], input:not([type]), input[type=file], select, textarea {
+ width: 100%; max-width: 100%; padding: 0.45em 0.5em; border: 1px solid #b9c0c9; border-radius: 4px; font: inherit; background: #fff; }
+input[type=color] { width: 4em; height: 2.2em; padding: 0.1em; border: 1px solid #b9c0c9; border-radius: 4px; background: #fff; }
+textarea { font-family: "Courier New", Courier, monospace; font-size: 0.95em; line-height: 1.45; }
+textarea.editor { min-height: 20em; }
+label.check { display: block; }
+label.check input { width: auto; margin-right: 0.4em; }
+.row { overflow: hidden; }
+.row label { float: left; margin-right: 1.5em; min-width: 12em; }
+.row label:last-child { margin-right: 0; }
+button, .btn { display: inline-block; font: inherit; padding: 0.45em 1em; border-radius: 4px; border: 1px solid #164b8f; background: #1a5fb4; color: #fff; cursor: pointer; text-decoration: none; }
+button:hover, .btn:hover { background: #164b8f; }
+.btn.secondary, button.secondary { background: #fff; color: #1a5fb4; }
+.btn.small { font-size: 0.75em; vertical-align: middle; }
+button.mini, .mini { font-size: 0.8em; padding: 0.15em 0.5em; background: #fff; color: #333; border-color: #b9c0c9; }
+button.mini:hover { background: #eef1f5; }
+button.danger { background: #b42318; border-color: #8a1a12; }
+a.danger, button.mini.danger { color: #b42318; }
+button.linkbtn { background: none; border: 0; padding: 0; color: inherit; font: inherit; cursor: pointer; text-decoration: none; }
+form.inline, .inline { display: inline; }
+details.inline summary { display: inline; cursor: pointer; }
+.filter { margin: 0 0 1em; }
+.filter select { width: auto; }
+
+table { border-collapse: collapse; width: 100%; }
+th, td { text-align: left; padding: 0.45em 0.5em; border-bottom: 1px solid #e5e8ec; vertical-align: middle; }
+th { font-size: 0.85em; text-transform: uppercase; color: #666; letter-spacing: 0.03em; }
+tr.disabled td { color: #999; }
+ul.plain { list-style: none; padding: 0; margin: 0; }
+ul.plain li { padding: 0.2em 0; }
+.help { background: #fbfbf4; }
+.cheat td { border: 0; padding: 0.2em 1em 0.2em 0; }
+
+.gallery { overflow: hidden; }
+.thumb { float: left; width: 200px; margin: 0 1em 1em 0; padding: 0.6em; text-align: center; }
+.thumb img { max-width: 100%; max-height: 140px; }
+.thumb .meta { font-size: 0.85em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
+.thumb .copy { font-size: 0.8em; margin: 0.4em 0; font-family: "Courier New", monospace; }
+.imagepick { margin-top: 0.5em; padding-top: 0.5em; border-top: 1px dashed #d9dde3; }
+.imagepick img.preview { display: block; max-width: 240px; max-height: 120px; margin-top: 0.4em; border: 1px solid #d9dde3; }
+.imagepick select { width: auto; max-width: 100%; }
+
+@media (max-width: 700px) {
+ .cols .card, .row label, .thumb { float: none; width: auto; margin-right: 0; }
+ .topbar .links, .blogbar .view { float: none; display: block; margin-top: 0.3em; }
+ .topbar .links a, .topbar .links form { margin-left: 0; margin-right: 1em; }
+ table { font-size: 0.9em; }
+ th, td { padding: 0.35em 0.3em; }
+}