Files
bludit-blowfish/css/style.css
T

1338 lines
29 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* ========================================
BLOWDIT — a Bludit theme inspired by Blowfish
Monochrome palette with light & dark modes
======================================== */
/* ----------------------------------------
THEME TOKENS — Light Mode (default)
---------------------------------------- */
:root {
color-scheme: light;
/* Accent (monochrome: near-black in light mode) */
--accent: #1f1f1f;
--accent-hover: #000000;
--accent-contrast: #ffffff;
/* Surfaces */
--bg-body: #ffffff;
--bg-surface: #ffffff;
--bg-subtle: #f5f5f5;
--bg-hover: #f0f0f0;
/* Text */
--text-primary: #1f1f1f;
--text-secondary: #595959;
--text-muted: #8c8c8c;
/* Borders */
--border-color: #e5e5e5;
--border-subtle: #ededed;
/* Chrome (navbar / footer) — fixed dark in both modes */
--chrome-bg: #1f1f1f;
--chrome-text: rgba(255, 255, 255, 0.92);
--chrome-text-hover: #ffffff;
/* Shadows */
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.06), 0 1px 2px rgba(0, 0, 0, 0.04);
--shadow-md: 0 4px 12px rgba(0, 0, 0, 0.08);
--shadow-lg: 0 12px 28px rgba(0, 0, 0, 0.12);
/* Code */
--code-bg: #f5f5f5;
--code-text: #1f1f1f;
/* Spacing scale */
--space-xs: 0.5rem;
--space-sm: 1rem;
--space-md: 1.5rem;
--space-lg: 2rem;
--space-xl: 3rem;
/* Radii */
--radius-sm: 8px;
--radius-md: 12px;
--radius-lg: 18px;
/* Typography */
--font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
--font-size-base: 1.05rem;
--font-size-sm: 0.875rem;
--font-size-xs: 0.78rem;
--line-height-base: 1.7;
/* Filter applied to the dark social SVG glyphs (none on light themes) */
--social-icon-filter: none;
}
/* ----------------------------------------
THEME TOKENS — Dark Mode
---------------------------------------- */
[data-theme="dark"] {
color-scheme: dark;
--accent: #e5e5e5;
--accent-hover: #ffffff;
--accent-contrast: #171717;
--bg-body: #171717;
--bg-surface: #1f1f1f;
--bg-subtle: #262626;
--bg-hover: #2e2e2e;
--text-primary: #ededed;
--text-secondary: #b0b0b0;
--text-muted: #808080;
--border-color: #333333;
--border-subtle: #2a2a2a;
--chrome-bg: #1f1f1f;
--chrome-text: rgba(255, 255, 255, 0.88);
--chrome-text-hover: #ffffff;
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.4);
--shadow-md: 0 4px 12px rgba(0, 0, 0, 0.45);
--shadow-lg: 0 12px 28px rgba(0, 0, 0, 0.5);
--code-bg: #262626;
--code-text: #ededed;
--social-icon-filter: brightness(0) invert(1);
}
/* ----------------------------------------
THEME TOKENS — Nord (arctic)
---------------------------------------- */
[data-theme="nord"] {
color-scheme: dark;
--accent: #88c0d0;
--accent-hover: #8fbcbb;
--accent-contrast: #2e3440;
--bg-body: #2e3440;
--bg-surface: #3b4252;
--bg-subtle: #434c5e;
--bg-hover: #4c566a;
--text-primary: #eceff4;
--text-secondary: #d8dee9;
--text-muted: #8b95a8;
--border-color: #434c5e;
--border-subtle: #3b4252;
--chrome-bg: #3b4252;
--chrome-text: rgba(236, 239, 244, 0.9);
--chrome-text-hover: #eceff4;
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.3);
--shadow-md: 0 4px 12px rgba(0, 0, 0, 0.35);
--shadow-lg: 0 12px 28px rgba(0, 0, 0, 0.4);
--code-bg: #3b4252;
--code-text: #eceff4;
--social-icon-filter: brightness(0) invert(1);
}
/* ----------------------------------------
THEME TOKENS — Dracula
---------------------------------------- */
[data-theme="dracula"] {
color-scheme: dark;
--accent: #bd93f9;
--accent-hover: #caa6fa;
--accent-contrast: #282a36;
--bg-body: #282a36;
--bg-surface: #343746;
--bg-subtle: #44475a;
--bg-hover: #44475a;
--text-primary: #f8f8f2;
--text-secondary: #c4c6d6;
--text-muted: #6272a4;
--border-color: #44475a;
--border-subtle: #383b4a;
--chrome-bg: #343746;
--chrome-text: rgba(248, 248, 242, 0.9);
--chrome-text-hover: #f8f8f2;
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.35);
--shadow-md: 0 4px 12px rgba(0, 0, 0, 0.4);
--shadow-lg: 0 12px 28px rgba(0, 0, 0, 0.45);
--code-bg: #21222c;
--code-text: #f8f8f2;
--social-icon-filter: brightness(0) invert(1);
}
/* ----------------------------------------
THEME TOKENS — Catppuccin Mocha
---------------------------------------- */
[data-theme="catppuccin"] {
color-scheme: dark;
--accent: #cba6f7;
--accent-hover: #d7bdf9;
--accent-contrast: #1e1e2e;
--bg-body: #1e1e2e;
--bg-surface: #313244;
--bg-subtle: #45475a;
--bg-hover: #585b70;
--text-primary: #cdd6f4;
--text-secondary: #bac2de;
--text-muted: #a6adc8;
--border-color: #45475a;
--border-subtle: #313244;
--chrome-bg: #313244;
--chrome-text: rgba(205, 214, 244, 0.9);
--chrome-text-hover: #cdd6f4;
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.35);
--shadow-md: 0 4px 12px rgba(0, 0, 0, 0.4);
--shadow-lg: 0 12px 28px rgba(0, 0, 0, 0.45);
--code-bg: #181825;
--code-text: #cdd6f4;
--social-icon-filter: brightness(0) invert(1);
}
/* ========================================
BASE
======================================== */
html {
position: relative;
min-height: 100%;
scroll-behavior: smooth;
background-color: var(--bg-body);
}
body {
font-family: var(--font-sans);
padding-top: 56px;
min-height: 100vh;
display: flex;
flex-direction: column;
background-color: var(--bg-body);
color: var(--text-primary);
font-size: var(--font-size-base);
line-height: var(--line-height-base);
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
}
/* Main content grows so the footer is pushed to the bottom (sticky footer) */
body > .container,
body > .container-wide {
flex: 1 0 auto;
width: 100%;
padding-bottom: var(--space-xl);
}
/* Wider container used on article pages that have a ToC sidebar.
Same gutter behaviour as Bootstrap's .container but with more breathing room. */
.container-wide {
padding-right: 15px;
padding-left: 15px;
margin-right: auto;
margin-left: auto;
max-width: 1400px;
}
/* Align the navbar's inner container with the wider article layout so the
brand lines up with the ToC and the nav items line up with the right sidebar. */
body.has-toc .navbar .container {
max-width: 1400px;
}
img {
max-width: 100%;
height: auto;
}
::selection {
background: var(--accent);
color: var(--accent-contrast);
}
/* ========================================
LINKS
======================================== */
a {
color: var(--text-primary);
text-decoration: none;
transition: color 0.2s ease;
}
a:hover {
color: var(--text-secondary);
text-decoration: none;
}
a:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
border-radius: 2px;
}
/* ========================================
TYPOGRAPHY
======================================== */
h1, h2, h3, h4, h5, h6 {
color: var(--text-primary);
font-weight: 700;
line-height: 1.25;
letter-spacing: -0.02em;
}
h1.title {
font-size: 2.4rem;
margin-bottom: var(--space-md);
}
h2.title {
font-size: 1.85rem;
margin-bottom: var(--space-sm);
}
.content {
margin-top: var(--space-md);
}
.content h2 { font-size: 1.6rem; margin-top: var(--space-xl); }
.content h3 { font-size: 1.3rem; margin-top: var(--space-lg); }
.content p,
.content ul,
.content ol {
margin-bottom: var(--space-md);
}
.content img {
border-radius: var(--radius-md);
margin: var(--space-md) 0;
}
hr {
border: none;
border-top: 1px solid var(--border-color);
margin: var(--space-xl) 0;
}
/* ========================================
FORMS
======================================== */
input,
textarea,
select,
.form-control {
background-color: var(--bg-surface);
color: var(--text-primary);
border: 1px solid var(--border-color);
border-radius: var(--radius-sm);
}
.form-control:focus {
background-color: var(--bg-surface);
color: var(--text-primary);
border-color: var(--accent);
box-shadow: 0 0 0 3px rgba(127, 127, 127, 0.18);
}
/* ========================================
CODE
======================================== */
pre,
code {
background: var(--code-bg);
color: var(--code-text);
border-radius: var(--radius-sm);
font-family: "JetBrains Mono", "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
transition: background-color 0.25s ease, color 0.25s ease;
}
pre {
border: 1px solid var(--border-color);
border-left: 3px solid var(--accent);
padding: var(--space-md);
overflow-x: auto;
/* max-width + min-width:0 on flex ancestors is required for overflow-x:auto
to actually scroll rather than expand or clip the flex column. */
max-width: 100%;
white-space: pre;
}
/* Bootstrap flex columns default to min-width:auto, which lets them grow past
their grid width and breaks overflow-x:auto on pre/code blocks inside them. */
.row > [class*="col-"] {
min-width: 0;
}
code {
display: inline-block;
padding: 0.15em 0.45em;
font-size: 0.875em;
}
pre code {
padding: 0;
background: transparent;
border: none;
}
/* Always-visible scrollbar on code blocks.
-webkit-appearance: none disables macOS overlay/auto-hide behaviour;
a non-transparent track ensures the slot is always painted. */
pre {
scrollbar-width: thin;
scrollbar-color: var(--text-muted) var(--bg-subtle);
}
pre::-webkit-scrollbar {
-webkit-appearance: none;
height: 8px;
}
pre::-webkit-scrollbar-track {
background: var(--bg-subtle);
border-radius: 0 0 var(--radius-sm) var(--radius-sm);
}
pre::-webkit-scrollbar-thumb {
background: var(--text-muted);
border-radius: 4px;
}
pre::-webkit-scrollbar-thumb:hover {
background: var(--text-secondary);
}
/* ========================================
TABLES
======================================== */
table {
empty-cells: show;
border: 1px solid var(--border-color);
width: 100%;
font-size: 0.95em;
margin-bottom: var(--space-md);
border-radius: var(--radius-sm);
overflow: hidden;
border-collapse: collapse;
}
thead {
background: var(--bg-subtle);
color: var(--text-primary);
text-align: left;
}
tbody tr {
transition: background-color 0.2s ease;
}
tbody tr:hover {
background-color: var(--bg-hover);
}
th, td {
padding: 0.75em 1em;
border-bottom: 1px solid var(--border-color);
}
/* ========================================
BLOCKQUOTES
======================================== */
blockquote {
padding: var(--space-md) var(--space-lg);
margin: 0 0 var(--space-lg) 0;
border-left: 4px solid var(--accent);
background-color: var(--bg-subtle);
border-radius: var(--radius-sm);
color: var(--text-secondary);
font-style: italic;
}
/* ========================================
NAVBAR
======================================== */
.navbar-modern {
background: var(--chrome-bg) !important;
box-shadow: var(--shadow-sm);
padding-top: 0.5rem;
padding-bottom: 0.5rem;
min-height: 56px;
}
.navbar-brand {
font-weight: 700;
font-size: 1.1rem;
letter-spacing: -0.01em;
}
.navbar-brand .text-white {
color: #ffffff !important;
}
.navbar .nav-link {
font-size: 0.85rem;
font-weight: 500;
color: var(--chrome-text) !important;
padding: 0.4rem 0.85rem !important;
border-radius: var(--radius-sm);
transition: background-color 0.2s ease, color 0.2s ease;
}
.navbar .nav-link:hover {
background-color: rgba(255, 255, 255, 0.12);
color: var(--chrome-text-hover) !important;
}
.navbar .nav-link.active {
background-color: rgba(255, 255, 255, 0.18);
color: var(--chrome-text-hover) !important;
}
.navbar .nav-link .bi {
font-size: 1.15rem;
margin-right: 0;
vertical-align: -0.05em;
}
/* Social SVG icons (img/<network>.svg) — rendered white on the dark navbar */
img.nav-svg-icon {
width: 1.2rem;
height: 1.2rem;
filter: brightness(0) invert(1);
opacity: 0.85;
transition: opacity 0.2s ease, transform 0.2s ease;
}
.nav-link:hover img.nav-svg-icon {
opacity: 1;
transform: translateY(-1px);
}
/* Theme toggle button */
.theme-toggle {
background: transparent;
border: 1px solid rgba(255, 255, 255, 0.2);
color: var(--chrome-text) !important;
border-radius: var(--radius-sm);
width: 38px;
height: 38px;
display: inline-flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: background-color 0.2s ease, border-color 0.2s ease;
}
.theme-toggle:hover {
background-color: rgba(255, 255, 255, 0.12);
border-color: rgba(255, 255, 255, 0.4);
color: #ffffff !important;
}
.theme-toggle .bi {
font-size: 1.1rem;
margin-right: 0;
}
/* ----------------------------------------
THEME PICKER DROPDOWN
---------------------------------------- */
.theme-picker-wrap {
position: relative;
}
.theme-picker {
position: absolute;
right: 0;
top: calc(100% + 10px);
display: flex;
gap: 2px;
padding: 10px 8px;
background: #111111;
border: 1px solid rgba(255, 255, 255, 0.12);
border-radius: var(--radius-md);
box-shadow: 0 8px 28px rgba(0, 0, 0, 0.5);
z-index: 1051;
/* hidden by default */
visibility: hidden;
opacity: 0;
transform: translateY(-6px) scale(0.95);
transition: opacity 0.15s ease, transform 0.15s ease, visibility 0s linear 0.15s;
pointer-events: none;
}
.theme-picker.is-open {
visibility: visible;
opacity: 1;
transform: translateY(0) scale(1);
transition: opacity 0.15s ease, transform 0.15s ease, visibility 0s linear 0s;
pointer-events: auto;
}
.swatch {
display: flex;
flex-direction: column;
align-items: center;
gap: 5px;
background: none;
border: none;
padding: 6px 7px;
cursor: pointer;
border-radius: 8px;
transition: background 0.12s;
}
.swatch:hover {
background: rgba(255, 255, 255, 0.08);
}
/* --sb = swatch background (bg-body of that theme)
--sa = swatch accent colour */
.swatch-dot {
width: 22px;
height: 22px;
border-radius: 50%;
background: var(--sb);
border: 2px solid var(--sa);
transition: box-shadow 0.15s;
}
.swatch.is-active .swatch-dot {
box-shadow: 0 0 0 2px var(--sa), 0 0 0 4px rgba(255, 255, 255, 0.18);
}
.swatch-label {
font-size: 9px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.05em;
color: rgba(255, 255, 255, 0.45);
transition: color 0.12s;
}
.swatch.is-active .swatch-label {
color: rgba(255, 255, 255, 0.9);
}
/* ========================================
PROFILE HERO (Blowfish-style homepage)
======================================== */
.profile {
padding: var(--space-lg) 0 var(--space-md);
margin-bottom: var(--space-md);
border-bottom: 1px solid var(--border-color);
}
.profile-avatar {
width: 150px;
height: 150px;
border-radius: 50%;
object-fit: cover;
border: 4px solid var(--bg-surface);
box-shadow: var(--shadow-md);
margin-bottom: var(--space-md);
}
.profile-name {
font-size: 2.1rem;
margin-bottom: var(--space-xs);
}
.profile-bio {
color: var(--text-secondary);
font-size: 1.1rem;
margin-bottom: var(--space-md);
}
.profile-social {
display: flex;
justify-content: center;
flex-wrap: wrap;
gap: var(--space-md);
}
.profile-social a {
display: inline-flex;
}
.profile-social-icon {
width: 1.4rem;
height: 1.4rem;
opacity: 0.65;
filter: var(--social-icon-filter);
transition: opacity 0.2s ease, transform 0.2s ease;
}
.profile-social a:hover .profile-social-icon {
opacity: 1;
transform: translateY(-2px);
}
@media (max-width: 767.98px) {
.profile-avatar { width: 120px; height: 120px; }
.profile-name { font-size: 1.7rem; }
}
/* ========================================
HOME SEARCH (relocated under the hero)
======================================== */
.home-search {
margin: 0 0 var(--space-md);
}
.home-search .plugin,
.home-search .plugin-content {
border: none;
padding: 0;
margin: 0;
}
/* Hide the "Search" label — Popeye-style bare search bar */
.home-search .plugin-label {
display: none;
}
.home-search .plugin-content,
.home-search form {
display: flex;
width: 100%;
gap: var(--space-sm);
align-items: stretch;
margin: 0;
}
/* Force the theme palette over the plugin's own / Bootstrap defaults */
.home-search input,
.home-search .form-control {
flex: 1 1 auto;
margin: 0 !important;
background-color: var(--bg-surface) !important;
color: var(--text-primary) !important;
border: 1px solid var(--border-color) !important;
border-radius: var(--radius-sm) !important;
}
.home-search input::placeholder,
.home-search .form-control::placeholder {
color: var(--text-muted) !important;
}
.home-search button,
.home-search .btn {
flex: 0 0 auto;
width: auto !important; /* cancel Bootstrap's btn-block */
margin: 0 !important;
white-space: nowrap;
background-color: var(--accent) !important;
border: 1px solid var(--accent) !important;
color: var(--accent-contrast) !important;
border-radius: var(--radius-sm) !important;
}
@media (max-width: 575.98px) {
.home-search .plugin-content,
.home-search form {
flex-direction: column;
}
.home-search button,
.home-search .btn {
width: 100% !important;
}
}
/* ========================================
POST LIST (titles only)
======================================== */
.post-list {
margin-top: var(--space-xl);
}
.post-list-item {
padding: var(--space-lg) 0;
border-bottom: 1px solid var(--border-subtle);
}
.post-list-item:first-child {
padding-top: 0;
}
.post-list-item:last-child {
border-bottom: none;
}
/* Stacked: title, then date right beneath it */
.post-list-title {
font-size: 1.4rem;
font-weight: 600;
margin: 0 0 0.2rem;
color: var(--text-primary);
transition: color 0.2s ease;
}
.post-list-head a:hover .post-list-title {
color: var(--text-secondary);
}
.post-list-date {
display: block;
color: var(--text-muted);
font-size: var(--font-size-sm);
}
.post-list-item .post-taxonomy {
margin-top: var(--space-sm);
}
/* ========================================
POST CARDS (single page / post)
======================================== */
.card-modern {
background: transparent;
border: none;
border-bottom: 1px solid var(--border-color);
padding-bottom: var(--space-xl);
margin-bottom: var(--space-xl);
}
.card-modern:last-child {
border-bottom: none;
}
.card-modern .card-img-top {
border-radius: var(--radius-md);
}
.card-modern .card-body {
padding: 0;
margin-top: var(--space-md);
}
.card-modern .title {
color: var(--text-primary);
transition: color 0.2s ease;
}
.card-modern a:hover .title {
color: var(--text-secondary);
}
.cover-image-wrapper {
position: relative;
overflow: hidden;
border-radius: var(--radius-md);
margin-bottom: var(--space-md);
}
.cover-image-wrapper .card-img-top {
transition: transform 0.4s ease;
}
.card-modern:hover .cover-image-wrapper .card-img-top {
transform: scale(1.03);
}
/* ========================================
METADATA (date, reading time)
======================================== */
.metadata {
color: var(--text-muted);
font-size: var(--font-size-sm);
display: flex;
flex-wrap: wrap;
gap: var(--space-md);
align-items: center;
}
.metadata i {
color: var(--text-muted);
margin-right: 0.35rem;
}
/* ========================================
BUTTONS
======================================== */
.btn-primary-gradient {
background: var(--accent);
border: none;
color: var(--accent-contrast);
padding: 0.6rem 1.3rem;
border-radius: var(--radius-sm);
font-weight: 600;
font-size: var(--font-size-sm);
transition: background-color 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease;
box-shadow: var(--shadow-sm);
display: inline-flex;
align-items: center;
gap: 0.5rem;
}
.btn-primary-gradient:hover {
background: var(--accent-hover);
color: var(--accent-contrast);
transform: translateY(-2px);
box-shadow: var(--shadow-md);
text-decoration: none;
}
.btn-primary-gradient .bi {
margin-right: 0;
transition: transform 0.2s ease;
}
.btn-primary-gradient:hover .bi {
transform: translateX(3px);
}
/* ========================================
TAXONOMY (tags & categories)
======================================== */
.post-taxonomy {
display: flex;
flex-wrap: wrap;
gap: 0.4rem;
align-items: center;
}
.taxonomy-badge {
display: inline-flex;
align-items: center;
padding: 0.3rem 0.8rem;
border-radius: 999px;
font-size: var(--font-size-xs);
font-weight: 500;
border: 1px solid var(--border-color);
color: var(--text-secondary);
background: transparent;
transition: all 0.2s ease;
}
.taxonomy-badge .bi {
margin-right: 0.35rem;
font-size: 0.85em;
}
.taxonomy-badge:hover {
background: var(--accent);
color: var(--accent-contrast);
border-color: var(--accent);
}
/* ========================================
PAGINATION
======================================== */
.pagination .page-link {
background: var(--bg-surface);
border: 1px solid var(--border-color);
color: var(--text-primary);
padding: 0.55rem 1.1rem;
border-radius: var(--radius-sm);
font-weight: 500;
transition: all 0.2s ease;
}
.pagination .page-link:hover {
background: var(--accent);
color: var(--accent-contrast);
border-color: var(--accent);
transform: translateY(-2px);
}
.pagination .page-item.disabled .page-link {
background: var(--bg-subtle);
color: var(--text-muted);
border-color: var(--border-color);
}
/* ========================================
SIDEBAR + PLUGINS
======================================== */
.sidebar-container {
margin-top: var(--space-xl);
background: var(--bg-surface);
border: 1px solid var(--border-color);
border-radius: var(--radius-lg);
padding: var(--space-lg);
font-size: 0.9rem;
}
/* Compact profile card inside the sidebar (article view) */
.sidebar-profile {
padding-bottom: 1.2rem;
margin-bottom: 1.2rem;
border-bottom: 1px solid var(--border-subtle);
}
.sidebar-profile-avatar {
width: 84px;
height: 84px;
border-radius: 50%;
object-fit: cover;
border: 3px solid var(--bg-surface);
box-shadow: var(--shadow-sm);
margin-bottom: var(--space-sm);
transition: transform 0.2s ease;
}
.sidebar-profile-avatar:hover {
transform: translateY(-2px);
}
.sidebar-profile-name {
font-weight: 700;
font-size: 1rem;
color: var(--text-primary);
}
.sidebar-profile-bio {
color: var(--text-secondary);
font-size: var(--font-size-sm);
margin: 0.35rem 0 0;
}
.plugin {
padding-bottom: 1.2rem;
margin-bottom: 1.2rem;
border-bottom: 1px solid var(--border-subtle);
}
.plugin:last-child {
border-bottom: none;
margin-bottom: 0;
padding-bottom: 0;
}
/* The navigation plugin is wrapped in .js-random-nav, so it matches
.plugin:last-child even when it isn't last — restore its divider/spacing. */
.js-random-nav .plugin {
border-bottom: 1px solid var(--border-subtle);
margin-bottom: 1.2rem;
padding-bottom: 1.2rem;
}
/* …unless the wrapped navigation really is the last item in the sidebar. */
.sidebar-container > .js-random-nav:last-child .plugin {
border-bottom: none;
margin-bottom: 0;
padding-bottom: 0;
}
.plugin-label {
font-size: var(--font-size-xs);
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--text-muted);
margin-bottom: var(--space-sm);
}
.plugin ul {
list-style: none;
padding: 0;
margin: 0;
}
.plugin ul li {
padding: 0.15rem 0;
}
.plugin ul li a {
color: var(--text-secondary);
display: block;
transition: color 0.2s ease;
}
.plugin ul li a:hover {
color: var(--text-primary);
}
/* Tags & categories in sidebar — badge style */
.plugin.plugin-tags ul,
.plugin.plugin-categories ul {
display: flex;
flex-wrap: wrap;
gap: 0.4rem;
}
.plugin.plugin-tags li,
.plugin.plugin-categories li {
padding: 0;
}
.plugin.plugin-tags li a,
.plugin.plugin-categories li a {
background: var(--bg-subtle);
color: var(--text-secondary);
padding: 0.3rem 0.8rem;
border-radius: 999px;
font-size: var(--font-size-xs);
font-weight: 500;
display: inline-block;
transition: all 0.2s ease;
}
.plugin.plugin-tags li a:hover,
.plugin.plugin-categories li a:hover {
background: var(--accent);
color: var(--accent-contrast);
}
/* Search plugin — target input directly in case the plugin omits form-control */
.plugin.plugin-search input,
.plugin.plugin-search .form-control {
border: 1px solid var(--border-color) !important;
border-radius: var(--radius-sm) !important;
padding: 0.6rem 0.9rem !important;
background: var(--bg-surface) !important;
background-color: var(--bg-surface) !important;
color: var(--text-primary) !important;
width: 100%;
}
.plugin.plugin-search input::placeholder,
.plugin.plugin-search .form-control::placeholder {
color: var(--text-muted) !important;
}
.plugin.plugin-search input:focus,
.plugin.plugin-search .form-control:focus {
border-color: var(--accent) !important;
box-shadow: 0 0 0 3px rgba(127, 127, 127, 0.18) !important;
outline: none !important;
background: var(--bg-surface) !important;
background-color: var(--bg-surface) !important;
}
.plugin.plugin-search button,
.plugin.plugin-search .btn {
background: var(--accent) !important;
background-color: var(--accent) !important;
border: 1px solid var(--accent) !important;
color: var(--accent-contrast) !important;
padding: 0.55rem 1.2rem;
border-radius: var(--radius-sm);
font-weight: 600;
transition: background-color 0.2s ease, transform 0.2s ease;
margin-top: var(--space-sm);
}
/* Higher-specificity rule for the sidebar context so we beat any plugin-bundled
CSS that gets loaded after style.css and re-sets the button colour. */
.sidebar-container .plugin.plugin-search button,
.sidebar-container .plugin.plugin-search .btn {
background: var(--accent) !important;
background-color: var(--accent) !important;
border-color: var(--accent) !important;
color: var(--accent-contrast) !important;
}
.plugin.plugin-search button:hover,
.plugin.plugin-search .btn:hover {
background: var(--accent-hover) !important;
background-color: var(--accent-hover) !important;
border-color: var(--accent-hover) !important;
transform: translateY(-2px);
}
/* ========================================
FOOTER
======================================== */
footer.footer-modern {
flex-shrink: 0;
width: 100%;
min-height: 64px;
line-height: 1.6;
background: var(--chrome-bg);
color: var(--chrome-text);
padding: 1rem 0;
font-size: var(--font-size-xs);
}
footer.footer-modern a {
color: var(--chrome-text);
transition: color 0.2s ease;
}
footer.footer-modern a:hover {
color: var(--chrome-text-hover);
}
.mini-logo {
height: 22px;
vertical-align: middle;
filter: brightness(0) invert(1);
}
/* ========================================
ICON SPACING
======================================== */
.bi {
margin-right: 0.4rem;
}
/* ========================================
LIGHTBOX
======================================== */
.lightbox-overlay {
position: fixed;
inset: 0;
z-index: 2000;
background: rgba(0, 0, 0, 0.88);
display: flex;
align-items: center;
justify-content: center;
cursor: zoom-out;
opacity: 0;
visibility: hidden;
transition: opacity 0.2s ease, visibility 0s linear 0.2s;
}
.lightbox-overlay.is-open {
opacity: 1;
visibility: visible;
transition: opacity 0.2s ease, visibility 0s linear 0s;
}
.lightbox-overlay img {
max-width: 90vw;
max-height: 90vh;
object-fit: contain;
border-radius: var(--radius-sm);
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6);
transform: scale(0.94);
transition: transform 0.2s ease;
cursor: zoom-out;
}
.lightbox-overlay.is-open img {
transform: scale(1);
}
/* Zoomable image wrapper — JS wraps each content image in this span */
.zoomable-wrap {
position: relative;
display: inline-block;
cursor: zoom-in;
/* clip the overlay to the image bounds */
overflow: hidden;
}
/* Full-image dark overlay with centred magnifier on hover.
Stroke-based SVG (24×24 viewBox, no fill) stays crisp at any rendered size. */
.zoomable-wrap::after {
content: '';
position: absolute;
inset: 0;
background-color: rgba(0, 0, 0, 0.38);
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'/%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'/%3E%3Cline x1='11' y1='8' x2='11' y2='14'/%3E%3Cline x1='8' y1='11' x2='14' y2='11'/%3E%3C/svg%3E");
background-position: center;
background-size: 52px;
background-repeat: no-repeat;
opacity: 0;
transition: opacity 0.2s ease;
pointer-events: none;
}
.zoomable-wrap:hover::after {
opacity: 1;
}
/* ========================================
TABLE OF CONTENTS (left sidebar, article view)
======================================== */
.toc-sidebar {
margin-top: var(--space-xl);
position: sticky;
/* 56px = fixed navbar height; extra gap so the ToC doesn't hug it */
top: calc(56px + var(--space-sm));
max-height: calc(100vh - 56px - var(--space-md));
overflow-y: auto;
font-size: var(--font-size-sm);
}
.toc-title {
font-size: var(--font-size-xs);
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--text-muted);
margin-bottom: 0.75rem;
}
.toc-list {
list-style: none;
padding: 0;
margin: 0;
}
.toc-item {
padding: 0.15rem 0;
}
.toc-h3 {
padding-left: 0.75rem;
}
.toc-h4 {
padding-left: 1.5rem;
}
.toc-link {
color: var(--text-muted);
text-decoration: none;
line-height: 1.5;
display: block;
transition: color 0.15s ease;
}
.toc-link:hover {
color: var(--text-primary);
text-decoration: none;
}
.toc-link.active {
color: var(--accent);
font-weight: 600;
text-decoration: none;
}
/* ========================================
RESPONSIVE
======================================== */
@media (max-width: 767.98px) {
h1.title { font-size: 1.9rem; }
h2.title { font-size: 1.5rem; }
body { font-size: 1rem; }
.sidebar-container {
position: static;
margin-top: var(--space-lg);
}
.btn-primary-gradient {
width: 100%;
justify-content: center;
}
.navbar-nav .theme-toggle {
width: 100%;
margin-top: 0.5rem;
height: 42px;
}
}