From 4423c3a64870b45be5a0ec5be9db6ed53c7c45ca Mon Sep 17 00:00:00 2001 From: Chen Gu Date: Thu, 23 Apr 2026 12:20:19 +0800 Subject: [PATCH] Val's Dreamscape Journal - initial --- .gitignore | 3 + .hugo_build.lock | 0 archetypes/essay.md | 30 ++ archetypes/gallery.md | 17 + archetypes/journey.md | 43 +++ archetypes/sketch.md | 17 + assets/css/main.css | 323 ++++++++++++++++++ assets/js/main.js | 187 ++++++++++ content/journey/first-light.md | 28 ++ hugo.toml | 90 +++++ .../dreamscape/layouts/_default/baseof.html | 17 + themes/dreamscape/layouts/_default/list.html | 16 + .../dreamscape/layouts/_default/single.html | 19 ++ themes/dreamscape/layouts/index.html | 32 ++ .../dreamscape/layouts/partials/footer.html | 3 + themes/dreamscape/layouts/partials/head.html | 3 + .../dreamscape/layouts/partials/header.html | 8 + themes/dreamscape/static/css/style.css | 241 +++++++++++++ 18 files changed, 1077 insertions(+) create mode 100644 .gitignore create mode 100644 .hugo_build.lock create mode 100644 archetypes/essay.md create mode 100644 archetypes/gallery.md create mode 100644 archetypes/journey.md create mode 100644 archetypes/sketch.md create mode 100644 assets/css/main.css create mode 100644 assets/js/main.js create mode 100644 content/journey/first-light.md create mode 100644 hugo.toml create mode 100644 themes/dreamscape/layouts/_default/baseof.html create mode 100644 themes/dreamscape/layouts/_default/list.html create mode 100644 themes/dreamscape/layouts/_default/single.html create mode 100644 themes/dreamscape/layouts/index.html create mode 100644 themes/dreamscape/layouts/partials/footer.html create mode 100644 themes/dreamscape/layouts/partials/head.html create mode 100644 themes/dreamscape/layouts/partials/header.html create mode 100644 themes/dreamscape/static/css/style.css diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2461bd1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +public/ +resources/ +.DS_Store diff --git a/.hugo_build.lock b/.hugo_build.lock new file mode 100644 index 0000000..e69de29 diff --git a/archetypes/essay.md b/archetypes/essay.md new file mode 100644 index 0000000..63ad47c --- /dev/null +++ b/archetypes/essay.md @@ -0,0 +1,30 @@ +--- +title: '{{ replace .File.ContentBaseName "-" " " | title }}' +date: {{ .Date }} +draft: true +categories: ["essay"] +tags: [] +series: "" +series_order: 1 +abstract: "" +description: "" +toc: true +reading_time: true +--- + +## 引言 + +文章开篇... + +## 正文 + +主要内容... + +## 结论 + +总结思考... + +## 参考 + +- +- diff --git a/archetypes/gallery.md b/archetypes/gallery.md new file mode 100644 index 0000000..33ef1b0 --- /dev/null +++ b/archetypes/gallery.md @@ -0,0 +1,17 @@ +--- +title: '{{ replace .File.ContentBaseName "-" " " | title }}' +date: {{ .Date }} +draft: true +categories: ["gallery"] +tags: [] +location: "" +world: "" +description: "" +--- + +图志说明文字... + +{{< gallery >}} + {{< image src="/images/gallery/image-01.jpg" alt="描述" caption="说明文字" >}} + {{< image src="/images/gallery/image-02.jpg" alt="描述" caption="说明文字" >}} +{{< /gallery >}} diff --git a/archetypes/journey.md b/archetypes/journey.md new file mode 100644 index 0000000..a1996a6 --- /dev/null +++ b/archetypes/journey.md @@ -0,0 +1,43 @@ +--- +title: '{{ replace .File.ContentBaseName "-" " " | title }}' +date: {{ .Date }} +draft: true +categories: ["journey"] +tags: [] +series: "" +series_order: 1 +location: "" +world: "" +cover: + image: "" + alt: "" +description: "" +toc: true +reading_time: true +--- + +## 旅程起点 + +描述出发地点和初始状态... + +## 路线与见闻 + +### 第一段路程 + +详细记录沿途的发现... + +## 关键发现 + +### 地点/事件名称 + +深度描述... + +## 感悟与反思 + +旅程带来的思考... + +## 实用信息 + +- **位置**: +- **时间**: +- **建议**: diff --git a/archetypes/sketch.md b/archetypes/sketch.md new file mode 100644 index 0000000..188db54 --- /dev/null +++ b/archetypes/sketch.md @@ -0,0 +1,17 @@ +--- +title: '{{ replace .File.ContentBaseName "-" " " | title }}' +date: {{ .Date }} +draft: true +categories: ["sketch"] +tags: [] +mood: "" +weather: "" +time_of_day: "" +location: "" +world: "" +description: "" +--- + +快速记录当下的灵感片段... + + diff --git a/assets/css/main.css b/assets/css/main.css new file mode 100644 index 0000000..50dd5e3 --- /dev/null +++ b/assets/css/main.css @@ -0,0 +1,323 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +/* CSS Variables */ +:root { + /* 浅色模式 */ + --color-bg-primary: #F7F5F0; + --color-bg-secondary: #FFFFFF; + --color-bg-tertiary: #EDE9E0; + --color-text-primary: #2D3E50; + --color-text-secondary: #5A6A7A; + --color-text-tertiary: #8A94A6; + --color-accent: #C9A961; + --color-accent-hover: #B89850; + --color-border: #E5E1D8; + --color-code-bg: #F0EDE6; +} + +[data-theme="dark"] { + /* 暗色模式 */ + --color-bg-primary: #1A1F2B; + --color-bg-secondary: #232936; + --color-bg-tertiary: #2D3544; + --color-text-primary: #D4D4D4; + --color-text-secondary: #A0AAB8; + --color-text-tertiary: #6B7280; + --color-accent: #D4B86A; + --color-accent-hover: #E0C87A; + --color-border: #3A4150; + --color-code-bg: #1E2530; +} + +/* 系统偏好检测 */ +@media (prefers-color-scheme: dark) { + :root:not([data-theme]) { + --color-bg-primary: #1A1F2B; + --color-bg-secondary: #232936; + --color-bg-tertiary: #2D3544; + --color-text-primary: #D4D4D4; + --color-text-secondary: #A0AAB8; + --color-text-tertiary: #6B7280; + --color-accent: #D4B86A; + --color-accent-hover: #E0C87A; + --color-border: #3A4150; + --color-code-bg: #1E2530; + } +} + +/* Base Styles */ +@layer base { + body { + font-family: 'Noto Sans SC', -apple-system, BlinkMacSystemFont, sans-serif; + background-color: var(--color-bg-primary); + color: var(--color-text-primary); + } + + h1, h2, h3, h4, h5, h6 { + font-family: 'Noto Serif SC', 'Source Serif 4', serif; + font-weight: 600; + } +} + +/* Utility Classes */ +@layer utilities { + .bg-primary { background-color: var(--color-bg-primary); } + .bg-secondary { background-color: var(--color-bg-secondary); } + .bg-tertiary { background-color: var(--color-bg-tertiary); } + .text-primary { color: var(--color-text-primary); } + .text-secondary { color: var(--color-text-secondary); } + .text-tertiary { color: var(--color-text-tertiary); } + .text-accent { color: var(--color-accent); } + .hover\:text-accent:hover { color: var(--color-accent); } + .border-border { border-color: var(--color-border); } +} + +/* Typography */ +.font-serif { + font-family: 'Noto Serif SC', 'Source Serif 4', serif; +} + +.font-sans { + font-family: 'Noto Sans SC', -apple-system, BlinkMacSystemFont, sans-serif; +} + +/* Article Content */ +.article-content { + line-height: 1.8; + font-size: 1.0625rem; +} + +.article-content h2 { + font-size: 1.5rem; + margin-top: 2.5rem; + margin-bottom: 1rem; + color: var(--color-text-primary); +} + +.article-content h3 { + font-size: 1.25rem; + margin-top: 2rem; + margin-bottom: 0.75rem; + color: var(--color-text-primary); +} + +.article-content p { + margin-bottom: 1.25rem; +} + +.article-content a { + color: var(--color-accent); + text-decoration: underline; + text-decoration-color: transparent; + transition: text-decoration-color 0.2s; +} + +.article-content a:hover { + text-decoration-color: var(--color-accent); +} + +.article-content ul, +.article-content ol { + margin-bottom: 1.25rem; + padding-left: 1.5rem; +} + +.article-content li { + margin-bottom: 0.5rem; +} + +.article-content blockquote { + border-left: 3px solid var(--color-accent); + padding-left: 1rem; + margin: 1.5rem 0; + color: var(--color-text-secondary); + font-style: italic; +} + +.article-content code { + font-family: 'JetBrains Mono', monospace; + font-size: 0.875em; + background-color: var(--color-code-bg); + padding: 0.125rem 0.375rem; + border-radius: 0.25rem; +} + +.article-content pre { + background-color: var(--color-code-bg); + padding: 1rem; + border-radius: 0.5rem; + overflow-x: auto; + margin: 1.5rem 0; +} + +.article-content pre code { + background: none; + padding: 0; +} + +.article-content img { + max-width: 100%; + height: auto; + border-radius: 0.5rem; +} + +/* Table of Contents */ +.toc { + background-color: var(--color-bg-secondary); + border: 1px solid var(--color-border); + border-radius: 0.5rem; + padding: 1rem 1.5rem; + margin: 1.5rem 0; +} + +.toc-title { + font-weight: 600; + margin-bottom: 0.75rem; + color: var(--color-text-primary); +} + +.toc ul { + list-style: none; + padding: 0; + margin: 0; +} + +.toc li { + margin: 0.375rem 0; +} + +.toc a { + color: var(--color-text-secondary); + text-decoration: none; + font-size: 0.9375rem; +} + +.toc a:hover { + color: var(--color-accent); +} + +/* Card Styles */ +.card { + background-color: var(--color-bg-secondary); + border: 1px solid var(--color-border); + border-radius: 0.5rem; + transition: box-shadow 0.2s, transform 0.2s; +} + +.card:hover { + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); +} + +/* Tag Styles */ +.tag { + display: inline-flex; + align-items: center; + padding: 0.25rem 0.75rem; + background-color: var(--color-bg-tertiary); + color: var(--color-text-secondary); + font-size: 0.875rem; + border-radius: 9999px; + transition: background-color 0.2s, color 0.2s; +} + +.tag:hover { + background-color: var(--color-accent); + color: var(--color-bg-primary); +} + +/* Search Results */ +.search-result { + padding: 1rem; + border-bottom: 1px solid var(--color-border); + transition: background-color 0.15s; +} + +.search-result:hover { + background-color: var(--color-bg-secondary); +} + +.search-result:last-child { + border-bottom: none; +} + +.search-result-title { + font-weight: 500; + color: var(--color-text-primary); + margin-bottom: 0.25rem; +} + +.search-result-summary { + font-size: 0.875rem; + color: var(--color-text-secondary); + line-height: 1.5; +} + +.search-highlight { + background-color: rgba(201, 169, 97, 0.3); + padding: 0.125rem 0.25rem; + border-radius: 0.125rem; +} + +/* Pagination */ +.pagination { + display: flex; + justify-content: center; + align-items: center; + gap: 0.5rem; + margin-top: 3rem; +} + +.pagination a, +.pagination span { + padding: 0.5rem 1rem; + border-radius: 0.375rem; + font-size: 0.875rem; +} + +.pagination a { + color: var(--color-text-secondary); + border: 1px solid var(--color-border); + transition: all 0.2s; +} + +.pagination a:hover { + border-color: var(--color-accent); + color: var(--color-accent); +} + +.pagination .current { + background-color: var(--color-accent); + color: var(--color-bg-primary); +} + +/* Mobile Menu Animation */ +#mobile-menu { + transition: all 0.2s ease-in-out; +} + +/* Scrollbar Styling */ +::-webkit-scrollbar { + width: 8px; + height: 8px; +} + +::-webkit-scrollbar-track { + background: var(--color-bg-secondary); +} + +::-webkit-scrollbar-thumb { + background: var(--color-border); + border-radius: 4px; +} + +::-webkit-scrollbar-thumb:hover { + background: var(--color-text-tertiary); +} + +/* Selection */ +::selection { + background-color: rgba(201, 169, 97, 0.3); + color: var(--color-text-primary); +} diff --git a/assets/js/main.js b/assets/js/main.js new file mode 100644 index 0000000..31352e4 --- /dev/null +++ b/assets/js/main.js @@ -0,0 +1,187 @@ +// Theme Toggle +(function() { + const toggle = document.getElementById('theme-toggle'); + const iconLight = document.getElementById('theme-icon-light'); + const iconDark = document.getElementById('theme-icon-dark'); + const html = document.documentElement; + + // Get initial theme + function getTheme() { + const saved = localStorage.getItem('theme'); + if (saved) return saved; + if (window.matchMedia('(prefers-color-scheme: dark)').matches) return 'dark'; + return 'light'; + } + + // Apply theme + function applyTheme(theme) { + html.setAttribute('data-theme', theme); + localStorage.setItem('theme', theme); + updateIcons(theme); + } + + // Update icons + function updateIcons(theme) { + if (theme === 'dark') { + iconLight?.classList.remove('hidden'); + iconDark?.classList.add('hidden'); + } else { + iconLight?.classList.add('hidden'); + iconDark?.classList.remove('hidden'); + } + } + + // Initialize + applyTheme(getTheme()); + + // Toggle handler + toggle?.addEventListener('click', () => { + const current = html.getAttribute('data-theme'); + applyTheme(current === 'dark' ? 'light' : 'dark'); + }); +})(); + +// Mobile Menu +(function() { + const menuToggle = document.getElementById('mobile-menu-toggle'); + const mobileMenu = document.getElementById('mobile-menu'); + + menuToggle?.addEventListener('click', () => { + mobileMenu?.classList.toggle('hidden'); + }); +})(); + +// Search +(function() { + const searchToggle = document.getElementById('search-toggle'); + const searchModal = document.getElementById('search-modal'); + const searchBackdrop = document.getElementById('search-backdrop'); + const searchInput = document.getElementById('search-input'); + const searchResults = document.getElementById('search-results'); + const searchCount = document.getElementById('search-count'); + + let fuse = null; + let searchIndex = null; + + // Load search index + async function loadSearchIndex() { + if (searchIndex) return searchIndex; + + try { + const response = await fetch('/index.json'); + searchIndex = await response.json(); + + fuse = new Fuse(searchIndex, { + keys: ['title', 'content', 'tags'], + threshold: 0.3, + includeMatches: true, + }); + + return searchIndex; + } catch (err) { + console.error('Failed to load search index:', err); + return []; + } + } + + // Open search + function openSearch() { + searchModal?.classList.remove('hidden'); + document.body.style.overflow = 'hidden'; + searchInput?.focus(); + loadSearchIndex(); + } + + // Close search + function closeSearch() { + searchModal?.classList.add('hidden'); + document.body.style.overflow = ''; + if (searchInput) searchInput.value = ''; + searchResults!.innerHTML = '
输入关键词开始搜索...
'; + searchCount!.textContent = '0'; + } + + // Perform search + function performSearch(query) { + if (!query || !fuse) { + searchResults!.innerHTML = '
输入关键词开始搜索...
'; + searchCount!.textContent = '0'; + return; + } + + const results = fuse.search(query); + searchCount!.textContent = results.length.toString(); + + if (results.length === 0) { + searchResults!.innerHTML = '
未找到相关结果
'; + return; + } + + const html = results.map(result => { + const item = result.item; + const matches = result.matches || []; + + // Highlight matches in title + let title = item.title; + matches.filter(m => m.key === 'title').forEach(m => { + m.indices.forEach(([start, end]) => { + const matched = title.slice(start, end + 1); + title = title.slice(0, start) + `${matched}` + title.slice(end + 1); + }); + }); + + // Get summary with highlighted content + let summary = item.summary || item.content?.slice(0, 150) + '...' || ''; + matches.filter(m => m.key === 'content').forEach(m => { + if (m.indices[0]) { + const [start, end] = m.indices[0]; + const contextStart = Math.max(0, start - 50); + const contextEnd = Math.min(item.content.length, end + 50); + summary = '...' + item.content.slice(contextStart, contextEnd) + '...'; + + m.indices.slice(0, 2).forEach(([s, e]) => { + const relativeStart = s - contextStart + 3; + const relativeEnd = e - contextStart + 3; + if (relativeStart >= 0 && relativeEnd < summary.length) { + const matched = summary.slice(relativeStart, relativeEnd + 1); + summary = summary.slice(0, relativeStart) + `${matched}` + summary.slice(relativeEnd + 1); + } + }); + } + }); + + return ` + +
${title}
+
${summary}
+
${item.date} · ${item.category}
+
+ `; + }).join(''); + + searchResults!.innerHTML = html; + } + + // Event listeners + searchToggle?.addEventListener('click', openSearch); + searchBackdrop?.addEventListener('click', closeSearch); + + document.addEventListener('keydown', (e) => { + if (e.key === 'k' && (e.metaKey || e.ctrlKey)) { + e.preventDefault(); + openSearch(); + } + if (e.key === 'Escape') { + closeSearch(); + } + }); + + // Debounced search input + let debounceTimer; + searchInput?.addEventListener('input', (e) => { + clearTimeout(debounceTimer); + debounceTimer = setTimeout(() => { + performSearch(e.target.value.trim()); + }, 300); + }); +})(); diff --git a/content/journey/first-light.md b/content/journey/first-light.md new file mode 100644 index 0000000..e8090cf --- /dev/null +++ b/content/journey/first-light.md @@ -0,0 +1,28 @@ +--- +title: "初见:梦境之始" +date: 2026-04-23 +draft: false +tags: ["创世", "梦境", "随笔"] +--- + +那是一个没有时间概念的夜晚。 + +我睁开眼,发现自己漂浮在一片星海之中。周围是流动的光河,每一颗星都是一段未曾发生的记忆。远处有一颗格外明亮的星辰,它似乎在召唤我。 + +于是我张开双翼——等等,我有翅膀吗? + +低头看去,我发现自己正站在一块漂浮的冰晶上。脚下是无尽的深渊,但并不恐惧。相反,一种奇异的平静笼罩着我。 + +> "每一次旅程,都是一场对话——与现实对话,与幻象对话,最终与自己对话。" + +我决定向北飞翔。在这个世界里,方向是真实的,距离却毫无意义。眨眼之间,我已经站在一片巨大的水晶森林前。每一棵树都是透明的棱镜,折射出无数个平行的世界。 + +那一刻,我明白了自己的使命: + +**记录。** + +记录这片梦境大陆的每一次日出与日落,每一次相遇与离别。记录那些真实世界永远不会发生,却在心灵深处激起涟漪的故事。 + +于是,这里诞生了——Val's Dreamscape Journal。 + +欢迎来到我的梦境。 diff --git a/hugo.toml b/hugo.toml new file mode 100644 index 0000000..4574fd6 --- /dev/null +++ b/hugo.toml @@ -0,0 +1,90 @@ +baseURL = 'https://val-dreamscape.github.io' +languageCode = 'zh-CN' +title = "Val's Dreamscape Journal" +theme = "dreamscape" + +[params] + author = "Val" + description = "记录多元宇宙的梦幻旅程——从真实世界的隐秘角落,到异世界的魔法大陆" + keywords = ["旅行", "奇幻", "科幻", "博客", "探险"] + + # 主题设置 + defaultTheme = "auto" # auto, light, dark + disableThemeToggle = false + + # 功能开关 + ShowReadingTime = true + ShowPostNavLinks = true + ShowBreadCrumbs = true + ShowCodeCopyButtons = true + ShowToc = true + + # 搜索 + searchEnabled = true + + # 社交链接 + [params.social] + github = "" + twitter = "" + rss = true + +[menu] + [[menu.main]] + identifier = "home" + name = "首页" + url = "/" + weight = 10 + [[menu.main]] + identifier = "journey" + name = "旅程" + url = "/journey/" + weight = 20 + [[menu.main]] + identifier = "sketch" + name = "速记" + url = "/sketch/" + weight = 30 + [[menu.main]] + identifier = "gallery" + name = "图志" + url = "/gallery/" + weight = 40 + [[menu.main]] + identifier = "essay" + name = "随笔" + url = "/essay/" + weight = 50 + [[menu.main]] + identifier = "about" + name = "关于" + url = "/about/" + weight = 60 + +[taxonomies] + tag = "tags" + category = "categories" + series = "series" + +[outputs] + home = ["HTML", "RSS", "JSON"] + section = ["HTML", "RSS"] + +[outputFormats] + [outputFormats.RSS] + mediatype = "application/rss" + baseName = "feed" + +[markup] + [markup.goldmark] + [markup.goldmark.renderer] + unsafe = true + [markup.highlight] + style = "github" + lineNos = true + codeFences = true + +[permalinks] + journey = "/journey/:year/:slug/" + sketch = "/sketch/:year/:slug/" + gallery = "/gallery/:year/:slug/" + essay = "/essay/:year/:slug/" diff --git a/themes/dreamscape/layouts/_default/baseof.html b/themes/dreamscape/layouts/_default/baseof.html new file mode 100644 index 0000000..0964ee9 --- /dev/null +++ b/themes/dreamscape/layouts/_default/baseof.html @@ -0,0 +1,17 @@ + + + + + + {{ if .Title }}{{ .Title }} | {{ end }}{{ .Site.Title }} + + {{- partial "head.html" . -}} + + + {{- partial "header.html" . -}} +
+ {{- block "main" . }}{{- end }} +
+ {{- partial "footer.html" . -}} + + diff --git a/themes/dreamscape/layouts/_default/list.html b/themes/dreamscape/layouts/_default/list.html new file mode 100644 index 0000000..137e87a --- /dev/null +++ b/themes/dreamscape/layouts/_default/list.html @@ -0,0 +1,16 @@ +{{ define "main" }} + + +
+ {{ range .Paginator.Pages }} +
+ +

{{ .Title }}

+

{{ .Summary | truncate 100 }}

+
+ {{ end }} +
+{{ end }} diff --git a/themes/dreamscape/layouts/_default/single.html b/themes/dreamscape/layouts/_default/single.html new file mode 100644 index 0000000..ac4beb6 --- /dev/null +++ b/themes/dreamscape/layouts/_default/single.html @@ -0,0 +1,19 @@ +{{ define "main" }} + + +
+ {{ .Content }} +
+ + +{{ end }} diff --git a/themes/dreamscape/layouts/index.html b/themes/dreamscape/layouts/index.html new file mode 100644 index 0000000..21cac1b --- /dev/null +++ b/themes/dreamscape/layouts/index.html @@ -0,0 +1,32 @@ +{{ define "main" }} +
+
+

{{ .Site.Title }}

+

{{ .Site.Params.description }}

+
+ + {{ $sections := slice "journey" "sketch" "gallery" "essay" }} + {{ range $sections }} + {{ $pages := where $.Site.RegularPages "Section" . }} + {{ if $pages }} +
+

+ {{ . | title }} · {{ len $pages }} +

+
+ {{ range first 3 $pages }} +
+
+ + {{ with .Params.tags }}{{ range . }}{{ . }}{{ end }}{{ end }} +
+

{{ .Title }}

+

{{ .Summary | truncate 120 }}

+
+ {{ end }} +
+
+ {{ end }} + {{ end }} +
+{{ end }} diff --git a/themes/dreamscape/layouts/partials/footer.html b/themes/dreamscape/layouts/partials/footer.html new file mode 100644 index 0000000..85febed --- /dev/null +++ b/themes/dreamscape/layouts/partials/footer.html @@ -0,0 +1,3 @@ + diff --git a/themes/dreamscape/layouts/partials/head.html b/themes/dreamscape/layouts/partials/head.html new file mode 100644 index 0000000..b285929 --- /dev/null +++ b/themes/dreamscape/layouts/partials/head.html @@ -0,0 +1,3 @@ + + + diff --git a/themes/dreamscape/layouts/partials/header.html b/themes/dreamscape/layouts/partials/header.html new file mode 100644 index 0000000..7a7d91d --- /dev/null +++ b/themes/dreamscape/layouts/partials/header.html @@ -0,0 +1,8 @@ + diff --git a/themes/dreamscape/static/css/style.css b/themes/dreamscape/static/css/style.css new file mode 100644 index 0000000..e9f293d --- /dev/null +++ b/themes/dreamscape/static/css/style.css @@ -0,0 +1,241 @@ +/* Dreamscape Theme — Val's Journal */ +:root { + --bg: #0a0a1a; + --bg2: #12122a; + --surface: #1a1a3e; + --text: #e0e0f0; + --text2: #9090b0; + --accent: #7b68ee; + --accent2: #9370db; + --glow: rgba(123,104,238,0.15); + --radius: 8px; + --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Noto Sans SC", sans-serif; +} + +* { margin: 0; padding: 0; box-sizing: border-box; } +html { scroll-behavior: smooth; } + +body { + font-family: var(--font); + background: var(--bg); + color: var(--text); + line-height: 1.7; + min-height: 100vh; +} + +/* --- Header --- */ +.site-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 1rem 2rem; + border-bottom: 1px solid rgba(123,104,238,0.15); + background: var(--bg2); + backdrop-filter: blur(10px); + position: sticky; + top: 0; + z-index: 100; +} + +.logo { + font-size: 1.1rem; + font-weight: 700; + color: var(--accent); + text-decoration: none; + letter-spacing: 0.5px; +} + +.site-header nav a { + color: var(--text2); + text-decoration: none; + margin-left: 1.5rem; + font-size: 0.9rem; + transition: color 0.2s; +} + +.site-header nav a:hover { color: var(--accent); } + +/* --- Main --- */ +main { + max-width: 900px; + margin: 0 auto; + padding: 2rem; +} + +/* --- Hero --- */ +.hero { + text-align: center; + padding: 4rem 0 2rem; +} + +.hero-title { + font-size: 2.2rem; + font-weight: 800; + background: linear-gradient(135deg, var(--accent), #b388ff, var(--accent2)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + margin-bottom: 0.5rem; +} + +.hero-subtitle { + color: var(--text2); + font-size: 1rem; +} + +/* --- Sections --- */ +.section { margin-top: 3rem; } + +.section-title { + font-size: 1.1rem; + font-weight: 600; + margin-bottom: 1rem; + padding-bottom: 0.5rem; + border-bottom: 1px solid rgba(123,104,238,0.2); +} + +.section-title a { color: var(--accent); text-decoration: none; } + +/* --- Cards --- */ +.card-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); + gap: 1rem; +} + +.card { + background: var(--surface); + border-radius: var(--radius); + padding: 1.2rem; + border: 1px solid rgba(123,104,238,0.1); + transition: border-color 0.2s, transform 0.15s; +} + +.card:hover { + border-color: rgba(123,104,238,0.3); + transform: translateY(-2px); +} + +.card-meta { + font-size: 0.75rem; + color: var(--text2); + margin-bottom: 0.5rem; +} + +.card-title { + font-size: 1rem; + margin-bottom: 0.4rem; +} + +.card-title a { color: var(--text); text-decoration: none; } +.card-title a:hover { color: var(--accent); } + +.card-summary { font-size: 0.85rem; color: var(--text2); } + +/* --- Tags --- */ +.tags { margin-left: 0.5rem; } +.tag { + display: inline-block; + font-size: 0.7rem; + background: var(--glow); + color: var(--accent); + padding: 1px 8px; + border-radius: 10px; + margin-right: 4px; +} + +/* --- Article --- */ +.page-header { margin-bottom: 2rem; } + +.page-header h1 { + font-size: 1.8rem; + font-weight: 700; + margin-bottom: 0.3rem; +} + +.page-header .meta { + font-size: 0.85rem; + color: var(--text2); + margin-top: 0.5rem; +} + +.article { line-height: 1.8; } +.article h2 { font-size: 1.4rem; margin: 2rem 0 1rem; color: var(--accent); } +.article h3 { font-size: 1.15rem; margin: 1.5rem 0 0.5rem; } +.article p { margin-bottom: 1rem; } +.article a { color: var(--accent); } +.article img { max-width: 100%; border-radius: var(--radius); } +.article blockquote { + border-left: 3px solid var(--accent); + padding-left: 1rem; + margin: 1rem 0; + color: var(--text2); + font-style: italic; +} +.article pre { + background: var(--bg2); + border: 1px solid rgba(123,104,238,0.15); + border-radius: var(--radius); + padding: 1rem; + overflow-x: auto; + margin: 1rem 0; + font-size: 0.85rem; +} +.article code { + background: var(--bg2); + padding: 2px 6px; + border-radius: 4px; + font-size: 0.9em; +} + +/* --- List --- */ +.list-item { + padding: 1rem 0; + border-bottom: 1px solid rgba(123,104,238,0.1); +} + +.list-item time { + font-size: 0.8rem; + color: var(--text2); +} + +.list-item h3 { + font-size: 1.1rem; + margin: 0.3rem 0; +} + +.list-item h3 a { color: var(--text); text-decoration: none; } +.list-item h3 a:hover { color: var(--accent); } +.list-item p { font-size: 0.85rem; color: var(--text2); } + +/* --- Post Nav --- */ +.post-nav { + display: flex; + justify-content: space-between; + margin-top: 3rem; + padding-top: 1rem; + border-top: 1px solid rgba(123,104,238,0.15); +} + +.post-nav a { color: var(--accent2); text-decoration: none; font-size: 0.9rem; } +.post-nav a:hover { color: var(--accent); } + +/* --- Footer --- */ +.site-footer { + text-align: center; + padding: 2rem; + color: var(--text2); + font-size: 0.8rem; + border-top: 1px solid rgba(123,104,238,0.1); + margin-top: 4rem; +} + +/* --- Responsive --- */ +@media (max-width: 640px) { + .site-header { padding: 0.8rem 1rem; } + .site-header nav a { margin-left: 1rem; font-size: 0.8rem; } + main { padding: 1rem; } + .hero { padding: 2rem 0 1rem; } + .hero-title { font-size: 1.6rem; } + .card-grid { grid-template-columns: 1fr; } +}