538 lines
13 KiB
CSS
538 lines
13 KiB
CSS
/* gallery.css — Exhibit system (always-visible inline blocks with overlay
|
||
expansion) and annotation system (static or collapsible callout boxes). */
|
||
|
||
|
||
/* ============================================================
|
||
EXHIBIT WRAPPER
|
||
Base styles shared by all exhibit types.
|
||
============================================================ */
|
||
|
||
.exhibit {
|
||
position: relative;
|
||
display: block;
|
||
margin: 1.65rem 0;
|
||
padding: 0; /* reset <figure> default margin */
|
||
}
|
||
|
||
|
||
/* ============================================================
|
||
MATH FOCUSABLE
|
||
Wrapper injected around every .katex-display by gallery.js.
|
||
Clicking anywhere on the wrapper opens the overlay.
|
||
============================================================ */
|
||
|
||
.math-focusable {
|
||
position: relative;
|
||
display: block;
|
||
cursor: zoom-in;
|
||
}
|
||
|
||
/* Expand glyph — decorative affordance, not interactive */
|
||
.exhibit-expand {
|
||
position: absolute;
|
||
top: 50%;
|
||
right: 0.4rem;
|
||
transform: translateY(-50%);
|
||
font-family: var(--font-sans);
|
||
font-size: 0.75rem;
|
||
line-height: 1;
|
||
color: var(--text-faint);
|
||
padding: 0.2rem 0.35rem;
|
||
border-radius: 2px;
|
||
pointer-events: none; /* click handled by wrapper */
|
||
opacity: 0;
|
||
transition: opacity var(--transition-fast);
|
||
user-select: none;
|
||
}
|
||
|
||
.math-focusable:hover .exhibit-expand {
|
||
opacity: 1;
|
||
}
|
||
|
||
/* Caption tooltip — appears above the math on hover, like alt text */
|
||
.math-focusable[data-caption]::after {
|
||
content: attr(data-caption);
|
||
position: absolute;
|
||
bottom: calc(100% + 0.5rem);
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
background: var(--bg);
|
||
border: 1px solid var(--border);
|
||
border-radius: 2px;
|
||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.07);
|
||
padding: 0.3rem 0.65rem;
|
||
font-family: var(--font-sans);
|
||
font-size: 0.72rem;
|
||
font-style: italic;
|
||
color: var(--text-muted);
|
||
/* Explicit width prevents the box from collapsing to a single-word column */
|
||
width: min(440px, 70vw);
|
||
white-space: normal;
|
||
text-align: center;
|
||
pointer-events: none;
|
||
opacity: 0;
|
||
transition: opacity var(--transition-fast);
|
||
z-index: 10;
|
||
}
|
||
|
||
.math-focusable[data-caption]:hover::after {
|
||
opacity: 1;
|
||
}
|
||
|
||
|
||
/* ============================================================
|
||
PROOF EXHIBIT
|
||
Always-visible inline block. Header is a non-interactive label.
|
||
============================================================ */
|
||
|
||
.exhibit--proof .exhibit-header {
|
||
display: flex;
|
||
align-items: baseline;
|
||
gap: 0.5rem;
|
||
padding-bottom: 0.45rem;
|
||
margin-bottom: 0.6rem;
|
||
border-bottom: 1px solid var(--border-muted);
|
||
}
|
||
|
||
.exhibit--proof .exhibit-header-label {
|
||
font-style: italic;
|
||
font-weight: 600;
|
||
color: var(--text);
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.exhibit--proof .exhibit-header-name {
|
||
font-family: var(--font-sans);
|
||
font-size: 0.82rem;
|
||
color: var(--text-muted);
|
||
}
|
||
|
||
|
||
/* ============================================================
|
||
ANNOTATION
|
||
Editorial callout boxes: definitions, notes, remarks, warnings.
|
||
Two variants: static (always visible) and collapsible.
|
||
============================================================ */
|
||
|
||
.annotation {
|
||
position: relative;
|
||
margin: 1.65rem 0;
|
||
border: 1px solid var(--border);
|
||
border-radius: 2px;
|
||
}
|
||
|
||
.annotation-header {
|
||
display: flex;
|
||
align-items: baseline;
|
||
justify-content: space-between;
|
||
gap: 0.5rem;
|
||
padding: 0.5rem 0.85rem;
|
||
border-bottom: 1px solid var(--border);
|
||
background: var(--bg-offset);
|
||
}
|
||
|
||
.annotation-label {
|
||
font-family: var(--font-sans);
|
||
font-size: 0.68rem;
|
||
font-weight: 600;
|
||
font-variant-caps: all-small-caps;
|
||
letter-spacing: 0.06em;
|
||
color: var(--text-faint);
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.annotation-name {
|
||
font-family: var(--font-sans);
|
||
font-size: 0.78rem;
|
||
color: var(--text-muted);
|
||
font-style: italic;
|
||
flex: 1;
|
||
min-width: 0;
|
||
}
|
||
|
||
.annotation-toggle {
|
||
background: none;
|
||
border: none;
|
||
cursor: pointer;
|
||
font-family: var(--font-sans);
|
||
font-size: 0.68rem;
|
||
color: var(--text-faint);
|
||
padding: 0;
|
||
line-height: 1;
|
||
flex-shrink: 0;
|
||
transition: color var(--transition-fast);
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.annotation-toggle:hover {
|
||
color: var(--text-muted);
|
||
}
|
||
|
||
.annotation-body {
|
||
padding: 0.825rem 0.85rem;
|
||
}
|
||
|
||
/* Collapsible variant: body hidden until toggled.
|
||
Only max-height transitions — padding applies instantly so that
|
||
scrollHeight reads the correct full height before the animation starts. */
|
||
.annotation--collapsible .annotation-body {
|
||
overflow: hidden;
|
||
max-height: 0;
|
||
padding-top: 0;
|
||
padding-bottom: 0;
|
||
transition: max-height 0.35s ease;
|
||
}
|
||
|
||
.annotation--collapsible.is-open .annotation-body {
|
||
padding-top: 0.825rem;
|
||
padding-bottom: 0.825rem;
|
||
}
|
||
|
||
/* Static variant: always open, no toggle */
|
||
.annotation--static .annotation-header {
|
||
border-bottom: 1px solid var(--border);
|
||
}
|
||
|
||
|
||
/* ============================================================
|
||
OVERLAY
|
||
Full-screen dark stage. Content floats inside — no panel box.
|
||
Modeled on Gwern's image-focus: the overlay IS the backdrop,
|
||
content is centered directly within it.
|
||
============================================================ */
|
||
|
||
#gallery-overlay {
|
||
position: fixed;
|
||
inset: 0;
|
||
z-index: 500;
|
||
background: rgba(0, 0, 0, 0.92);
|
||
cursor: zoom-out;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
#gallery-overlay[hidden] {
|
||
display: none;
|
||
}
|
||
|
||
/* Content stage — large light area centered in the dark screen.
|
||
Fixed width (not max-width) so JS can detect overflow for font fitting. */
|
||
#gallery-overlay-body {
|
||
background: var(--bg);
|
||
padding: 3.5rem 4.5rem;
|
||
width: 88vw;
|
||
max-height: 80vh;
|
||
overflow: hidden; /* JS shrinks font until content fits; auto as last resort */
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
box-shadow: 0 0 80px rgba(0, 0, 0, 0.5);
|
||
cursor: default; /* undo zoom-out from parent */
|
||
}
|
||
|
||
#gallery-overlay-body .katex-display {
|
||
/* font-size is set entirely by JS after measuring — no CSS value here */
|
||
overflow-x: hidden;
|
||
margin: 0;
|
||
}
|
||
|
||
/* Close — top right of screen */
|
||
#gallery-overlay-close {
|
||
position: absolute;
|
||
top: 1.1rem;
|
||
right: 1.5rem;
|
||
background: none;
|
||
border: none;
|
||
cursor: pointer;
|
||
font-family: var(--font-sans);
|
||
font-size: 1.5rem;
|
||
color: rgba(255, 255, 255, 0.5);
|
||
padding: 0.3rem 0.5rem;
|
||
line-height: 1;
|
||
transition: color var(--transition-fast);
|
||
}
|
||
|
||
#gallery-overlay-close:hover {
|
||
color: rgba(255, 255, 255, 0.95);
|
||
}
|
||
|
||
/* Group name — top center of screen */
|
||
#gallery-overlay-name {
|
||
position: absolute;
|
||
top: 1.5rem;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
font-family: var(--font-sans);
|
||
font-size: 0.9rem;
|
||
font-weight: 600;
|
||
font-variant-caps: all-small-caps;
|
||
letter-spacing: 0.09em;
|
||
color: rgba(255, 255, 255, 0.5);
|
||
white-space: nowrap;
|
||
pointer-events: none;
|
||
}
|
||
|
||
/* Caption — bottom center of screen, above counter */
|
||
#gallery-overlay-caption {
|
||
position: absolute;
|
||
bottom: 3.5rem;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
font-family: var(--font-sans);
|
||
font-size: 1rem;
|
||
font-style: italic;
|
||
color: rgba(255, 255, 255, 0.65);
|
||
text-align: center;
|
||
max-width: 60vw;
|
||
pointer-events: none;
|
||
}
|
||
|
||
#gallery-overlay-caption:empty,
|
||
#gallery-overlay-caption[hidden] {
|
||
display: none;
|
||
}
|
||
|
||
/* Counter — bottom center of screen */
|
||
#gallery-overlay-counter {
|
||
position: absolute;
|
||
bottom: 1.5rem;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
font-family: var(--font-sans);
|
||
font-size: 0.82rem;
|
||
color: rgba(255, 255, 255, 0.38);
|
||
pointer-events: none;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
/* Nav buttons — floating at the screen edges, vertically centered */
|
||
.gallery-nav-btn {
|
||
position: absolute;
|
||
top: 50%;
|
||
transform: translateY(-50%);
|
||
background: none;
|
||
border: none;
|
||
cursor: pointer;
|
||
font-family: var(--font-sans);
|
||
font-size: 2.25rem;
|
||
color: rgba(255, 255, 255, 0.35);
|
||
padding: 0.75rem 1rem;
|
||
line-height: 1;
|
||
transition: color var(--transition-fast);
|
||
}
|
||
|
||
.gallery-nav-btn:hover:not(:disabled) {
|
||
color: rgba(255, 255, 255, 0.9);
|
||
}
|
||
|
||
.gallery-nav-btn:disabled {
|
||
opacity: 0;
|
||
pointer-events: none;
|
||
}
|
||
|
||
#gallery-overlay-prev { left: 1rem; }
|
||
#gallery-overlay-next { right: 1rem; }
|
||
|
||
|
||
/* ============================================================
|
||
SCORE FRAGMENT
|
||
Inline SVG music notation. Integrates with the gallery focusable
|
||
and named-exhibit systems. No header — caption only.
|
||
============================================================ */
|
||
|
||
.score-fragment {
|
||
position: relative;
|
||
display: block;
|
||
margin: 2rem 0;
|
||
cursor: zoom-in;
|
||
}
|
||
|
||
/* Reset #markdownBody figure box styles — must use ID+class to beat
|
||
the specificity of `#markdownBody figure` (0,1,1 vs 0,1,0). */
|
||
#markdownBody figure.score-fragment {
|
||
background: none;
|
||
border: none;
|
||
padding: 0;
|
||
box-shadow: none;
|
||
max-width: 100%; /* override fit-content so SVG fills the column */
|
||
margin: 2rem 0; /* override the base 3.3rem auto */
|
||
}
|
||
|
||
.score-fragment-inner {
|
||
display: block;
|
||
line-height: 0; /* collapse inline gap below the SVG block */
|
||
}
|
||
|
||
/* Make the LilyPond SVG responsive and theme-aware.
|
||
CSS width/height override the SVG's own width/height presentation
|
||
attributes. color: var(--text) is inherited by currentColor fills/strokes
|
||
(set by Filters.Score at build time). */
|
||
.score-fragment-inner svg {
|
||
width: 100%;
|
||
height: auto;
|
||
display: block;
|
||
color: var(--text);
|
||
}
|
||
|
||
/* Remove LilyPond's white background rectangle */
|
||
.score-fragment-inner svg > rect:first-child {
|
||
fill: none;
|
||
}
|
||
|
||
/* Expand glyph: top-right corner, not vertically centred */
|
||
.score-fragment .exhibit-expand {
|
||
top: 0.5rem;
|
||
transform: none;
|
||
}
|
||
|
||
.score-fragment:hover .exhibit-expand {
|
||
opacity: 1;
|
||
}
|
||
|
||
.score-caption {
|
||
font-family: var(--font-sans);
|
||
font-size: 0.82rem;
|
||
font-style: italic;
|
||
color: var(--text-muted);
|
||
text-align: center;
|
||
margin-top: 0.65rem;
|
||
line-height: 1.4;
|
||
}
|
||
|
||
|
||
/* ============================================================
|
||
OVERLAY — SCORE MODE
|
||
Tighter horizontal padding; SVG fills available width.
|
||
============================================================ */
|
||
|
||
#gallery-overlay-body.is-score {
|
||
padding: 2rem 1.5rem;
|
||
/* Caption sits at bottom: 3.5rem in the viewport. The body is flex-centered,
|
||
so its bottom edge = (100vh + body-height) / 2. To guarantee clearance,
|
||
body-height must be ≤ 100vh − 2 × caption-offset − some margin.
|
||
calc(100vh − 12rem) keeps the bottom edge ≥ 6rem above the viewport bottom
|
||
regardless of screen size. */
|
||
max-height: calc(100vh - 12rem);
|
||
}
|
||
|
||
#gallery-overlay-body.is-score svg {
|
||
width: 100%;
|
||
height: auto;
|
||
max-height: calc(100vh - 16rem); /* body height minus 2rem padding each side */
|
||
display: block;
|
||
color: var(--text);
|
||
}
|
||
|
||
#gallery-overlay-body.is-score svg > rect:first-child {
|
||
fill: none;
|
||
}
|
||
|
||
|
||
/* ============================================================
|
||
TOC EXHIBIT INTEGRATION
|
||
============================================================ */
|
||
|
||
/* Compact inline exhibit links under a heading entry */
|
||
.toc-exhibits-inline {
|
||
font-size: 0.69rem;
|
||
color: var(--text-faint);
|
||
line-height: 1.4;
|
||
margin-top: 0.1rem;
|
||
padding-left: 0.75rem;
|
||
}
|
||
|
||
.toc-exhibits-inline a {
|
||
display: flex;
|
||
align-items: baseline;
|
||
gap: 0.4em;
|
||
color: var(--text-faint);
|
||
text-decoration: none;
|
||
padding: 0.1rem 0;
|
||
font-size: 0.74rem;
|
||
transition: color var(--transition-fast);
|
||
}
|
||
|
||
.toc-exhibits-inline a:hover {
|
||
color: var(--text-muted);
|
||
}
|
||
|
||
/* Contained Herein — collapsible global exhibit index */
|
||
.toc-contained {
|
||
margin-top: 0.9rem;
|
||
padding-top: 0.6rem;
|
||
border-top: 1px solid var(--border);
|
||
}
|
||
|
||
.toc-contained-toggle {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.35em;
|
||
background: none;
|
||
border: none;
|
||
cursor: pointer;
|
||
font-family: var(--font-sans);
|
||
font-size: 0.69rem;
|
||
font-weight: 600;
|
||
font-variant-caps: all-small-caps;
|
||
letter-spacing: 0.06em;
|
||
color: var(--text-faint);
|
||
padding: 0;
|
||
line-height: 1.5;
|
||
width: 100%;
|
||
text-align: left;
|
||
transition: color var(--transition-fast);
|
||
}
|
||
|
||
.toc-contained-toggle:hover {
|
||
color: var(--text-muted);
|
||
}
|
||
|
||
.toc-contained-arrow {
|
||
font-size: 0.55rem;
|
||
display: inline-block;
|
||
transition: transform 0.15s ease;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.toc-contained.is-open .toc-contained-arrow {
|
||
transform: rotate(90deg);
|
||
}
|
||
|
||
.toc-contained-list {
|
||
list-style: none;
|
||
padding: 0;
|
||
margin: 0.35rem 0 0 0;
|
||
display: none;
|
||
}
|
||
|
||
.toc-contained.is-open .toc-contained-list {
|
||
display: block;
|
||
}
|
||
|
||
.toc-contained-list li {
|
||
margin: 0.2rem 0;
|
||
}
|
||
|
||
.toc-contained-list a {
|
||
display: flex;
|
||
align-items: baseline;
|
||
gap: 0.4em;
|
||
font-size: 0.72rem;
|
||
color: var(--text-faint);
|
||
text-decoration: none;
|
||
transition: color var(--transition-fast);
|
||
}
|
||
|
||
.toc-contained-list a:hover {
|
||
color: var(--text-muted);
|
||
}
|
||
|
||
.toc-exhibit-type-badge {
|
||
font-size: 0.6rem;
|
||
font-variant-caps: all-small-caps;
|
||
letter-spacing: 0.05em;
|
||
color: var(--text-faint);
|
||
flex-shrink: 0;
|
||
}
|