Compare commits
7
Commits
c3a2ebc594
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
26224b2ab7 | ||
|
|
fff248f25f | ||
|
|
6897103041 | ||
|
|
d4769e9a33 | ||
|
|
061f94c85f | ||
|
|
5ff2867a26 | ||
|
|
8e3cbb6530 |
+1
-1
@@ -3,7 +3,7 @@ dist/
|
||||
.astro/
|
||||
.DS_Store
|
||||
|
||||
# Content lives in the ctao/content repo (build overlays it; scripts/link-content.sh locally)
|
||||
# Content lives in the ctao/content repo (deploy copies it in; npm run content:link links ../content locally)
|
||||
src/content/news/
|
||||
src/content/pages/
|
||||
public/uploads/
|
||||
|
||||
@@ -1,110 +1,54 @@
|
||||
# CTAO Science Portal — simple proof of concept
|
||||
# CTAO Science Portal
|
||||
|
||||
The `main` branch uses the sibling `mockup` project's layout, assets, CSS,
|
||||
and header interactions. Astro generates a static site. Sveltia CMS edits
|
||||
exactly four Markdown pages in the separate `ctao/content` repository.
|
||||
Static Astro site with a git-based CMS (Sveltia). Code lives here; editorial
|
||||
content lives in the separate [`ctao/content`](https://astro-git.isl-dev.grid.cyfronet.pl/ctao/content)
|
||||
repository. The Home page and four Example pages are editable; the rest are placeholders.
|
||||
|
||||
## Scope
|
||||
|
||||
| Example submenu | URL | Content file |
|
||||
|---|---|---|
|
||||
| Lorem ipsum | `/example/lorem-ipsum/` | `pages/lorem-ipsum.md` |
|
||||
| Dolor sit amet | `/example/dolor-sit-amet/` | `pages/dolor-sit-amet.md` |
|
||||
| Consectetur adipiscing | `/example/consectetur-adipiscing/` | `pages/consectetur-adipiscing.md` |
|
||||
| Sed do eiusmod | `/example/sed-do-eiusmod/` | `pages/sed-do-eiusmod.md` |
|
||||
|
||||
Home, News, Data, Proposals, Dashboard, Sign in, Search, Support, Privacy,
|
||||
Disclaimer, and Contact have the shared header/footer, a title, and an empty
|
||||
body. Search submits to its placeholder. Only English is available; the
|
||||
other language options are inactive. There are no news articles, news
|
||||
pagination, RSS feeds, search index, service integrations, or public sign-in.
|
||||
`/admin/` remains the working CMS entry point.
|
||||
- Live demo: https://astro.isl-dev.grid.cyfronet.pl
|
||||
- Editor: https://astro.isl-dev.grid.cyfronet.pl/admin/ (Gitea sign-in)
|
||||
|
||||
## Run locally
|
||||
|
||||
Use Node 22.19 or newer (deployment uses Node 24).
|
||||
Node 22.19 or newer. Clone the content repository next to this one:
|
||||
|
||||
```sh
|
||||
git clone https://astro-git.isl-dev.grid.cyfronet.pl/ctao/content.git ../content
|
||||
npm ci
|
||||
npm run dev
|
||||
npm run dev # http://localhost:4321
|
||||
```
|
||||
|
||||
Open `http://localhost:4321/example/lorem-ipsum/` for the full mockup example.
|
||||
The first run copies bundled `sample-content/pages/` and `uploads/` into the
|
||||
ignored runtime directories. Existing content is preserved. An incomplete
|
||||
existing set fails with a missing-file error instead of silently mixing
|
||||
sample content with editorial content.
|
||||
The site reads `../content` directly through links, so pull that repository
|
||||
for the latest content. To use a checkout elsewhere:
|
||||
`npm run content:link -- <path>`.
|
||||
|
||||
```sh
|
||||
npm run content:setup # explicitly restore the four sample pages
|
||||
npm run content:sync -- ../ctao-content # copy from a separate content checkout
|
||||
npm run check # types, static build, internal links
|
||||
npm run build
|
||||
npm run preview # inspect the built site
|
||||
```
|
||||
Before pushing code, run `npm run check` (types, build, internal links).
|
||||
|
||||
`content:setup` and `content:sync` replace the four runtime Markdown files and
|
||||
copy uploads, overwriting same-named media. They do not modify the source
|
||||
content checkout. Only the four allowlisted pages are loaded and rendered;
|
||||
unrelated Markdown files never create public routes.
|
||||
## Edit content locally
|
||||
|
||||
## Edit with Sveltia locally, without Gitea
|
||||
With `npm run dev` running, open `http://localhost:4321/admin/` in Chrome or
|
||||
Edge, choose **Work with Local Repository** and select the `../content` folder.
|
||||
Saves write the Markdown files and show up on the local site on reload. They
|
||||
are not committed: commit and push in `../content` to publish.
|
||||
|
||||
```sh
|
||||
npm run content:local
|
||||
npm run dev
|
||||
```
|
||||
## Publishing
|
||||
|
||||
In Chrome or Edge, open `/admin/`, select **Work with Local Repository**, and
|
||||
choose this project's `.tmp/content` directory. The setup command creates a
|
||||
local Git repository there, seeded from the bundled content. Re-running it
|
||||
preserves edits in that directory.
|
||||
|
||||
Save an Example page, then run this in another terminal to refresh the site:
|
||||
|
||||
```sh
|
||||
npm run content:sync -- .tmp/content
|
||||
```
|
||||
|
||||
The local editor writes files without committing them. This follows
|
||||
[Sveltia's local workflow](https://sveltiacms.app/en/docs/workflows/local).
|
||||
Choose the content repository root, not the portal code repository root:
|
||||
the CMS expects `pages/` and `uploads/` directly beneath it.
|
||||
|
||||
## Content and publishing
|
||||
|
||||
The CMS uses a [fixed file collection](https://sveltiacms.app/en/docs/collections/files).
|
||||
Editors can change title, introduction, optional image/alternative text/caption,
|
||||
Markdown body, and optional button label/destination. Both button fields are
|
||||
needed to display the button. A Markdown blockquote receives the mockup's
|
||||
highlight styling. Images without alternative text are treated as decorative.
|
||||
Menu labels, ordering, URLs, and the shared site layout remain code-controlled.
|
||||
|
||||
Remote editing uses Gitea OAuth and saves to **`ctao/content`, branch `main`**.
|
||||
That branch must contain the four files from `sample-content/pages/` and the
|
||||
sample upload before publishing this version. The code mirror is
|
||||
**`ctao/portal`, branch `main`**. Deployment independently selects
|
||||
`CODE_BRANCH` and `CONTENT_BRANCH`, overlays content, runs checks, and publishes
|
||||
atomically. `CONTENT_BRANCH` must match `backend.branch` in the CMS config.
|
||||
|
||||
See [deploy/README.md](deploy/README.md) for migration and publishing steps.
|
||||
A push to Bitbucket alone does not deploy the site.
|
||||
Pushing to `main` of `ctao/portal` (code) or `ctao/content` (content) on
|
||||
Gitea rebuilds and publishes the live demo automatically; the online editor
|
||||
commits to `ctao/content` directly. Pushing to Bitbucket does not deploy.
|
||||
Server setup is in [deploy/README.md](deploy/README.md).
|
||||
|
||||
## Where things live
|
||||
|
||||
| Path | Purpose |
|
||||
|---|---|
|
||||
| `src/layouts/Base.astro` | Mockup header, navigation, footer, page shell |
|
||||
| `src/components/PageHero.astro` | Breadcrumb, title, introduction, nebula |
|
||||
| `src/pages/example/[slug].astro` | One reusable editable-page template |
|
||||
| `src/data/examples.json` | Fixed submenu labels, order, and slugs |
|
||||
| `src/data/placeholders.json` | Empty destinations |
|
||||
| `src/styles/global.css` | Mockup styles plus Markdown/placeholder variants |
|
||||
| `public/assets/`, `public/header.js` | Mockup assets and menu behavior |
|
||||
| `sample-content/` | Versioned seed content for local use and Gitea setup |
|
||||
| `src/content/pages/`, `public/uploads/` | Ignored runtime content overlay |
|
||||
| `public/admin/config.yml` | Four fixed CMS files and Gitea configuration |
|
||||
| `scripts/preview-styles.mjs` | Generates CMS body preview styles from site CSS |
|
||||
| `src/layouts/Base.astro` | Header, navigation, footer, page shell |
|
||||
| `src/layouts/ContentPage.astro` | Layout of the editable pages (Home and Examples) |
|
||||
| `src/data/examples.json` | Example pages: menu labels, order, slugs |
|
||||
| `src/data/placeholders.json` | Placeholder pages |
|
||||
| `src/styles/global.css` | All site styles |
|
||||
| `public/admin/config.yml` | CMS fields and Gitea connection |
|
||||
| `scripts/preview-styles.mjs` | Builds the CMS preview styles from `global.css` |
|
||||
| `scripts/content.mjs` | Links the content checkout into the site |
|
||||
|
||||
The vendored CMS bundle remains in `public/vendor/sveltia-cms.js`. Dependencies
|
||||
remain pinned; this simplification adds no application dependencies.
|
||||
To add an Example page, add it to `src/data/examples.json` and
|
||||
`public/admin/config.yml`, and commit its Markdown file to `ctao/content`.
|
||||
|
||||
+7
-10
@@ -31,13 +31,11 @@ missing). Everything else runs inside containers.
|
||||
|
||||
## Publish the simplified portal from `main`
|
||||
|
||||
1. In a checkout of `ctao/content`, switch to `main`. Copy the missing
|
||||
Example files from `sample-content/pages/` and
|
||||
`sample-content/uploads/hero.jpg` from this code repository into its root
|
||||
`pages/` and `uploads/` directories, then commit the seed files. Preserve
|
||||
any existing editorial versions of these files. Existing
|
||||
news or other page files can remain in the content history; this portal
|
||||
loads only the four Example files.
|
||||
1. Check that `ctao/content:main` contains the four Example files in `pages/`
|
||||
(listed in `src/data/examples.json`) and the uploads they reference. They
|
||||
are already committed there (`a3452d7`, "demo lorem ipsum pages"). News and
|
||||
other page files can remain in the content repository; this portal loads
|
||||
only the four Example files.
|
||||
2. Push the content branch to Gitea as `ctao/content:main`, and the code
|
||||
branch as `ctao/portal:main`. These are separate pushes; Bitbucket is
|
||||
not the deployment remote.
|
||||
@@ -90,9 +88,8 @@ the previous portal may be restored.
|
||||
password never lands in a file or shell history:
|
||||
`podman exec -it ctao-demo-gitea gitea admin user create --admin --username <you> --email <you@…> --random-password`
|
||||
7. **[W]** In the Gitea UI: create org `ctao` with repos `portal` and
|
||||
`content` (both public read). Seed the content `main` branch with
|
||||
`sample-content/pages/` and `sample-content/uploads/` as described above.
|
||||
Then, from your workstation, push both over
|
||||
`content` (both public read). The content `main` branch needs the four
|
||||
Example pages described above. Then, from your workstation, push both over
|
||||
the vhost with a repo-scoped token:
|
||||
`git push https://<user>:<token>@astro-git.isl-dev.grid.cyfronet.pl/ctao/portal.git main`
|
||||
`git push https://<user>:<token>@astro-git.isl-dev.grid.cyfronet.pl/ctao/content.git main`
|
||||
|
||||
+4
-6
@@ -4,15 +4,13 @@
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"content:setup": "node scripts/content.mjs",
|
||||
"content:sync": "node scripts/content.mjs",
|
||||
"content:local": "node scripts/local-content.mjs",
|
||||
"predev": "node scripts/content.mjs --ensure && node scripts/preview-styles.mjs",
|
||||
"content:link": "node scripts/content.mjs --relink",
|
||||
"predev": "node scripts/content.mjs && node scripts/preview-styles.mjs",
|
||||
"dev": "astro dev",
|
||||
"prebuild": "node scripts/content.mjs --ensure && node scripts/preview-styles.mjs",
|
||||
"prebuild": "node scripts/content.mjs && node scripts/preview-styles.mjs",
|
||||
"build": "astro build",
|
||||
"preview": "astro preview",
|
||||
"precheck": "node scripts/content.mjs --ensure && node scripts/preview-styles.mjs",
|
||||
"precheck": "node scripts/content.mjs && node scripts/preview-styles.mjs",
|
||||
"check": "astro check && astro build && node scripts/check-links.mjs"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
+24
-1
@@ -5,7 +5,6 @@
|
||||
backend:
|
||||
name: gitea
|
||||
# Keep this branch in sync with CONTENT_BRANCH in deploy/build.sh.
|
||||
# Seed the content branch from sample-content/ before deploying.
|
||||
repo: ctao/content
|
||||
branch: main
|
||||
base_url: https://astro-git.isl-dev.grid.cyfronet.pl
|
||||
@@ -45,6 +44,30 @@ media_libraries:
|
||||
optimize: true
|
||||
|
||||
collections:
|
||||
- name: home
|
||||
label: "Home page"
|
||||
files:
|
||||
- name: home
|
||||
label: "Home page"
|
||||
file: "pages/home.md"
|
||||
format: frontmatter
|
||||
fields:
|
||||
- { name: title, label: "Title", widget: string }
|
||||
- { name: introduction, label: "Introduction", widget: text, required: false }
|
||||
- name: images
|
||||
label: "Images"
|
||||
label_singular: "image"
|
||||
widget: list
|
||||
required: false
|
||||
max: 2
|
||||
hint: "Up to two images, shown side by side."
|
||||
fields:
|
||||
- { name: image, label: "Image", widget: image }
|
||||
- { name: alt, label: "Alternative text", widget: string, required: false, hint: "Describe the image; leave empty only for decorative images." }
|
||||
- { name: caption, label: "Caption", widget: string, required: false }
|
||||
- { name: body, label: "Body", widget: markdown }
|
||||
- { name: buttonLabel, label: "Button label", widget: string, required: false }
|
||||
- { name: buttonUrl, label: "Button destination", widget: string, required: false, hint: "A site path such as /example/lorem-ipsum/, or an https:// URL." }
|
||||
- name: examples
|
||||
label: "Example pages"
|
||||
files:
|
||||
|
||||
+261
-23
@@ -1,7 +1,10 @@
|
||||
/* Generated by scripts/preview-styles.mjs; edit src/styles/global.css. */
|
||||
|
||||
/* ==========================================================================
|
||||
CTAO Science Portal: content page mockup
|
||||
Colours and type follow the CTAO Brand Guidelines (April 2024).
|
||||
The editor preview (public/admin/preview.css) is generated from the
|
||||
hero, prose and button sections below by scripts/preview-styles.mjs.
|
||||
========================================================================== */
|
||||
|
||||
/* Fonts
|
||||
@@ -50,9 +53,12 @@
|
||||
--gutter: clamp(1rem, 4vw, 2.5rem);
|
||||
--header-height: 7rem;
|
||||
--header-height-scrolled: 5rem;
|
||||
--radius-lg: 60px;
|
||||
--radius-md: 30px;
|
||||
/* Large decorative corners (hero, header, search panel): grows with the
|
||||
viewport instead of switching at breakpoints */
|
||||
--radius-lg: min(15vw, 180px);
|
||||
--radius-sm: 15px;
|
||||
/* How far photos are pulled up into the hero */
|
||||
--hero-overlap: clamp(6rem, 11.25vw, 9rem);
|
||||
/* Dropdown submenus (Example, language) */
|
||||
--radius-menu: 8px;
|
||||
--transition: 0.3s ease-in-out;
|
||||
@@ -126,19 +132,182 @@ button {
|
||||
outline-color: var(--cherenkov-blue);
|
||||
}
|
||||
|
||||
/* Utilities
|
||||
========================================================================== */
|
||||
|
||||
.container {
|
||||
width: min(100% - 2 * var(--gutter), var(--content-width));
|
||||
margin-inline: auto;
|
||||
}
|
||||
|
||||
.visually-hidden {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
margin: -1px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
clip-path: inset(50%);
|
||||
white-space: nowrap;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.skip-link {
|
||||
position: absolute;
|
||||
top: -4rem;
|
||||
left: 1rem;
|
||||
z-index: 100;
|
||||
padding: 0.5rem 1rem;
|
||||
color: var(--galaxy-blue);
|
||||
background: var(--white);
|
||||
border-radius: var(--radius-sm);
|
||||
}
|
||||
|
||||
.skip-link:focus {
|
||||
top: 1rem;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
display: inline-block;
|
||||
transition: transform 0.25s ease;
|
||||
}
|
||||
|
||||
a:hover .arrow,
|
||||
button:hover .arrow {
|
||||
transform: translateX(4px);
|
||||
}
|
||||
|
||||
@keyframes panel-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-6px);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Page hero
|
||||
========================================================================== */
|
||||
|
||||
.page-hero {
|
||||
margin-top: calc(-1 * var(--header-height));
|
||||
padding: calc(var(--header-height) + 3rem) 0 calc(var(--hero-overlap) + 3rem);
|
||||
color: var(--white);
|
||||
background: var(--grain), var(--galaxy-blue);
|
||||
border-bottom-right-radius: var(--radius-lg);
|
||||
}
|
||||
|
||||
/* Pages without a photo: no room needed for the figure to overlap */
|
||||
.page-hero--compact {
|
||||
padding-bottom: 4rem;
|
||||
}
|
||||
|
||||
.breadcrumb ol {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5rem;
|
||||
margin: 0 0 1rem;
|
||||
padding: 0;
|
||||
font-size: 0.875rem;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.breadcrumb li + li::before {
|
||||
content: "›";
|
||||
margin-right: 0.5rem;
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.breadcrumb a {
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
|
||||
.breadcrumb a:hover {
|
||||
color: var(--white);
|
||||
}
|
||||
|
||||
.breadcrumb [aria-current] {
|
||||
font-weight: 500;
|
||||
color: var(--white);
|
||||
}
|
||||
|
||||
/* Headline: Space Grotesk medium, white on dark (D.3.4) */
|
||||
.page-hero__title {
|
||||
max-width: 24ch;
|
||||
margin: 0 0 1.25rem;
|
||||
font-family: var(--font-head);
|
||||
font-size: clamp(2rem, 5vw, 3.75rem);
|
||||
font-weight: 500;
|
||||
line-height: 1.05;
|
||||
letter-spacing: -0.02em;
|
||||
text-wrap: balance;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.page-hero__lead {
|
||||
max-width: 70ch;
|
||||
margin: 0;
|
||||
font-size: 1.0625rem;
|
||||
font-weight: 500;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
/* Photo pulled up over the hero; flat, no shadow */
|
||||
.page-figure {
|
||||
margin: calc(-1 * var(--hero-overlap)) 0 4rem;
|
||||
}
|
||||
|
||||
.page-figure img {
|
||||
width: 100%;
|
||||
border-radius: var(--radius-sm);
|
||||
}
|
||||
|
||||
.page-figure figcaption {
|
||||
margin-top: 0.75rem;
|
||||
font-size: 0.8125rem;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
/* Two photos side by side (Home), pulled up over the hero together; they
|
||||
stack by themselves once each would be narrower than 18rem */
|
||||
.page-figures {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
|
||||
gap: 1.5rem;
|
||||
margin: calc(-1 * var(--hero-overlap)) 0 4rem;
|
||||
}
|
||||
|
||||
.page-figures .page-figure {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Same shape for both photos, whatever the uploads' proportions */
|
||||
.page-figures img {
|
||||
aspect-ratio: 3 / 2;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
/* Prose
|
||||
========================================================================== */
|
||||
|
||||
body {
|
||||
.prose {
|
||||
padding-bottom: 5rem;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
body > * {
|
||||
.prose--no-image {
|
||||
padding-top: 4rem;
|
||||
}
|
||||
|
||||
.prose > * {
|
||||
max-width: 64rem;
|
||||
}
|
||||
|
||||
/* Galaxy Blue headline on light background (D.3.4) */
|
||||
body h2 {
|
||||
.prose h2 {
|
||||
margin: 3rem 0 1rem;
|
||||
font-family: var(--font-head);
|
||||
font-size: clamp(1.75rem, 3vw, 2.375rem);
|
||||
@@ -148,26 +317,26 @@ body h2 {
|
||||
color: var(--galaxy-blue);
|
||||
}
|
||||
|
||||
body h2:first-child {
|
||||
.prose h2:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
body p {
|
||||
.prose p {
|
||||
margin: 0 0 1.25rem;
|
||||
font-size: 1.0625rem;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* Text links: colour only at rest, underline on hover and focus */
|
||||
body a:not(.btn):hover,
|
||||
body a:not(.btn):focus-visible {
|
||||
.prose a:not(.btn):hover,
|
||||
.prose a:not(.btn):focus-visible {
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 0.15em;
|
||||
}
|
||||
|
||||
/* Cherenkov Blue fails contrast as text on white, so it is the accent bar */
|
||||
body .highlight,
|
||||
body blockquote {
|
||||
.prose .highlight,
|
||||
.prose blockquote {
|
||||
margin: 2.5rem 0;
|
||||
padding-left: 1.5rem;
|
||||
font-size: 1.375rem;
|
||||
@@ -177,6 +346,61 @@ body blockquote {
|
||||
border-left: 4px solid var(--cherenkov-blue);
|
||||
}
|
||||
|
||||
.prose blockquote p {
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
.prose h3,
|
||||
.prose h4,
|
||||
.prose h5,
|
||||
.prose h6 {
|
||||
font-family: var(--font-head);
|
||||
color: var(--galaxy-blue);
|
||||
}
|
||||
|
||||
.prose li {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.prose img {
|
||||
border-radius: var(--radius-sm);
|
||||
}
|
||||
|
||||
.prose pre {
|
||||
padding: 1rem;
|
||||
overflow-x: auto;
|
||||
background: var(--moon-gray);
|
||||
}
|
||||
|
||||
.prose code {
|
||||
overflow-wrap: normal;
|
||||
}
|
||||
|
||||
.prose table {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.prose th,
|
||||
.prose td {
|
||||
padding: 0.75rem;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.prose hr {
|
||||
margin: 2rem 0;
|
||||
border: 0;
|
||||
border-top: 1px solid #ddd;
|
||||
}
|
||||
|
||||
/* Placeholder pages: empty body until their content exists */
|
||||
.placeholder-body {
|
||||
min-height: 12rem;
|
||||
}
|
||||
|
||||
/* Buttons
|
||||
========================================================================== */
|
||||
|
||||
@@ -217,16 +441,30 @@ body blockquote {
|
||||
filter: brightness(1.1);
|
||||
}
|
||||
|
||||
body { overflow-wrap: anywhere; }
|
||||
body h3, body h4, body h5, body h6 { color: var(--galaxy-blue); font-family: var(--font-head); }
|
||||
body li { margin-bottom: 0.5rem; }
|
||||
body blockquote p { font-size: inherit; line-height: inherit; }
|
||||
body pre { padding: 1rem; overflow-x: auto; background: var(--moon-gray); }
|
||||
body code { overflow-wrap: normal; }
|
||||
body table { display: block; overflow-x: auto; border-collapse: collapse; }
|
||||
body th, body td { padding: 0.75rem; border-bottom: 1px solid #ddd; text-align: left; }
|
||||
body hr { margin: 2rem 0; border: 0; border-top: 1px solid #ddd; }
|
||||
body img { border-radius: var(--radius-sm); }
|
||||
/* Preferences
|
||||
========================================================================== */
|
||||
|
||||
body { display: block; min-height: 0; max-width: 64rem; margin: 0 auto; padding: 1.5rem; }
|
||||
h1 { color: var(--galaxy-blue); font-family: var(--font-head); font-weight: 500; line-height: 1.05; }
|
||||
/* Windows High Contrast: drop the decorative hero background behind system text */
|
||||
@media (forced-colors: active) {
|
||||
.page-hero {
|
||||
background-image: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
animation: none !important;
|
||||
transition: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Preview frame
|
||||
========================================================================== */
|
||||
|
||||
/* There is no site header above the hero */
|
||||
.page-hero {
|
||||
margin-top: 0;
|
||||
padding-top: 3rem;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" id="Ebene_1" x="0" y="0" viewBox="0 0 153 43.9">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" id="Ebene_1" x="0" y="0" viewBox="0 0 153 46.0">
|
||||
<style>
|
||||
.st3{fill:#ffffff}
|
||||
.st5{fill:#00E4D8}
|
||||
@@ -7,5 +7,5 @@
|
||||
<path d="m100 22.3 4.3 8.4h9.2l-5.3-10.2zm22.4-6.2V16c0-5.2 2.9-8.2 10.2-8.2 5.7 0 8.7 1.9 9.8 5.2l8.8-1.4c-1.8-7-8.2-11-18.6-11-12.4 0-19.1 5.7-19.1 15.5 0 .5 0 1.1.1 1.6zm20.1-2.7c.2.8.3 1.7.3 2.6 0 5.1-3 8.3-10.2 8.3-6.4 0-9.5-2.5-10.1-6.7l-8.7 1.8c1.4 7.7 7.9 12.2 18.8 12.2 12.4 0 19.1-5.8 19.1-15.6 0-1.6-.2-3.1-.5-4.4zM73.4 26.9l-2 3.8h9.2l2.7-5.4zm25-25.6H86.6L74.5 24.7l10.2-2.2 7.8-15.2 6.4 12.6 8.3-1.3zM53.7 30.1v.6h8.5v-2zm0-1.1 8.5-1.7V8.5h13.4V1.3H40.2v7.2h13.5zM19.6.5c10.8 0 17 4.7 17.8 12.2h-9.1c-.6-2.7-3.3-5-8.8-5-6.3 0-9.4 3.1-9.4 8.2s3.1 8.3 9.4 8.3c5.4 0 8.2-2.3 8.8-5.1h9.1c-.9 7.6-7 12.3-17.8 12.3C7.8 31.5 1.3 26.1 1.3 16S7.8.5 19.6.5" class="st3"/>
|
||||
<path d="M94.4 23.7c1-1.4 3.3-2.1 5.1-2.7-2 .1-4.4.3-5.8-.6-1.4-1-2.1-3.3-2.7-5.1.1 2 .3 4.4-.6 5.8-1 1.4-3.3 2.1-5.1 2.7 2-.1 4.4-.3 5.8.6 1.4 1 2.1 3.3 2.7 5.1-.2-2-.4-4.4.6-5.8" class="st5"/>
|
||||
</g>
|
||||
<path d="M5.6 42.3c-.6 0-1-.1-1.4-.3s-.7-.4-1-.8c-.2-.3-.4-.7-.4-1.2H4c0 .2.1.5.2.6.1.2.3.3.5.4s.5.1.7.1c.3 0 .5 0 .7-.1s.4-.2.5-.4c.3 0 .4-.2.4-.4s-.1-.3-.2-.5-.3-.2-.4-.3c-.2-.1-.4-.2-.7-.2l-.8-.2c-.6-.2-1.1-.4-1.4-.7-.4-.3-.5-.7-.5-1.2 0-.4.1-.8.3-1.1s.5-.6.9-.7.9-.3 1.4-.3 1 .1 1.3.3c.4.2.7.4.9.7s.3.7.3 1.1H6.9c0-.3-.2-.5-.4-.7s-.6-.3-.9-.3-.5 0-.7.1-.3.2-.4.3-.2.3-.2.5.1.4.2.5.3.2.5.3.3.2.5.2l.7.2c.3.1.5.1.8.3s.5.2.7.4.4.4.5.6.2.5.2.8c0 .4-.1.8-.3 1.1s-.5.6-.9.7c-.6.2-1.1.2-1.6.2m11.8 0c-.6 0-1.2-.1-1.7-.4s-.9-.7-1.2-1.3c-.3-.5-.4-1.2-.4-2s.1-1.4.4-2c.3-.5.7-1 1.2-1.3s1-.4 1.7-.4c.4 0 .8.1 1.1.2s.6.3.9.5.5.5.7.8.3.7.3 1h-1.3c0-.2-.1-.4-.2-.6s-.2-.3-.4-.4c-.1-.1-.3-.2-.5-.3s-.4-.1-.6-.1c-.4 0-.7.1-1 .3s-.5.5-.7.9-.3.8-.3 1.4c0 .5.1 1 .3 1.4s.4.7.7.8c.3.2.6.3 1 .3.2 0 .4 0 .6-.1s.4-.1.5-.3c.2-.1.3-.3.4-.4s.2-.4.2-.6h1.3c0 .3-.2.7-.3 1-.2.3-.4.6-.6.8-.3.2-.6.4-.9.5-.4.3-.8.3-1.2.3m10.3-7.2v7.1h-1.3v-7.1zm6.3 7.1v-7.1h4.6v1.1h-3.4v1.9h3.1v1.1h-3.1v2h3.4v1.1H34zm10.9 0v-7.1h1.4l2.5 3.9c.1.2.2.3.3.6s.2.4.4.7c.1.3.2.5.4.8h-.1c0-.3 0-.5-.1-.8s0-.5 0-.8v-4.3H51v7.1h-1.4l-2.2-3.5c-.1-.2-.3-.4-.4-.7-.1-.2-.3-.5-.4-.7l-.5-1h.2c0 .3 0 .7.1 1v4.9h-1.5zm15.3.1c-.6 0-1.2-.1-1.7-.4s-.9-.7-1.2-1.3c-.3-.5-.4-1.2-.4-2s.1-1.4.4-2c.3-.5.7-1 1.2-1.3s1-.4 1.7-.4c.4 0 .8.1 1.1.2s.6.3.9.5.5.5.7.8.3.7.3 1H62c0-.2-.1-.4-.2-.6s-.2-.3-.4-.4c-.1-.1-.3-.2-.5-.3s-.4-.1-.6-.1c-.4 0-.7.1-1 .3s-.5.5-.7.9-.3.8-.3 1.4c0 .5.1 1 .3 1.4s.4.7.7.8c.3.2.6.3 1 .3.2 0 .4 0 .6-.1s.4-.1.5-.3c.2-.1.3-.3.4-.4s.2-.4.2-.6h1.3c0 .3-.2.7-.3 1-.2.3-.4.6-.6.8-.3.2-.6.4-.9.5-.5.3-.8.3-1.3.3m9.1-.1v-7.1H74v1.1h-3.4v1.9h3.1v1.1h-3.1v2H74v1.1h-4.7zm18.2 0v-7.1h2.7c.5 0 1 .1 1.4.3s.7.5.8.8.3.8.3 1.2q0 .75-.3 1.2c-.2.4-.5.6-.9.8s-.8.3-1.4.3h-1.8v-1.1H90c.3 0 .6-.1.8-.2s.4-.3.5-.5.1-.4.1-.7 0-.5-.1-.7-.2-.3-.5-.5-.5-.2-.8-.2h-1.2v6.1h-1.3zm14.3.1c-.6 0-1.2-.1-1.7-.4s-.9-.7-1.2-1.3-.4-1.2-.4-2 .1-1.4.4-2 .7-1 1.2-1.3 1.1-.4 1.7-.4 1.2.1 1.7.4.9.7 1.2 1.3c.3.5.4 1.2.4 2s-.1 1.4-.4 2c-.3.5-.7 1-1.2 1.3s-1.1.4-1.7.4m0-1.1c.4 0 .7-.1 1-.3s.5-.5.7-.9.3-.8.3-1.4c0-.5-.1-1-.3-1.4s-.4-.7-.7-.9-.6-.3-1-.3-.7.1-1 .3-.5.5-.7.9-.3.8-.3 1.4c0 .5.1 1 .3 1.4s.4.7.7.9.6.3 1 .3m9.4 1v-7.1h2.7c.5 0 1 .1 1.4.3s.7.5.8.8.3.7.3 1.2-.1.8-.3 1.2c-.2.3-.5.6-.9.8s-.8.3-1.4.3h-1.9v-1.1h1.7c.3 0 .6 0 .8-.1s.4-.2.5-.4.1-.4.1-.6c0-.3 0-.5-.1-.7s-.3-.3-.5-.4-.5-.1-.8-.1h-1.2v6.1h-1.2zm4 0-1.7-3.2h1.4l1.8 3.2zm6.9-6v-1.1h5.7v1.1h-2.2v6.1h-1.3v-6.1zm10.4 6 2.5-7.1h1.6l2.5 7.1h-1.4l-1.3-3.7c-.1-.4-.3-.8-.4-1.3s-.3-1-.4-1.6h.3c-.2.6-.3 1.2-.4 1.7s-.3.9-.4 1.3l-1.2 3.7h-1.4zm1.5-1.7v-1h3.8v1zm11 1.7v-7.1h1.3v6.1h3.1v1.1H145z" class="st3"/>
|
||||
<path d="M6.48 45.77Q5.41 45.77 4.62 45.44Q3.83 45.1 3.38 44.47Q2.94 43.83 2.9 42.92H4.53Q4.57 43.4 4.83 43.72Q5.09 44.04 5.52 44.2Q5.95 44.36 6.47 44.36Q7.01 44.36 7.43 44.19Q7.85 44.03 8.08 43.72Q8.32 43.42 8.32 43.03Q8.32 42.67 8.11 42.43Q7.9 42.2 7.53 42.03Q7.15 41.87 6.65 41.75L5.6 41.47Q4.45 41.18 3.8 40.57Q3.15 39.97 3.15 38.99Q3.15 38.18 3.59 37.57Q4.03 36.95 4.8 36.61Q5.56 36.28 6.52 36.28Q7.51 36.28 8.25 36.62Q8.99 36.96 9.41 37.56Q9.83 38.16 9.85 38.93H8.25Q8.18 38.33 7.71 38.01Q7.25 37.68 6.5 37.68Q5.98 37.68 5.6 37.84Q5.23 38 5.03 38.27Q4.83 38.55 4.83 38.9Q4.83 39.28 5.06 39.53Q5.3 39.78 5.66 39.93Q6.03 40.08 6.4 40.17L7.26 40.39Q7.77 40.51 8.26 40.72Q8.74 40.92 9.13 41.24Q9.52 41.55 9.75 41.99Q9.97 42.44 9.97 43.04Q9.97 43.85 9.56 44.47Q9.15 45.08 8.37 45.43Q7.58 45.77 6.48 45.77ZM18.24 45.75Q17.03 45.75 16.08 45.19Q15.12 44.63 14.57 43.57Q14.02 42.51 14.02 41.02Q14.02 39.53 14.58 38.47Q15.13 37.4 16.08 36.84Q17.04 36.28 18.24 36.28Q19 36.28 19.66 36.49Q20.32 36.71 20.84 37.12Q21.35 37.53 21.69 38.12Q22.02 38.72 22.13 39.47H20.47Q20.39 39.06 20.19 38.74Q20 38.43 19.71 38.21Q19.41 37.98 19.05 37.87Q18.68 37.76 18.27 37.76Q17.51 37.76 16.93 38.14Q16.34 38.52 16.01 39.25Q15.68 39.97 15.68 41.02Q15.68 42.08 16.02 42.8Q16.35 43.53 16.93 43.9Q17.52 44.27 18.27 44.27Q18.68 44.27 19.04 44.16Q19.41 44.04 19.7 43.82Q20 43.6 20.19 43.28Q20.39 42.97 20.47 42.56H22.14Q22.05 43.22 21.73 43.8Q21.42 44.38 20.91 44.82Q20.41 45.26 19.74 45.51Q19.06 45.75 18.24 45.75ZM28.13 36.4V45.63H26.48V36.4ZM32.81 45.63V36.4H38.81V37.79H34.46V40.28H38.49V41.66H34.46V44.24H38.83V45.63ZM43.31 45.63V36.4H45.18L48.38 41.48Q48.57 41.8 48.8 42.2Q49.02 42.6 49.26 43.09Q49.5 43.58 49.74 44.19H49.55Q49.51 43.66 49.48 43.12Q49.44 42.57 49.43 42.07Q49.41 41.58 49.41 41.24V36.4H51.09V45.63H49.21L46.33 41.05Q46.06 40.61 45.82 40.19Q45.57 39.76 45.3 39.22Q45.02 38.68 44.62 37.92H44.85Q44.89 38.59 44.92 39.2Q44.96 39.8 44.98 40.28Q45 40.75 45 41.05V45.63ZM59.7 45.75Q58.49 45.75 57.53 45.19Q56.58 44.63 56.03 43.57Q55.48 42.51 55.48 41.02Q55.48 39.53 56.03 38.47Q56.58 37.4 57.54 36.84Q58.5 36.28 59.7 36.28Q60.46 36.28 61.12 36.49Q61.78 36.71 62.29 37.12Q62.81 37.53 63.14 38.12Q63.48 38.72 63.59 39.47H61.92Q61.84 39.06 61.65 38.74Q61.45 38.43 61.16 38.21Q60.87 37.98 60.51 37.87Q60.14 37.76 59.73 37.76Q58.97 37.76 58.38 38.14Q57.8 38.52 57.47 39.25Q57.14 39.97 57.14 41.02Q57.14 42.08 57.47 42.8Q57.81 43.53 58.39 43.9Q58.97 44.27 59.72 44.27Q60.14 44.27 60.5 44.16Q60.86 44.04 61.16 43.82Q61.45 43.6 61.65 43.28Q61.85 42.97 61.93 42.56H63.59Q63.5 43.22 63.19 43.8Q62.88 44.38 62.37 44.82Q61.86 45.26 61.19 45.51Q60.52 45.75 59.7 45.75ZM67.93 45.63V36.4H73.93V37.79H69.59V40.28H73.61V41.66H69.59V44.24H73.95V45.63ZM84.45 45.63V36.4H87.91Q88.97 36.4 89.69 36.8Q90.41 37.2 90.78 37.89Q91.15 38.57 91.15 39.46Q91.15 40.34 90.78 41.03Q90.41 41.72 89.68 42.11Q88.95 42.51 87.88 42.51H85.59V41.15H87.66Q88.29 41.15 88.69 40.93Q89.09 40.71 89.28 40.33Q89.46 39.95 89.46 39.46Q89.46 38.96 89.28 38.59Q89.09 38.21 88.69 38Q88.28 37.78 87.65 37.78H86.11V45.63ZM99.41 45.75Q98.2 45.75 97.24 45.19Q96.28 44.63 95.72 43.57Q95.17 42.51 95.17 41.02Q95.17 39.53 95.72 38.47Q96.28 37.4 97.24 36.84Q98.2 36.28 99.41 36.28Q100.62 36.28 101.57 36.84Q102.53 37.4 103.08 38.47Q103.64 39.53 103.64 41.02Q103.64 42.51 103.08 43.57Q102.53 44.63 101.57 45.19Q100.62 45.75 99.41 45.75ZM99.41 44.27Q100.16 44.27 100.74 43.9Q101.32 43.52 101.65 42.8Q101.98 42.07 101.98 41.02Q101.98 39.96 101.65 39.23Q101.32 38.51 100.74 38.13Q100.16 37.76 99.41 37.76Q98.65 37.76 98.07 38.13Q97.49 38.51 97.16 39.24Q96.83 39.97 96.83 41.02Q96.83 42.07 97.16 42.8Q97.49 43.52 98.07 43.9Q98.65 44.27 99.41 44.27ZM108.03 45.63V36.4H111.48Q112.54 36.4 113.26 36.77Q113.99 37.14 114.36 37.81Q114.73 38.47 114.73 39.35Q114.73 40.24 114.35 40.89Q113.98 41.54 113.25 41.89Q112.52 42.24 111.45 42.24H108.99V40.87H111.23Q111.86 40.87 112.26 40.69Q112.66 40.52 112.85 40.18Q113.04 39.84 113.04 39.35Q113.04 38.86 112.85 38.51Q112.66 38.16 112.26 37.97Q111.86 37.78 111.23 37.78H109.68V45.63ZM113.22 45.63 110.98 41.44H112.79L115.07 45.63ZM118.71 37.79V36.4H126.06V37.79H123.21V45.63H121.56V37.79ZM129.7 45.63 132.92 36.4H135.02L138.31 45.63H136.5L134.86 40.84Q134.62 40.09 134.36 39.15Q134.1 38.22 133.78 37.02H134.13Q133.82 38.23 133.57 39.17Q133.32 40.12 133.09 40.84L131.51 45.63ZM131.58 43.34V42.01H136.44V43.34ZM142.37 45.63V36.4H144.02V44.24H148.1V45.63Z" class="st3"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 5.4 KiB |
@@ -1,4 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" id="Ebene_1" x="0" y="0" viewBox="0 0 153 43.9">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" id="Ebene_1" x="0" y="0" viewBox="0 0 153 46.0">
|
||||
<style>
|
||||
.st3{fill:#00004a}
|
||||
</style>
|
||||
@@ -6,5 +6,5 @@
|
||||
<path d="m100 22.3 4.3 8.4h9.2l-5.3-10.2zm22.4-6.2V16c0-5.2 2.9-8.2 10.2-8.2 5.7 0 8.7 1.9 9.8 5.2l8.8-1.4c-1.8-7-8.2-11-18.6-11-12.4 0-19.1 5.7-19.1 15.5 0 .5 0 1.1.1 1.6zm20.1-2.7c.2.8.3 1.7.3 2.6 0 5.1-3 8.3-10.2 8.3-6.4 0-9.5-2.5-10.1-6.7l-8.7 1.8c1.4 7.7 7.9 12.2 18.8 12.2 12.4 0 19.1-5.8 19.1-15.6 0-1.6-.2-3.1-.5-4.4zM73.4 26.9l-2 3.8h9.2l2.7-5.4zm25-25.6H86.6L74.5 24.7l10.2-2.2 7.8-15.2 6.4 12.6 8.3-1.3zM53.7 30.1v.6h8.5v-2zm0-1.1 8.5-1.7V8.5h13.4V1.3H40.2v7.2h13.5zM19.6.5c10.8 0 17 4.7 17.8 12.2h-9.1c-.6-2.7-3.3-5-8.8-5-6.3 0-9.4 3.1-9.4 8.2s3.1 8.3 9.4 8.3c5.4 0 8.2-2.3 8.8-5.1h9.1c-.9 7.6-7 12.3-17.8 12.3C7.8 31.5 1.3 26.1 1.3 16S7.8.5 19.6.5" class="st3"/>
|
||||
<path d="M94.4 23.7c1-1.4 3.3-2.1 5.1-2.7-2 .1-4.4.3-5.8-.6-1.4-1-2.1-3.3-2.7-5.1.1 2 .3 4.4-.6 5.8-1 1.4-3.3 2.1-5.1 2.7 2-.1 4.4-.3 5.8.6 1.4 1 2.1 3.3 2.7 5.1-.2-2-.4-4.4.6-5.8" class="st3"/>
|
||||
</g>
|
||||
<path d="M5.6 42.3c-.6 0-1-.1-1.4-.3s-.7-.4-1-.8c-.2-.3-.4-.7-.4-1.2H4c0 .2.1.5.2.6.1.2.3.3.5.4s.5.1.7.1c.3 0 .5 0 .7-.1s.4-.2.5-.4c.3 0 .4-.2.4-.4s-.1-.3-.2-.5-.3-.2-.4-.3c-.2-.1-.4-.2-.7-.2l-.8-.2c-.6-.2-1.1-.4-1.4-.7-.4-.3-.5-.7-.5-1.2 0-.4.1-.8.3-1.1s.5-.6.9-.7.9-.3 1.4-.3 1 .1 1.3.3c.4.2.7.4.9.7s.3.7.3 1.1H6.9c0-.3-.2-.5-.4-.7s-.6-.3-.9-.3-.5 0-.7.1-.3.2-.4.3-.2.3-.2.5.1.4.2.5.3.2.5.3.3.2.5.2l.7.2c.3.1.5.1.8.3s.5.2.7.4.4.4.5.6.2.5.2.8c0 .4-.1.8-.3 1.1s-.5.6-.9.7c-.6.2-1.1.2-1.6.2m11.8 0c-.6 0-1.2-.1-1.7-.4s-.9-.7-1.2-1.3c-.3-.5-.4-1.2-.4-2s.1-1.4.4-2c.3-.5.7-1 1.2-1.3s1-.4 1.7-.4c.4 0 .8.1 1.1.2s.6.3.9.5.5.5.7.8.3.7.3 1h-1.3c0-.2-.1-.4-.2-.6s-.2-.3-.4-.4c-.1-.1-.3-.2-.5-.3s-.4-.1-.6-.1c-.4 0-.7.1-1 .3s-.5.5-.7.9-.3.8-.3 1.4c0 .5.1 1 .3 1.4s.4.7.7.8c.3.2.6.3 1 .3.2 0 .4 0 .6-.1s.4-.1.5-.3c.2-.1.3-.3.4-.4s.2-.4.2-.6h1.3c0 .3-.2.7-.3 1-.2.3-.4.6-.6.8-.3.2-.6.4-.9.5-.4.3-.8.3-1.2.3m10.3-7.2v7.1h-1.3v-7.1zm6.3 7.1v-7.1h4.6v1.1h-3.4v1.9h3.1v1.1h-3.1v2h3.4v1.1H34zm10.9 0v-7.1h1.4l2.5 3.9c.1.2.2.3.3.6s.2.4.4.7c.1.3.2.5.4.8h-.1c0-.3 0-.5-.1-.8s0-.5 0-.8v-4.3H51v7.1h-1.4l-2.2-3.5c-.1-.2-.3-.4-.4-.7-.1-.2-.3-.5-.4-.7l-.5-1h.2c0 .3 0 .7.1 1v4.9h-1.5zm15.3.1c-.6 0-1.2-.1-1.7-.4s-.9-.7-1.2-1.3c-.3-.5-.4-1.2-.4-2s.1-1.4.4-2c.3-.5.7-1 1.2-1.3s1-.4 1.7-.4c.4 0 .8.1 1.1.2s.6.3.9.5.5.5.7.8.3.7.3 1H62c0-.2-.1-.4-.2-.6s-.2-.3-.4-.4c-.1-.1-.3-.2-.5-.3s-.4-.1-.6-.1c-.4 0-.7.1-1 .3s-.5.5-.7.9-.3.8-.3 1.4c0 .5.1 1 .3 1.4s.4.7.7.8c.3.2.6.3 1 .3.2 0 .4 0 .6-.1s.4-.1.5-.3c.2-.1.3-.3.4-.4s.2-.4.2-.6h1.3c0 .3-.2.7-.3 1-.2.3-.4.6-.6.8-.3.2-.6.4-.9.5-.5.3-.8.3-1.3.3m9.1-.1v-7.1H74v1.1h-3.4v1.9h3.1v1.1h-3.1v2H74v1.1h-4.7zm18.2 0v-7.1h2.7c.5 0 1 .1 1.4.3s.7.5.8.8.3.8.3 1.2q0 .75-.3 1.2c-.2.4-.5.6-.9.8s-.8.3-1.4.3h-1.8v-1.1H90c.3 0 .6-.1.8-.2s.4-.3.5-.5.1-.4.1-.7 0-.5-.1-.7-.2-.3-.5-.5-.5-.2-.8-.2h-1.2v6.1h-1.3zm14.3.1c-.6 0-1.2-.1-1.7-.4s-.9-.7-1.2-1.3-.4-1.2-.4-2 .1-1.4.4-2 .7-1 1.2-1.3 1.1-.4 1.7-.4 1.2.1 1.7.4.9.7 1.2 1.3c.3.5.4 1.2.4 2s-.1 1.4-.4 2c-.3.5-.7 1-1.2 1.3s-1.1.4-1.7.4m0-1.1c.4 0 .7-.1 1-.3s.5-.5.7-.9.3-.8.3-1.4c0-.5-.1-1-.3-1.4s-.4-.7-.7-.9-.6-.3-1-.3-.7.1-1 .3-.5.5-.7.9-.3.8-.3 1.4c0 .5.1 1 .3 1.4s.4.7.7.9.6.3 1 .3m9.4 1v-7.1h2.7c.5 0 1 .1 1.4.3s.7.5.8.8.3.7.3 1.2-.1.8-.3 1.2c-.2.3-.5.6-.9.8s-.8.3-1.4.3h-1.9v-1.1h1.7c.3 0 .6 0 .8-.1s.4-.2.5-.4.1-.4.1-.6c0-.3 0-.5-.1-.7s-.3-.3-.5-.4-.5-.1-.8-.1h-1.2v6.1h-1.2zm4 0-1.7-3.2h1.4l1.8 3.2zm6.9-6v-1.1h5.7v1.1h-2.2v6.1h-1.3v-6.1zm10.4 6 2.5-7.1h1.6l2.5 7.1h-1.4l-1.3-3.7c-.1-.4-.3-.8-.4-1.3s-.3-1-.4-1.6h.3c-.2.6-.3 1.2-.4 1.7s-.3.9-.4 1.3l-1.2 3.7h-1.4zm1.5-1.7v-1h3.8v1zm11 1.7v-7.1h1.3v6.1h3.1v1.1H145z" class="st3"/>
|
||||
<path d="M6.48 45.77Q5.41 45.77 4.62 45.44Q3.83 45.1 3.38 44.47Q2.94 43.83 2.9 42.92H4.53Q4.57 43.4 4.83 43.72Q5.09 44.04 5.52 44.2Q5.95 44.36 6.47 44.36Q7.01 44.36 7.43 44.19Q7.85 44.03 8.08 43.72Q8.32 43.42 8.32 43.03Q8.32 42.67 8.11 42.43Q7.9 42.2 7.53 42.03Q7.15 41.87 6.65 41.75L5.6 41.47Q4.45 41.18 3.8 40.57Q3.15 39.97 3.15 38.99Q3.15 38.18 3.59 37.57Q4.03 36.95 4.8 36.61Q5.56 36.28 6.52 36.28Q7.51 36.28 8.25 36.62Q8.99 36.96 9.41 37.56Q9.83 38.16 9.85 38.93H8.25Q8.18 38.33 7.71 38.01Q7.25 37.68 6.5 37.68Q5.98 37.68 5.6 37.84Q5.23 38 5.03 38.27Q4.83 38.55 4.83 38.9Q4.83 39.28 5.06 39.53Q5.3 39.78 5.66 39.93Q6.03 40.08 6.4 40.17L7.26 40.39Q7.77 40.51 8.26 40.72Q8.74 40.92 9.13 41.24Q9.52 41.55 9.75 41.99Q9.97 42.44 9.97 43.04Q9.97 43.85 9.56 44.47Q9.15 45.08 8.37 45.43Q7.58 45.77 6.48 45.77ZM18.24 45.75Q17.03 45.75 16.08 45.19Q15.12 44.63 14.57 43.57Q14.02 42.51 14.02 41.02Q14.02 39.53 14.58 38.47Q15.13 37.4 16.08 36.84Q17.04 36.28 18.24 36.28Q19 36.28 19.66 36.49Q20.32 36.71 20.84 37.12Q21.35 37.53 21.69 38.12Q22.02 38.72 22.13 39.47H20.47Q20.39 39.06 20.19 38.74Q20 38.43 19.71 38.21Q19.41 37.98 19.05 37.87Q18.68 37.76 18.27 37.76Q17.51 37.76 16.93 38.14Q16.34 38.52 16.01 39.25Q15.68 39.97 15.68 41.02Q15.68 42.08 16.02 42.8Q16.35 43.53 16.93 43.9Q17.52 44.27 18.27 44.27Q18.68 44.27 19.04 44.16Q19.41 44.04 19.7 43.82Q20 43.6 20.19 43.28Q20.39 42.97 20.47 42.56H22.14Q22.05 43.22 21.73 43.8Q21.42 44.38 20.91 44.82Q20.41 45.26 19.74 45.51Q19.06 45.75 18.24 45.75ZM28.13 36.4V45.63H26.48V36.4ZM32.81 45.63V36.4H38.81V37.79H34.46V40.28H38.49V41.66H34.46V44.24H38.83V45.63ZM43.31 45.63V36.4H45.18L48.38 41.48Q48.57 41.8 48.8 42.2Q49.02 42.6 49.26 43.09Q49.5 43.58 49.74 44.19H49.55Q49.51 43.66 49.48 43.12Q49.44 42.57 49.43 42.07Q49.41 41.58 49.41 41.24V36.4H51.09V45.63H49.21L46.33 41.05Q46.06 40.61 45.82 40.19Q45.57 39.76 45.3 39.22Q45.02 38.68 44.62 37.92H44.85Q44.89 38.59 44.92 39.2Q44.96 39.8 44.98 40.28Q45 40.75 45 41.05V45.63ZM59.7 45.75Q58.49 45.75 57.53 45.19Q56.58 44.63 56.03 43.57Q55.48 42.51 55.48 41.02Q55.48 39.53 56.03 38.47Q56.58 37.4 57.54 36.84Q58.5 36.28 59.7 36.28Q60.46 36.28 61.12 36.49Q61.78 36.71 62.29 37.12Q62.81 37.53 63.14 38.12Q63.48 38.72 63.59 39.47H61.92Q61.84 39.06 61.65 38.74Q61.45 38.43 61.16 38.21Q60.87 37.98 60.51 37.87Q60.14 37.76 59.73 37.76Q58.97 37.76 58.38 38.14Q57.8 38.52 57.47 39.25Q57.14 39.97 57.14 41.02Q57.14 42.08 57.47 42.8Q57.81 43.53 58.39 43.9Q58.97 44.27 59.72 44.27Q60.14 44.27 60.5 44.16Q60.86 44.04 61.16 43.82Q61.45 43.6 61.65 43.28Q61.85 42.97 61.93 42.56H63.59Q63.5 43.22 63.19 43.8Q62.88 44.38 62.37 44.82Q61.86 45.26 61.19 45.51Q60.52 45.75 59.7 45.75ZM67.93 45.63V36.4H73.93V37.79H69.59V40.28H73.61V41.66H69.59V44.24H73.95V45.63ZM84.45 45.63V36.4H87.91Q88.97 36.4 89.69 36.8Q90.41 37.2 90.78 37.89Q91.15 38.57 91.15 39.46Q91.15 40.34 90.78 41.03Q90.41 41.72 89.68 42.11Q88.95 42.51 87.88 42.51H85.59V41.15H87.66Q88.29 41.15 88.69 40.93Q89.09 40.71 89.28 40.33Q89.46 39.95 89.46 39.46Q89.46 38.96 89.28 38.59Q89.09 38.21 88.69 38Q88.28 37.78 87.65 37.78H86.11V45.63ZM99.41 45.75Q98.2 45.75 97.24 45.19Q96.28 44.63 95.72 43.57Q95.17 42.51 95.17 41.02Q95.17 39.53 95.72 38.47Q96.28 37.4 97.24 36.84Q98.2 36.28 99.41 36.28Q100.62 36.28 101.57 36.84Q102.53 37.4 103.08 38.47Q103.64 39.53 103.64 41.02Q103.64 42.51 103.08 43.57Q102.53 44.63 101.57 45.19Q100.62 45.75 99.41 45.75ZM99.41 44.27Q100.16 44.27 100.74 43.9Q101.32 43.52 101.65 42.8Q101.98 42.07 101.98 41.02Q101.98 39.96 101.65 39.23Q101.32 38.51 100.74 38.13Q100.16 37.76 99.41 37.76Q98.65 37.76 98.07 38.13Q97.49 38.51 97.16 39.24Q96.83 39.97 96.83 41.02Q96.83 42.07 97.16 42.8Q97.49 43.52 98.07 43.9Q98.65 44.27 99.41 44.27ZM108.03 45.63V36.4H111.48Q112.54 36.4 113.26 36.77Q113.99 37.14 114.36 37.81Q114.73 38.47 114.73 39.35Q114.73 40.24 114.35 40.89Q113.98 41.54 113.25 41.89Q112.52 42.24 111.45 42.24H108.99V40.87H111.23Q111.86 40.87 112.26 40.69Q112.66 40.52 112.85 40.18Q113.04 39.84 113.04 39.35Q113.04 38.86 112.85 38.51Q112.66 38.16 112.26 37.97Q111.86 37.78 111.23 37.78H109.68V45.63ZM113.22 45.63 110.98 41.44H112.79L115.07 45.63ZM118.71 37.79V36.4H126.06V37.79H123.21V45.63H121.56V37.79ZM129.7 45.63 132.92 36.4H135.02L138.31 45.63H136.5L134.86 40.84Q134.62 40.09 134.36 39.15Q134.1 38.22 133.78 37.02H134.13Q133.82 38.23 133.57 39.17Q133.32 40.12 133.09 40.84L131.51 45.63ZM131.58 43.34V42.01H136.44V43.34ZM142.37 45.63V36.4H144.02V44.24H148.1V45.63Z" class="st3"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 5.4 KiB |
@@ -1,12 +0,0 @@
|
||||
---
|
||||
title: "Consectetur adipiscing"
|
||||
introduction: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
|
||||
---
|
||||
|
||||
## Consectetur adipiscing
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
|
||||
- Lorem ipsum dolor sit amet.
|
||||
- Consectetur adipiscing elit.
|
||||
- Sed do eiusmod tempor incididunt.
|
||||
@@ -1,19 +0,0 @@
|
||||
---
|
||||
title: "Dolor sit amet"
|
||||
introduction: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
|
||||
image: "/uploads/hero.jpg"
|
||||
imageAlt: "Telescope beneath a star-filled night sky"
|
||||
imageCaption: "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
|
||||
---
|
||||
|
||||
## Dolor sit amet
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
|
||||
|
||||
|
||||
Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam.
|
||||
|
||||
Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur. At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti.
|
||||
|
||||
Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus.
|
||||
@@ -1,25 +0,0 @@
|
||||
---
|
||||
title: "Lorem Ipsum Dolor Sit Amet Consectetur"
|
||||
introduction: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
|
||||
image: "/uploads/hero.jpg"
|
||||
imageAlt: "Telescope beneath a star-filled night sky"
|
||||
imageCaption: "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
|
||||
buttonLabel: "Lorem ipsum"
|
||||
buttonUrl: "/example/dolor-sit-amet/"
|
||||
---
|
||||
|
||||
## Lorem Ipsum Dolor
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat ([lorem ipsum](/example/dolor-sit-amet/)). Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
|
||||
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo [inventore veritatis](/example/consectetur-adipiscing/) et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia [consequuntur magni](/example/sed-do-eiusmod/) dolores eos qui ratione voluptatem sequi nesciunt.
|
||||
|
||||
> Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
|
||||
|
||||
## Consectetur Adipiscing Elit
|
||||
|
||||
Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam.
|
||||
|
||||
Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur. At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti.
|
||||
|
||||
Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus.
|
||||
@@ -1,16 +0,0 @@
|
||||
---
|
||||
title: "Sed do eiusmod"
|
||||
introduction: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
|
||||
---
|
||||
|
||||
## Sed do eiusmod
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
|
||||
|
||||
|
||||
Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam.
|
||||
|
||||
Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur. At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti.
|
||||
|
||||
Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus.
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 176 KiB |
+43
-27
@@ -1,34 +1,50 @@
|
||||
// Copy the four editable files into Astro's ignored content directory.
|
||||
// --ensure seeds only a fresh checkout; an incomplete existing set fails loudly.
|
||||
import { cpSync, existsSync, mkdirSync, readFileSync } from 'node:fs';
|
||||
import { resolve, join } from 'node:path';
|
||||
// Point the site at a checkout of the ctao/content repository (default: the
|
||||
// sibling ../content clone), the same content the live demo builds from.
|
||||
// src/content/pages and public/uploads become links into that checkout, so
|
||||
// saves from Sveltia's local-repository mode show up in `npm run dev` directly.
|
||||
//
|
||||
// node scripts/content.mjs link if missing, then check the pages (pre-hooks)
|
||||
// npm run content:link -- [dir] replace existing links or copies
|
||||
//
|
||||
// The deploy build copies the content into place instead (deploy/build.sh);
|
||||
// existing directories are left alone unless --relink is given.
|
||||
import { existsSync, lstatSync, mkdirSync, readFileSync, rmSync, symlinkSync, unlinkSync } from 'node:fs';
|
||||
import { dirname, join, relative, resolve } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const root = fileURLToPath(new URL('../', import.meta.url));
|
||||
const examples = JSON.parse(readFileSync(join(root, 'src/data/examples.json'), 'utf8'));
|
||||
const ensure = process.argv.includes('--ensure');
|
||||
const source = resolve(process.argv[2] && !ensure ? process.argv[2] : join(root, 'sample-content'));
|
||||
const relink = process.argv.includes('--relink');
|
||||
const source = resolve(root, process.argv.slice(2).find((arg) => !arg.startsWith('--')) ?? '../content');
|
||||
const targets = [
|
||||
{ from: join(source, 'pages'), to: join(root, 'src/content/pages') },
|
||||
{ from: join(source, 'uploads'), to: join(root, 'public/uploads') },
|
||||
];
|
||||
|
||||
const exists = (path) => {
|
||||
try { lstatSync(path); return true; } catch { return false; }
|
||||
};
|
||||
|
||||
for (const { from, to } of targets) {
|
||||
if (exists(to) && !relink) continue;
|
||||
if (!existsSync(from)) {
|
||||
throw new Error(`Missing ${from}. Clone the content repository first:\n` +
|
||||
` git clone https://astro-git.isl-dev.grid.cyfronet.pl/ctao/content.git ${relative(root, source) || '.'}\n` +
|
||||
'or pass another checkout: npm run content:link -- <path>');
|
||||
}
|
||||
if (exists(to)) {
|
||||
// Remove only the link itself, never the content it points to.
|
||||
if (lstatSync(to).isSymbolicLink()) unlinkSync(to);
|
||||
else rmSync(to, { recursive: true }); // an old copied overlay
|
||||
}
|
||||
mkdirSync(dirname(to), { recursive: true });
|
||||
symlinkSync(from, to, 'junction'); // a junction needs no admin rights on Windows
|
||||
console.log(`Linked ${relative(root, to)} -> ${from}`);
|
||||
}
|
||||
|
||||
const pages = join(root, 'src/content/pages');
|
||||
const uploads = join(root, 'public/uploads');
|
||||
|
||||
function validate(directory) {
|
||||
for (const { slug } of examples) {
|
||||
if (!existsSync(join(directory, `${slug}.md`))) {
|
||||
throw new Error(`Missing ${join(directory, `${slug}.md`)}. Run npm run content:setup or npm run content:sync -- <content-clone>.`);
|
||||
}
|
||||
for (const slug of ['home', ...examples.map(({ slug }) => slug)]) {
|
||||
if (!existsSync(join(pages, `${slug}.md`))) {
|
||||
throw new Error(`Missing ${join(pages, `${slug}.md`)}. Check the content checkout, or run npm run content:link -- <path>.`);
|
||||
}
|
||||
}
|
||||
|
||||
if (ensure && existsSync(pages)) {
|
||||
validate(pages);
|
||||
} else {
|
||||
validate(join(source, 'pages'));
|
||||
if (!existsSync(join(source, 'uploads'))) throw new Error(`Missing uploads directory in ${source}`);
|
||||
mkdirSync(pages, { recursive: true });
|
||||
mkdirSync(uploads, { recursive: true });
|
||||
for (const { slug } of examples) {
|
||||
cpSync(join(source, 'pages', `${slug}.md`), join(pages, `${slug}.md`));
|
||||
}
|
||||
cpSync(join(source, 'uploads'), uploads, { recursive: true });
|
||||
console.log(`Example content copied from ${source}`);
|
||||
}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Local dev: put the content repo's files where the build expects them.
|
||||
# Usage: ./scripts/link-content.sh [path-to-content-clone] (default ../ctao-content)
|
||||
# Cross-platform implementation is shared with npm run content:sync.
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/.."
|
||||
node scripts/content.mjs "${1:-../ctao-content}"
|
||||
@@ -1,19 +0,0 @@
|
||||
// Prepare a disposable content repository for Sveltia's local folder picker.
|
||||
import { cpSync, existsSync, mkdirSync } from 'node:fs';
|
||||
import { execFileSync } from 'node:child_process';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { join } from 'node:path';
|
||||
|
||||
const root = fileURLToPath(new URL('../', import.meta.url));
|
||||
const local = join(root, '.tmp/content');
|
||||
if (!existsSync(local)) {
|
||||
mkdirSync(local, { recursive: true });
|
||||
cpSync(join(root, 'sample-content/pages'), join(local, 'pages'), { recursive: true });
|
||||
cpSync(join(root, 'sample-content/uploads'), join(local, 'uploads'), { recursive: true });
|
||||
}
|
||||
if (!existsSync(join(local, '.git'))) {
|
||||
execFileSync('git', ['init', '--quiet', '--initial-branch=main', local], { stdio: 'inherit' });
|
||||
}
|
||||
execFileSync(process.execPath, [join(root, 'scripts/content.mjs'), local], { stdio: 'inherit' });
|
||||
console.log(`In Sveltia, choose Work with Local Repository and select: ${local}`);
|
||||
console.log('After saving, run: npm run content:sync -- .tmp/content');
|
||||
+24
-10
@@ -1,13 +1,27 @@
|
||||
// Derive editor body styles from the mockup CSS so the preview cannot drift.
|
||||
// Derive editor preview styles from the site CSS so the preview cannot drift.
|
||||
// The preview template in src/pages/admin/index.astro renders the same markup
|
||||
// as the Example pages, so the page hero, figure and prose rules apply as-is.
|
||||
import { readFileSync, writeFileSync } from 'node:fs';
|
||||
|
||||
const css = readFileSync(new URL('../src/styles/global.css', import.meta.url), 'utf8');
|
||||
const base = css.slice(0, css.indexOf('/* Utilities'));
|
||||
const prose = css.slice(css.indexOf('/* Prose'), css.indexOf('/* Footer'));
|
||||
const markdown = css.slice(css.indexOf('.prose { overflow-wrap:'), css.indexOf('.submenu a[aria-current="page"]'));
|
||||
const preview = (base + prose + markdown).replace(/\.prose\b/g, 'body');
|
||||
const css = readFileSync(new URL('../src/styles/global.css', import.meta.url), 'utf8').replace(/\r\n/g, '\n');
|
||||
const between = (start, end) => {
|
||||
const from = css.indexOf(start);
|
||||
const to = end ? css.indexOf(end, from) : css.length;
|
||||
if (from < 0 || to < 0) throw new Error(`preview-styles: marker not found in global.css: ${from < 0 ? start : end}`);
|
||||
return css.slice(from, to).trim();
|
||||
};
|
||||
const preview = [
|
||||
between('/* ===', '/* Header'), // fonts, tokens, base, utilities
|
||||
between('/* Page hero', '/* Footer'), // hero, figure, prose, buttons
|
||||
between('/* Preferences'), // high contrast, reduced motion
|
||||
`/* Preview frame
|
||||
========================================================================== */
|
||||
|
||||
/* There is no site header above the hero */
|
||||
.page-hero {
|
||||
margin-top: 0;
|
||||
padding-top: 3rem;
|
||||
}`,
|
||||
];
|
||||
writeFileSync(new URL('../public/admin/preview.css', import.meta.url),
|
||||
'/* Generated by scripts/preview-styles.mjs; edit src/styles/global.css. */\n' + preview + `
|
||||
body { display: block; min-height: 0; max-width: 64rem; margin: 0 auto; padding: 1.5rem; }
|
||||
h1 { color: var(--galaxy-blue); font-family: var(--font-head); font-weight: 500; line-height: 1.05; }
|
||||
`);
|
||||
'/* Generated by scripts/preview-styles.mjs; edit src/styles/global.css. */\n\n' + preview.join('\n\n') + '\n');
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
---
|
||||
interface Props { title: string; introduction?: string; example?: boolean; hasImage?: boolean }
|
||||
const { title, introduction, example = false, hasImage = false } = Astro.props;
|
||||
interface Props { title: string; introduction?: string; example?: boolean; breadcrumb?: boolean; hasImage?: boolean }
|
||||
const { title, introduction, example = false, breadcrumb = true, hasImage = false } = Astro.props;
|
||||
---
|
||||
<section class:list={['page-hero', { 'page-hero--compact': !hasImage }]}>
|
||||
<div class="container">
|
||||
<nav class="breadcrumb" aria-label="Breadcrumb">
|
||||
{breadcrumb && <nav class="breadcrumb" aria-label="Breadcrumb">
|
||||
<ol>
|
||||
{Astro.url.pathname !== '/' && <li><a href="/">Home</a></li>}
|
||||
{example && <li>Example</li>}
|
||||
<li aria-current="page">{title}</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</nav>}
|
||||
<h1 class="page-hero__title">{title}</h1>
|
||||
{introduction && <p class="page-hero__lead">{introduction}</p>}
|
||||
</div>
|
||||
|
||||
@@ -8,17 +8,24 @@ const destination = z.string().refine(
|
||||
'Use a site path, https:// URL, mailto: address, or fragment.',
|
||||
);
|
||||
const pages = defineCollection({
|
||||
// Only these four files can become public content pages.
|
||||
// Only the Home page and the four Example files can become public pages.
|
||||
loader: glob({
|
||||
pattern: `{${examples.map(({ slug }) => slug).join(',')}}.md`,
|
||||
pattern: `{home,${examples.map(({ slug }) => slug).join(',')}}.md`,
|
||||
base: './src/content/pages',
|
||||
}),
|
||||
schema: z.object({
|
||||
title: z.string().min(1),
|
||||
introduction: z.string().optional(),
|
||||
// Example pages: one photo
|
||||
image: z.string().optional(),
|
||||
imageAlt: z.string().optional(),
|
||||
imageCaption: z.string().optional(),
|
||||
// Home: up to two photos side by side
|
||||
images: z.array(z.object({
|
||||
image: z.string().min(1),
|
||||
alt: z.string().optional(),
|
||||
caption: z.string().optional(),
|
||||
})).max(2).optional(),
|
||||
buttonLabel: z.string().optional(),
|
||||
buttonUrl: destination.optional(),
|
||||
}),
|
||||
|
||||
@@ -24,7 +24,7 @@ const canonical = new URL(Astro.url.pathname, Astro.site);
|
||||
<div class="site-header__inner">
|
||||
|
||||
<a class="site-header__logo" href="/">
|
||||
<img src="/assets/logo-sp-negative.svg" alt="CTAO – Home" width="153" height="43.9">
|
||||
<img src="/assets/logo-sp-negative.svg" alt="CTAO – Home" width="153" height="46">
|
||||
</a>
|
||||
|
||||
<nav class="site-nav" id="site-nav" aria-label="Main">
|
||||
@@ -104,7 +104,7 @@ const canonical = new URL(Astro.url.pathname, Astro.site);
|
||||
<main id="main" tabindex="-1"><slot /></main>
|
||||
<footer class="site-footer">
|
||||
<div class="container site-footer__inner">
|
||||
<img class="site-footer__logo" src="/assets/logo-sp-negative.svg" alt="CTAO" width="153" height="43.9" />
|
||||
<img class="site-footer__logo" src="/assets/logo-sp-negative.svg" alt="CTAO" width="153" height="46" />
|
||||
<ul class="site-footer__nav">
|
||||
<li><a href="/pages/privacy/">Privacy</a></li>
|
||||
<li><a href="/pages/disclaimer/">Disclaimer</a></li>
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
---
|
||||
// Editable content page: hero, one photo (Example pages) or two side by side
|
||||
// (Home), Markdown body and optional button. The CMS preview template in
|
||||
// src/pages/admin/index.astro mirrors this markup.
|
||||
import type { CollectionEntry } from 'astro:content';
|
||||
import { render } from 'astro:content';
|
||||
import Base from './Base.astro';
|
||||
import PageHero from '../components/PageHero.astro';
|
||||
|
||||
interface Props { page: CollectionEntry<'pages'>; example?: boolean; breadcrumb?: boolean }
|
||||
const { page, example = false, breadcrumb = true } = Astro.props;
|
||||
const { Content } = await render(page);
|
||||
const { title, introduction, image, imageAlt, imageCaption, images, buttonLabel, buttonUrl } = page.data;
|
||||
const photos = images ?? (image ? [{ image, alt: imageAlt, caption: imageCaption }] : []);
|
||||
---
|
||||
<Base title={example ? title : undefined} description={introduction}>
|
||||
<PageHero title={title} introduction={introduction} example={example} breadcrumb={breadcrumb} hasImage={photos.length > 0} />
|
||||
{photos.length > 0 && <div class="container">
|
||||
<div class:list={{ 'page-figures': photos.length > 1 }}>
|
||||
{photos.map(({ image, alt, caption }) => (
|
||||
<figure class="page-figure">
|
||||
<img src={image} alt={alt || ''} />
|
||||
{caption && <figcaption>{caption}</figcaption>}
|
||||
</figure>
|
||||
))}
|
||||
</div>
|
||||
</div>}
|
||||
<article class:list={['container', 'prose', { 'prose--no-image': photos.length === 0 }]}>
|
||||
<Content />
|
||||
{buttonLabel && buttonUrl && <p>
|
||||
<a class="btn btn--primary" href={buttonUrl}>
|
||||
<span class="btn__label">{buttonLabel}</span><span class="arrow" aria-hidden="true">→</span>
|
||||
</a>
|
||||
</p>}
|
||||
</article>
|
||||
</Base>
|
||||
@@ -5,6 +5,9 @@
|
||||
// deliberate — see README); note the bundle still fetches its own UI fonts
|
||||
// from jsDelivr at runtime. Kept is:inline so Astro doesn't process/bundle it.
|
||||
// CTAO branding on the sign-in screen comes from the documented `logo` option.
|
||||
import examples from '../../data/examples.json';
|
||||
|
||||
const previewNames = examples.map(({ slug }) => slug);
|
||||
---
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
@@ -32,5 +35,64 @@
|
||||
// Generated from the site's CSS; see scripts/preview-styles.mjs.
|
||||
window.CMS?.registerPreviewStyle?.('/admin/preview.css');
|
||||
</script>
|
||||
<script is:inline define:vars={{ previewNames }}>
|
||||
// Preview pane: the same markup as src/layouts/ContentPage.astro and
|
||||
// PageHero.astro, without field labels. Sveltia looks templates up by
|
||||
// file name for file collections, so register one per page.
|
||||
const { h, rf } = window;
|
||||
// Our own <img>: Sveltia's image widget keeps the image transparent until
|
||||
// a visibility check that does not complete inside a custom template.
|
||||
// The asset URL starts as the public path and becomes a blob URL once
|
||||
// Sveltia has fetched the file, which covers images not deployed yet.
|
||||
const PreviewImage = ({ asset, fallback, alt }) => h('img', {
|
||||
src: asset ? String(asset) : fallback,
|
||||
alt,
|
||||
onError: ({ currentTarget: img }) => {
|
||||
const retry = (tries) => {
|
||||
const url = asset && String(asset);
|
||||
if (url && url !== img.getAttribute('src')) img.src = url;
|
||||
else if (tries) setTimeout(() => retry(tries - 1), 500);
|
||||
};
|
||||
retry(10);
|
||||
},
|
||||
});
|
||||
const PagePreview = ({ entry, widgetFor, getAsset, home = false }) => {
|
||||
const get = (key) => entry.getIn(['data', key]);
|
||||
const title = get('title') || '';
|
||||
const introduction = get('introduction');
|
||||
const buttonLabel = get('buttonLabel');
|
||||
const buttonUrl = get('buttonUrl');
|
||||
// Home: a list of up to two photos; Example pages: a single photo
|
||||
const photos = home
|
||||
? (get('images')?.toJS?.() ?? []).filter((item) => item?.image)
|
||||
: get('image') ? [{ image: get('image'), alt: get('imageAlt'), caption: get('imageCaption') }] : [];
|
||||
return h(rf, null,
|
||||
h('section', { className: photos.length ? 'page-hero' : 'page-hero page-hero--compact' },
|
||||
h('div', { className: 'container' },
|
||||
!home && h('nav', { className: 'breadcrumb', 'aria-label': 'Breadcrumb' },
|
||||
h('ol', null,
|
||||
h('li', null, h('a', { href: '/' }, 'Home')),
|
||||
h('li', null, 'Example'),
|
||||
h('li', { 'aria-current': 'page' }, title))),
|
||||
h('h1', { className: 'page-hero__title' }, title),
|
||||
introduction && h('p', { className: 'page-hero__lead' }, introduction))),
|
||||
photos.length > 0 && h('div', { className: 'container' },
|
||||
h('div', { className: photos.length > 1 ? 'page-figures' : undefined },
|
||||
photos.map(({ image, alt, caption }, index) => h('figure', { className: 'page-figure', key: index },
|
||||
h(PreviewImage, { key: image, asset: getAsset(image), fallback: image, alt: alt || '' }),
|
||||
caption && h('figcaption', null, caption))))),
|
||||
h('article', { className: photos.length ? 'container prose' : 'container prose prose--no-image' },
|
||||
widgetFor('body'),
|
||||
buttonLabel && buttonUrl && h('p', null,
|
||||
h('a', { className: 'btn btn--primary', href: buttonUrl },
|
||||
h('span', { className: 'btn__label' }, buttonLabel),
|
||||
h('span', { className: 'arrow', 'aria-hidden': 'true' }, '→')))));
|
||||
};
|
||||
const HomePreview = (props) => h(PagePreview, { ...props, home: true });
|
||||
if (window.CMS?.registerPreviewTemplate && h) {
|
||||
window.CMS.registerPreviewTemplate('home', HomePreview);
|
||||
for (const name of previewNames) window.CMS.registerPreviewTemplate(name, PagePreview);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,35 +1,16 @@
|
||||
---
|
||||
import { getCollection, render } from 'astro:content';
|
||||
import Base from '../../layouts/Base.astro';
|
||||
import PageHero from '../../components/PageHero.astro';
|
||||
import { getCollection } from 'astro:content';
|
||||
import ContentPage from '../../layouts/ContentPage.astro';
|
||||
import examples from '../../data/examples.json';
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const pages = await getCollection('pages');
|
||||
return examples.map(({ slug }) => {
|
||||
const page = pages.find(({ id }) => id === slug);
|
||||
if (!page) throw new Error(`Missing Example page: ${slug}. Run npm run content:setup.`);
|
||||
if (!page) throw new Error(`Missing Example page: ${slug}. Check the content checkout (npm run content:link -- <path>).`);
|
||||
return { params: { slug }, props: { page } };
|
||||
});
|
||||
}
|
||||
const { page } = Astro.props;
|
||||
const { Content } = await render(page);
|
||||
const { title, introduction, image, imageAlt, imageCaption, buttonLabel, buttonUrl } = page.data;
|
||||
---
|
||||
<Base title={title} description={introduction}>
|
||||
<PageHero title={title} introduction={introduction} example hasImage={Boolean(image)} />
|
||||
{image && <div class="container">
|
||||
<figure class="page-figure">
|
||||
<img src={image} alt={imageAlt || ''} />
|
||||
{imageCaption && <figcaption>{imageCaption}</figcaption>}
|
||||
</figure>
|
||||
</div>}
|
||||
<article class:list={['container', 'prose', { 'prose--no-image': !image }]}>
|
||||
<Content />
|
||||
{buttonLabel && buttonUrl && <p>
|
||||
<a class="btn btn--primary" href={buttonUrl}>
|
||||
<span class="btn__label">{buttonLabel}</span><span class="arrow" aria-hidden="true">→</span>
|
||||
</a>
|
||||
</p>}
|
||||
</article>
|
||||
</Base>
|
||||
<ContentPage page={page} example />
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
---
|
||||
import Placeholder from '../layouts/Placeholder.astro';
|
||||
import { getEntry } from 'astro:content';
|
||||
import ContentPage from '../layouts/ContentPage.astro';
|
||||
|
||||
const page = await getEntry('pages', 'home');
|
||||
if (!page) throw new Error('Missing Home page: pages/home.md. Check the content checkout (npm run content:link -- <path>).');
|
||||
---
|
||||
<Placeholder title="CTAO Science Portal" />
|
||||
<ContentPage page={page} breadcrumb={false} />
|
||||
|
||||
+136
-83
@@ -1,6 +1,8 @@
|
||||
/* ==========================================================================
|
||||
CTAO Science Portal: content page mockup
|
||||
Colours and type follow the CTAO Brand Guidelines (April 2024).
|
||||
The editor preview (public/admin/preview.css) is generated from the
|
||||
hero, prose and button sections below by scripts/preview-styles.mjs.
|
||||
========================================================================== */
|
||||
|
||||
/* Fonts
|
||||
@@ -49,9 +51,10 @@
|
||||
--gutter: clamp(1rem, 4vw, 2.5rem);
|
||||
--header-height: 7rem;
|
||||
--header-height-scrolled: 5rem;
|
||||
--radius-lg: 60px;
|
||||
--radius-md: 30px;
|
||||
--radius-lg: min(15vw, 180px);
|
||||
--radius-sm: 15px;
|
||||
/* How far photos are pulled up into the hero */
|
||||
--hero-overlap: clamp(6rem, 11.25vw, 9rem);
|
||||
/* Dropdown submenus (Example, language) */
|
||||
--radius-menu: 8px;
|
||||
--transition: 0.3s ease-in-out;
|
||||
@@ -194,17 +197,17 @@ button:hover .arrow {
|
||||
transition: background-color var(--transition);
|
||||
}
|
||||
|
||||
/* Solid once the page scrolls or a full-width panel is open */
|
||||
.site-header.is-scrolled,
|
||||
.site-header.is-open {
|
||||
background: var(--galaxy-blue);
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.site-header__inner {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 1.5rem;
|
||||
gap: clamp(0.5rem, 4vw, 1.5rem);
|
||||
width: min(100% - 2 * var(--gutter), var(--content-width));
|
||||
height: var(--header-height);
|
||||
margin-inline: auto;
|
||||
@@ -221,8 +224,8 @@ button:hover .arrow {
|
||||
}
|
||||
|
||||
.site-header__logo img {
|
||||
width: 153px;
|
||||
height: 44px;
|
||||
width: clamp(120px, 32vw, 153px);
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/* Submenus: one disclosure dropdown shared by Example and the language menu
|
||||
@@ -284,6 +287,19 @@ button:hover .arrow {
|
||||
color: var(--cherenkov-blue);
|
||||
}
|
||||
|
||||
.submenu a[aria-current="page"] {
|
||||
color: var(--cherenkov-blue);
|
||||
}
|
||||
|
||||
/* Languages without a translation yet */
|
||||
.submenu__unavailable {
|
||||
display: block;
|
||||
padding: 0.5rem 0.75rem;
|
||||
font-size: 0.9375rem;
|
||||
color: #b3b3c9;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/* Main nav
|
||||
========================================================================== */
|
||||
|
||||
@@ -321,6 +337,10 @@ button:hover .arrow {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.site-nav__link[aria-current="page"] {
|
||||
color: var(--cherenkov-blue);
|
||||
}
|
||||
|
||||
.site-nav__label {
|
||||
position: relative;
|
||||
}
|
||||
@@ -361,7 +381,7 @@ button:hover .arrow {
|
||||
display: flex;
|
||||
flex: 0 0 auto;
|
||||
align-items: center;
|
||||
gap: 0.625rem;
|
||||
gap: clamp(0.25rem, 1.5vw, 0.625rem);
|
||||
}
|
||||
|
||||
.pill {
|
||||
@@ -445,6 +465,7 @@ button:hover .arrow {
|
||||
|
||||
.search-panel__input {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
padding: 0.75rem 0;
|
||||
font: inherit;
|
||||
font-size: clamp(1.25rem, 3vw, 2rem);
|
||||
@@ -454,6 +475,11 @@ button:hover .arrow {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.search-panel__input:focus-visible {
|
||||
outline: 2px solid var(--cherenkov-blue);
|
||||
outline-offset: 4px;
|
||||
}
|
||||
|
||||
.search-panel__input::placeholder {
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
@@ -478,7 +504,7 @@ button:hover .arrow {
|
||||
}
|
||||
|
||||
.site-header:not(.is-open) {
|
||||
border-bottom-right-radius: var(--radius-md);
|
||||
border-bottom-right-radius: var(--radius-lg);
|
||||
}
|
||||
|
||||
.site-header__signin {
|
||||
@@ -555,43 +581,22 @@ button:hover .arrow {
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.site-header__logo img {
|
||||
width: 120px;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
/* Page hero
|
||||
========================================================================== */
|
||||
|
||||
@media (max-width: 359px) {
|
||||
.site-header__inner {
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.site-header__tools {
|
||||
gap: 0.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* Page hero ========================================================================== */
|
||||
.page-hero {
|
||||
--hero-veil: linear-gradient(
|
||||
90deg,
|
||||
rgba(0, 0, 74, 0.72) 0%,
|
||||
rgba(0, 0, 74, 0.45) 45%,
|
||||
rgba(0, 0, 74, 0) 75%
|
||||
);
|
||||
|
||||
margin-top: calc(-1 * var(--header-height));
|
||||
padding: calc(var(--header-height) + 3rem) 0 12rem;
|
||||
padding: calc(var(--header-height) + 3rem) 0 calc(var(--hero-overlap) + 3rem);
|
||||
color: var(--white);
|
||||
background:
|
||||
var(--grain),
|
||||
linear-gradient(180deg, rgba(0, 0, 74, 0.55) 0, rgba(0, 0, 74, 0) 10rem),
|
||||
var(--hero-veil),
|
||||
#00004a;
|
||||
background: var(--grain), var(--galaxy-blue);
|
||||
border-bottom-right-radius: var(--radius-lg);
|
||||
}
|
||||
|
||||
/* Pages without a photo: no room needed for the figure to overlap */
|
||||
.page-hero--compact {
|
||||
padding-bottom: 4rem;
|
||||
}
|
||||
|
||||
.breadcrumb ol {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
@@ -631,6 +636,7 @@ button:hover .arrow {
|
||||
line-height: 1.05;
|
||||
letter-spacing: -0.02em;
|
||||
text-wrap: balance;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.page-hero__lead {
|
||||
@@ -643,7 +649,7 @@ button:hover .arrow {
|
||||
|
||||
/* Photo pulled up over the hero; flat, no shadow */
|
||||
.page-figure {
|
||||
margin: -9rem 0 4rem;
|
||||
margin: calc(-1 * var(--hero-overlap)) 0 4rem;
|
||||
}
|
||||
|
||||
.page-figure img {
|
||||
@@ -657,11 +663,35 @@ button:hover .arrow {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
/* Two photos side by side (Home), pulled up over the hero together; they
|
||||
stack by themselves once each would be narrower than 18rem */
|
||||
.page-figures {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
|
||||
gap: 1.5rem;
|
||||
margin: calc(-1 * var(--hero-overlap)) 0 4rem;
|
||||
}
|
||||
|
||||
.page-figures .page-figure {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Same shape for both photos, whatever the uploads' proportions */
|
||||
.page-figures img {
|
||||
aspect-ratio: 3 / 2;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
/* Prose
|
||||
========================================================================== */
|
||||
|
||||
.prose {
|
||||
padding-bottom: 5rem;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.prose--no-image {
|
||||
padding-top: 4rem;
|
||||
}
|
||||
|
||||
.prose > * {
|
||||
@@ -708,6 +738,61 @@ button:hover .arrow {
|
||||
border-left: 4px solid var(--cherenkov-blue);
|
||||
}
|
||||
|
||||
.prose blockquote p {
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
.prose h3,
|
||||
.prose h4,
|
||||
.prose h5,
|
||||
.prose h6 {
|
||||
font-family: var(--font-head);
|
||||
color: var(--galaxy-blue);
|
||||
}
|
||||
|
||||
.prose li {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.prose img {
|
||||
border-radius: var(--radius-sm);
|
||||
}
|
||||
|
||||
.prose pre {
|
||||
padding: 1rem;
|
||||
overflow-x: auto;
|
||||
background: var(--moon-gray);
|
||||
}
|
||||
|
||||
.prose code {
|
||||
overflow-wrap: normal;
|
||||
}
|
||||
|
||||
.prose table {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.prose th,
|
||||
.prose td {
|
||||
padding: 0.75rem;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.prose hr {
|
||||
margin: 2rem 0;
|
||||
border: 0;
|
||||
border-top: 1px solid #ddd;
|
||||
}
|
||||
|
||||
/* Placeholder pages: empty body until their content exists */
|
||||
.placeholder-body {
|
||||
min-height: 12rem;
|
||||
}
|
||||
|
||||
/* Buttons
|
||||
========================================================================== */
|
||||
|
||||
@@ -751,6 +836,18 @@ button:hover .arrow {
|
||||
/* Footer
|
||||
========================================================================== */
|
||||
|
||||
/* Keep the footer at the bottom of short pages */
|
||||
body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
main {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.site-footer {
|
||||
margin-top: 2rem;
|
||||
padding: 3rem 0;
|
||||
@@ -791,27 +888,6 @@ button:hover .arrow {
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
|
||||
/* Responsive page
|
||||
========================================================================== */
|
||||
|
||||
@media (max-width: 800px) {
|
||||
/* Text spans the full width here, so keep at least 50% navy everywhere */
|
||||
.page-hero {
|
||||
--hero-veil: linear-gradient(
|
||||
90deg,
|
||||
rgba(0, 0, 74, 0.72) 0%,
|
||||
rgba(0, 0, 74, 0.5) 100%
|
||||
);
|
||||
|
||||
padding-bottom: 8rem;
|
||||
border-bottom-right-radius: var(--radius-md);
|
||||
}
|
||||
|
||||
.page-figure {
|
||||
margin-top: -6rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* Preferences
|
||||
========================================================================== */
|
||||
|
||||
@@ -830,26 +906,3 @@ button:hover .arrow {
|
||||
transition: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Page variants and Markdown elements. Preview styles derive from this file. */
|
||||
body { min-height: 100vh; display: flex; flex-direction: column; }
|
||||
main { flex: 1; min-width: 0; }
|
||||
.page-hero--compact { padding-bottom: 4rem; }
|
||||
.placeholder-body { min-height: 12rem; }
|
||||
.prose--no-image { padding-top: 4rem; }
|
||||
.prose { overflow-wrap: anywhere; }
|
||||
.prose h3, .prose h4, .prose h5, .prose h6 { color: var(--galaxy-blue); font-family: var(--font-head); }
|
||||
.prose li { margin-bottom: 0.5rem; }
|
||||
.prose blockquote p { font-size: inherit; line-height: inherit; }
|
||||
.prose pre { padding: 1rem; overflow-x: auto; background: var(--moon-gray); }
|
||||
.prose code { overflow-wrap: normal; }
|
||||
.prose table { display: block; overflow-x: auto; border-collapse: collapse; }
|
||||
.prose th, .prose td { padding: 0.75rem; border-bottom: 1px solid #ddd; text-align: left; }
|
||||
.prose hr { margin: 2rem 0; border: 0; border-top: 1px solid #ddd; }
|
||||
.prose img { border-radius: var(--radius-sm); }
|
||||
.submenu a[aria-current="page"], .site-nav__link[aria-current="page"] { color: var(--cherenkov-blue); }
|
||||
.submenu__unavailable { display: block; padding: 0.5rem 0.75rem; font-size: 0.9375rem; color: #b3b3c9; cursor: default; }
|
||||
.search-panel__input { min-width: 0; }
|
||||
.search-panel__input:focus-visible { outline: 2px solid var(--cherenkov-blue); outline-offset: 4px; }
|
||||
.page-hero__title { overflow-wrap: anywhere; }
|
||||
|
||||
Reference in New Issue
Block a user