/* 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
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; }