@heroiclands/package-build 25.1.3 → 25.2.0

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 (83) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/assets/styles/content-base.css +0 -9
  3. package/bin/content-commands.mjs +22 -16
  4. package/bin/package-build.mjs +24 -25
  5. package/content-config.mjs +7 -34
  6. package/docs/api.md +38 -21
  7. package/docs/authoring/first-note.md +3 -3
  8. package/docs/authoring/frontmatter.md +30 -2
  9. package/docs/authoring/links-and-markup.md +92 -31
  10. package/docs/commands.md +103 -59
  11. package/docs/configuration.md +10 -45
  12. package/docs/content-format.md +7 -5
  13. package/docs/diagnostics.md +75 -0
  14. package/docs/guides/book.md +3 -3
  15. package/docs/guides/module-project.md +1 -1
  16. package/docs/guides/reference-pages.md +7 -3
  17. package/docs/project-setup.md +3 -0
  18. package/docs/reference/format-details.md +299 -185
  19. package/docs/reference/note-types.md +16 -17
  20. package/engine/changelog-group.mjs +84 -173
  21. package/engine/changelog-labels.mjs +73 -0
  22. package/engine/changelog-lint.mjs +168 -44
  23. package/engine/content-expand.mjs +58 -38
  24. package/engine/content-format.yaml +0 -2
  25. package/engine/content-index.mjs +49 -23
  26. package/engine/content-links.mjs +4 -0
  27. package/engine/content-lint.mjs +2 -3
  28. package/engine/content-render.mjs +6 -2
  29. package/engine/culture-parents.mjs +1 -1
  30. package/engine/culture-reach.mjs +10 -1
  31. package/engine/diagnostics.mjs +3 -2
  32. package/engine/dictionary-rows.mjs +3 -1
  33. package/engine/first-use.mjs +301 -87
  34. package/engine/frontmatter-lint.mjs +40 -14
  35. package/engine/glossary-entries.mjs +5 -5
  36. package/engine/glossary-language.mjs +21 -44
  37. package/engine/homepage.mjs +0 -4
  38. package/engine/index-records.mjs +3 -1
  39. package/engine/infobox.mjs +6 -3
  40. package/engine/language-names.mjs +3 -2
  41. package/engine/language-rows.mjs +6 -7
  42. package/engine/lexical-sections.mjs +3 -1
  43. package/engine/literature-notes.mjs +4 -76
  44. package/engine/metadata-index.mjs +15 -8
  45. package/engine/name-forms.mjs +99 -0
  46. package/engine/name-refs.mjs +143 -0
  47. package/engine/name-rows.mjs +11 -1
  48. package/engine/names.mjs +27 -22
  49. package/engine/note-addresses.mjs +0 -3
  50. package/engine/note-frontmatter.mjs +3 -5
  51. package/engine/note-language.mjs +348 -0
  52. package/engine/note-vocabulary.mjs +13 -11
  53. package/engine/pdf-index.mjs +3 -2
  54. package/engine/pdf-render.mjs +2 -4
  55. package/engine/settlement-tables.mjs +4 -3
  56. package/engine/site-build.mjs +2 -7
  57. package/engine/site-search.mjs +3 -5
  58. package/engine/site-theme.mjs +1 -1
  59. package/engine/sql-tables.mjs +29 -14
  60. package/engine/wikilink-syntax.mjs +2 -0
  61. package/engine/word-citations.mjs +3 -3
  62. package/engine/word-rows.mjs +3 -1
  63. package/engine/word-terms.mjs +2 -2
  64. package/package.json +1 -1
  65. package/site-theme/static/css/style.css +0 -4
  66. package/types/engine/changelog-group.d.mts +6 -10
  67. package/types/engine/changelog-labels.d.mts +10 -0
  68. package/types/engine/changelog-lint.d.mts +11 -6
  69. package/types/engine/content-index.d.mts +16 -16
  70. package/types/engine/diagnostics.d.mts +1 -1
  71. package/types/engine/first-use.d.mts +97 -1
  72. package/types/engine/frontmatter-lint.d.mts +9 -2
  73. package/types/engine/glossary-language.d.mts +13 -6
  74. package/types/engine/homepage.d.mts +0 -3
  75. package/types/engine/literature-notes.d.mts +2 -27
  76. package/types/engine/name-forms.d.mts +61 -0
  77. package/types/engine/name-refs.d.mts +51 -0
  78. package/types/engine/name-rows.d.mts +4 -0
  79. package/types/engine/names.d.mts +12 -92
  80. package/types/engine/note-frontmatter.d.mts +1 -4
  81. package/types/engine/note-language.d.mts +47 -0
  82. package/types/engine/settlement-tables.d.mts +1 -1
  83. package/types/engine/site-build.d.mts +2 -6
@@ -122,8 +122,8 @@ Item link.
122
122
  order** — the very table each `### type:` section below states. There is no
123
123
  second list, so a key added to a type appears in the book, on the website and
124
124
  in a compendium journal with no further edit. A `Name` row stands first on
125
- every note, because every note has one. An `Aliases` row follows it when the
126
- note names any aliases, preserving their authored order.
125
+ every note, because every note has one. An `Other names` row follows it when
126
+ the note's `name` lists any forms, preserving their authored order.
127
127
 
128
128
  A few keys carry no row, and the reason in each case is one of exactly three —
129
129
  the key is **machinery**, steering a build or an interface rather than
@@ -378,8 +378,13 @@ Any other top-level key is an error. To keep an author-only note beside the
378
378
  content, comment out its YAML lines with `#`. Comments remain valid YAML text
379
379
  and do not become data in the JSONL index, generated pages, or Foundry documents.
380
380
 
381
- `name` is a map with a required nonempty `full` string when present. It may
382
- also contain `aliases`, an ordered list of nonempty strings, and `sort`, a nonempty
381
+ `name` is a map with a required nonempty `full` string when present: the
382
+ English name a page, a compendium entry and an index print. Every other name
383
+ the subject goes by is an ordered list of nonempty strings under the code of
384
+ its language, a code [`languages:`](../configuration.md#languages) declares or
385
+ `en`. `full` counts as an English form, so a form under `en` that repeats it,
386
+ ignoring case, is an error at the form. The first form in each list is that
387
+ language's standard form. `name` may also contain `sort`, a nonempty
383
388
  string giving the form the name takes in an index, such as `Black Flame, The` or
384
389
  `Hilvan, Doran`. `sort` files the note wherever notes are ordered by name (page
385
390
  lists, generated lists of related notes, the book index, the `nameSort` column)
@@ -387,8 +392,18 @@ and is the note's entry text in the book index; every other list still displays
387
392
  `full`. Without `sort`, the note files and indexes by `full`. Ordering compares
388
393
  the ASCII fold of the key (`Árdavon` files beside `Ardavon`). A being with
389
394
  `subType: character` may additionally contain nonempty `given` and `clan`
390
- strings. Other keys under `name` are errors. For a character or NPC, the first
391
- alias is its nickname. A being's homes belong in `data.homes`.
395
+ strings. Other keys under `name` are errors at the key. For a character or
396
+ NPC, the first English form is its nickname. A being's homes belong in
397
+ `data.homes`.
398
+
399
+ ```yaml
400
+ name: { full: Johnathan Lewis, en: [John, Long John], vyla: [juan juis] }
401
+ ```
402
+
403
+ Names match whatever their case: matching folds case, and a page displays a
404
+ name as the note writes it. Two notes whose forms differ only by case are one
405
+ ambiguous name, reported where a span or label uses it, like any other name two
406
+ notes share.
392
407
 
393
408
  There is no custom site metadata. `description` supplies the page's short
394
409
  description; `tags` carries publication and classification tags.
@@ -466,6 +481,76 @@ infobox's `born` and `died`, `dateformat` with no calendar named, the `events`
466
481
  relation's `whenText`, and every date in the [event views](#event-views) the
467
482
  note's page shows.
468
483
 
484
+ ##### A note's language
485
+
486
+ Every note is in one language, a code
487
+ [`languages:`](../configuration.md#languages) declares or `en`, which needs no
488
+ declaration. It is the first of:
489
+
490
+ 1. its own `data.lang`, which every note type accepts;
491
+ 2. its culture's language: the culture note its `data.culture` names,
492
+ resolved by these same rules;
493
+ 3. its parents' language: each note its `data.parents` names, nearest first
494
+ and in the order the list gives them, resolved by these same rules;
495
+ 4. `en`.
496
+
497
+ Steps 2 and 3 take only a language some note states. A culture or a parent
498
+ that itself falls through to `en` contributes nothing, and the chain goes on to
499
+ the next parent. A culture note's language is its own `data.lang`, else its
500
+ parent cultures'. A culture or parent in another package contributes the
501
+ language its published entry carries. A being, an affiliation or a place with a
502
+ culture takes its culture's language; a place with no culture takes its
503
+ region's.
504
+
505
+ ```yaml
506
+ # package-build.config.yaml
507
+ languages:
508
+ reed: { tag: art-x-reed, note: skill-reedtongue }
509
+ ```
510
+
511
+ ```yaml
512
+ # Cultures/Reedfolk.md
513
+ shortcode: reedfolk
514
+ type: lore
515
+ subType: culture
516
+ data: { lang: reed }
517
+ ```
518
+
519
+ ```yaml
520
+ # Places/Marsh.md — takes reed from its culture
521
+ shortcode: marsh
522
+ type: place
523
+ data: { culture: lore-reedfolk }
524
+ ```
525
+
526
+ ```yaml
527
+ # Places/Landing.md — takes reed from its parent, the marsh
528
+ shortcode: landing
529
+ type: place
530
+ data: { parents: [place-marsh] }
531
+ ```
532
+
533
+ The content index publishes the result on every note record as `lang`, and
534
+ each language note that `languages:` names carries its code as `languageCode`,
535
+ so a reader holding only the records maps a code to its note. A note whose
536
+ subject has two tongues still has one language; its `name` lists the forms of
537
+ both.
538
+
539
+ Three things are errors, each at the value that causes it:
540
+
541
+ - a `data.lang` naming no declared code, nor `en`;
542
+ - a `data.culture` whose culture resolves to no language: the culture states
543
+ no `data.lang` and inherits none from its parent cultures;
544
+ - every `data.parents` entry on a cycle, whether or not a note's language
545
+ depends on it: each note of the cycle is reported at the entry naming the
546
+ next. A cycle among culture notes is the
547
+ [culture parents](#culture-parents-and-inherited-fields) check's finding
548
+ instead.
549
+
550
+ ```text
551
+ Places/Landing.md:4:19: error: data.parents.0 names place-marsh, which closes a parents cycle; a note is never its own ancestor
552
+ ```
553
+
469
554
  Markdown prose accepts inline `{{...}}` expressions. A property path reads
470
555
  the note's frontmatter, and `dateformat` converts a date to the reckoning used by a
471
556
  calendar. The first argument names a calendar note by shortcode or Address, or
@@ -908,6 +993,7 @@ noticed:
908
993
  | `seeAlso[].address` | a note `Address` | Required; the whole note to read next. |
909
994
  | `seeAlso[].gloss` | `string` | An optional short phrase saying why to follow the reference. |
910
995
  | `calendar` | `Address` | The calendar note this note's dates print in — see [a note's calendar](#a-notes-calendar). |
996
+ | `lang` | language code | The language the note is in — see [a note's language](#a-notes-language). |
911
997
  | `id` | `string` | A pinned document identity. |
912
998
  | `pack` | `string` | The shared compendium route. |
913
999
  | `packFolder` | `Address` or pack map | The shared compendium folder Address. |
@@ -1817,8 +1903,9 @@ There is one namespace, and the pipe is required:
1817
1903
  **A link written without a label addresses nothing**, and the correction
1818
1904
  is always the same: write `[[type-shortcode|Text]]`.
1819
1905
 
1820
- The bare form does not resolve by display name or alias. `name.aliases` is
1821
- indexed for search and completion, while an authored link names an Address.
1906
+ The bare form does not resolve by display name or listed form. A note's
1907
+ listed forms are indexed for search and completion, while an authored link
1908
+ names an Address.
1822
1909
 
1823
1910
  Requiring the label is also what makes positional parsing safe. Note names
1824
1911
  contain hyphens — `Grukar-ahk` is a name, not a `Grukar` of type `ahk` — so a
@@ -1866,48 +1953,67 @@ text itself as a spoiler; it declares no destination audience. See
1866
1953
 
1867
1954
  #### Marking names in prose
1868
1955
 
1869
- `package-build lint` reports name-marking warnings in authored body prose.
1870
- The warnings leave a valid package passing. Headings, frontmatter, tables,
1871
- infoboxes, code, comments and embeds are outside this check.
1872
-
1873
- A name is explicit: a `[Name]{.name}` bracket span or an authored link label.
1874
- Use typed `.name` spans for unwritten subjects and ordinary wikilinks for
1875
- indexed subjects, including private ones. Mark or link another subject at its
1876
- first prose use, and use plain text for the note's own subject and for later
1877
- mentions and aliases. A wikilink identifies its note, so its label is whatever
1878
- reads naturally in the sentence: `[[place-vedyara|Vedyara]]` for a note whose
1879
- full name is _Vedyara Region_, and a lowercase article mid-sentence
1880
- (`[[place-southwall|the Southern Wall]]`). A `.name` span has no note behind
1881
- it, so it carries the full name.
1882
- Plain prose is not searched for names. Wikilinks, ordinary Markdown links and
1883
- reference links all supply names; a resolved empty wikilink label uses the
1884
- note's full name. Images, code, footnote markers and bare autolinks without
1885
- authored labels supply none.
1886
-
1887
- 1. A `.name` span whose whole text matches an indexed `name.full` or
1888
- `name.aliases` should be a link. Use `[[place-arden|Arden Vale]]` or
1889
- `[[place-arden|]]` to introduce that note. A span with a `data-type`
1890
- matches only notes of that type, and only notes of that subtype when it
1891
- names one; an untyped span matches a note of any type. One name can
1892
- belong to two things, so
1956
+ A name in prose is explicit: a `[Name]{.name}` bracket span or a name
1957
+ wikilink, `[[place-arden|Arden Vale]]{.name}`. Plain prose, bold and ordinary
1958
+ link labels are never read as names.
1959
+
1960
+ ##### The first use of a name
1961
+
1962
+ The first use of each name in a page is bold when the page renders, on the
1963
+ website, in the Foundry journal and in the book. Bold an author writes is the
1964
+ author's choice, and a name inside authored bold takes no second bold. Each use is keyed, and the first use of each key is the bold one:
1965
+
1966
+ 1. A name wikilink is keyed by its address. Every spelling of one address is
1967
+ one key, and so is each system's document of one note:
1968
+ `[[place-arden|the vale]]{.name}` and `[Vale]{.name ref=test-note-place-arden}`
1969
+ share a key.
1970
+ 2. A `.name` span with a `ref` is keyed by the `ref`: a note address, read as a
1971
+ wikilink's is, or a page-local key such as `ref="#jane"`.
1972
+ 3. Any other `.name` span is keyed by its label, case folded, with its `lang`
1973
+ (`en` when the span states none). `[Old Tam]{.name}` and
1974
+ `[old tam]{.name}` share a key; `[old tam]{.name lang=vyl}` has its own.
1975
+
1976
+ Only body prose counts: paragraphs, list items, quotations and footnotes, in
1977
+ source order. Headings, tables, captions, the title line of a named block,
1978
+ raw HTML, code, verse and the generated sections neither take the bold nor
1979
+ count as a use, and neither does a name inside a span or div that states
1980
+ `lang`, `font` or `enc`, which is that run's text. A name inside authored
1981
+ strong text counts as its key's first use and takes no second bold. A
1982
+ wikilink without the `name` class is a link, not a name, and neither takes
1983
+ the bold nor counts.
1984
+
1985
+ ```markdown
1986
+ [Jane Doe]{.name ref="#jane"} keeps the ferry to [[place-harbor|the harbor]]{.name}.
1987
+ [Jane]{.name ref="#jane"} rows it alone, and the river folk call her
1988
+ [Miss Gorgeous]{.name ref="#jane"}. [Old Tam]{.name} mends the nets at
1989
+ [[place-harbor|the harbor]]{.name}, and [old tam]{.name} sells them.
1990
+ ```
1991
+
1992
+ _Jane Doe_, the first _the harbor_ and _Old Tam_ are bold; every later use is
1993
+ not.
1994
+
1995
+ ##### Name-marking findings
1996
+
1997
+ `package-build lint` reports two name-marking warnings in authored body prose.
1998
+ They leave a valid package passing. Headings, frontmatter, tables, infoboxes,
1999
+ code, comments and embeds are outside both.
2000
+
2001
+ 1. A `.name` span without a `ref` whose whole text matches an indexed
2002
+ `name.full` or a form its `name` lists, ignoring case, should be a link or
2003
+ carry a `ref`: `[[place-arden|Arden Vale]]{.name}`,
2004
+ `[[place-arden|]]{.name}` or `[Arden]{.name ref=place-arden}`. A span with
2005
+ a `data-type` matches only notes of that type, and only notes of that
2006
+ subtype when it names one; an untyped span matches a note of any type. One
2007
+ name can belong to two things, so
1893
2008
  `[Theinuvael]{.name data-type="affiliation/lineage"}` draws no warning
1894
- when _Theinuvael_ is an alias of a place note, while
2009
+ when _Theinuvael_ is a listed form of a place note, while
1895
2010
  `[Theinuvael]{.name data-type="place"}` and `[Theinuvael]{.name}` should
1896
- be links to it. The same match decides a span's identity for the rules
1897
- below and for the unwritten-name advisory.
1898
- 2. Mark or link each name at most once per note. An indexed full name and its
1899
- declared aliases share one identity, including across different heading
1900
- anchors. Other labels use their whole text as their identity: different
1901
- labels linking to one page are separate names, and a label is not
1902
- automatically an alias of its destination.
1903
- 3. A `.name` span or an ordinary Markdown link introduces the full name
1904
- before a short form or declared alias. A resolved wikilink introduces its
1905
- note under any label. Possessives and regular plurals count as uses; other
1906
- indexed forms can be declared aliases.
2011
+ be linked or tied to it. The same match decides a span's identity for the
2012
+ unwritten-name advisory.
1907
2013
 
1908
2014
  Bold is emphasis and is never read as a name. A bold label such as
1909
2015
  `**Strength**:` is ordinary emphasis even when its text matches an indexed
1910
- full name or alias, and it supplies no name occurrence or introduction.
2016
+ full name or listed form.
1911
2017
 
1912
2018
  Inline Markdown remains active inside name spans, and name spans remain
1913
2019
  valid inside emphasis:
@@ -1916,12 +2022,11 @@ valid inside emphasis:
1916
2022
  **This is a phrase with [Joe Blow]{.name} in it**
1917
2023
  ```
1918
2024
 
1919
- The name is `Joe Blow`; the surrounding phrase is emphasis. Sites and books display
1920
- `.name` text in bold.
2025
+ The name is `Joe Blow`; the surrounding phrase is emphasis.
1921
2026
 
1922
- Each affected occurrence produces one warning at its authored
1923
- `file:line:column`, naming the full name or explicit label. A warning
1924
- can describe several marking problems at that occurrence.
2027
+ Each finding is one warning at its authored `file:line:column`, naming the
2028
+ full name or explicit label. A warning can describe both findings at one
2029
+ occurrence.
1925
2030
 
1926
2031
  An optional `data-type` on a `.name` span states what the named thing is:
1927
2032
 
@@ -1938,20 +2043,35 @@ at the `data-type` attribute's file, line and UTF-16 column. The same attribute
1938
2043
  on a span without the exact `name` class is an ordinary attribute. An untyped
1939
2044
  `.name` is valid; its type is not inferred from a matching note.
1940
2045
 
2046
+ An optional `ref` on a `.name` span ties the span to its note without linking
2047
+ it: a note address such as `being-tomr`, or a declared dependency's with its
2048
+ package prefix, `sohl-note-being-tomr`. The address states the type, so
2049
+ `data-type` beside `ref` is an error at `data-type`. A `ref` that resolves to
2050
+ no note in this package or its declared dependencies is an error at the
2051
+ attribute's value, and `ref` on a span without `.name` is an error at `ref`. A
2052
+ wikilink never takes `ref`. A value beginning `#` is a page-local key, such as
2053
+ `ref="#jane"`, for a subject with no note: it ties every spelling carrying it
2054
+ to one subject within the page, resolves to no note and is never a finding for
2055
+ that reason. A key is `#` followed by letters, digits, `_` and `-`, starting
2056
+ with a letter or digit; it is the attribute's value, never the span's `{#id}`
2057
+ anchor. A `ref` span draws no warning to link the name, and its first use is
2058
+ bold under the `ref`'s key. Site and Foundry spans retain `ref` as they retain
2059
+ `data-type`; the book adds nothing.
2060
+
1941
2061
  The index captures actual `.name` spans throughout the authored body, including
1942
- headings, tables, verse and spans within links. The prose-only marking checks
1943
- above keep their narrower scope. Frontmatter, literal code, escaped syntax,
2062
+ headings, tables, verse and spans within links. The first-use bold and the
2063
+ prose-only marking checks above keep their narrower scope. Frontmatter, literal code, escaped syntax,
1944
2064
  unmarked link labels, bold, plain prose and generated content add no names.
1945
2065
  The rendered visible text preserves its spelling and inline content.
1946
2066
 
1947
2067
  Each own-note metadata record carries `names` in authored order. Every entry
1948
- has exactly `name`, `type`, `subType`, `line` and `column`; absent
1949
- classifications are explicit `null`, and no occurrences gives an empty array.
2068
+ has exactly `name`, `type`, `subType`, `ref`, `line` and `column`; absent
2069
+ classifications and an absent `ref` are explicit `null`, and no occurrences gives an empty array.
1950
2070
  This is derived metadata, not frontmatter. Documentation mirrors and assets
1951
2071
  do not duplicate a note's occurrences. The [`names` relation](#content-tables)
1952
2072
  flattens these entries with their containing NOTE Address.
1953
2073
 
1954
- Lint groups names without an indexed full-name or alias match, among notes
2074
+ Lint groups names without an indexed full-name or listed-form match, among notes
1955
2075
  of the span's type and subtype when it supplies them, by supplied
1956
2076
  classification and lists all their source uses. It also groups conflicting
1957
2077
  annotations of the same visible name. Untyped uses do not conflict. A bare
@@ -3457,11 +3577,12 @@ row has these columns, including on an empty relation:
3457
3577
  | `name` | `VARCHAR` | Rendered visible text, preserving its spelling. |
3458
3578
  | `type` | `VARCHAR` | Supplied note type, or `NULL`. |
3459
3579
  | `subType` | `VARCHAR` | Supplied subtype, or `NULL`. |
3580
+ | `ref` | `VARCHAR` | The span's `ref=` as written, a note address or a page-local `#key`, or `NULL`. |
3460
3581
  | `line` | `BIGINT` | Original 1-based source line at the span's opening `[`. |
3461
3582
  | `column` | `BIGINT` | Original 1-based UTF-16 source column at that `[`. |
3462
3583
 
3463
3584
  ```sql
3464
- SELECT owner, name, type, subType, line, "column"
3585
+ SELECT owner, name, type, subType, ref, line, "column"
3465
3586
  FROM names
3466
3587
  WHERE type = 'place'
3467
3588
  ORDER BY owner, line, "column"
@@ -3566,16 +3687,18 @@ in `data.parents`. Each entry is an Address naming another culture lore note;
3566
3687
  a missing target, a target of another type or subtype, and a parent cycle are
3567
3688
  errors at the offending list entry. No other lore subtype accepts the key.
3568
3689
 
3569
- A culture inherits `data.language` and `data.appearanceProfile` independently
3570
- when it leaves either field out. A stated value wins for that field. The
3690
+ A culture inherits `data.appearanceProfile` when it leaves the field out, and a
3691
+ stated value wins. Its language comes down the same parents, as
3692
+ [a note's language](#a-notes-language) describes. The
3571
3693
  profile is inherited as one complete object; its weights and ranges are not
3572
3694
  merged with another profile. Parents are searched in listed order, depth-first:
3573
3695
  the first parent's chain is searched before the next parent's chain. Sources
3574
- at the same depth that disagree on a field produce a finding. Nothing is
3696
+ at the same depth that disagree on the profile produce a finding. Nothing is
3575
3697
  inherited through a broken parent address.
3576
3698
 
3577
- The emitted content-index JSONL carries the resolved fields in the child's
3578
- `data`, exactly as if the child had stated them. `package-build npc new` and
3699
+ The emitted content-index JSONL carries the resolved profile in the child's
3700
+ `data`, exactly as if the child had stated it, and the derived language as the
3701
+ record's `lang`. `package-build npc new` and
3579
3702
  other consumers read those resolved values; they do not walk culture parents.
3580
3703
  The child's `data.culture` remains its own Address. A being, place or
3581
3704
  affiliation naming the parent in `data.culture` belongs to that named culture;
@@ -3590,7 +3713,7 @@ name: { full: Reedfolk }
3590
3713
  type: lore
3591
3714
  subType: culture
3592
3715
  data:
3593
- language: skill-reedtongue
3716
+ lang: reed
3594
3717
  appearanceProfile:
3595
3718
  frame: { medium: 1 }
3596
3719
  eye_color: { brown: 1 }
@@ -3622,7 +3745,8 @@ beside the river's deep channels, where their boats carry grain, timber and
3622
3745
  woven reeds between settlements.
3623
3746
  ```
3624
3747
 
3625
- The parent names this language note, whose lists supply generated names:
3748
+ The parent's language is `reed`, which `languages:` maps to this language note,
3749
+ whose lists supply generated names:
3626
3750
 
3627
3751
  ```markdown
3628
3752
  ---
@@ -3645,17 +3769,14 @@ given name followed by a family name, and carry those names between river
3645
3769
  settlements with their trade.
3646
3770
  ```
3647
3771
 
3648
- In a package named `reedflats`, the Riverfolk index record carries the Reedfolk
3649
- profile and `data.language` as a published Address object:
3650
-
3651
- ```json
3652
- { "address": "reedflats-note-skill-reedtongue", "anchor": null, "anchorKind": null }
3653
- ```
3772
+ In a package named `reedflats` whose configuration maps `reed` to
3773
+ `skill-reedtongue`, the Riverfolk index record carries the Reedfolk profile in
3774
+ its `data` and the language as `"lang": "reed"`.
3654
3775
 
3655
- Adding `language: skill-rivertongue` to Riverfolk's `data` selects that language
3656
- instead while retaining the inherited profile, provided the named language
3657
- note exists. Stating an `appearanceProfile` there replaces the inherited
3658
- profile while leaving the inherited tongue in place.
3776
+ Adding `lang: river` to Riverfolk's `data` selects that language instead while
3777
+ retaining the inherited profile, provided `languages:` declares `river`.
3778
+ Stating an `appearanceProfile` there replaces the inherited profile while
3779
+ leaving the inherited tongue in place.
3659
3780
 
3660
3781
  ##### Culture in the index
3661
3782
 
@@ -3952,7 +4073,7 @@ The watch wears [a _blue_ sash]{#watch-sash .uniform lang=en}.
3952
4073
  ```
3953
4074
 
3954
4075
  The exact `.name` class marks a name, with optional `data-type="type/subType"`;
3955
- see [marking names in prose](#marking-names-in-prose) for the vocabulary and index.
4076
+ see [marking names in prose](#marking-names-in-prose) for the vocabulary, `ref=` and index.
3956
4077
  The exact `.secret` class marks the enclosed text as an inline spoiler:
3957
4078
 
3958
4079
  ```markdown
@@ -3964,8 +4085,8 @@ The website provides an inline show/hide button and preserves interactive links
3964
4085
  inside the revealed content. Foundry renders a focusable, CSS-redacted inline
3965
4086
  span that reveals its text and nested content on hover or keyboard focus.
3966
4087
  Native Foundry secret sections retain their own controls. Books ignore `.secret`
3967
- on inline spans, preserving their text, emphasis, links, anchors and `.name`
3968
- bold styling. Secret sections and `:::secret` fences keep their visible labelled
4088
+ on inline spans, preserving their text, emphasis, links, anchors and a name's
4089
+ first-use bold. Secret sections and `:::secret` fences keep their visible labelled
3969
4090
  boxes. Published HTML retains the text, so opening the spoiler or inspecting the
3970
4091
  source reveals it.
3971
4092
 
@@ -4783,9 +4904,9 @@ culture note. A culture may obtain the complete profile from its
4783
4904
  `package-build npc new` draws a person's name from it, or checks a name it is
4784
4905
  given against it — see [the command](../commands.md#package-build-npc-new).
4785
4906
  Only a `skill` note of `subType: language` takes the key; on any other skill it
4786
- is an error at the key. A culture reaches the lists through `data.language`,
4787
- which names the language skill note its people speak, so cultures sharing a
4788
- tongue share its lists.
4907
+ is an error at the key. A culture reaches the lists through its
4908
+ [language](#a-notes-language): the note `languages:` names for its code, so
4909
+ cultures sharing a tongue share its lists.
4789
4910
 
4790
4911
  The lists have two required keys, and any number of lists named by the
4791
4912
  language:
@@ -5413,44 +5534,43 @@ rank names the standing, and the standing says.
5413
5534
 
5414
5535
  **Standing**: aligned, unaligned, rival, nemesis
5415
5536
 
5416
- | `data` property | Values | Description |
5417
- | ----------------------------------------------- | ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
5418
- | `templatePriority` | `number` | Template priority, _null_ = not a template |
5419
- | `events` | event entries — see [Events](#events) | What happened to or at this subject: dated, attributed events |
5420
- | `demonym` | `string` | What a member of this affiliation is called (a Vylarian) |
5421
- | `epithet` | `string` | The by-name it is known by — a god's, an order's, a company's |
5422
- | `symbol` | `string` | Its emblem in words: a feather atop a golden scale, a chisel carving a star |
5423
- | `governance.model` | `GovernanceModel` | Type of government structure, if applicable |
5424
- | `governance.summary` | `string` | summary of the governance situation |
5425
- | `governance.ranks` | `Rank[]` | The ranks the affiliation confers; level 0 and level 1 are required |
5426
- | `governance.ranks[].level` | `integer`, required | The rung's position on this body's ladder; a member's `rank` names it |
5427
- | `governance.ranks[].title` | `string`, required | What the standing is called |
5428
- | `governance.ranks[].description` | `string`, required | What the standing is |
5429
- | `governance.ranks[].lore` | `Address` | The `law` lore note stating what the standing is, shared with every body that confers it |
5430
- | `governance.offices` | `Map<name, description \| {description, holders}>` | Official offices and their dated holders |
5431
- | `governance.offices.<name>` | `string` or `{ description, holders }` | One office, keyed by its name: its description, or a map of description and holders |
5432
- | `governance.offices.<name>.description` | `string`, required | What the office is |
5433
- | `governance.offices.<name>.holders` | `{ being, start?, end?, contested? }[]`, required | Who has held the office, each with the dates of the term |
5434
- | `governance.offices.<name>.holders[].being` | `Address`, required | The `being` who held it |
5435
- | `governance.offices.<name>.holders[].start` | `date` | When the term began; omitted, it began before anything recorded |
5436
- | `governance.offices.<name>.holders[].end` | `date` | When the term ended; omitted, the being holds the office now |
5437
- | `governance.offices.<name>.holders[].contested` | `boolean` | `true` where the term may overlap another holder's |
5438
- | `seat` | `Address` | Where the affiliation's authority sits |
5439
- | `population` | `number` | Number of people in the affiliation (precision 2 significant digits). |
5440
- | `economy` | `Address[]` | Economic life: `affiliation` or `lore` Addresses, with an explicit type and no default |
5441
- | `lore` | `Address[]` | Lore concerning it — the peoples it draws on, the god a faith venerates, its law, its calendar |
5442
- | `parents` | `Address[]` | Affiliations that this affiliation is subordinate to |
5443
- | `culture` | `Address` | The people this affiliation belongs to, naming a lore note with `subType: culture` |
5444
- | `language` | `Address` | The trade, temple or order tongue it keeps, naming a skill note with `subType: language` |
5445
- | `glossary` | `{ name, name_sort?, common?, definition?, pronunciation?, language? }[]` | Its own glossary terms — see [glossary terms](#glossary-terms) |
5446
- | `glossary[].name` | `string`, required | The headword |
5447
- | `glossary[].name_sort` | `string` | Its sort key; the matching word's, else the name, when unstated |
5448
- | `glossary[].common` | `boolean` | `true` for a term in this owner's core vocabulary; `false` when unstated |
5449
- | `glossary[].definition` | `string` | Its context meaning or own gloss; unstated, a matching dictionary word supplies its senses |
5450
- | `glossary[].pronunciation` | `string` | A respelling, as `sol-MEH-reh`: letters, apostrophes and hyphens, at most one syllable in capitals |
5451
- | `glossary[].language` | `Address` | The language the term is in, naming a skill note with `subType: language`; unstated, the affiliation's, its parents' or its culture's |
5452
- | `relations` | `Map<Address, Standing>` | Standing with other affiliations, keyed by the other body's Address |
5453
- | `relations.<Address>` | `aligned`, `unaligned`, `rival` or `nemesis` | The standing this body holds toward that one; any other value is an error at the value |
5537
+ | `data` property | Values | Description |
5538
+ | ----------------------------------------------- | ------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
5539
+ | `templatePriority` | `number` | Template priority, _null_ = not a template |
5540
+ | `events` | event entries — see [Events](#events) | What happened to or at this subject: dated, attributed events |
5541
+ | `demonym` | `string` | What a member of this affiliation is called (a Vylarian) |
5542
+ | `epithet` | `string` | The by-name it is known by — a god's, an order's, a company's |
5543
+ | `symbol` | `string` | Its emblem in words: a feather atop a golden scale, a chisel carving a star |
5544
+ | `governance.model` | `GovernanceModel` | Type of government structure, if applicable |
5545
+ | `governance.summary` | `string` | summary of the governance situation |
5546
+ | `governance.ranks` | `Rank[]` | The ranks the affiliation confers; level 0 and level 1 are required |
5547
+ | `governance.ranks[].level` | `integer`, required | The rung's position on this body's ladder; a member's `rank` names it |
5548
+ | `governance.ranks[].title` | `string`, required | What the standing is called |
5549
+ | `governance.ranks[].description` | `string`, required | What the standing is |
5550
+ | `governance.ranks[].lore` | `Address` | The `law` lore note stating what the standing is, shared with every body that confers it |
5551
+ | `governance.offices` | `Map<name, description \| {description, holders}>` | Official offices and their dated holders |
5552
+ | `governance.offices.<name>` | `string` or `{ description, holders }` | One office, keyed by its name: its description, or a map of description and holders |
5553
+ | `governance.offices.<name>.description` | `string`, required | What the office is |
5554
+ | `governance.offices.<name>.holders` | `{ being, start?, end?, contested? }[]`, required | Who has held the office, each with the dates of the term |
5555
+ | `governance.offices.<name>.holders[].being` | `Address`, required | The `being` who held it |
5556
+ | `governance.offices.<name>.holders[].start` | `date` | When the term began; omitted, it began before anything recorded |
5557
+ | `governance.offices.<name>.holders[].end` | `date` | When the term ended; omitted, the being holds the office now |
5558
+ | `governance.offices.<name>.holders[].contested` | `boolean` | `true` where the term may overlap another holder's |
5559
+ | `seat` | `Address` | Where the affiliation's authority sits |
5560
+ | `population` | `number` | Number of people in the affiliation (precision 2 significant digits). |
5561
+ | `economy` | `Address[]` | Economic life: `affiliation` or `lore` Addresses, with an explicit type and no default |
5562
+ | `lore` | `Address[]` | Lore concerning it — the peoples it draws on, the god a faith venerates, its law, its calendar |
5563
+ | `parents` | `Address[]` | Affiliations that this affiliation is subordinate to |
5564
+ | `culture` | `Address` | The people this affiliation belongs to, naming a lore note with `subType: culture` |
5565
+ | `glossary` | `{ name, name_sort?, common?, definition?, pronunciation?, language? }[]` | Its own glossary terms — see [glossary terms](#glossary-terms) |
5566
+ | `glossary[].name` | `string`, required | The headword |
5567
+ | `glossary[].name_sort` | `string` | Its sort key; the matching word's, else the name, when unstated |
5568
+ | `glossary[].common` | `boolean` | `true` for a term in this owner's core vocabulary; `false` when unstated |
5569
+ | `glossary[].definition` | `string` | Its context meaning or own gloss; unstated, a matching dictionary word supplies its senses |
5570
+ | `glossary[].pronunciation` | `string` | A respelling, as `sol-MEH-reh`: letters, apostrophes and hyphens, at most one syllable in capitals |
5571
+ | `glossary[].language` | `Address` | The language the term is in, naming a skill note with `subType: language`; unstated, the note of the affiliation's language |
5572
+ | `relations` | `Map<Address, Standing>` | Standing with other affiliations, keyed by the other body's Address |
5573
+ | `relations.<Address>` | `aligned`, `unaligned`, `rival` or `nemesis` | The standing this body holds toward that one; any other value is an error at the value |
5454
5574
 
5455
5575
  **An affiliation names the people it belongs to in `data.culture`.** An
5456
5576
  affiliation that names none takes its culture from its `data.parents`. A
@@ -5459,8 +5579,8 @@ together with every place whose `data.government` names it. See
5459
5579
  [Culture in the index](#culture-in-the-index).
5460
5580
 
5461
5581
  **An affiliation may keep a tongue of its own.** A trade cant, a temple
5462
- language or an order's tongue is named in the affiliation's `data.language`, and
5463
- it supplies the language of the affiliation's own
5582
+ language or an order's tongue is the affiliation's `data.lang`, and its note
5583
+ supplies the language of the affiliation's own
5464
5584
  [glossary terms](#glossary-terms) where an entry names none. A culture can
5465
5585
  select a word of that tongue for its own glossary by naming the language on
5466
5586
  the entry. In a tree that holds at least one culture note, an
@@ -6405,7 +6525,7 @@ note cites a word when its body marks the word in italics, `_amère_` or
6405
6525
  `*amère*`: an italic span holding text alone, no link and no code, whose text
6406
6526
  is the word's form or one of its `variants`, compared with diacritics taken off
6407
6527
  and case folded, so `_Amere_` cites `amère` too. A note also cites a word its
6408
- frontmatter names whole, under the same folding: a full name or an alias that
6528
+ frontmatter names whole, under the same folding: a full name or a listed form that
6409
6529
  spells the word, or an affiliation's rank or office title that does. An italic
6410
6530
  span or a name that spells no word cites nothing, and neither does a word
6411
6531
  found only inside a longer name. A language note never cites its own words,
@@ -6665,7 +6785,7 @@ and affixes, its pieces as a word's `built` writes them; `gloss` says what the
6665
6785
  name means where the pages give its sense, and `why` says why a name stands
6666
6786
  outside the pattern. Which notes carry a name is not
6667
6787
  written: the `register` relation derives it from the index — every note in
6668
- `scope` having it as its full name, an alias or a part of its name, every
6788
+ `scope` having it as its full name, a listed form or a part of its name, every
6669
6789
  affiliation in `scope` having it as a rank or office title, and every anchor of
6670
6790
  a note in `scope` having it as its name. A folder note carries no name, and a
6671
6791
  language that states no `scope` reads every note of the package.
@@ -7128,57 +7248,56 @@ not a different cultural identity. See
7128
7248
  [Culture parents](#culture-parents-and-inherited-fields) and
7129
7249
  [Culture in the index](#culture-in-the-index).
7130
7250
 
7131
- | `data` property | Values | Description |
7132
- | ------------------------------------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
7133
- | `epoch` | canonical `<year>.<day>` | The canonical day that equals calendar year 1, day 1 |
7134
- | `months` | `{ name, abbreviation?, days }[]` | Ordered months; their days sum to the world's year |
7135
- | `months[].name` | `string`, required | The month's name |
7136
- | `months[].abbreviation` | `string` | Its short form, for a compact date |
7137
- | `months[].days` | `integer`, required | How many days the month holds |
7138
- | `weekdays` | `{ name, abbreviation? }[]` | Ordered week days, indexed from zero; weeks run continuously |
7139
- | `weekdays[].name` | `string`, required | The day's name |
7140
- | `weekdays[].abbreviation` | `string` | Its short form, for a compact date |
7141
- | `seasons` | `{ name, abbreviation?, start }[]` | Seasons starting on one-based days of year |
7142
- | `seasons[].name` | `string`, required | The season's name |
7143
- | `seasons[].abbreviation` | `string` | Its short form, for a compact date |
7144
- | `seasons[].start` | `integer`, required | The one-based day of the year it begins; starts increase down the list |
7145
- | `namedDays` | `{ name, abbreviation?, day }[]` | Names assigned to one-based days of year |
7146
- | `namedDays[].name` | `string`, required | The day's name |
7147
- | `namedDays[].abbreviation` | `string` | Its short form, for a compact date |
7148
- | `namedDays[].day` | `integer`, required | The one-based day of the year it names, distinct within the calendar |
7149
- | `eras` | `{ shortcode, name, abbreviation?, marker?, proclaimedBy?, start, label? }[]` | Year counts; `start` is `null` or an in-calendar year |
7150
- | `eras[].shortcode` | `string`, required | The era's own segment of `<calendar>.<era>`, unique within the calendar |
7151
- | `eras[].name` | `string`, required | The era's name |
7152
- | `eras[].marker` | `string` | Uppercase letters and digits, beginning with a letter, unique across the corpus; an authored date names the era by it |
7153
- | `eras[].abbreviation` | `string` | Its short form, for a compact date |
7154
- | `eras[].proclaimedBy` | `Address` | The body that began the reckoning |
7155
- | `eras[].start` | `null` or `integer`, required | The calendar year the era begins; `null` for the era before year 1 |
7156
- | `eras[].label` | `string` or `{ after?, before? }` | How a date in the era reads, around one `{date}` slot; a string is `after` |
7157
- | `eras[].label.after` | `string` | How a date from the era's start reads, with exactly one `{date}` |
7158
- | `eras[].label.before` | `string` | How a date before the era's start reads, with exactly one `{date}` |
7159
- | `formats` | map of names to Calendaria patterns | Named date formats; `std` is the preferred default |
7160
- | `culture` | `Address` | The people this lore belongs to — for a `literature` note, the people whose work it is — naming a lore note with `subType: culture`; not on a `culture` note |
7161
- | `form` | `string` | `literature` only: the kind of work in its people's own terms — `epic`, `saga`, `praise-song`, `elegy`. Free text |
7162
- | `subjects` | `Address[]` | `literature` only: the beings, places, gods and other notes the work concerns, and any event, as `note#id` |
7163
- | `parents` | `Address[]` | `culture` only: the larger cultures this one belongs to; each target is a culture lore note — see [culture parents](#culture-parents-and-inherited-fields) |
7164
- | `language` | `Address` | `literature` and `culture` only: the tongue a work is composed in, or a culture's people speak, naming a skill note with `subType: language`; `package-build npc new` draws a culture's names from that language's [name lists](#name-lists); glossary entries whose own `language` is unstated resolve to it |
7165
- | `events` | event entries — see [Events](#events) | What happened to or at this subject: dated, attributed events |
7166
- | `appearanceProfile` | `{ frame, eye_color, hair_color, skin_color, complexion, height }` | `culture` only: what its people look like, for `package-build npc new` — see [appearance profiles](#appearance-profiles) |
7167
- | `appearanceProfile.frame` | map of `frame` words to positive weights, required | How often each frame is drawn |
7168
- | `appearanceProfile.eye_color` | map of `eye_color` words to positive weights, required | How often each eye colour is drawn |
7169
- | `appearanceProfile.hair_color` | map of `hair_color` words to positive weights, required | How often each hair colour is drawn |
7170
- | `appearanceProfile.skin_color` | map of `skin_color` words to positive weights, required | How often each skin colour is drawn |
7171
- | `appearanceProfile.complexion` | map of `complexion` words to positive weights, required | How often each complexion is drawn |
7172
- | `appearanceProfile.height` | map of `gender` words to `{ min, max }`, required | Height ranges by gender; `female` and `male` are required |
7173
- | `appearanceProfile.height.<name>.min` | height in metres or feet and inches, required | The shortest height drawn for that gender |
7174
- | `appearanceProfile.height.<name>.max` | height in metres or feet and inches, required | The tallest height drawn for that gender |
7175
- | `glossary` | `{ name, name_sort?, common?, definition?, pronunciation?, language? }[]` | `culture` only: the culture's own glossary terms — see [glossary terms](#glossary-terms) |
7176
- | `glossary[].name` | `string`, required | The headword |
7177
- | `glossary[].name_sort` | `string` | Its sort key; the matching word's, else the name, when unstated |
7178
- | `glossary[].common` | `boolean` | `true` for a term in this owner's core vocabulary; `false` when unstated |
7179
- | `glossary[].definition` | `string` | Its context meaning or own gloss; unstated, a matching dictionary word supplies its senses |
7180
- | `glossary[].pronunciation` | `string` | A respelling, as `sol-MEH-reh`: letters, apostrophes and hyphens, at most one syllable in capitals |
7181
- | `glossary[].language` | `Address` | The language the term is in, naming a skill note with `subType: language`; unstated, the note's language |
7251
+ | `data` property | Values | Description |
7252
+ | ------------------------------------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
7253
+ | `epoch` | canonical `<year>.<day>` | The canonical day that equals calendar year 1, day 1 |
7254
+ | `months` | `{ name, abbreviation?, days }[]` | Ordered months; their days sum to the world's year |
7255
+ | `months[].name` | `string`, required | The month's name |
7256
+ | `months[].abbreviation` | `string` | Its short form, for a compact date |
7257
+ | `months[].days` | `integer`, required | How many days the month holds |
7258
+ | `weekdays` | `{ name, abbreviation? }[]` | Ordered week days, indexed from zero; weeks run continuously |
7259
+ | `weekdays[].name` | `string`, required | The day's name |
7260
+ | `weekdays[].abbreviation` | `string` | Its short form, for a compact date |
7261
+ | `seasons` | `{ name, abbreviation?, start }[]` | Seasons starting on one-based days of year |
7262
+ | `seasons[].name` | `string`, required | The season's name |
7263
+ | `seasons[].abbreviation` | `string` | Its short form, for a compact date |
7264
+ | `seasons[].start` | `integer`, required | The one-based day of the year it begins; starts increase down the list |
7265
+ | `namedDays` | `{ name, abbreviation?, day }[]` | Names assigned to one-based days of year |
7266
+ | `namedDays[].name` | `string`, required | The day's name |
7267
+ | `namedDays[].abbreviation` | `string` | Its short form, for a compact date |
7268
+ | `namedDays[].day` | `integer`, required | The one-based day of the year it names, distinct within the calendar |
7269
+ | `eras` | `{ shortcode, name, abbreviation?, marker?, proclaimedBy?, start, label? }[]` | Year counts; `start` is `null` or an in-calendar year |
7270
+ | `eras[].shortcode` | `string`, required | The era's own segment of `<calendar>.<era>`, unique within the calendar |
7271
+ | `eras[].name` | `string`, required | The era's name |
7272
+ | `eras[].marker` | `string` | Uppercase letters and digits, beginning with a letter, unique across the corpus; an authored date names the era by it |
7273
+ | `eras[].abbreviation` | `string` | Its short form, for a compact date |
7274
+ | `eras[].proclaimedBy` | `Address` | The body that began the reckoning |
7275
+ | `eras[].start` | `null` or `integer`, required | The calendar year the era begins; `null` for the era before year 1 |
7276
+ | `eras[].label` | `string` or `{ after?, before? }` | How a date in the era reads, around one `{date}` slot; a string is `after` |
7277
+ | `eras[].label.after` | `string` | How a date from the era's start reads, with exactly one `{date}` |
7278
+ | `eras[].label.before` | `string` | How a date before the era's start reads, with exactly one `{date}` |
7279
+ | `formats` | map of names to Calendaria patterns | Named date formats; `std` is the preferred default |
7280
+ | `culture` | `Address` | The people this lore belongs to — for a `literature` note, the people whose work it is — naming a lore note with `subType: culture`; not on a `culture` note |
7281
+ | `form` | `string` | `literature` only: the kind of work in its people's own terms — `epic`, `saga`, `praise-song`, `elegy`. Free text |
7282
+ | `subjects` | `Address[]` | `literature` only: the beings, places, gods and other notes the work concerns, and any event, as `note#id` |
7283
+ | `parents` | `Address[]` | `culture` only: the larger cultures this one belongs to; each target is a culture lore note — see [culture parents](#culture-parents-and-inherited-fields) |
7284
+ | `events` | event entries — see [Events](#events) | What happened to or at this subject: dated, attributed events |
7285
+ | `appearanceProfile` | `{ frame, eye_color, hair_color, skin_color, complexion, height }` | `culture` only: what its people look like, for `package-build npc new` — see [appearance profiles](#appearance-profiles) |
7286
+ | `appearanceProfile.frame` | map of `frame` words to positive weights, required | How often each frame is drawn |
7287
+ | `appearanceProfile.eye_color` | map of `eye_color` words to positive weights, required | How often each eye colour is drawn |
7288
+ | `appearanceProfile.hair_color` | map of `hair_color` words to positive weights, required | How often each hair colour is drawn |
7289
+ | `appearanceProfile.skin_color` | map of `skin_color` words to positive weights, required | How often each skin colour is drawn |
7290
+ | `appearanceProfile.complexion` | map of `complexion` words to positive weights, required | How often each complexion is drawn |
7291
+ | `appearanceProfile.height` | map of `gender` words to `{ min, max }`, required | Height ranges by gender; `female` and `male` are required |
7292
+ | `appearanceProfile.height.<name>.min` | height in metres or feet and inches, required | The shortest height drawn for that gender |
7293
+ | `appearanceProfile.height.<name>.max` | height in metres or feet and inches, required | The tallest height drawn for that gender |
7294
+ | `glossary` | `{ name, name_sort?, common?, definition?, pronunciation?, language? }[]` | `culture` only: the culture's own glossary terms — see [glossary terms](#glossary-terms) |
7295
+ | `glossary[].name` | `string`, required | The headword |
7296
+ | `glossary[].name_sort` | `string` | Its sort key; the matching word's, else the name, when unstated |
7297
+ | `glossary[].common` | `boolean` | `true` for a term in this owner's core vocabulary; `false` when unstated |
7298
+ | `glossary[].definition` | `string` | Its context meaning or own gloss; unstated, a matching dictionary word supplies its senses |
7299
+ | `glossary[].pronunciation` | `string` | A respelling, as `sol-MEH-reh`: letters, apostrophes and hyphens, at most one syllable in capitals |
7300
+ | `glossary[].language` | `Address` | The language the term is in, naming a skill note with `subType: language`; unstated, the note's language |
7182
7301
 
7183
7302
  `data.events` is available on every `lore` subType, and is described in full under [Events](#events).
7184
7303
 
@@ -7242,22 +7361,16 @@ word.
7242
7361
  **Every entry resolves to a language**, and the first match wins:
7243
7362
 
7244
7363
  1. the entry's own `language`;
7245
- 2. on an affiliation, its own `data.language`, then the nearest parent
7246
- affiliation's, nearest first and parents in the order `data.parents` lists
7247
- them, then its culture's `data.language`;
7248
- 3. on a culture, its own `data.language`.
7364
+ 2. the note `languages:` names for the [language](#a-notes-language) of the
7365
+ note the entry is written on: its own `data.lang`, its culture's, or its
7366
+ parents'.
7249
7367
 
7250
- On lore and affiliation notes, `data.language` and
7251
- `data.glossary[].language` name language notes. Use `skill-provnzlng` for a
7368
+ `data.glossary[].language` names a language note. Use `skill-provnzlng` for a
7252
7369
  language in this package, or `<pkg>-note-skill-provnzlng` for its complete
7253
7370
  NOTE Address. Any other system segment, including `sohl`, is an error at the
7254
7371
  authored value. A SOHL skill Address names a compiled Item.
7255
7372
 
7256
- An affiliation's culture is the one it states or inherits, as
7257
- [Culture in the index](#culture-in-the-index) describes, and a culture's
7258
- `data.language` includes one it inherits from its
7259
- [parent cultures](#culture-parents-and-inherited-fields). An entry in another
7260
- tongue names that language explicitly:
7373
+ An entry in another tongue names that language explicitly:
7261
7374
 
7262
7375
  ```yaml
7263
7376
  # Affiliations/Wardens.md — an order with a cant of its own
@@ -7265,7 +7378,7 @@ type: affiliation
7265
7378
  subType: order
7266
7379
  data:
7267
7380
  culture: lore-sinaleclt
7268
- language: skill-tradelng
7381
+ lang: trade
7269
7382
  glossary:
7270
7383
  - { name: zarq, common: true } # a word of the cant
7271
7384
  - { name: gate-oath, definition: "the oath sworn at the gate" } # in the cant
@@ -7279,7 +7392,8 @@ Each finding is located at the entry's key:
7279
7392
  - Two entries of one name in one glossary are an error at the second. Names are
7280
7393
  compared after NFC normalisation, with case kept.
7281
7394
  - An entry that resolves to no language is an error at the entry: state its
7282
- `language`, or `data.language` on the note.
7395
+ `language`, or a `data.lang` on the note whose language has a `note` in
7396
+ `languages:`.
7283
7397
  - An entry's `language` that names no language skill is an error at the value.
7284
7398
  - An entry with no `definition` naming neither a word of its resolved
7285
7399
  language, including inherited words, nor a rank or office that reaches its