- Added support for --config in generate_theme_previews.sh, with config resolution aligned to the main build flow: command-line override first, then BSSG_LCONF, then local/default config files.

- Improved theme preview generation so it now loads the effective BSSG config once, reuses configured SITE_URL, OUTPUT_DIR, THEMES_DIR, and TEMPLATES_DIR, and passes the selected config through to each preview build.
- Improved preview output path detection for external site setups, so previews are generated under the correct site example directory instead of assuming the project root layout.
- Standardized list-page article headings from <h3> to <h2> across homepage, archives, authors, tags, and secondary pages, improving heading hierarchy and semantic consistency.
- Fixed Open Graph URL generation in templates/header.html by concatenating {{site_url}}{{page_url}} directly, and normalized page URL placeholders to leading-slash paths like /, /archives/, /authors/..., and /pages.html.
- Updated theme stylesheets to match the new list markup, switching post-list selectors from .posts-list h3 to .posts-list h2 and preserving hover, focus, spacing, and responsive typography rules.
- Adjusted themes with decorative h2 treatments so post listings do not inherit unwanted heading ornaments or pseudo-elements after the heading-level change.
This commit is contained in:
Stefano Marinelli 2026-03-18 11:35:13 +01:00
parent 37c5a2283e
commit 608a82aec4
65 changed files with 240 additions and 150 deletions

View file

@ -1061,11 +1061,22 @@ You can also specify a custom SITE_URL for the previews:
./generate_theme_previews.sh --site-url "https://example.com/blog"
```
The script will use the SITE_URL from the following sources in order of precedence:
1. Command line argument (--site-url)
2. Local config file (config.sh.local)
3. Main config file (config.sh)
4. Default value (http://localhost)
You can also point the preview generator at a site-specific config file, just like `bssg.sh build`:
```bash
./generate_theme_previews.sh --config /path/to/site/config.sh.local
```
BSSG configuration is resolved in this order:
1. Command line argument (`--config`)
2. `BSSG_LCONF` environment variable
3. Local config file (`config.sh.local`)
4. Main config file (`config.sh`)
The preview `SITE_URL` is then chosen from:
1. Command line argument (`--site-url`)
2. The selected BSSG configuration
3. Default value (`http://localhost`)
Each theme preview will be accessible at `SITE_URL/theme` (e.g., `https://example.com/blog/dark`).

View file

@ -11,9 +11,13 @@ set -euo pipefail
# Ensure BSSG_MAIN_SCRIPT points to the main bssg.sh in the project root
# Ensure this script (generate_theme_previews.sh) is run from the project root.
readonly BSSG_MAIN_SCRIPT="./bssg.sh"
readonly THEMES_DIR="./themes"
THEMES_DIR="./themes"
TEMPLATES_DIR="./templates"
CONFIG_FILE="config.sh" # For reading default SITE_URL if not overridden
LOCAL_CONFIG_FILE="config.sh.local" # For reading default SITE_URL if not overridden
CMD_LINE_CONFIG_FILE=""
FINAL_CONFIG_OVERRIDE=""
site_url_from_cli=""
# Global variable for the dynamic example root directory
EXAMPLE_ROOT_DIR_DYNAMIC="./example" # Default value, will be updated
@ -64,16 +68,22 @@ Generate preview sites for all available BSSG themes.
Options:
-h, --help Display this help message and exit
--config PATH Use a custom BSSG configuration file
--site-url URL Set the base SITE_URL for theme previews
(overrides config files)
--full-build Build each theme independently (slower fallback mode)
Configuration:
BSSG configuration is selected in this order:
1. Command line argument (--config)
2. BSSG_LCONF environment variable
3. Local config file ($LOCAL_CONFIG_FILE)
4. Main config file ($CONFIG_FILE)
The script will use the SITE_URL from the following sources in order of precedence:
1. Command line argument (--site-url)
2. Local config file ($LOCAL_CONFIG_FILE)
3. Main config file ($CONFIG_FILE)
4. Default value (http://localhost)
2. Selected BSSG configuration
3. Default value (http://localhost)
Output:
Theme previews will be generated in the '$EXAMPLE_ROOT_DIR_DYNAMIC' directory,
@ -90,13 +100,19 @@ EOF
# --- Parse Command Line Arguments (for this script) ---
parse_args() {
site_url_from_cli="" # Made global for load_config
while [[ $# -gt 0 ]]; do
case "$1" in
-h|--help)
print_help
;;
--config)
if [[ -n "${2:-}" && "$2" != -* ]]; then
CMD_LINE_CONFIG_FILE="$2"
shift 2
else
error "--config requires a path to a BSSG configuration file"
fi
;;
--site-url)
if [[ -n "${2:-}" ]]; then
site_url_from_cli="$2"
@ -117,41 +133,50 @@ parse_args() {
done
}
resolve_config_override() {
if [ -n "$CMD_LINE_CONFIG_FILE" ]; then
FINAL_CONFIG_OVERRIDE="$CMD_LINE_CONFIG_FILE"
info "Using configuration file specified via --config: $FINAL_CONFIG_OVERRIDE"
elif [ -v BSSG_LCONF ] && [ -n "${BSSG_LCONF}" ]; then
FINAL_CONFIG_OVERRIDE="$BSSG_LCONF"
info "Using configuration file specified via BSSG_LCONF: $FINAL_CONFIG_OVERRIDE"
fi
}
load_effective_bssg_configuration() {
local project_root_abs config_dump
local config_separator=$'\037'
project_root_abs=$(pwd -P)
config_dump=$(
export BSSG_SCRIPT_DIR="$project_root_abs"
bash -c '
source "$BSSG_SCRIPT_DIR/scripts/build/config_loader.sh" "$1" >/dev/null 2>&1
printf "%s\037%s\037%s\037%s" "$SITE_URL" "$OUTPUT_DIR" "$THEMES_DIR" "$TEMPLATES_DIR"
' bash "$FINAL_CONFIG_OVERRIDE"
) || {
if [ -n "$FINAL_CONFIG_OVERRIDE" ]; then
error "Failed to load BSSG configuration from '$FINAL_CONFIG_OVERRIDE'."
fi
error "Failed to load the default BSSG configuration."
}
IFS="$config_separator" read -r SITE_URL OUTPUT_DIR THEMES_DIR TEMPLATES_DIR <<< "$config_dump"
}
# --- Load Configuration (for this script's SITE_URL_BASE) ---
load_config() {
info "Loading base SITE_URL configuration for previews..."
if [ -f "$CONFIG_FILE" ]; then
# Portable way to extract SITE_URL="value"
local main_conf_site_url
main_conf_site_url=$(awk -F'"' '/^SITE_URL=/ {print $2; exit}' "$CONFIG_FILE")
if [ -n "$main_conf_site_url" ]; then
SITE_URL_BASE="$main_conf_site_url"
info "Using SITE_URL_BASE='$SITE_URL_BASE' from $CONFIG_FILE as default"
fi
else
warn "Main configuration file '$CONFIG_FILE' not found, using default SITE_URL_BASE='$SITE_URL_BASE'."
fi
if [ -f "$LOCAL_CONFIG_FILE" ]; then
local local_conf_site_url
# Check if SITE_URL is actually defined in the local config
if grep -q "^SITE_URL=" "$LOCAL_CONFIG_FILE" 2>/dev/null; then
local_conf_site_url=$(awk -F'"' '/^SITE_URL=/ {print $2; exit}' "$LOCAL_CONFIG_FILE")
if [ -n "$local_conf_site_url" ]; then
SITE_URL_BASE="$local_conf_site_url"
info "Overridden SITE_URL_BASE='$SITE_URL_BASE' from $LOCAL_CONFIG_FILE"
else
warn "Found $LOCAL_CONFIG_FILE but failed to extract SITE_URL, using current SITE_URL_BASE='$SITE_URL_BASE'"
fi
fi
fi
load_effective_bssg_configuration
SITE_URL_BASE="$SITE_URL"
info "Using SITE_URL_BASE='$SITE_URL_BASE' from the effective BSSG configuration"
if [ -n "$site_url_from_cli" ]; then
SITE_URL_BASE="$site_url_from_cli"
info "Using SITE_URL_BASE='$SITE_URL_BASE' from command line argument for previews"
fi
success "Configuration loaded. Using SITE_URL_BASE='$SITE_URL_BASE' for theme previews."
}
@ -287,6 +312,21 @@ find_themes() {
info "Found ${#themes[@]} themes: ${themes[*]}"
}
run_bssg_build() {
local -a cmd=("$BSSG_MAIN_SCRIPT")
local formatted_cmd
if [ -n "$FINAL_CONFIG_OVERRIDE" ]; then
cmd+=(--config "$FINAL_CONFIG_OVERRIDE")
fi
cmd+=(build "$@")
formatted_cmd=$(printf '%q ' "${cmd[@]}")
info "Executing: ${formatted_cmd% }"
"${cmd[@]}"
}
build_previews() {
prepare_example_directory
@ -324,7 +364,11 @@ prepare_example_directory() {
build_previews_full() {
info "Starting theme preview builds..."
info "Previews will use content from the BSSG site configured by your standard config.sh/config.sh.local files."
if [ -n "$FINAL_CONFIG_OVERRIDE" ]; then
info "Previews will use content from the BSSG site configured by '$FINAL_CONFIG_OVERRIDE'."
else
info "Previews will use content from the BSSG site configured by your standard config.sh/config.sh.local files."
fi
for theme in "${themes[@]}"; do
info "Building preview for theme: '$theme'"
@ -337,9 +381,7 @@ build_previews_full() {
mkdir -p "$theme_output_path"
info "Executing: $BSSG_MAIN_SCRIPT build -f --theme \"$theme\" --site-url \"$theme_site_url\" --output \"$theme_output_path\""
if ! "$BSSG_MAIN_SCRIPT" build -f --theme "$theme" --site-url "$theme_site_url" --output "$theme_output_path"; then
if ! run_bssg_build -f --theme "$theme" --site-url "$theme_site_url" --output "$theme_output_path"; then
error "Build failed for theme '$theme'. Check output above."
fi
success "Preview for theme '$theme' built successfully in '$theme_output_path'"
@ -349,7 +391,7 @@ build_previews_full() {
}
has_theme_specific_templates() {
local template_root="./templates"
local template_root="$TEMPLATES_DIR"
local theme
for theme in "${themes[@]}"; do
if [ -d "$template_root/$theme" ]; then
@ -400,7 +442,7 @@ build_previews_fast() {
fi
info "Building base preview once with theme '$base_theme' and SITE_URL token '$SITE_URL_TOKEN'..."
if ! "$BSSG_MAIN_SCRIPT" build -f --theme "$base_theme" --site-url "$SITE_URL_TOKEN" --output "$base_output_path"; then
if ! run_bssg_build -f --theme "$base_theme" --site-url "$SITE_URL_TOKEN" --output "$base_output_path"; then
error "Base build failed in fast preview mode."
fi
@ -572,22 +614,17 @@ determine_example_root_dir() {
# Portable way to get absolute path of current directory
project_root_abs=$( (cd . && pwd -P) || { error "Could not determine project root."; exit 1; } )
local effective_output_dir
effective_output_dir=$(export BSSG_SCRIPT_DIR="$project_root_abs"; \
bash -c 'source "$BSSG_SCRIPT_DIR/scripts/build/config_loader.sh" "" &>/dev/null; echo "$OUTPUT_DIR"')
if [ -z "$effective_output_dir" ]; then
if [ -z "${OUTPUT_DIR:-}" ]; then
warn "Could not determine effective OUTPUT_DIR from BSSG configuration. Defaulting EXAMPLE_ROOT_DIR_DYNAMIC to '$EXAMPLE_ROOT_DIR_DYNAMIC'."
return
fi
info "Effective OUTPUT_DIR from BSSG configuration: '$effective_output_dir'"
info "Effective OUTPUT_DIR from BSSG configuration: '$OUTPUT_DIR'"
local effective_output_dir_abs_unnormalized
if [[ "$effective_output_dir" == /* ]]; then
effective_output_dir_abs_unnormalized="$effective_output_dir"
if [[ "$OUTPUT_DIR" == /* ]]; then
effective_output_dir_abs_unnormalized="$OUTPUT_DIR"
else
effective_output_dir_abs_unnormalized="$project_root_abs/$effective_output_dir"
effective_output_dir_abs_unnormalized="$project_root_abs/$OUTPUT_DIR"
fi
# Normalize the path using our helper (handles ., .., and non-existent paths)
@ -605,7 +642,7 @@ determine_example_root_dir() {
fi
if [[ "$site_root_candidate" != "$project_root_abs" && "$effective_output_dir" == /* ]]; then
if [[ "$site_root_candidate" != "$project_root_abs" && "$OUTPUT_DIR" == /* ]]; then
info "Detected external site configuration. Previews will be generated in '$site_root_candidate/example'."
EXAMPLE_ROOT_DIR_DYNAMIC="$site_root_candidate/example"
else
@ -622,6 +659,7 @@ main() {
declare -a themes
parse_args "$@"
resolve_config_override
load_config
check_dependencies
determine_example_root_dir

View file

@ -133,7 +133,7 @@ _generate_ram_month_archive_page() {
cat << EOF
<article>
<h3><a href="${post_url}">$title</a></h3>
<h2><a href="${post_url}">$title</a></h2>
<div class="meta">${MSG_PUBLISHED_ON:-\"Published on\"} $formatted_date ${MSG_BY:-\"by\"} <strong>$display_author_name</strong></div>
EOF
if [ -n "$image" ]; then
@ -201,7 +201,7 @@ _generate_archive_pages_ram() {
header_content=${header_content//\{\{og_description\}\}/"$SITE_DESCRIPTION"}
header_content=${header_content//\{\{twitter_description\}\}/"$SITE_DESCRIPTION"}
header_content=${header_content//\{\{og_type\}\}/"website"}
header_content=${header_content//\{\{page_url\}\}/"archives/"}
header_content=${header_content//\{\{page_url\}\}/"/archives/"}
header_content=${header_content//\{\{site_url\}\}/"$SITE_URL"}
header_content=${header_content//\{\{og_image\}\}/""}
header_content=${header_content//\{\{twitter_image\}\}/""}
@ -402,7 +402,7 @@ _generate_main_archive_index() {
header_content=${header_content//\{\{og_description\}\}/"$SITE_DESCRIPTION"}
header_content=${header_content//\{\{twitter_description\}\}/"$SITE_DESCRIPTION"}
header_content=${header_content//\{\{og_type\}\}/"website"}
header_content=${header_content//\{\{page_url\}\}/"archives/"} # Relative URL for header placeholder
header_content=${header_content//\{\{page_url\}\}/"/archives/"} # Relative URL for header placeholder
header_content=${header_content//\{\{site_url\}\}/"$SITE_URL"}
header_content=${header_content//\{\{og_image\}\}/""}
header_content=${header_content//\{\{twitter_image\}\}/""}
@ -685,7 +685,7 @@ process_single_month() {
# Use cat heredoc for multi-line article structure
cat << EOF
<article>
<h3><a href="${post_url}">$title</a></h3>
<h2><a href="${post_url}">$title</a></h2>
<div class="meta">${MSG_PUBLISHED_ON:-\"Published on\"} $formatted_date ${MSG_BY:-\"by\"} <strong>$display_author_name</strong></div>
EOF

View file

@ -49,7 +49,7 @@ _generate_author_pages_ram() {
local author_data="${author_posts_by_slug[$author_slug_key]}"
local author_page_html_file="$OUTPUT_DIR/authors/$author_slug_key/index.html"
local author_rss_file="$OUTPUT_DIR/authors/$author_slug_key/${RSS_FILENAME:-rss.xml}"
local author_page_rel_url="authors/${author_slug_key}/"
local author_page_rel_url="/authors/${author_slug_key}/"
local author_rss_rel_url="/authors/${author_slug_key}/${RSS_FILENAME:-rss.xml}"
local post_count
post_count=$(printf '%s\n' "$author_data" | awk 'NF { c++ } END { print c+0 }')
@ -169,7 +169,7 @@ _generate_author_pages_ram() {
header_content=${header_content//\{\{og_description\}\}/"$page_description"}
header_content=${header_content//\{\{twitter_description\}\}/"$page_description"}
header_content=${header_content//\{\{og_type\}\}/"website"}
header_content=${header_content//\{\{page_url\}\}/"authors/"}
header_content=${header_content//\{\{page_url\}\}/"/authors/"}
header_content=${header_content//\{\{site_url\}\}/"$SITE_URL"}
header_content=${header_content//\{\{og_image\}\}/}
header_content=${header_content//\{\{twitter_image\}\}/}
@ -364,7 +364,7 @@ generate_author_pages() {
if [ -n "$author" ]; then
local author_page_html_file="$OUTPUT_DIR/authors/$author_slug/index.html"
local author_rss_file="$OUTPUT_DIR/authors/$author_slug/${RSS_FILENAME:-rss.xml}"
local author_page_rel_url="authors/${author_slug}/"
local author_page_rel_url="/authors/${author_slug}/"
local author_rss_rel_url="/authors/${author_slug}/${RSS_FILENAME:-rss.xml}"
local rebuild_html=false
local rebuild_rss=false
@ -620,7 +620,7 @@ generate_author_pages() {
# Generate full HTML page for main authors index
local page_title="${MSG_ALL_AUTHORS:-All Authors}"
local page_description="${MSG_ALL_AUTHORS:-All Authors} - $SITE_DESCRIPTION"
local authors_index_rel_url="authors/"
local authors_index_rel_url="/authors/"
# Process templates with placeholder replacement (following tags generator pattern)
local header_content="$HEADER_TEMPLATE"

View file

@ -43,7 +43,7 @@ _generate_index_ram() {
page_header=${page_header//\{\{site_title\}\}/"$SITE_TITLE"}
page_header=${page_header//\{\{page_title\}\}/"${MSG_HOME:-"Home"}"}
page_header=${page_header//\{\{og_type\}\}/"website"}
page_header=${page_header//\{\{page_url\}\}/""}
page_header=${page_header//\{\{page_url\}\}/"/"}
page_header=${page_header//\{\{site_url\}\}/"$SITE_URL"}
local home_schema
home_schema=$(cat <<EOF
@ -192,7 +192,7 @@ EOF
cat >> "$output_file" <<EOF
<article>
<h3><a href="$(fix_url "$post_link")">$title</a></h3>
<h2><a href="$(fix_url "$post_link")">$title</a></h2>
<div class="meta">${MSG_PUBLISHED_ON:-"Published on"} $formatted_date${author_name:+" ${MSG_BY:-"by"} ${author_name:-$AUTHOR_NAME}"}</div>
EOF
@ -365,7 +365,7 @@ generate_index() {
# For the homepage
page_header=${page_header//\{\{page_title\}\}/"${MSG_HOME:-"Home"}"}
page_header=${page_header//\{\{og_type\}\}/"website"}
page_header=${page_header//\{\{page_url\}\}/""}
page_header=${page_header//\{\{page_url\}\}/"/"}
page_header=${page_header//\{\{site_url\}\}/"$SITE_URL"}
# Create WebSite schema for homepage
@ -506,7 +506,7 @@ EOF
local post_link="/$formatted_path/"
cat >> "$output_file" << EOF
<article>
<h3><a href="$(fix_url "$post_link")">$title</a></h3>
<h2><a href="$(fix_url "$post_link")">$title</a></h2>
<div class="meta">${MSG_PUBLISHED_ON:-"Published on"} $formatted_date${author_name:+" ${MSG_BY:-"by"} ${author_name:-$AUTHOR_NAME}"}</div>
EOF
if [ -n "$image" ]; then

View file

@ -87,7 +87,7 @@ generate_pages_index() {
header_content=${header_content//\{\{og_type\}\}/"website"}
# Set proper URL in og:url
header_content=${header_content//\{\{page_url\}\}/"pages.html"}
header_content=${header_content//\{\{page_url\}\}/"/pages.html"}
header_content=${header_content//\{\{site_url\}\}/"$SITE_URL"}
# Generate CollectionPage schema
@ -135,7 +135,7 @@ EOF
IFS='|' read -r title url _ <<< "$page" # Ignore date for menu
cat >> "$pages_index" << EOF
<article>
<h3><a href="$url">$title</a></h3>
<h2><a href="$url">$title</a></h2>
</article>
EOF
done

View file

@ -291,7 +291,7 @@ _generate_tag_pages_ram() {
local display_author_name="${author_name:-${AUTHOR_NAME:-Anonymous}}"
local article_html=""
article_html+=' <article>'$'\n'
article_html+=" <h3><a href=\"${SITE_URL}${post_link}\">${title}</a></h3>"$'\n'
article_html+=" <h2><a href=\"${SITE_URL}${post_link}\">${title}</a></h2>"$'\n'
article_html+=" <div class=\"meta\">${MSG_PUBLISHED_ON:-Published on} ${formatted_date} ${MSG_BY:-by} <strong>${display_author_name}</strong></div>"$'\n'
if [ -n "$image" ]; then
local image_url alt_text figcaption_content
@ -939,7 +939,7 @@ EOF
cat >> "$tag_page_html_file" << EOF
<article>
<h3><a href="${SITE_URL}${post_link}">$title</a></h3>
<h2><a href="${SITE_URL}${post_link}">$title</a></h2>
<div class="meta">${MSG_PUBLISHED_ON:-"Published on"} $formatted_date ${MSG_BY:-"by"} <strong>$display_author_name</strong></div>
EOF

View file

@ -8,7 +8,7 @@
<meta property="og:title" content="{{page_title}}">
<meta property="og:description" content="{{og_description}}">
<meta property="og:type" content="{{og_type}}">
<meta property="og:url" content="{{site_url}}/{{page_url}}">
<meta property="og:url" content="{{site_url}}{{page_url}}">
{{og_image}}
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="{{page_title}}">

View file

@ -890,7 +890,7 @@ hr {
margin-bottom: 20px;
}
.posts-list h2, .posts-list h3 {
.posts-list h2 {
margin-top: 0;
margin-bottom: 0.5rem;
}

View file

@ -225,6 +225,7 @@ h2 {
font-size: 1.3rem;
}
.posts-list h2,
h3 {
font-size: 1.2rem;
}

View file

@ -691,7 +691,7 @@ figcaption {
margin-bottom: 3rem;
}
.posts-list h3 {
.posts-list h2 {
margin-top: 0;
font-size: 1.8rem;
text-align: center;

View file

@ -244,6 +244,7 @@ h2 {
font-size: 1.4rem;
}
.posts-list h2,
h3 {
font-size: 1.2rem;
}
@ -593,6 +594,7 @@ footer a:focus {
font-size: 1.2rem;
}
.posts-list h2,
h3 {
font-size: 1.1rem;
}

View file

@ -486,7 +486,7 @@ footer a:focus {
border-bottom: none;
}
.posts-list h3 {
.posts-list h2 {
margin-top: 0;
font-size: 1.8rem;
}

View file

@ -315,11 +315,13 @@ h2::before {
color: var(--accent-1);
}
.posts-list h2,
h3 {
font-size: 1.3rem;
color: var(--link-hover);
}
.posts-list h2::before,
h3::before {
content: "> ";
color: var(--accent-1);
@ -920,6 +922,7 @@ hr::before {
font-size: 1.4rem;
}
.posts-list h2,
h3 {
font-size: 1.2rem;
}
@ -975,6 +978,7 @@ hr::before {
font-size: 1.2rem;
}
.posts-list h2,
h3 {
font-size: 1.1rem;
}
@ -988,4 +992,4 @@ hr::before {
font-size: 0.8rem;
padding: 6px 8px;
}
}
}

View file

@ -252,6 +252,7 @@ h2 {
font-size: 1.6rem;
}
.posts-list h2,
h3 {
font-size: 1.4rem;
}
@ -717,6 +718,7 @@ tr:nth-child(even) {
font-size: 1.4rem;
}
.posts-list h2,
h3 {
font-size: 1.2rem;
}

View file

@ -637,7 +637,7 @@ hr {
margin-bottom: 2rem;
}
.posts-list h2, .posts-list h3 {
.posts-list h2 {
margin-top: 0;
margin-bottom: 0.5rem;
}

View file

@ -441,7 +441,7 @@ footer a:focus {
padding-bottom: 0;
}
.posts-list h3 {
.posts-list h2 {
margin-top: 0;
font-size: 1.5rem;
margin-bottom: calc(var(--grid-size) * 1);

View file

@ -266,6 +266,7 @@ h2 {
letter-spacing: -1px;
}
.posts-list h2,
h3 {
font-size: 1.5rem;
}
@ -667,6 +668,7 @@ footer a:focus {
font-size: 1.8rem;
}
.posts-list h2,
h3 {
font-size: 1.5rem;
}
@ -741,6 +743,7 @@ footer a:focus {
font-size: 1.6rem;
}
.posts-list h2,
h3 {
font-size: 1.4rem;
}
@ -795,6 +798,7 @@ footer a:focus {
font-size: 1.5rem;
}
.posts-list h2,
h3 {
font-size: 1.3rem;
}

View file

@ -481,12 +481,12 @@ hr {
margin-bottom: 2rem;
}
.posts-list h2, .posts-list h3 {
.posts-list h2 {
margin-top: 0;
margin-bottom: 0.5rem;
}
.posts-list h2::before, .posts-list h3::before {
.posts-list h2::before {
content: ">";
margin-right: 0.5rem;
color: var(--link-color);

View file

@ -18,6 +18,7 @@ a { font-family:sans-serif; color:var(--highlight2); text-decoration:none; }
body { font-size:1.1em; color:var(--text); padding:0.2em; font-family:sans-serif; max-width:60em; margin:auto; line-height:1.5; }
h1 { font-size:2em; color:var(--highlight1); text-shadow:0 0 20px; }
h2 { font-size:1.7em; color:var(--highlight1); text-shadow:0 0 20px; }
.posts-list h2,
h3 { font-size:1.4em; color:var(--highlight1); text-shadow:0 0 20px; }
nav { display:block; text-align:center; padding-top:0.8em; padding-bottom:3.5em; }
nav { a { padding-left:0.5em; padding-right:0.5em; text-decoration:underline var(--highlight1); text-shadow:0 0 9px var(--highlight1); } }
@ -26,7 +27,7 @@ p { padding-top:0.5em; padding-bottom:0.5em; }
header { text-align:center; margin:auto; }
header { p { text-shadow:0 0 10px var(--highlight2); } }
img { display:block; max-width: 100%; margin: auto; padding-top: 20px; padding-bottom: 20px; }
.posts-list { h3 { a { color:var(--highlight1); text-decoration: underline var(--highlight2); text-shadow:0 0 15px var(--highlight2); } } }
.posts-list { h2 { a { color:var(--highlight1); text-decoration: underline var(--highlight2); text-shadow:0 0 15px var(--highlight2); } } }
.featured-image.index-image { img { display:block; max-width: 100%; max-height:640px; margin: auto; padding-top: 20px; padding-bottom: 20px; } }
.image-caption { color:var(--muted-text); text-align: center; }
.site-title { a { text-shadow:0 0 30px var(--highlight2); text-decoration:underline 2px var(--highlight2); font-size:3em; font-weight:bold; color:var(--highlight1); }}

View file

@ -525,7 +525,7 @@ footer::before {
padding-bottom: 1.5rem;
}
.posts-list h3 {
.posts-list h2 {
margin-top: 0;
margin-bottom: 0.5rem;
}

View file

@ -742,18 +742,18 @@ hr::before {
padding-bottom: 1.5rem;
}
.posts-list h2, .posts-list h3 {
.posts-list h2 {
margin-top: 0;
margin-bottom: 0.5rem;
}
.posts-list h2 a, .posts-list h3 a {
.posts-list h2 a {
outline: 2px solid transparent;
outline-offset: 2px;
border-radius: 2px;
}
.posts-list h2 a:focus, .posts-list h3 a:focus {
.posts-list h2 a:focus {
outline-color: var(--link-color);
}

View file

@ -336,10 +336,15 @@ h2::after {
background: linear-gradient(to right, var(--accent-primary), transparent);
}
.posts-list h2,
h3 {
font-size: 1.5rem;
}
.posts-list h2::after {
content: none;
}
h4 {
font-size: 1.25rem;
}
@ -822,6 +827,7 @@ article {
font-size: 1.6rem;
}
.posts-list h2,
h3 {
font-size: 1.3rem;
}
@ -878,6 +884,7 @@ article {
font-size: 1.5rem;
}
.posts-list h2,
h3 {
font-size: 1.25rem;
}
@ -1007,6 +1014,7 @@ article {
font-size: 1.4rem;
}
.posts-list h2,
h3 {
font-size: 1.2rem;
}

View file

@ -319,8 +319,7 @@ hr {
margin-top: 0.95rem;
}
.posts-list h2,
.posts-list h3 {
.posts-list h2 {
margin-top: 0;
}

View file

@ -228,6 +228,7 @@ h2 {
margin-top: 40px;
}
.posts-list h2,
h3 {
font-size: 20px;
margin-top: 30px;
@ -605,6 +606,7 @@ footer a:focus::after {
font-size: 24px;
}
.posts-list h2,
h3 {
font-size: 18px;
}
@ -727,6 +729,7 @@ footer a:focus::after {
margin-top: 30px;
}
.posts-list h2,
h3 {
font-size: 17px;
margin-top: 20px;
@ -794,6 +797,7 @@ footer a:focus::after {
font-size: 18px;
}
.posts-list h2,
h3 {
font-size: 16px;
}

View file

@ -358,8 +358,7 @@ hr {
margin-top: 0.85rem;
}
.posts-list h2,
.posts-list h3 {
.posts-list h2 {
margin-top: 0;
}

View file

@ -262,6 +262,7 @@ h2 {
font-size: 2rem;
}
.posts-list h2,
h3 {
font-size: 1.5rem;
}

View file

@ -632,16 +632,16 @@ footer a:focus {
box-shadow: var(--floating-shadow);
}
.posts-list h3 {
.posts-list h2 {
margin-top: 0;
margin-bottom: var(--spacing-xs);
}
.posts-list h3 a {
.posts-list h2 a {
color: var(--header-color);
}
.posts-list h3 a:hover, .posts-list h3 a:active {
.posts-list h2 a:hover, .posts-list h2 a:active {
color: var(--accent-color);
}

View file

@ -290,8 +290,7 @@ h3 { font-size: clamp(1.18rem, 1.8vw, 1.4rem); }
article.post > h1,
article.page > h1,
.posts-list h2,
.posts-list h3 {
.posts-list h2 {
margin-top: 0;
}

View file

@ -562,17 +562,17 @@ main > h1 {
border-bottom: none;
}
.posts-list h3 {
.posts-list h2 {
margin-top: 0;
font-size: 1.8rem;
}
.posts-list h3 a {
.posts-list h2 a {
color: var(--heading-color);
text-decoration: none;
}
.posts-list h3 a:hover {
.posts-list h2 a:hover {
color: var(--link-color);
}

View file

@ -577,7 +577,7 @@ footer {
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.posts-list h3 {
.posts-list h2 {
margin-top: 0;
margin-bottom: 5px;
}

View file

@ -501,7 +501,7 @@ footer {
border-bottom: 1px solid var(--accent-color);
}
.posts-list h3 {
.posts-list h2 {
margin-top: 0;
margin-bottom: 0.3em;
}

View file

@ -345,6 +345,7 @@ h2 {
margin-top: var(--spacing-xl);
}
.posts-list h2,
h3 {
font-size: 1.3rem;
color: var(--mario-pipe-green);

View file

@ -312,6 +312,7 @@ nav a.active::after {
font-size: 1.75rem;
}
.posts-list h2,
h3 {
font-size: 1.35rem;
}
@ -351,6 +352,7 @@ nav a.active::after {
font-size: 1.5rem;
}
.posts-list h2,
h3 {
font-size: 1.25rem;
}
@ -426,6 +428,7 @@ nav a.active::after {
font-size: 1.35rem;
}
.posts-list h2,
h3 {
font-size: 1.15rem;
}
@ -502,6 +505,7 @@ nav a.active::after {
font-size: 1.2rem;
}
.posts-list h2,
h3 {
font-size: 1.05rem;
}
@ -583,6 +587,7 @@ h2 {
letter-spacing: -0.01em;
}
.posts-list h2,
h3 {
font-size: 1.5rem;
}

View file

@ -355,8 +355,7 @@ hr {
margin-top: 0.9rem;
}
.posts-list h2,
.posts-list h3 {
.posts-list h2 {
margin-top: 0;
}

View file

@ -630,7 +630,7 @@ img {
transform: translateX(5px);
}
.posts-list h3 {
.posts-list h2 {
margin-top: 0;
font-size: 1.8rem;
}

View file

@ -467,18 +467,18 @@ footer a:focus {
margin-bottom: 1.75rem;
}
.posts-list h3 {
.posts-list h2 {
margin-top: 0;
margin-bottom: 0.5rem;
}
.posts-list h3 a {
.posts-list h2 a {
outline: 2px solid transparent;
outline-offset: 2px;
transition: outline-color var(--transition);
}
.posts-list h3 a:focus {
.posts-list h2 a:focus {
outline-color: var(--link-color);
}

View file

@ -579,7 +579,7 @@ figcaption,
margin-bottom: 1rem;
}
.posts-list h3 {
.posts-list h2 {
margin-top: 0;
font-size: 1.8rem;
text-align: left;

View file

@ -264,6 +264,7 @@ h2 {
margin-top: calc(var(--spacing-unit) * 3);
}
.posts-list h2,
h3 {
font-size: 1.1rem;
margin-top: calc(var(--spacing-unit) * 2.5);

View file

@ -299,8 +299,7 @@ pre code {
margin-top: 1rem;
}
.posts-list h2,
.posts-list h3 {
.posts-list h2 {
margin-top: 0;
}

View file

@ -203,8 +203,7 @@ h3 {
article.post > h1,
article.page > h1,
.posts-list h2,
.posts-list h3 {
.posts-list h2 {
margin-top: 0;
}

View file

@ -607,23 +607,23 @@ blockquote p:last-child {
transform: scale(1.01);
}
.posts-list h3 {
.posts-list h2 {
margin-top: 0;
font-size: 1.1rem;
margin-bottom: var(--spacing-sm);
}
.posts-list h3 a {
.posts-list h2 a {
color: var(--nes-light-blue);
text-decoration: none;
}
.posts-list h3 a:hover {
.posts-list h2 a:hover {
color: var(--nes-light-yellow);
}
/* ACCESSIBILITY: Focus states for post list links */
.posts-list h3 a:focus {
.posts-list h2 a:focus {
outline: 2px solid var(--nes-light-yellow);
outline-offset: 2px;
color: var(--nes-light-yellow);

View file

@ -372,8 +372,7 @@ hr {
margin-top: 0.82rem;
}
.posts-list h2,
.posts-list h3 {
.posts-list h2 {
margin-top: 0;
}

View file

@ -529,7 +529,7 @@ footer::after {
margin-bottom: var(--spacing-lg);
}
.posts-list h3 {
.posts-list h2 {
margin-top: var(--spacing-xs);
font-size: 1.6rem;
text-transform: uppercase;
@ -538,18 +538,18 @@ footer::after {
text-align: center;
}
.posts-list h3 a {
.posts-list h2 a {
color: var(--header-color);
text-decoration: none;
transition: color 0.2s;
}
.posts-list h3 a:hover {
.posts-list h2 a:hover {
color: var(--link-color);
}
/* ACCESSIBILITY: Focus states for post list links */
.posts-list h3 a:focus {
.posts-list h2 a:focus {
outline: 2px solid var(--link-color);
outline-offset: 2px;
color: var(--link-color);

View file

@ -275,6 +275,7 @@ h2 {
font-size: 1.6rem;
}
.posts-list h2,
h3 {
font-size: 1.4rem;
}

View file

@ -544,7 +544,7 @@ footer a:focus {
padding-bottom: 0;
}
.posts-list h3 {
.posts-list h2 {
margin-top: 0;
font-size: 1.8rem;
margin-bottom: var(--spacing-sm);

View file

@ -373,8 +373,7 @@ hr {
margin-top: 0.78rem;
}
.posts-list h2,
.posts-list h3 {
.posts-list h2 {
margin-top: 0;
}

View file

@ -502,16 +502,16 @@ footer {
border-color: var(--border-color);
}
.posts-list h3 {
.posts-list h2 {
margin-top: 0;
margin-bottom: var(--spacing-xs);
}
.posts-list h3 a {
.posts-list h2 a {
color: var(--header-color);
}
.posts-list h3 a:hover {
.posts-list h2 a:hover {
color: var(--accent-color);
text-decoration: none;
}

View file

@ -525,13 +525,13 @@ figcaption {
border-bottom: none;
}
.posts-list h3 {
.posts-list h2 {
margin-top: 0;
text-align: center;
margin-bottom: var(--spacing-sm);
}
.posts-list h3 a {
.posts-list h2 a {
color: var(--heading-color);
text-decoration: none;
transition: color var(--transition-base) ease;
@ -539,13 +539,13 @@ figcaption {
outline: none;
}
.posts-list h3 a:hover {
.posts-list h2 a:hover {
color: var(--link-color);
text-decoration: underline;
}
/* ACCESSIBILITY: Focus states for post list links */
.posts-list h3 a:focus {
.posts-list h2 a:focus {
outline: 2px solid var(--link-color);
outline-offset: 2px;
}

View file

@ -408,6 +408,7 @@ h2 {
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.8);
}
.posts-list h2,
h3 {
font-size: 1.4rem;
color: var(--leather-medium);

View file

@ -522,21 +522,21 @@ footer {
box-shadow: 0 15px 35px rgba(0, 0, 0, 0.1);
}
.posts-list h3 {
.posts-list h2 {
margin-top: 0;
margin-bottom: var(--spacing-xs);
}
.posts-list h3 a {
.posts-list h2 a {
color: var(--header-color);
}
.posts-list h3 a:hover {
.posts-list h2 a:hover {
color: var(--accent);
}
/* ACCESSIBILITY: Focus states for post list links */
.posts-list h3 a:focus {
.posts-list h2 a:focus {
outline: 2px solid var(--link-color);
outline-offset: 2px;
color: var(--accent);

View file

@ -488,7 +488,7 @@ footer a:focus {
padding-bottom: 0;
}
.posts-list h3 {
.posts-list h2 {
margin-top: 0;
font-size: var(--text-2xl);
margin-bottom: var(--spacing-sm);

View file

@ -698,13 +698,13 @@ footer::before {
color: var(--command-prompt);
}
.posts-list h3 {
.posts-list h2 {
margin-top: var(--spacing-xs);
margin-bottom: var(--spacing-xs);
text-transform: none;
}
.posts-list h3::before {
.posts-list h2::before {
content: "";
}

View file

@ -244,7 +244,7 @@ hr {
border-bottom: 1px solid var(--color-border);
}
.posts-list h3 {
.posts-list h2 {
margin: 0;
}

View file

@ -719,25 +719,25 @@ figcaption {
border-bottom: 1px solid var(--border-light);
}
.posts-list h3 {
.posts-list h2 {
margin: 0 0 var(--space-6);
font-size: var(--text-2xl);
text-align: center;
line-height: var(--line-height-tight);
}
.posts-list h3 a {
.posts-list h2 a {
color: var(--text-primary);
text-decoration: none;
transition: color var(--transition-normal);
display: block;
}
.posts-list h3 a:hover {
.posts-list h2 a:hover {
color: var(--accent-primary);
}
.posts-list h3 a:focus {
.posts-list h2 a:focus {
outline: 2px solid var(--link-color);
outline-offset: 2px;
}

View file

@ -642,16 +642,14 @@ figcaption {
margin-bottom: var(--spacing-xs);
}
.posts-list h2,
.posts-list h3 {
.posts-list h2 {
margin-top: 0;
font-size: var(--text-md);
padding-left: 1.5em; /* Increased to prevent overlap */
position: relative;
}
.posts-list h2::before,
.posts-list h3::before {
.posts-list h2::before {
position: absolute;
left: 0;
top: 0;

View file

@ -364,6 +364,7 @@ h2 {
text-shadow: 0 0 5px var(--neon-blue);
}
.posts-list h2,
h3 {
font-size: var(--text-xl);
color: var(--neon-pink);
@ -704,6 +705,7 @@ footer a:hover {
font-size: var(--text-xl);
}
.posts-list h2,
h3 {
font-size: var(--text-lg);
}
@ -743,6 +745,7 @@ footer a:hover {
font-size: var(--text-lg);
}
.posts-list h2,
h3 {
font-size: var(--text-md);
}

View file

@ -352,6 +352,7 @@ h2 {
text-shadow: 1px 1px 1px #ff00ff;
}
.posts-list h2,
h3 {
font-size: var(--text-xl);
color: #00cc00;

View file

@ -283,6 +283,7 @@ h2 {
color: #444;
}
.posts-list h2,
h3 {
font-size: var(--text-xl);
color: #555;

View file

@ -513,7 +513,7 @@ footer {
margin-bottom: var(--spacing-md);
}
.posts-list h3 {
.posts-list h2 {
margin-top: 0;
margin-bottom: var(--spacing-xs);
color: var(--highlight-color);

View file

@ -355,6 +355,7 @@ h2 {
color: #1a73e8;
}
.posts-list h2,
h3 {
font-size: var(--text-xl);
}

View file

@ -399,7 +399,7 @@ a:hover {
border-bottom: 1px solid var(--border-color);
}
.posts-list h3 {
.posts-list h2 {
margin-top: var(--spacing-lg);
margin-bottom: var(--spacing-sm);
}

View file

@ -280,6 +280,7 @@ h1, h2, h3, h4, h5, h6 {
h1 { font-size: var(--text-2xl); }
h2 { font-size: var(--text-xl); }
.posts-list h2,
h3 { font-size: var(--text-lg); }
h4 { font-size: var(--text-md); }
@ -731,6 +732,7 @@ footer a:focus {
h1 { font-size: var(--text-3xl); }
h2 { font-size: var(--text-2xl); }
.posts-list h2,
h3 { font-size: var(--text-xl); }
h4 { font-size: var(--text-lg); }

View file

@ -328,6 +328,7 @@ h2 {
}
}
.posts-list h2,
h3 {
font-size: var(--text-lg);
color: var(--accent-blue);
@ -778,6 +779,7 @@ hr {
font-size: var(--text-lg);
}
.posts-list h2,
h3 {
font-size: var(--text-md);
}

View file

@ -268,11 +268,16 @@ h2::before {
color: var(--bright-yellow);
}
.posts-list h2,
h3 {
font-size: var(--font-size-md);
color: var(--bright-green);
}
.posts-list h2::before {
content: none;
}
p {
margin-bottom: var(--spacing-md);
line-height: var(--line-height-normal);
@ -670,4 +675,4 @@ ul, ol {
li {
margin-bottom: var(--spacing-xs);
}
}