levineuwirth.org/static/css/components.css

1076 lines
23 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.

/* components.css — Nav, TOC, metadata block, page footer.
Loaded on every page. */
/* ============================================================
SKIP LINK
============================================================ */
.skip-link {
position: absolute;
top: -100%;
left: 0;
z-index: 9999;
padding: 0.5em 1em;
background: var(--bg);
color: var(--text);
border: 1px solid var(--border);
text-decoration: none;
font-size: 0.875rem;
}
.skip-link:focus {
top: 0;
}
/* ============================================================
NAV
Two-row: primary links (always visible) + portal links
(collapsed by default, expanded via nav.js + localStorage).
============================================================ */
nav.site-nav {
display: flex;
flex-direction: column;
align-items: stretch;
font-family: var(--font-sans);
}
/* Row 1: centered primary links + right-side controls */
.nav-row-primary {
position: relative;
display: flex;
justify-content: center;
align-items: center;
padding: 0.65rem 1.5rem;
}
.nav-primary {
display: flex;
align-items: center;
gap: 0;
font-size: 0.8rem;
font-weight: 600;
font-variant-caps: small-caps;
letter-spacing: 0.06em;
}
.nav-primary a {
text-decoration: none;
color: var(--text-muted);
padding: 0.15rem 0.85rem;
transition: color var(--transition-fast);
}
.nav-primary a:hover {
color: var(--text);
}
.nav-primary a + a {
border-left: 1px solid var(--border);
}
/* Controls cluster: portals toggle + theme toggle, pinned right */
.nav-controls {
position: absolute;
right: 1.25rem;
display: flex;
align-items: center;
gap: 0.75rem;
}
.nav-portal-toggle {
background: none;
border: none;
cursor: pointer;
font-family: var(--font-sans);
font-size: 0.72rem;
font-weight: 600;
font-variant-caps: all-small-caps;
letter-spacing: 0.06em;
color: var(--text-faint);
padding: 0;
line-height: 1;
transition: color var(--transition-fast);
white-space: nowrap;
}
.nav-portal-toggle:hover {
color: var(--text-muted);
}
.nav-portal-arrow {
font-size: 0.6rem;
display: inline-block;
margin-right: 0.2em;
vertical-align: middle;
}
/* Settings button + panel */
.settings-wrap {
position: relative;
}
.settings-toggle {
background: none;
border: none;
cursor: pointer;
color: var(--text-faint);
font-size: 0.85rem;
font-family: var(--font-sans);
padding: 0;
line-height: 1;
transition: color var(--transition-fast);
}
.settings-toggle:hover,
.settings-toggle[aria-expanded="true"] {
color: var(--text-muted);
}
.settings-panel {
position: absolute;
top: calc(100% + 0.6rem);
right: 0;
z-index: 800;
min-width: 148px;
padding: 0.5rem;
background: var(--bg);
border: 1px solid var(--border);
border-radius: 4px;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
display: none;
flex-direction: column;
gap: 0.1rem;
}
.settings-panel.is-open {
display: flex;
}
.settings-section {
padding: 0.3rem 0.2rem;
}
.settings-section + .settings-section {
border-top: 1px solid var(--border);
padding-top: 0.4rem;
margin-top: 0.1rem;
}
.settings-label {
font-family: var(--font-sans);
font-size: 0.62rem;
font-weight: 600;
font-variant-caps: all-small-caps;
letter-spacing: 0.07em;
color: var(--text-faint);
margin-bottom: 0.3rem;
line-height: 1;
}
.settings-row {
display: flex;
gap: 0.3rem;
}
.settings-btn {
flex: 1;
background: var(--bg-offset);
border: 1px solid var(--border);
border-radius: 3px;
color: var(--text-muted);
font-family: var(--font-sans);
font-size: 0.72rem;
font-weight: 500;
padding: 0.3rem 0.5rem;
cursor: pointer;
transition: background var(--transition-fast), color var(--transition-fast),
border-color var(--transition-fast);
white-space: nowrap;
line-height: 1.2;
}
.settings-btn:hover:not(:disabled) {
background: var(--border);
color: var(--text);
}
.settings-btn.is-active {
background: var(--text);
border-color: var(--text);
color: var(--bg);
}
.settings-btn:disabled {
opacity: 0.35;
cursor: default;
}
.settings-btn--full {
width: 100%;
flex: none;
text-align: center;
}
.settings-col {
display: flex;
flex-direction: column;
gap: 0.3rem;
}
/* ============================================================
FOCUS MODE — header fade
TOC hide lives in layout.css.
============================================================ */
[data-focus-mode] body > header {
opacity: 0.07;
transition: opacity 0.5s ease;
}
[data-focus-mode] body > header:hover,
[data-focus-mode] body > header:focus-within {
opacity: 1;
transition: opacity 0.15s ease;
}
/* ============================================================
REDUCE MOTION
Collapses all transitions and animations site-wide.
Applied to <html> before first paint by theme.js.
============================================================ */
[data-reduce-motion] *,
[data-reduce-motion] *::before,
[data-reduce-motion] *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
/* Row 2: portal links — hidden until nav.js adds .is-open */
.nav-portals {
display: none;
justify-content: center;
flex-wrap: wrap;
gap: 0;
padding: 0.4rem 1.5rem 0.5rem;
border-top: 1px solid var(--border);
}
.nav-portals.is-open {
display: flex;
}
.nav-portals a {
font-size: 0.75rem;
font-weight: 600;
font-variant-caps: all-small-caps;
letter-spacing: 0.05em;
text-decoration: none;
color: var(--text-faint);
padding: 0.1rem 0.7rem;
transition: color var(--transition-fast);
}
.nav-portals a + a {
border-left: 1px solid var(--border);
}
.nav-portals a:hover {
color: var(--text);
}
/* ============================================================
TABLE OF CONTENTS
Sticky left sidebar (position: sticky set in layout.css).
toc.js manages: .is-active links, .is-collapsed state,
and the --toc-progress custom property for the progress bar.
============================================================ */
#toc {
font-family: var(--font-sans);
font-size: 0.85rem;
line-height: 1.5;
padding-right: 1.5rem;
padding-left: 0.5rem;
}
/* Header row: current section label + collapse toggle */
.toc-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 0.4rem;
padding-bottom: 0.55rem;
margin-bottom: 0.35rem;
position: relative;
}
/* Progress track — full width, faint */
.toc-header::before {
content: '';
position: absolute;
bottom: 0; left: 0;
width: 100%; height: 1px;
background: var(--border);
}
/* Progress fill — grows left→right with scroll */
.toc-header::after {
content: '';
position: absolute;
bottom: 0; left: 0;
height: 1px;
width: calc(var(--toc-progress, 0) * 100%);
background: var(--text-muted);
transition: width 0.12s ease;
}
/* Current section label */
.toc-active-label {
font-size: 0.72rem;
font-weight: 600;
font-variant-caps: all-small-caps;
letter-spacing: 0.07em;
color: var(--text-faint);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
min-width: 0;
flex: 1;
}
#toc.is-collapsed .toc-active-label {
color: var(--text-muted);
}
/* Collapse toggle button */
.toc-toggle {
background: none;
border: none;
cursor: pointer;
color: var(--text-faint);
font-size: 0.72rem;
padding: 0;
line-height: 1;
flex-shrink: 0;
transition: color var(--transition-fast), transform 0.28s ease;
}
.toc-toggle:hover {
color: var(--text-muted);
}
#toc.is-collapsed .toc-toggle {
transform: rotate(-90deg);
}
/* Nav: animates open/closed via max-height */
.toc-nav {
overflow: hidden;
max-height: 80vh;
transition: max-height 0.3s ease;
}
#toc.is-collapsed .toc-nav {
max-height: 0;
visibility: hidden;
}
/* Nav list */
.toc-nav ol {
list-style: none;
padding: 0;
margin: 0;
}
.toc-nav > ol > li {
margin: 0.3rem 0;
}
.toc-nav > ol > li > ol {
margin: 0.1rem 0 0.2rem 0;
}
.toc-nav > ol > li > ol > li {
margin: 0.15rem 0;
}
.toc-nav a {
text-decoration: none;
color: var(--text-faint);
display: block;
padding: 0.1rem 0;
transition: color var(--transition-fast);
}
.toc-nav a:hover {
color: var(--text);
}
/* JS adds .is-active to the current heading's link */
.toc-nav a.is-active {
color: var(--text);
font-weight: 600;
}
/* h2-level links slightly more prominent */
.toc-nav > ol > li > a {
color: var(--text-muted);
}
.toc-nav > ol > li > a:hover,
.toc-nav > ol > li > a.is-active {
color: var(--text);
}
/* h3-level links indented and smaller */
.toc-nav > ol > li > ol > li > a {
padding-left: 0.75rem;
font-size: 0.74rem;
}
/* ============================================================
PAGE TITLE
============================================================ */
.page-title {
font-family: var(--font-sans);
font-size: 2.6rem;
font-weight: 600;
margin: 0 0 1.65rem 0;
line-height: 1.1;
color: var(--text);
}
/* ============================================================
METADATA BLOCK
Vertical sequence above the body: tags, description,
authors (optional), jump links to bottom footer sections.
============================================================ */
.metadata {
margin-bottom: 2.475rem;
font-family: var(--font-sans);
display: flex;
flex-direction: column;
gap: 0.6rem;
}
.meta-row {
font-size: 0.82rem;
color: var(--text-muted);
line-height: 1.5;
}
/* Tags, authors, jump links: centered */
.meta-tags,
.meta-authors,
.meta-pagelinks {
text-align: center;
}
/* Description: blockquote style, left-aligned */
.meta-description {
font-style: italic;
padding-left: 1.25em;
border-left: 2px solid var(--border);
color: var(--text-muted);
}
/* Tags: centered row of small-caps links separated by middots */
.meta-tags {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 0;
color: var(--text-faint);
font-size: 0.72rem;
}
.meta-tag {
color: var(--text-faint);
text-decoration: none;
font-variant-caps: all-small-caps;
letter-spacing: 0.06em;
transition: color var(--transition-fast);
}
.meta-tag:hover {
color: var(--text-muted);
}
.meta-tag + .meta-tag::before {
content: " · ";
color: var(--text-faint);
letter-spacing: 0;
font-variant-caps: normal;
}
/* Authors: "by" label + name */
.meta-authors {
font-size: 0.78rem;
color: var(--text-faint);
}
.meta-authors .meta-label {
font-variant-caps: all-small-caps;
font-weight: 600;
letter-spacing: 0.06em;
font-size: 0.68rem;
color: var(--text-faint);
margin-right: 0.4rem;
}
/* Jump links: inline, separated by middots */
.meta-pagelinks {
font-size: 0.75rem;
color: var(--text-faint);
}
.meta-pagelinks a {
color: var(--text-faint);
text-decoration: none;
}
.meta-pagelinks a:hover {
color: var(--text-muted);
text-decoration: underline;
text-underline-offset: 2px;
}
.meta-pagelinks a + a::before {
content: " · ";
color: var(--border);
}
/* ============================================================
BOTTOM METADATA FOOTER
Full-width section outside the essay's three-column layout.
Structure: [Further Reading row?] [Bibliography row?] [metadata grid].
============================================================ */
.page-meta-footer {
border-top: 1px solid var(--border);
padding: 2rem var(--page-padding);
font-family: var(--font-sans);
font-size: 0.82rem;
color: var(--text-muted);
display: flex;
flex-direction: column;
align-items: center;
gap: 2.5rem;
}
/* Each section is constrained and centered. */
.page-meta-footer > * {
width: 100%;
max-width: min(1200px, 100%);
}
/* Shared heading style for full-width section headings */
.meta-footer-full > h3,
.meta-footer-section h3 {
font-size: 0.78rem;
font-weight: 600;
font-variant-caps: all-small-caps;
letter-spacing: 0.07em;
color: var(--text-faint);
margin: 0 0 0.75rem 0;
font-family: var(--font-sans);
text-rendering: optimizeLegibility;
}
/* Full-width rows: Further Reading and Bibliography */
.meta-footer-full {
width: 100%;
}
/* Metadata entries: horizontal auto-grid, centered */
.meta-footer-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
justify-content: center;
gap: 1.65rem 2rem;
padding-top: 0.5rem;
border-top: 1px solid var(--border-muted, var(--border));
}
.meta-footer-section p,
.meta-footer-section ul {
margin: 0;
font-size: 0.78rem;
color: var(--text-muted);
line-height: 1.5;
}
.meta-footer-section ul {
padding-left: 1em;
list-style: none;
}
.meta-footer-section ul li::before {
content: "\00a0";
color: var(--text-faint);
}
/* ============================================================
BACKLINKS LIST
============================================================ */
#backlinks .backlinks-list {
padding-left: 0;
list-style: none;
margin: 0;
}
#backlinks .backlinks-list li::before {
content: none;
}
.backlink-item {
padding: 0.3rem 0;
}
/* Source title — always visible */
.backlink-source {
font-size: 0.78rem;
font-family: var(--font-sans);
font-variant: small-caps;
letter-spacing: 0.02em;
color: var(--text-muted);
text-decoration: none;
}
.backlink-source:hover {
color: var(--text);
}
/* Context toggle — collapsed by default */
.backlink-details {
display: inline;
}
.backlink-summary {
display: inline;
margin-left: 0.4em;
font-size: 0.68rem;
font-family: var(--font-sans);
color: var(--text-faint);
cursor: pointer;
list-style: none;
user-select: none;
}
.backlink-summary::-webkit-details-marker {
display: none;
}
.backlink-summary::before {
content: "▸\00a0";
font-size: 0.6em;
vertical-align: 0.1em;
}
details[open] > .backlink-summary::before {
content: "▾\00a0";
}
.backlink-summary:hover {
color: var(--text-muted);
}
/* Context paragraph — shown when <details> is open */
.backlink-context {
margin-top: 0.35rem;
margin-bottom: 0.2rem;
padding-left: 0.75rem;
border-left: 2px solid var(--border-muted);
font-size: 0.75rem;
color: var(--text-faint);
line-height: 1.5;
}
.backlink-context a {
color: var(--text-faint);
text-decoration-color: var(--border-muted);
}
.backlink-context a:hover {
color: var(--text-muted);
}
/* ============================================================
EPISTEMIC METADATA BLOCK
Compact display (status chip + confidence % + dot scales)
with an expandable <details> for the full profile.
============================================================ */
/* Compact row — chips laid out inline */
.ep-compact {
display: flex;
flex-wrap: wrap;
align-items: baseline;
gap: 0.35rem 0.55rem;
margin-bottom: 0.5rem;
}
/* Status chip */
.ep-status {
font-family: var(--font-sans);
font-size: 0.72rem;
font-variant-caps: all-small-caps;
letter-spacing: 0.05em;
color: var(--text-muted);
}
/* Confidence percentage */
.ep-confidence {
font-family: var(--font-sans);
font-size: 0.72rem;
color: var(--text-faint);
}
.ep-confidence::before { content: "·\00a0"; color: var(--border); }
/* Dot scale (importance / evidence) */
.ep-dots {
font-size: 0.55rem;
letter-spacing: 0.12em;
color: var(--text-muted);
line-height: 1;
vertical-align: 0.15em;
}
.ep-dots::before { content: "·\00a0"; color: var(--border); font-size: 0.72rem; vertical-align: 0; }
/* Expandable detail block */
.ep-details {
margin-top: 0.1rem;
}
.ep-summary {
font-size: 0.68rem;
font-family: var(--font-sans);
color: var(--text-faint);
cursor: pointer;
list-style: none;
user-select: none;
}
.ep-summary::-webkit-details-marker { display: none; }
.ep-summary::before {
content: "▸\00a0";
font-size: 0.6em;
vertical-align: 0.1em;
}
details[open] > .ep-summary::before { content: "▾\00a0"; }
.ep-summary:hover { color: var(--text-muted); }
/* Definition list for expanded profile */
.ep-expanded {
display: grid;
grid-template-columns: max-content 1fr;
gap: 0.2rem 0.75rem;
margin: 0.5rem 0 0 0;
font-size: 0.75rem;
line-height: 1.45;
}
.ep-expanded dt {
color: var(--text-faint);
font-family: var(--font-sans);
font-variant-caps: all-small-caps;
letter-spacing: 0.04em;
}
.ep-expanded dd {
margin: 0;
color: var(--text-muted);
font-family: var(--font-sans);
}
/* ============================================================
PAGINATION NAV
============================================================ */
.paginate-nav {
display: flex;
align-items: center;
justify-content: center;
gap: 1.25rem;
margin-top: 2.5rem;
padding-top: 1.25rem;
border-top: 1px solid var(--border-muted);
font-family: var(--font-sans);
}
.paginate-btn {
color: var(--text-faint);
text-decoration: none;
font-size: 1rem;
line-height: 1;
transition: color var(--transition-fast);
}
.paginate-btn:hover {
color: var(--text-muted);
}
.paginate-info {
font-size: 0.75rem;
color: var(--text-faint);
font-variant-numeric: tabular-nums;
}
/* ============================================================
CITATION MARKERS (inline superscripts)
============================================================ */
.cite-marker {
font-family: var(--font-sans);
font-size: 0.62em;
line-height: 1;
vertical-align: super;
margin: 0 0.08em;
}
.cite-link {
color: var(--text-faint);
text-decoration: none;
border: 1px solid var(--border-muted);
border-radius: 2px;
padding: 0.05em 0.28em;
font-weight: 600;
letter-spacing: 0.01em;
transition: color var(--transition-fast), border-color var(--transition-fast);
}
.cite-link:hover {
color: var(--text-muted);
border-color: var(--border);
text-decoration: none;
}
/* Tooltip shown on hover */
.cite-tooltip {
position: absolute;
z-index: 200;
max-width: 340px;
padding: 0.55rem 0.75rem;
background: var(--bg);
border: 1px solid var(--border);
border-radius: 3px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.07);
font-family: var(--font-sans);
font-size: 0.78rem;
color: var(--text-muted);
line-height: 1.5;
pointer-events: auto;
}
.cite-tooltip em {
font-style: italic;
}
/* ============================================================
BIBLIOGRAPHY (inside .page-meta-footer #bibliography)
============================================================ */
/* Number badge preceding each entry */
.ref-num {
font-family: var(--font-sans);
font-size: 0.72rem;
font-weight: 600;
color: var(--text-faint);
margin-right: 0.4em;
white-space: nowrap;
}
/* Each bibliography entry */
.csl-bib-body .csl-entry {
font-size: 0.95rem;
color: var(--text-muted);
line-height: 1.6;
margin-bottom: 0.6rem;
padding-left: 1.6em;
text-indent: -1.6em;
}
.csl-bib-body .csl-entry a {
color: var(--text-faint);
word-break: break-all;
}
.csl-bib-body .csl-entry a:hover {
color: var(--text-muted);
}
/* ============================================================
COLLAPSIBLE SECTIONS
collapse.js wraps h2/h3 content in .section-body divs and
injects .section-toggle buttons into the heading elements.
============================================================ */
.section-body {
overflow: hidden;
transition: max-height 0.3s ease;
}
.section-toggle {
background: none;
border: none;
cursor: pointer;
color: var(--text-faint);
padding: 0 0 0 0.5em;
font-size: 0.5em;
line-height: 1;
vertical-align: middle;
position: relative;
top: -0.1em;
opacity: 0;
transition: color var(--transition-fast), opacity var(--transition-fast);
}
h2:hover .section-toggle,
h3:hover .section-toggle,
.section-toggle:hover,
.section-toggle:focus {
opacity: 1;
}
.section-toggle:hover {
color: var(--text-muted);
}
.section-toggle::before {
content: '▼';
}
.section-toggle[aria-expanded="false"]::before {
content: '▶';
}
/* ============================================================
PAGEFIND SEARCH UI
CSS custom property overrides so pagefind-ui matches the
site's design tokens. Pagefind reads these via var().
============================================================ */
#search {
margin-top: 1.65rem;
--pagefind-ui-scale: 0.85;
--pagefind-ui-primary: var(--text-muted);
--pagefind-ui-text: var(--text);
--pagefind-ui-background: var(--bg);
--pagefind-ui-border: var(--border);
--pagefind-ui-tag: var(--bg-offset);
--pagefind-ui-border-width: 1px;
--pagefind-ui-border-radius: 2px;
--pagefind-ui-font: var(--font-sans);
}
/* ============================================================
COMPOSITION LANDING PAGE
============================================================ */
.composition-meta .meta-row.composition-details {
display: flex;
flex-wrap: wrap;
gap: 0 1.25rem;
color: var(--text-muted);
font-family: var(--font-ui);
font-size: 0.85rem;
}
.comp-detail + .comp-detail::before {
content: "·";
margin-right: 1.25rem;
color: var(--border);
}
.meta-row.composition-actions {
display: flex;
gap: 0.6rem;
flex-wrap: wrap;
}
.comp-btn {
display: inline-block;
padding: 0.3rem 0.8rem;
font-family: var(--font-ui);
font-size: 0.82rem;
font-weight: 600;
border: 1px solid var(--border);
color: var(--text);
text-decoration: none;
background: transparent;
cursor: pointer;
}
.comp-btn:hover {
background: var(--bg-offset);
}
.comp-btn--secondary {
color: var(--text-muted);
}
/* Full-piece recording player */
.comp-recording {
margin: 1.25rem 0;
}
.comp-recording-audio {
width: 100%;
height: 2rem;
accent-color: var(--text-muted);
}
/* Movement list */
.composition-movements {
margin: 1.25rem 0;
border-top: 1px solid var(--border);
}
.comp-movement {
padding: 0.65rem 0;
border-bottom: 1px solid var(--border);
}
.comp-movement-header {
display: flex;
align-items: baseline;
gap: 0.75rem;
flex-wrap: wrap;
}
.comp-movement-name {
font-weight: 600;
flex: 1 1 auto;
}
.comp-movement-duration {
font-family: var(--font-ui);
font-size: 0.82rem;
color: var(--text-muted);
}
.comp-movement-score {
font-family: var(--font-ui);
font-size: 0.82rem;
color: var(--text-muted);
text-decoration: none;
}
.comp-movement-score:hover {
text-decoration: underline;
}
.movement-audio {
display: block;
width: 100%;
height: 2rem;
margin-top: 0.5rem;
accent-color: var(--text-muted);
}