diff --git a/modules/blox/assets/css/blox/all.css b/modules/blox/assets/css/blox/all.css
deleted file mode 100644
index 7936878d..00000000
--- a/modules/blox/assets/css/blox/all.css
+++ /dev/null
@@ -1,3 +0,0 @@
-@import "biography.css";
-@import "skills.css";
-@import "navbar.css";
diff --git a/modules/blox/assets/css/blox/biography.css b/modules/blox/assets/css/blox/biography.css
deleted file mode 100644
index d1a03f44..00000000
--- a/modules/blox/assets/css/blox/biography.css
+++ /dev/null
@@ -1,281 +0,0 @@
-.resume-biography {
- #profile {
- text-align: center;
- padding: 30px 10px;
- position: relative;
- }
-
- /* Custom avatar size on homepage - size controlled by template params */
- .avatar {
- width: auto;
- height: auto;
- object-fit: cover;
- }
-
- .network-icon {
- display: inline-flex;
- flex-direction: row;
- flex-wrap: wrap;
- justify-content: center;
- list-style: none;
- padding: 0;
- margin: 0;
- }
-
- #profile .network-icon {
- margin-top: 0.5rem;
- }
-
- .network-icon li {
- margin-right: 10px;
-
- @media (max-width: 640px) {
- /* Min 48px Lighthouse tap targets on mobile */
- margin-right: 12px;
- }
- }
-
- .network-icon li:last-of-type {
- margin-right: 0;
- }
-
- .network-icon li:hover {
- transform: scale(1.2);
- }
-
- .big-icon {
- font-size: 2rem;
- }
-
- .ul-interests li {
- font-size: 0.9rem;
- }
-
- .ul-edu li .description p.course {
- font-size: 0.9rem;
- }
-
- .ul-edu li .description p.institution {
- font-size: 0.75rem;
- }
-
- .network-icon .big-icon {
- font-size: 1.5rem;
- }
-
- .bio-text {
- max-width: 680px;
- }
-}
-
-/* Modern Biography Block Enhancements */
-.resume-biography-modern {
- /* Ensure proper stacking context for gradients and effects */
- position: relative;
- z-index: 1;
-}
-
-/* Ruby pronunciation styling - 2026+ modern design */
-.hb-ruby-name {
- ruby-position: over;
- display: ruby;
- text-align: center;
-}
-
-.hb-ruby-name rt {
- /* Elegant, subdued annotation text */
- font-size: 0.45em;
- font-weight: var(--hb-font-weight-body-bold, 600);
- letter-spacing: 0.08em;
- line-height: 1.2;
-
- /* Subtle gradient text for premium feel */
- background: linear-gradient(135deg, var(--color-gray-500) 0%, var(--color-gray-400) 100%);
- -webkit-background-clip: text;
- background-clip: text;
- -webkit-text-fill-color: transparent;
-
- /* Smooth reveal animation */
- opacity: 0.85;
- transition:
- opacity 0.3s ease,
- transform 0.3s ease;
-}
-
-.dark .hb-ruby-name rt {
- background: linear-gradient(135deg, var(--color-gray-400) 0%, var(--color-gray-300) 100%);
- -webkit-background-clip: text;
- background-clip: text;
- -webkit-text-fill-color: transparent;
-}
-
-/* Hover enhancement - subtle lift */
-.hb-ruby-name:hover rt {
- opacity: 1;
- transform: translateY(-1px);
-}
-
-/* CJK-optimized variant - larger annotation for CJK characters over Latin */
-.hb-ruby-name--cjk rt {
- font-size: 0.5em;
- font-weight: 400;
- letter-spacing: 0.12em;
-}
-
-/* Latin-optimized variant - smaller annotation for romanization over CJK */
-.hb-ruby-name--latin rt {
- font-size: 0.4em;
- font-weight: var(--hb-font-weight-body-bold, 600);
- text-transform: none;
-}
-
-/* Accessibility: respect reduced motion */
-@media (prefers-reduced-motion: reduce) {
- .hb-ruby-name rt {
- transition: none;
- }
-
- .hb-ruby-name:hover rt {
- transform: none;
- }
-}
-
-/* Fallback styling for browsers without ruby support */
-@supports not (display: ruby) {
- .hb-ruby-name {
- display: inline-block;
- }
-
- .hb-ruby-name rt {
- display: block;
- font-size: 0.6em;
- margin-bottom: 0.25em;
- }
-}
-
-/* Legacy class support */
-.ruby-modern {
- ruby-position: over;
-}
-
-.ruby-modern rt {
- font-size: 0.7em;
- opacity: 0.8;
- letter-spacing: 0.05em;
-}
-
-/* Enhanced backdrop blur support */
-@supports (backdrop-filter: blur(10px)) {
- .resume-biography-modern [class*="backdrop-blur"] {
- backdrop-filter: blur(10px);
- }
-}
-
-/* Smooth animations for all interactive elements */
-.resume-biography-modern * {
- transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
-}
-
-/* Enhanced focus states for accessibility */
-.resume-biography-modern a:focus-visible {
- outline: 2px solid var(--color-primary-500);
- outline-offset: 2px;
- border-radius: 0.5rem;
-}
-
-/* Improved text selection styling */
-.resume-biography-modern ::selection {
- background-color: color-mix(in oklch, var(--color-primary-200) 30%, transparent);
- color: var(--color-primary-900);
-}
-
-.dark .resume-biography-modern ::selection {
- background-color: color-mix(in oklch, var(--color-primary-800) 30%, transparent);
- color: var(--color-primary-100);
-}
-
-/* Enhanced gradient text support */
-.resume-biography-modern .bg-clip-text {
- -webkit-background-clip: text;
- background-clip: text;
- -webkit-text-fill-color: transparent;
-}
-
-/* Ensure text remains readable on fallback */
-@supports not (background-clip: text) {
- .resume-biography-modern .bg-clip-text {
- color: var(--color-neutral-900);
- }
-
- .dark .resume-biography-modern .bg-clip-text {
- color: var(--color-neutral-100);
- }
-}
-
-.avatar-wrapper {
- position: relative;
- /* width and height controlled by template params */
- margin-left: auto;
- margin-right: auto;
-}
-
-.avatar-emoji {
- position: absolute;
- width: 40px;
- height: 40px;
- line-height: 40px;
- border-radius: 100%;
- bottom: 0;
- right: 0;
- text-align: center;
- font-size: 20px;
- background-color: #fff;
- color: #000;
- /* override parent alpha */
- box-shadow:
- 0 10px 20px rgb(0 0 0 / 4%),
- 0 2px 6px rgb(0 0 0 / 4%),
- 0 0 1px rgb(0 0 0 / 4%);
-}
-
-.dark .avatar-emoji {
- background-color: #000;
- box-shadow:
- 0 10px 20px rgb(0 0 0 / 4%),
- 0 2px 6px rgb(0 0 0 / 4%),
- 0 0 1px rgb(255 255 255 / 96%);
-}
-
-/* Biography Block */
-
-.hbx-bg-gradient {
- position: relative;
- isolation: isolate;
-}
-
-.hbx-bg-gradient::before {
- content: "";
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- z-index: -1;
- background-attachment: fixed;
- transition: opacity 0.5s ease-in-out;
- opacity: 1;
-}
-
-/* Light Mode Gradient */
-.hbx-bg-gradient::before {
- background-image:
- radial-gradient(at 20% 25%, hsla(212, 80%, 95%, 1) 0px, transparent 50%), radial-gradient(at 75% 30%, hsla(160, 80%, 95%, 1) 0px, transparent 50%),
- radial-gradient(at 25% 80%, hsla(280, 80%, 95%, 1) 0px, transparent 50%), radial-gradient(at 75% 85%, hsla(30, 80%, 95%, 1) 0px, transparent 50%);
-}
-
-/* Dark Mode Gradient */
-.dark .hbx-bg-gradient::before {
- background-image:
- radial-gradient(at 20% 25%, hsla(212, 35%, 15%, 1) 0px, transparent 50%), radial-gradient(at 75% 30%, hsla(160, 35%, 15%, 1) 0px, transparent 50%),
- radial-gradient(at 25% 80%, hsla(280, 35%, 15%, 1) 0px, transparent 50%), radial-gradient(at 75% 85%, hsla(30, 35%, 15%, 1) 0px, transparent 50%);
-}
diff --git a/modules/blox/assets/css/components/all.css b/modules/blox/assets/css/components/all.css
index 8869f149..fdc86ffe 100644
--- a/modules/blox/assets/css/components/all.css
+++ b/modules/blox/assets/css/components/all.css
@@ -10,3 +10,4 @@
@import "author-notes.css";
@import "glassmorphism.css";
@import "cover.css";
+@import "navbar.css";
diff --git a/modules/blox/assets/css/blox/navbar.css b/modules/blox/assets/css/components/navbar.css
similarity index 100%
rename from modules/blox/assets/css/blox/navbar.css
rename to modules/blox/assets/css/components/navbar.css
diff --git a/modules/blox/assets/css/main.css b/modules/blox/assets/css/main.css
index b7157579..503a7d9c 100644
--- a/modules/blox/assets/css/main.css
+++ b/modules/blox/assets/css/main.css
@@ -34,8 +34,10 @@
/* Hugo Blox module components */
@import "components/all.css";
-@import "blox/all.css";
@import "views/all.css";
+
+/* Block-specific CSS is auto-discovered from co-located style.css files */
+/* See css.html partial for the discovery mechanism */
@import "chroma.css";
/* Hugo Blox Search */
diff --git a/modules/blox/blox/resume-biography/style.css b/modules/blox/blox/resume-biography/style.css
new file mode 100644
index 00000000..e744feb5
--- /dev/null
+++ b/modules/blox/blox/resume-biography/style.css
@@ -0,0 +1,63 @@
+.resume-biography {
+ #profile {
+ text-align: center;
+ padding: 30px 10px;
+ position: relative;
+ }
+
+ .avatar {
+ width: auto;
+ height: auto;
+ object-fit: cover;
+ }
+
+ .network-icon {
+ display: inline-flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ justify-content: center;
+ list-style: none;
+ padding: 0;
+ margin: 0;
+ }
+
+ #profile .network-icon {
+ margin-top: 0.5rem;
+ }
+
+ .network-icon li {
+ margin-right: 10px;
+
+ @media (max-width: 640px) {
+ margin-right: 12px;
+ }
+ }
+
+ .network-icon li:last-of-type {
+ margin-right: 0;
+ }
+
+ .network-icon li:hover {
+ transform: scale(1.2);
+ }
+
+ .big-icon {
+ font-size: 2rem;
+ }
+
+ .ul-interests li {
+ font-size: 0.9rem;
+ }
+
+ .ul-edu li .description p.course {
+ font-size: 0.9rem;
+ }
+
+ .ul-edu li .description p.institution {
+ font-size: 0.75rem;
+ }
+
+ .network-icon .big-icon {
+ font-size: 1.5rem;
+ }
+}
diff --git a/modules/blox/assets/css/blox/skills.css b/modules/blox/blox/resume-skills/style.css
similarity index 51%
rename from modules/blox/assets/css/blox/skills.css
rename to modules/blox/blox/resume-skills/style.css
index 21542e5d..d68d9a9d 100644
--- a/modules/blox/assets/css/blox/skills.css
+++ b/modules/blox/blox/resume-skills/style.css
@@ -1,36 +1,14 @@
-/*************************************************
- * Hugo Blox: Skills
- **************************************************/
-
-/* MOVED TO HTML */
-/* .skill-group-title { */
-/* display: inline-block; */
-/* margin-bottom: 15px; */
-/* padding-bottom: 5px; */
-/* border-bottom: 2px solid #c7c7c7; */
-/* font-size: 1rem; */
-/* line-height: 30px; */
-/* font-weight: 600; */
-/* text-transform: uppercase; */
-/* letter-spacing: 1px; */
-/* } */
-
.skills-content {
margin-bottom: 15px;
}
.skills-name {
margin-bottom: 6px;
- /* color: #888; */ /* Inaccessible */
font-size: 1rem;
letter-spacing: 1px;
text-transform: uppercase;
}
-/* .dark .skills-name { */
-/* color: #eee; */
-/* } */
-
.skills-description {
margin-bottom: 6px;
font-size: 0.7rem;
diff --git a/modules/blox/blox/shared/css/biography-shared.css b/modules/blox/blox/shared/css/biography-shared.css
new file mode 100644
index 00000000..7fb1a56c
--- /dev/null
+++ b/modules/blox/blox/shared/css/biography-shared.css
@@ -0,0 +1,122 @@
+/* Shared styles for biography-family blocks (resume-biography, resume-biography-3) */
+
+.avatar-wrapper {
+ position: relative;
+ /* width and height controlled by template params */
+ margin-left: auto;
+ margin-right: auto;
+}
+
+.avatar-emoji {
+ position: absolute;
+ width: 40px;
+ height: 40px;
+ line-height: 40px;
+ border-radius: 100%;
+ bottom: 0;
+ right: 0;
+ text-align: center;
+ font-size: 20px;
+ background-color: #fff;
+ color: #000;
+ /* override parent alpha */
+ box-shadow:
+ 0 10px 20px rgb(0 0 0 / 4%),
+ 0 2px 6px rgb(0 0 0 / 4%),
+ 0 0 1px rgb(0 0 0 / 4%);
+}
+
+.dark .avatar-emoji {
+ background-color: #000;
+ box-shadow:
+ 0 10px 20px rgb(0 0 0 / 4%),
+ 0 2px 6px rgb(0 0 0 / 4%),
+ 0 0 1px rgb(255 255 255 / 96%);
+}
+
+/* Ruby pronunciation styling */
+.hb-ruby-name {
+ ruby-position: over;
+ display: ruby;
+ text-align: center;
+}
+
+.hb-ruby-name rt {
+ font-size: 0.45em;
+ font-weight: var(--hb-font-weight-body-bold, 600);
+ letter-spacing: 0.08em;
+ line-height: 1.2;
+
+ background: linear-gradient(135deg, var(--color-gray-500) 0%, var(--color-gray-400) 100%);
+ -webkit-background-clip: text;
+ background-clip: text;
+ -webkit-text-fill-color: transparent;
+
+ opacity: 0.85;
+ transition:
+ opacity 0.3s ease,
+ transform 0.3s ease;
+}
+
+.dark .hb-ruby-name rt {
+ background: linear-gradient(135deg, var(--color-gray-400) 0%, var(--color-gray-300) 100%);
+ -webkit-background-clip: text;
+ background-clip: text;
+ -webkit-text-fill-color: transparent;
+}
+
+.hb-ruby-name:hover rt {
+ opacity: 1;
+ transform: translateY(-1px);
+}
+
+/* CJK-optimized variant */
+.hb-ruby-name--cjk rt {
+ font-size: 0.5em;
+ font-weight: 400;
+ letter-spacing: 0.12em;
+}
+
+/* Latin-optimized variant */
+.hb-ruby-name--latin rt {
+ font-size: 0.4em;
+ font-weight: var(--hb-font-weight-body-bold, 600);
+ text-transform: none;
+}
+
+@media (prefers-reduced-motion: reduce) {
+ .hb-ruby-name rt {
+ transition: none;
+ }
+
+ .hb-ruby-name:hover rt {
+ transform: none;
+ }
+}
+
+@supports not (display: ruby) {
+ .hb-ruby-name {
+ display: inline-block;
+ }
+
+ .hb-ruby-name rt {
+ display: block;
+ font-size: 0.6em;
+ margin-bottom: 0.25em;
+ }
+}
+
+/* Legacy class support */
+.ruby-modern {
+ ruby-position: over;
+}
+
+.ruby-modern rt {
+ font-size: 0.7em;
+ opacity: 0.8;
+ letter-spacing: 0.05em;
+}
+
+.bio-text {
+ max-width: 680px;
+}
diff --git a/modules/blox/layouts/_partials/css.html b/modules/blox/layouts/_partials/css.html
index 422dd1a8..8a694233 100644
--- a/modules/blox/layouts/_partials/css.html
+++ b/modules/blox/layouts/_partials/css.html
@@ -3,8 +3,24 @@
{{/* Build dynamic @source list and prepend it before main.css */}}
{{ $dynamic_sources_str := partial "tailwind_sources.html" . }}
{{ $dynamic_sources_res := resources.FromString "css/_dynamic_sources.css" $dynamic_sources_str }}
+
{{ $main_css := . }}
- {{ $entry := slice $dynamic_sources_res $main_css | resources.Concat "css/_entry.css" }}
+ {{ $entry_parts := slice $dynamic_sources_res $main_css }}
+
+ {{/* Auto-discover co-located block CSS: shared utilities first, then per-block styles */}}
+ {{ range resources.Match "css/hbx/blocks/shared/**/*.css" }}
+ {{ $entry_parts = $entry_parts | append . }}
+ {{ end }}
+ {{ range resources.Match "css/hbx/blocks/**/style.css" }}
+ {{ $entry_parts = $entry_parts | append . }}
+ {{ end }}
+
+ {{/* Community block CSS (mounted by templates into dist/community/blox/) */}}
+ {{ range resources.Match "dist/community/blox/**/*.css" }}
+ {{ $entry_parts = $entry_parts | append . }}
+ {{ end }}
+
+ {{ $entry := $entry_parts | resources.Concat "css/_entry.css" }}
{{ $opts := dict "minify" (not hugo.IsDevelopment) }}
{{ with $entry | css.TailwindCSS $opts }}
{{ if hugo.IsDevelopment }}
diff --git a/modules/blox/layouts/_partials/site_head.html b/modules/blox/layouts/_partials/site_head.html
index b8f5c5a4..1585d2ce 100644
--- a/modules/blox/layouts/_partials/site_head.html
+++ b/modules/blox/layouts/_partials/site_head.html
@@ -70,16 +70,6 @@
{{ partial "css.html" . }}
{{ end }}
- {{/* Load community blox styles */}}
- {{ $hb_community_styles := resources.Match "dist/community/blox/**.css" }}
- {{ with $hb_community_styles }}
- {{ $hb_community_styles = $hb_community_styles | resources.Concat "css/community-hugo-blox.css" }}
- {{- if hugo.IsProduction -}}
- {{- $hb_community_styles = $hb_community_styles | minify | fingerprint "sha256" -}}
- {{- end -}}
-
- {{ end }}
-
{{ if fileExists "assets/css/custom.css" }}
{{ $styles := resources.Get "css/custom.css" | minify | fingerprint "sha256" }}