# Un ensayo de historia con notas de Chicago

> Un ensayo de historia de cuatro páginas cuyas citas [@clave, 87] salen como notas de Chicago al pie: completas la primera vez, breves después.

- Versión HTML: https://postext.dev/es/cookbook/history-essay-chicago-notes
- Receta N.º 089 · Estructura del libro · Nivel 2 (Intermedio) · Salidas: Canvas, PDF
- Géneros: Artículos y trabajos académicos
- Requiere postext ≥ 1.12.0, postext-pdf ≥ 1.12.0 · probada con 1.12.0, postext-pdf 1.12.0 el 2026-10-01
- Páginas: [1](https://postext.dev/cookbook/history-essay-chicago-notes/es/p01.webp?v=13d95f84), [2](https://postext.dev/cookbook/history-essay-chicago-notes/es/p02.webp?v=13d95f84), [3](https://postext.dev/cookbook/history-essay-chicago-notes/es/p03.webp?v=13d95f84), [4](https://postext.dev/cookbook/history-essay-chicago-notes/es/p04.webp?v=13d95f84)
- PDF: https://postext.dev/cookbook/history-essay-chicago-notes/es/history-essay-chicago-notes.pdf?v=13d95f84
- Abrir en el Sandbox: https://postext.dev/es/sandbox#recipe=history-essay-chicago-notes&lang=es (.postext: https://postext.dev/cookbook/history-essay-chicago-notes/es/history-essay-chicago-notes.postext)
- Última actualización: 2026-10-01
- Otros idiomas: [en](https://postext.dev/en/cookbook/history-essay-chicago-notes.md), [zh](https://postext.dev/zh/cookbook/history-essay-chicago-notes.md)

## En pocas palabras

Un ensayo sobre cómo las ciudades británicas adoptaron la hora de Londres. Cada fuente que cita la autora se convierte en una nota numerada al pie de la página, y la lista de obras va al final.

## Lo que vas a componer

Una separata de la serie de historia de la técnica de una revista: un ensayo de unas 1.100 palabras sobre cómo las ciudades británicas dejaron su propio mediodía por el de Londres entre 1840 y 1880. La página mide 156 × 234 mm, con márgenes en espejo, en Crimson Pro de 11/14 pt, y una banda verde ferrocarril cubre la mitad superior de la primera. La autora escribe cada fuente como una clave, `[@howse1980, 87]`, y Postext compone cada una como una nota numerada al pie en el estilo de notas y bibliografía de Chicago. La primera nota de una obra da autor, título y editorial; las siguientes, la forma breve. Las notas propias de la autora toman su número de la misma serie, y la bibliografía cierra el ensayo.

**Esta receta responde a:**

- ¿Cómo pongo las citas en notas al pie de Chicago, con forma breve en las siguientes?
- ¿Cómo cito obras y compongo la bibliografía en APA, IEEE u otro estilo de cita?

## La respuesta corta

```js
// script.js, líneas 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') },
};
```

## Ingredientes

**Enseña**

- [Citas en notas](https://postext.dev/es/docs/document-format.md#citas-y-bibliografía): Un estilo de notas (Chicago notas, OSCOLA, GB/T 7714 notas) pone cada cita en una nota al pie, con forma breve en las citas siguientes, o en una nota de dos líneas dentro del renglón chino.
- [Citas en un estilo de cita](https://postext.dev/es/docs/document-format.md#citas-y-bibliografía): Obras citadas como [@clave, pág. 33] y formateadas en un estilo CSL (APA, Chicago, MLA, IEEE, Vancouver, ISO 690, GB/T 7714…) elegido en los ajustes, enlazadas con sus entradas.

**También usa**

- [Bibliografía a partir de las referencias](https://postext.dev/es/docs/document-format.md#citas-y-bibliografía)
- [Notas al pie](https://postext.dev/es/docs/document-format.md#notas-al-pie)
- [Aperturas diseñadas](https://postext.dev/es/docs/configuration.md#span-y-diseño-avanzado)
- [Atributos de título](https://postext.dev/es/docs/document-format.md#atributos-de-encabezado)
- [Cabeceras y folios](https://postext.dev/es/docs/configuration.md#encabezados-y-pies)
- [Márgenes simétricos](https://postext.dev/es/docs/configuration.md#márgenes-simétricos-espejo)
- [Estilos de párrafo](https://postext.dev/es/docs/configuration.md#estilos-de-párrafo)
- [Paleta de color semántica](https://postext.dev/es/docs/configuration.md#paleta-de-colores)
- [Exportación a PDF](https://postext.dev/es/docs/configuration.md#generación-de-pdf)
- [Referencias cruzadas](https://postext.dev/es/docs/document-format.md#referencias-cruzadas-y-anclas)
- [Color del papel](https://postext.dev/es/docs/configuration.md#página)
- [Cabeceras según el tipo de página](https://postext.dev/es/docs/configuration.md#elementos-de-texto)
- [Fuentes incrustadas en el PDF](https://postext.dev/es/docs/configuration.md#por-qué-un-proveedor-de-fuentes)

**La configuración de un vistazo**

- [`bodyText`](https://postext.dev/es/docs/configuration.md#texto-de-cuerpo), [`citations`](https://postext.dev/es/docs/configuration.md#citas), [`colorPalette`](https://postext.dev/es/docs/configuration.md#paleta-de-colores), [`footer`](https://postext.dev/es/docs/configuration.md#encabezados-y-pies), `footnotes`, [`header`](https://postext.dev/es/docs/configuration.md#encabezados-y-pies), [`headings`](https://postext.dev/es/docs/configuration.md#encabezados), [`layout`](https://postext.dev/es/docs/configuration.md#disposición), [`locale`](https://postext.dev/es/docs/configuration.md#separación-silábica), [`page`](https://postext.dev/es/docs/configuration.md#página), [`paragraphStyles`](https://postext.dev/es/docs/configuration.md#estilos-de-párrafo)

**API**

- [`LOCALES`](https://postext.dev/es/docs/document-format.md#citas-y-bibliografía), [`STYLES`](https://postext.dev/es/docs/document-format.md#citas-y-bibliografía), [`buildDocument`](https://postext.dev/es/docs/configuration.md#construir-un-documento), [`clearMeasurementCache`](https://postext.dev/es/docs/configuration.md#caché-de-medidas), [`createCiteprocEngine`](https://postext.dev/es/docs/document-format.md#citas-y-bibliografía), [`decompressWoff2`](https://postext.dev/es/docs/configuration.md#proveedor-de-fuentes-en-el-navegador-fontsource--woff2), [`registerCitationEngine`](https://postext.dev/es/docs/document-format.md#citas-y-bibliografía), [`renderPageToCanvas`](https://postext.dev/es/docs/configuration.md#renderizar-una-página-a-un-bitmap), [`renderToPdf`](https://postext.dev/es/docs/configuration.md#generación-de-pdf)

**Tipografías**

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

## Elaboración

### 1 · Una nota para cada cita

El código es [la respuesta corta](#la-respuesta-corta) de arriba. `chicago-notes-bibliography` es un estilo de notas: una cita deja en el texto un número volado y sus palabras pasan a una nota al pie, numerada junto con las `[^notas]` de la autora; `notes: 'footnote'` lo dice de forma explícita. citeproc-js lleva la cuenta de las obras ya citadas, así que la nota 3 dice *Derek Howse, Greenwich Time and the Discovery of the Longitude (Oxford University Press, 1980), 87* y la nota 4, que vuelve al mismo libro, *Howse, Greenwich Time and the Discovery of the Longitude, 90–91*. El estilo incluido es la 18.ª edición del Manual de Chicago, que abandona *ibid.* y repite la forma breve, de modo que las notas 11 y 12 la imprimen dos veces.

### 2 · Las notas de la autora también citan

Una cita dentro de una `[^nota]` se queda en esa nota y se compone dentro de la línea, completa si es la primera vez que aparece la obra: la nota 1 es la frase de la autora seguida de la referencia completa de Schivelbusch. Toda cita termina con el punto del estilo, así que una nota que acaba en una cita no lleva punto propio en el Markdown.

### 3 · Prefijos, sufijos y localizadores

`[véase @simmons1991, 346–47; y @bartky2000, cap. 9]` pone *véase* delante de la primera obra, separa las dos con punto y coma y conserva el localizador de cada una. Un número solo es una página; `cap.` y `chap.` nombran un capítulo en cualquiera de los dos idiomas. El texto que sigue al localizador es un sufijo: `[@howse1980, 82–84, sobre los relojes de las diligencias]` imprime la frase detrás de las páginas.

### 4 · La apertura va en una banda

```js
// script.js, líneas 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 banda baja 122 mm desde el corte y el texto empieza 9 mm por debajo. Las fechas salen de un atributo del título, `years="1840–1880"`, en Crimson Pro Light de 54 pt, para que la tarjeta muestre una cifra tan grande como un título; el atributo de la firma alimenta además la cabecera de las páginas pares.

```js
// script.js, líneas 16–23
const palette = {
  ink: '#211d1a', green: '#24493d', tint: '#dfe8e2', rule: '#b7b0a4', muted: '#6a645b',
  paper: '#fbf9f4',
};
// A design element paints the hex written beside its paletteId (gotcha: palette-skips-designs).
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 receta completa

Un solo archivo, compuesto a partir de la carpeta de la receta con el texto de ejemplo y el kit común del Recetario ya incluidos; construye su propia página. Para ejecutarlo, ponlo en un `<script type="module">` de una página vacía o pégalo en el panel JS de un pen nuevo de CodePen (como módulo). Importa postext desde esm.sh, así que no hay nada que instalar ni compilar.

- Carpeta de la receta: 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.12.0
import {
  buildDocument, renderPageToCanvas, clearMeasurementCache, 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 = 'es'; // @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',
};
// A design element paints the hex written beside its paletteId (gotcha: palette-skips-designs).
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 = () => ({ // a factory: the engine caches resolved configs per object
  locale: t({ en: 'en-us', es: 'es' }), // exact codes (gotcha: hyphenation-locales)
  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: [
      // Restated: any headings object drops the H1 break (gotcha: headings-drop-h1-break).
      { 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: "La hora del ferrocarril"
author: "Clara Whitcombe"
---

# La hora del ferrocarril: cómo las ciudades británicas adoptaron la hora de Londres {#essay kicker="Ensayos de historia de la técnica · n.º 14" years="1840–1880" byline="Clara Whitcombe"}

En el otoño de 1840, un viajero que salía de Paddington en el Great Western Railway llevaba consigo dos horas. El horario que guardaba en el bolsillo daba las horas de Londres; el reloj de la iglesia de Bath o de Bristol, al llegar, daba las del lugar, unos minutos atrasadas. Bristol está algo más de dos grados y medio al oeste de Greenwich, y su mediodía, el instante en que el sol cruza el meridiano local, llegaba unos diez minutos después que el de Londres. Durante siglos la diferencia no había importado. Una diligencia que tardaba un día en cubrir el trayecto perdía más de diez minutos por un caballo cojo. Un tren que lo cubría en cuatro horas, no.[^frame]

Este ensayo sigue los cuarenta años en que se resolvió esa diferencia, desde los primeros horarios del Great Western hasta la ley que en 1880 hizo de la hora de Greenwich la hora legal de Gran Bretaña. La historia suele contarse como una victoria de la ingeniería sobre la costumbre. Se entiende mejor como una negociación, en la que compañías ferroviarias, compañías de telégrafos, ayuntamientos y tribunales resolvieron la cuestión cada uno a su manera, y no siempre en el mismo sentido.

[^frame]: Sobre el efecto del ferrocarril en la percepción del tiempo y la distancia, véase [@schivelbusch1986, cap. 3]

## Las compañías deciden

Los primeros ferrocarriles marcaban la marcha de sus trenes por los relojes de sus propias estaciones. En una línea de pocas millas aquello no causaba problemas, y los primeros horarios no decían a qué hora se referían. La dificultad llegó con las grandes líneas troncales de finales de la década de 1830, que unían ciudades cuyos relojes discrepaban en un cuarto de hora.[@simmons1991, 345]

El Great Western imprimió la hora de Londres en sus horarios a partir de noviembre de 1840 y pidió a sus estaciones que la siguieran.[@howse1980, 87] En 1847 la Railway Clearing House, el organismo a través del cual las compañías liquidaban sus cuentas por el tráfico compartido, recomendó a todos sus miembros adoptar la hora de Greenwich desde el 1 de diciembre. A finales de 1848 casi todos lo habían hecho.[@howse1980, 90–91]

La decisión fue comercial antes que científica. Una compañía que mantenía una sola hora en toda su línea necesitaba un solo horario y un solo reglamento para su personal, y podía publicar los enlaces con otras líneas sin una tabla de correcciones. Se eligió Greenwich porque en Londres tenían sus oficinas las compañías y el correo sus diligencias, no porque allí estuviera el observatorio.[^post]

[^post]: El correo enviaba a sus guardas con relojes puestos en la hora de Londres desde la década de 1790; véase [@howse1980, 82–84, sobre los relojes de las diligencias]

## El hilo lleva la hora

Al principio la hora viajaba en el reloj de un guarda del primer tren, puesto en Paddington, y los jefes de estación ajustaban los suyos por él. El telégrafo eléctrico cambió el medio. Desde 1852 el Observatorio Real enviaba cada día una señal por los hilos de la Electric Telegraph Company, que la transmitía a las estaciones y oficinas de correos de su red.[@standage1998, 59] La señal ponía la hora de Greenwich al alcance de cualquier lugar al que llegaran los hilos; no obligaba a nadie a seguirla.[@schivelbusch1986, 43–44]

## Las ciudades dudan

La mayoría de las ciudades de las líneas principales cedieron en pocos años, porque un reloj que no coincidía con el de la estación hacía perder trenes. Algunas resistieron. En 1852 el reloj de la Lonja de Granos de Bristol recibió una segunda aguja de minutos, una para Bristol y otra para Londres, y conserva las dos.[@simmons1991, 346] En Exeter, adonde el ferrocarril llegó en 1844, el reloj de la catedral siguió marcando la hora de la ciudad durante algunos años después de que cambiara el de la estación.[^exeter]

[^exeter]: Sobre las ciudades británicas, y sobre la misma disputa en las ciudades estadounidenses treinta años después, véase [@simmons1991, 346–47; y @bartky2000, cap. 9]

La hora media local seguía al sol, y el sol aún ordenaba la jornada de campesinos, pescadores y de cualquiera cuyo trabajo dependiera de la luz del día. Una hora fijada en Londres era para ellos una imposición. El historiador de la disciplina fabril ha sostenido que el reloj se había convertido ya en el siglo XVIII en un medio de controlar el trabajo;[@thompson1967, 80–82] la disputa por la hora del ferrocarril extendió ese argumento a ciudades enteras, a las que se pedía aceptar una hora fijada en otra parte.

## Los tribunales se resisten

Las leyes que mencionaban una hora se referían a la del lugar, y esa hora era la hora media local. En 1858 un juicio en Dorchester empezó a las diez según el reloj del tribunal, que seguía la hora de Londres, y se dictó sentencia contra un demandado que llegó a las diez según la hora de la ciudad, unos minutos más tarde. En la apelación, los jueces sostuvieron que la hora fijada era la local, y la sentencia se anuló.[@howse1980, 113]

La Statutes (Definition of Time) Act de 1880 cerró la brecha. Declaraba que toda expresión de tiempo en una ley, una escritura u otro instrumento jurídico significaba, salvo indicación en contrario, la hora media de Greenwich en Gran Bretaña y la de Dublín en Irlanda.[@howse1980, 114]

## Un acuerdo, no una conquista

Vista desde 1840, la hora del ferrocarril era uno de varios arreglos posibles. Las compañías podrían haber mantenido las horas locales e impreso tablas de correcciones, como hicieron algunos ferrocarriles estadounidenses hasta 1883,[@bartky2000, 140–45] y el sistema internacional de husos que siguió a la conferencia de Washington de 1884 tardó medio siglo en llegar a la mayor parte del mundo.[@ogle2015, cap. 1] En Gran Bretaña las distancias eran cortas, las compañías eran pocas y podían ponerse de acuerdo en una sola cámara de compensación, y el telégrafo llegó a las estaciones al mismo tiempo que los trenes. Esas condiciones, más que ningún principio, explican la rapidez con que un país de mediodías locales pasó a guardar una sola hora.[@ogle2015, 25; véase también @schivelbusch1986, cap. 3]

## Bibliografía

:::bibliography{title=""}

:::paragraphs{style="colophon"}
Ensayo de muestra para el Recetario de Postext (CC BY 4.0). Obras citadas reales, páginas ilustrativas. Crimson Pro e 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 (gotcha: fonts-first).
const FONTS = {
  'Crimson Pro': ['300', '400', '400i', '600', '600i'],
  'IBM Plex Sans Condensed': ['400', '600'],
};

// ─── 4 · Build & show ───────────────────────────────────────────────────────
await loadFonts(FONTS, markdown);
const doc = await buildWithFonts(() => buildDocument({ markdown }, config()), markdown);
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 v1 ── the same in every recipe · postext.dev/cookbook ────────
// Postext measures text with the faces the browser has loaded, and caches the
// widths, so every face must be ready before the first build. Faces come from
// Fontsource: the same static files the PDF embeds, so screen and PDF agree.

/** faces = { 'Family Name': ['400', '400i', '700'] }. `text` is the sample:
 *  letters beyond Latin-1 (č, ł, ő…) also load the latin-ext files. With
 *  `optional`, a face Fontsource does not ship is skipped instead of failing.
 *  Resolves to the number of faces added. */
async function loadFonts(faces, text = '', { optional = false } = {}) {
  kitStatus('Loading fonts…');
  const ranges = {
    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',
  };
  const subsets = /[Ā-˿Ḁ-ỿ]/.test(text) ? ['latin', 'latin-ext'] : ['latin'];
  const jobs = [];
  let added = 0;
  for (const [family, specs] of Object.entries(faces)) {
    const id = fontsourceId(family);
    const meta = optional ? await fontsourceMeta(family) : null;
    for (const spec of new Set(specs)) {
      const weight = parseInt(spec, 10);
      const style = spec.endsWith('i') ? 'italic' : 'normal';
      if (hasFace(family, weight, style)) continue;
      if (optional && !(meta?.weights.includes(weight) && meta.styles.includes(style))) continue;
      for (const subset of subsets) {
        const url = `https://cdn.jsdelivr.net/npm/@fontsource/${id}@5/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().then((ready) => { document.fonts.add(ready); added++; }, () => {
          if (subset === 'latin' && !optional) throw new Error(`Fontsource has no ${family} ${weight} ${style}`);
        }));
      }
    }
  }
  await Promise.all(jobs).catch((error) => { kitFail(error); throw error; });
  return added;
}

/** Runs `build` (a buildDocument or buildBundle call) and checks the faces
 *  the pages use. A regular face missing from FONTS is loaded with a warning;
 *  bold and italic variants are loaded when the family ships them. Then the
 *  measurement caches are cleared and the build runs again. */
async function buildWithFonts(build, text = '') {
  const tried = new Set();
  for (let round = 0; round < 3; round++) {
    kitStatus('Laying out…');
    await new Promise(requestAnimationFrame);          // let the status paint first
    const result = await Promise.resolve().then(build).catch((error) => { kitFail(error); throw error; });
    const wanted = { base: {}, variants: {} };
    for (const { font, base } of [result].flat().flatMap(fontStringsOf)) {
      const { family, weight, style } = parseFont(font);
      const key = `${family}|${weight}|${style}`;
      if (tried.has(key) || hasFace(family, weight, style)) continue;
      tried.add(key);
      (wanted[base ? 'base' : 'variants'][family] ??= []).push(`${weight}${style === 'italic' ? 'i' : ''}`);
    }
    if (Object.keys(wanted.base).length) {
      console.warn(`[cookbook] FONTS does not list ${JSON.stringify(wanted.base)}: loading them.`);
    }
    const added = await loadFonts(wanted.base, text) + await loadFonts(wanted.variants, text, { optional: true });
    if (added === 0) return result;
    clearMeasurementCache();
  }
  throw new Error('The fonts did not settle after three builds.');
}

/** Every font string of the layout. `base` marks a block's own face; its
 *  bold, italic and bold-italic variants are listed whether or not used. */
function fontStringsOf(doc) {
  const found = new Map();
  const walk = (node) => {
    if (!node || typeof node !== 'object') return;
    if (Array.isArray(node)) { node.forEach(walk); return; }
    for (const [key, value] of Object.entries(node)) {
      if (typeof value === 'string' && /fontString$/i.test(key)) {
        found.set(value, found.get(value) || key === 'fontString');
      } else if (value && typeof value === 'object') walk(value);
    }
  };
  walk(doc.pages);
  walk(doc.blocks);
  return [...found].map(([font, base]) => ({ font, base }));
}

/** '700 37.5px Open Sans' / 'italic 400 13px "Source Serif 4"' → { family, weight, style }.
 *  A string with no weight ('95.8px Young Serif', from a design text) is 400. */
function parseFont(font) {
  const m = /^(?:(italic|oblique)\s+)?(?:small-caps\s+)?(?:(\d+|bold|normal)\s+)?[\d.]+px\s+(.+)$/.exec(font.trim());
  if (!m) throw new Error(`Unexpected font string: ${font}`);
  const weight = m[2] === 'bold' ? 700 : !m[2] || m[2] === 'normal' ? 400 : Number(m[2]);
  return { family: m[3].replace(/^["']|["']$/g, ''), weight, style: m[1] ? 'italic' : 'normal' };
}

/** True when a loaded FontFace covers exactly this family, weight and style
 *  (document.fonts.check() is also true 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;
}

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

/** The weights and styles a family ships ({ weights: [400, 700], styles: ['normal', 'italic'] }), 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 v1 ── the same in every recipe · postext.dev/cookbook ───────
/** Shows the pages as facing spreads on a dark desk: the first page is a
 *  recto on its own, then verso | recto pairs, as in a bound book. Pages
 *  are painted when they scroll near the screen. */
function showPages(docs, { title, width = 460 } = {}) {
  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, { 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 v1 ── the same in every recipe that exports a PDF ──────────────
/** postext-pdf embeds TrueType bytes. Fetch the Fontsource file the screen
 *  used, snapping to a weight the family ships and falling back to upright
 *  when it has no italic: the PDF asks for every face a block could use. */
async function fontsourceProvider(family, weight, style) {
  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 res = await fetch(`https://cdn.jsdelivr.net/npm/@fontsource/${id}@5/files/${id}-latin-${w}-${s}.woff2`);
  if (!res.ok) throw new Error(`Fontsource has no ${family} ${w} ${s} (${res.status})`);
  return decompressWoff2(new Uint8Array(await res.arrayBuffer()));
}

/** A "Build the PDF" button in the bar. Once built: "Open the PDF" (a new
 *  tab, since CodePen's preview frame cannot show 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 ───────────────────────────────────────────────────────────────────────
```

## Variantes

### Lleva las notas al final

Algunas revistas reúnen las notas tras el ensayo; las citas conservan sus formas completa y breve.

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

### Vuelve a escribir ibid.

La 17.ª edición del estilo de Chicago imprime *ibid.* en la nota que repite la obra anterior. Pega el archivo `.csl` de ese estilo, del repositorio de estilos de Zotero, en una cadena y úsalo como estilo propio.

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

## Errores frecuentes

- **Cualquier objeto headings desactiva el salto de página del H1.** Por defecto un H1 salta a una página impar (always-odd), pero cualquier objeto headings anula ese valor, así que los capítulos van seguidos y span: 'page' no hace nada. Vuelve a declarar headings.levels[0].breakBefore: { enabled: true, parity } en cada configuración.
- **Carga todas las fuentes antes de componer.** La composición mide el texto con las fuentes que el navegador ha cargado y guarda los anchos, así que una fuente que llega después de la primera composición deja cortes de línea erróneos y un PDF que ya no coincide con la pantalla. Carga antes todos los pesos y estilos, y llama a clearMeasurementCache() antes de recomponer si alguna llega tarde.
- **Una paleta cambiada no llega a los elementos de diseño ni al color de las remisiones.** postext 1.4.1 aplica colorPalette a los estilos de texto (cuerpo, títulos, listas, pies, tablas, recuadros), pero no a los elementos de cabeceras, pies de página, aperturas y portadillas, ni a bodyText.referenceColor: conservan el hex escrito junto a su paletteId. Si cambias la paleta, para una edición de pantalla oscura o para recolorear, reescribe cada color enlazado a partir de colorPalette antes de componer.
- **Solo 8 idiomas tienen separación silábica, con el código exacto.** La separación silábica existe para en-us, es, fr, de, it, pt, ca y nl, con el código exacto: 'es-ES' o cualquier otro idioma pasa sin aviso al inglés americano.
- **Una configuración se cachea por identidad: crea un objeto nuevo.** El motor guarda en caché las configuraciones resueltas según la identidad del objeto, así que modificar el mismo objeto y volver a componer reutiliza el resultado anterior. Crea un objeto nuevo en cada composición: por eso la configuración de una receta es una función, config().

- No cierres con punto una nota que acaba en una cita: el estilo ya pone el suyo, y Postext no funde los dos, así que la nota terminaría con dos puntos.
- En un estilo de notas, `@howse1980` sin corchetes deja en la frase solo el número de la nota, *Como ¹ dice*, sin el nombre del autor. Escribe tú el nombre y cita entre corchetes: `Como dice Howse,[@howse1980]`.

## Créditos

- Receta: Ignacio Ferro ([@drnachio](https://github.com/drnachio))
- Tipografías: Crimson Pro (OFL-1.1), IBM Plex Sans Condensed (OFL-1.1)
- Código: MIT · Contenido de ejemplo: CC-BY-4.0

## Relacionadas

- [N.º 087 · Un capítulo de tesis citado en APA 7](https://postext.dev/es/cookbook/apa-thesis-with-bibtex.md): Un capítulo de tesis doctoral cuyas citas [@clave, p. 33] salen en APA 7 gracias a citeproc-js, con la lista de referencias tomada de un bloque BibTeX. · Nivel 2 (Intermedio) · Artículos y trabajos académicos, Informes y memorias
- [N.º 093 · Un mismo texto en cuatro estilos de cita](https://postext.dev/es/cookbook/one-text-four-citation-styles.md): Un ensayo breve con seis citas, compuesto en APA 7, Chicago autor-año, IEEE e ISO 690: el ajuste del estilo es lo único que cambia. · Nivel 2 (Intermedio) · Artículos y trabajos académicos, Informes y memorias
- [N.º 031 · Final de tesis: apéndice, glosario e índice](https://postext.dev/es/cookbook/thesis-back-matter.md): El final de una tesis en blanco y negro: apéndice con letra, glosario a dos columnas, bibliografía APA e índice sacado de marcas en el texto. · Nivel 3 (Avanzado) · Artículos y trabajos académicos
