Pre-PMTools
This commit is contained in:
@@ -32,6 +32,7 @@
|
||||
"@types/node": "^22.20.4",
|
||||
"@types/react": "^19.2.18",
|
||||
"@types/react-dom": "^19.2.4",
|
||||
"autoprefixer": "^10.6.1",
|
||||
"eslint": "^10.11.0",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-astro": "^3.2.1",
|
||||
|
||||
24
pnpm-lock.yaml
generated
24
pnpm-lock.yaml
generated
@@ -66,6 +66,9 @@ importers:
|
||||
'@types/react-dom':
|
||||
specifier: ^19.2.4
|
||||
version: 19.3.0(@types/react@19.3.0)
|
||||
autoprefixer:
|
||||
specifier: ^10.6.1
|
||||
version: 10.6.1(postcss@8.5.28)
|
||||
eslint:
|
||||
specifier: ^10.11.0
|
||||
version: 10.11.0
|
||||
@@ -1470,6 +1473,13 @@ packages:
|
||||
'@astrojs/markdown-remark':
|
||||
optional: true
|
||||
|
||||
autoprefixer@10.6.1:
|
||||
resolution: {integrity: sha512-cL1Qz6ADZhcEbny/8HPfe99J6HhNoYtpX2LFLIbhgGE7Q1hlQVkYFdetDN7Id3KiQxhDrHwzlHr/YQCnZ8+xSA==}
|
||||
engines: {node: ^10 || ^12 || >=14}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
postcss: ^8.1.0
|
||||
|
||||
axobject-query@4.1.0:
|
||||
resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -1949,6 +1959,9 @@ packages:
|
||||
resolution: {integrity: sha512-Wp1zXWPVUPBmfoa3Cqc9ctaKuzKAV6uLstRqlR56kSjplf5uAce+qeyYym7F+PHbGTk+tCEdkCW6RD7DX/gBZw==}
|
||||
engines: {node: '>=20'}
|
||||
|
||||
fraction.js@5.3.4:
|
||||
resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==}
|
||||
|
||||
fresh@2.0.0:
|
||||
resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==}
|
||||
engines: {node: '>= 0.8'}
|
||||
@@ -4994,6 +5007,15 @@ snapshots:
|
||||
- uploadthing
|
||||
- yaml
|
||||
|
||||
autoprefixer@10.6.1(postcss@8.5.28):
|
||||
dependencies:
|
||||
browserslist: 4.29.0
|
||||
caniuse-lite: 1.0.30001810
|
||||
fraction.js: 5.3.4
|
||||
picocolors: 1.1.1
|
||||
postcss: 8.5.28
|
||||
postcss-value-parser: 4.2.0
|
||||
|
||||
axobject-query@4.1.0: {}
|
||||
|
||||
bail@2.0.2: {}
|
||||
@@ -5448,6 +5470,8 @@ snapshots:
|
||||
dependencies:
|
||||
tiny-inflate: 1.0.3
|
||||
|
||||
fraction.js@5.3.4: {}
|
||||
|
||||
fresh@2.0.0: {}
|
||||
|
||||
fsevents@2.3.3:
|
||||
|
||||
@@ -7,5 +7,6 @@ export default {
|
||||
files: ['./src/styles/base/custom-media.css'],
|
||||
},
|
||||
'postcss-custom-media': {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 329 KiB |
BIN
src/assets/content/articles/pm-world/summary/cover/image.jpg
Normal file
BIN
src/assets/content/articles/pm-world/summary/cover/image.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 577 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 3.4 MiB |
BIN
src/assets/content/articles/stages/summary/cover/image.jpg
Normal file
BIN
src/assets/content/articles/stages/summary/cover/image.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.0 MiB |
BIN
src/assets/content/articles/the-crucible/summary/cover/image.jpg
Normal file
BIN
src/assets/content/articles/the-crucible/summary/cover/image.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.2 MiB |
BIN
src/assets/content/articles/tincture/summary/cover/image.jpg
Normal file
BIN
src/assets/content/articles/tincture/summary/cover/image.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 MiB |
@@ -7,9 +7,10 @@ type Props = {
|
||||
term: string
|
||||
kind?: TermKind
|
||||
see?: string
|
||||
ink?: boolean
|
||||
}
|
||||
|
||||
const { term, kind = 'entry', see = '' } = Astro.props
|
||||
const { term, kind = 'entry', see = '', ink = false } = Astro.props
|
||||
|
||||
const links: SeeLink[] = see
|
||||
.split(',')
|
||||
@@ -18,6 +19,6 @@ const links: SeeLink[] = see
|
||||
.map((name) => ({ title: name, href: `#${slugify(name)}` }))
|
||||
---
|
||||
|
||||
<TermEntry id={slugify(term)} title={term} kind={kind} see={links} ink>
|
||||
<TermEntry id={slugify(term)} title={term} kind={kind} see={links} ink={ink}>
|
||||
<slot />
|
||||
</TermEntry>
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
<dl class="terms terms--cross">
|
||||
---
|
||||
import type { DefinitionVariant } from '@/lib/constants/blocks/definitions'
|
||||
|
||||
type Props = {
|
||||
variant?: DefinitionVariant
|
||||
}
|
||||
|
||||
const { variant = 'cross' } = Astro.props
|
||||
---
|
||||
|
||||
<dl class:list={['terms', `terms--${variant}`]}>
|
||||
<slot />
|
||||
</dl>
|
||||
|
||||
@@ -10,6 +10,8 @@ const { variant = 'default', caption } = Astro.props
|
||||
---
|
||||
|
||||
<figure class:list={['table-wrapper', `table-wrapper--${variant}`]}>
|
||||
<div class="table-scroll" tabindex="0" role="region" aria-label={caption ?? 'Table'}>
|
||||
<slot />
|
||||
</div>
|
||||
{caption && <figcaption>{caption}</figcaption>}
|
||||
</figure>
|
||||
|
||||
@@ -25,9 +25,7 @@ const label = TERM_KINDS.find((option) => option.value === kind)?.label ?? kind
|
||||
</dt>
|
||||
|
||||
<dd class="term__body">
|
||||
<p class="term__definition">
|
||||
<slot />
|
||||
</p>
|
||||
|
||||
{see.length > 0 && (
|
||||
<p class="term__see">
|
||||
|
||||
140
src/content/general/articles/alchemical-materialism.mdoc
Normal file
140
src/content/general/articles/alchemical-materialism.mdoc
Normal file
@@ -0,0 +1,140 @@
|
||||
---
|
||||
title: Alchemical Materialism
|
||||
subtitle: The grammar of the Crucible
|
||||
status: published
|
||||
noindex: false
|
||||
stage: stub
|
||||
route:
|
||||
parent: the-crucible
|
||||
index: 1
|
||||
sequence: false
|
||||
summary:
|
||||
excerpt: Three Primes, five Essences, one engine.
|
||||
cover:
|
||||
image: >-
|
||||
/src/assets/content/articles/alchemical-materialism/summary/cover/image.jpg
|
||||
alt: >-
|
||||
A night valley lit by a roaring furnace; orange flames and smoke fill the
|
||||
sky above dark buildings, and small figures and horses in the foreground
|
||||
are dwarfed by the blaze.
|
||||
caption: Coalbrookdale by Night
|
||||
credit: Philip James de Loutherbourg
|
||||
effect: none
|
||||
ratio: 21-9
|
||||
published: 2026-09-30T20:41:00.000Z
|
||||
tags:
|
||||
- alchemical-materialism
|
||||
- the-crucible
|
||||
---
|
||||
## Overview
|
||||
|
||||
- shared grammar of all seven stages
|
||||
- **Primes =>** *Soul, Body, Spirit;* forces in tension
|
||||
- **Essences =>** *Aether, Air, Earth, Fire, Water;* surplus regimes
|
||||
- **Engine =>** baseline, degrees, signatures → *Materia*
|
||||
|
||||
## The Engine
|
||||
|
||||
- **Token =>** one *Prime* or one *Essence;* the unit of *Materia*
|
||||
- **Baseline =>** stage default; no deviations, no tokens
|
||||
- **Degree =>** structured; steps along fixed axes
|
||||
- **Signature =>** freeform; declared limitations; taboos, weaknesses, obligations, anomalies; yields tokens
|
||||
- **Materia =>** combined tokens from *degrees & signatures;* the pool is the entity's identity
|
||||
- **Spending =>** tokens buy the stage's traits, capabilities, relationships
|
||||
- **Leftovers =>** unspent tokens flow downstream
|
||||
|
||||
## The Elements
|
||||
|
||||
### The Three Primes
|
||||
|
||||
- Three alchemical principles: something **burns** *(Sulphur),* something **remains** *(Salt),* something **transforms** *(Mercury)*
|
||||
- Every entity holds all three; dominance sets character
|
||||
- **Interdependence:**
|
||||
- No **Soul =>** nothing starts
|
||||
- No **Body =>** nothing hols
|
||||
- No **Spirit =>** nothing changes
|
||||
|
||||
{% tableWrapper
|
||||
variant="default"
|
||||
caption="The three Primes - Overview"
|
||||
columns=["rowheader", "default", "default", "default", "default", "default"] %}
|
||||
{% table %}
|
||||
- Prime
|
||||
- Alchemical
|
||||
- Core
|
||||
- Keyword
|
||||
- Organization
|
||||
- Failure
|
||||
---
|
||||
- Soul
|
||||
- Sulfur
|
||||
- Agency; the spark
|
||||
- »I burn«
|
||||
- Individual excellence
|
||||
- Consumed everything
|
||||
---
|
||||
- Body
|
||||
- Salt
|
||||
- Structure; the form
|
||||
- »It endures«
|
||||
- Institutional strength
|
||||
- Calcifies everything
|
||||
---
|
||||
- Spirit
|
||||
- Mercury
|
||||
- Transformation; the flux
|
||||
- »Nothing stays«
|
||||
- Adaptive innovation
|
||||
- Dissolves everything
|
||||
{% /table %}
|
||||
{% /tableWrapper %}
|
||||
|
||||
### The Five Essences
|
||||
|
||||
- **Regime =>** what a surplus enables; mechanical reading
|
||||
- **Symbolic =>** resonance; myth, faith, flavour
|
||||
- **Lenses =>** each stage reads essences through its own lens; core fixed, expression varies
|
||||
- **Assignment =>** ask what a surplus enables; never assign by physical association
|
||||
|
||||
{% tableWrapper
|
||||
variant="default"
|
||||
caption="The Five Essences"
|
||||
columns=["rowheader", "default", "default", "default", "default"] %}
|
||||
{% table %}
|
||||
- Essence
|
||||
- Regime
|
||||
- Qualities
|
||||
- Properties
|
||||
- Image
|
||||
---
|
||||
- Aether
|
||||
- Given away
|
||||
- Quintessence
|
||||
- Transcendent, ordered, numinous
|
||||
- The Stars
|
||||
---
|
||||
- Air
|
||||
- Governs & administers
|
||||
- Hot & Wet
|
||||
- Pervasive, overarching, commanding
|
||||
- The Sky
|
||||
---
|
||||
- Earth
|
||||
- Accumulates
|
||||
- Cold & Dry
|
||||
- Heavy, material, foundational
|
||||
- The Mountain
|
||||
---
|
||||
- Fire
|
||||
- Spent in violence
|
||||
- Hot & Dry
|
||||
- Bright, consuming, refining
|
||||
- The Volcano
|
||||
---
|
||||
- Water
|
||||
- Travels & trades
|
||||
- Cold & Wet
|
||||
- Flowing, deep, dissolving
|
||||
- The River
|
||||
{% /table %}
|
||||
{% /tableWrapper %}
|
||||
14
src/content/general/articles/meta.mdoc
Normal file
14
src/content/general/articles/meta.mdoc
Normal file
@@ -0,0 +1,14 @@
|
||||
---
|
||||
title: The Metatron
|
||||
status: draft
|
||||
noindex: false
|
||||
stage: stub
|
||||
route:
|
||||
sequence: false
|
||||
summary:
|
||||
cover:
|
||||
effect: none
|
||||
ratio: original
|
||||
published: 2026-10-12T14:30:00.000Z
|
||||
tags: []
|
||||
---
|
||||
341
src/content/general/articles/pm-area.mdoc
Normal file
341
src/content/general/articles/pm-area.mdoc
Normal file
@@ -0,0 +1,341 @@
|
||||
---
|
||||
title: Area
|
||||
status: draft
|
||||
noindex: false
|
||||
stage: stub
|
||||
route:
|
||||
segment: area
|
||||
parent: prima-materia
|
||||
index: 2
|
||||
sequence: false
|
||||
summary:
|
||||
cover:
|
||||
effect: none
|
||||
ratio: original
|
||||
published: 2026-10-07T13:38:00.000Z
|
||||
tags:
|
||||
- the-crucible
|
||||
- genesis
|
||||
- prima-materia
|
||||
---
|
||||
## Overview
|
||||
|
||||
An area is one hex of the World map; it reads from it and rolls its own moisture, terrain, and anomaly; every Region inside starts from what the area sets.
|
||||
|
||||
{% definitions variant="compact" %}
|
||||
{% definition term="Elevation" kind="entry" %}
|
||||
How high the Area stands: Lowland, Upland, or Montane. It is determined by the distance to the ranges
|
||||
{% /definition %}
|
||||
|
||||
{% definition term="Band" kind="entry" %}
|
||||
The Area's temperature, from Arctic to Tropical
|
||||
{% /definition %}
|
||||
|
||||
{% definition term="Current" kind="entry" %}
|
||||
Warm or cold water along a coastal area
|
||||
{% /definition %}
|
||||
|
||||
{% definition term="Moisture" kind="entry" %}
|
||||
How much rain the area gets: Arid, Moderate, or Wet
|
||||
{% /definition %}
|
||||
|
||||
{% definition term="Anomaly" kind="entry" %}
|
||||
A local strangeness confined to one area
|
||||
{% /definition %}
|
||||
|
||||
{% definition term="Terrain" kind="entry" %}
|
||||
What shaped the Area's ground: Glacial, Plateau, Alluvial, Dissection, Karst or none
|
||||
{% /definition %}
|
||||
|
||||
{% definition term="Lake" kind="entry" %}
|
||||
Standing water on the ground
|
||||
{% /definition %}
|
||||
|
||||
{% definition term="Salt Basin" kind="entry" %}
|
||||
Salt water or salt crust where a lake has no outflow in dry country: a salt lake like the Dead Sea, or a dry salt pan.
|
||||
{% /definition %}
|
||||
{% /definitions %}
|
||||
|
||||
### Procedure
|
||||
|
||||
1. Roll the anomaly
|
||||
1. Read the elevation
|
||||
1. Read the band and current
|
||||
1. Roll the moisture
|
||||
1. Read or roll the terrain
|
||||
1. Read the lakes
|
||||
|
||||
## Anomalies
|
||||
|
||||
Area Anomalies are locale strangeness, rarer the less warped the world is. Only land areas roll them. Roll `2d6` against the {% xref reference="pm-world" anchor="warp" %}Anomaly Target{% /xref %}. On a hit, roll `1d36` (for non-costal areas: `1d26`) or simply choose – re-roll any Anomalies with effects that contradict or simply have no effect.
|
||||
|
||||
**Reach =>** an anomaly covers one Area and changes every read of the values it names inside it
|
||||
|
||||
**Timing =>** Each effect applies at the step that sets its value. A set replaces what its step would roll.
|
||||
|
||||
**Map Facts =>** Drawn rivers and coasts stay; the anomaly only changes what passed through them
|
||||
|
||||
{% tableWrapper
|
||||
variant="default"
|
||||
caption="Random Table – World Anomalies"
|
||||
columns=["num", "rowheader", "default", "default"] %}
|
||||
{% table %}
|
||||
- d36
|
||||
- Anomaly
|
||||
- Description
|
||||
- Effect
|
||||
---
|
||||
- **11**
|
||||
- Upthrust
|
||||
- Raised ground far from any range
|
||||
- `elevation +1`
|
||||
---
|
||||
- **12**
|
||||
- Sunken Basin
|
||||
- Ground dropped below its surroundings
|
||||
- `elevation -1`
|
||||
---
|
||||
- **13**
|
||||
- Verdant
|
||||
- Unnaturally lush growth
|
||||
- `cover = Forest`
|
||||
---
|
||||
- **14**
|
||||
- Glassed
|
||||
- Ground fused to Glass
|
||||
- `cover = Barren`
|
||||
---
|
||||
- **15**
|
||||
- Sinkland
|
||||
- Sinkholes and caves
|
||||
- `terrain = Karst`
|
||||
---
|
||||
- **16**
|
||||
- Wellspring
|
||||
- Springs rising from the ground
|
||||
- `1d3` lakes
|
||||
---
|
||||
- **21**
|
||||
- Thunderhead
|
||||
- Violent wet season
|
||||
- `moisture = Wet`
|
||||
---
|
||||
- **22**
|
||||
- Searing Wind
|
||||
- A hot dry wind that never stops
|
||||
- `moisture = Arid`
|
||||
---
|
||||
- **23**
|
||||
- Wind-scoured
|
||||
- Wind-stripped country
|
||||
- `Wind level = 4`
|
||||
---
|
||||
- **24**
|
||||
- Dead Calm
|
||||
- Air that never moves
|
||||
- `Wind level = 0`
|
||||
---
|
||||
- **25**
|
||||
- Pall
|
||||
- Permanent overcast
|
||||
- `band -1`
|
||||
---
|
||||
- **26**
|
||||
- Kiln
|
||||
- Ground warm from below
|
||||
- `band +1`
|
||||
---
|
||||
- **31**
|
||||
- Drowned Coast
|
||||
- Sunken coast; marsh and shallow
|
||||
- `coastal drainage -2`
|
||||
---
|
||||
- **32**
|
||||
- Skerries
|
||||
- A coast broken into rocky islets
|
||||
- `coastal drainage +2`
|
||||
---
|
||||
- **33**
|
||||
- Upwelling
|
||||
- Cold, rich water rising at the coast
|
||||
- `current = cold`
|
||||
---
|
||||
- **34**
|
||||
- Warm Drift
|
||||
- Warm water running along the coast
|
||||
- `current = warm`
|
||||
---
|
||||
- **35**
|
||||
- Banks
|
||||
- Wide, shallow shelf offshore
|
||||
- Shelf reaches 3 areas from land
|
||||
---
|
||||
- **36**
|
||||
- Abyssal Shore
|
||||
- Deep water at the shoreline
|
||||
- no Shelf; Deep starts at the coast
|
||||
{% /table %}
|
||||
{% /tableWrapper %}
|
||||
|
||||
## Elevation
|
||||
|
||||
1. Count the distance in Areas to each range within 3 Areas
|
||||
1. Read each range's column, and take the highest result
|
||||
|
||||
{% tableWrapper
|
||||
variant="default"
|
||||
columns=["rowheader", "key", "key", "key", "key"] %}
|
||||
{% table %}
|
||||
- Range
|
||||
- 0
|
||||
- 1
|
||||
- 2
|
||||
- 3+
|
||||
---
|
||||
- High
|
||||
- Montane
|
||||
- Montane
|
||||
- Upland
|
||||
- Lowland
|
||||
---
|
||||
- Medium
|
||||
- Montane
|
||||
- Upland
|
||||
- Lowland
|
||||
- Lowland
|
||||
---
|
||||
- Low
|
||||
- Upland
|
||||
- Lowland
|
||||
- Lowland
|
||||
- Lowland
|
||||
---
|
||||
- Rift
|
||||
- Lowland
|
||||
- Upland
|
||||
- Lowland
|
||||
- Lowland
|
||||
---
|
||||
- Hotspot
|
||||
- Montane
|
||||
- Lowland
|
||||
- Lowland
|
||||
- Lowland
|
||||
{% /table %}
|
||||
{% /tableWrapper %}
|
||||
|
||||
## Band and Current
|
||||
|
||||
The Area takes its band from the World map. A coastal Area also takes a current from its band's prevailing wind.
|
||||
|
||||
1. Take the band from the World map
|
||||
1. A coastal Area facing open sea takes a current, unless its Wind level is 0. A windward coast has a warm current: `band +1`. A leeward coast has a cold current: `band −1`. An Area with both takes the warm current.
|
||||
|
||||
**Open Sea =>** Ocean or Deep within 2 Areas of the coast
|
||||
|
||||
## Moisture
|
||||
|
||||
1. Roll `2d6`, and add the {% xref reference="pm-world" anchor="water" %}Water{% /xref %} moisture and the belt shift: a wet belt adds, a dry belt subtracts, and Wind level sets how much. A neutral belt adds nothing.
|
||||
|
||||
{% tableWrapper
|
||||
variant="default"
|
||||
caption="Belt Shift"
|
||||
columns=["rowheader", "num", "num", "num"] %}
|
||||
{% table %}
|
||||
- Wind level
|
||||
- 0
|
||||
- 1–2
|
||||
- 3–4
|
||||
---
|
||||
- Wet belt
|
||||
- 0
|
||||
- `+1`
|
||||
- `+1`
|
||||
---
|
||||
- Dry belt
|
||||
- 0
|
||||
- `-1`
|
||||
- `-2`
|
||||
{% /table %}
|
||||
{% /tableWrapper %}
|
||||
|
||||
{% tableWrapper
|
||||
variant="default"
|
||||
caption="Moisture"
|
||||
columns=["rowheader", "key", "key", "key"] %}
|
||||
{% table %}
|
||||
- Total
|
||||
- ≤5
|
||||
- 6–9
|
||||
- 10+
|
||||
---
|
||||
- Moisture
|
||||
- Arid
|
||||
- Moderate
|
||||
- Wet
|
||||
{% /table %}
|
||||
{% /tableWrapper %}
|
||||
|
||||
**Fogbound =>** a coastal Area with a cold current that reads Arid is Fogbound: `cover +1`
|
||||
|
||||
**Salt-Flat =>** A lake in an Arid Area reads Salt-flat
|
||||
|
||||
## Terrain
|
||||
|
||||
Read the first terrain whose condition the Area meets, top to bottom. If none applies, the Area has no terrain.
|
||||
|
||||
{% tableWrapper variant="default" columns=["rowheader", "default", "key"] %}
|
||||
{% table %}
|
||||
- Terrain
|
||||
- Description
|
||||
- Condition
|
||||
---
|
||||
- Glacial
|
||||
- ice-scoured ground
|
||||
- `band = Arctic | Subarctic || elevation = Montane`
|
||||
---
|
||||
- Plateau
|
||||
- high, flat ground
|
||||
- `elevation = Upland && origin = Uplift | Rift`
|
||||
---
|
||||
- Alluvial
|
||||
- river-laid soil
|
||||
- `elevation = Lowland && has river`
|
||||
---
|
||||
- Dissection
|
||||
- dry ground cut by gullies
|
||||
- `moisture = Arid`
|
||||
---
|
||||
- Karst
|
||||
- limestone dissolved into caves
|
||||
- `elevation = Lowland && origin = Uplift`
|
||||
{% /table %}
|
||||
{% /tableWrapper %}
|
||||
|
||||
**Scoured =>** On a {% xref reference="pm-world" anchor="world-anomalies" %}Scoured{% /xref %} world, Temperate Areas also read Glacial.
|
||||
|
||||
## Lakes
|
||||
|
||||
1. Read the Area's lakes: where a river cannot reach the sea, on a Rift floor, and from anomalies
|
||||
1. A river crossing the Area rolls `1d6`. On a `6`, or `5–6` where `terrain = Glacial`, it widens into a lake and flows on
|
||||
1. A lake without an outflow in an Area with `moisture = Arid` reads Salt Basin, unless its spring-fed.
|
||||
1. Read each lake's size from the river that feeds or flows through it
|
||||
|
||||
{% tableWrapper
|
||||
variant="default"
|
||||
caption="Lake Size"
|
||||
columns=["rowheader", "key", "key", "key", "key"] %}
|
||||
{% table %}
|
||||
- River Tier
|
||||
- River
|
||||
- Major River
|
||||
- Grand River
|
||||
- no River
|
||||
---
|
||||
- Lake Size
|
||||
- Tract
|
||||
- Region
|
||||
- Area
|
||||
- Tract
|
||||
{% /table %}
|
||||
{% /tableWrapper %}
|
||||
549
src/content/general/articles/pm-locality.mdoc
Normal file
549
src/content/general/articles/pm-locality.mdoc
Normal file
@@ -0,0 +1,549 @@
|
||||
---
|
||||
title: Locality
|
||||
status: draft
|
||||
noindex: false
|
||||
stage: stub
|
||||
route:
|
||||
segment: locality
|
||||
parent: prima-materia
|
||||
index: 5
|
||||
sequence: false
|
||||
summary:
|
||||
cover:
|
||||
effect: none
|
||||
ratio: original
|
||||
published: 2026-10-07T15:27:00.000Z
|
||||
tags:
|
||||
- the-crucible
|
||||
- genesis
|
||||
- prima-materia
|
||||
---
|
||||
## Overview
|
||||
|
||||
Every locality starts from its tract, rolls its own cover, and may hold a landform and a resource.
|
||||
|
||||
{% definitions variant="compact" %}
|
||||
{% definition term="Position" kind="entry" %}
|
||||
Where the Locality lies against water: Floor, Shore or Flank
|
||||
{% /definition %}
|
||||
|
||||
{% definition term="Landform" kind="entry" %}
|
||||
A small physical feature of the Locality's ground, such as a meander, a headland, or a spur
|
||||
{% /definition %}
|
||||
|
||||
{% definition term="Resource" kind="entry" %}
|
||||
Something the Locality is exceptional for: a deposit, a wild population, or ground ideally suited to it.
|
||||
{% /definition %}
|
||||
{% /definitions %}
|
||||
|
||||
### Procedure
|
||||
|
||||
1. Place the Tract's features
|
||||
1. Read the position
|
||||
1. Roll the cover
|
||||
1. Roll the landform
|
||||
1. Roll the resource
|
||||
|
||||
## Placing
|
||||
|
||||
1. Draw each river and headwaters through the Tract, and mark the localities they cross
|
||||
1. Mark the Localities on a coast or a lake
|
||||
1. Put a volcano in the centre Locality.
|
||||
1. Put a landmark on a fitting Locality: a river landmark on a river, a coast landmark on the coast, any other anywhere
|
||||
|
||||
## Position
|
||||
|
||||
Read the position from what you marked; from left to right – a Locality takes the first position that fits
|
||||
|
||||
{% tableWrapper
|
||||
variant="default"
|
||||
columns=["rowheader", "key", "key", "key"] %}
|
||||
{% table %}
|
||||
- Position
|
||||
- Shore
|
||||
- Floor
|
||||
- Flank
|
||||
---
|
||||
- Clause
|
||||
- on a coast or a lake
|
||||
- a river or headwaters crosses it
|
||||
- anywhere else
|
||||
{% /table %}
|
||||
{% /tableWrapper %}
|
||||
|
||||
## Cover
|
||||
|
||||
1. Take the Tract's cover
|
||||
1. Roll `1d6` for the Locality's deviation
|
||||
|
||||
{% tableWrapper
|
||||
variant="default"
|
||||
caption="Random Table – Cover Deviation"
|
||||
columns=["rowheader", "key", "key", "key"] %}
|
||||
{% table %}
|
||||
- 1d6
|
||||
- 1
|
||||
- 2–5
|
||||
- 6
|
||||
---
|
||||
- Cover
|
||||
- one step toward Barren
|
||||
- –
|
||||
- one step toward Forest
|
||||
{% /table %}
|
||||
{% /tableWrapper %}
|
||||
|
||||
## Landform
|
||||
|
||||
Roll `1d6` on the position's column
|
||||
|
||||
{% tableWrapper
|
||||
variant="default"
|
||||
caption="Random Table - Landform"
|
||||
columns=["num", "key", "key", "key"] %}
|
||||
{% table %}
|
||||
- 1d6
|
||||
- Floor
|
||||
- Shore
|
||||
- Flank
|
||||
---
|
||||
- 1–2
|
||||
- –
|
||||
- –
|
||||
- –
|
||||
---
|
||||
- 3
|
||||
- Terrace
|
||||
- Beach
|
||||
- Bench
|
||||
---
|
||||
- 4
|
||||
- Meander
|
||||
- Bay
|
||||
- Hollow
|
||||
---
|
||||
- 5
|
||||
- Confluence
|
||||
- Headland
|
||||
- Spur
|
||||
---
|
||||
- 6
|
||||
- River Island
|
||||
- Islet
|
||||
- Knoll
|
||||
{% /table %}
|
||||
{% /tableWrapper %}
|
||||
|
||||
## Resources
|
||||
|
||||
1. Roll `2d6`, plus `1d6` for each that applies: `fertility = Rich`; volcanic; a landform
|
||||
1. Count the sixes: one gives a Common resource, two an Uncommon resource, three or more a Rare
|
||||
1. Pick a random among the resources of that tier whose gate the locality passes.
|
||||
|
||||
{% tableWrapper
|
||||
variant="default"
|
||||
caption="Random Table – Cover Deviation"
|
||||
columns=["rowheader", "key", "key", "key", "key"] %}
|
||||
{% table %}
|
||||
- Sixes
|
||||
- 0
|
||||
- 1
|
||||
- 2
|
||||
- 3+
|
||||
---
|
||||
- Resource
|
||||
- –
|
||||
- Common
|
||||
- Uncommon
|
||||
- Rare
|
||||
{% /table %}
|
||||
{% /tableWrapper %}
|
||||
|
||||
**Step down =>** With no resource of that tier eligible, take the next tier down.
|
||||
|
||||
{% tableWrapper
|
||||
variant="default"
|
||||
caption="Resource List"
|
||||
columns=["rowheader", "default", "default", "key"] %}
|
||||
{% table %}
|
||||
- Resource
|
||||
- Gate
|
||||
- Bar
|
||||
- Tier
|
||||
---
|
||||
- Alchemical Earths
|
||||
- `terrain = Karst | Dissection || volcanic || lake = Salt Basin`
|
||||
- `cover = Forest`
|
||||
- Common
|
||||
---
|
||||
- Base Metals
|
||||
- `drainage = Broken`
|
||||
-
|
||||
- Common
|
||||
---
|
||||
- Cattle
|
||||
- `cover = Grassland | Woodland && elevation ≠ Montane`
|
||||
- `band = Arctic`
|
||||
- Common
|
||||
---
|
||||
- Clay
|
||||
- `position = Floor | Shore || drainage = Sodden`
|
||||
- `elevation = Montane`
|
||||
- Common
|
||||
---
|
||||
- Dates
|
||||
- `moisture = Arid && band = Subtropical | Tropical`
|
||||
-
|
||||
- Common
|
||||
---
|
||||
- Dye Plants
|
||||
- `cover = Grassland | Woodland && fertility ≠ Poor`
|
||||
- `band = Arctic`
|
||||
- Common
|
||||
---
|
||||
- Fish
|
||||
- `coastal || riverine || lake = fresh`
|
||||
-
|
||||
- Common
|
||||
---
|
||||
- Flax
|
||||
- `elevation = Lowland && drainage = Shed`
|
||||
- `band = Arctic`
|
||||
- Common
|
||||
---
|
||||
- Fruits
|
||||
- `cover = Woodland && drainage = Shed`
|
||||
- `band = Arctic`
|
||||
- Common
|
||||
---
|
||||
- Grapes
|
||||
- `drainage = Shed | Broken && band = Temperate | Subtropical`
|
||||
-
|
||||
- Common
|
||||
---
|
||||
- Hardwoods
|
||||
- `cover = Woodland | Forest && band = Temperate | Subtropical | Tropical`
|
||||
-
|
||||
- Common
|
||||
---
|
||||
- Hardy Grains
|
||||
- `cover = Scrub | Grassland && band = Subarctic | Temperate`
|
||||
- `elevation = Montane`
|
||||
- Common
|
||||
---
|
||||
- Hemp
|
||||
- `cover = Grassland | Woodland && drainage = Shed | Sodden`
|
||||
- `band = Arctic`
|
||||
- Common
|
||||
---
|
||||
- Herbs
|
||||
- `cover = Scrub | Woodland`
|
||||
-
|
||||
- Common
|
||||
---
|
||||
- Honey
|
||||
- `cover ≠ Barren && band = Subarctic | Temperate | Subtropical`
|
||||
-
|
||||
- Common
|
||||
---
|
||||
- Horses
|
||||
- `cover = Grassland && drainage = Shed`
|
||||
-
|
||||
- Common
|
||||
---
|
||||
- Kelp
|
||||
- `coastal && band = Arctic | Subarctic | Temperate`
|
||||
- `world_anomaly = Dead Seas`
|
||||
- Common
|
||||
---
|
||||
- Ochre
|
||||
- `drainage = Broken && moisture ≠ Wet`
|
||||
- `cover = Forest`
|
||||
- Common
|
||||
---
|
||||
- Oilseeds
|
||||
- `cover = Grassland | Woodland && drainage = Shed`
|
||||
- `band = Arctic`
|
||||
- Common
|
||||
---
|
||||
- Olives
|
||||
- `climate = Mediterranean | Semiarid && drainage = Shed | Broken`
|
||||
- `elevation = Montane`
|
||||
- Common
|
||||
---
|
||||
- Peat
|
||||
- `drainage = Sodden && band = Arctic | Subarctic | Temperate`
|
||||
- `cover = Barren`
|
||||
- Common
|
||||
---
|
||||
- Psychoactives
|
||||
- `cover = Woodland | Forest`
|
||||
-
|
||||
- Common
|
||||
---
|
||||
- Reeds
|
||||
- `drainage = Sodden || position = Floor`
|
||||
- `cover = Barren`
|
||||
- Common
|
||||
---
|
||||
- Rice
|
||||
- `drainage = Sodden && band = Temperate | Subtropical | Tropical`
|
||||
-
|
||||
- Common
|
||||
---
|
||||
- Salt
|
||||
- `lake = Salt Basin || coastal || terrain = Karst`
|
||||
- `moisture = Wet`
|
||||
- Common
|
||||
---
|
||||
- Seals
|
||||
- `coastal && band = Arctic | Subarctic`
|
||||
- `world_anomaly = Dead Seas`
|
||||
- Common
|
||||
---
|
||||
- Semiprecious Stone
|
||||
- `drainage = Broken || terrain = Karst`
|
||||
-
|
||||
- Common
|
||||
---
|
||||
- Sheep/Goats
|
||||
- `cover = Scrub | Grassland`
|
||||
- `drainage = Sodden`
|
||||
- Common
|
||||
---
|
||||
- Shellfish
|
||||
- `position = Shore`
|
||||
- `band = Arctic || (world_anomaly = Dead Seas && coastal)`
|
||||
- Common
|
||||
---
|
||||
- Smallstock
|
||||
- `cover = Woodland | Forest && elevation ≠ Montane`
|
||||
-
|
||||
- Common
|
||||
---
|
||||
- Softwoods
|
||||
- `cover = Woodland | Forest && band = Subarctic | Temperate`
|
||||
-
|
||||
- Common
|
||||
---
|
||||
- Special Lifestock
|
||||
- `moisture = Arid || elevation = Montane`
|
||||
- `cover = Forest`
|
||||
- Common
|
||||
---
|
||||
- Staple Grains
|
||||
- `cover = Grassland && fertility ≠ Poor`
|
||||
- `band = Arctic`
|
||||
- Common
|
||||
---
|
||||
- Stone
|
||||
- `drainage = Broken || elevation = Montane`
|
||||
-
|
||||
- Common
|
||||
---
|
||||
- Wild Game
|
||||
- `cover = Grassland | Woodland | Forest`
|
||||
-
|
||||
- Common
|
||||
---
|
||||
- Alum
|
||||
- `volcanic || terrain = Karst`
|
||||
- `drainage = Sodden`
|
||||
- Uncommon
|
||||
---
|
||||
- Amber
|
||||
- `coastal && band = Subarctic | Temperate`
|
||||
-
|
||||
- Uncommon
|
||||
---
|
||||
- Bitumen
|
||||
- `terrain = Dissection || lake = Salt Basin`
|
||||
- `cover = Forest`
|
||||
- Uncommon
|
||||
---
|
||||
- Cedar
|
||||
- `cover = Woodland | Forest && climate = Mediterranean | Semiarid`
|
||||
-
|
||||
- Uncommon
|
||||
---
|
||||
- Citrus
|
||||
- `climate = Mediterranean | Sultry && drainage = Shed`
|
||||
-
|
||||
- Uncommon
|
||||
---
|
||||
- Cochineal
|
||||
- `cover = Scrub && band = Subtropical | Tropical`
|
||||
-
|
||||
- Uncommon
|
||||
---
|
||||
- Cotton
|
||||
- `drainage = Shed && band = Subtropical | Tropical`
|
||||
-
|
||||
- Uncommon
|
||||
---
|
||||
- Iron
|
||||
- `drainage = Broken | Sodden`
|
||||
-
|
||||
- Uncommon
|
||||
---
|
||||
- Jade
|
||||
- `origin = Suture && riverine`
|
||||
-
|
||||
- Uncommon
|
||||
---
|
||||
- Lacquer
|
||||
- `cover = Woodland | Forest && moisture = Wet && band = Temperate | Subtropical`
|
||||
-
|
||||
- Uncommon
|
||||
---
|
||||
- Marble
|
||||
- `origin = Suture && drainage = Broken`
|
||||
-
|
||||
- Uncommon
|
||||
---
|
||||
- Obsidian
|
||||
- `volcanic && drainage = Broken`
|
||||
-
|
||||
- Uncommon
|
||||
---
|
||||
- Pelts
|
||||
- `cover = Woodland | Forest && band = Arctic | Subarctic`
|
||||
-
|
||||
- Uncommon
|
||||
---
|
||||
- Poppy
|
||||
- `cover = Grassland && band = Subtropical`
|
||||
-
|
||||
- Uncommon
|
||||
---
|
||||
- Saffron
|
||||
- `climate = Semiarid | Continental && drainage = Shed`
|
||||
-
|
||||
- Uncommon
|
||||
---
|
||||
- Silver
|
||||
- `drainage = Broken && elevation = Upland | Montane`
|
||||
-
|
||||
- Uncommon
|
||||
---
|
||||
- Spices
|
||||
- `cover = Woodland | Forest && band = Tropical`
|
||||
-
|
||||
- Uncommon
|
||||
---
|
||||
- Stibnite
|
||||
- `origin = Arc | Transform && drainage = Broken`
|
||||
-
|
||||
- Uncommon
|
||||
---
|
||||
- Sugar
|
||||
- `riverine && elevation = Lowland && band = Subtropical | Tropical`
|
||||
-
|
||||
- Uncommon
|
||||
---
|
||||
- Sulfur
|
||||
- `volcanic || lake = Salt Basin`
|
||||
- `drainage = Sodden`
|
||||
- Uncommon
|
||||
---
|
||||
- Tea
|
||||
- `elevation = Upland && moisture = Wet`
|
||||
-
|
||||
- Uncommon
|
||||
---
|
||||
- Turtles
|
||||
- `position = Shore && band = Subtropical | Tropical`
|
||||
-
|
||||
- Uncommon
|
||||
---
|
||||
- Whales
|
||||
- `open sea && current = cold`
|
||||
- `world_anomaly = Dead Seas`
|
||||
- Uncommon
|
||||
---
|
||||
- White Sand
|
||||
- `landform = Beach || cover = Barren`
|
||||
- `drainage = Sodden`
|
||||
- Uncommon
|
||||
---
|
||||
- Yew
|
||||
- `cover = Woodland | Forest && elevation = Upland | Montane && band = Subarctic | Temperate`
|
||||
-
|
||||
- Uncommon
|
||||
---
|
||||
- Aromatics
|
||||
- `climate = Desert | Hot Steppe && cover = Scrub`
|
||||
-
|
||||
- Rare
|
||||
---
|
||||
- Asbestos
|
||||
- `origin = Suture && elevation = Upland | Montane`
|
||||
-
|
||||
- Rare
|
||||
---
|
||||
- Behemoth
|
||||
- `climate = Savanna | Monsoon && fertility = Rich`
|
||||
-
|
||||
- Rare
|
||||
---
|
||||
- Cinnabar
|
||||
- `volcanic && elevation = Upland | Montane`
|
||||
-
|
||||
- Rare
|
||||
---
|
||||
- Coal
|
||||
- `origin = Uplift && drainage = Broken`
|
||||
-
|
||||
- Rare
|
||||
---
|
||||
- Gold
|
||||
- `origin = Arc | Island Arc && riverine`
|
||||
-
|
||||
- Rare
|
||||
---
|
||||
- Kaolin
|
||||
- `elevation = Upland && landform = Hollow`
|
||||
-
|
||||
- Rare
|
||||
---
|
||||
- Lapis
|
||||
- `elevation = Montane && landform = Spur`
|
||||
-
|
||||
- Rare
|
||||
---
|
||||
- Lotus
|
||||
- `drainage = Sodden && band = Subtropical | Tropical`
|
||||
-
|
||||
- Rare
|
||||
---
|
||||
- Murex
|
||||
- `position = Shore && band = Subtropical`
|
||||
- `world_anomaly = Dead Seas`
|
||||
- Rare
|
||||
---
|
||||
- Nitre
|
||||
- `moisture = Arid && terrain = Karst | Dissection`
|
||||
-
|
||||
- Rare
|
||||
---
|
||||
- Pozzolana
|
||||
- `volcano = Cone | Shield | Fissure`
|
||||
-
|
||||
- Rare
|
||||
---
|
||||
- Precious Stone
|
||||
- `volcanic && riverine`
|
||||
-
|
||||
- Rare
|
||||
---
|
||||
- Silk
|
||||
- `cover = Woodland && fertility = Rich && band = Temperate | Subtropical`
|
||||
-
|
||||
- Rare
|
||||
---
|
||||
- Silphium
|
||||
- `cover = Scrub && climate = Mediterranean`
|
||||
-
|
||||
- Rare
|
||||
{% /table %}
|
||||
{% /tableWrapper %}
|
||||
304
src/content/general/articles/pm-region.mdoc
Normal file
304
src/content/general/articles/pm-region.mdoc
Normal file
@@ -0,0 +1,304 @@
|
||||
---
|
||||
title: Region
|
||||
status: draft
|
||||
noindex: false
|
||||
stage: stub
|
||||
route:
|
||||
segment: region
|
||||
parent: prima-materia
|
||||
index: 3
|
||||
sequence: false
|
||||
summary:
|
||||
cover:
|
||||
effect: none
|
||||
ratio: original
|
||||
published: 2026-10-07T15:27:00.000Z
|
||||
tags:
|
||||
- the-crucible
|
||||
- genesis
|
||||
- prima-materia
|
||||
---
|
||||
## Overview
|
||||
|
||||
Every Region starts from its Area and rolls its own gradient, moisture and cover.
|
||||
|
||||
{% definitions variant="compact" %}
|
||||
{% definition term="Gradient" kind="entry" %}
|
||||
How steep the Region's ground is, on the scale Gentle → Moderate → Steep.
|
||||
{% /definition %}
|
||||
|
||||
{% definition term="Moisture" kind="entry" %}
|
||||
How much rain the Region gets, on the scale Arid → Moderate → Wet.
|
||||
{% /definition %}
|
||||
|
||||
{% definition term="Climate" kind="entry" %}
|
||||
The Region's climate, one of 15, from Icecap to Monsoon
|
||||
{% /definition %}
|
||||
|
||||
{% definition term="Drainage" kind="entry" %}
|
||||
What happens to water on the Region's ground, on the scale Sodden → Shed → Broken: it stands, runs off, or cuts the ground apart.
|
||||
{% /definition %}
|
||||
|
||||
{% definition term="Cover" kind="entry" %}
|
||||
What grows on the Region's ground, on the scale Barren → Scrub → Grassland → Woodland → Forest.
|
||||
{% /definition %}
|
||||
|
||||
{% definition term="Mouth" kind="entry" %}
|
||||
The landform where a river meets the sea: Delta, Estuary, Ria, or Fjord.
|
||||
{% /definition %}
|
||||
{% /definitions %}
|
||||
|
||||
**Lakes =>** Place the Area's lakes as {% xref reference="pm-area" anchor="lakes" %}Area: Lakes{% /xref %} says. A Region filled by a lake has no ground; skip its steps.
|
||||
|
||||
### Procedure
|
||||
|
||||
1. Roll the gradient
|
||||
1. Roll the moisture
|
||||
1. Read the climate
|
||||
1. Read the drainage
|
||||
1. Roll the Cover
|
||||
|
||||
## Gradient
|
||||
|
||||
1. Read the first gradient whose condition the Area meets, top to bottom.
|
||||
1. Roll `1d6` for the Region's deviation.
|
||||
|
||||
{% tableWrapper variant="default" columns=["rowheader", "text"] %}
|
||||
{% table %}
|
||||
- Gradient
|
||||
- Condition
|
||||
---
|
||||
- Steep
|
||||
- `elevation = Montane || terrain = Glacial`
|
||||
---
|
||||
- Gentle
|
||||
- `terrain = Plateau`
|
||||
---
|
||||
- Moderate
|
||||
- `terrain = Dissection | Karst || elevation = Upland`
|
||||
{% /table %}
|
||||
{% /tableWrapper %}
|
||||
|
||||
If none of these Conditions apply, the Gradient is Gentle.
|
||||
|
||||
{% tableWrapper
|
||||
variant="default"
|
||||
caption="Gradient Deviation"
|
||||
columns=["rowheader", "key", "key", "key"] %}
|
||||
{% table %}
|
||||
- 1d6
|
||||
- 1
|
||||
- 2–5
|
||||
- 6
|
||||
---
|
||||
- Gradient
|
||||
- one step gentler
|
||||
- –
|
||||
- one step steeper
|
||||
{% /table %}
|
||||
{% /tableWrapper %}
|
||||
|
||||
## Moisture
|
||||
|
||||
1. Take the Area's Moisture
|
||||
1. Roll `1d6` for the Region's deviation
|
||||
1. Shift for the Region's position: a Region in the lee of a range is drier, a Region on a windward coast is wetter.
|
||||
|
||||
{% tableWrapper
|
||||
variant="default"
|
||||
caption="Moisture Deviation"
|
||||
columns=["rowheader", "key", "key", "key"] %}
|
||||
{% table %}
|
||||
- 1d6
|
||||
- 1
|
||||
- 2–5
|
||||
- 6
|
||||
---
|
||||
- Moisture
|
||||
- one step drier
|
||||
- –
|
||||
- one step wetter
|
||||
{% /table %}
|
||||
{% /tableWrapper %}
|
||||
|
||||
{% tableWrapper
|
||||
variant="default"
|
||||
caption="Position"
|
||||
columns=["rowheader", "key", "key", "key"] %}
|
||||
{% table %}
|
||||
- Wind Level
|
||||
- 0
|
||||
- 1–2
|
||||
- 3–4
|
||||
---
|
||||
- Lee
|
||||
- –
|
||||
- `moisture -1`
|
||||
- `moisture -2`
|
||||
---
|
||||
- Windward coast
|
||||
- –
|
||||
- `moisture +1`
|
||||
- `moisture +2`
|
||||
{% /table %}
|
||||
{% /tableWrapper %}
|
||||
|
||||
**Lee =>** A region is in the lee when Montane ground lies upwind of it within 2 Regions
|
||||
|
||||
## Climate
|
||||
|
||||
Read the Region's band against its moisture. A Montane Region reads its band one step colder.
|
||||
|
||||
{% tableWrapper
|
||||
variant="default"
|
||||
columns=["rowheader", "key", "key", "key"] %}
|
||||
{% table %}
|
||||
- Band
|
||||
- Arid
|
||||
- Moderate
|
||||
- Wet
|
||||
---
|
||||
- Arctic
|
||||
- Icecap
|
||||
- Permafrost
|
||||
- Polar
|
||||
---
|
||||
- Subarctic
|
||||
- Cold Steppe
|
||||
- Boreal
|
||||
- Subpolar
|
||||
---
|
||||
- Temperate
|
||||
- Semiarid
|
||||
- Continental
|
||||
- Oceanic
|
||||
---
|
||||
- Subtropical
|
||||
- Desert
|
||||
- Mediterranean
|
||||
- Sultry
|
||||
---
|
||||
- Tropical
|
||||
- Hot Steppe
|
||||
- Savanna
|
||||
- Monsoon
|
||||
{% /table %}
|
||||
{% /tableWrapper %}
|
||||
|
||||
## Drainage
|
||||
|
||||
1. Read the gradient against the moisture
|
||||
1. For a coastal region, apply `coastal drainage`.
|
||||
|
||||
{% tableWrapper
|
||||
variant="default"
|
||||
columns=["rowheader", "key", "key", "key"] %}
|
||||
{% table %}
|
||||
- Gradient
|
||||
- Arid
|
||||
- Moderate
|
||||
- Wet
|
||||
---
|
||||
- Steep
|
||||
- Broken
|
||||
- Broken
|
||||
- Broken
|
||||
---
|
||||
- Moderate
|
||||
- Broken
|
||||
- Shed
|
||||
- Shed
|
||||
---
|
||||
- Gentle
|
||||
- Shed
|
||||
- Shed
|
||||
- Sodden
|
||||
{% /table %}
|
||||
{% /tableWrapper %}
|
||||
|
||||
**Mouths =>** Where a river meets the sea, its mouth is named by the Region's drainage: Sodden a Delta, Shed an Estuary, Broken a Ria. Broken ground with `terrain = Glacial` makes Fjord instead.
|
||||
|
||||
## Cover
|
||||
|
||||
1. Roll `2d6`, and add the modifiers for the Region's moisture, band, and drainage. A Montane Region uses the colder band it read for climate.
|
||||
1. Read the total
|
||||
|
||||
{% tableWrapper
|
||||
variant="default"
|
||||
caption="Cover Modifiers - Moisture"
|
||||
columns=["rowheader", "num", "num", "num"] %}
|
||||
{% table %}
|
||||
- Moisture
|
||||
- Arid
|
||||
- Moderate
|
||||
- Wet
|
||||
---
|
||||
- Modifier
|
||||
- `-2`
|
||||
- –
|
||||
- `+2`
|
||||
{% /table %}
|
||||
{% /tableWrapper %}
|
||||
|
||||
{% tableWrapper
|
||||
variant="default"
|
||||
caption="Cover Modifiers – Band"
|
||||
columns=["rowheader", "num", "num", "num", "num", "num"] %}
|
||||
{% table %}
|
||||
- Band
|
||||
- Arctic
|
||||
- Subarctic
|
||||
- Temperate
|
||||
- Subtropical
|
||||
- Tropical
|
||||
---
|
||||
- Modifier
|
||||
- `-3`
|
||||
- –
|
||||
- –
|
||||
- `-1`
|
||||
- `+1`
|
||||
{% /table %}
|
||||
{% /tableWrapper %}
|
||||
|
||||
{% tableWrapper
|
||||
variant="default"
|
||||
caption="Cover Modifiers – Drainage"
|
||||
columns=["rowheader", "num", "num", "num"] %}
|
||||
{% table %}
|
||||
- Drainage
|
||||
- Sodden
|
||||
- Shed
|
||||
- Broken
|
||||
---
|
||||
- Modifier
|
||||
- `+1`
|
||||
- –
|
||||
- `-1`
|
||||
{% /table %}
|
||||
{% /tableWrapper %}
|
||||
|
||||
{% tableWrapper
|
||||
variant="default"
|
||||
caption="Cover"
|
||||
columns=["rowheader", "key", "key", "key", "key", "key"] %}
|
||||
{% table %}
|
||||
- Total
|
||||
- ≤3
|
||||
- 4–5
|
||||
- 6–7
|
||||
- 8–9
|
||||
- 10+
|
||||
---
|
||||
- Cover
|
||||
- Barren
|
||||
- Scrub
|
||||
- Grassland
|
||||
- Woodland
|
||||
- Forest
|
||||
{% /table %}
|
||||
{% /tableWrapper %}
|
||||
|
||||
**Arctic =>** An Arctic Region reads Grassland at most
|
||||
|
||||
**Anomalies =>** An anomaly that sets cover, replaces the roll; {% xref reference="pm-area" anchor="anomalies" %}Fogbound{% /xref %} adds `+1` to it
|
||||
348
src/content/general/articles/pm-tract.mdoc
Normal file
348
src/content/general/articles/pm-tract.mdoc
Normal file
@@ -0,0 +1,348 @@
|
||||
---
|
||||
title: Tract
|
||||
status: draft
|
||||
noindex: false
|
||||
stage: stub
|
||||
route:
|
||||
segment: tract
|
||||
parent: prima-materia
|
||||
index: 4
|
||||
sequence: false
|
||||
summary:
|
||||
cover:
|
||||
effect: none
|
||||
ratio: original
|
||||
published: 2026-10-07T15:27:00.000Z
|
||||
tags:
|
||||
- the-crucible
|
||||
- genesis
|
||||
- prima-materia
|
||||
---
|
||||
## Overview
|
||||
|
||||
Every Tract starts from its Region and rolls its own relief, fertility, headwaters and landmark.
|
||||
|
||||
{% definitions variant="compact" %}
|
||||
{% definition term="Fertility" kind="entry" %}
|
||||
How rich the Tract's soil is, on the scale Poor → Fair → Rich
|
||||
{% /definition %}
|
||||
|
||||
{% definition term="Headwaters" kind="entry" see="Riverine" %}
|
||||
Small water that rises in a Tract and runs downhill, below the size of a River
|
||||
{% /definition %}
|
||||
|
||||
{% definition term="Riverine" kind="entry" see="Headwaters" %}
|
||||
Crossed by a river or headwaters
|
||||
{% /definition %}
|
||||
|
||||
{% definition term="Volcanic" kind="entry" see="Volcano" %}
|
||||
Holding volcanoes or volcanic ground
|
||||
{% /definition %}
|
||||
|
||||
{% definition term="Volcano" kind="entry" see="volcanic" %}
|
||||
A single volcanic feature: a Cone, Shield, or Fissure
|
||||
{% /definition %}
|
||||
|
||||
{% definition term="Landmark" kind="entry" %}
|
||||
One notable feature of the Tract's ground, water or coast
|
||||
{% /definition %}
|
||||
|
||||
{% definition term="Crossable" kind="entry" %}
|
||||
Open to travel: on foot across ground and rivers, by landing from a sea on a coast
|
||||
{% /definition %}
|
||||
{% /definitions %}
|
||||
|
||||
### Procedure
|
||||
|
||||
1. Roll for landmark
|
||||
1. Roll for volcano
|
||||
1. Roll the relief
|
||||
1. Roll the headwaters
|
||||
1. Roll the fertility
|
||||
1. Read the cover
|
||||
|
||||
## Landmark
|
||||
|
||||
Roll `1d6`. On a `6`, the Tract has a landmark: roll `1d36`; a non-coastal Tract rolls `1d26`; re-roll any Landmarks that fail the gate.
|
||||
|
||||
**Timing =>** Each effect applies at the step that sets its value; lakes, crossings, and coast effects apply at once. A set replaces what its step would read or roll.
|
||||
|
||||
{% tableWrapper
|
||||
variant="default"
|
||||
caption="Random Table – World Anomalies"
|
||||
columns=["num", "rowheader", "default", "key", "default"] %}
|
||||
{% table %}
|
||||
- d36
|
||||
- Landmark
|
||||
- Description
|
||||
- Gate
|
||||
- Effect
|
||||
---
|
||||
- **11**
|
||||
- Fen
|
||||
- Waterlogged Ground
|
||||
- –
|
||||
- `drainage = Sodden`
|
||||
---
|
||||
- **12**
|
||||
- Gullies
|
||||
- Ground cut into channels
|
||||
- –
|
||||
- `drainage = Broken`
|
||||
---
|
||||
- **13**
|
||||
- Loam
|
||||
- Deep, dark soil
|
||||
- –
|
||||
- `fertility = Rich`
|
||||
---
|
||||
- **14**
|
||||
- Scree
|
||||
- Loose stone over thin soil
|
||||
- –
|
||||
- `fertility = Poor`
|
||||
---
|
||||
- **15**
|
||||
- Caverns
|
||||
- A cave passage beneath the land
|
||||
- `terrain = Karst` or volcanic
|
||||
- every barrier in the Tract crossable underground
|
||||
---
|
||||
- **16**
|
||||
- Scarp
|
||||
- A long cliff across the land
|
||||
- –
|
||||
- Uncrossable
|
||||
---
|
||||
- **21**
|
||||
- Spring
|
||||
- Water rising from the ground
|
||||
- –
|
||||
- headwaters rise here
|
||||
---
|
||||
- **22**
|
||||
- Swallow-hole
|
||||
- A shaft that takes the water
|
||||
- –
|
||||
- no headwaters rise here
|
||||
---
|
||||
- **23**
|
||||
- Mere
|
||||
- Standing water
|
||||
- –
|
||||
- a lake
|
||||
---
|
||||
- **24**
|
||||
- Dry Lake
|
||||
- A lakebed without water
|
||||
- –
|
||||
- a Salt Basin
|
||||
---
|
||||
- **25**
|
||||
- Ford
|
||||
- Shallows across the river
|
||||
- a river
|
||||
- river crossable
|
||||
---
|
||||
- **26**
|
||||
- Gorge
|
||||
- The river cut deep into rock
|
||||
- a river
|
||||
- river uncrossable
|
||||
---
|
||||
- **31**
|
||||
- Harbour
|
||||
- A sheltered landing
|
||||
- Coastal
|
||||
- coast crossable
|
||||
---
|
||||
- **32**
|
||||
- Sea Cliffs
|
||||
- Rock walls over the sea
|
||||
- Coastal
|
||||
- coast uncrossable
|
||||
---
|
||||
- **33**
|
||||
- Salt Marsh
|
||||
- Tidal mud and grasses
|
||||
- Costal
|
||||
- `drainage = Sodden`
|
||||
---
|
||||
- **34**
|
||||
- Sea Stacks
|
||||
- Rock pillars off a broken shoore
|
||||
- Coastal
|
||||
- `drainage = Broken`
|
||||
---
|
||||
- **35**
|
||||
- Spit
|
||||
- A tongue of land into the sea
|
||||
- Coastal
|
||||
- the coast reaches one Locality out to sea
|
||||
---
|
||||
- **36**
|
||||
- Cove
|
||||
- A bay cut into the shore
|
||||
- Coastal
|
||||
- the sea reaches one Locality inland
|
||||
{% /table %}
|
||||
{% /tableWrapper %}
|
||||
|
||||
## Volcano
|
||||
|
||||
1. If the Tract is volcanic, roll `1d6`. On a `6`, it has a volcano
|
||||
1. Read the volcano's type from the origin of the margin or hotspot
|
||||
|
||||
**Volcanic =>** A Tract is volcanic when its Area lies on a volcanic margin or hotspot
|
||||
|
||||
{% tableWrapper
|
||||
variant="default"
|
||||
columns=["rowheader", "default", "default", "key"] %}
|
||||
{% table %}
|
||||
- Type
|
||||
- Origin
|
||||
- Description
|
||||
- Effect
|
||||
---
|
||||
- Cone
|
||||
- Arc | Island Arc
|
||||
- Steep, explosive peak
|
||||
- `gradient = Steep`
|
||||
---
|
||||
- Shield
|
||||
- Hotspot
|
||||
- Broad, gentle dome
|
||||
- `fertility = Rich`
|
||||
---
|
||||
- Fissure
|
||||
- Rift | Transform
|
||||
- Cracks and lava fields
|
||||
- `cover = Barren`
|
||||
{% /table %}
|
||||
{% /tableWrapper %}
|
||||
|
||||
## Relief
|
||||
|
||||
1. Roll `1d6`
|
||||
1. A shifted Tract moves its elevation and its gradient one step the same way, and re-reads its drainage from the {% xref reference="pm-region" anchor="#drainage" %}Region's table{% /xref %}.
|
||||
1. A Tract shifted into Montane reads its band one step colder and re-reads its climate.
|
||||
|
||||
{% tableWrapper
|
||||
variant="default"
|
||||
columns=["rowheader", "key", "key", "key"] %}
|
||||
{% table %}
|
||||
- 1d6
|
||||
- 1
|
||||
- 2–5
|
||||
- 6
|
||||
---
|
||||
- Relief
|
||||
- one step down
|
||||
- –
|
||||
- one step up
|
||||
{% /table %}
|
||||
{% /tableWrapper %}
|
||||
|
||||
**Barriers =>** Montane ground, Major and Grand Rivers, and Broken coasts are barriers. Landmarks and saddles open or close them.
|
||||
|
||||
**Saddle =>** A Tract that Relief shifts down out of Montane is a saddle across the range.
|
||||
|
||||
## Headwaters
|
||||
|
||||
1. Roll `1d6` and add the modifiers for the Tract's gradient and moisture
|
||||
1. On `6+`, headwaters rise in the Tract and join the nearest rivers, lake or coast. If a range lies between, they end in a lake.
|
||||
|
||||
{% tableWrapper
|
||||
variant="default"
|
||||
caption="Fertility Modifiers"
|
||||
columns=["default", "num"] %}
|
||||
{% table %}
|
||||
- Clause
|
||||
- Modifier
|
||||
---
|
||||
- `gradient = Gentle`
|
||||
- `-1`
|
||||
---
|
||||
- `gradient = Steep`
|
||||
- `+1`
|
||||
---
|
||||
- `moisture = Arid`
|
||||
- `-1`
|
||||
---
|
||||
- `moisture = Wet`
|
||||
- `+1`
|
||||
{% /table %}
|
||||
{% /tableWrapper %}
|
||||
|
||||
## Fertility
|
||||
|
||||
1. Roll `1d6` and add the modifiers
|
||||
1. Read the total
|
||||
|
||||
{% tableWrapper
|
||||
variant="default"
|
||||
caption="Fertility Modifiers"
|
||||
columns=["default", "num"] %}
|
||||
{% table %}
|
||||
- Clause
|
||||
- Modifier
|
||||
---
|
||||
- `terrain = Alluvial`
|
||||
- `+1`
|
||||
---
|
||||
- volcanic
|
||||
- `+1`
|
||||
---
|
||||
- `terrain = Glacial | Karst`
|
||||
- `-1`
|
||||
---
|
||||
- `band = Arctic | Subarctic`
|
||||
- `-1`
|
||||
---
|
||||
- `moisture = Arid`
|
||||
- `-1`
|
||||
---
|
||||
- riverine
|
||||
- `+1`
|
||||
{% /table %}
|
||||
{% /tableWrapper %}
|
||||
|
||||
{% tableWrapper
|
||||
variant="default"
|
||||
caption="Random Tables – Fertility"
|
||||
columns=["rowheader", "key", "key", "key"] %}
|
||||
{% table %}
|
||||
- Total
|
||||
- ≤1
|
||||
- 2–5
|
||||
- 6+
|
||||
---
|
||||
- Fertility
|
||||
- Poor
|
||||
- Fair
|
||||
- Rich
|
||||
{% /table %}
|
||||
{% /tableWrapper %}
|
||||
|
||||
## Cover
|
||||
|
||||
Take the Region's cover, and shift it by every clause that applies.
|
||||
|
||||
{% tableWrapper
|
||||
variant="default"
|
||||
caption="Fertility Modifiers"
|
||||
columns=["default", "num"] %}
|
||||
{% table %}
|
||||
- Clause
|
||||
- Modifier
|
||||
---
|
||||
- `fertility = Poor`
|
||||
- `-1`
|
||||
---
|
||||
- `fertility = Rich`
|
||||
- `+1`
|
||||
---
|
||||
- `drainage = Broken`
|
||||
- `-1`
|
||||
{% /table %}
|
||||
{% /tableWrapper %}
|
||||
1193
src/content/general/articles/pm-world.mdoc
Normal file
1193
src/content/general/articles/pm-world.mdoc
Normal file
File diff suppressed because it is too large
Load Diff
@@ -7,13 +7,13 @@ stage: stub
|
||||
route:
|
||||
parent: stages
|
||||
index: 1
|
||||
sequence: false
|
||||
sequence: true
|
||||
summary:
|
||||
cover:
|
||||
image: /src/assets/content/articles/prima-materia/summary/cover/image.jpg
|
||||
alt: The Great Day of His Wrath
|
||||
credit: John Martin – The Great Day of His Wrath
|
||||
effect: xeroxed
|
||||
effect: none
|
||||
ratio: 21-9
|
||||
published: 2026-09-21T12:35:00.000Z
|
||||
tags:
|
||||
@@ -21,192 +21,48 @@ tags:
|
||||
- alchemical-materialism
|
||||
- genesis
|
||||
---
|
||||
{% lead %}
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. This first paragraph is the lead, so it should be larger and carry the drop cap. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. A sentence with *emphasis*, **strong text**, `inline code`, ~~struck text~~ and an [external link](https://example.com).
|
||||
{% /lead %}
|
||||
- **Scope =>** complete generation procedure; world map to locality
|
||||
|
||||
## Heading two, long enough to wrap onto a second line
|
||||
|
||||
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur{% footnote note="A footnote with *emphasis* and a [link](https://example.com)." /%}. Excepteur sint occaecat cupidatat non proident{% sidenote type="default" marker="†" note="A sidenote in the margin, beside the line it belongs to." /%}.
|
||||
|
||||
### Heading three
|
||||
|
||||
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam.
|
||||
|
||||
#### Heading four
|
||||
|
||||
At vero eos et accusamus et iusto odio dignissimos ducimus.
|
||||
|
||||
## Lists
|
||||
|
||||
- First item
|
||||
- Second item, with enough text to run past the end of a line and wrap underneath the marker
|
||||
- Third item
|
||||
- Nested item
|
||||
- Another nested item
|
||||
- Third level
|
||||
|
||||
1. First step
|
||||
1. Second step
|
||||
1. Sub-step
|
||||
1. Another sub-step
|
||||
1. Third step
|
||||
|
||||
## Quotes and rules
|
||||
|
||||
> A plain blockquote, no attribution.
|
||||
>
|
||||
> With a second paragraph.
|
||||
|
||||
{% quote
|
||||
cite="Paracelsus"
|
||||
source="Die dritte Defension"
|
||||
href="https://example.com" %}
|
||||
All things are poison, and nothing is without poison; the dosage alone makes it so a thing is not a poison.
|
||||
{% /quote %}
|
||||
|
||||
---
|
||||
|
||||
## Callouts
|
||||
|
||||
{% callout type="default" title="TITA TITLE" %}
|
||||
I AM DONE WITH THIS SHIT! SO COMPLETELY AND TOTALLY DONE!
|
||||
{% /callout %}
|
||||
|
||||
{% callout type="optional" title="Note" %}
|
||||
A default callout with a [link](https://example.com) and `code` inside it.
|
||||
{% /callout %}
|
||||
|
||||
{% callout type="example" title="Worked example" %}
|
||||
An example callout containing a list:
|
||||
|
||||
- one
|
||||
- two
|
||||
{% /callout %}
|
||||
|
||||
{% reveal summary="Spoiler" %}
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. This first paragraph is the lead, so it should be larger and carry the drop cap. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. A sentence with *emphasis*, **strong text**, `inline code`, ~~struck text~~ and an [external link](https://example.com).
|
||||
{% /reveal %}
|
||||
|
||||
## Code
|
||||
|
||||
```js
|
||||
const crucible = { stage: 'prima-materia', heat: 3 }
|
||||
|
||||
for (const [key, value] of Object.entries(crucible)) {
|
||||
console.log(`${key}: ${value}`)
|
||||
}
|
||||
```
|
||||
|
||||
## Tables
|
||||
## Hierarchy
|
||||
|
||||
{% tableWrapper
|
||||
variant="default"
|
||||
caption="Stages of the Work"
|
||||
columns=["rowheader", "key", "num", "num", "text"] %}
|
||||
caption="Hierarchy of the Zoom Levels"
|
||||
columns=["rowheader", "num", "num", "default", "default"] %}
|
||||
{% table %}
|
||||
- Stage
|
||||
- No
|
||||
- Heat
|
||||
- Hours
|
||||
- Notes
|
||||
- Level
|
||||
- Across flats (km)
|
||||
- Area (km²)
|
||||
- Children
|
||||
- Scope
|
||||
---
|
||||
- Prima Materia
|
||||
- I
|
||||
- 3
|
||||
- 0.25
|
||||
- The undifferentiated ground; nothing is named yet.
|
||||
- Area
|
||||
- 270
|
||||
- 63133
|
||||
- 9 Regions
|
||||
- plate, seam, band, base moisture
|
||||
---
|
||||
- Calcination
|
||||
- II
|
||||
- 7
|
||||
- 1.50
|
||||
- Burned down to what will not burn.
|
||||
- Region
|
||||
- 90
|
||||
- 7015
|
||||
- 9 Countries
|
||||
- gradient, climate, drainage, base density
|
||||
---
|
||||
- Solutio
|
||||
- III
|
||||
- 5
|
||||
- 12
|
||||
- Dissolved back into flow; forms loosen.
|
||||
- Country
|
||||
- 30
|
||||
- 779
|
||||
- 9 localities
|
||||
- soil, features
|
||||
---
|
||||
- Tincture
|
||||
- VII
|
||||
- Locality
|
||||
- 10
|
||||
- 120.75
|
||||
- The finished colour, carried into everything it touches.
|
||||
- 87
|
||||
- –
|
||||
- position, density, capacity, surplus
|
||||
{% /table %}
|
||||
{% /tableWrapper %}
|
||||
|
||||
## Images
|
||||
## Sequence
|
||||
|
||||
{% figure
|
||||
image="/src/assets/content/articles/prima-materia/john_martin_-_the_great_day_of_his_wrath_-_google_art_project.jpg"
|
||||
alt="A placeholder image"
|
||||
caption="An inline figure with a caption"
|
||||
credit="Dave Damage"
|
||||
effect="xeroxed"
|
||||
ratio="16-9"
|
||||
size="inline" /%}
|
||||
|
||||
Aliquam erat volutpat. Fusce sed velit at arcu tincidunt vulputate{% sidenote type="example" marker="‡" note="A second sidenote, typed as an example." /%}. Nam vitae lacus a nisl ultrices dictum.
|
||||
|
||||
Finally, a link to another article: {% xref reference="the-crucible" %}The Crucible{% /xref %}.
|
||||
|
||||
## Code
|
||||
|
||||
```ts
|
||||
const crucible = { stage: 'prima-materia', heat: 3 }
|
||||
|
||||
function temper(work: typeof crucible): 'calcined' | 'raw' {
|
||||
return work.heat > 5 ? 'calcined' : 'raw'
|
||||
}
|
||||
```
|
||||
|
||||
A fence with no language, which should render unhighlighted and with no label:
|
||||
|
||||
```
|
||||
Prima materia — the undifferentiated ground.
|
||||
Nothing is named yet.
|
||||
```
|
||||
|
||||
A long line, which should scroll inside the block rather than widen the article:
|
||||
|
||||
```css
|
||||
.prose :is(h2, h3, h4) + .table-wrapper thead th { border-block-end: var(--border-card) solid var(--color-border-strong); color: inherit; background-color: transparent; }
|
||||
```
|
||||
|
||||
An unknown language, which should render plain and raise a warning in the dev banner:
|
||||
|
||||
```brainfuck
|
||||
+[----->+++<]>+.
|
||||
```
|
||||
|
||||
{% callout type="example" title="Code inside a block" %}
|
||||
The frame should sit inside the callout body, not fight it:
|
||||
|
||||
```js
|
||||
export const isTag = (node) => Markdoc.Tag.isTag(node)
|
||||
```
|
||||
{% /callout %}
|
||||
|
||||
## Spoiler
|
||||
|
||||
Duis aute irure dolor in reprehenderit, and then {% spoiler %}the prima materia was the vessel all along{% /spoiler %}, which changes the reading of everything above.
|
||||
|
||||
A spoiler long enough to wrap across a line break: {% spoiler %}Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua{% /spoiler %}. And text after it.
|
||||
|
||||
## Definitions
|
||||
|
||||
{% definitions %}
|
||||
{% definition term="Prima Materia" kind="prime" see="Calcination, Solutio" %}
|
||||
The undifferentiated ground. Nothing is named yet, which is precisely what makes it workable.
|
||||
{% /definition %}
|
||||
|
||||
{% definition term="Calcination" kind="stage" see="Prima Materia" %}
|
||||
Burned down to what will not burn.
|
||||
{% /definition %}
|
||||
|
||||
{% definition term="Solutio" kind="stage" %}
|
||||
Dissolved back into flow, so that forms loosen.
|
||||
{% /definition %}
|
||||
{% /definitions %}
|
||||
1. {% xref reference="pm-world" %}**The World**{% /xref %}
|
||||
1. {% xref reference="pm-area" %}Area{% /xref %}
|
||||
|
||||
@@ -5,11 +5,59 @@ noindex: false
|
||||
stage: stub
|
||||
route:
|
||||
parent: the-crucible
|
||||
index: 2
|
||||
sequence: true
|
||||
summary:
|
||||
cover:
|
||||
image: /src/assets/content/articles/stages/summary/cover/image.jpg
|
||||
alt: >-
|
||||
An enormous tiered tower of stone arches rising above a harbour city; its
|
||||
lower levels are complete while the upper tiers stand unfinished, swarming
|
||||
with workers, cranes, and scaffolding.
|
||||
caption: The Tower of Babel
|
||||
credit: Pieter Bruegel the Elder
|
||||
effect: none
|
||||
ratio: original
|
||||
ratio: 21-9
|
||||
published: 2026-09-21T12:34:00.000Z
|
||||
tags: []
|
||||
---
|
||||
## Overview
|
||||
|
||||
{% tableWrapper
|
||||
variant="default"
|
||||
caption="The Seven Stages"
|
||||
columns=["rowheader", "default", "default"] %}
|
||||
{% table %}
|
||||
- Stage
|
||||
- Generates
|
||||
- Reads from
|
||||
---
|
||||
- {% xref reference="prima-materia" %}Prima Materia{% /xref %}
|
||||
- Terrain, climate, rivers, resources
|
||||
- –
|
||||
---
|
||||
- Calcination
|
||||
- Stocks, lineages, cultures
|
||||
- Land
|
||||
---
|
||||
- Fermentation
|
||||
- Religions, gods
|
||||
- Land, peoples
|
||||
---
|
||||
- Sublimation
|
||||
- Magical traditions, lores
|
||||
- Peoples, faith
|
||||
---
|
||||
- Coagulation
|
||||
- Vessels
|
||||
- Peoples, faith, traditions
|
||||
---
|
||||
- Conjunction
|
||||
- Realms, tribes, settlements
|
||||
- Vessels, land, peoples
|
||||
---
|
||||
- Dissolution
|
||||
- War, tribute, treaty, collapse
|
||||
- Realms
|
||||
{% /table %}
|
||||
{% /tableWrapper %}
|
||||
|
||||
@@ -1,20 +1,71 @@
|
||||
---
|
||||
title: The Crucible
|
||||
status: draft
|
||||
status: published
|
||||
noindex: false
|
||||
stage: stub
|
||||
route:
|
||||
index: 1
|
||||
sequence: false
|
||||
sequence: true
|
||||
summary:
|
||||
excerpt: >-
|
||||
Where we explore the crucible – a materialistic alchemist Worldbuilding
|
||||
Framework
|
||||
excerpt: Fantasy setting generator based on the 7 alchemical stages.
|
||||
cover:
|
||||
image: /src/assets/content/articles/the-crucible/summary/cover/image.jpg
|
||||
alt: >-
|
||||
A vast palace hall of colossal columns and towers under a storm-lit sky;
|
||||
crowds of feasters recoil in terror from glowing writing on the wall.
|
||||
caption: Belshazzar's Feast
|
||||
credit: John Martin
|
||||
effect: none
|
||||
ratio: original
|
||||
ratio: 21-9
|
||||
published: 2026-09-21T12:33:00.000Z
|
||||
tags:
|
||||
- the-crucible
|
||||
---
|
||||
hmm, do you even sharp?
|
||||
## Overview
|
||||
|
||||
- Procedural worldbuilding tool for fantasy settings
|
||||
- Seven stages: same procedure every stage
|
||||
- Upstream sets what's possible; each stage chooses within it
|
||||
- Tokens from *degrees* (fixed axes) and *signatures* (declared limitations)
|
||||
- Procedure: see {% xref reference="alchemical-materialism" %}Alchemical Materialism{% /xref %}
|
||||
|
||||
## Reading Order
|
||||
|
||||
- **Generate =>** start at {% xref reference="prima-materia" %}Prima Materia{% /xref %}
|
||||
- **Understand/Modify =>** start at {% xref reference="alchemical-materialism" %}Alchemical Materialism{% /xref %}
|
||||
|
||||
## The Seven Stages
|
||||
|
||||
{% table %}
|
||||
- Stage
|
||||
- Generates
|
||||
- Reads from
|
||||
---
|
||||
- {% xref reference="prima-materia" %}*Prima Materia*{% /xref %}
|
||||
- Terrain, climate, rivers, resources
|
||||
- –
|
||||
---
|
||||
- *Calcination*
|
||||
- Stocks, lineages, cultures
|
||||
- Land
|
||||
---
|
||||
- *Fermentation*
|
||||
- Religions, gods
|
||||
- Land, peoples
|
||||
---
|
||||
- *Sublimation*
|
||||
- Magical traditions, lores
|
||||
- Peoples, faith
|
||||
---
|
||||
- *Coagulation*
|
||||
- Vessels
|
||||
- Peoples, faith, traditions
|
||||
---
|
||||
- *Conjunction*
|
||||
- Realms, tribes, settlements
|
||||
- Vessels, land, peoples
|
||||
---
|
||||
- *Dissolution*
|
||||
- War, tribute, treaty, collapse
|
||||
- Realms
|
||||
{% /table %}
|
||||
|
||||
30
src/content/general/articles/tincture.mdoc
Normal file
30
src/content/general/articles/tincture.mdoc
Normal file
@@ -0,0 +1,30 @@
|
||||
---
|
||||
title: Tincture
|
||||
subtitle: Customs and Colour
|
||||
status: draft
|
||||
noindex: false
|
||||
stage: stub
|
||||
route:
|
||||
parent: the-crucible
|
||||
index: 3
|
||||
sequence: false
|
||||
summary:
|
||||
excerpt: >-
|
||||
Flavour tables for cultural customs; the detail that makes a culture
|
||||
recognisable at the table.
|
||||
cover:
|
||||
image: /src/assets/content/articles/tincture/summary/cover/image.jpg
|
||||
alt: >-
|
||||
A crowded town square split between tavern and church; on one side a fat
|
||||
reveller rides a barrel with a roasting spit, on the other a gaunt figure
|
||||
on a cart offers fish, while dancers, beggars, and merchants fill every
|
||||
corner.
|
||||
caption: The Fight Between Carnival and Lent
|
||||
credit: Pieter Bruegel the Elder
|
||||
effect: none
|
||||
ratio: original
|
||||
published: 2026-10-01T08:03:00.000Z
|
||||
tags:
|
||||
- the-crucible
|
||||
- genesis
|
||||
---
|
||||
4
src/content/general/tags/prima-materia.json
Normal file
4
src/content/general/tags/prima-materia.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"title": "Prima Materia",
|
||||
"description": "The first stage of the crucible"
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
version: '0.12'
|
||||
date: 2026-09-30T13:00:00.000Z
|
||||
changes:
|
||||
- kind: added
|
||||
article: prima-materia
|
||||
text: Section on the ground state; first table of correspondences
|
||||
@@ -1,12 +0,0 @@
|
||||
version: '0.13'
|
||||
date: 2026-09-30T13:00:00.000Z
|
||||
changes:
|
||||
- kind: added
|
||||
article: calcination
|
||||
text: Test
|
||||
- kind: added
|
||||
article: fermentation
|
||||
text: Big test with a longer sentence
|
||||
- kind: changed
|
||||
article: coagulation
|
||||
text: Lorem ipsum, blablabla ipbsum whorum
|
||||
@@ -1,19 +0,0 @@
|
||||
version: '0.14'
|
||||
date: 2026-09-30T13:00:00.000Z
|
||||
changes:
|
||||
- kind: added
|
||||
article: coagulation
|
||||
text: >-
|
||||
s the raw release exactly as Keystatic reads it, inferred from the schema
|
||||
like the other three
|
||||
- kind: changed
|
||||
article: prima-materia
|
||||
text: >-
|
||||
releases are loaded, resolved and attached to articles. Six files; nothing
|
||||
renders yet.
|
||||
- kind: fixed
|
||||
article: fermentation
|
||||
text: We don't burn the priests anymore, we burn the gods
|
||||
- kind: removed
|
||||
article: the-crucible
|
||||
text: AND EVERYTHING GOES BOOOOOOOM
|
||||
19
src/keystatic/blocks/general/color.ts
Normal file
19
src/keystatic/blocks/general/color.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { fields } from '@keystatic/core'
|
||||
import { mark } from '@keystatic/core/content-components'
|
||||
|
||||
import { paletteIcon } from '@keystar/ui/icon/icons/paletteIcon'
|
||||
|
||||
import { COLOR_VARIANTS } from '@/lib/constants/blocks/color'
|
||||
|
||||
export const color = mark({
|
||||
label: 'Colour',
|
||||
icon: paletteIcon,
|
||||
tag: 'span',
|
||||
schema: {
|
||||
variant: fields.select({
|
||||
label: 'Colour',
|
||||
options: COLOR_VARIANTS,
|
||||
defaultValue: 'lava-text',
|
||||
}),
|
||||
},
|
||||
})
|
||||
@@ -1,5 +1,8 @@
|
||||
import { fields } from '@keystatic/core'
|
||||
import { repeating } from '@keystatic/core/content-components'
|
||||
|
||||
import { DEFINITION_VARIANTS } from '@/lib/constants/blocks/definitions'
|
||||
|
||||
export const definitions = repeating({
|
||||
label: 'Definitions',
|
||||
description: 'A list of terms defined for this article only',
|
||||
@@ -9,5 +12,11 @@ export const definitions = repeating({
|
||||
min: 1,
|
||||
},
|
||||
},
|
||||
schema: {},
|
||||
schema: {
|
||||
variant: fields.select({
|
||||
label: 'Style',
|
||||
options: DEFINITION_VARIANTS,
|
||||
defaultValue: 'cross',
|
||||
}),
|
||||
},
|
||||
})
|
||||
|
||||
24
src/keystatic/blocks/general/element.ts
Normal file
24
src/keystatic/blocks/general/element.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { fields } from '@keystatic/core'
|
||||
import { inline } from '@keystatic/core/content-components'
|
||||
|
||||
import { flameIcon } from '@keystar/ui/icon/icons/flameIcon'
|
||||
|
||||
import { ELEMENT_STYLES, ELEMENTS } from '@/lib/constants/elements'
|
||||
|
||||
export const element = inline({
|
||||
label: 'Element',
|
||||
description: 'An elemental glyph, set in Unigrim Dee',
|
||||
icon: flameIcon,
|
||||
schema: {
|
||||
name: fields.select({
|
||||
label: 'Element',
|
||||
options: ELEMENTS,
|
||||
defaultValue: 'earth',
|
||||
}),
|
||||
style: fields.select({
|
||||
label: 'Style',
|
||||
options: ELEMENT_STYLES,
|
||||
defaultValue: 'filled',
|
||||
}),
|
||||
},
|
||||
})
|
||||
@@ -1,6 +1,8 @@
|
||||
import { callout } from './callout'
|
||||
import { color } from './color'
|
||||
import { definition } from './definition-list/definition'
|
||||
import { definitions } from './definition-list/definitions'
|
||||
import { element } from './element'
|
||||
import { figure } from './figure'
|
||||
import { footnote } from './footnote'
|
||||
import { lead } from './lead'
|
||||
@@ -9,19 +11,23 @@ import { reveal } from './reveal'
|
||||
import { sidenote } from './sidenote'
|
||||
import { spoiler } from './spoiler'
|
||||
import { tableWrapper } from './table-wrapper'
|
||||
import { underline } from './underline'
|
||||
import { xref } from './xref'
|
||||
|
||||
export const generalBlocks = (collection: string) => ({
|
||||
figure: figure(collection),
|
||||
callout,
|
||||
color,
|
||||
definition,
|
||||
definitions,
|
||||
lead,
|
||||
footnote,
|
||||
element,
|
||||
sidenote,
|
||||
tableWrapper,
|
||||
quote,
|
||||
reveal,
|
||||
spoiler,
|
||||
underline,
|
||||
xref: xref(),
|
||||
})
|
||||
|
||||
10
src/keystatic/blocks/general/underline.ts
Normal file
10
src/keystatic/blocks/general/underline.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { mark } from '@keystatic/core/content-components'
|
||||
|
||||
import { underlineIcon } from '@keystar/ui/icon/icons/underlineIcon'
|
||||
|
||||
export const underline = mark({
|
||||
label: 'Underline',
|
||||
icon: underlineIcon,
|
||||
tag: 'u',
|
||||
schema: {},
|
||||
})
|
||||
@@ -9,6 +9,7 @@ export const releases = collection({
|
||||
label: 'Releases',
|
||||
slugField: 'version',
|
||||
path: `src/content/site/${RELEASES}/*`,
|
||||
format: 'json',
|
||||
columns: ['version', 'date'],
|
||||
schema: {
|
||||
version: fields.slug({
|
||||
|
||||
@@ -7,7 +7,7 @@ export const content = (collection: string) =>
|
||||
fields.markdoc({
|
||||
label: 'Content',
|
||||
options: {
|
||||
heading: [2, 3, 4],
|
||||
heading: [2, 3, 4, 5],
|
||||
image: assets(collection),
|
||||
},
|
||||
components: generalBlocks(collection),
|
||||
|
||||
@@ -46,7 +46,7 @@ const previewUrl = preview ? new URL(preview.src, Astro.site) : undefined
|
||||
<Font cssVariable="--font-geist-mono" preload />
|
||||
<Font cssVariable="--font-blaka" preload />
|
||||
<Font cssVariable="--font-julia-mono" preload />
|
||||
<Font cssVariable="--font-unigrim" />
|
||||
<Font cssVariable="--font-unigrim" preload />
|
||||
<style is:inline>
|
||||
@layer reset, tokens, base, components.prose, components.blocks, utilities;
|
||||
</style>
|
||||
|
||||
10
src/lib/constants/blocks/color.ts
Normal file
10
src/lib/constants/blocks/color.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
export const COLOR_VARIANTS = [
|
||||
{ label: 'Lava text', value: 'lava-text' },
|
||||
{ label: 'Lime text', value: 'lime-text' },
|
||||
{ label: 'Canary text', value: 'canary-text' },
|
||||
{ label: 'Lava fill', value: 'lava-fill' },
|
||||
{ label: 'Lime fill', value: 'lime-fill' },
|
||||
{ label: 'Canary fill', value: 'canary-fill' },
|
||||
] as const
|
||||
|
||||
export type ColorVariant = (typeof COLOR_VARIANTS)[number]['value']
|
||||
12
src/lib/constants/blocks/definitions.ts
Normal file
12
src/lib/constants/blocks/definitions.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
export const DEFINITION_VARIANTS = [
|
||||
{
|
||||
label: 'Boxed',
|
||||
value: 'cross',
|
||||
},
|
||||
{
|
||||
label: 'Compact',
|
||||
value: 'compact',
|
||||
},
|
||||
] as const
|
||||
|
||||
export type DefinitionVariant = (typeof DEFINITION_VARIANTS)[number]['value']
|
||||
@@ -3,10 +3,18 @@ export const TABLE_VARIANTS = [
|
||||
label: 'Default',
|
||||
value: 'default',
|
||||
},
|
||||
{
|
||||
label: 'Wide',
|
||||
value: 'wide',
|
||||
},
|
||||
{
|
||||
label: 'Matrix',
|
||||
value: 'matrix',
|
||||
},
|
||||
{
|
||||
label: 'Deviation',
|
||||
value: 'deviation',
|
||||
},
|
||||
] as const
|
||||
|
||||
export type TableVariant = (typeof TABLE_VARIANTS)[number]['value']
|
||||
|
||||
20
src/lib/constants/elements.ts
Normal file
20
src/lib/constants/elements.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
export const ELEMENTS = [
|
||||
{ label: 'Earth', value: 'earth', glyph: 'N' },
|
||||
{ label: 'Fire', value: 'fire', glyph: 'B' },
|
||||
{ label: 'Water', value: 'water', glyph: 'H' },
|
||||
{ label: 'Air', value: 'air', glyph: 'E' },
|
||||
{ label: 'Aether', value: 'aether', glyph: 'Q' },
|
||||
{ label: 'Soul', value: 'soul', glyph: 'A' },
|
||||
{ label: 'Body', value: 'body', glyph: 'C' },
|
||||
{ label: 'Spirit', value: 'spirit', glyph: 'S' },
|
||||
] as const
|
||||
|
||||
export type ElementName = (typeof ELEMENTS)[number]['value']
|
||||
|
||||
export const ELEMENT_STYLES = [
|
||||
{ label: 'Filled', value: 'filled' },
|
||||
{ label: 'Outline', value: 'outline' },
|
||||
{ label: 'Bare', value: 'bare' },
|
||||
] as const
|
||||
|
||||
export type ElementStyle = (typeof ELEMENT_STYLES)[number]['value']
|
||||
@@ -1,11 +1,6 @@
|
||||
export const TERM_KINDS = [
|
||||
{ label: 'Entry', value: 'entry' },
|
||||
{ label: 'Prime', value: 'prime' },
|
||||
{ label: 'Essence', value: 'essence' },
|
||||
{ label: 'Element', value: 'element' },
|
||||
{ label: 'Stage', value: 'stage' },
|
||||
{ label: 'Tier', value: 'tier' },
|
||||
{ label: 'Premise', value: 'premise' },
|
||||
{ label: 'Form', value: 'form' },
|
||||
] as const
|
||||
|
||||
export type TermKind = (typeof TERM_KINDS)[number]['value']
|
||||
|
||||
@@ -4,7 +4,9 @@ import Markdoc, { type Node, type RenderableTreeNode, type Schema } from '@markd
|
||||
|
||||
import { generalBlocks } from '@/keystatic/blocks/general'
|
||||
|
||||
import type { DefinitionVariant } from '../constants/blocks/definitions'
|
||||
import { ARTICLES } from '../constants/collections'
|
||||
import { ELEMENTS } from '../constants/elements'
|
||||
import { inlineOf } from './notes'
|
||||
import { eachTag, firstTag, isTag } from './tree'
|
||||
import type { NodeState, ResolveLink } from './types'
|
||||
@@ -67,6 +69,7 @@ const generated =
|
||||
tableWrapper: 'TableWrapper',
|
||||
quote: 'Quote',
|
||||
reveal: 'Reveal',
|
||||
underline: 'u',
|
||||
},
|
||||
},
|
||||
}).tags ?? {}
|
||||
@@ -86,6 +89,27 @@ export function createTags(state: NodeState, resolveLink: ResolveLink): Record<s
|
||||
])
|
||||
},
|
||||
},
|
||||
element: {
|
||||
...generated.element,
|
||||
inline: undefined,
|
||||
transform(node) {
|
||||
const name = text(node.attributes.name)
|
||||
const style = text(node.attributes.style) || 'filled'
|
||||
const entry = ELEMENTS.find((option) => option.value === name)
|
||||
|
||||
if (!entry) {
|
||||
state.problems.push({ level: 'error', message: `Unknown element "${name}".` })
|
||||
return []
|
||||
}
|
||||
|
||||
return new Tag('span', { class: `element-glyph element-glyph--${style}` }, [
|
||||
new Tag('span', { class: 'element-glyph__symbol', 'aria-hidden': 'true' }, [
|
||||
entry.glyph,
|
||||
]),
|
||||
new Tag('span', { class: 'element-glyph__name' }, [entry.label]),
|
||||
])
|
||||
},
|
||||
},
|
||||
spoiler: {
|
||||
...generated.spoiler,
|
||||
transform(node, config) {
|
||||
@@ -96,6 +120,17 @@ export function createTags(state: NodeState, resolveLink: ResolveLink): Record<s
|
||||
])
|
||||
},
|
||||
},
|
||||
color: {
|
||||
...generated.color,
|
||||
transform(node, config) {
|
||||
const variant = text(node.attributes.variant) || 'lava-text'
|
||||
return new Tag(
|
||||
'span',
|
||||
{ class: `accent accent--${variant}` },
|
||||
node.transformChildren(config),
|
||||
)
|
||||
},
|
||||
},
|
||||
sidenote: {
|
||||
...generated.sidenote,
|
||||
transform(node, config) {
|
||||
@@ -110,7 +145,9 @@ export function createTags(state: NodeState, resolveLink: ResolveLink): Record<s
|
||||
const n = (state.sidenoteCount += 1)
|
||||
const children = inlineOf(text(node.attributes.note))
|
||||
return [
|
||||
new Tag('a', { class: 'sidenote-ref', id: `snref-${n}`, href: `#sn-${n}` }, [marker]),
|
||||
new Tag('sup', { class: 'sidenote-ref' }, [
|
||||
new Tag('a', { id: `snref-${n}`, href: `#sn-${n}` }, [marker]),
|
||||
]),
|
||||
new Tag(
|
||||
'span',
|
||||
{ class: `sidenote sidenote--${noteType}`, id: `sn-${n}`, role: 'note' },
|
||||
@@ -178,6 +215,19 @@ export function createTags(state: NodeState, resolveLink: ResolveLink): Record<s
|
||||
]
|
||||
},
|
||||
},
|
||||
definitions: {
|
||||
...generated.definitions,
|
||||
transform(node, config) {
|
||||
const { variant = 'cross' } = node.transformAttributes(config) as {
|
||||
variant?: DefinitionVariant
|
||||
}
|
||||
const children = node.transformChildren(config)
|
||||
eachTag(children, 'Definition', (definition) => {
|
||||
definition.attributes.ink = variant === 'cross'
|
||||
})
|
||||
return new Tag('DefinitionList', { variant }, children)
|
||||
},
|
||||
},
|
||||
lead: {
|
||||
...generated.lead,
|
||||
transform(node, config) {
|
||||
|
||||
@@ -47,6 +47,9 @@
|
||||
--color-text-disabled: var(--color-palette-stone);
|
||||
--color-text-inverse: var(--color-palette-paper);
|
||||
--color-text-on-accent: var(--color-palette-black-ink);
|
||||
--color-text-lava: oklch(from var(--color-primary) 55% c h);
|
||||
--color-text-lime: oklch(from var(--color-secondary) 50% c h);
|
||||
--color-text-canary: oklch(from var(--color-tertiary) 52% c h);
|
||||
|
||||
/* == Surfaces == */
|
||||
--color-surface-base: var(--color-palette-stock);
|
||||
@@ -124,6 +127,9 @@
|
||||
--color-text-disabled: var(--color-palette-stone);
|
||||
--color-text-inverse: var(--color-palette-black-ink);
|
||||
--color-text-on-accent: var(--color-palette-black-ink);
|
||||
--color-text-lava: var(--color-primary);
|
||||
--color-text-lime: var(--color-secondary);
|
||||
--color-text-canary: var(--color-tertiary);
|
||||
|
||||
/* == Surfaces: elevation still means lighter == */
|
||||
--color-surface-base: var(--color-palette-black-ink);
|
||||
|
||||
34
src/styles/components/blocks/accent.css
Normal file
34
src/styles/components/blocks/accent.css
Normal file
@@ -0,0 +1,34 @@
|
||||
@layer components.blocks {
|
||||
.accent--lava-text {
|
||||
color: var(--color-text-lava);
|
||||
}
|
||||
|
||||
.accent--lime-text {
|
||||
color: var(--color-text-lime);
|
||||
}
|
||||
|
||||
.accent--canary-text {
|
||||
color: var(--color-text-canary);
|
||||
}
|
||||
|
||||
.accent--lava-fill,
|
||||
.accent--lime-fill,
|
||||
.accent--canary-fill {
|
||||
@mixin px var(--space-1);
|
||||
|
||||
color: var(--color-text-on-accent);
|
||||
box-decoration-break: clone;
|
||||
}
|
||||
|
||||
.accent--lava-fill {
|
||||
background-color: var(--color-primary);
|
||||
}
|
||||
|
||||
.accent--lime-fill {
|
||||
background-color: var(--color-secondary);
|
||||
}
|
||||
|
||||
.accent--canary-fill {
|
||||
background-color: var(--color-tertiary);
|
||||
}
|
||||
}
|
||||
34
src/styles/components/blocks/element-glyph.css
Normal file
34
src/styles/components/blocks/element-glyph.css
Normal file
@@ -0,0 +1,34 @@
|
||||
@layer components.blocks {
|
||||
.element-glyph {
|
||||
display: inline-grid;
|
||||
place-items: center;
|
||||
|
||||
aspect-ratio: 1;
|
||||
width: 1.1em;
|
||||
|
||||
font-family: var(--font-symbols);
|
||||
font-size: 1.3em;
|
||||
font-weight: var(--font-weight-body);
|
||||
font-style: normal;
|
||||
line-height: 1;
|
||||
vertical-align: -0.2em;
|
||||
}
|
||||
|
||||
.element-glyph--filled {
|
||||
color: var(--color-text-inverse);
|
||||
background-color: var(--color-surface-inverse);
|
||||
}
|
||||
|
||||
.element-glyph--outline {
|
||||
box-shadow: inset 0 0 0 var(--border-hairline) currentcolor;
|
||||
}
|
||||
|
||||
.element-glyph--bare {
|
||||
aspect-ratio: auto;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.element-glyph__name {
|
||||
@mixin visually-hidden;
|
||||
}
|
||||
}
|
||||
@@ -9,3 +9,5 @@
|
||||
@import url("code.css");
|
||||
@import url("terms.css");
|
||||
@import url("spoiler.css");
|
||||
@import url("element-glyph.css");
|
||||
@import url("accent.css");
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
@layer components.blocks {
|
||||
.sidenote-ref {
|
||||
@mixin px var(--size-1);
|
||||
|
||||
font-family: var(--font-mono);
|
||||
font-family: var(--font-body);
|
||||
font-size: 0.75em;
|
||||
font-weight: var(--font-weight-emphasis);
|
||||
line-height: 1;
|
||||
|
||||
& a {
|
||||
@mixin px var(--size-1);
|
||||
|
||||
color: var(--color-text-primary);
|
||||
text-decoration: none;
|
||||
|
||||
@@ -16,6 +19,7 @@
|
||||
@mixin focus-ring;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sidenote {
|
||||
@mixin typo_body-small;
|
||||
@@ -23,6 +27,8 @@
|
||||
@mixin border-t var(--border-card), solid, var(--color-border-strong);
|
||||
|
||||
color: var(--color-text-secondary);
|
||||
text-align: start;
|
||||
white-space: normal;
|
||||
|
||||
/* Hangs, so the first line starts against the marker. */
|
||||
& .sidenote__marker {
|
||||
|
||||
@@ -24,6 +24,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
& .table-scroll {
|
||||
overflow-x: auto;
|
||||
overscroll-behavior-x: contain;
|
||||
|
||||
&:focus-visible {
|
||||
@mixin focus-ring;
|
||||
}
|
||||
}
|
||||
|
||||
& table {
|
||||
@mixin my var(--size-0);
|
||||
|
||||
@@ -38,22 +47,174 @@
|
||||
& td {
|
||||
&.text {
|
||||
font-family: var(--font-body);
|
||||
font-size: 1.077em;
|
||||
line-height: 1.55;
|
||||
line-height: 1.7;
|
||||
color: var(--color-text-secondary);
|
||||
text-wrap: pretty;
|
||||
}
|
||||
}
|
||||
|
||||
& code {
|
||||
@mixin px var(--size-2);
|
||||
@mixin py var(--size-1);
|
||||
font-size: inherit;
|
||||
color: var(--color-text-inverse);
|
||||
background-color: var(--color-surface-inverse);
|
||||
box-decoration-break: clone;
|
||||
}
|
||||
}
|
||||
|
||||
& .num {
|
||||
font-variant-numeric: tabular-nums;
|
||||
text-align: right;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
& .key {
|
||||
font-weight: var(--font-weight-emphasis);
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.table-wrapper--wide {
|
||||
@media (--bp-desktop) {
|
||||
@mixin me calc(-1 * (var(--layout-gutter) + var(--layout-margin-width)));
|
||||
}
|
||||
}
|
||||
|
||||
.table-wrapper--matrix {
|
||||
& table {
|
||||
table-layout: fixed;
|
||||
border-collapse: collapse;
|
||||
border: var(--border-card) solid var(--color-border-strong);
|
||||
|
||||
& :is(th, td) {
|
||||
border: var(--border-hairline) solid var(--color-border-subtle);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
& thead th {
|
||||
border-color: var(--color-border-normal);
|
||||
color: var(--color-text-inverse);
|
||||
background-color: var(--color-surface-inverse);
|
||||
}
|
||||
|
||||
& tr > :first-child {
|
||||
width: 8rem;
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
& tbody tr > :first-child {
|
||||
@mixin typo_table-header;
|
||||
border-color: var(--color-border-normal);
|
||||
color: var(--color-text-inverse);
|
||||
background-color: var(--color-surface-inverse);
|
||||
}
|
||||
|
||||
& tbody tr:hover > :first-child {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
& tbody td {
|
||||
font-variant-numeric: tabular-nums;
|
||||
|
||||
&:hover {
|
||||
box-shadow: inset 0 0 0 var(--border-card) var(--color-border-strong);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Crosshair: highlight the hovered cell's column, one rule per column. */
|
||||
.table-wrapper--matrix table:has(tbody td:nth-child(2):hover) {
|
||||
& tbody td:nth-child(2) {
|
||||
background-color: var(--color-surface-hover);
|
||||
}
|
||||
|
||||
& thead th:nth-child(2) {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.table-wrapper--matrix table:has(tbody td:nth-child(3):hover) {
|
||||
& tbody td:nth-child(3) {
|
||||
background-color: var(--color-surface-hover);
|
||||
}
|
||||
|
||||
& thead th:nth-child(3) {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.table-wrapper--matrix table:has(tbody td:nth-child(4):hover) {
|
||||
& tbody td:nth-child(4) {
|
||||
background-color: var(--color-surface-hover);
|
||||
}
|
||||
|
||||
& thead th:nth-child(4) {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.table-wrapper--matrix table:has(tbody td:nth-child(5):hover) {
|
||||
& tbody td:nth-child(5) {
|
||||
background-color: var(--color-surface-hover);
|
||||
}
|
||||
|
||||
& thead th:nth-child(5) {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.table-wrapper--matrix table:has(tbody td:nth-child(6):hover) {
|
||||
& tbody td:nth-child(6) {
|
||||
background-color: var(--color-surface-hover);
|
||||
}
|
||||
|
||||
& thead th:nth-child(6) {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.table-wrapper--matrix table:has(tbody td:nth-child(7):hover) {
|
||||
& tbody td:nth-child(7) {
|
||||
background-color: var(--color-surface-hover);
|
||||
}
|
||||
|
||||
& thead th:nth-child(7) {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.table-wrapper--matrix table:has(tbody td:nth-child(8):hover) {
|
||||
& tbody td:nth-child(8) {
|
||||
background-color: var(--color-surface-hover);
|
||||
}
|
||||
|
||||
& thead th:nth-child(8) {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.table-wrapper--deviation {
|
||||
& table {
|
||||
table-layout: fixed;
|
||||
|
||||
& thead th {
|
||||
&:nth-child(1) {
|
||||
width: 10%;
|
||||
}
|
||||
|
||||
&:nth-child(2) {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
&:nth-child(3) {
|
||||
width: 45%;
|
||||
}
|
||||
|
||||
&:nth-child(4) {
|
||||
width: 20%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,12 +26,12 @@
|
||||
}
|
||||
|
||||
.term__body {
|
||||
@mixin typo_body;
|
||||
@mixin ma var(--size-0);
|
||||
}
|
||||
|
||||
.term__definition {
|
||||
@mixin typo_body;
|
||||
@mixin ma var(--size-0);
|
||||
:where(.term__body p) {
|
||||
@mixin my var(--size-0);
|
||||
}
|
||||
|
||||
.term__see {
|
||||
@@ -100,4 +100,53 @@
|
||||
|
||||
background-color: var(--color-surface-elevated-1);
|
||||
}
|
||||
|
||||
.terms--compact {
|
||||
@mixin my var(--space-9);
|
||||
@mixin border-t var(--border-hairline), solid, var(--color-border-strong);
|
||||
|
||||
grid-template-columns: minmax(0, 9rem) minmax(0, 1fr);
|
||||
column-gap: var(--size-9);
|
||||
}
|
||||
|
||||
.terms--compact .term,
|
||||
.terms--compact .term__body {
|
||||
@mixin py var(--size-5);
|
||||
@mixin border-b var(--border-hairline), solid, var(--color-border-subtle);
|
||||
}
|
||||
|
||||
.terms--compact .term {
|
||||
gap: var(--size-2);
|
||||
justify-content: start;
|
||||
}
|
||||
|
||||
.terms--compact .term__name {
|
||||
@mixin typo_heading-5;
|
||||
}
|
||||
|
||||
.terms--compact .term__body {
|
||||
@mixin typo_definition-data;
|
||||
}
|
||||
|
||||
.terms--compact .term__see {
|
||||
@mixin mt var(--size-3);
|
||||
|
||||
padding-block-start: var(--size-0);
|
||||
border-block-start: none;
|
||||
}
|
||||
|
||||
.terms--compact .term:target .term__name {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
@media (--bp-tablet-down) {
|
||||
.terms--compact {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
|
||||
.terms--compact .term {
|
||||
padding-block-end: var(--size-0);
|
||||
border-block-end: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,6 +93,34 @@
|
||||
border-block: var(--border-shell) solid var(--color-text-primary);
|
||||
}
|
||||
|
||||
& h5 {
|
||||
@mixin typo_heading-5;
|
||||
@mixin mt var(--space-12);
|
||||
@mixin mb var(--space-4);
|
||||
|
||||
display: flex;
|
||||
gap: var(--size-4);
|
||||
align-items: center;
|
||||
color: var(--color-text-secondary);
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
|
||||
flex: none;
|
||||
|
||||
width: var(--size-3);
|
||||
height: var(--size-3);
|
||||
|
||||
background-color: var(--color-primary);
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
flex: 1;
|
||||
border-block-start: var(--border-hairline) solid var(--color-border-strong);
|
||||
}
|
||||
}
|
||||
|
||||
/* === LISTS === */
|
||||
|
||||
& ul,
|
||||
@@ -107,12 +135,13 @@
|
||||
|
||||
& li {
|
||||
--prose-line: 1lh;
|
||||
display: grid;
|
||||
grid-template-columns: var(--slot-prose-marker) minmax(0, 1fr);
|
||||
column-gap: var(--slot-prose-gap);
|
||||
|
||||
& > * {
|
||||
grid-column: 2;
|
||||
position: relative;
|
||||
padding-inline-start: calc(var(--slot-prose-marker) + var(--slot-prose-gap));
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
inset-inline-start: 0;
|
||||
}
|
||||
|
||||
& > ul,
|
||||
@@ -121,6 +150,16 @@
|
||||
@mixin mb var(--size-0);
|
||||
gap: var(--space-3);
|
||||
}
|
||||
|
||||
& > p {
|
||||
&:first-child {
|
||||
margin-block-start: var(--size-0);
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
margin-block-end: var(--size-0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,11 +168,11 @@
|
||||
&::before {
|
||||
content: "";
|
||||
|
||||
justify-self: center;
|
||||
inset-block-start: calc((var(--prose-line) - 0.625rem) / 2);
|
||||
inset-inline-start: calc((var(--slot-prose-marker) - 0.625rem) / 2);
|
||||
|
||||
width: 0.625rem;
|
||||
height: 0.625rem;
|
||||
margin-block-start: calc((var(--prose-line) - 0.625rem) / 2);
|
||||
|
||||
background-color: var(--color-text-primary);
|
||||
}
|
||||
@@ -149,8 +188,8 @@
|
||||
& ul {
|
||||
& > li {
|
||||
&::before {
|
||||
inset-block-start: calc((var(--prose-line) - var(--size-2)) / 2);
|
||||
height: var(--size-2);
|
||||
margin-block-start: calc((var(--prose-line) - var(--size-2)) / 2);
|
||||
background-color: var(--color-text-primary);
|
||||
box-shadow: none;
|
||||
}
|
||||
@@ -169,11 +208,13 @@
|
||||
&::before {
|
||||
content: counter(step, decimal-leading-zero);
|
||||
|
||||
inset-block-start: calc((var(--prose-line) - 1.375rem) / 2);
|
||||
|
||||
display: grid;
|
||||
place-items: center;
|
||||
|
||||
width: var(--slot-prose-marker);
|
||||
height: 1.375rem;
|
||||
margin-block-start: calc((var(--prose-line) - 1.375rem) / 2);
|
||||
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.75rem;
|
||||
@@ -287,6 +328,12 @@
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
& u {
|
||||
text-decoration: underline;
|
||||
text-decoration-thickness: var(--border-hairline);
|
||||
text-underline-offset: var(--size-2);
|
||||
}
|
||||
|
||||
/* === TABLES === */
|
||||
table {
|
||||
@mixin typo_table-data;
|
||||
@@ -297,9 +344,10 @@
|
||||
|
||||
& th,
|
||||
& td {
|
||||
@mixin py var(--space-4);
|
||||
@mixin px var(--space-6);
|
||||
@mixin py var(--size-3);
|
||||
@mixin px var(--size-5);
|
||||
@mixin border-b var(--border-hairline), solid, var(--color-border-subtle);
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
& thead {
|
||||
|
||||
@@ -33,6 +33,15 @@
|
||||
letter-spacing: var(--tracking-label);
|
||||
}
|
||||
|
||||
@define-mixin typo_heading-5 {
|
||||
font-family: var(--font-header);
|
||||
font-size: var(--type--1);
|
||||
font-weight: var(--font-weight-label);
|
||||
line-height: var(--leading--1);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: var(--tracking-label);
|
||||
}
|
||||
|
||||
@define-mixin typo_code {
|
||||
font-family: var(--font-mono);
|
||||
font-size: var(--type--1);
|
||||
|
||||
Reference in New Issue
Block a user