This commit is contained in:
2026-04-29 19:04:20 +08:00
parent df60e8dd42
commit 07d11a15af
58 changed files with 3937 additions and 520 deletions
+27
View File
@@ -0,0 +1,27 @@
// =============================================================================
// abstracts/_functions.scss
// Pure SCSS helper functions.
// =============================================================================
// Convert px value to rem.
@function rem($px, $base: 16) {
@return #{$px / $base}rem;
}
// Strip units from a value.
@function strip-unit($value) {
@return $value / ($value * 0 + 1);
}
// Fluid type scale using clamp().
// Usage: font-size: fluid-type(16px, 24px);
@function fluid-type($min-size, $max-size, $min-vw: 375px, $max-vw: 1280px) {
$min-rem: rem(strip-unit($min-size));
$max-rem: rem(strip-unit($max-size));
@return clamp(
#{$min-rem},
calc(#{$min-rem} + (#{strip-unit($max-size)} - #{strip-unit($min-size)}) * ((100vw - #{$min-vw}) / (#{strip-unit($max-vw)} - #{strip-unit($min-vw)}))),
#{$max-rem}
);
}
+100
View File
@@ -0,0 +1,100 @@
// =============================================================================
// abstracts/_mixins.scss
// Responsive helpers and reusable patterns.
// =============================================================================
// Bulma-matching breakpoint mixins.
@mixin mobile {
@media screen and (max-width: 768px) { @content; }
}
@mixin tablet {
@media screen and (min-width: 769px) { @content; }
}
@mixin tablet-only {
@media screen and (min-width: 769px) and (max-width: 1023px) { @content; }
}
@mixin desktop {
@media screen and (min-width: 1024px) { @content; }
}
@mixin widescreen {
@media screen and (min-width: 1216px) { @content; }
}
// Truncate text to N lines using -webkit-line-clamp.
@mixin line-clamp($lines: 2) {
display: -webkit-box;
-webkit-line-clamp: $lines;
-webkit-box-orient: vertical;
overflow: hidden;
}
// Visually hidden (accessible).
@mixin visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
// Aspect-ratio box.
@mixin aspect-ratio($w, $h) {
position: relative;
&::before {
content: '';
display: block;
padding-top: percentage($h / $w);
}
> * {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
object-fit: cover;
}
}
// Focus visible ring (WCAG 2.1).
@mixin focus-ring($color: var(--color-primary)) {
&:focus-visible {
outline: 3px solid $color;
outline-offset: 2px;
}
}
// Card elevation with hover lift.
@mixin card-lift {
transition: transform var(--transition-base), box-shadow var(--transition-base);
&:hover {
transform: translateY(-4px);
box-shadow: var(--card-shadow-hover);
}
}
// Skeleton loading shimmer.
@mixin skeleton-shimmer {
background: linear-gradient(
90deg,
var(--color-surface) 25%,
rgba(255, 255, 255, 0.5) 50%,
var(--color-surface) 75%
);
background-size: 200% 100%;
animation: skeleton-shimmer 1.5s infinite;
}
@keyframes skeleton-shimmer {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
+79
View File
@@ -0,0 +1,79 @@
// =============================================================================
// abstracts/_variables.scss
// CSS Custom Properties + SCSS variables for the 7-1 architecture.
// Bulma 1.x is built on CSS variables, so we map our design tokens here.
// =============================================================================
// --- Colour tokens -----------------------------------------------------------
:root {
--color-primary: #00d1b2;
--color-primary-dark: #00a896;
--color-dark: #363636;
--color-light: #f5f5f5;
--color-white: #ffffff;
--color-danger: #f14668;
--color-warning: #ffe08a;
--color-info: #3e8ed0;
--color-success: #48c78e;
// Semantic surface tokens (flipped in dark mode).
--color-background: #ffffff;
--color-text: #363636;
--color-surface: #f5f5f5;
--color-border: #dbdbdb;
--color-shadow: rgba(0, 0, 0, 0.1);
// Navbar
--navbar-bg: rgba(255, 255, 255, 0.85);
--navbar-shadow: 0 1px 3px rgba(0, 0, 0, 0.08), 0 1px 2px rgba(0, 0, 0, 0.04);
// Card
--card-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
--card-shadow-hover: 0 8px 24px rgba(0, 0, 0, 0.14);
--card-radius: 8px;
// Typography
--font-family-base: 'Noto Sans SC', system-ui, -apple-system, sans-serif;
--font-size-base: 1rem;
--line-height-base: 1.7;
// Spacing scale (mirrors theme.json)
--space-1: 0.25rem;
--space-2: 0.5rem;
--space-3: 1rem;
--space-4: 1.5rem;
--space-5: 2rem;
--space-6: 3rem;
--space-7: 4.5rem;
// Breakpoints (Bulma defaults)
--bp-mobile: 768px;
--bp-tablet: 769px;
--bp-desktop: 1024px;
--bp-widescreen: 1216px;
// Transitions
--transition-base: 0.3s ease;
}
// Dark mode overrides via data-attribute or media query.
[data-theme='dark'],
@media (prefers-color-scheme: dark) {
:root {
--color-background: #1a1a2e;
--color-text: #e0e0e0;
--color-surface: #16213e;
--color-border: #444444;
--color-shadow: rgba(0, 0, 0, 0.4);
--navbar-bg: rgba(26, 26, 46, 0.9);
--card-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
--card-shadow-hover:0 8px 24px rgba(0, 0, 0, 0.5);
}
}
// SCSS-only convenience aliases (not emitted as CSS).
$primary: #00d1b2 !default;
$primary-dark: #00a896 !default;
$dark: #363636 !default;
$font-base: var(--font-family-base);
$transition: var(--transition-base);
+56
View File
@@ -0,0 +1,56 @@
// =============================================================================
// base/_reset.scss
// Minimal modern reset on top of Bulma's built-in normalisation.
// =============================================================================
*,
*::before,
*::after {
box-sizing: border-box;
}
html {
scroll-behavior: smooth;
text-size-adjust: 100%;
}
body {
background-color: var(--color-background);
color: var(--color-text);
font-family: var(--font-family-base);
font-size: var(--font-size-base);
line-height: var(--line-height-base);
transition:
background-color var(--transition-base),
color var(--transition-base);
}
img,
video,
svg {
max-width: 100%;
height: auto;
}
a {
color: var(--color-primary);
text-underline-offset: 0.2em;
&:hover {
color: var(--color-primary-dark);
}
@include focus-ring;
}
button {
cursor: pointer;
}
// Remove default list style for navigation lists.
nav ul,
nav ol {
list-style: none;
margin: 0;
padding: 0;
}
+58
View File
@@ -0,0 +1,58 @@
// =============================================================================
// base/_typography.scss
// =============================================================================
h1, h2, h3, h4, h5, h6 {
line-height: 1.3;
font-weight: 700;
color: var(--color-dark);
}
p {
margin-bottom: var(--space-3);
}
code,
pre {
font-family: 'JetBrains Mono', 'Fira Code', 'Courier New', monospace;
font-size: 0.875em;
}
pre {
overflow-x: auto;
padding: var(--space-3);
background: var(--color-surface);
border-radius: var(--card-radius);
border-left: 4px solid var(--color-primary);
code {
background: transparent;
padding: 0;
}
}
blockquote {
border-left: 4px solid var(--color-primary);
padding-left: var(--space-3);
margin-left: 0;
color: #6b7280;
font-style: italic;
}
.screen-reader-text {
@include visually-hidden;
&:focus {
background-color: var(--color-background);
clip: auto;
height: auto;
left: var(--space-3);
top: var(--space-3);
width: auto;
z-index: 100000;
padding: var(--space-2) var(--space-3);
border: 2px solid var(--color-primary);
border-radius: 4px;
font-weight: 600;
}
}
+38
View File
@@ -0,0 +1,38 @@
// =============================================================================
// components/_button.scss
// =============================================================================
// Extend Bulma's .button with our colour tokens.
.button.is-primary {
background-color: var(--color-primary);
border-color: transparent;
color: #fff;
&:hover {
background-color: var(--color-primary-dark);
}
}
// Copy-code button on code blocks.
.copy-code-btn {
position: absolute;
top: 0.5rem;
right: 0.5rem;
background: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.2);
border-radius: 4px;
color: #e0e0e0;
font-size: 0.75rem;
padding: 0.2rem 0.5rem;
cursor: pointer;
transition: background var(--transition-base);
&:hover {
background: rgba(255, 255, 255, 0.2);
}
&.is-copied {
color: var(--color-success);
border-color: var(--color-success);
}
}
+168
View File
@@ -0,0 +1,168 @@
// =============================================================================
// components/_card.scss
// Post card component.
// =============================================================================
.post-card {
border-radius: var(--card-radius);
overflow: hidden;
background: var(--color-background);
border: 1px solid var(--color-border);
box-shadow: var(--card-shadow);
margin-bottom: var(--space-4);
transition:
transform var(--transition-base),
box-shadow var(--transition-base);
&:hover {
transform: translateY(-4px);
box-shadow: var(--card-shadow-hover);
}
// Featured image wrapper.
&__image {
overflow: hidden;
img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.5s ease;
}
}
&:hover &__image img {
transform: scale(1.03);
}
// Gradient placeholder when no featured image.
&__gradient-placeholder {
width: 100%;
height: 100%;
background: linear-gradient(135deg, var(--color-primary), var(--color-info));
display: flex;
align-items: center;
justify-content: center;
}
&__category-initial {
font-size: 2.5rem;
font-weight: 700;
color: rgba(255, 255, 255, 0.6);
}
// Categories.
&__categories {
display: flex;
flex-wrap: wrap;
gap: var(--space-1);
margin-bottom: var(--space-2);
}
&__category-badge {
font-size: 0.75rem;
text-decoration: none;
border-radius: 4px;
transition: opacity var(--transition-base);
&:hover {
opacity: 0.8;
}
}
// Title.
&__title {
margin-bottom: var(--space-2) !important;
a {
color: var(--color-text);
text-decoration: none;
transition: color var(--transition-base);
&:hover {
color: var(--color-primary);
}
}
}
// Meta row.
&__meta {
display: flex;
flex-wrap: wrap;
gap: var(--space-3);
color: #6b7280;
font-size: 0.85rem;
margin-bottom: var(--space-3) !important;
a {
color: #6b7280;
&:hover {
color: var(--color-primary);
}
}
i {
margin-right: 0.25rem;
}
}
// Footer row.
&__footer {
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
gap: var(--space-2);
margin-top: var(--space-3);
}
// "Continue reading" button arrow animation.
&__read-more {
display: inline-flex;
align-items: center;
gap: 0.25rem;
text-decoration: none;
transition:
background-color var(--transition-base),
color var(--transition-base);
}
&__read-more-arrow {
display: inline-block;
transition: transform var(--transition-base);
}
&__read-more:hover &__read-more-arrow {
transform: translateX(4px);
}
// Hero variant (sticky posts).
&--hero {
.post-card__image {
max-height: 400px;
}
.post-card__title {
font-size: 1.75rem;
}
}
// Skeleton loading state.
&--loading {
pointer-events: none;
.post-card__image,
.post-card__title,
.post-card__meta,
.post-card__content {
border-radius: 4px;
@include skeleton-shimmer;
color: transparent;
}
.post-card__image {
height: 180px;
}
}
}
+89
View File
@@ -0,0 +1,89 @@
// =============================================================================
// components/_navigation.scss
// Bulma navbar customisation + mobile dropdown corrections.
// =============================================================================
// Navbar item links.
.navbar-item,
.navbar-link {
color: var(--color-text);
transition: color var(--transition-base), background-color var(--transition-base);
&:hover,
&:focus-visible {
background-color: transparent;
color: var(--color-primary);
}
}
// Dropdown.
.navbar-dropdown {
background: var(--color-background);
border: 1px solid var(--color-border);
border-top: none;
border-radius: 0 0 8px 8px;
box-shadow: var(--card-shadow);
.navbar-item {
padding: 0.5rem 1rem;
&:hover {
background-color: var(--color-surface);
}
}
.navbar-divider {
background-color: var(--color-border);
}
}
// Breadcrumb.
.breadcrumb {
margin: var(--space-3) 0;
font-size: 0.9rem;
a {
color: var(--color-text);
text-decoration: none;
display: inline-flex;
align-items: center;
gap: 0.25rem;
transition: color var(--transition-base);
&:hover {
color: var(--color-primary);
}
}
li.is-active a {
color: #6b7280;
}
}
// Post navigation.
.nav-links {
.nav-previous,
.nav-next {
a {
display: inline-flex;
flex-direction: column;
text-decoration: none;
max-width: 300px;
color: var(--color-text);
transition: color var(--transition-base);
&:hover {
color: var(--color-primary);
}
}
}
.nav-subtitle {
font-size: 0.8rem;
color: #6b7280;
}
.nav-title {
font-weight: 600;
}
}
+66
View File
@@ -0,0 +1,66 @@
// =============================================================================
// components/_toc.scss
// Article Table of Contents sidebar widget.
// =============================================================================
.toc {
background: var(--color-background);
border: 1px solid var(--color-border);
border-radius: var(--card-radius);
position: sticky;
top: 80px;
max-height: calc(100vh - 120px);
overflow-y: auto;
scrollbar-width: thin;
.card-header {
background: transparent;
border-bottom: 1px solid var(--color-border);
}
.card-header-title {
font-size: 0.9rem;
color: var(--color-text);
}
.card-content {
padding: var(--space-2);
}
}
#toc-list {
ol {
list-style: decimal;
padding-left: var(--space-4);
margin: 0;
}
li {
margin-bottom: var(--space-2);
font-size: 0.85rem;
}
a {
color: var(--color-text);
text-decoration: none;
line-height: 1.4;
transition: color var(--transition-base);
display: block;
&:hover,
&.toc-active {
color: var(--color-primary);
}
&.toc-active {
font-weight: 600;
}
}
// Second-level (h3).
.toc-level-3 {
padding-left: var(--space-3);
list-style: disc;
color: #6b7280;
}
}
+106
View File
@@ -0,0 +1,106 @@
// =============================================================================
// layout/_footer.scss
// =============================================================================
.site-footer {
margin-top: var(--space-6);
background-color: var(--color-surface);
border-top: 1px solid var(--color-border);
padding-top: var(--space-5);
}
.footer-site-name {
font-size: 1.25rem;
font-weight: 700;
margin-bottom: var(--space-2);
a {
color: var(--color-text);
text-decoration: none;
&:hover {
color: var(--color-primary);
}
}
}
.footer-site-description {
color: #6b7280;
font-size: 0.875rem;
line-height: 1.5;
margin-bottom: var(--space-3);
}
.footer-menu-list {
list-style: none;
margin: 0;
padding: 0;
li {
margin-bottom: var(--space-2);
}
a {
color: var(--color-text);
text-decoration: none;
transition: color var(--transition-base);
&:hover {
color: var(--color-primary);
}
}
}
.social-menu-list {
display: flex;
flex-wrap: wrap;
gap: var(--space-2);
list-style: none;
margin: 0;
padding: 0;
a {
display: inline-flex;
align-items: center;
justify-content: center;
width: 2.25rem;
height: 2.25rem;
border-radius: 50%;
background-color: var(--color-border);
color: var(--color-text);
transition:
background-color var(--transition-base),
color var(--transition-base);
&:hover {
background-color: var(--color-primary);
color: #fff;
}
}
}
.footer-widget-title {
font-size: 1rem;
font-weight: 700;
margin-bottom: var(--space-3);
color: var(--color-text);
}
.footer-bottom {
margin-top: var(--space-5);
padding: var(--space-3) 0;
border-top: 1px solid var(--color-border);
}
.footer-copyright {
color: #6b7280;
font-size: 0.875rem;
a {
color: var(--color-text);
&:hover {
color: var(--color-primary);
}
}
}
+66
View File
@@ -0,0 +1,66 @@
// =============================================================================
// layout/_grid.scss
// Site-wide layout helpers.
// =============================================================================
.site-content {
padding-top: var(--space-4);
padding-bottom: var(--space-6);
}
// Primary content area + sidebar layout.
.content-area {
@include desktop {
display: flex;
gap: var(--space-5);
#main {
flex: 1;
min-width: 0; // Prevent flex blowout.
}
}
}
// Responsive post grid.
.posts-grid {
margin-bottom: var(--space-4);
}
// Pagination.
.posts-pagination {
margin-top: var(--space-4);
display: flex;
justify-content: center;
.nav-links {
display: flex;
gap: var(--space-2);
flex-wrap: wrap;
justify-content: center;
}
a,
span {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 2.25rem;
height: 2.25rem;
padding: 0 var(--space-2);
border: 1px solid var(--color-border);
border-radius: 6px;
color: var(--color-text);
text-decoration: none;
transition:
background-color var(--transition-base),
color var(--transition-base),
border-color var(--transition-base);
&:hover,
&.current {
background-color: var(--color-primary);
color: #fff;
border-color: var(--color-primary);
}
}
}
+192
View File
@@ -0,0 +1,192 @@
// =============================================================================
// layout/_header.scss
// =============================================================================
.site-navbar {
position: sticky;
top: 0;
z-index: 100;
background-color: var(--navbar-bg);
box-shadow: var(--navbar-shadow);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
transition: box-shadow var(--transition-base), background-color var(--transition-base);
&.is-scrolled {
box-shadow: 0 4px 12px var(--color-shadow);
}
}
// Logo area.
.navbar-logo {
padding: 0.5rem 0.75rem;
img {
max-height: 2.5rem;
width: auto;
}
}
.navbar-site-name {
display: flex;
align-items: center;
gap: 0.5rem;
font-weight: 700;
color: var(--color-dark) !important;
white-space: nowrap;
}
.site-title-initial {
display: inline-flex;
align-items: center;
justify-content: center;
width: 2rem;
height: 2rem;
border-radius: 50%;
background-color: var(--color-primary);
color: #fff;
font-weight: 700;
font-size: 1rem;
}
// Hamburger burger three-line → X animation.
.navbar-burger {
background: transparent;
border: none;
padding: 0.5rem;
transition: opacity var(--transition-base);
span {
display: block;
width: 1.25rem;
height: 2px;
background: var(--color-text);
margin: 4px 0;
transition:
transform 0.3s ease,
opacity 0.3s ease;
transform-origin: center;
}
&.is-active span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
&.is-active span:nth-child(2) { opacity: 0; }
&.is-active span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }
}
// Search widget.
.navbar-search-wrap {
position: relative;
}
.navbar-search-toggle {
background: transparent;
border: none;
color: var(--color-text);
font-size: 1rem;
padding: 0.25rem 0.5rem;
transition: color var(--transition-base);
&:hover {
color: var(--color-primary);
}
@include focus-ring;
}
.navbar-search-form {
position: absolute;
top: 110%;
right: 0;
background: var(--color-background);
border: 1px solid var(--color-border);
border-radius: 6px;
padding: 0.5rem;
box-shadow: var(--card-shadow);
min-width: 200px;
.input {
border-color: var(--color-border);
background: var(--color-background);
color: var(--color-text);
}
}
// Dark-mode toggle.
.theme-toggle {
background: transparent;
border: none;
font-size: 1rem;
color: var(--color-text);
padding: 0.25rem 0.5rem;
transition: color var(--transition-base);
line-height: 1;
&:hover {
color: var(--color-primary);
}
@include focus-ring;
}
// Show only the relevant icon.
body:not([data-theme='dark']) .theme-toggle__light-icon { display: none; }
[data-theme='dark'] .theme-toggle__dark-icon { display: none; }
// Back-to-top button.
.back-to-top {
position: fixed;
bottom: 2rem;
right: 2rem;
z-index: 200;
width: 3rem;
height: 3rem;
border-radius: 50%;
background-color: var(--color-primary);
color: #fff;
border: none;
font-size: 1.25rem;
display: flex;
align-items: center;
justify-content: center;
box-shadow: var(--card-shadow);
transition:
opacity var(--transition-base),
transform var(--transition-base),
box-shadow var(--transition-base);
opacity: 0;
transform: translateY(1rem);
pointer-events: none;
&.is-visible {
opacity: 1;
transform: translateY(0);
pointer-events: auto;
}
&:hover {
box-shadow: var(--card-shadow-hover);
}
@include focus-ring;
}
// Skip link.
.skip-link {
@include visually-hidden;
&:focus {
position: fixed;
top: var(--space-2);
left: var(--space-2);
z-index: 9999;
background: var(--color-primary);
color: #fff;
padding: var(--space-2) var(--space-3);
border-radius: 4px;
clip: auto;
height: auto;
width: auto;
font-weight: 700;
text-decoration: none;
}
}
+26
View File
@@ -0,0 +1,26 @@
// =============================================================================
// layout/_sidebar.scss
// =============================================================================
.widget-area {
.widget {
border-radius: var(--card-radius);
overflow: hidden;
.card-content {
padding-top: var(--space-3);
}
}
}
// Sticky sidebar on desktop.
@include desktop {
#secondary.widget-area {
position: sticky;
top: calc(var(--space-5) + 60px); // 60px = approx navbar height.
align-self: flex-start;
max-height: calc(100vh - 100px);
overflow-y: auto;
scrollbar-width: thin;
}
}
+35
View File
@@ -0,0 +1,35 @@
// =============================================================================
// main.scss CyyWordpress 7-1 SCSS entry point
// =============================================================================
// 1. Abstracts (no CSS output, just variables / mixins / functions)
@use 'abstracts/variables';
@use 'abstracts/mixins' as *;
@use 'abstracts/functions';
// 2. Third-party framework (selective Bulma import)
@use 'vendors/bulma';
// 3. Base styles
@use 'base/reset';
@use 'base/typography';
// 4. Layout shells
@use 'layout/grid';
@use 'layout/header';
@use 'layout/footer';
@use 'layout/sidebar';
// 5. Reusable components
@use 'components/card';
@use 'components/navigation';
@use 'components/button';
@use 'components/toc';
// 6. Page-specific
@use 'pages/home';
@use 'pages/single';
@use 'pages/archive';
// 7. Themes (dark mode overrides)
@use 'themes/dark';
+18
View File
@@ -0,0 +1,18 @@
// =============================================================================
// pages/_archive.scss
// =============================================================================
.archive-header {
margin-bottom: var(--space-4);
padding-bottom: var(--space-3);
border-bottom: 1px solid var(--color-border);
.page-title {
font-size: 1.75rem;
font-weight: 700;
}
.archive-description {
color: #6b7280;
}
}
+8
View File
@@ -0,0 +1,8 @@
// =============================================================================
// pages/_home.scss
// =============================================================================
.welcome-banner {
margin-bottom: var(--space-3);
border-radius: var(--card-radius);
}
+181
View File
@@ -0,0 +1,181 @@
// =============================================================================
// pages/_single.scss
// =============================================================================
// Reading progress bar.
.reading-progress {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 3px;
z-index: 9999;
background: transparent;
pointer-events: none;
&__bar {
height: 100%;
width: 0;
background: var(--color-primary);
transition: width 0.1s linear;
}
}
// Hero featured image.
.single-hero {
position: relative;
width: 100%;
max-height: 450px;
overflow: hidden;
border-radius: var(--card-radius);
margin-bottom: var(--space-4);
&__image {
width: 100%;
height: 450px;
object-fit: cover;
display: block;
loading: eager;
}
&__overlay {
position: absolute;
inset: 0;
background: linear-gradient(to top, rgba(0, 0, 0, 0.65) 0%, transparent 60%);
display: flex;
align-items: flex-end;
padding: var(--space-5);
}
&__title {
color: #fff;
font-size: clamp(1.5rem, 4vw, 2.5rem);
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
margin: 0;
}
}
// Single article layout.
.single-layout {
align-items: flex-start;
}
// Social share.
.social-share {
display: flex;
align-items: center;
gap: var(--space-2);
flex-wrap: wrap;
margin: var(--space-4) 0;
padding: var(--space-3);
background: var(--color-surface);
border-radius: var(--card-radius);
border: 1px solid var(--color-border);
&__label {
font-size: 0.875rem;
color: #6b7280;
}
&__btn {
display: inline-flex;
align-items: center;
justify-content: center;
width: 2.25rem;
height: 2.25rem;
border-radius: 50%;
background: var(--color-border);
color: var(--color-text);
border: none;
font-size: 1rem;
text-decoration: none;
transition:
background-color var(--transition-base),
color var(--transition-base);
&:hover {
background-color: var(--color-primary);
color: #fff;
}
&--weibo:hover { background-color: #e6162d; }
&--twitter:hover { background-color: #000; }
}
}
// Author bio.
.author-bio {
margin: var(--space-4) 0;
border-radius: var(--card-radius);
border: 1px solid var(--color-border);
.media {
align-items: flex-start;
}
&__avatar {
border-radius: 50%;
}
&__name {
display: block;
color: var(--color-text);
text-decoration: none;
margin-bottom: var(--space-2);
&:hover { color: var(--color-primary); }
}
&__description {
font-size: 0.9rem;
color: #6b7280;
line-height: 1.6;
}
}
// Related posts.
.related-posts {
margin: var(--space-4) 0;
&__title {
margin-bottom: var(--space-3);
}
}
.related-post-card {
height: 100%;
border-radius: var(--card-radius);
border: 1px solid var(--color-border);
overflow: hidden;
transition:
transform var(--transition-base),
box-shadow var(--transition-base);
&:hover {
transform: translateY(-2px);
box-shadow: var(--card-shadow-hover);
}
&__image {
width: 100%;
height: 100%;
object-fit: cover;
}
&__title {
display: block;
font-size: 0.9rem;
font-weight: 600;
color: var(--color-text);
text-decoration: none;
line-height: 1.4;
&:hover { color: var(--color-primary); }
}
}
// Code block copy button wrapper.
.entry-content pre,
.post-card__content pre {
position: relative;
}
+42
View File
@@ -0,0 +1,42 @@
// =============================================================================
// themes/_dark.scss
// Dark mode extra overrides beyond CSS custom properties.
// =============================================================================
[data-theme='dark'],
@media (prefers-color-scheme: dark) {
// Bulma component overrides.
.navbar {
background-color: var(--navbar-bg);
border-bottom: 1px solid var(--color-border);
}
.card {
background-color: var(--color-surface);
border-color: var(--color-border);
}
.notification.is-primary {
background-color: rgba(0, 209, 178, 0.15);
color: #00d1b2;
}
.input,
.select select,
.textarea {
background-color: var(--color-surface);
border-color: var(--color-border);
color: var(--color-text);
}
.footer {
background-color: var(--color-surface);
}
// Code blocks.
pre,
code {
background-color: #0d1117;
color: #e6edf3;
}
}
+10
View File
@@ -0,0 +1,10 @@
// =============================================================================
// vendors/_bulma.scss
// Selective Bulma 1.x import only import what the theme uses.
// Bulma 1.x exposes sass/ subdirectory; each module uses @use.
// =============================================================================
@use 'bulma/sass' with (
$primary: #00d1b2,
$dark: #363636,
$light: #f5f5f5
);