@janga/norna 0.7.0 → 0.7.2

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.
Files changed (63) hide show
  1. package/README.md +18 -4
  2. package/astro.config.mjs +2 -0
  3. package/bin/norna-cli.mjs +170 -0
  4. package/bin/norna.mjs +149 -150
  5. package/docs/README.md +36 -16
  6. package/docs/commands.md +18 -5
  7. package/docs/configuration.md +37 -2
  8. package/docs/content.md +98 -257
  9. package/docs/{command-organization.md → design/command-organization.md} +9 -5
  10. package/docs/{site-examples-structure-note.md → design/site-examples-structure.md} +17 -22
  11. package/docs/engine-development.md +33 -5
  12. package/docs/getting-started.md +40 -4
  13. package/docs/local-development.md +13 -0
  14. package/docs/publishing.md +23 -0
  15. package/docs/routes.md +90 -0
  16. package/docs/site-structure.md +15 -8
  17. package/docs/theme.md +150 -0
  18. package/docs/typography.md +125 -0
  19. package/examples/dog-gallery/site/.norna/generated-images.json +226 -0
  20. package/examples/dog-gallery/site/config.mjs +97 -0
  21. package/examples/dog-gallery/site/content.md +146 -0
  22. package/examples/dog-gallery/site/images/black-dogs/black-puppy-meadow.png +0 -0
  23. package/examples/dog-gallery/site/images/black-dogs/photo-of-a-black-dog.jpg +0 -0
  24. package/examples/dog-gallery/site/images/brown-dogs/brown-dog.jpg +0 -0
  25. package/examples/dog-gallery/site/images/brown-dogs/dog-accompanies-master.jpg +0 -0
  26. package/examples/dog-gallery/site/images/golden-dogs/golden-retriever.jpg +0 -0
  27. package/examples/dog-gallery/site/images/golden-dogs/toller-puppy.jpg +0 -0
  28. package/examples/dog-gallery/site/images/white-dogs/white-cute-dog.jpg +0 -0
  29. package/examples/dog-gallery/site/images/white-dogs/white-puppy-garden.png +0 -0
  30. package/examples/dog-gallery/site/public/favicon.svg +7 -0
  31. package/examples/dog-gallery/site/public/robots.txt +2 -0
  32. package/examples/dog-gallery/site/routes/dog-care/route-content.md +35 -0
  33. package/examples/dog-gallery/site/theme.md +55 -0
  34. package/fixtures/basic/site/config.mjs +1 -0
  35. package/package.json +8 -7
  36. package/scripts/check-config.mjs +1 -0
  37. package/scripts/dev-local.mjs +64 -15
  38. package/scripts/init-site.mjs +1 -1
  39. package/scripts/lib/project-config.mjs +22 -0
  40. package/scripts/lib/site-content.mjs +2 -1
  41. package/scripts/lib/site-paths.mjs +18 -3
  42. package/scripts/lib/typography.mjs +5 -5
  43. package/scripts/show-typography.mjs +252 -29
  44. package/scripts/test-cli-discovery.mjs +124 -0
  45. package/scripts/test-engine-commands.mjs +18 -4
  46. package/scripts/test-navigation.mjs +10 -6
  47. package/scripts/test-package-check.mjs +32 -4
  48. package/src/components/SiteNavigation.astro +7 -5
  49. package/src/components/SitePage.astro +3 -0
  50. package/src/components/SiteSection.astro +24 -24
  51. package/src/content.config.ts +4 -0
  52. package/src/layouts/BaseLayout.astro +2 -1
  53. package/src/lib/basePath.ts +21 -0
  54. package/src/lib/generatedImages.ts +8 -4
  55. package/src/lib/sectionContent.ts +6 -1
  56. package/src/lib/sitePublicAssets.ts +8 -1
  57. package/src/styles/global.css +8 -8
  58. package/starters/basic/.github/workflows/deploy.yml +3 -3
  59. package/starters/basic/README.md +21 -0
  60. package/starters/basic/package.json +1 -1
  61. package/starters/basic/site/config.mjs +1 -0
  62. package/starters/basic/site/content.md +5 -3
  63. package/starters/basic/site/theme.md +4 -0
@@ -4,7 +4,8 @@ This document is for work on the reusable `norna` package itself.
4
4
 
5
5
  ## Main Areas
6
6
 
7
- - `bin/norna.mjs`: public CLI dispatcher.
7
+ - `bin/norna.mjs`: public CLI launcher and local-version resolver.
8
+ - `bin/norna-cli.mjs`: public CLI command dispatcher.
8
9
  - `scripts/lib/site-paths.mjs`: engine/site path resolution.
9
10
  - `scripts/lib/project-config.mjs`: `site/config.mjs` validation and defaults.
10
11
  - `scripts/sync-content-sections.mjs`: content validation and sync behavior.
@@ -18,9 +19,12 @@ This document is for work on the reusable `norna` package itself.
18
19
  - `tests/`: Playwright navigation diagnostics.
19
20
  - `fixtures/basic/site/`: minimal site used for engine checks.
20
21
  - `starters/basic/`: copyable site starter.
22
+ - `examples/dog-gallery/site/`: visual dog-gallery demo used by demo builds
23
+ and navigation diagnostics.
21
24
 
22
- The repository-local `site/` directory is a dog-gallery demo. It is useful for
23
- manual engine checks, but it is not a published site.
25
+ The repository-local `site/` directory is reserved for a local documentation
26
+ site. It is useful for dogfooding `norna` documentation, but it is not the
27
+ primary visual regression demo.
24
28
 
25
29
  ## Common Checks
26
30
 
@@ -34,7 +38,24 @@ npm run demo:build
34
38
  npm run package:check
35
39
  ```
36
40
 
37
- `npm run test` runs the same set in sequence.
41
+ `npm run test` runs the standard non-demo check sequence.
42
+
43
+ The root `site/` directory is the documentation site. Use the ordinary local
44
+ commands for it:
45
+
46
+ ```sh
47
+ npm run dev:local
48
+ npm run build
49
+ ```
50
+
51
+ The dog gallery remains the visual demo and navigation diagnostic target:
52
+
53
+ ```sh
54
+ cd examples/dog-gallery/site
55
+ node ../../../bin/norna.mjs dev:local
56
+ cd ../../..
57
+ npm run demo:build
58
+ ```
38
59
 
39
60
  Navigation diagnostics are separate because they use Playwright:
40
61
 
@@ -92,11 +113,18 @@ npm run norna:engine:update -- <version>
92
113
  Commit the resulting `package.json` and `package-lock.json` changes in the
93
114
  site repository after the site's normal checks pass.
94
115
 
116
+ The installed `norna` command is created from the package `bin` field. The
117
+ launcher first looks for the nearest project `package.json`. If that project
118
+ declares `@janga/norna` and Node can resolve an installed copy from that project
119
+ root, the launcher delegates to that local entrypoint. The engine repository
120
+ itself is excluded from delegation so local engine development keeps using the
121
+ working tree entrypoint.
122
+
95
123
  ## npm Release
96
124
 
97
125
  The npm package is published under the `@janga` scope. Choose the release type
98
126
  when starting a release; the command requires a clean working tree, verifies npm
99
- registry authentication for the same registry/cache used by `release:publish`,
127
+ registry authentication for the same registry/cache used by the publish step,
100
128
  runs `npm test`, requires a clean working tree after the checks, updates
101
129
  `package.json` and `package-lock.json`, creates the release commit and Git tag,
102
130
  publishes to npm, then pushes the commit and tag.
@@ -29,6 +29,11 @@ npm install
29
29
  npm run norna:dev
30
30
  ```
31
31
 
32
+ After `npm install`, the project's npm scripts use the project-local `norna`
33
+ binary from `node_modules/.bin`. A globally installed `norna` can also be used
34
+ as a convenience launcher; inside a project with an installed `@janga/norna`
35
+ dependency, it delegates to the project's local version.
36
+
32
37
  A freshly created empty directory is not a `norna` site yet. It becomes a
33
38
  site when `init` copies the starter files, including `package.json`. If you run
34
39
  `npm install` in an empty directory, npm may walk up to a parent directory and
@@ -75,7 +80,37 @@ npm run norna:check
75
80
  npm run build
76
81
  ```
77
82
 
78
- Read [Site Structure](site-structure.md), [Content](content.md), and
83
+ ## Configure The Public URL
84
+
85
+ For a custom domain or any site published at the web root, use:
86
+
87
+ ```js
88
+ site: {
89
+ url: 'https://example.com/',
90
+ basePath: '/',
91
+ }
92
+ ```
93
+
94
+ For a GitHub Pages project site without a custom domain, the site is served
95
+ under the repository name. Configure both values:
96
+
97
+ ```js
98
+ site: {
99
+ url: 'https://owner.github.io/repository-name/',
100
+ basePath: '/repository-name/',
101
+ }
102
+ ```
103
+
104
+ After that, content files may still use root-style internal links such as
105
+ `/getting-started/` and `/workflow.svg`. Norna applies `site.basePath` during
106
+ rendering so the built links work under the GitHub Pages project path.
107
+
108
+ The starter includes a GitHub Pages workflow in `.github/workflows/deploy.yml`.
109
+ In the GitHub repository settings, configure Pages to build from GitHub
110
+ Actions.
111
+
112
+ Read [Site Structure](site-structure.md), [Content](content.md),
113
+ [Theme](theme.md), [Typography](typography.md), [Routes](routes.md), and
79
114
  [Configuration](configuration.md) before publishing a real site.
80
115
 
81
116
  To change the site's maximum page width, set `layout.pageWidth` in
@@ -91,6 +126,7 @@ accepted format and default value.
91
126
 
92
127
  To change the site-wide typography preset, edit `site/theme.md`. To change one
93
128
  page or section, add a focused `presentation.typography` override in
94
- `site/content.md`. Use `npm run norna:typography:presets` to inspect the
95
- installed preset values and `npm run norna:typography:show` to inspect the
96
- resolved typography for the selected site.
129
+ `site/content.md`. See [Typography](typography.md). Use
130
+ `npm run norna:typography:presets` to inspect the installed preset values and
131
+ `npm run norna:typography:show` to inspect the resolved typography for the
132
+ selected site.
@@ -24,6 +24,19 @@ localhost:4321
24
24
  If the port is already in use, the command fails and asks you to stop the
25
25
  process using it.
26
26
 
27
+ To stop any process that is blocking the standard port before starting, pass
28
+ `--kill`:
29
+
30
+ ```sh
31
+ npm run norna:dev -- --kill
32
+ ```
33
+
34
+ For the pure starter's `dev` alias, use:
35
+
36
+ ```sh
37
+ npm run dev -- --kill
38
+ ```
39
+
27
40
  ## Test On A Phone
28
41
 
29
42
  To make the local dev server available to devices on the same Wi-Fi network:
@@ -25,6 +25,29 @@ workflow:
25
25
  Site-specific static files such as `site/public/CNAME`, `robots.txt`, and
26
26
  `sitemap.xml` belong in the site repository.
27
27
 
28
+ In the GitHub repository settings, set Pages to build from GitHub Actions. For
29
+ a project site without a custom domain, configure the site URL and base path in
30
+ `site/config.mjs`:
31
+
32
+ ```js
33
+ site: {
34
+ url: 'https://owner.github.io/repository-name/',
35
+ basePath: '/repository-name/',
36
+ }
37
+ ```
38
+
39
+ For a custom domain, keep `basePath` as `/`:
40
+
41
+ ```js
42
+ site: {
43
+ url: 'https://example.com/',
44
+ basePath: '/',
45
+ }
46
+ ```
47
+
48
+ Norna uses `site.basePath` for generated internal page links, favicons,
49
+ generated images, and root-relative links or images written in Markdown.
50
+
28
51
  ## Deploy An Already Committed Branch
29
52
 
30
53
  Use:
package/docs/routes.md ADDED
@@ -0,0 +1,90 @@
1
+ # Routes
2
+
3
+ `site/content.md` is the homepage and builds to `/`. Optional route pages live
4
+ under `site/routes/<route-folder>/route-content.md` and build to first-level
5
+ URLs.
6
+
7
+ Routes use the same page frontmatter, section frontmatter, gallery rows, and
8
+ Markdown section model as the homepage. See [Content](content.md) for the page
9
+ and section model.
10
+
11
+ ## Route File
12
+
13
+ Add a first-level route by creating:
14
+
15
+ ```text
16
+ site/routes/about/route-content.md
17
+ ```
18
+
19
+ Minimal route page:
20
+
21
+ ```md
22
+ ---
23
+ title: About
24
+ description: About this gallery.
25
+ navigation:
26
+ label: About
27
+ order: 20
28
+ sections:
29
+ - id: intro
30
+ ---
31
+
32
+ ## Intro {#intro}
33
+
34
+ Text...
35
+ ```
36
+
37
+ The example above builds to `/about/`.
38
+
39
+ ## Slug
40
+
41
+ If `slug` is omitted, the route folder name is used. If `slug` is set, it must
42
+ use lowercase letters, numbers, and hyphens.
43
+
44
+ ```yaml
45
+ slug: about-the-work
46
+ ```
47
+
48
+ Keep the route folder and `slug` aligned unless you intentionally need a
49
+ different URL.
50
+
51
+ The homepage ignores `slug`.
52
+
53
+ ## Navigation
54
+
55
+ `navigation` may contain:
56
+
57
+ - `include`: optional boolean. Defaults to `true`.
58
+ - `label`: optional string. Defaults to `title`.
59
+ - `order`: optional integer. Defaults to `0` for the homepage and `100` for
60
+ route pages.
61
+
62
+ Current route navigation is intended for small sites. This guidance may change
63
+ as route support matures, but the present model is:
64
+
65
+ - A single-page site should normally use only page navigation between sections.
66
+ - A small multi-page site may use site navigation between routes plus page
67
+ navigation between sections on the current page.
68
+ - If a site needs many routes, deeply nested routes, or several navigation
69
+ levels, it has probably outgrown the current sticky-navigation model and may
70
+ need a different site structure or navigation system.
71
+
72
+ ## Route Images
73
+
74
+ Route images live under the route:
75
+
76
+ ```text
77
+ site/routes/about/images/intro/image.jpg
78
+ ```
79
+
80
+ Image references in route frontmatter still use only the filename:
81
+
82
+ ```yaml
83
+ sections:
84
+ - id: intro
85
+ gallery:
86
+ - image: image.jpg
87
+ alt: "Intro image."
88
+ ```
89
+
90
+ The image directory segment after `images/` should match the section id.
@@ -26,8 +26,10 @@ site/
26
26
  ```
27
27
 
28
28
  Use `NORNA_SITE_DIR` or `norna --site-dir <path>` to select another
29
- site directory. Commands started from a subdirectory walk upward until they find
30
- the selected site directory containing both `config.mjs` and `content.md`.
29
+ site directory. Without an explicit site directory, commands first accept the
30
+ current directory when it contains both `config.mjs` and `content.md`.
31
+ Otherwise, commands started from a subdirectory walk upward until they find the
32
+ default `site/` directory containing those files.
31
33
  `theme.md` is optional; omit it to use the engine's built-in presentation
32
34
  defaults.
33
35
 
@@ -36,12 +38,13 @@ defaults.
36
38
  Version these files in a site repository:
37
39
 
38
40
  - `site/config.mjs`: technical site configuration.
39
- - `site/theme.md`: optional site-wide visual theme, inline styles, and frame
40
- defaults.
41
+ - `site/theme.md`: optional site-wide visual theme, inline styles, typography
42
+ defaults, and frame colors. See [Theme](theme.md).
41
43
  - `site/content.md`: homepage page file with editable content, section
42
- definitions, gallery rows, alt text, and captions.
44
+ definitions, gallery rows, alt text, and captions. See [Content](content.md).
43
45
  - `site/images/<section-id>/`: original source images.
44
46
  - `site/routes/<route-folder>/route-content.md`: optional route page files.
47
+ See [Routes](routes.md).
45
48
  - `site/routes/<route-folder>/images/<section-id>/`: original source images
46
49
  for that route page.
47
50
  - `site/public/`: site-specific static public files.
@@ -66,16 +69,20 @@ Do not edit these by hand:
66
69
 
67
70
  Favicons are convention-based. Put files such as `favicon.svg`, `favicon.ico`,
68
71
  `favicon.png`, or `apple-touch-icon.png` in `site/public/`. The renderer emits
69
- icon links only for files that exist.
72
+ icon links only for files that exist and prefixes them with `site.basePath`
73
+ when the site is published below a path such as `/repository-name/`.
70
74
 
71
75
  ## Engine Repository Layout
72
76
 
73
77
  In this repository:
74
78
 
75
- - `bin/norna.mjs` dispatches public CLI commands.
79
+ - `bin/norna.mjs` launches the appropriate installed Norna version.
80
+ - `bin/norna-cli.mjs` dispatches public CLI commands.
76
81
  - `scripts/` contains validation, image, local preview, deploy, and test tools.
77
82
  - `src/` contains the Astro renderer, components, styles, and content schema.
78
83
  - `starters/basic/` is copied by `norna init <target-dir>` to create a
79
84
  site repository.
80
85
  - `fixtures/basic/site/` is used by engine regression tests.
81
- - `site/` is the local dog-gallery demo used by default in this repository.
86
+ - `examples/dog-gallery/site/` is the local visual dog-gallery demo used by
87
+ demo builds and navigation diagnostics.
88
+ - `site/` is reserved for the local documentation site.
package/docs/theme.md ADDED
@@ -0,0 +1,150 @@
1
+ # Theme
2
+
3
+ `site/theme.md` defines optional site-wide visual defaults for a `norna` site.
4
+ It uses YAML frontmatter and does not need a Markdown body. If the file is
5
+ missing, built-in engine defaults are used.
6
+
7
+ Page-level presentation in `site/content.md` and route page files is always an
8
+ override on top of `site/theme.md`. Section-level presentation is an override
9
+ on top of the resolved page presentation.
10
+
11
+ ## Minimal Theme
12
+
13
+ ```yaml
14
+ ---
15
+ navigation:
16
+ brand: Example Gallery
17
+ presentation:
18
+ backgroundColor: "#000000"
19
+ textColor: "#f7f4ee"
20
+ typography:
21
+ preset: quiet-gallery
22
+ frame:
23
+ colors: presentation
24
+ ---
25
+ ```
26
+
27
+ Starter sites include a marked comment block such as
28
+ `norna:start theme-help` / `norna:end theme-help`. The block is only
29
+ explorable help text; YAML comments do not affect rendering. The active
30
+ configuration is the uncommented YAML below it.
31
+
32
+ ## Navigation
33
+
34
+ `navigation` is optional. It currently supports:
35
+
36
+ - `brand`: optional site-wide brand or home-link text shown in the site
37
+ navigation.
38
+
39
+ If `navigation.brand` is omitted, Norna uses the homepage `title` from
40
+ `site/content.md`. Use `navigation.brand` when the homepage title is editorial
41
+ or route-specific, but the navigation should keep a stable site name.
42
+
43
+ Example:
44
+
45
+ ```yaml
46
+ navigation:
47
+ brand: Norna
48
+ ```
49
+
50
+ ## Presentation
51
+
52
+ `presentation` is optional. It can contain:
53
+
54
+ - `backgroundColor`: optional quoted hex color in `#rgb`, `#rrggbb`, or
55
+ `#rrggbbaa` form.
56
+ - `textColor`: optional quoted hex color in `#rgb`, `#rrggbb`, or
57
+ `#rrggbbaa` form.
58
+ - `inlineStyles`: optional named inline text styles.
59
+ - `typography`: optional typography preset and overrides. See
60
+ [Typography](typography.md).
61
+
62
+ Example:
63
+
64
+ ```yaml
65
+ presentation:
66
+ backgroundColor: "#101418"
67
+ textColor: "#f4f1ea"
68
+ ```
69
+
70
+ ## Page And Section Overrides
71
+
72
+ Site-wide presentation belongs in `site/theme.md`. Page-level presentation in a
73
+ page file is always an override on top of the theme:
74
+
75
+ ```yaml
76
+ presentation:
77
+ typography:
78
+ overrides:
79
+ body:
80
+ paragraphSpacing: 1em
81
+ ```
82
+
83
+ Section-specific presentation belongs under `sections[].presentation`:
84
+
85
+ ```yaml
86
+ sections:
87
+ - id: intro
88
+ presentation:
89
+ backgroundColor: "#161616"
90
+ textColor: "#ffffff"
91
+ typography:
92
+ preset: statement
93
+ ```
94
+
95
+ If a page omits `presentation`, it uses the theme presentation unchanged. If a
96
+ section omits `presentation`, it uses the resolved page presentation.
97
+
98
+ Configured section backgrounds render as full-width horizontal bands while the
99
+ section content keeps the normal page and gallery widths. The top spacing
100
+ before the first heading, the spacing between sections, and the spacing after
101
+ the final section are part of the section background.
102
+
103
+ Configured section text colors apply to section headings, Markdown text,
104
+ Markdown subheadings, and gallery captions. Links keep the global accent color.
105
+
106
+ ## Frame Colors
107
+
108
+ `frame.colors` controls the sticky navigation and footer colors.
109
+
110
+ Allowed values:
111
+
112
+ - `presentation`: use the resolved presentation colors for this level.
113
+ - `theme`: use the site theme frame colors. This is useful in page-level
114
+ frontmatter.
115
+ - explicit colors:
116
+
117
+ ```yaml
118
+ frame:
119
+ colors:
120
+ backgroundColor: "#111111"
121
+ textColor: "#eeeeee"
122
+ ```
123
+
124
+ The sticky section navigation row and footer use the resolved frame colors, not
125
+ section-specific presentation.
126
+
127
+ ## Inline Styles
128
+
129
+ `presentation.inlineStyles` defines named inline text styles that can be used
130
+ from Markdown:
131
+
132
+ ```yaml
133
+ presentation:
134
+ inlineStyles:
135
+ highlight:
136
+ color: "#ffd84d"
137
+ ```
138
+
139
+ Inline style names must match `^[a-z][a-z0-9-]*$`. Each style currently
140
+ supports a required `color` field using the same quoted hex color format as
141
+ `textColor`.
142
+
143
+ Apply an inline style in Markdown with `[text]{.style-name}`:
144
+
145
+ ```md
146
+ This sentence contains [highlighted text]{.highlight}.
147
+ ```
148
+
149
+ `content:check` fails if Markdown uses an inline style that is not defined in
150
+ `site/theme.md` `presentation.inlineStyles`.
@@ -0,0 +1,125 @@
1
+ # Typography
2
+
3
+ `norna` typography is configured through presets with optional overrides. The
4
+ site font family itself is a technical setting in
5
+ [`typography.fontFamily`](configuration.md#typographyfontfamily).
6
+
7
+ The normal place to choose a site-wide typography preset is `site/theme.md`.
8
+ Page and section files may override the theme when a page or section needs a
9
+ different presentation.
10
+
11
+ ## Presets
12
+
13
+ Available presets:
14
+
15
+ - `quiet-gallery`: the default for image-led art and portfolio sites. Text is
16
+ restrained and supports the images without dominating the page.
17
+ - `compact-gallery`: tighter typography for many sections, many images, or
18
+ short information blocks.
19
+ - `text-forward`: more generous body text for pages where longer text carries
20
+ more of the experience.
21
+ - `statement`: stronger type for introductions, first sections, and short
22
+ programmatic statements. Use it sparingly, usually as a section override.
23
+
24
+ If theme typography is omitted, `quiet-gallery` is used.
25
+
26
+ Presets normally keep `heading.size` and `body.size` at `medium`. They differ
27
+ primarily through alignment, line height, paragraph spacing, caption treatment,
28
+ and intended use. Choose larger or smaller type with focused overrides when a
29
+ specific page or section needs it.
30
+
31
+ Use this command to inspect the exact preset values shipped with the installed
32
+ engine:
33
+
34
+ ```sh
35
+ npm run norna:typography:presets
36
+ ```
37
+
38
+ Use this command to inspect the effective values for the selected site after
39
+ presets and overrides have been applied:
40
+
41
+ ```sh
42
+ npm run norna:typography:show
43
+ ```
44
+
45
+ The output includes the site theme, every page route, and every section. Each
46
+ resolved value shows its `source`; values inherited by a page or section are
47
+ also marked with `inherited: true`.
48
+
49
+ ## Configuration Shape
50
+
51
+ ```yaml
52
+ presentation:
53
+ typography:
54
+ preset: quiet-gallery
55
+ overrides:
56
+ body:
57
+ paragraphSpacing: 0.8em
58
+ ```
59
+
60
+ The typographic roles are:
61
+
62
+ - `heading`: section headings.
63
+ - `body`: Markdown body text inside sections.
64
+ - `caption`: gallery captions.
65
+
66
+ Allowed alignment values are `left`, `center`, and `right`. Alignment can be
67
+ responsive:
68
+
69
+ ```yaml
70
+ align:
71
+ desktop: left
72
+ mobile: center
73
+ ```
74
+
75
+ Allowed size values are `small`, `medium`, `large`, and `xlarge`. `medium` is
76
+ the normal reading size. Use `small` for quieter supporting text, and use
77
+ `large` or `xlarge` only when a page or section needs stronger emphasis.
78
+ Headings use their own scale, but follow the same principle: `medium` is the
79
+ normal section heading size, not a hero size.
80
+
81
+ `lineHeight` is a unitless number from `1` through `3`. `spacing` and
82
+ `paragraphSpacing` are CSS lengths such as `0`, `0.8em`, `1rem`, or `12px`.
83
+
84
+ Supported override fields:
85
+
86
+ - `heading.align`, `heading.size`, `heading.lineHeight`, `heading.spacing`
87
+ - `body.align`, `body.size`, `body.lineHeight`, `body.paragraphSpacing`
88
+ - `caption.align`, `caption.size`, `caption.lineHeight`, `caption.spacing`
89
+
90
+ ## Inheritance
91
+
92
+ Theme typography is the site-wide base:
93
+
94
+ ```yaml
95
+ # site/theme.md
96
+ presentation:
97
+ typography:
98
+ preset: quiet-gallery
99
+ ```
100
+
101
+ A page-level `presentation.typography.preset` changes the typographic base for
102
+ that page. A section-level `sections[].presentation.typography.preset` changes
103
+ the typographic base for that section.
104
+
105
+ If a section sets `typography.preset`, that section starts from that preset. If
106
+ a section only sets `typography.overrides`, it keeps the resolved page preset
107
+ and changes only the specified values.
108
+
109
+ Example section override:
110
+
111
+ ```yaml
112
+ sections:
113
+ - id: intro
114
+ presentation:
115
+ typography:
116
+ preset: statement
117
+ overrides:
118
+ body:
119
+ paragraphSpacing: 0.7em
120
+ ```
121
+
122
+ Centered text uses narrower text widths. Left- or right-aligned heading and body
123
+ text use the calculated gallery layout width so text edges line up with gallery
124
+ images after layout gutters and gallery limits are applied. Gallery captions
125
+ are normally centered.