# Un saggio di storia con note Chicago

> Un saggio di storia di quattro pagine le cui citazioni [@key, 87] diventano note Chicago a piè di pagina: complete la prima volta, brevi poi, con bibliografia.

- Versione HTML: https://postext.dev/it/cookbook/history-essay-chicago-notes
- Ricetta Nº 089 · Struttura del libro · Livello 2 (Intermedio) · Output: Canvas, PDF
- Generi: Articoli scientifici e testi accademici
- Richiede postext ≥ 1.25.0, postext-pdf ≥ 1.25.0 · provata con 1.31.0, postext-pdf 1.31.0 il 2026-10-13
- Pagine: [1](https://postext.dev/cookbook/history-essay-chicago-notes/en/p01.webp?v=82363864), [2](https://postext.dev/cookbook/history-essay-chicago-notes/en/p02.webp?v=82363864), [3](https://postext.dev/cookbook/history-essay-chicago-notes/en/p03.webp?v=82363864), [4](https://postext.dev/cookbook/history-essay-chicago-notes/en/p04.webp?v=82363864)
- PDF: https://postext.dev/cookbook/history-essay-chicago-notes/en/history-essay-chicago-notes.pdf?v=82363864
- Apri nella Sandbox: https://postext.dev/it/sandbox#recipe=history-essay-chicago-notes&lang=en (.postext: https://postext.dev/cookbook/history-essay-chicago-notes/en/history-essay-chicago-notes.postext)
- Ultimo aggiornamento: 2026-10-11
- Altre lingue: [en](https://postext.dev/en/cookbook/history-essay-chicago-notes.md), [es](https://postext.dev/es/cookbook/history-essay-chicago-notes.md), [ca](https://postext.dev/ca/cookbook/history-essay-chicago-notes.md), [de](https://postext.dev/de/cookbook/history-essay-chicago-notes.md), [fr](https://postext.dev/fr/cookbook/history-essay-chicago-notes.md), [pt](https://postext.dev/pt/cookbook/history-essay-chicago-notes.md), [zh](https://postext.dev/zh/cookbook/history-essay-chicago-notes.md), [ja](https://postext.dev/ja/cookbook/history-essay-chicago-notes.md), [ar](https://postext.dev/ar/cookbook/history-essay-chicago-notes.md)

## In breve

Un saggio su come le città britanniche adottarono l’ora di Londra. Ogni fonte citata dall’autore diventa una nota numerata a piè di pagina, e l’elenco delle opere viene alla fine.

## Che cosa comporrai

Un estratto dalla collana di storia della tecnologia di una rivista: un saggio di circa 1.100 parole su come, tra il 1840 e il 1880, le città britanniche rinunciarono al proprio mezzogiorno per quello di Londra. La pagina è di 156 × 234 mm, a margini speculari, in Crimson Pro a 11/14 pt, con una fascia verde ferrovia sulla metà superiore della prima pagina. L’autore scrive ogni fonte come una chiave, `[@howse1980, 87]`, e Postext la compone come nota numerata a piè di pagina nello stile Chicago note e bibliografia. La prima nota di un’opera dà autore, titolo ed editore; ogni nota successiva dà la forma breve. Le note discorsive dell’autore prendono i numeri dalla stessa sequenza, e la bibliografia chiude il saggio.

**Questa ricetta risponde a:**

- Come compongo le citazioni come note a piè di pagina Chicago, con forme brevi per le citazioni successive?
- Come cito le opere e costruisco la bibliografia in APA, IEEE o un altro stile citazionale?

## La risposta breve

```js
// script.js, righe 32–49
// The text cites with [@howse1980, 87]; a note style turns every citation into a
// footnote. The first note for a work gives it in full, later ones in the short form
// (author, short title, page), and the bibliography lists the works by author.
registerCitationEngine(createCiteprocEngine({ styles: STYLES, locales: LOCALES }));
const citations = {
  style: 'chicago-notes-bibliography', // CMOS 18th edition, notes and bibliography
  notes: 'footnote', // each citation in a note at the foot of the page
  link: true, // a note's citation jumps to its bibliography entry
  bibliography: { fontSize: em(0.92), lineHeight: pt(13), hangingIndent: em(1.8),
    entrySpacing: pt(3) },
};
// The citation notes share the numbering and the look of the author's own [^notes].
const footnotes = {
  placement: 'column', numbering: 'chapter',
  fontSize: pt(8.5), lineHeight: pt(10.75), spaceBetween: pt(2),
  textAlign: 'left', // ragged: the gap after a note's number stays the same in every note
  separator: { width: 0.3, lineWidth: pt(0.5), color: col('rule') },
};
```

## Ingredienti

**Insegna**

- [Citazioni nelle note](https://postext.dev/it/docs/document-format.md#citazioni-e-bibliografia): Uno stile a note (Chicago notes, OSCOLA, GB/T 7714 a note) compone ogni citazione come nota a piè di pagina, con forme abbreviate per le citazioni successive, o come nota su due righe dentro una riga cinese.
- [Citazioni in uno stile citazionale](https://postext.dev/it/docs/document-format.md#citazioni-e-bibliografia): Opere citate come [@key, p. 33] e formattate in uno stile CSL (APA, Chicago, MLA, IEEE, Vancouver, ISO 690, GB/T 7714…) scelto nelle impostazioni, collegate alle loro voci.

**Usa anche**

- [Bibliografia dai riferimenti](https://postext.dev/it/docs/document-format.md#citazioni-e-bibliografia)
- [Note a piè di pagina](https://postext.dev/it/docs/document-format.md#note-a-piè-di-pagina)
- [Aperture progettate](https://postext.dev/it/docs/configuration-text.md#estensione-e-progetto-grafico-avanzato)
- [Attributi dei titoli](https://postext.dev/it/docs/document-format.md#attributi-dei-titoli)
- [Testatine e folio](https://postext.dev/it/docs/configuration-page-layout.md#intestazioni-e-piè-di-pagina)
- [Margini speculari](https://postext.dev/it/docs/configuration-page-layout.md#margini-speculari)
- [Stili di paragrafo](https://postext.dev/it/docs/configuration-styles.md#stili-di-paragrafo)
- [Tavolozza di colori semantica](https://postext.dev/it/docs/configuration-fonts-colors-viewers.md#tavolozza-dei-colori)
- [Esportazione in PDF](https://postext.dev/it/docs/configuration-programmatic-usage.md#generare-pdf)
- [Rimandi](https://postext.dev/it/docs/document-format.md#rimandi-e-ancore)
- [Colore della carta](https://postext.dev/it/docs/configuration-page-layout.md#pagina)
- [Testatine secondo il ruolo della pagina](https://postext.dev/it/docs/configuration-page-layout.md#elementi-di-testo)
- [Font incorporati nel PDF](https://postext.dev/it/docs/configuration-programmatic-usage.md#perché-un-provider-di-font)

**La configurazione in breve**

- [`bodyText`](https://postext.dev/it/docs/configuration-text.md#testo-corrente), [`citations`](https://postext.dev/it/docs/configuration-notes-references.md#citazioni), [`colorPalette`](https://postext.dev/it/docs/configuration-fonts-colors-viewers.md#tavolozza-dei-colori), [`footer`](https://postext.dev/it/docs/configuration-page-layout.md#intestazioni-e-piè-di-pagina), `footnotes`, [`header`](https://postext.dev/it/docs/configuration-page-layout.md#intestazioni-e-piè-di-pagina), [`headings`](https://postext.dev/it/docs/configuration-text.md#titoli), [`layout`](https://postext.dev/it/docs/configuration-page-layout.md#impaginazione), [`locale`](https://postext.dev/it/docs/configuration-text.md#sillabazione), [`page`](https://postext.dev/it/docs/configuration-page-layout.md#pagina), [`paragraphStyles`](https://postext.dev/it/docs/configuration-styles.md#stili-di-paragrafo)

**API**

- [`LOCALES`](https://postext.dev/it/docs/document-format.md#citazioni-e-bibliografia), [`STYLES`](https://postext.dev/it/docs/document-format.md#citazioni-e-bibliografia), [`buildDocumentWithFonts`](https://postext.dev/it/docs/configuration-programmatic-usage.md#caricare-i-font-prima-dellimpaginazione), [`createCiteprocEngine`](https://postext.dev/it/docs/document-format.md#citazioni-e-bibliografia), [`decompressWoff2`](https://postext.dev/it/docs/configuration-programmatic-usage.md#provider-di-font-per-il-browser-fontsource--woff2), [`registerCitationEngine`](https://postext.dev/it/docs/document-format.md#citazioni-e-bibliografia), [`renderPageToCanvas`](https://postext.dev/it/docs/configuration-programmatic-usage.md#rendere-una-pagina-come-bitmap), [`renderToPdf`](https://postext.dev/it/docs/configuration-programmatic-usage.md#generare-pdf)

**Caratteri**

- Crimson Pro (OFL-1.1), IBM Plex Sans Condensed (OFL-1.1)

## Preparazione

### 1 · Una nota per ogni citazione

Il codice è nella [risposta breve](https://postext.dev/it/cookbook/history-essay-chicago-notes.md#la-risposta-breve) qui sopra. `chicago-notes-bibliography` è uno stile a note, quindi una citazione nel testo lascia un numero in apice e le sue parole vanno in una nota a piè di pagina numerata insieme alle `[^notes]` dell’autore; `notes: 'footnote'` lo dice in modo esplicito. citeproc-js tiene traccia delle opere già citate, così la nota 3 dice *Derek Howse, Greenwich Time and the Discovery of the Longitude (Oxford University Press, 1980), 87* e la nota 4, che cita di nuovo lo stesso libro, dice *Howse, Greenwich Time and the Discovery of the Longitude, 90–91*. Lo stile incluso è la 18ª edizione del Chicago Manual, che abbandona *Ibid.* e ripete la forma breve, quindi le note 11 e 12 stampano due volte la forma breve.

### 2 · Anche le note dell’autore citano

Una citazione dentro una `[^note]` resta in quella nota e si compone in linea, per esteso se è la prima apparizione dell’opera: la nota 1 è la frase dell’autore seguita dal riferimento completo a Schivelbusch. Ogni citazione finisce con il punto dello stile, quindi una nota che si chiude con una citazione non ha bisogno di un punto proprio nel Markdown.

### 3 · Prefissi, suffissi e locatori

`[see @simmons1991, 346–47; and @bartky2000, chap. 9]` mette *see* prima della prima opera, separa le due con un punto e virgola e conserva il locatore di ciascuna. Un numero da solo è una pagina; `chap.` e `cap.` indicano un capitolo in entrambe le lingue. Il testo dopo il locatore è un suffisso: `[@howse1980, 82–84, on the mail-coach timepieces]` stampa la frase dopo le pagine.

### 4 · L’apertura sta in una fascia

```js
// script.js, righe 53–74
const BAND = 122; // mm from the trim's top
const opener = {
  enabled: true,
  minHeight: mm(BAND - MARGIN.top + 9), // the text starts 9 mm under the band
  slot: { elements: [
    { kind: 'box', id: 'band', style: { backgroundColor: col('green') },
      placement: { ...at('page', 'top-left'), size: { width: 'fill', height: mm(BAND) } } },
    { kind: 'text', id: 'kicker', content: '{attr.kicker}', fontFamily: LABEL, fontWeight: 600,
      fontSize: pt(7.5), letterSpacing: pt(1.4), textTransform: 'uppercase', color: col('tint'),
      align: 'left', placement: at('container', 'top-left', 0, 4) },
    { kind: 'text', id: 'years', content: '{attr.years}', fontFamily: TEXT, fontWeight: 300,
      fontSize: pt(54), lineHeight: 1, color: col('tint'), align: 'left',
      placement: at('container', 'top-left', -1, 16) },
    { kind: 'text', id: 'title', content: '{titleText}', fontFamily: TEXT, fontWeight: 600,
      fontSize: pt(25), lineHeight: 1.08, color: col('paper'), align: 'left', overflow: 'wrap',
      placement: { ...at('container', 'top-left', 0, 47),
        size: { width: mm(112), height: 'auto' } } },
    { kind: 'text', id: 'byline', content: '{attr.byline}', fontFamily: LABEL, fontWeight: 600,
      fontSize: pt(9), letterSpacing: pt(0.6), color: col('tint'), align: 'left',
      placement: at('container', 'top-left', 0, 92) },
  ] },
};
```

La fascia scende per 122 mm dal rifilo e il testo comincia 9 mm sotto. Le date vengono da un attributo del titolo, `years="1840–1880"`, composto in Crimson Pro Light a 54 pt, così la scheda mostra una cifra grande quanto un titolo; anche l’attributo della firma alimenta la testatina sui versi.

```js
// script.js, righe 16–23
const palette = {
  ink: '#211d1a', green: '#24493d', tint: '#dfe8e2', rule: '#b7b0a4', muted: '#6a645b',
  paper: '#fbf9f4',
};
// col() links a colour to its palette entry; the hex is the value the entry holds today.
const col = (id) => ({ hex: palette[id], model: 'hex', paletteId: id });
const colorPalette = Object.entries({ ...palette, 'main-color': palette.green })
  .map(([id, hex]) => ({ id, name: id, value: { hex, model: 'hex' } }));
```

## La ricetta completa

Un unico file, composto a partire dalla cartella della ricetta con il testo di esempio e il kit comune del Ricettario già inclusi; costruisce la propria pagina. Per eseguirlo, mettilo in uno `<script type="module">` di una pagina vuota, oppure incollalo nel pannello JS di un nuovo pen di CodePen (come modulo). Importa postext da esm.sh: non c’è niente da installare né da compilare.

- Cartella della ricetta: https://github.com/drnachio/postext/tree/main/cookbook/history-essay-chicago-notes

### script.js

```js
// ═══ Postext Cookbook · Nº 089 · A history essay with Chicago notes ═══════════════
// https://postext.dev/en/cookbook/history-essay-chicago-notes
// Code: MIT · Text: original (CC BY 4.0) · Pictures: none
// Fonts: Crimson Pro, IBM Plex Sans Condensed (SIL OFL 1.1) · Needs postext ≥ 1.25.0
import {
  buildDocumentWithFonts, renderPageToCanvas, registerCitationEngine,
} from 'https://esm.sh/postext';
import { renderToPdf, decompressWoff2 } from 'https://esm.sh/postext-pdf';
import { createCiteprocEngine, STYLES, LOCALES } from 'https://esm.sh/postext-citeproc';

const LANG = 'en'; // @lang: the language of the sample document ('en' | 'es')
const RECIPE = 'history-essay-chicago-notes';

// ─── 1 · Design ─────────────────────────────────────────────────────────────
// #region palette: a railway green for the opener band, ink and warm paper for the rest
const palette = {
  ink: '#211d1a', green: '#24493d', tint: '#dfe8e2', rule: '#b7b0a4', muted: '#6a645b',
  paper: '#fbf9f4',
};
// col() links a colour to its palette entry; the hex is the value the entry holds today.
const col = (id) => ({ hex: palette[id], model: 'hex', paletteId: id });
const colorPalette = Object.entries({ ...palette, 'main-color': palette.green })
  .map(([id, hex]) => ({ id, name: id, value: { hex, model: 'hex' } }));
// #endregion
const TEXT = 'Crimson Pro', LABEL = 'IBM Plex Sans Condensed';
const TRIM = { width: 156, height: 234 }; // a journal offprint, trimmed like a trade book
const MARGIN = { top: 22, bottom: 22, inner: 20, outer: 17 };
const LEAD = 14; // pt
const at = (to, edge, x = 0, y = 0) => ({ anchor: { to, edge }, offset: { x: mm(x), y: mm(y) } });

// #region answer: Chicago notes and bibliography, one note per citation
// The text cites with [@howse1980, 87]; a note style turns every citation into a
// footnote. The first note for a work gives it in full, later ones in the short form
// (author, short title, page), and the bibliography lists the works by author.
registerCitationEngine(createCiteprocEngine({ styles: STYLES, locales: LOCALES }));
const citations = {
  style: 'chicago-notes-bibliography', // CMOS 18th edition, notes and bibliography
  notes: 'footnote', // each citation in a note at the foot of the page
  link: true, // a note's citation jumps to its bibliography entry
  bibliography: { fontSize: em(0.92), lineHeight: pt(13), hangingIndent: em(1.8),
    entrySpacing: pt(3) },
};
// The citation notes share the numbering and the look of the author's own [^notes].
const footnotes = {
  placement: 'column', numbering: 'chapter',
  fontSize: pt(8.5), lineHeight: pt(10.75), spaceBetween: pt(2),
  textAlign: 'left', // ragged: the gap after a note's number stays the same in every note
  separator: { width: 0.3, lineWidth: pt(0.5), color: col('rule') },
};
// #endregion

// #region opener: the green band holds the kicker, the dates and the title
const BAND = 122; // mm from the trim's top
const opener = {
  enabled: true,
  minHeight: mm(BAND - MARGIN.top + 9), // the text starts 9 mm under the band
  slot: { elements: [
    { kind: 'box', id: 'band', style: { backgroundColor: col('green') },
      placement: { ...at('page', 'top-left'), size: { width: 'fill', height: mm(BAND) } } },
    { kind: 'text', id: 'kicker', content: '{attr.kicker}', fontFamily: LABEL, fontWeight: 600,
      fontSize: pt(7.5), letterSpacing: pt(1.4), textTransform: 'uppercase', color: col('tint'),
      align: 'left', placement: at('container', 'top-left', 0, 4) },
    { kind: 'text', id: 'years', content: '{attr.years}', fontFamily: TEXT, fontWeight: 300,
      fontSize: pt(54), lineHeight: 1, color: col('tint'), align: 'left',
      placement: at('container', 'top-left', -1, 16) },
    { kind: 'text', id: 'title', content: '{titleText}', fontFamily: TEXT, fontWeight: 600,
      fontSize: pt(25), lineHeight: 1.08, color: col('paper'), align: 'left', overflow: 'wrap',
      placement: { ...at('container', 'top-left', 0, 47),
        size: { width: mm(112), height: 'auto' } } },
    { kind: 'text', id: 'byline', content: '{attr.byline}', fontFamily: LABEL, fontWeight: 600,
      fontSize: pt(9), letterSpacing: pt(0.6), color: col('tint'), align: 'left',
      placement: at('container', 'top-left', 0, 92) },
  ] },
};
// #endregion

const head = (id, content, parity, edge, x, align) => ({
  kind: 'text', id, content, parity, pages: 'body', fontFamily: LABEL, fontWeight: 600,
  fontSize: pt(7.5), letterSpacing: pt(1.1), textTransform: 'uppercase', color: col('muted'),
  align, placement: at('page', edge, x, 12),
});

const config = () => ({
  locale: t({ en: 'en-us', es: 'es' }), // the hyphenation patterns of each edition
  colorPalette,
  citations,
  footnotes,
  page: {
    sizePreset: 'custom', width: mm(TRIM.width), height: mm(TRIM.height), dpi: 150,
    backgroundColor: col('paper'),
    margins: { top: mm(MARGIN.top), bottom: mm(MARGIN.bottom), left: mm(MARGIN.inner),
      right: mm(MARGIN.outer), mirror: true },
  },
  layout: { layoutType: 'single' },
  bodyText: {
    fontFamily: TEXT, fontSize: pt(11), lineHeight: pt(LEAD), color: col('ink'),
    boldColor: col('ink'), italicColor: col('ink'), referenceColor: col('ink'),
    textAlign: 'justify', firstLineIndent: mm(5), indentAfterHeading: false,
    hyphenation: { enabled: true }, optimalLineBreaking: true,
    avoidWidows: true, avoidOrphans: true, avoidRunts: true,
  },
  headings: {
    fontFamily: TEXT, fontWeight: 600, color: col('ink'),
    levels: [
      // parity 'any': the H1 opens on the next page, either side (the default waits for a recto).
      { level: 1, fontSize: pt(25), breakBefore: { enabled: true, parity: 'any' },
        advancedDesign: opener },
      { level: 2, fontFamily: LABEL, fontWeight: 600, fontSize: pt(8.5), letterSpacing: pt(1.3),
        textTransform: 'uppercase', color: col('green'), lineHeight: pt(LEAD),
        marginTop: pt(LEAD), marginBottom: pt(LEAD / 2) },
    ],
  },
  paragraphStyles: [
    { id: 'colophon', fontFamily: LABEL, fontSize: pt(7), lineHeight: pt(9.5),
      color: col('muted'), textAlign: 'left', firstLineIndent: pt(0), marginTop: pt(LEAD) },
  ],
  header: { elements: [
    head('verso-folio', '{pageNumber}', 'even', 'top-left', MARGIN.outer, 'left'),
    head('verso-author', '{attr.byline}', 'even', 'top-left', MARGIN.outer + 8, 'left'),
    head('recto-title', '{title}', 'odd', 'top-right', -(MARGIN.outer + 8), 'right'),
    head('recto-folio', '{pageNumber}', 'odd', 'top-right', -MARGIN.outer, 'right'),
  ] },
  footer: { elements: [] },
});

// ─── 2 · Content ────────────────────────────────────────────────────────────
const markdown = String.raw`---
title: "Railway Time"
author: "Clara Whitcombe"
---

# Railway Time: How British Towns Came to Keep London’s Hour {#essay kicker="Essays in the History of Technology · No. 14" years="1840–1880" byline="Clara Whitcombe"}

In the autumn of 1840 a traveller who left Paddington on the Great Western Railway carried two times with him. The timetable in his pocket gave the hours of London; the church clock at Bath or Bristol, when he arrived, gave the hours of the place, a few minutes behind. Bristol stood a little over two and a half degrees west of Greenwich, and its noon, the moment the sun crossed the local meridian, came about ten minutes after London’s. For centuries the difference had not mattered. A stagecoach that took a day to cover the distance lost more than ten minutes to a lame horse. A train that covered it in four hours could not.[^frame]

This essay follows the forty years in which that difference was settled, from the Great Western’s first timetables to the act of Parliament that made Greenwich time the legal time of Great Britain in 1880. The story has usually been told as a triumph of engineering over custom. It reads better as a negotiation, in which railway companies, telegraph companies, town councils and courts each settled the question for their own purposes, and not always in the same direction.

[^frame]: For the railway’s effect on the sense of time and distance, see [@schivelbusch1986, chap. 3]

## The companies decide

The first railways ran their trains by the clocks of their own stations. On a line of a few miles this caused no trouble, and the early timetables did not say which time they meant. The difficulty came with the long trunk lines of the late 1830s, which joined towns whose clocks disagreed by a quarter of an hour.[@simmons1991, 345]

The Great Western printed London time in its timetables from November 1840 and asked its station clocks to keep it.[@howse1980, 87] In 1847 the Railway Clearing House, the body through which the companies settled their accounts for through traffic, recommended that every member adopt Greenwich time from the first of December. By the end of 1848 nearly all of them had.[@howse1980, 90–91]

The decision was commercial before it was scientific. A company that kept one time along its line needed one timetable and one set of instructions for its staff, and it could publish connections with other lines without a table of corrections. Greenwich was chosen because London was where the companies had their offices and the Post Office its mail coaches, not because the observatory stood there.[^post]

[^post]: The Post Office had sent its guards out with watches set to London time since the 1790s; see [@howse1980, 82–84, on the mail-coach timepieces]

## The wire carries the hour

A time that every station is meant to keep has to reach every station. At first it travelled by hand: a guard on the morning down train carried a watch set at Paddington, and the stationmasters along the line set their clocks from it.

The electric telegraph changed the means. From 1852 the Royal Observatory sent a signal each day along the wires of the Electric Telegraph Company, and the company passed it on to the railway stations and post offices on its network.[@standage1998, 59] A clock in Manchester or Edinburgh could now be checked against Greenwich within a second or two of the event. The signal made Greenwich time available everywhere the wires went; it did not oblige anyone to keep it.[@schivelbusch1986, 43]

## The towns hesitate

Most towns on a main line gave way within a few years, since a clock that disagreed with the station made people miss trains. Some held out. In 1852 the clock on the Corn Exchange at Bristol was given a second minute hand, one for Bristol and one for London, and it still has both.[@simmons1991, 346] At Exeter, which the railway reached in 1844, the cathedral clock went on keeping the time of the city for some years after the station clock had changed.[^exeter]

[^exeter]: On the British towns, and on the same quarrel in American towns thirty years later, see [@simmons1991, 346–47; and @bartky2000, chap. 9]

The holdouts were not cranks. Local mean time followed the sun, and the sun still ordered the working day of farmers, fishermen and anyone whose hours depended on daylight. An hour fixed in London was an imposition on them. The historian of factory discipline has argued that the clock had already become a means of controlling labour by the eighteenth century;[@thompson1967, 80–82] the dispute over railway time extended that argument to whole towns, which were asked to accept an hour set elsewhere.

## The courts decline

The law was slower than the towns. Statutes that named a time meant the time of the place, and that time was local mean time. In 1858 a trial at Dorchester began at ten by the court’s clock, which kept London time, and judgment was given against a defendant who arrived at ten by the time of the town, some minutes later. On appeal the judges held that the hour meant was the local one, and the judgment was set aside.[@howse1980, 113] For twenty more years a contract, a polling station or a public house could be bound by one time while the trains ran by another.

The Statutes (Definition of Time) Act of 1880 closed the gap. It declared that any expression of time in an act of Parliament, deed or other legal instrument meant, unless stated otherwise, Greenwich mean time in Great Britain and Dublin mean time in Ireland.[@howse1980, 114]

## A settlement, not a conquest

Seen from 1840, railway time was one of several possible arrangements. The companies might have kept local times and printed tables of corrections, as some American railroads did until 1883,[@bartky2000, 140–45] and the international system of zones that followed the Washington conference of 1884 took half a century to reach most of the world.[@ogle2015] In Britain the distances were short, the companies were few enough to agree through a single clearing house, and the telegraph reached the stations as the trains did. Those conditions, more than any principle, account for the speed with which a country of local noons came to keep one hour.[@ogle2015, 25; see also @schivelbusch1986, chap. 3]

## Bibliography

:::bibliography{title=""}

:::paragraphs{style="colophon"}
A sample essay written for the Postext Cookbook (CC BY 4.0). The cited works are real; the page numbers in the notes are illustrative. Set in Crimson Pro and IBM Plex Sans Condensed (SIL OFL).
:::

:::references{format=csl-yaml}
- id: schivelbusch1986
  type: book
  author: [{family: Schivelbusch, given: Wolfgang}]
  title: "The Railway Journey: The Industrialization of Time and Space in the 19th Century"
  publisher: University of California Press
  publisher-place: Berkeley
  issued: 1986
- id: thompson1967
  type: article-journal
  author: [{family: Thompson, given: E. P.}]
  title: "Time, Work-Discipline, and Industrial Capitalism"
  container-title: Past & Present
  issue: 38
  page: 56-97
  issued: 1967
- id: howse1980
  type: book
  author: [{family: Howse, given: Derek}]
  title: Greenwich Time and the Discovery of the Longitude
  publisher: Oxford University Press
  publisher-place: Oxford
  issued: 1980
- id: simmons1991
  type: book
  author: [{family: Simmons, given: Jack}]
  title: The Victorian Railway
  publisher: Thames and Hudson
  publisher-place: London
  issued: 1991
- id: standage1998
  type: book
  author: [{family: Standage, given: Tom}]
  title: The Victorian Internet
  publisher: Walker
  publisher-place: New York
  issued: 1998
- id: bartky2000
  type: book
  author: [{family: Bartky, given: Ian R.}]
  title: "Selling the True Time: Nineteenth-Century Timekeeping in America"
  publisher: Stanford University Press
  publisher-place: Stanford, CA
  issued: 2000
- id: ogle2015
  type: book
  author: [{family: Ogle, given: Vanessa}]
  title: The Global Transformation of Time, 1870–1950
  publisher: Harvard University Press
  publisher-place: Cambridge, MA
  issued: 2015
:::
`;

// ─── 3 · Fonts ──────────────────────────────────────────────────────────────
// Every face the design uses.
const FONTS = {
  'Crimson Pro': ['300', '400', '400i', '600', '600i'],
  'IBM Plex Sans Condensed': ['400', '600'],
};

// ─── 4 · Build & show ───────────────────────────────────────────────────────
const doc = await buildDocumentWithFonts({ markdown }, config(), kitFonts(FONTS));
const title = t({ en: 'A history essay with Chicago notes',
  es: 'Un ensayo de historia con notas de Chicago' });
showPages(doc, { title });
offerPdf(() => renderToPdf(doc, { fontProvider: fontsourceProvider }), `${RECIPE}.pdf`);

// ─── Kit ── helpers shared by every Cookbook recipe · postext.dev/cookbook ─────

// ─── Kit · core v1 ── the same in every recipe · postext.dev/cookbook
function mm(value) { return { value, unit: 'mm' }; }
function pt(value) { return { value, unit: 'pt' }; }
function em(value) { return { value, unit: 'em' }; }
/** The sample language's string: t({ en: 'Figure', es: 'Figura' }). */
function t(strings) { return strings[LANG] ?? Object.values(strings)[0]; }
/** A file in this recipe's assets folder, served from the Postext repo by jsDelivr. */
function asset(file) { return `https://cdn.jsdelivr.net/gh/drnachio/postext@main/cookbook/${RECIPE}/assets/${file}`; }

// ─── Kit · fonts v3 ── the same in every recipe · postext.dev/cookbook
// Postext loads the faces a config asks for before layout (prepareFonts,
// buildDocumentWithFonts) and asks the kit for the files: Fontsource's, the
// files the PDF embeds too.

/** The options of buildDocumentWithFonts / prepareFonts / withLoadedFonts:
 *  the Fontsource resolver, and the faces of FONTS loaded with the ones the
 *  config names. FONTS = { 'Family Name': ['400', '400i', '700'] }. */
function kitFonts(FONTS = {}) {
  const faces = Object.entries(FONTS).flatMap(([family, specs]) => specs.map((spec) =>
    ({ family, weight: parseInt(spec, 10), style: spec.endsWith('i') ? 'italic' : 'normal' })));
  return { resolve: fontsourceResolver, faces };
}

/** A face's Fontsource files, in a fixed order: latin, then latin-ext and greek
 *  when `text` needs them and the family ships them (kitSubsetsFor), each with
 *  its unicode-range. Null for a weight or slant Fontsource does not ship. */
async function fontsourceResolver(family, weight, style, { text = '' } = {}) {
  const id = fontsourceId(family);
  const meta = await fontsourceMeta(family);
  if (meta && !(meta.weights.includes(weight) && meta.styles.includes(style))) return null;
  kitStatus('Loading fonts…');
  const at = await fontsourceAt(id);
  return ['latin', ...kitSubsetsFor(text, meta)].map((subset) => ({
    source: `${at}files/${id}-${subset}-${weight}-${style}.woff2`,
    unicodeRange: kitRanges()[subset],
  }));
}

/** The unicode-range of each Fontsource file the kit loads (a function: the
 *  kit is inlined after the pen's code, which runs before a const would be set). */
function kitRanges() {
  return {
    latin: 'U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,'
      + 'U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD',
    'latin-ext': 'U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,'
      + 'U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF',
    greek: 'U+0370-03FF',
  };
}

/** For the cjk, arabic and comics blocks, which add their own files: the
 *  faces of `faces` = { 'Family Name': ['400', '400i', '700'] }. `text` is the sample:
 *  č ł † α χ also load latin-ext and greek files (kitSubsetsFor). With
 *  `optional`, a face Fontsource does not ship is skipped instead of failing.
 *  The files are added once all have loaded, in the order asked (latin, then
 *  latin-ext, then greek), whatever order they arrive in: the last one added
 *  wins a character two files hold. Resolves to the number of faces added. */
async function loadFonts(faces, text = '', { optional = false } = {}) {
  kitStatus('Loading fonts…');
  const ranges = kitRanges();
  const jobs = [];
  for (const [family, specs] of Object.entries(faces)) {
    const id = fontsourceId(family);
    const todo = [...new Set(specs)].map((spec) => [parseInt(spec, 10), spec.endsWith('i') ? 'italic' : 'normal'])
      .filter(([weight, style]) => !hasFace(family, weight, style)); // before any await
    const at = fontsourceAt(id);
    const meta = optional || /[^\0-ÿ]/u.test(text) ? await fontsourceMeta(family) : null;
    const subsets = ['latin', ...kitSubsetsFor(text, meta)];
    for (const [weight, style] of todo) {
      if (optional && !(meta?.weights.includes(weight) && meta.styles.includes(style))) continue;
      for (const subset of subsets) {
        const url = `${await at}files/${id}-${subset}-${weight}-${style}.woff2`;
        const face = new FontFace(family, `url(${url}) format('woff2')`,
          { weight: String(weight), style, unicodeRange: ranges[subset] });
        jobs.push(face.load().catch(() => {
          if (subset === 'latin' && !optional) throw new Error(`Fontsource has no ${family} ${weight} ${style}`);
        }));
      }
    }
  }
  const ready = await Promise.all(jobs).catch((error) => { kitFail(error); throw error; });
  return ready.filter((face) => face && document.fonts.add(face)).length;
}

/** A loaded FontFace covers this family, weight and style (fonts.check() would
 *  also say yes for families nobody declared). */
function hasFace(family, weight, style) {
  for (const face of document.fonts) {
    if (face.status !== 'loaded' || face.style !== style) continue;
    if (face.family.replace(/^["']|["']$/g, '') !== family) continue;
    const [low, high = low] = face.weight.split(' ').map(Number);
    if (weight >= low && weight <= high) return true;
  }
  return false;
}

/** The files beyond latin `text` needs that `meta`'s family ships. */
function kitSubsetsFor(text, meta) {
  return [[/[Ā-˿ᴀ-ᶿḀ-ỿ†ℓⱠ-Ɀ꜠-ꟿ]/u, 'latin-ext'], [/[Ͱ-Ͽ]/u, 'greek']]
    .filter(([re, x]) => re.test(text) && meta?.subsets?.includes(x)).map(([, x]) => x);
}

/** Fontsource's id for a family: 'Source Serif 4' → 'source-serif-4'. */
function fontsourceId(family) { return family.toLowerCase().replace(/\s+/g, '-'); }

/** A package's folder at the one version @5 names now (#766). */
function fontsourceAt(id, u = `https://cdn.jsdelivr.net/npm/@fontsource/${id}@`) {
  return (fontsourceAt.c ??= {})[id] ??= fetch(u + '5/package.json').then((r) => r.json())
    .then((p) => p.version || 5, () => 5).then((v) => `${u}${v}/`);
}

/** The family's Fontsource metadata (weights, styles, subsets), or null. */
function fontsourceMeta(family) {
  fontsourceMeta.cache ??= new Map();
  const id = fontsourceId(family);
  if (!fontsourceMeta.cache.has(id)) {
    fontsourceMeta.cache.set(id, fetch(`https://api.fontsource.org/v1/fonts/${id}`)
      .then((res) => (res.ok ? res.json() : null), () => null));
  }
  return fontsourceMeta.cache.get(id);
}

// ─── Kit · viewer v2 ── the same in every recipe · postext.dev/cookbook
/** The pages as spreads on a dark desk, page 1 alone, then verso | recto,
 *  each painted when it scrolls near. Other options go to renderPageToCanvas. */
function showPages(docs, { title, width = 460, ...render } = {}) {
  const root = viewer(title);
  const pages = [docs].flat().flatMap((doc) =>
    doc.pages.map((page) => ({ doc, page, n: (doc.pageIndexOffset ?? 0) + page.index })));
  const spreads = [];
  let verso = null;
  for (const p of pages) {
    if (p.n % 2 === 1) { if (verso) spreads.push([verso, null]); verso = p; }
    else { spreads.push([verso, p]); verso = null; }
  }
  if (verso) spreads.push([verso, null]);
  const density = Math.min(window.devicePixelRatio || 1, 2);
  showPages.painter?.disconnect();
  const painter = new IntersectionObserver((entries) => {
    for (const { isIntersecting, target } of entries) {
      if (!isIntersecting) continue;
      painter.unobserve(target);
      const { doc, page } = target.postext;
      renderPageToCanvas(page, doc, target, { ...render, scale: (width * density) / page.width });
    }
  }, { rootMargin: '800px' });
  showPages.painter = painter;
  root.replaceChildren(...spreads.map((pair) => {
    const spread = document.createElement('div');
    spread.className = 'pt-spread';
    for (const p of pair) {
      const figure = document.createElement('figure');
      if (p) {
        const label = p.page.pageLabel || String(p.n + 1);
        const canvas = document.createElement('canvas');
        canvas.postext = p;
        canvas.style.aspectRatio = `${p.page.width} / ${p.page.height}`;
        canvas.setAttribute('role', 'img');
        canvas.setAttribute('aria-label', `Page ${label}`);
        const folio = document.createElement('figcaption');
        folio.textContent = label;
        figure.append(canvas, folio);
        painter.observe(canvas);
      } else figure.className = 'pt-blank';
      spread.append(figure);
    }
    return spread;
  }));
  kitStatus(`${pages.length} ${pages.length === 1 ? 'page' : 'pages'}`);
  document.documentElement.dataset.postext = 'ready';
  return pages.length;
}

/** The desk, the bar and the error reporting, created once. */
function viewer(title) {
  if (!document.getElementById('pt-kit')) {
    document.head.insertAdjacentHTML('beforeend', `<style id="pt-kit">
      :root { color-scheme: dark; }
      body { margin: 0; background: #0e1014; color: #b9bcc4; font: 13px/1.45 system-ui, sans-serif; }
      #pt-bar { position: sticky; top: 0; z-index: 1; display: flex; flex-wrap: wrap; align-items: center;
        gap: 6px 16px; padding: 10px 16px; background: rgb(14 16 20 / .92); backdrop-filter: blur(6px);
        border-bottom: 1px solid #23262d; }
      #pt-bar strong { color: #f4f1ea; font-weight: 600; }
      #pt-actions { display: flex; gap: 12px; margin-left: auto; }
      #pt-actions a, #pt-actions button { color: #d8a21a; font: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
      #pages { display: grid; justify-items: center; gap: 48px; padding: 32px 16px 72px; }
      .pt-spread { display: flex; }
      .pt-spread figure { margin: 0; width: min(460px, 44vw); }
      .pt-spread canvas { display: block; width: 100%; background: #fff;
        box-shadow: 0 1px 2px rgb(0 0 0 / .5), 0 22px 44px -16px rgb(0 0 0 / .8); }
      .pt-spread figure:first-child canvas { box-shadow: inset -14px 0 14px -14px rgb(0 0 0 / .18), 0 1px 2px rgb(0 0 0 / .5), 0 22px 44px -16px rgb(0 0 0 / .8); }
      .pt-spread figcaption { margin-top: 10px; text-align: center; font: 600 10px/1 system-ui, sans-serif;
        letter-spacing: .18em; text-transform: uppercase; color: #6c7079; }
      .pt-blank { visibility: hidden; }
      @media (max-width: 760px) {
        .pt-spread { flex-direction: column; gap: 32px; }
        .pt-spread figure { width: min(460px, 92vw); }
        .pt-blank { display: none; }
      }
    </style>`);
    document.body.insertAdjacentHTML('afterbegin',
      '<header id="pt-bar"><strong id="pt-title"></strong><span id="pt-status" role="status"></span><span id="pt-actions"></span></header>');
    document.getElementById('pt-title').textContent = document.title || 'Postext';
    addEventListener('error', (event) => kitFail(event.error ?? event.message));
    addEventListener('unhandledrejection', (event) => kitFail(event.reason));
  }
  if (title) document.getElementById('pt-title').textContent = title;
  return document.getElementById('pages')
    ?? document.body.appendChild(Object.assign(document.createElement('main'), { id: 'pages' }));
}

function kitStatus(text) {
  viewer();
  document.getElementById('pt-status').textContent = text;
}

function kitFail(error) {
  document.documentElement.dataset.postext = 'error';
  kitStatus(`Error: ${error?.message ?? error}`);
}

// ─── Kit · pdf v3 ── the same in every recipe that exports a PDF
/** The Fontsource files the screen used, as TrueType, with their range and
 *  place: the nearest weight the family ships, upright with no italic;
 *  latin, then what its letters need (kitSubsetsFor). */
async function fontsourceProvider(family, weight, style, request) {
  const id = fontsourceId(family);
  const meta = await fontsourceMeta(family);
  const weights = meta?.weights?.length ? meta.weights : [400, 700];
  const w = weights.reduce((a, b) => (Math.abs(b - weight) < Math.abs(a - weight) ? b : a));
  const s = style === 'italic' && meta && !meta.styles.includes('italic') ? 'normal' : style;
  const text = String.fromCodePoint(...(request?.codePoints ?? []));
  const files = await Promise.all(['latin', ...kitSubsetsFor(text, meta)].map(async (subset, order) => {
    const res = await fetch(`${await fontsourceAt(id)}files/${id}-${subset}-${w}-${s}.woff2`);
    if (!res.ok) throw new Error(`Fontsource has no ${family} ${w} ${s} ${subset}`);
    return Object.assign(await decompressWoff2(new Uint8Array(await res.arrayBuffer())),
      { unicodeRange: kitRanges()[subset], order });
  }));
  return files.length === 1 ? files[0] : files;
}

/** A "Build the PDF" button; then "Open the PDF" (a new tab: CodePen's frame
 *  shows no PDFs) and a download link. */
function offerPdf(makePdf, filename) {
  viewer();
  const button = Object.assign(document.createElement('button'), { type: 'button', textContent: 'Build the PDF' });
  button.dataset.postextPdf = filename;
  button.addEventListener('click', async () => {
    button.disabled = true;
    button.textContent = 'Building the PDF…';
    try {
      const bytes = await makePdf();
      const url = URL.createObjectURL(new Blob([bytes], { type: 'application/pdf' }));
      const size = `${Math.max(1, Math.round(bytes.length / 1024))} KB`;
      button.replaceWith(
        Object.assign(document.createElement('a'), { href: url, target: '_blank', rel: 'noopener', textContent: 'Open the PDF ↗' }),
        Object.assign(document.createElement('a'), { href: url, download: filename, textContent: `Download ${filename} · ${size}` }));
    } catch (error) {
      button.disabled = false;
      button.textContent = 'Build the PDF';
      kitFail(error);
    }
  });
  document.getElementById('pt-actions').append(button);
}

// ─── /Kit ───────────────────────────────────────────────────────────────────────
```

## Varianti

### Metti le note alla fine

Alcune riviste raccolgono le note dopo il saggio; le citazioni conservano le loro forme complete e brevi.

```diff
-  placement: 'column', numbering: 'chapter',
+  placement: 'chapterEnd', numbering: 'chapter',
```

### Scrivi di nuovo Ibid.

La 17ª edizione dello stile Chicago stampa *Ibid.* per una nota che ripete l’opera precedente. Incolla il file `.csl` di quello stile, dal repository degli stili di Zotero, in una stringa e usalo come stile personalizzato.

```diff
-  style: 'chicago-notes-bibliography', // CMOS 18th edition, notes and bibliography
+  style: 'custom', customStyle: CHICAGO_17TH_CSL, // the XML of the .csl file
```

## Errori frequenti

- Non chiudere una nota con un punto dopo una citazione: lo stile chiude già la citazione con un punto, e Postext non unisce i due, quindi la nota finirebbe con due punti.
- In uno stile a note, `@howse1980` senza parentesi quadre lascia nella frase solo il numero della nota, *As ¹ says*, senza il nome dell’autore. Scrivi tu il nome e cita tra parentesi quadre: `As Howse says,[@howse1980]`.

## Crediti

- Ricetta: Ignacio Ferro ([@drnachio](https://github.com/drnachio))
- Caratteri: Crimson Pro (OFL-1.1), IBM Plex Sans Condensed (OFL-1.1)
- Codice: MIT · Contenuto di esempio: CC-BY-4.0

## Ricette correlate

- [Nº 099 · Un commento giuridico citato secondo OSCOLA](https://postext.dev/it/cookbook/legal-opinion-oscola.md): Un commento a sentenza di quattro pagine in cui le citazioni [@robinson2018, para 21] diventano note OSCOLA: casi in corsivo, citazioni neutre, ibid e (n 1). · Livello 2 (Intermedio) · Articoli scientifici e testi accademici
- [Nº 096 · Un saggio umanistico con bibliografia MLA](https://postext.dev/it/cookbook/mla-humanities-essay.md): Un saggio letterario le cui citazioni [@key, 48] diventano riferimenti autore-pagina MLA 9, con una citazione in blocco e una lista Works Cited da dati BibTeX. · Livello 2 (Intermedio) · Articoli scientifici e testi accademici
- [Nº 098 · Un volume collettaneo con una bibliografia per capitolo](https://postext.dev/it/cookbook/edited-volume-chapter-bibliographies.md): Tre saggi di tre autori, ciascuno un documento a sé in buildBundle, ciascuno chiuso da un elenco Chicago autore-data delle sole opere che cita. · Livello 3 (Avanzato) · Articoli scientifici e testi accademici, Libri di testo
