# Licences and attribution — Before the Law

This is the complete attribution document for the project. It accompanies both the
publicly hosted version and the submission.

## Summary

**Two obligations, both satisfied inside the shipped file.** three.js and howler.js
are MIT and require their copyright notices to be retained; both notices are in the
banner at the top of the `<script>` block in `index.html`. Nothing else here needs
attribution — every other asset is CC0 or original to this project.

**Two exceptions, both added later and both described at the end of this file:**
the portrait on the acknowledgements page, and the character sculpts in *An Imperial Message*.
Neither is CC0. Everything said below about free reuse applies to the rest.

Apart from those, there is **no attribution to track over time**, no per-use registration, and nothing
that expires. The piece can be hosted, forked, and reused by other institutions
without licensing bookkeeping.

**Rule for anything added later:** CC0, MIT, or original only. No CC-BY, no
non-commercial clauses, no account-gated licences. An attribution obligation is
forever, and this project is meant to spread without a maintainer tracking it.

---

## 1. Original work — CC0

| Asset | Files | Notes |
|---|---|---|
| Parable prose | `before-the-law.html` | Original English adaptation of Kafka's *Vor dem Gesetz* |
| Figure and structure silhouettes | `assets/svg/*.svg` | Generated by `tools/build-svg.mjs` |
| Audio — drone, gate, bell | `assets/audio/*.mp3` | Synthesised by `tools/make-audio.mjs` |
| Game logic | `src/game.js` | |
| 3D scene, gate geometry, radiance shader | `src/scene.js` | |
| Audio playback layer | `src/audio.js` | |
| *An Imperial Message* prose | `imperial-message.html` | Original English adaptation of Kafka's *Eine kaiserliche Botschaft*, written from the public-domain German (also quoted there, after the 1919 *Selbstwehr* printing) |
| *An Imperial Message* scenes, shaders, crowd, sound | `src/im/*.js` | All geometry, textures (canvas-painted at runtime) and sound (WebAudio) are generated in code |
| Home page | `tools/hub.mjs` → `dist/index.html` | |
| Acknowledgements page (apart from the portrait) | `tools/tribute.mjs` → `dist/acknowledgements.html` | |
| Teachers' page | `tools/teachers.mjs` → `dist/for-teachers.html` | |

### The prose

Kafka died in 1924 and the German original is public domain. Published **English
translations generally are not.** The text here is an original adaptation written for
this project. If you revise the dialogue, revise it yourself — do not paste in a
published translation.

`before-the-law.html` is the **only** home for the prose. `tools/extract-text.mjs`
pulls it into `src/text.gen.js` at build time so the 3D build cannot drift from the
2D one. Edit the prose there and nowhere else; `text.gen.js` is overwritten on every
build.

### The audio

**These are original synthesised files, not sourced recordings.** The asset plan
called for sourcing from Freesound or Pixabay. Neither is reachable without account
credentials — Freesound's API returns `401`, Pixabay's `400`, and its CDN `403`
(verified, not assumed). Rather than leave the ending silent, the three cues are
generated from first principles in `tools/make-audio.mjs`:

- `ambient-drone.mp3` — 14.5 s loop, 48 kbps, 85 KB. Low partials at 41.25 / 55 /
  55.125 / 82.5 / 110 Hz over filtered noise. Every frequency is an exact integer
  multiple of the loop rate, so the waveform is continuous across the loop point.
- `gate-close.mp3` — 3.6 s, 64 kbps, 28 KB. Filtered noise under a falling lowpass
  (760 → 85 Hz), then the shut at 84 → 34 Hz.
- `bell-oldage.mp3` — 3.4 s, 64 kbps, 27 KB. Six inharmonic partials on 110 Hz.

This is arguably a better outcome than sourcing: CC0, no third-party provenance to
verify, and 141 KB total. **To swap in sourced files instead,** drop them in
`assets/audio/` and change the three filenames in the `AUDIO` map in
`tools/build-3d.mjs`. Nothing else moves. Record their URLs and licences here:

| Sourced audio | Source URL | Licence |
|---|---|---|
| *(none — all audio is original)* | | |

---

## 2. Bundled code — MIT

Both notices are retained inside `index.html`. **`tools/build-3d.mjs` must keep
`legalComments: 'eof'` and the explicit banner** — an earlier build of this pipeline
used `'none'`, which silently stripped them.

| Library | Version | Licence | Why |
|---|---|---|---|
| [three.js](https://threejs.org) | 0.185.1 | MIT | WebGL renderer, geometry, postprocessing |
| [howler.js](https://howlerjs.com) | 2.2.4 | MIT | Audio playback and looping |

MIT is a light obligation — retain the notice, no tracking — and unavoidable: there
is no CC0 WebGL engine.

---

## 3. Build-time only — not shipped

These run on the developer's machine and never reach the browser. Their licences do
not attach to the output.

| Tool | Licence | Note |
|---|---|---|
| esbuild | MIT | Bundler |
| sharp | Apache-2.0 | Texture resizing |
| lamejs | **LGPL-3.0** | MP3 encoder. Build-time only — the encoder never ships, and an encoded MP3 is not a derivative work of the encoder |
| puppeteer | Apache-2.0 | Headless verification harness |

---

## 4. Textures — CC0

| Asset | Source | Used for |
|---|---|---|
| `Ground108` | [ambientcg.com/view?id=Ground108](https://ambientcg.com/view?id=Ground108) | Ground plane |
| `Metal055C` | [ambientcg.com/view?id=Metal055C](https://ambientcg.com/view?id=Metal055C) | Reserved; not currently sampled |

Downloaded as 8K JPG sets totalling 456 MB. **The 8K originals are not shippable** —
the Ground108 colour map alone is 91 MB. `tools/shrink-textures.mjs` converts them to
1K and 2K WebP; the shipped build inlines the 512 px set at 269 KB.

Albedo is encoded at quality 82. Normal, roughness, and metalness maps are **data,
not pictures** — lossy artefacts in them surface as visible shading noise — so they
are encoded at quality 94.

---

## 5. Fonts — none

**The build uses system font stacks only and loads no webfonts.** Verified: zero
occurrences of `@font-face`, `fonts.googleapis`, `fonts.gstatic`, `.woff`, `.ttf`, or
`.otf` in the shipped file.

The asset plan anticipated Google Fonts (EB Garamond, Cinzel, Inter) under OFL, but
none were used, so **there is no font licensing obligation.** Serif prose renders in
Georgia / Iowan Old Style / Palatino; choices render in the platform UI sans.

Adding a webfont later would mean self-hosting a `.woff2`, inlining it as a data URI
to preserve the offline property, and recording its OFL notice here. It would cost
roughly 30–60 KB per weight. It is not currently needed.

---

## 6. Decided against — do not reopen

**HDRI environment map: none.** Both downloaded HDRIs were deleted. `kloppenheim_04`
was a sunny daytime sky — wrong asset. `satara_night_no_lamps` was the right mood but
unnecessary: the scene is near-black and lit by one warm source that has to be
*animated* per stage (intensity 0 → 16). An environment map cannot do that; an
explicit `PointLight` can, and costs zero bytes.

**Gate model: none.** The arch is built in code from a `THREE.Shape` extrusion in
`src/scene.js`. It is the same outline as `assets/svg/gate-arch.svg`, so one
silhouette drives both the 2D and 3D builds and they cannot drift; it is parametric
(`OW`, `IW`, `SPRING`); and it costs 0 bytes against a 41 MB download. The
`large_iron_gate_4k.blend` file has been deleted — `.blend` is unloadable by any web
renderer regardless.

---

## 7. Network and privacy

The shipped page makes **zero network requests.** Textures, audio, geometry, and both
libraries are inlined as data URIs or bundled source. It runs offline and from a
`file://` URL.

There is no analytics, no telemetry, no cookies, no `localStorage`, and no external
resource of any kind. Nothing about a player leaves their device.

---

## Storage layout

```
dist/               the deliverable — host or zip this
  index.html          the game, fully self-contained
  text-only.html      2D fallback, no WebGL required
  LICENSES.md         this file
  README.md

src/                source (bundled into dist/index.html)
assets/
  audio/              generated MP3s
  svg/                generated silhouettes
  textures/           web-ready WebP
  _source/            raw 8K downloads — gitignored, never served
tools/                build and verification scripts
```

`assets/_source/` holds ~725 MB and must never reach the repository or the served
build. Nothing in it is needed to build: `tools/shrink-textures.mjs` is the only step
that reads it, and its outputs are already committed under `assets/textures/`.

## Narration (assets/voice/)

Every spoken line was generated at build time by `tools/make-voice.mjs` using
**Kokoro-82M** (hexgrad, Apache License 2.0) through **kokoro-js** (Apache
License 2.0). Voices used: `bm_george` (narrator), `am_fenrir` (doorkeeper,
pitched down with added reverb), `bm_lewis` (the old man). The model and its
runtime are build tools only and do not ship; only the resulting MP3 audio is
inlined into `index.html`. The music, wind, footsteps, heartbeat and other
effects are synthesised in the browser by `src/audio.js` and are original work.

## An Imperial Message: narration and models

Narration (`assets/voice-im/`) is made the same way, by `tools/make-voice.mjs im`
with Kokoro-82M: `bm_george` (narrator; the "if" passages with a larger room) and
`bf_emma` ("but never, never can that happen"). Everything else you hear in that
game, including the whisper, the crowd, the bells, the knocking and the Shepard tone
under the thousand years, is synthesised in the browser by `src/im/sound.js`.

Character sculpts for it (`assets/models/im/`, prompts in `docs/meshy-prompts.md`)
are optional; without them the game uses its hand-built figures. **Before adding
any, confirm their licence meets the rule above.** Generated models from a free
plan may carry an attribution licence. Record the plan and terms here:

| Sculpts | Source | Licence |
|---|---|---|
| townswoman, official, prince (`assets/models/Meshy_AI_Full_body_*`) | Meshy AI, text to 3D, generated 8 Oct 2026 | **Unconfirmed: depends on the Meshy plan used** |
| emperor, messenger (courier), villager (`ancient+emperor`, `heroic+courier`, `traveling+villager`) | Tripo AI, generated 8 Oct 2026 | **Unconfirmed: depends on the Tripo plan used** |

Imported by `tools/import-im-models.mjs` (painted textures baked into vertex colours) and reduced by `tools/prep-models.mjs im`. The servant and child are still the hand-built figures.

## Save the Poet: text, narration and models

**Text.** Cicero's *Pro Archia* (62 BC) is in the public domain. Every English line in the game, including the passages of the speech, is our own, written for the game from the Latin; no published translation is quoted. The Latin lines shown under Cicero's words are Cicero's own. The jurors, Grattius' words (his speech is lost), the clerk, the night-before scene and the water costs are invented for the game.

**Narration** (`assets/voice-poet/`, 117 lines) was generated at build time by `tools/make-voice-poet.mjs` with Kokoro-82M (Apache License 2.0): `bm_george` (narrator), `bm_daniel` (Cicero), `am_onyx` (Grattius), `am_michael` (Quintus), `bm_lewis` (Archias), `am_fenrir` (Lucullus), `am_puck` (the clerk). The MP3s sit beside the page (`dist/voice-poet/`) rather than inside it. The crowd, the lyre, the water clock, the knocking and the wax tablets are synthesised in the browser by `src/poet/audio.js`.

**Sculpts.** Two sculpts, generated by the developer with Meshy AI (text to 3D, 24 Oct 2026), are used for every figure in the game: "The Philosopher's Scroll" as Archias and the Greeks, "The Stoic Senator" as Cicero and everyone in a toga. Only reduced copies ship, as geometry inside the page (`src/poet/models.gen.js`, made by `tools/prep-poet-models.mjs`); the raw downloads in `assets/models/poet/` are not published. Their painting, the seated pose, the moving head and arm are done in code (`src/poet/sculpt.js`).

| Sculpts | Source | Licence |
|---|---|---|
| archias, cicero (`assets/models/poet/`) | Meshy AI, text to 3D, generated 24 Oct 2026 | **Unconfirmed: depends on the Meshy plan used** |

## Acknowledgements page: the portrait

`assets/professor.jpg` is a portrait of Prof. (Dr.) Prasannanshu, inlined into
`dist/acknowledgements.html` (and appears on its share-preview picture). It was supplied by the developer, as an AI-rendered painting made
from a photograph on the professor's own website, whose pictures are marked
"all rights reserved". **It is not CC0** and is the one exception to the rule above:
it is shown with the page made in his honour and should not be reused elsewhere
without his consent. To ship the page without it, delete the file and rebuild; the
medallion falls back to a monogram.
