pandorga 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +77 -0
- data/DESIGN.md +1434 -0
- data/LICENSE +21 -0
- data/README.md +81 -0
- data/_data/themes/dark.yml +97 -0
- data/_data/themes/light.yml +120 -0
- data/_data/themes/shared.yml +37 -0
- data/_data/translations.yml +85 -0
- data/_includes/chord-tab.html +38 -0
- data/_includes/content-runtime/00-config.html +22 -0
- data/_includes/content-runtime/10-utils.html +176 -0
- data/_includes/content-runtime/20-markdown.html +264 -0
- data/_includes/content-runtime/25-code-blocks.html +315 -0
- data/_includes/content-runtime/30-includes-bib.html +190 -0
- data/_includes/content-runtime/30-includes-xcite.html +122 -0
- data/_includes/content-runtime/30-includes.html +365 -0
- data/_includes/content-runtime/40-listing.html +225 -0
- data/_includes/content-runtime/41-listing-helpers.html +71 -0
- data/_includes/content-runtime/42-listing-filter.html +208 -0
- data/_includes/content-runtime/43-blocks.html +379 -0
- data/_includes/content-runtime/50-detail.html +861 -0
- data/_includes/content-runtime/55-toc.html +176 -0
- data/_includes/content-runtime/60-fragments.html +567 -0
- data/_includes/content-runtime/90-bootstrap.html +76 -0
- data/_includes/cut-in.html +10 -0
- data/_includes/cv/cv-box.html +18 -0
- data/_includes/dict-card.html +24 -0
- data/_includes/figure.html +36 -0
- data/_includes/home/band-index.html +43 -0
- data/_includes/home/band-listing.html +49 -0
- data/_includes/mathjax.html +10 -0
- data/_includes/ongoing-product.html +1 -0
- data/_includes/page/content-runtime.html +20 -0
- data/_includes/page/date_evolution.html +19 -0
- data/_includes/page/figure-lightbox.html +102 -0
- data/_includes/page/formatted_date.html +15 -0
- data/_includes/page/hero-default.html +18 -0
- data/_includes/page/listing-runtime-attrs.html +8 -0
- data/_includes/page/mermaid.html +101 -0
- data/_includes/page/network-graph.html +1253 -0
- data/_includes/page/page-header.html +41 -0
- data/_includes/page/professional-connections.html +2 -0
- data/_includes/page/site-footer.html +101 -0
- data/_includes/page/timeline-section.html +868 -0
- data/_includes/plotly.html +22 -0
- data/_includes/theme/dev-reexport.html +100 -0
- data/_includes/theme/favicons.html +4 -0
- data/_includes/theme/font-loader.html +55 -0
- data/_includes/theme/shell-theme-boot.html +115 -0
- data/_includes/theme/site-logo.html +6 -0
- data/_includes/theme/tailwind-theme-colors.json.liquid +65 -0
- data/_includes/theme/tailwind-theme-fonts.json.liquid +6 -0
- data/_includes/theme/theme-context.liquid +20 -0
- data/_includes/theme/theme-toggle.html +94 -0
- data/_includes/theme/theme-vars-block.liquid +161 -0
- data/_includes/theme/theme-vars.html +16 -0
- data/_includes/transcription.html +80 -0
- data/_includes/tweet.html +22 -0
- data/_includes/video.html +11 -0
- data/_includes/xcite.html +3 -0
- data/_includes/youtube-short.html +26 -0
- data/_includes/youtube.html +12 -0
- data/_layouts/article.html +27 -0
- data/_layouts/articles.html +534 -0
- data/_layouts/bibliography.html +417 -0
- data/_layouts/blog.html +544 -0
- data/_layouts/cv.html +393 -0
- data/_layouts/home.html +319 -0
- data/_layouts/network.html +9 -0
- data/_layouts/pandorga/articles.html +4 -0
- data/_layouts/pandorga/bibliography.html +4 -0
- data/_layouts/pandorga/blog.html +4 -0
- data/_layouts/pandorga/cv.html +4 -0
- data/_layouts/pandorga/media.html +4 -0
- data/_layouts/pandorga/network.html +4 -0
- data/_layouts/pandorga/portfolio.html +4 -0
- data/_layouts/post.html +7 -0
- data/_layouts/product.html +5 -0
- data/_layouts/project.html +27 -0
- data/_layouts/projects.html +534 -0
- data/_layouts/resources.html +387 -0
- data/_layouts/shell.html +203 -0
- data/_layouts/text.html +246 -0
- data/_plugins/bibliography_artifact.rb +57 -0
- data/_plugins/content_backend.rb +37 -0
- data/_plugins/content_collections.rb +51 -0
- data/_plugins/content_detail_paths.rb +58 -0
- data/_plugins/content_headers.rb +73 -0
- data/_plugins/content_keys.rb +310 -0
- data/_plugins/content_local_serve.rb +168 -0
- data/_plugins/content_site_adapter.rb +159 -0
- data/_plugins/content_validators_hook.rb +20 -0
- data/_plugins/content_writing_index.rb +52 -0
- data/_plugins/content_writing_paths.rb +55 -0
- data/_plugins/force_utf8_encoding.rb +13 -0
- data/_plugins/git_chronology.rb +211 -0
- data/_plugins/git_metadata.rb +43 -0
- data/_plugins/job_sections.rb +25 -0
- data/_plugins/lib/content_validators.rb +27 -0
- data/_plugins/lib/resource_validator.rb +56 -0
- data/_plugins/lib/tag_validator.rb +153 -0
- data/_plugins/lib/text_excerpt.rb +56 -0
- data/_plugins/lib/writing_entry.rb +107 -0
- data/_plugins/local_detail_rewrites.rb +194 -0
- data/_plugins/timeline.rb +507 -0
- data/_plugins/writing_slug_limits.rb +70 -0
- data/assets/css/article.css +1330 -0
- data/assets/css/base.css +1432 -0
- data/assets/css/cv.css +13 -0
- data/assets/css/global-link.css +94 -0
- data/assets/css/ledger/bibliography.css +307 -0
- data/assets/css/ledger/chrome.css +118 -0
- data/assets/css/ledger/cv.css +836 -0
- data/assets/css/ledger/detail.css +1270 -0
- data/assets/css/ledger/footer.css +298 -0
- data/assets/css/ledger/home.css +1490 -0
- data/assets/css/ledger/network.css +106 -0
- data/assets/css/ledger/projects.css +716 -0
- data/assets/css/ledger/rascunhos.css +379 -0
- data/assets/css/ledger/sources.css +327 -0
- data/assets/css/ledger/writing.css +754 -0
- data/assets/tailwind-play.js +15 -0
- data/examples/full/Gemfile +7 -0
- data/examples/full/_config.yml +92 -0
- data/examples/full/_redirects +3 -0
- data/examples/full/content/collections/articles/2026-01-01-welcome.md +9 -0
- data/examples/full/content/collections/data/contacts.yml +3 -0
- data/examples/full/content/collections/data/education.yml +4 -0
- data/examples/full/content/collections/jobs/research-fellow.md +12 -0
- data/examples/full/content/collections/posts/2026-01-02-note.md +9 -0
- data/examples/full/content/collections/products/ledger-tool.md +6 -0
- data/examples/full/content/collections/projects/demo-kit.md +10 -0
- data/examples/full/content/collections/resources/style-guide.md +7 -0
- data/examples/full/content/pages/cv/summary.md +1 -0
- data/examples/full/content/pages/headers.yml +20 -0
- data/examples/full/index.html +4 -0
- data/examples/minimal/Gemfile +7 -0
- data/examples/minimal/_config.yml +47 -0
- data/examples/minimal/_redirects +3 -0
- data/examples/minimal/content/collections/articles/2026-01-01-hello.md +10 -0
- data/examples/minimal/content/collections/articles/2026-01-02-second.md +9 -0
- data/examples/minimal/content/pages/headers.yml +6 -0
- data/examples/minimal/index.html +4 -0
- data/exe/pandorga +7 -0
- data/functions/api/studio/[[path]].js +562 -0
- data/functions/api/studio/_lib/auth.js +131 -0
- data/functions/api/studio/_lib/blocks.js +156 -0
- data/functions/api/studio/_lib/gemini.js +62 -0
- data/functions/api/studio/_lib/github.js +278 -0
- data/functions/api/studio/_lib/guidelines.js +143 -0
- data/functions/api/studio/_lib/paths.js +76 -0
- data/functions/api/studio/_lib/prompts.js +165 -0
- data/functions/api/studio/_lib/rate-limit.js +40 -0
- data/functions/api/studio/_lib/rewrite.js +136 -0
- data/functions/api/studio/_lib/sanitize.js +143 -0
- data/lib/pandorga/cli.rb +66 -0
- data/lib/pandorga/commands/doctor.rb +66 -0
- data/lib/pandorga/commands/export.rb +30 -0
- data/lib/pandorga/commands/install_functions.rb +41 -0
- data/lib/pandorga/commands/new.rb +113 -0
- data/lib/pandorga/commands/publish.rb +53 -0
- data/lib/pandorga/commands/serve.rb +34 -0
- data/lib/pandorga/commands/studio_schema.rb +309 -0
- data/lib/pandorga/jekyll/generator.rb +74 -0
- data/lib/pandorga/jekyll/plugins/bibliography_artifact.rb +57 -0
- data/lib/pandorga/jekyll/plugins/content_backend.rb +37 -0
- data/lib/pandorga/jekyll/plugins/content_collections.rb +51 -0
- data/lib/pandorga/jekyll/plugins/content_detail_paths.rb +58 -0
- data/lib/pandorga/jekyll/plugins/content_headers.rb +73 -0
- data/lib/pandorga/jekyll/plugins/content_keys.rb +310 -0
- data/lib/pandorga/jekyll/plugins/content_local_serve.rb +168 -0
- data/lib/pandorga/jekyll/plugins/content_site_adapter.rb +159 -0
- data/lib/pandorga/jekyll/plugins/content_validators_hook.rb +20 -0
- data/lib/pandorga/jekyll/plugins/content_writing_index.rb +52 -0
- data/lib/pandorga/jekyll/plugins/content_writing_paths.rb +55 -0
- data/lib/pandorga/jekyll/plugins/force_utf8_encoding.rb +13 -0
- data/lib/pandorga/jekyll/plugins/git_chronology.rb +211 -0
- data/lib/pandorga/jekyll/plugins/git_metadata.rb +43 -0
- data/lib/pandorga/jekyll/plugins/job_sections.rb +25 -0
- data/lib/pandorga/jekyll/plugins/lib/content_validators.rb +27 -0
- data/lib/pandorga/jekyll/plugins/lib/resource_validator.rb +56 -0
- data/lib/pandorga/jekyll/plugins/lib/tag_validator.rb +153 -0
- data/lib/pandorga/jekyll/plugins/lib/text_excerpt.rb +56 -0
- data/lib/pandorga/jekyll/plugins/lib/writing_entry.rb +107 -0
- data/lib/pandorga/jekyll/plugins/local_detail_rewrites.rb +194 -0
- data/lib/pandorga/jekyll/plugins/timeline.rb +507 -0
- data/lib/pandorga/jekyll/plugins/writing_slug_limits.rb +70 -0
- data/lib/pandorga/jekyll.rb +15 -0
- data/lib/pandorga/object_store_env.rb +51 -0
- data/lib/pandorga/registry/schema.yml +115 -0
- data/lib/pandorga/registry.rb +279 -0
- data/lib/pandorga/version.rb +5 -0
- data/lib/pandorga.rb +19 -0
- data/scripts/cdn-allowlist.json +19 -0
- data/scripts/content/backfill-content-keys.rb +99 -0
- data/scripts/content/band_art.rb +362 -0
- data/scripts/content/export-content-json.rb +741 -0
- data/scripts/content/flatten-ansi-capture.mjs +153 -0
- data/scripts/content/hero_portraits.rb +28 -0
- data/scripts/content/publish-content-to-object-store.sh +78 -0
- data/scripts/content/publish-content-to-r2.sh +5 -0
- data/scripts/content/sync-content-json-to-r2.rb +167 -0
- data/scripts/content/sync-content-redirects.rb +12 -0
- data/scripts/generate-configuration-doc.rb +127 -0
- data/scripts/lib/content_license.rb +50 -0
- data/scripts/lib/content_storage_config.rb +70 -0
- data/scripts/lib/normalize-display-math.mjs +52 -0
- data/scripts/lib/r2_json_sync.rb +76 -0
- data/scripts/lib/withdrawn_public_objects.rb +23 -0
- data/scripts/lib/writing_index_contract.rb +61 -0
- data/scripts/pdf/md-to-pdf.mjs +1400 -0
- data/scripts/pdf/md-to-pdf.sh +27 -0
- data/scripts/test/fixtures/dual-template/_config.yml +32 -0
- data/scripts/test/fixtures/dual-template/index.html +4 -0
- data/scripts/test/render-parity/article-note.json +5 -0
- data/scripts/test/render-parity/blockquote.json +5 -0
- data/scripts/test/render-parity/blocks/ansi-basic.json +7 -0
- data/scripts/test/render-parity/blocks/ansi-bold-is-bright.json +7 -0
- data/scripts/test/render-parity/blocks/ansi-drops-cursor-moves.json +7 -0
- data/scripts/test/render-parity/blocks/ansi-escapes-markup.json +7 -0
- data/scripts/test/render-parity/blocks/ansi-extended-colour.json +7 -0
- data/scripts/test/render-parity/blocks/ansi-real-control-byte.json +7 -0
- data/scripts/test/render-parity/blocks/archive-card-date-once.json +19 -0
- data/scripts/test/render-parity/blocks/archive-card-empty-foot.json +7 -0
- data/scripts/test/render-parity/blocks/archive-card-footer-dates.json +22 -0
- data/scripts/test/render-parity/blocks/archive-card-meta-parts.json +26 -0
- data/scripts/test/render-parity/blocks/archive-card.json +32 -0
- data/scripts/test/render-parity/blocks/cta-link.json +13 -0
- data/scripts/test/render-parity/blocks/lang-pill-pt.json +8 -0
- data/scripts/test/render-parity/blocks/lang-pill.json +8 -0
- data/scripts/test/render-parity/blocks/ledger-row-meta-parts.json +29 -0
- data/scripts/test/render-parity/blocks/ledger-row.json +35 -0
- data/scripts/test/render-parity/blocks/meta-strip.json +27 -0
- data/scripts/test/render-parity/blocks/poster-media-image.json +8 -0
- data/scripts/test/render-parity/blocks/poster-media-video.json +9 -0
- data/scripts/test/render-parity/blocks/section-banner.json +13 -0
- data/scripts/test/render-parity/blocks/system-card-custom-meta.json +22 -0
- data/scripts/test/render-parity/blocks/system-card.json +48 -0
- data/scripts/test/render-parity/blocks/tag-chips-links.json +12 -0
- data/scripts/test/render-parity/blocks/tag-chips.json +9 -0
- data/scripts/test/render-parity/cut-in-blank-line.json +9 -0
- data/scripts/test/render-parity/cut-in-right.json +9 -0
- data/scripts/test/render-parity/cut-in.json +8 -0
- data/scripts/test/render-parity/figure.json +5 -0
- data/scripts/test/render-parity/load-runtime.mjs +337 -0
- data/scripts/test/render-parity/ongoing-product.json +5 -0
- data/scripts/test/render-parity/plotly.json +5 -0
- data/scripts/test/render-parity/poem.json +5 -0
- data/scripts/test/render-parity/run-absent-field-checks.mjs +232 -0
- data/scripts/test/render-parity/run-block-fixture.mjs +86 -0
- data/scripts/test/render-parity/run-detail-parity-checks.mjs +123 -0
- data/scripts/test/render-parity/run-field-flow-checks.mjs +227 -0
- data/scripts/test/render-parity/run-fixture.mjs +159 -0
- data/scripts/test/render-parity/selectors.mjs +43 -0
- data/scripts/test/render-parity/video.json +5 -0
- data/scripts/test/render-parity/youtube-short.json +10 -0
- data/scripts/test/render-parity/youtube.json +8 -0
- data/scripts/test/test-absent-field-absent-element.rb +43 -0
- data/scripts/test/test-cdn-pins.rb +44 -0
- data/scripts/test/test-cloudflare-watch-paths-doc.rb +31 -0
- data/scripts/test/test-configuration-doc.rb +36 -0
- data/scripts/test/test-content-detail-urls.rb +346 -0
- data/scripts/test/test-content-keys.rb +110 -0
- data/scripts/test/test-content-license.rb +45 -0
- data/scripts/test/test-content-render-parity.rb +38 -0
- data/scripts/test/test-content-validators.rb +12 -0
- data/scripts/test/test-css-structure.rb +72 -0
- data/scripts/test/test-cv-export-contract.rb +158 -0
- data/scripts/test/test-detail-render-parity.rb +40 -0
- data/scripts/test/test-dev-reexport.rb +122 -0
- data/scripts/test/test-doctor.rb +39 -0
- data/scripts/test/test-dual-template-instances.rb +87 -0
- data/scripts/test/test-dual-template-runtime.rb +167 -0
- data/scripts/test/test-examples-build.rb +60 -0
- data/scripts/test/test-export-content-json-incremental.rb +138 -0
- data/scripts/test/test-export.rb +53 -0
- data/scripts/test/test-exported-fields-reach-the-view.rb +60 -0
- data/scripts/test/test-form-control-theming.rb +143 -0
- data/scripts/test/test-git-chronology.rb +414 -0
- data/scripts/test/test-hero-portraits.mjs +97 -0
- data/scripts/test/test-hero-portraits.rb +162 -0
- data/scripts/test/test-home-band-art.rb +135 -0
- data/scripts/test/test-install-functions.rb +39 -0
- data/scripts/test/test-language-export.rb +79 -0
- data/scripts/test/test-listing-filter-contract.rb +119 -0
- data/scripts/test/test-math-row-breaks.mjs +79 -0
- data/scripts/test/test-math-row-breaks.rb +18 -0
- data/scripts/test/test-new.rb +113 -0
- data/scripts/test/test-no-personal-data.rb +85 -0
- data/scripts/test/test-public-cv-export.rb +164 -0
- data/scripts/test/test-r2-config-consistency.rb +57 -0
- data/scripts/test/test-r2-json-sync.rb +193 -0
- data/scripts/test/test-registry-home.rb +34 -0
- data/scripts/test/test-runtime-js-syntax.rb +64 -0
- data/scripts/test/test-slim-writing-index.rb +126 -0
- data/scripts/test/test-studio-api-contract.rb +99 -0
- data/scripts/test/test-studio-content-files.rb +79 -0
- data/scripts/test/test-studio-liquid-roundtrip.mjs +179 -0
- data/scripts/test/test-studio-rate-limit.mjs +70 -0
- data/scripts/test/test-studio-rewrite-api-contract.rb +59 -0
- data/scripts/test/test-studio-rewrite-sanitize.mjs +210 -0
- data/scripts/test/test-studio-schema-composition.rb +126 -0
- data/scripts/test/test-studio-slug-config.rb +167 -0
- data/scripts/test/test-template-packages.rb +51 -0
- data/scripts/test/test-text-excerpt.rb +51 -0
- data/scripts/test/test-unwrap-media-src.mjs +39 -0
- data/scripts/test/test-unwrap-media-src.rb +19 -0
- data/scripts/test/test-withdrawn-content-export.rb +69 -0
- data/scripts/test/test-writing-index-export-slugs.rb +84 -0
- data/scripts/test/test-writing-slug-limits.rb +61 -0
- data/scripts/test/test-xcite-chronology.rb +106 -0
- data/scripts/validate.sh +74 -0
- data/scripts/visual/build-cv-pages-json.js +33 -0
- data/scripts/visual/build-site-pages-json.js +94 -0
- data/scripts/visual/publish-visual-inspection-to-r2.sh +42 -0
- data/scripts/visual/take-screenshots.js +88 -0
- data/scripts/visual/visual-inspection-pages.json +113 -0
- data/studio/assets/index-B_j0pMD5.css +1 -0
- data/studio/assets/index-Ch4YEv9g.js +285 -0
- data/studio/index.html +27 -0
- data/studio/schema.yml +869 -0
- data/studio-app/README.md +27 -0
- data/studio-app/index.html +26 -0
- data/studio-app/package-lock.json +2499 -0
- data/studio-app/package.json +26 -0
- data/studio-app/skills-lock.json +47 -0
- data/studio-app/src/api/client.js +71 -0
- data/studio-app/src/editor/body-editor.js +70 -0
- data/studio-app/src/editor/liquid-core.js +382 -0
- data/studio-app/src/editor/liquid.js +77 -0
- data/studio-app/src/lib/document.js +207 -0
- data/studio-app/src/lib/list-controls.js +317 -0
- data/studio-app/src/lib/schema.js +66 -0
- data/studio-app/src/lib/yaml-doc.js +100 -0
- data/studio-app/src/main.js +3693 -0
- data/studio-app/src/media/browser.js +578 -0
- data/studio-app/src/preview/render.js +430 -0
- data/studio-app/src/styles/studio.css +2826 -0
- data/studio-app/vite.config.js +25 -0
- data/templates/articles/README.md +40 -0
- data/templates/articles/fixtures/article.md +9 -0
- data/templates/articles/screenshots/README.md +6 -0
- data/templates/articles/studio.yml +73 -0
- data/templates/articles/template.yml +21 -0
- data/templates/bibliography/README.md +41 -0
- data/templates/bibliography/fixtures/references.json +9 -0
- data/templates/bibliography/screenshots/README.md +6 -0
- data/templates/bibliography/studio.yml +66 -0
- data/templates/bibliography/template.yml +18 -0
- data/templates/blog/README.md +38 -0
- data/templates/blog/fixtures/post.md +9 -0
- data/templates/blog/screenshots/README.md +6 -0
- data/templates/blog/studio.yml +69 -0
- data/templates/blog/template.yml +20 -0
- data/templates/cv/README.md +34 -0
- data/templates/cv/fixtures/job.md +12 -0
- data/templates/cv/screenshots/README.md +6 -0
- data/templates/cv/studio.yml +200 -0
- data/templates/cv/template.yml +25 -0
- data/templates/media/README.md +38 -0
- data/templates/media/fixtures/resource.md +7 -0
- data/templates/media/screenshots/README.md +6 -0
- data/templates/media/studio.yml +58 -0
- data/templates/media/template.yml +17 -0
- data/templates/network/README.md +34 -0
- data/templates/network/fixtures/sources.json +3 -0
- data/templates/network/screenshots/README.md +6 -0
- data/templates/network/studio.yml +28 -0
- data/templates/network/template.yml +10 -0
- data/templates/portfolio/README.md +39 -0
- data/templates/portfolio/fixtures/project.md +10 -0
- data/templates/portfolio/screenshots/README.md +6 -0
- data/templates/portfolio/studio.yml +89 -0
- data/templates/portfolio/template.yml +18 -0
- metadata +505 -0
|
@@ -0,0 +1,1270 @@
|
|
|
1
|
+
/* Ledger page styles: detail. Owned by the detail page; shared component rules
|
|
2
|
+
belong in assets/css/base.css under "Architectural Ledger blocks".
|
|
3
|
+
|
|
4
|
+
Scope note. Public detail views are assembled in the browser by
|
|
5
|
+
`_includes/content-runtime/50-detail.html` (`buildTextSidebar`,
|
|
6
|
+
`renderRuntimeDetailSection`) and mounted by the listing layouts, so this
|
|
7
|
+
file styles the DOM that runtime emits. `_layouts/text.html` emits the same
|
|
8
|
+
class contract for the private studio build; every rule below therefore
|
|
9
|
+
targets classes, never a container that exists on only one of the two paths.
|
|
10
|
+
|
|
11
|
+
Specificity note. The Tailwind Play CDN injects its utilities *after* this
|
|
12
|
+
stylesheet, so a single-class rule loses to any colliding utility already on
|
|
13
|
+
the element (`text-tertiary`, `text-xs`, `flex`, `mb-8`, …). Rules that have
|
|
14
|
+
to beat one are written with two compound parts on purpose. */
|
|
15
|
+
|
|
16
|
+
/* ══ Reading progress ══
|
|
17
|
+
Pure UI state, no field beNewsreader it, and no DOM hook to hang it on — the
|
|
18
|
+
runtime owns the detail markup. A scroll-driven animation on a pseudo of
|
|
19
|
+
the detail section gives the mockup's indicator with zero markup, and the
|
|
20
|
+
@supports guard means older engines simply get no bar.
|
|
21
|
+
|
|
22
|
+
Sit under the sticky site nav (z-50), not over it — a top-of-viewport bar
|
|
23
|
+
was invisible against the nav surface. */
|
|
24
|
+
@supports (animation-timeline: scroll(root block)) {
|
|
25
|
+
|
|
26
|
+
:is([data-dynamic-article-detail],
|
|
27
|
+
[data-dynamic-post-detail],
|
|
28
|
+
[data-dynamic-project-detail],
|
|
29
|
+
[data-dynamic-product-detail],
|
|
30
|
+
[data-detail-view])::before {
|
|
31
|
+
content: "";
|
|
32
|
+
position: fixed;
|
|
33
|
+
left: 0;
|
|
34
|
+
right: 0;
|
|
35
|
+
/* Approx sticky nav stack: wordmark row + padding (shell sticky nav). */
|
|
36
|
+
top: 4.25rem;
|
|
37
|
+
z-index: 40;
|
|
38
|
+
height: 2px;
|
|
39
|
+
background: var(--color-primary);
|
|
40
|
+
transform: scaleX(0);
|
|
41
|
+
transform-origin: 0 50%;
|
|
42
|
+
pointer-events: none;
|
|
43
|
+
animation-name: detail-read-progress;
|
|
44
|
+
animation-duration: 1ms;
|
|
45
|
+
animation-timing-function: linear;
|
|
46
|
+
animation-fill-mode: both;
|
|
47
|
+
animation-timeline: scroll(root block);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@keyframes detail-read-progress {
|
|
52
|
+
from {
|
|
53
|
+
transform: scaleX(0);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
to {
|
|
57
|
+
transform: scaleX(1);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/* The bar is decoration driven by the scroll position: nothing on the page
|
|
62
|
+
depends on it, so a reader who has asked for less motion simply does not get
|
|
63
|
+
a strip that tracks their scrolling. */
|
|
64
|
+
@media (prefers-reduced-motion: reduce) {
|
|
65
|
+
|
|
66
|
+
:is([data-dynamic-article-detail],
|
|
67
|
+
[data-dynamic-post-detail],
|
|
68
|
+
[data-dynamic-project-detail],
|
|
69
|
+
[data-dynamic-product-detail],
|
|
70
|
+
[data-detail-view])::before {
|
|
71
|
+
display: none;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/* ══ Return link ══
|
|
76
|
+
The ledger's first line: mono, uppercase, tracked out. */
|
|
77
|
+
a.back-link {
|
|
78
|
+
display: inline-flex;
|
|
79
|
+
align-items: center;
|
|
80
|
+
gap: var(--space-xs);
|
|
81
|
+
padding: 0.35rem 0.85rem;
|
|
82
|
+
background: var(--color-surface-card);
|
|
83
|
+
border: 1.5px solid var(--border-ink);
|
|
84
|
+
border-radius: var(--radius-card);
|
|
85
|
+
font-family: var(--font-mono);
|
|
86
|
+
font-size: var(--type-label-lg);
|
|
87
|
+
line-height: 1.4;
|
|
88
|
+
text-transform: uppercase;
|
|
89
|
+
letter-spacing: 0.12em;
|
|
90
|
+
color: var(--color-on-surface-variant);
|
|
91
|
+
text-decoration: none !important;
|
|
92
|
+
transition: color var(--motion-duration-fast) var(--motion-ease-default),
|
|
93
|
+
border-color var(--motion-duration-fast) var(--motion-ease-default),
|
|
94
|
+
background-color var(--motion-duration-fast) var(--motion-ease-default);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
a.back-link:hover {
|
|
98
|
+
color: var(--color-primary);
|
|
99
|
+
border-color: var(--color-primary);
|
|
100
|
+
background: var(--color-surface-high);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
a.back-link .material-symbols-outlined {
|
|
104
|
+
font-size: var(--type-body);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/* ══ Meta action row ══
|
|
108
|
+
Share · Cite · PDF as pill buttons with Google icons. */
|
|
109
|
+
.detail-actions {
|
|
110
|
+
display: flex;
|
|
111
|
+
flex-wrap: wrap;
|
|
112
|
+
gap: var(--space-xs) var(--space-sm);
|
|
113
|
+
margin-top: var(--space-sm);
|
|
114
|
+
padding-top: var(--space-sm);
|
|
115
|
+
border-top: 1px solid var(--border-gentle-faint);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.detail-action {
|
|
119
|
+
display: inline-flex;
|
|
120
|
+
align-items: center;
|
|
121
|
+
gap: 0.35rem;
|
|
122
|
+
padding: 0.35rem 0.85rem;
|
|
123
|
+
background: var(--color-surface-card);
|
|
124
|
+
border: 1px solid var(--border-ink);
|
|
125
|
+
border-radius: var(--radius-pill);
|
|
126
|
+
font-family: var(--font-label);
|
|
127
|
+
font-size: var(--type-label-lg);
|
|
128
|
+
font-weight: var(--weight-label);
|
|
129
|
+
letter-spacing: 0.04em;
|
|
130
|
+
color: var(--color-on-surface);
|
|
131
|
+
text-decoration: none !important;
|
|
132
|
+
cursor: pointer;
|
|
133
|
+
transition: background-color var(--motion-duration-fast) var(--motion-ease-default),
|
|
134
|
+
border-color var(--motion-duration-fast) var(--motion-ease-default),
|
|
135
|
+
color var(--motion-duration-fast) var(--motion-ease-default);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.detail-action:hover {
|
|
139
|
+
background: var(--color-surface-high);
|
|
140
|
+
border-color: var(--color-primary);
|
|
141
|
+
color: var(--color-primary);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.detail-action .material-symbols-outlined {
|
|
145
|
+
font-size: 1rem;
|
|
146
|
+
line-height: 1;
|
|
147
|
+
color: var(--color-primary);
|
|
148
|
+
transition: color var(--motion-duration-fast) var(--motion-ease-default);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.detail-action:hover .material-symbols-outlined {
|
|
152
|
+
color: var(--color-primary);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/* Reading-size step. Compact pill beside Share and Cite; opens a −4…+4 menu. */
|
|
156
|
+
.detail-type-size {
|
|
157
|
+
position: relative;
|
|
158
|
+
display: inline-flex;
|
|
159
|
+
align-items: center;
|
|
160
|
+
color: var(--color-on-surface);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.detail-type-size-trigger {
|
|
164
|
+
appearance: none;
|
|
165
|
+
display: inline-flex;
|
|
166
|
+
align-items: center;
|
|
167
|
+
gap: 0.2rem;
|
|
168
|
+
padding: 0.35rem 0.55rem 0.35rem 0.7rem;
|
|
169
|
+
background: var(--color-surface-card);
|
|
170
|
+
border: 1px solid var(--border-ink);
|
|
171
|
+
border-radius: var(--radius-pill);
|
|
172
|
+
font-family: var(--font-label);
|
|
173
|
+
font-size: var(--type-label-lg);
|
|
174
|
+
font-weight: var(--weight-label);
|
|
175
|
+
letter-spacing: 0.04em;
|
|
176
|
+
line-height: 1;
|
|
177
|
+
color: var(--color-on-surface);
|
|
178
|
+
cursor: pointer;
|
|
179
|
+
transition: background-color var(--motion-duration-fast) var(--motion-ease-default),
|
|
180
|
+
border-color var(--motion-duration-fast) var(--motion-ease-default),
|
|
181
|
+
color var(--motion-duration-fast) var(--motion-ease-default);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.detail-type-size-trigger:hover,
|
|
185
|
+
.detail-type-size-trigger[aria-expanded="true"] {
|
|
186
|
+
background: var(--color-surface-high);
|
|
187
|
+
border-color: var(--color-primary);
|
|
188
|
+
color: var(--color-primary);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.detail-type-size-trigger:focus-visible {
|
|
192
|
+
outline: 1px solid var(--color-primary);
|
|
193
|
+
outline-offset: 1px;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.detail-type-size-trigger .material-symbols-outlined {
|
|
197
|
+
font-size: 1rem;
|
|
198
|
+
line-height: 1;
|
|
199
|
+
color: var(--color-primary);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.detail-type-size-value {
|
|
203
|
+
min-width: 1.6em;
|
|
204
|
+
text-align: center;
|
|
205
|
+
font-variant-numeric: tabular-nums;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
.detail-type-size-caret {
|
|
209
|
+
font-size: 1rem;
|
|
210
|
+
line-height: 1;
|
|
211
|
+
transition: transform var(--motion-duration-fast) var(--motion-ease-default);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.detail-type-size-trigger[aria-expanded="true"] .detail-type-size-caret {
|
|
215
|
+
transform: rotate(180deg);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.detail-type-size:has(.detail-type-size-trigger[aria-expanded="true"]) {
|
|
219
|
+
z-index: 30;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.detail-type-size-menu {
|
|
223
|
+
position: absolute;
|
|
224
|
+
top: calc(100% + 0.35rem);
|
|
225
|
+
left: 0;
|
|
226
|
+
z-index: 20;
|
|
227
|
+
display: flex;
|
|
228
|
+
flex-direction: column;
|
|
229
|
+
gap: 0.1rem;
|
|
230
|
+
min-width: 100%;
|
|
231
|
+
max-height: min(14.5rem, 70vh);
|
|
232
|
+
overflow-y: auto;
|
|
233
|
+
overscroll-behavior: contain;
|
|
234
|
+
padding: 0.35rem;
|
|
235
|
+
background: var(--color-surface-card);
|
|
236
|
+
border: 1px solid var(--border-ink);
|
|
237
|
+
border-radius: var(--radius-card);
|
|
238
|
+
box-shadow: 0 0.45rem 1.1rem color-mix(in srgb, var(--color-on-surface) 12%, transparent);
|
|
239
|
+
scrollbar-width: thin;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/* On the stacked mobile dossier the actions sit near the plate floor, so the
|
|
243
|
+
menu opens upward into the panel instead of vanishing under the next block. */
|
|
244
|
+
@media (max-width: 767px) {
|
|
245
|
+
.detail-type-size-menu {
|
|
246
|
+
top: auto;
|
|
247
|
+
bottom: calc(100% + 0.35rem);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.detail-type-size-menu[hidden] {
|
|
252
|
+
display: none;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
.detail-type-size-step {
|
|
256
|
+
appearance: none;
|
|
257
|
+
display: flex;
|
|
258
|
+
align-items: center;
|
|
259
|
+
justify-content: space-between;
|
|
260
|
+
gap: 0.75rem;
|
|
261
|
+
width: 100%;
|
|
262
|
+
border: 0;
|
|
263
|
+
background: transparent;
|
|
264
|
+
border-radius: var(--radius-pill);
|
|
265
|
+
padding: 0.35rem 0.55rem;
|
|
266
|
+
font-family: var(--font-label);
|
|
267
|
+
font-size: var(--type-label);
|
|
268
|
+
font-weight: var(--weight-label);
|
|
269
|
+
letter-spacing: 0.02em;
|
|
270
|
+
line-height: 1;
|
|
271
|
+
color: var(--color-on-surface);
|
|
272
|
+
cursor: pointer;
|
|
273
|
+
font-variant-numeric: tabular-nums;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
.detail-type-size-step::after {
|
|
277
|
+
content: "";
|
|
278
|
+
width: 0.35rem;
|
|
279
|
+
height: 0.35rem;
|
|
280
|
+
border-radius: 999px;
|
|
281
|
+
background: var(--border-ink);
|
|
282
|
+
opacity: 0.55;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
.detail-type-size-step[aria-selected="true"] {
|
|
286
|
+
background: var(--color-surface-high);
|
|
287
|
+
color: var(--color-primary);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
.detail-type-size-step[aria-selected="true"]::after {
|
|
291
|
+
background: var(--color-primary);
|
|
292
|
+
opacity: 1;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
.detail-type-size-step:hover,
|
|
296
|
+
.detail-type-size-step:focus-visible {
|
|
297
|
+
color: var(--color-primary);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
.detail-type-size-step:focus-visible {
|
|
301
|
+
outline: 1px solid var(--color-primary);
|
|
302
|
+
outline-offset: 1px;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/* ══ Detail column grid ══
|
|
306
|
+
Two tracks, dossier then body. This used to be Tailwind's twelve-column
|
|
307
|
+
grid with the dossier on `md:col-span-3`, which left the panel around 15rem
|
|
308
|
+
on a laptop: narrow enough that a fourteen-letter word in a title broke
|
|
309
|
+
mid-word rather than wrapping. The dossier now takes a quarter more width.
|
|
310
|
+
|
|
311
|
+
Three of twelve columns plus the two gaps between them is `25% - 0.75gap`,
|
|
312
|
+
so a quarter more is `31.25% - 0.9375gap`. The body track keeps whatever is
|
|
313
|
+
left, and since the reading column inside it is capped at
|
|
314
|
+
`--reading-measure` and sets flush left, the widening moves the prose right
|
|
315
|
+
by exactly what the dossier gained instead of narrowing it.
|
|
316
|
+
|
|
317
|
+
The gap values mirror the `gap-8 lg:gap-12` utilities the markup still
|
|
318
|
+
carries; the track formula needs the number, and Tailwind's own gap cannot
|
|
319
|
+
be read back out of the cascade. Change one and change the other. The
|
|
320
|
+
selector compounds `.grid` for the reason given at the top of this file:
|
|
321
|
+
the Play CDN injects `grid-cols-1` after this sheet, so a single class
|
|
322
|
+
loses the tie and the page stays stacked.
|
|
323
|
+
|
|
324
|
+
Every detail page uses this one rule, including the projects page, which
|
|
325
|
+
only differs in holding the split back to 1024px (ledger/projects.css). */
|
|
326
|
+
@media (min-width: 768px) {
|
|
327
|
+
.grid.text-detail-grid {
|
|
328
|
+
--detail-column-gap: 2rem;
|
|
329
|
+
|
|
330
|
+
grid-template-columns:
|
|
331
|
+
calc(31.25% - 0.9375 * var(--detail-column-gap)) minmax(0, 1fr);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
@media (min-width: 1024px) {
|
|
336
|
+
.grid.text-detail-grid {
|
|
337
|
+
--detail-column-gap: 3rem;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/* ══ Dossier ══
|
|
342
|
+
Title, description, classification and dates read as one panel. The runtime
|
|
343
|
+
emits the heading block and the meta block as siblings with no wrapper, so
|
|
344
|
+
the panel is made by giving both the same surface and closing the gap
|
|
345
|
+
between them rather than by boxing them. */
|
|
346
|
+
|
|
347
|
+
/* The column already asks to be sticky (`md:sticky md:top-32`), but the grid
|
|
348
|
+
sets `items-start`, which shrinks the <aside> to its own content and leaves
|
|
349
|
+
the sticky child no distance to travel — so the dossier scrolled away with
|
|
350
|
+
the first screen. Stretching the column to the row restores it. */
|
|
351
|
+
aside:has(> .text-detail-sidebar) {
|
|
352
|
+
align-self: stretch;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/* The markup pins the column with Tailwind's `md:top-32`, which is 8rem. The
|
|
356
|
+
CV register rail and the rascunhos marginalia column both park at 7rem below
|
|
357
|
+
the 78px sticky nav; one sticky offset for the site. The child combinator
|
|
358
|
+
supplies the extra specificity the utility would otherwise win on. */
|
|
359
|
+
.text-detail-sidebar {
|
|
360
|
+
background: var(--color-panel-contrast);
|
|
361
|
+
border: 1.5px solid var(--border-ink);
|
|
362
|
+
border-radius: var(--radius-card);
|
|
363
|
+
overflow: hidden;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/* Reading-size menu is absolute and must escape the plate; the heading
|
|
367
|
+
already clips its own shard, so opening the menu can drop the plate clip. */
|
|
368
|
+
.text-detail-sidebar:has(.detail-type-size-trigger[aria-expanded="true"]) {
|
|
369
|
+
overflow: visible;
|
|
370
|
+
position: relative;
|
|
371
|
+
z-index: 4;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
@media (min-width: 768px) {
|
|
375
|
+
|
|
376
|
+
/* Default park under the nav. After mount, syncDetailSidebarSticky()
|
|
377
|
+
rewrites top from the dossier's own height so a tall plate (Related Texts)
|
|
378
|
+
scrolls with the page until its bottom meets the viewport, then sticks. */
|
|
379
|
+
aside>.text-detail-sidebar {
|
|
380
|
+
top: 7rem;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/* Article / rascunho dossier uses the site type scale as-is — no local remaps. */
|
|
385
|
+
|
|
386
|
+
.text-detail-sidebar .article-sidebar-heading {
|
|
387
|
+
position: relative;
|
|
388
|
+
overflow: hidden;
|
|
389
|
+
margin-bottom: 0;
|
|
390
|
+
padding: var(--space-lg);
|
|
391
|
+
background: var(--color-panel-contrast);
|
|
392
|
+
border-bottom: 0;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/* Canonical shard, bottom-right, as in the mockup. Decoration only: it is
|
|
396
|
+
suppressed below the tablet breakpoint like every other shard. */
|
|
397
|
+
.text-detail-sidebar .article-sidebar-heading::after {
|
|
398
|
+
content: "";
|
|
399
|
+
position: absolute;
|
|
400
|
+
right: -1.75rem;
|
|
401
|
+
bottom: -1.75rem;
|
|
402
|
+
width: 5rem;
|
|
403
|
+
height: 5rem;
|
|
404
|
+
clip-path: var(--shard-alpha);
|
|
405
|
+
background: var(--color-secondary);
|
|
406
|
+
opacity: var(--cubist-shard-opacity);
|
|
407
|
+
pointer-events: none;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
@media (max-width: 639px) {
|
|
411
|
+
.text-detail-sidebar .article-sidebar-heading::after {
|
|
412
|
+
display: none;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
.text-detail-sidebar .article-sidebar-heading>* {
|
|
417
|
+
position: relative;
|
|
418
|
+
z-index: 1;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/* The detail title is the page h1 and stays in the left column, but it sits
|
|
422
|
+
inside a ~18rem panel now, so it comes down one step from the full
|
|
423
|
+
.text-title scale. */
|
|
424
|
+
.text-detail-sidebar .text-title {
|
|
425
|
+
/* Moves with the h2 above it. At 1.7rem against the new 1.87rem h2 the page
|
|
426
|
+
h1 would have been the smaller of the two — at the old 1.6em h2 the pair
|
|
427
|
+
were already dead level between 768px and 1024px. */
|
|
428
|
+
font-size: var(--type-title);
|
|
429
|
+
font-weight: var(--weight-title);
|
|
430
|
+
font-synthesis: none;
|
|
431
|
+
line-height: 1.15;
|
|
432
|
+
margin: 0;
|
|
433
|
+
text-wrap: balance;
|
|
434
|
+
/* A word longer than the panel breaks at a syllable with a real hyphen
|
|
435
|
+
rather than mid-letter: "Hiperespaçolândia" is seventeen characters and
|
|
436
|
+
still overruns the widened dossier, and it used to read as
|
|
437
|
+
"Hiperespaçolândi / a". The dictionary follows the document language the
|
|
438
|
+
shell sets (pt-BR on the rascunhos shell, en on the others), and a title
|
|
439
|
+
whose words already fit is left alone. `overflow-wrap` stays as the last
|
|
440
|
+
resort for a string no dictionary can break, such as a bare URL. */
|
|
441
|
+
hyphens: auto;
|
|
442
|
+
overflow-wrap: break-word;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
@media (min-width: 1024px) {
|
|
446
|
+
.text-detail-sidebar .text-title {
|
|
447
|
+
font-size: var(--type-title-lg);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
.text-detail-sidebar .article-sidebar-heading .material-symbols-outlined {
|
|
452
|
+
color: var(--color-secondary);
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
/* Lead thesis. `description` is the article's own one-sentence claim — body
|
|
456
|
+
face and body size, in legend ink so it sits under the H1 without matching
|
|
457
|
+
the reading column. */
|
|
458
|
+
.text-detail-sidebar .article-sidebar-description {
|
|
459
|
+
font-family: var(--font-body);
|
|
460
|
+
font-style: normal;
|
|
461
|
+
font-size: var(--type-body);
|
|
462
|
+
font-weight: var(--weight-body);
|
|
463
|
+
line-height: var(--leading-body);
|
|
464
|
+
color: var(--color-legend);
|
|
465
|
+
margin: var(--space-md) 0 0;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
.text-detail-sidebar .article-sidebar-thumbnail {
|
|
469
|
+
margin-top: var(--space-md);
|
|
470
|
+
width: 100%;
|
|
471
|
+
max-width: none;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
/* ── Dossier ledger rows ── */
|
|
475
|
+
.text-detail-sidebar .article-meta {
|
|
476
|
+
margin-bottom: 0;
|
|
477
|
+
padding: 0 var(--space-lg) var(--space-lg);
|
|
478
|
+
background: var(--color-panel-contrast);
|
|
479
|
+
color: var(--color-on-surface-variant);
|
|
480
|
+
font-family: var(--font-mono);
|
|
481
|
+
font-size: var(--type-meta);
|
|
482
|
+
letter-spacing: 0.04em;
|
|
483
|
+
text-transform: none;
|
|
484
|
+
gap: var(--space-md);
|
|
485
|
+
font-variant-numeric: tabular-nums;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
/* Projects and products can carry no meta at all, and on articles and posts
|
|
489
|
+
the byline below is the block's only child. Either way an all-empty meta
|
|
490
|
+
block must not hang a stub of padding off the bottom of the panel. */
|
|
491
|
+
.text-detail-sidebar .article-meta:has(> div:empty),
|
|
492
|
+
.text-detail-sidebar .article-meta:has(> div > span.text-secondary:not(.font-bold):only-child) {
|
|
493
|
+
display: none;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
.text-detail-sidebar .article-meta>div {
|
|
497
|
+
gap: var(--space-sm);
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/* Author byline. Dropped: single-author site. The runtime still emits it, so
|
|
501
|
+
it is suppressed here until `buildTextSidebar` stops rendering it — see the
|
|
502
|
+
runtime-change note in this branch's commit message. The product/company
|
|
503
|
+
line is the same colour but carries `font-bold`, hence the :not(). */
|
|
504
|
+
.text-detail-sidebar .article-meta>div>span.text-secondary:not(.font-bold) {
|
|
505
|
+
display: none;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
.text-detail-sidebar .article-meta .text-tertiary,
|
|
509
|
+
.text-detail-sidebar .article-meta span.font-bold {
|
|
510
|
+
font-family: var(--font-label);
|
|
511
|
+
font-size: var(--type-label-lg);
|
|
512
|
+
letter-spacing: 0.04em;
|
|
513
|
+
color: var(--color-tertiary);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
/* Dates. The runtime already localises "Published" / "Updated" into each
|
|
517
|
+
span's title attribute, so the label can be lifted from the markup instead
|
|
518
|
+
of being invented in CSS — and it stays in the reader's language. */
|
|
519
|
+
.text-detail-sidebar .article-meta .date-evolution {
|
|
520
|
+
gap: var(--space-xs);
|
|
521
|
+
width: 100%;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
.text-detail-sidebar .article-meta .date-evolution>span {
|
|
525
|
+
display: flex;
|
|
526
|
+
align-items: baseline;
|
|
527
|
+
justify-content: space-between;
|
|
528
|
+
gap: var(--space-sm);
|
|
529
|
+
opacity: 1;
|
|
530
|
+
color: var(--color-on-surface);
|
|
531
|
+
white-space: nowrap;
|
|
532
|
+
border-top: 1px solid var(--border-gentle-faint);
|
|
533
|
+
padding-top: var(--space-sm);
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
.text-detail-sidebar .article-meta .date-evolution>span[title]::before {
|
|
537
|
+
content: attr(title);
|
|
538
|
+
color: var(--color-outline);
|
|
539
|
+
text-transform: uppercase;
|
|
540
|
+
letter-spacing: 0.1em;
|
|
541
|
+
font-size: var(--type-label);
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
/* Classification chips and the language pill, once the dossier carries them. */
|
|
545
|
+
.text-detail-sidebar .article-meta .ledger-chip-row {
|
|
546
|
+
margin-bottom: var(--space-sm);
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
|
|
550
|
+
/* ══ Table of contents ══
|
|
551
|
+
Restyled from `55-toc.html`, which builds it from the body's own h2/h3. The
|
|
552
|
+
numbering is part of that same structural derivation, not a field. */
|
|
553
|
+
.article-toc--sidebar {
|
|
554
|
+
margin-top: var(--space-sm);
|
|
555
|
+
padding: var(--space-md);
|
|
556
|
+
border: 1.5px solid var(--border-ink);
|
|
557
|
+
border-radius: var(--radius-card);
|
|
558
|
+
background: var(--color-surface-container-low);
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
.article-toc-title,
|
|
562
|
+
.article-toc-summary {
|
|
563
|
+
font-family: var(--font-label);
|
|
564
|
+
font-size: var(--type-label-lg);
|
|
565
|
+
letter-spacing: 0.08em;
|
|
566
|
+
text-transform: uppercase;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
.article-toc-title {
|
|
570
|
+
color: var(--color-on-surface);
|
|
571
|
+
font-weight: 600;
|
|
572
|
+
margin-bottom: var(--space-md);
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
.article-toc--sidebar .article-toc-list,
|
|
576
|
+
.article-toc-panel .article-toc-list {
|
|
577
|
+
padding-left: 0;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
.article-toc-item+.article-toc-item {
|
|
581
|
+
margin-top: 0.35rem;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
.article-toc-link {
|
|
585
|
+
display: flex;
|
|
586
|
+
align-items: baseline;
|
|
587
|
+
gap: var(--space-sm);
|
|
588
|
+
padding: 0.25rem 0;
|
|
589
|
+
font-family: var(--font-body);
|
|
590
|
+
font-size: var(--type-body);
|
|
591
|
+
line-height: 1.45;
|
|
592
|
+
letter-spacing: normal;
|
|
593
|
+
text-transform: none;
|
|
594
|
+
color: var(--color-on-surface-variant);
|
|
595
|
+
transition: color var(--motion-duration-fast) var(--motion-ease-default);
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
.article-toc-link:hover {
|
|
599
|
+
color: var(--color-primary);
|
|
600
|
+
text-decoration: none;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
.article-toc-num {
|
|
604
|
+
flex: 0 0 auto;
|
|
605
|
+
min-width: 1.75rem;
|
|
606
|
+
font-family: var(--font-mono);
|
|
607
|
+
font-size: 0.9em;
|
|
608
|
+
letter-spacing: 0.04em;
|
|
609
|
+
color: var(--color-outline);
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
.article-toc-item.is-active>.article-toc-link,
|
|
613
|
+
.article-toc-item.is-active .article-toc-num {
|
|
614
|
+
color: var(--color-primary);
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
.article-toc-item.is-active>.article-toc-link {
|
|
618
|
+
text-decoration: underline;
|
|
619
|
+
text-decoration-thickness: 2px;
|
|
620
|
+
text-underline-offset: 0.22em;
|
|
621
|
+
text-decoration-color: color-mix(in srgb, var(--color-primary) 55%, transparent);
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
.article-toc-item--h3>.article-toc-link {
|
|
625
|
+
padding-left: 1.75rem;
|
|
626
|
+
font-size: var(--type-subtitle);
|
|
627
|
+
color: var(--color-outline);
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
.article-toc-item--h3>.article-toc-link:hover {
|
|
631
|
+
color: var(--color-primary);
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
/* Mobile disclosure: the same panel, folded. */
|
|
635
|
+
.article-toc--disclosure {
|
|
636
|
+
margin-bottom: var(--space-xl);
|
|
637
|
+
border: 0;
|
|
638
|
+
background: var(--color-surface-container-low);
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
.article-toc-summary {
|
|
642
|
+
padding: var(--space-sm) var(--space-md);
|
|
643
|
+
font-weight: 400;
|
|
644
|
+
color: var(--color-on-surface-variant);
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
.article-toc-panel {
|
|
648
|
+
padding: 0 var(--space-md) var(--space-md);
|
|
649
|
+
border-top: 1px solid var(--border-gentle-faint);
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
/* ══ Prose column ══
|
|
653
|
+
The page's reason to exist. Measure is already var(--reading-measure);
|
|
654
|
+
what changes here is the vertical rhythm and the heading voice. */
|
|
655
|
+
.article-content {
|
|
656
|
+
/* Body face; slightly larger than UI body. */
|
|
657
|
+
font-family: var(--font-body);
|
|
658
|
+
font-size: var(--type-prose);
|
|
659
|
+
font-weight: var(--weight-body);
|
|
660
|
+
line-height: var(--leading-prose);
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
/* Opening initial. Front matter `drop_cap: true` adds `.has-drop-cap` when the
|
|
664
|
+
body does not open with a heading. The letter spans `--drop-cap-lines`
|
|
665
|
+
(site config, default 2) in the reading face. `initial-letter` sinks it
|
|
666
|
+
inside the paragraph; the float is only for engines that still lack that
|
|
667
|
+
property. */
|
|
668
|
+
.article-content.has-drop-cap > p:first-of-type::first-letter {
|
|
669
|
+
font-family: var(--font-body);
|
|
670
|
+
font-weight: var(--weight-body);
|
|
671
|
+
font-style: normal;
|
|
672
|
+
color: var(--color-on-surface);
|
|
673
|
+
initial-letter: var(--drop-cap-lines);
|
|
674
|
+
margin-right: 0.2em;
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
@supports not (initial-letter: 3) {
|
|
678
|
+
.article-content.has-drop-cap > p:first-of-type::first-letter {
|
|
679
|
+
float: left;
|
|
680
|
+
font-size: calc(var(--drop-cap-lines) * var(--leading-prose) / 0.66 * 1em);
|
|
681
|
+
line-height: 0.75;
|
|
682
|
+
margin: 0.04em 0.2em 0 0;
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
/* The display serif for section heads, the same face as the title, with a
|
|
687
|
+
hairline above so a long article reads as a sequence of plates rather than a
|
|
688
|
+
scroll. The body face at semibold — what this replaces — belonged to no type
|
|
689
|
+
role.
|
|
690
|
+
|
|
691
|
+
Raised from 1.6em: at that size a section head opening a plate sat too close
|
|
692
|
+
to the paragraph under it to stop the eye on its own, and the hairline was
|
|
693
|
+
doing most of the work. h3 and the sidebar h1 move with it below. */
|
|
694
|
+
.article-content h2 {
|
|
695
|
+
font-family: var(--font-content-title);
|
|
696
|
+
font-size: var(--type-title);
|
|
697
|
+
font-weight: var(--weight-title);
|
|
698
|
+
font-synthesis: none;
|
|
699
|
+
line-height: 1.25;
|
|
700
|
+
color: var(--color-on-surface);
|
|
701
|
+
margin-top: var(--space-2xl);
|
|
702
|
+
margin-bottom: var(--space-md);
|
|
703
|
+
padding-top: var(--space-lg);
|
|
704
|
+
border-top: 1px solid var(--border-gentle-divider);
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
.article-content> :first-child {
|
|
708
|
+
margin-top: 0;
|
|
709
|
+
padding-top: 0;
|
|
710
|
+
border-top: 0;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
.article-content> :last-child {
|
|
714
|
+
margin-bottom: 0;
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
/* Sub-heads are titles, so they take the display face a step below h2 rather
|
|
718
|
+
than the small-caps label voice. Small caps belong to tags and chrome; run
|
|
719
|
+
over a sentence-shaped heading they shout. */
|
|
720
|
+
.article-content h3 {
|
|
721
|
+
font-family: var(--font-content-title);
|
|
722
|
+
/* Holds a step below h2. */
|
|
723
|
+
font-size: var(--type-card-lg);
|
|
724
|
+
font-weight: var(--weight-title);
|
|
725
|
+
font-synthesis: none;
|
|
726
|
+
letter-spacing: normal;
|
|
727
|
+
text-transform: none;
|
|
728
|
+
line-height: 1.3;
|
|
729
|
+
color: var(--color-on-surface);
|
|
730
|
+
margin-top: var(--space-xl);
|
|
731
|
+
margin-bottom: var(--space-sm);
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
.article-content h4 {
|
|
735
|
+
font-family: var(--font-body);
|
|
736
|
+
font-size: var(--type-body);
|
|
737
|
+
font-weight: var(--weight-title);
|
|
738
|
+
font-synthesis: none;
|
|
739
|
+
color: var(--color-on-surface);
|
|
740
|
+
margin-top: var(--space-lg);
|
|
741
|
+
margin-bottom: var(--space-xs);
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
.article-content p {
|
|
745
|
+
margin-bottom: 1.15em;
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
/* Architectural rectilinearity: the prose furniture still had soft corners. */
|
|
749
|
+
.article-content code,
|
|
750
|
+
.article-content pre,
|
|
751
|
+
.article-content blockquote,
|
|
752
|
+
.article-content .article-note {
|
|
753
|
+
border-radius: 0;
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
.article-content code {
|
|
757
|
+
background: var(--color-surface-container);
|
|
758
|
+
color: var(--color-on-surface);
|
|
759
|
+
padding: 0.05em 0.35em;
|
|
760
|
+
font-size: var(--type-meta);
|
|
761
|
+
font-family: var(--font-code);
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
/* `--color-surface-container-lowest` is the mockup's well, but it resolves to
|
|
765
|
+
the page white in the light palette, so the deepest surface that reads in
|
|
766
|
+
both is the container step. */
|
|
767
|
+
.article-content pre {
|
|
768
|
+
background: var(--color-surface-container);
|
|
769
|
+
border-left: 2px solid var(--color-outline-variant);
|
|
770
|
+
padding: var(--space-md);
|
|
771
|
+
margin: var(--space-lg) 0;
|
|
772
|
+
font-size: var(--type-meta);
|
|
773
|
+
line-height: 1.6;
|
|
774
|
+
font-family: var(--font-code);
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
.article-content pre code {
|
|
778
|
+
color: var(--color-on-surface);
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
/* Pull quotes are running text and are read, not glanced at, so they keep the
|
|
782
|
+
body face at prose size. The tonal band and the rule mark the quote. */
|
|
783
|
+
.article-content blockquote {
|
|
784
|
+
background: var(--color-surface-container-low);
|
|
785
|
+
/* Borders Detail dialect: accent spine (secondary / forest), square plate. */
|
|
786
|
+
border: 1.5px solid var(--border-ink);
|
|
787
|
+
border-left: 3px solid var(--color-secondary);
|
|
788
|
+
border-radius: var(--radius-card);
|
|
789
|
+
padding: var(--space-md) var(--space-lg);
|
|
790
|
+
margin: var(--space-xl) 0;
|
|
791
|
+
font-family: var(--font-body);
|
|
792
|
+
font-style: normal;
|
|
793
|
+
font-size: var(--type-prose);
|
|
794
|
+
font-weight: var(--weight-body);
|
|
795
|
+
line-height: var(--leading-prose);
|
|
796
|
+
color: var(--color-on-surface);
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
/* A poem is set verse by verse at prose size — same as notes and body copy. */
|
|
800
|
+
.article-content blockquote .poem,
|
|
801
|
+
.article-content .poem {
|
|
802
|
+
font-family: var(--font-body);
|
|
803
|
+
font-style: normal;
|
|
804
|
+
font-size: var(--type-prose);
|
|
805
|
+
font-weight: var(--weight-body);
|
|
806
|
+
line-height: var(--leading-prose);
|
|
807
|
+
color: var(--color-on-surface);
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
.article-content .poem p {
|
|
811
|
+
font-size: inherit;
|
|
812
|
+
font-weight: inherit;
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
/* ── Theorem / proof / key-takeaways callout ──
|
|
816
|
+
Authored per article as `<div class="article-note" markdown="1">`; styled
|
|
817
|
+
here, never injected. Ochre wash + tertiary spine = scannable field note. */
|
|
818
|
+
.article-content .article-note {
|
|
819
|
+
position: relative;
|
|
820
|
+
background: color-mix(in srgb, var(--color-tertiary) 10%, var(--color-panel-contrast));
|
|
821
|
+
border: 1px solid color-mix(in srgb, var(--color-tertiary) 22%, var(--border-gentle-subtle));
|
|
822
|
+
padding: var(--space-lg) var(--space-lg) var(--space-lg) calc(var(--space-lg) + 3px);
|
|
823
|
+
margin: var(--space-xl) 0;
|
|
824
|
+
font-size: var(--type-subtitle);
|
|
825
|
+
font-weight: var(--weight-body);
|
|
826
|
+
line-height: var(--leading-prose);
|
|
827
|
+
color: var(--color-on-surface);
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
[data-theme="dark"] .article-content .article-note {
|
|
831
|
+
background: color-mix(in srgb, var(--color-tertiary) 6%, var(--color-panel-contrast));
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
.article-content .article-note::before {
|
|
835
|
+
content: "";
|
|
836
|
+
position: absolute;
|
|
837
|
+
inset: 0 auto 0 0;
|
|
838
|
+
width: 3px;
|
|
839
|
+
background: var(--color-tertiary);
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
.article-content .article-note strong {
|
|
843
|
+
color: var(--color-on-surface);
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
/* A formula band inside a callout, as in the mockup's axiomatic block. */
|
|
847
|
+
.article-content .article-note .math-display,
|
|
848
|
+
.article-content .article-note mjx-container[display="true"] {
|
|
849
|
+
background: var(--color-surface-dim);
|
|
850
|
+
padding: var(--space-sm) var(--space-md);
|
|
851
|
+
margin: var(--space-md) 0;
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
/* ── Benchmark and data tables ──
|
|
855
|
+
Authored as GFM; the ledger treatment is rules between rows, a label-voice
|
|
856
|
+
header, and figures that line up. */
|
|
857
|
+
/* No table surface: the header band and the hover row are the only fills, so
|
|
858
|
+
both read against the page canvas in either palette. */
|
|
859
|
+
.article-content table,
|
|
860
|
+
.article-content .table-csv {
|
|
861
|
+
margin: var(--space-xl) 0;
|
|
862
|
+
font-size: var(--type-dek);
|
|
863
|
+
font-variant-numeric: tabular-nums;
|
|
864
|
+
background: transparent;
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
.article-content th,
|
|
868
|
+
.article-content td,
|
|
869
|
+
.article-content .table-csv th,
|
|
870
|
+
.article-content .table-csv td {
|
|
871
|
+
border: 0;
|
|
872
|
+
border-bottom: 1px solid var(--border-gentle-subtle);
|
|
873
|
+
padding: var(--space-sm) var(--space-md);
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
/* GFM column alignment. Markdown's `|--:|` becomes align="right" on the cell,
|
|
877
|
+
which is a presentational hint and therefore loses to any author rule —
|
|
878
|
+
including the reset's `th { text-align: inherit }`. Numeric columns in a
|
|
879
|
+
results table are exactly where alignment carries meaning, so honour what
|
|
880
|
+
the author wrote. */
|
|
881
|
+
.article-content th[align="left"],
|
|
882
|
+
.article-content td[align="left"] {
|
|
883
|
+
text-align: left;
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
.article-content th[align="center"],
|
|
887
|
+
.article-content td[align="center"] {
|
|
888
|
+
text-align: center;
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
.article-content th[align="right"],
|
|
892
|
+
.article-content td[align="right"] {
|
|
893
|
+
text-align: right;
|
|
894
|
+
font-variant-numeric: tabular-nums;
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
.article-content thead th,
|
|
898
|
+
.article-content .table-csv thead th {
|
|
899
|
+
background: var(--color-surface-container);
|
|
900
|
+
font-family: var(--font-body);
|
|
901
|
+
font-size: var(--type-body);
|
|
902
|
+
font-weight: var(--weight-emphasis);
|
|
903
|
+
letter-spacing: normal;
|
|
904
|
+
color: var(--color-legend);
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
/* Zebra striping fights the row rules; the hover row is the reading aid. */
|
|
908
|
+
.article-content tbody tr:nth-child(even),
|
|
909
|
+
.article-content .table-csv tbody tr:nth-child(even) td {
|
|
910
|
+
background: transparent;
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
.article-content tbody tr:hover,
|
|
914
|
+
.article-content .table-csv tbody tr:hover {
|
|
915
|
+
background: var(--color-surface-container-low);
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
.article-content tbody tr:last-child td {
|
|
919
|
+
border-bottom: 0;
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
/* ── Notation on demand ── */
|
|
923
|
+
/* The Mermaid plate used to live here, at the container-low step. It has moved
|
|
924
|
+
to article.css and moved up one step, to the container step, because
|
|
925
|
+
container-low sits between the cluster fill (panel-contrast) and the node
|
|
926
|
+
fill (surface-card) that `mermaidConfig()` paints — so subgraph boxes and
|
|
927
|
+
nodes were dissolving into their own plate on this page. */
|
|
928
|
+
|
|
929
|
+
/* Display math takes its spacing from article.css, where the `.math-display`
|
|
930
|
+
wrapper carries a margin measured against the paragraph gap `.article-content
|
|
931
|
+
p` sets in this file. Do not override the margin here: the wrapper's padding
|
|
932
|
+
stays either way, so a larger margin only adds to a gap that is already the
|
|
933
|
+
one we want. */
|
|
934
|
+
|
|
935
|
+
/* A caption is a sentence about the figure — body face, description size
|
|
936
|
+
(body − 1pt), upright. Same treatment for image, video, YouTube, Plotly.
|
|
937
|
+
Softened toward variant so the legend reads as apparatus, not body. */
|
|
938
|
+
.article-content figcaption,
|
|
939
|
+
.article-content figure figcaption {
|
|
940
|
+
font-family: var(--font-body);
|
|
941
|
+
font-size: var(--type-subtitle);
|
|
942
|
+
font-style: normal;
|
|
943
|
+
font-weight: var(--weight-body);
|
|
944
|
+
line-height: 1.55;
|
|
945
|
+
letter-spacing: normal;
|
|
946
|
+
color: var(--color-legend);
|
|
947
|
+
margin-top: var(--space-sm);
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
.article-content hr {
|
|
951
|
+
margin: var(--space-2xl) 0;
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
/* ══ Marginalia: citations and the reference apparatus ══ */
|
|
955
|
+
.article-content .citation-sup {
|
|
956
|
+
font-family: var(--font-mono);
|
|
957
|
+
font-size: var(--type-meta);
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
.article-content .citation-sup a.citation {
|
|
961
|
+
color: var(--color-primary);
|
|
962
|
+
text-decoration: none;
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
.article-content .citation-sup a.citation:hover {
|
|
966
|
+
text-decoration: underline;
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
.article-content .article-references {
|
|
970
|
+
margin-top: var(--space-3xl);
|
|
971
|
+
padding-top: var(--space-lg);
|
|
972
|
+
border-top: 1px solid var(--border-gentle-divider);
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
/* The heading is an h2, so it would otherwise collect the section rule above
|
|
976
|
+
on top of the apparatus rule — two hairlines and a hole. Keep the ## face;
|
|
977
|
+
only drop the duplicated top rule. */
|
|
978
|
+
.article-content .article-references .section-title {
|
|
979
|
+
margin-top: 0;
|
|
980
|
+
padding-top: 0;
|
|
981
|
+
border-top: 0;
|
|
982
|
+
margin-bottom: var(--space-md);
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
.article-content .article-references .bibliography {
|
|
986
|
+
counter-reset: detail-ref;
|
|
987
|
+
list-style: none;
|
|
988
|
+
margin-left: 0;
|
|
989
|
+
padding-left: 0;
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
.article-content .article-references .bibliography>li {
|
|
993
|
+
counter-increment: detail-ref;
|
|
994
|
+
display: flex;
|
|
995
|
+
gap: var(--space-sm);
|
|
996
|
+
padding: 0.3rem var(--space-xs);
|
|
997
|
+
margin-bottom: 0;
|
|
998
|
+
font-family: var(--font-mono);
|
|
999
|
+
/* The floor of the apparatus, one step under the caption. It was 0.78rem,
|
|
1000
|
+
which in the notation face against a 1.1rem column was small enough that
|
|
1001
|
+
a reference read as a footnote to a footnote. */
|
|
1002
|
+
font-size: var(--type-meta);
|
|
1003
|
+
line-height: 1.55;
|
|
1004
|
+
color: var(--color-on-surface-variant);
|
|
1005
|
+
transition: background-color var(--motion-duration-fast) var(--motion-ease-default);
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
.article-content .article-references .bibliography>li:hover {
|
|
1009
|
+
background: var(--color-surface-container-low);
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
.article-content .article-references .bibliography>li::before {
|
|
1013
|
+
content: "[" counter(detail-ref) "]";
|
|
1014
|
+
flex: none;
|
|
1015
|
+
color: var(--color-primary);
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
/* ══ Prev / next ══
|
|
1019
|
+
Two panels, ordered by date upstream, replacing the bare text links. */
|
|
1020
|
+
nav.text-page-nav {
|
|
1021
|
+
display: grid;
|
|
1022
|
+
grid-template-columns: 1fr;
|
|
1023
|
+
gap: var(--space-md);
|
|
1024
|
+
align-items: stretch;
|
|
1025
|
+
margin-top: var(--space-xl);
|
|
1026
|
+
width: 100%;
|
|
1027
|
+
max-width: var(--reading-measure);
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
@media (min-width: 640px) {
|
|
1031
|
+
nav.text-page-nav {
|
|
1032
|
+
grid-template-columns: 1fr 1fr;
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
nav.text-page-nav>a {
|
|
1037
|
+
display: flex;
|
|
1038
|
+
align-items: center;
|
|
1039
|
+
gap: var(--space-xs);
|
|
1040
|
+
padding: var(--space-md);
|
|
1041
|
+
background: var(--color-background);
|
|
1042
|
+
border: 1.5px solid var(--border-ink);
|
|
1043
|
+
border-radius: var(--radius-card);
|
|
1044
|
+
color: var(--color-on-surface);
|
|
1045
|
+
font-family: var(--font-label);
|
|
1046
|
+
font-size: var(--type-meta);
|
|
1047
|
+
letter-spacing: 0.04em;
|
|
1048
|
+
text-decoration: none;
|
|
1049
|
+
transition: background-color var(--motion-duration-fast) var(--motion-ease-default),
|
|
1050
|
+
border-color var(--motion-duration-fast) var(--motion-ease-default),
|
|
1051
|
+
color var(--motion-duration-fast) var(--motion-ease-default);
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
nav.text-page-nav>a:hover {
|
|
1055
|
+
background: var(--color-surface-container-high);
|
|
1056
|
+
border-color: var(--color-primary);
|
|
1057
|
+
color: var(--color-primary);
|
|
1058
|
+
text-decoration: none;
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
nav.text-page-nav>a:last-child {
|
|
1062
|
+
justify-content: flex-end;
|
|
1063
|
+
text-align: right;
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
/* First and last entries emit an empty <span> on the missing side, which is
|
|
1067
|
+
fine — it just holds the column. A nav with no link at all, though, would be
|
|
1068
|
+
nothing but a rule and a gap. */
|
|
1069
|
+
nav.text-page-nav:not(:has(a)) {
|
|
1070
|
+
display: none;
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
/* ══ Cite this text block ══
|
|
1074
|
+
Dedicated block below controls, rendered using the standard code-block chrome. */
|
|
1075
|
+
.article-cite-block {
|
|
1076
|
+
margin-top: var(--space-xl);
|
|
1077
|
+
width: 100%;
|
|
1078
|
+
max-width: var(--reading-measure);
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
.article-cite-label {
|
|
1082
|
+
margin: 0 0 var(--space-xs);
|
|
1083
|
+
color: var(--color-on-surface-variant);
|
|
1084
|
+
font-family: var(--font-label);
|
|
1085
|
+
font-size: var(--type-meta);
|
|
1086
|
+
letter-spacing: 0.08em;
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
.article-cite-block .code-block {
|
|
1090
|
+
margin: 0;
|
|
1091
|
+
background: var(--color-background);
|
|
1092
|
+
border: 1.5px solid var(--border-ink);
|
|
1093
|
+
border-radius: var(--radius-card);
|
|
1094
|
+
overflow: hidden;
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
.article-cite-block .code-block pre {
|
|
1098
|
+
padding: var(--space-md);
|
|
1099
|
+
font-family: var(--font-technical);
|
|
1100
|
+
font-size: var(--type-meta);
|
|
1101
|
+
line-height: 1.55;
|
|
1102
|
+
color: var(--color-on-surface);
|
|
1103
|
+
white-space: pre;
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
/* ══ Column rhythm at the breakpoints ══ */
|
|
1107
|
+
@media (max-width: 767px) {
|
|
1108
|
+
|
|
1109
|
+
.text-page-main,
|
|
1110
|
+
.text-reading-column,
|
|
1111
|
+
.article-content {
|
|
1112
|
+
width: 100% !important;
|
|
1113
|
+
max-width: 100% !important;
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
.text-detail-sidebar .article-sidebar-heading,
|
|
1117
|
+
.text-detail-sidebar .article-meta {
|
|
1118
|
+
padding-left: var(--space-md);
|
|
1119
|
+
padding-right: var(--space-md);
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
.article-content h2 {
|
|
1123
|
+
font-size: var(--type-section-lg);
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
/* A four-column benchmark table wanted 468px inside a 355px column at 390px
|
|
1127
|
+
and pushed the whole document sideways — every page on the site got a
|
|
1128
|
+
horizontal scrollbar because of one article. The ledger cell padding is
|
|
1129
|
+
most of the excess (35px per cell), so it comes down first; what is still
|
|
1130
|
+
too wide then scrolls inside the table rather than moving the page. The
|
|
1131
|
+
runtime emits the table with no wrapper, so the table itself has to be the
|
|
1132
|
+
scroll container. */
|
|
1133
|
+
.article-content table,
|
|
1134
|
+
.article-content .table-csv {
|
|
1135
|
+
display: block;
|
|
1136
|
+
width: 100%;
|
|
1137
|
+
max-width: 100%;
|
|
1138
|
+
overflow-x: auto;
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
.article-content th,
|
|
1142
|
+
.article-content td,
|
|
1143
|
+
.article-content .table-csv th,
|
|
1144
|
+
.article-content .table-csv td {
|
|
1145
|
+
padding: var(--space-xs) var(--space-sm);
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
/* ══ Related Texts ══
|
|
1150
|
+
Neighbors from writing_index.json xcites. Section pills are neutral gray;
|
|
1151
|
+
card titles pick up the linked collection's triad colour on hover. */
|
|
1152
|
+
.article-related-box {
|
|
1153
|
+
margin-top: var(--space-xl);
|
|
1154
|
+
padding: 0 var(--space-md) var(--space-lg);
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
@media (max-width: 1023px) {
|
|
1158
|
+
.article-related-box {
|
|
1159
|
+
display: none;
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
.article-related-title {
|
|
1164
|
+
font-family: var(--font-label);
|
|
1165
|
+
font-size: var(--type-label-lg);
|
|
1166
|
+
letter-spacing: 0.08em;
|
|
1167
|
+
text-transform: uppercase;
|
|
1168
|
+
color: var(--color-on-surface);
|
|
1169
|
+
font-weight: 600;
|
|
1170
|
+
margin: 0 0 var(--space-md);
|
|
1171
|
+
padding: 0;
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
.article-related-section+.article-related-section {
|
|
1175
|
+
margin-top: var(--space-lg);
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
.article-related-section-pill {
|
|
1179
|
+
display: flex;
|
|
1180
|
+
align-items: center;
|
|
1181
|
+
justify-content: center;
|
|
1182
|
+
width: fit-content;
|
|
1183
|
+
margin: 0 0 var(--space-md);
|
|
1184
|
+
padding: 0.2rem 0.7rem;
|
|
1185
|
+
min-height: 1.65rem;
|
|
1186
|
+
border-radius: 0;
|
|
1187
|
+
background: color-mix(in srgb, var(--color-on-surface-variant) 18%, transparent);
|
|
1188
|
+
color: var(--color-on-surface-variant);
|
|
1189
|
+
font-family: var(--font-label);
|
|
1190
|
+
font-size: var(--type-label);
|
|
1191
|
+
font-weight: var(--weight-label);
|
|
1192
|
+
letter-spacing: 0.04em;
|
|
1193
|
+
text-transform: uppercase;
|
|
1194
|
+
line-height: 1;
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
.article-related-list {
|
|
1198
|
+
display: flex;
|
|
1199
|
+
flex-direction: column;
|
|
1200
|
+
gap: var(--space-2xs, 0.35rem);
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
.article-related-card {
|
|
1204
|
+
display: flex;
|
|
1205
|
+
flex-direction: column;
|
|
1206
|
+
gap: var(--space-2xs, 0.25rem);
|
|
1207
|
+
padding: var(--space-sm) var(--space-md);
|
|
1208
|
+
background: var(--color-surface-container-low);
|
|
1209
|
+
border-radius: var(--radius-card);
|
|
1210
|
+
border: 1px solid var(--border-gentle-subtle);
|
|
1211
|
+
text-decoration: none;
|
|
1212
|
+
transition:
|
|
1213
|
+
border-color var(--motion-duration-fast) var(--motion-ease-default),
|
|
1214
|
+
background-color var(--motion-duration-fast) var(--motion-ease-default);
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
.article-related-card:hover {
|
|
1218
|
+
border-color: color-mix(in srgb, var(--color-on-surface) 28%, var(--border-gentle-subtle));
|
|
1219
|
+
background: var(--color-surface-container);
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
.article-related-card--articles:hover {
|
|
1223
|
+
border-color: color-mix(in srgb, var(--triad-secondary) 40%, var(--border-gentle-subtle));
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
.article-related-card--posts:hover {
|
|
1227
|
+
border-color: color-mix(in srgb, var(--triad-tertiary) 40%, var(--border-gentle-subtle));
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
.article-related-card--projects:hover {
|
|
1231
|
+
border-color: color-mix(in srgb, var(--triad-primary) 40%, var(--border-gentle-subtle));
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
.article-related-card-title {
|
|
1235
|
+
font-family: var(--font-content-title);
|
|
1236
|
+
font-size: calc(var(--type-subtitle) - 1pt);
|
|
1237
|
+
font-weight: 400;
|
|
1238
|
+
line-height: 1.3;
|
|
1239
|
+
margin: 0;
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
.article-related-card-title a {
|
|
1243
|
+
color: var(--color-on-surface);
|
|
1244
|
+
text-decoration: none;
|
|
1245
|
+
transition: color var(--motion-duration-fast) var(--motion-ease-default);
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
.article-related-card--articles:hover .article-related-card-title a {
|
|
1249
|
+
color: var(--triad-secondary);
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
.article-related-card--posts:hover .article-related-card-title a {
|
|
1253
|
+
color: var(--triad-tertiary);
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1256
|
+
.article-related-card--projects:hover .article-related-card-title a {
|
|
1257
|
+
color: var(--triad-primary);
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
.article-related-card-dates {
|
|
1261
|
+
font-family: var(--font-mono);
|
|
1262
|
+
font-size: var(--type-meta);
|
|
1263
|
+
color: var(--color-on-surface);
|
|
1264
|
+
line-height: 1.4;
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1267
|
+
.article-related-card-dates-sep {
|
|
1268
|
+
color: var(--color-on-surface);
|
|
1269
|
+
opacity: 0.55;
|
|
1270
|
+
}
|