/* Layout: a Book of Hours read at night, on one sheet of dark paper. A terminal written over a
   faint manuscript is the whole page, and every office opens inside it: a rose window that is
   also a 24-hour clock, lancet windows that hold the hours, specimen cards that hold the
   bestiary. The accent is the green of Ordinary Time, and it never changes.
   Nothing has a light fill. Every animation stops when the visitor asks for stillness: the
   Motus button in the footer, or the system setting for reduced motion. */

@property --k { syntax: "<length>"; inherits: false; initial-value: 12px; }

:root {
  /* the one ground, dark paper (the stock below), and the light ink that reads on it */
  --bg: var(--stock);
  --bg-2: #14100c;
  --panel: rgba(10, 8, 5, 0.34);
  --panel-hi: rgba(42, 34, 24, 0.5);
  --ink: #ece3cf;
  --muted: var(--sepia-2);
  --faint: #6f624a;
  --rule: rgba(203, 184, 143, 0.12);
  --edge: rgba(203, 184, 143, 0.2);
  --lead: #020106;
  --gilt: #e6c060;
  --gilt-hi: #fff0b8;
  --shine: rgba(255, 255, 255, 0.24);
  --sun: rgba(255, 236, 190, 0.55);

  /* the vestment: liturgical green, the one accent */
  --vest: #4fc98d;
  --glow: color-mix(in oklab, var(--vest) 50%, transparent);
  --tint: color-mix(in oklab, var(--vest) 12%, transparent);
  --echo: 5px 5px 0 -1px color-mix(in oklab, var(--vest) 20%, transparent);

  /* glass of the eight hours */
  --g-matutinum: #4659d6;
  --g-laudes: #e584ab;
  --g-prima: #f0c24f;
  --g-tertia: #46b3d0;
  --g-sexta: #ffd96b;
  --g-nona: #f08c3c;
  --g-vesperae: #c9417e;
  --g-completorium: #7650c4;

  /* the box, and the dark paper in it: brown-black stock, sepia ink and a fainter second ink,
     each at 4.5:1 or better on the stock */
  --box: #0b0908;
  --box-face: #17130f;
  --box-face-lo: #100d0a;
  --stock: #211b14;
  --stock-hi: #272017;
  --stock-lo: #1b1712;
  --sepia: #cbb88f;
  --sepia-2: #a8946c;
  /* the torn foot of a sheet: the mask, and the pale rim the tear leaves */
  --tear: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 14' preserveAspectRatio='none'%3E%3Cpath d='M0 0H200V8L192 7.5 189.6 9.3 187.2 7.7 181.8 8.8 178.6 9.3 176.2 7.9 171.3 4.1 168.3 6.8 162.3 8.6 156 8 152.8 7 150.2 8.4 145.3 10.2 142.5 11.6 138.5 10 132.9 9.4 130.6 8.8 128.1 9.2 122.7 3 120.3 3 117.1 4.2 114.7 5.8 110.9 3 104.8 8.5 101.9 8.8 95.6 9.2 91.8 6.3 86.4 10.2 84.1 8.9 80.7 9.1 75.5 9.9 69 5.1 65.7 6.5 61.5 7.4 56.6 10.2 52.6 9.3 48.5 9.2 45.7 9.8 43.4 10.4 40.7 7.9 35.9 8.9 29.5 5 27.3 7.8 24.9 5.9 21.6 6.1 16.7 4.7 12.4 4 8.1 3.6 4 3.8 0 8Z'/%3E%3C/svg%3E");
  --tear-rim: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 14' preserveAspectRatio='none'%3E%3Cpath d='M0 8 4 3.8 8.1 3.6 12.4 4 16.7 4.7 21.6 6.1 24.9 5.9 27.3 7.8 29.5 5 35.9 8.9 40.7 7.9 43.4 10.4 45.7 9.8 48.5 9.2 52.6 9.3 56.6 10.2 61.5 7.4 65.7 6.5 69 5.1 75.5 9.9 80.7 9.1 84.1 8.9 86.4 10.2 91.8 6.3 95.6 9.2 101.9 8.8 104.8 8.5 110.9 3 114.7 5.8 117.1 4.2 120.3 3 122.7 3 128.1 9.2 130.6 8.8 132.9 9.4 138.5 10 142.5 11.6 145.3 10.2 150.2 8.4 152.8 7 156 8 162.3 8.6 168.3 6.8 171.3 4.1 176.2 7.9 178.6 9.3 181.8 8.8 187.2 7.7 189.6 9.3 192 7.5 200 8' fill='none' stroke='rgba(203,184,143,0.3)' stroke-width='2.4'/%3E%3C/svg%3E");

  /* the terminal under the rose */
  --tty-bg: #020504;

  /* code */
  --syn-kw: var(--vest);
  --syn-ty: var(--gilt);
  --syn-num: #ff9ec7;
  --syn-attr: #6fd0ea;
  --err: #ff6b6b;
  --ins: color-mix(in oklab, var(--vest) 14%, transparent);

  /* type */
  --font-display: "Jacquard 24", "UnifrakturMaguntia", "Old English Text MT", "Courier New", monospace;
  --font-body: "Instrument Sans", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-voice: "Instrument Serif", "Iowan Old Style", "Palatino Linotype", Georgia, serif;
  --font-mono: "JetBrains Mono", ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;

  --step--1: 0.8125rem;
  --step-0: 1.0625rem;
  --step-1: 1.25rem;
  --step-2: 1.6rem;
  --step-3: clamp(2.6rem, 6.5vw, 5rem);
  --step-4: clamp(5rem, 16vw, 12.5rem);

  --measure: 65ch;
  --ease: cubic-bezier(0.2, 0.7, 0.2, 1);

  color-scheme: dark;
}

/* ---------- base ---------- */

*, *::before, *::after { box-sizing: border-box; }

html { scroll-padding-top: 1.5rem; -webkit-text-size-adjust: 100%; }
/* Not before liturgy.js has landed a link into the page: a glide that starts while the layout
   above is still changing ends where the target used to be. */
:root[data-motion="on"][data-landed] { scroll-behavior: smooth; }

/* The paper sits on body so that it moves to the canvas: one ground under everything. */
body {
  margin: 0;
  background: url("paper.png") 0 0 / 128px, linear-gradient(172deg, var(--stock-hi), var(--stock) 45%, var(--stock-lo)) fixed;
  background-color: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--step-0);
  line-height: 1.6;
  overflow-x: hidden;
}

body::before {
  content: "";
  position: fixed;
  inset: 0 0 auto;
  height: env(safe-area-inset-top, 0px);
  z-index: 30;
  background: var(--bg);
}

img, svg, canvas { max-width: 100%; }
h1, h2, h3 { text-wrap: balance; margin: 0; }
p { margin: 0; }
a { color: inherit; text-decoration-color: var(--vest); text-decoration-thickness: 1px; text-underline-offset: 0.22em; transition: color 0.25s ease, text-shadow 0.25s ease; }
a:hover { color: var(--vest); text-shadow: 0 0 14px var(--glow); }
code, pre, .tty, .out, .chip { font-variant-ligatures: none; }
code {
  font-family: var(--font-mono);
  font-size: 0.86em;
  color: color-mix(in oklab, var(--ink) 82%, var(--vest));
  background: rgba(255, 255, 255, 0.045);
  padding: 0.05em 0.35em;
  border: 1px solid var(--rule);
  white-space: nowrap;
}
::selection { background: color-mix(in oklab, var(--vest) 38%, transparent); color: #fff; }

:focus-visible { outline: 2px solid var(--vest); outline-offset: 3px; }

.tabular { font-variant-numeric: tabular-nums; }
.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

.wrap {
  width: 100%;
  max-width: 1240px;
  margin-inline: auto;
  padding-left: max(16px, env(safe-area-inset-left, 0px));
  padding-right: max(16px, env(safe-area-inset-right, 0px));
}

.skip {
  position: absolute;
  left: 1rem;
  top: -4rem;
  z-index: 40;
  background: var(--bg-2);
  color: var(--ink);
  border: 1px solid var(--vest);
  padding: 0.5rem 0.9rem;
  font-family: var(--font-mono);
  font-size: var(--step--1);
}
.skip:focus { top: calc(env(safe-area-inset-top, 0px) + 0.5rem); }

.latin { font-family: var(--font-display); font-weight: 400; letter-spacing: 0.01em; }
.vulgar { font-family: var(--font-voice); font-style: italic; font-weight: 400; }

@keyframes spin { to { rotate: 360deg; } }
@keyframes spin-back { to { rotate: -360deg; } }

/* ---------- glass panels ---------- */

.beast, .beast-recto, .beast-verso, .codebox, .verdict, .examen-grid.one {
  position: relative;
  background: linear-gradient(160deg, var(--panel-hi), var(--panel) 62%);
  border: 1px solid var(--edge);
  box-shadow: var(--echo), 0 30px 70px -40px rgba(0, 0, 0, 0.95), inset 0 1px 0 rgba(255, 255, 255, 0.05);
}

/* corner brackets, as on a heads-up display */
.beast::before, .beast-recto::before, .beast-verso::before, .codebox::before, .verdict::before, .examen-grid.one::before {
  content: "";
  position: absolute;
  inset: -1px;
  pointer-events: none;
  opacity: 0.85;
  background:
    linear-gradient(var(--vest) 0 0) left top / var(--k) 2px,
    linear-gradient(var(--vest) 0 0) left top / 2px var(--k),
    linear-gradient(var(--vest) 0 0) right top / var(--k) 2px,
    linear-gradient(var(--vest) 0 0) right top / 2px var(--k),
    linear-gradient(var(--vest) 0 0) left bottom / var(--k) 2px,
    linear-gradient(var(--vest) 0 0) left bottom / 2px var(--k),
    linear-gradient(var(--vest) 0 0) right bottom / var(--k) 2px,
    linear-gradient(var(--vest) 0 0) right bottom / 2px var(--k);
  background-repeat: no-repeat;
  filter: drop-shadow(0 0 4px var(--glow));
  transition: --k 0.45s var(--ease), opacity 0.45s ease;
}

/* ---------- introit: the terminal, written over a manuscript ---------- */

/* The site is one sheet of dark paper with a terminal on it. Under the command line lies a
   manuscript of drafts, faint as an older text scraped from the page and written over: scraps
   of the introit, the introduction as first written and struck out, a compass drawing of the
   rose, the litany begun up the margin. A scrap comes up under the pointer, or when a link in
   it has the focus. The rose window opens inside the terminal from the button in its bar, and
   the commands step aside for it. */
.introit { --head: env(safe-area-inset-top, 0px); }
.palimpsest {
  --bar-h: 2.6rem;
  --pad: clamp(1rem, 4.5vw, 4.5rem);
  --view: calc(100svh - var(--head)); /* the sheet fills the window */
  position: relative;
  height: var(--view);
  min-height: 22rem;
  margin-top: var(--head);
  overflow: clip;
  /* the paper is the body's; the sheet adds only its age: darker edges, foxing, and the green
     light of the terminal */
  background:
    radial-gradient(120% 95% at 50% 45%, transparent 58%, rgba(0, 0, 0, 0.36)),
    radial-gradient(55% 45% at 16% 16%, color-mix(in oklab, var(--vest) 6%, transparent), transparent 70%),
    radial-gradient(4rem 3rem at 93% 12%, rgba(120, 86, 44, 0.14), transparent),
    radial-gradient(3rem 2.4rem at 4% 64%, rgba(120, 86, 44, 0.12), transparent),
    radial-gradient(7rem 4rem at 58% 97%, rgba(120, 86, 44, 0.1), transparent);
}

/* the manuscript: sepia ink, and green where a missal would have red */
.manuscript {
  --ink: var(--sepia);
  --muted: var(--sepia-2);
  --rubric: color-mix(in oklab, var(--vest) 72%, var(--sepia));
  --rule: rgba(203, 184, 143, 0.12);
  position: absolute;
  inset: 0;
  color: var(--ink);
  transition: opacity 0.5s ease;
}

/* Each scrap keeps a third of its ink, and gets it back under the pointer or the focus. */
.scrap { position: absolute; margin: 0; opacity: 0.3; transition: opacity 0.6s ease; }
.scrap:hover, .scrap:focus-within { opacity: 0.9; }

.scrap-versicle { display: grid; justify-items: start; gap: 0.4rem; width: min(25rem, 82%); rotate: -1.4deg; }
.scrap .eyebrow { font-size: 0.6rem; color: var(--rubric); }
.scrap .eyebrow span::before { color: inherit; text-shadow: none; }
.scrap .versicle { gap: 0.1rem; font-size: clamp(1.05rem, 0.9rem + 0.45vw, 1.35rem); line-height: 1.2; }
.scrap .versicle p { padding-left: 1.45em; text-indent: -1.45em; }
.scrap .versicle .vr { display: inline-block; width: 1.45em; text-indent: 0; font-size: 0.66em; vertical-align: 0.1em; color: var(--rubric); text-shadow: none; }

.fleuron { display: flex; align-items: center; gap: 0.7rem; width: 9rem; font-size: 0.7rem; line-height: 1; color: var(--rubric); }
.fleuron::before, .fleuron::after { content: ""; flex: 1; height: 1px; background: linear-gradient(90deg, transparent, color-mix(in oklab, var(--ink) 45%, transparent)); }
.fleuron::after { background: linear-gradient(270deg, transparent, color-mix(in oklab, var(--ink) 45%, transparent)); }

/* the introduction, ruled, under an illuminated initial; the lines are wide apart so that a
   correction can be written over a word struck out */
.scrap.lede {
  width: min(23rem, 84%);
  max-width: none;
  font: 400 clamp(0.8rem, 0.76rem + 0.12vw, 0.9rem) / 2 var(--font-voice);
  color: var(--ink);
  background: repeating-linear-gradient(180deg, transparent 0 calc(1lh - 1px), var(--rule) calc(1lh - 1px) 1lh);
  rotate: 0.6deg;
}
.scrap.lede::first-letter {
  float: left;
  margin: 0.4rem 0.55rem 0 0;
  padding: 0.3rem 0.4rem 0.4rem;
  font-family: var(--font-display);
  font-size: 3.2em;
  line-height: 0.8;
  color: var(--vest);
  background: radial-gradient(circle at 50% 40%, var(--tint), transparent 75%);
  border: 1px solid color-mix(in oklab, var(--gilt) 50%, transparent);
  box-shadow: inset 0 0 0 3px var(--stock), inset 0 0 0 4px color-mix(in oklab, var(--gilt) 25%, transparent);
}
.emend { position: relative; white-space: nowrap; }
.emend del { color: var(--muted); text-decoration: line-through 1px color-mix(in oklab, var(--ink) 75%, transparent); }
.emend ins {
  position: absolute;
  left: 50%;
  bottom: 1.02em;
  translate: -50% 0;
  font-size: 0.78em;
  font-style: italic;
  line-height: 1;
  text-decoration: none;
  color: var(--ink);
}
/* a hand in the margin points at the passage */
.nota { position: absolute; top: 2.3em; left: calc(100% + 1rem); line-height: 1; white-space: nowrap; color: var(--muted); }

/* the offices, as the table at the head of a book: folio, name, a dotted leader, and gloss */
.scrap.offices { width: min(19rem, 84%); rotate: -0.7deg; }
.offices ol { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.05rem; }
.offices a { display: flex; align-items: baseline; gap: 0.6rem; padding-block: 0.2rem; text-decoration: none; }
.offices a::after { content: ""; order: 1; flex: 1 1 1rem; min-width: 1rem; border-bottom: 1px dotted color-mix(in oklab, var(--ink) 32%, transparent); translate: 0 -0.3em; transition: border-color 0.3s ease; }
.offices .fol { flex: none; width: 3.2rem; font: 600 0.52rem / 1 var(--font-mono); letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); }
.offices .latin { font-size: 1.05rem; line-height: 1; color: var(--ink); transition: color 0.3s ease, text-shadow 0.3s ease; }
.offices .latin::first-letter { color: var(--rubric); }
.offices .vulgar { order: 2; font-size: 0.8rem; line-height: 1.25; color: var(--muted); }
.offices a:hover { color: inherit; text-shadow: none; }
.offices a:hover .latin { color: var(--vest); text-shadow: 0 0 14px var(--glow); }
.offices a:hover::after { border-color: color-mix(in oklab, var(--vest) 60%, transparent); }

/* the colophon: the scribe's note at the foot of the sheet */
.scrap.colophon { width: min(19rem, 84%); display: grid; gap: 0.3rem; font: 400 0.72rem / 1.55 var(--font-voice); color: var(--muted); rotate: 0.9deg; }
.scrap.colophon .ite { font: 400 1.15rem / 1 var(--font-display); color: var(--rubric); }

/* The drafts proper: fainter still, and not read out. */
.drafts { position: absolute; inset: 0; pointer-events: none; }
.vacat {
  position: absolute;
  font: italic 400 0.84rem / 1.8 var(--font-voice);
  color: color-mix(in oklab, var(--sepia-2) 26%, transparent);
  text-decoration: line-through 1px color-mix(in oklab, var(--sepia-2) 20%, transparent);
  rotate: -1.2deg;
}
.vacat .va { display: inline-block; color: color-mix(in oklab, var(--vest) 30%, transparent); }
.vacat .va:first-child { position: absolute; right: calc(100% + 0.6em); top: 0; }
.vacat .va:last-child { margin-left: 0.5em; }
.sketch { position: absolute; aspect-ratio: 1; overflow: visible; fill: none; stroke: color-mix(in oklab, var(--sepia-2) 26%, transparent); stroke-width: 0.55; }
.sketch .guide { stroke-width: 0.3; stroke-dasharray: 1.4 2.6; }
.sketch > circle, .sketch > use { stroke-dasharray: 1; }
.sketch .pin { fill: color-mix(in oklab, var(--sepia-2) 34%, transparent); stroke: none; }
.marginal {
  position: absolute;
  writing-mode: vertical-rl;
  rotate: 180deg;
  font: italic 400 0.74rem / 1.4 var(--font-voice);
  white-space: nowrap;
  color: color-mix(in oklab, var(--sepia-2) 28%, transparent);
}
.marginal em { color: color-mix(in oklab, var(--vest) 26%, transparent); }

/* Where the scraps lie. On a wide screen they keep to the right of the sheet, where the
   terminal seldom writes; on a tall one they lie under it, below its first lines. */
.scrap-versicle { top: 13%; right: 6%; }
.scrap.lede { top: 37%; right: 9%; }
.scrap.offices { bottom: 9%; right: 13%; }
.scrap.colophon { bottom: 6%; left: 30%; }
.vacat { top: 60%; left: 30%; width: min(22rem, 28%); }
.sketch { left: -5rem; bottom: -6rem; width: min(26rem, 50svh); }
.marginal { right: 1.6%; top: 16%; height: 70%; overflow: hidden; }
@media (max-width: 999.98px) and (max-aspect-ratio: 1/1) {
  .scrap-versicle { top: 37%; left: 7%; right: auto; }
  .scrap.lede { top: 49%; right: 6%; }
  .scrap.offices { bottom: 15%; left: 9%; right: auto; }
  .scrap.colophon { bottom: 3%; left: auto; right: 6%; width: min(19rem, 72%); }
  .vacat { top: calc(var(--bar-h) + 1.2rem); left: var(--pad); right: var(--pad); width: auto; max-width: 34rem; color: color-mix(in oklab, var(--sepia-2) 18%, transparent); text-decoration-color: color-mix(in oklab, var(--sepia-2) 14%, transparent); }
  .vacat .va:first-child { position: static; margin-right: 0.5em; }
  .sketch { left: auto; bottom: auto; right: -5rem; top: calc(var(--bar-h) - 3.5rem); width: 16rem; }
  .nota, .marginal { display: none; }
}
@media (max-width: 600px) and (max-aspect-ratio: 1/1) {
  .scrap-versicle { top: 35%; }
  .scrap.lede { top: 46%; }
  .scrap.offices { bottom: 18%; }
  .scrap.colophon { right: auto; left: 8%; width: 84%; font-size: 0.62rem; }
  .scrap.colophon .ite { font-size: 1rem; }
}

/* the ink comes up on the paper as the page opens, and the rose is drawn with the compass */
.scrap { animation: ink 1.6s var(--ease) backwards; }
.scrap.lede { animation-delay: 0.3s; }
.scrap.offices, .scrap.colophon { animation-delay: 0.6s; }
.vacat, .marginal { animation: ink 2.2s ease 0.8s backwards; }
.sketch > circle, .sketch > use { animation: draw 2.4s var(--ease) 0.5s backwards; }
.sketch > use { animation-delay: calc(0.9s + var(--i, 0) * 0.14s); }
.sketch .guide { animation: fade 2s ease 0.3s backwards; }
@keyframes ink { from { opacity: 0; filter: blur(4px); } }
@keyframes draw { from { stroke-dashoffset: 1; } }

/* the terminal, over the manuscript */
.tty {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-rows: var(--bar-h) minmax(0, 1fr);
  pointer-events: none; /* the manuscript stays to hand wherever the terminal has written nothing */
  font: 400 clamp(0.88rem, 0.8rem + 0.25vw, 1.05rem) / 1.7 var(--font-mono);
  color: color-mix(in oklab, var(--ink) 86%, var(--vest));
  /* a halo of the paper round each letter keeps the line clear of the drafts beneath */
  text-shadow: 0 0 2px var(--stock), 0 0 4px var(--stock), 0 0 8px var(--stock), 0 0 12px color-mix(in oklab, var(--vest) 22%, transparent);
}
.tty-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding-inline: var(--pad) calc(var(--pad) - 0.5rem);
  overflow: hidden;
  font-size: 0.68rem;
  line-height: 1.2;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--sepia-2);
  text-shadow: none;
  border-bottom: 1px solid rgba(203, 184, 143, 0.16);
  box-shadow: 0 4px 0 -3px rgba(203, 184, 143, 0.08);
  pointer-events: auto;
}
/* the name of the site, faded into the bar beside the terminal's */
.tty-mark { display: flex; align-items: baseline; gap: 0.9rem; white-space: nowrap; }
.tty-mark .latin { font-size: 1.35rem; line-height: 1; letter-spacing: 0; text-transform: none; color: color-mix(in oklab, var(--sepia) 46%, transparent); }
.tty-screen {
  overflow-y: auto;
  padding: clamp(1rem, 3vh, 2rem) var(--pad) 2rem;
  overflow-wrap: anywhere;
  scrollbar-width: thin;
  scrollbar-color: rgba(203, 184, 143, 0.25) transparent;
  transition: opacity 0.4s ease, visibility 0s;
}
.tty-screen > * { max-width: 72ch; pointer-events: auto; }
.tty-screen .prompt { color: var(--vest); margin-right: 0.8ch; }
.tty-screen .rite { color: var(--vest); }
.tty-screen .rite:empty { display: none; }
.tty-screen .dim { color: color-mix(in oklab, var(--sepia) 70%, var(--muted)); }
.tty-screen kbd { font: inherit; color: var(--vest); }
.tty-screen code { font-size: 1em; padding: 0 0.3ch; background: rgba(0, 0, 0, 0.25); border-color: rgba(203, 184, 143, 0.14); }
.tty-screen a { color: var(--vest); }
.tty-boot > [hidden] { display: none; }
.tty-boot #tty-hint { margin-top: 1.2em; }
.tty-echo { margin-top: 1em; }
.tty-table { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 0.1em 3ch; }
.tty-table > :nth-child(odd) { white-space: nowrap; color: var(--vest); }
.tty-screen .nunc-mark { color: var(--gilt); }

/* the line typed into, with a cursor that waits in it until it is used */
.tty-line { display: flex; align-items: baseline; margin-top: 1em; border-bottom: 1px solid transparent; transition: border-color 0.3s ease; }
.tty-line:focus-within { border-bottom-color: color-mix(in oklab, var(--vest) 45%, transparent); }
.tty-line input {
  flex: 1;
  min-width: 0;
  padding: 0;
  font: inherit;
  font-size: max(16px, 1em); /* no zoom on a phone */
  color: var(--ink);
  background: none;
  border: 0;
  outline: none;
  caret-color: var(--vest);
  text-shadow: inherit;
}
.tty-line input:not(:focus):placeholder-shown {
  background: linear-gradient(var(--vest), var(--vest)) 0 50% / 0.6em 1.15em no-repeat;
  animation: cursor 1.05s steps(2, jump-none) infinite;
}
@keyframes cursor { 50% { background-size: 0 0; } }
@media (max-width: 540px) {
  .tty-table { grid-template-columns: minmax(0, 1fr); }
  .tty-table > :nth-child(even) { margin-bottom: 0.5em; color: color-mix(in oklab, var(--sepia) 70%, var(--muted)); }
}

/* The bar's buttons: the rose, each office and the litany, each a small emblem with its name.
   At rest an emblem keeps half its colour, sunk into the paper; under the pointer, or while
   its view is open, it comes up whole. On a narrow screen only the emblems show. */
.tty-views { display: flex; align-items: center; gap: clamp(0.1rem, 1vw, 0.6rem); }
.view-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.3rem 0.45rem;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  color: color-mix(in oklab, var(--sepia-2) 80%, transparent);
  background: none;
  border: 0;
  cursor: pointer;
  transition: color 0.3s ease;
}
.view-btn .emblem { display: block; width: 1.6rem; height: 1.6rem; overflow: visible; opacity: 0.5; filter: saturate(0.45) sepia(0.3); transition: opacity 0.4s ease, filter 0.4s ease, rotate 0.9s var(--ease), translate 0.4s var(--ease); }
.view-btn:hover, .view-btn:focus-visible, .view-btn[aria-expanded="true"] { color: var(--sepia); }
.view-btn[aria-expanded="true"] { color: var(--vest); }
.view-btn:hover .emblem, .view-btn:focus-visible .emblem, .view-btn[aria-expanded="true"] .emblem { opacity: 1; filter: drop-shadow(0 0 6px color-mix(in oklab, var(--gilt) 35%, transparent)); translate: 0 -1px; }
.view-btn[data-view="rosa"]:hover .emblem, .view-btn[data-view="rosa"][aria-expanded="true"] .emblem { rotate: 45deg; }
.emblem.lancet { --gem: var(--gilt); width: 0.62rem; }
.emblem.hedera path { fill: color-mix(in oklab, var(--vest) 70%, var(--sepia)); }
.emblem.hedera .vein, .emblem.hedera .stem { fill: none; stroke-linecap: round; }
.emblem.hedera .vein { stroke: var(--bg-2); stroke-width: 0.8; }
.emblem.hedera .stem { stroke: color-mix(in oklab, var(--vest) 70%, var(--sepia)); stroke-width: 1.3; }
.emblem.initial { display: grid; place-items: center; font: 400 1.25rem / 1 var(--font-display); letter-spacing: 0; text-transform: none; color: var(--sepia); border: 1px solid color-mix(in oklab, var(--sepia) 40%, transparent); }
@media (max-width: 720px) {
  .view-btn .view-name { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
}
@media (max-width: 520px) {
  .tty-mark > :last-child { display: none; }
}

/* the rose, opened in the terminal: it fills the first screen of the sheet, the commands step
   aside, and the manuscript sinks back into the paper */
.tty > .rose {
  --rose: min(100vw - 2rem, var(--view) - var(--bar-h) - 2rem);
  position: absolute;
  top: var(--bar-h);
  left: 0;
  right: 0;
  height: min(100% - var(--bar-h), var(--view) - var(--bar-h));
  align-content: center;
  pointer-events: auto;
}
.tty > .rose[hidden] { display: none; }
.palimpsest:not([data-view]) .tty > .rose { pointer-events: none; } /* while it goes back into the button */
.tty > .rose::before { top: 50%; translate: -50% -50%; }
@media (max-aspect-ratio: 4/5) {
  .tty > .rose { --rose: min(100vw, var(--view) - var(--bar-h) - 2rem); }
}
.palimpsest[data-view] .manuscript { opacity: 0.4; }
.palimpsest[data-view]:not([data-view="rosa"]) .manuscript { opacity: 0.12; }
.palimpsest[data-view] .tty-screen { opacity: 0; visibility: hidden; transition: opacity 0.3s ease, visibility 0s 0.3s; }

/* An office opened in the terminal: it fills the sheet under the bar and scrolls within it, on
   the same paper. Its name is in the bar already, so the view opens on its objects, the windows
   or the cards; the heading stays for screen readers, and the office's few words of
   introduction come after the objects, small. */
.tty > .view {
  position: absolute;
  top: var(--bar-h);
  left: 0;
  right: 0;
  bottom: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  scroll-padding-top: 1rem;
  scrollbar-width: thin;
  scrollbar-color: rgba(203, 184, 143, 0.25) transparent;
  padding-top: clamp(1rem, 3vh, 2rem);
  font: 400 var(--step-0) / 1.6 var(--font-body);
  font-variant-ligatures: normal;
  color: var(--ink);
  text-shadow: none;
  pointer-events: auto;
}
.tty > .view > .wrap { display: flex; flex-direction: column; }
.tty > .view .office-head { order: 1; display: block; max-width: 38rem; margin: clamp(1.5rem, 4vh, 2.5rem) 0 0; }
.tty > .view .office-head .folio, .tty > .view .compartment > .label { display: none; }
.tty > .view .office-head h2 { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.tty > .view .office-lede { font-size: var(--step--1); line-height: 1.6; color: var(--muted); }
.tty > .view[hidden]:not([hidden="until-found"]) { display: none; }
.tty > .view[hidden], .palimpsest:not([data-view]) .tty > .view { pointer-events: none; }
.tty > .view:focus { outline: none; } /* a link to it gives it the focus, and it fills the sheet */

/* the litany, said one petition at a time */
.petitions { list-style: none; margin: 0 auto; padding: 0 0 clamp(2rem, 6vh, 4rem); display: grid; gap: clamp(0.5rem, 1.6vh, 0.9rem); max-width: 40rem; text-align: center; font: 400 clamp(1.2rem, 1rem + 0.9vw, 1.75rem) / 1.3 var(--font-voice); text-wrap: balance; }
.petitions em { color: var(--vest); text-shadow: 0 0 14px var(--glow); }
.petitions li + li::before { content: "❦"; display: block; margin-bottom: clamp(0.5rem, 1.6vh, 0.9rem); font-size: 0.55em; color: color-mix(in oklab, var(--sepia-2) 60%, transparent); }
.petitions .rogamus { margin-top: 0.6rem; font-size: 1.1em; }
.litania .office-head { grid-template-columns: minmax(0, 1fr); text-align: center; }
.litania .office-head h2 { justify-content: center; }
.tty > .litania .petitions { padding-top: clamp(0.5rem, 3vh, 2rem); }

.eyebrow {
  font-family: var(--font-mono);
  font-size: var(--step--1);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem 0.9rem;
}
.eyebrow span:empty { display: none; }
.eyebrow span::before { content: "◆ "; color: var(--vest); text-shadow: 0 0 10px var(--glow); }

/* The 404 page keeps a woven title: row by row, as on the loom the typeface is named after.
   The shuttle rides the edge of the cloth, so both step together. */
h1 {
  position: relative;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--step-4);
  line-height: 0.8;
  letter-spacing: -0.01em;
  display: flex;
  flex-wrap: wrap;
  column-gap: 0.18em;
  margin-block: 0.1em 0.05em;
}
.h1-b {
  background: linear-gradient(100deg, var(--vest) 0%, var(--vest) 30%, var(--gilt-hi) 45%, var(--gilt) 50%, var(--vest) 62%, var(--vest) 100%);
  background-size: 260% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  filter: drop-shadow(0 0 26px var(--glow));
  animation: shimmer 9s linear infinite;
}
@keyframes shimmer { from { background-position: 100% 0; } to { background-position: -160% 0; } }
.lost h1 { animation: weave 1.2s steps(14, end) 0.2s backwards; }
.lost h1::after {
  content: "";
  position: absolute;
  left: -2%;
  right: -2%;
  top: 130%;
  height: 2px;
  translate: 0 -100%;
  background: linear-gradient(90deg, transparent, var(--gilt-hi), var(--vest), transparent);
  box-shadow: 0 0 16px var(--gilt), 0 0 32px var(--glow);
  opacity: 0;
  pointer-events: none;
  animation: shuttle 1.2s steps(14, end) 0.2s backwards;
}
@keyframes weave {
  from { clip-path: inset(-20% -6% 130% -6%); }
  to { clip-path: inset(-20% -6% -30% -6%); }
}
@keyframes shuttle {
  from { top: -30%; opacity: 1; }
  to { top: 130%; opacity: 1; }
}

.versicle { display: grid; gap: 0.15rem; font-family: var(--font-voice); font-size: var(--step-2); line-height: 1.25; }
.versicle .vr { font-family: var(--font-body); font-weight: 600; color: var(--vest); font-size: 0.8em; margin-right: 0.25em; text-shadow: 0 0 12px var(--glow); }

.lede { max-width: var(--measure); color: color-mix(in oklab, var(--ink) 88%, var(--muted)); }

@keyframes rise { from { opacity: 0; translate: 0 22px; filter: blur(6px); } }
@keyframes fade { from { opacity: 0; } }

.out .prompt { color: var(--vest); margin-right: 0.4em; text-shadow: 0 0 8px var(--glow); }

.actions { display: flex; flex-wrap: wrap; gap: 0.9rem; }

.btn {
  position: relative;
  display: inline-block;
  overflow: hidden;
  isolation: isolate;
  font: 600 var(--step--1) / 1 var(--font-mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink);
  background: linear-gradient(180deg, color-mix(in oklab, var(--vest) 24%, var(--bg-2)), color-mix(in oklab, var(--vest) 7%, var(--bg)));
  border: 1px solid color-mix(in oklab, var(--vest) 75%, transparent);
  padding: 0.95rem 1.25rem;
  box-shadow: var(--echo), 0 14px 34px -16px var(--glow), inset 0 1px 0 rgba(255, 255, 255, 0.1);
  cursor: pointer;
  transition: translate 0.3s var(--ease), box-shadow 0.3s ease, border-color 0.3s ease;
}
.btn::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(110deg, transparent 30%, rgba(255, 255, 255, 0.2) 48%, transparent 66%);
  translate: -110% 0;
  transition: translate 0.8s var(--ease);
}
.btn:hover {
  color: #fff;
  text-shadow: none;
  translate: 0 -2px;
  border-color: var(--vest);
  box-shadow: 7px 7px 0 -1px color-mix(in oklab, var(--vest) 32%, transparent), 0 0 30px -4px var(--glow), inset 0 1px 0 rgba(255, 255, 255, 0.14);
}
.btn:hover::before { translate: 110% 0; }
.btn:active { translate: 1px 1px; box-shadow: 2px 2px 0 -1px color-mix(in oklab, var(--vest) 30%, transparent), 0 0 16px -4px var(--glow); }
.btn.ghost { background: rgba(255, 255, 255, 0.025); border-color: var(--edge); box-shadow: none; }
.btn.ghost:hover { border-color: var(--vest); box-shadow: 0 0 26px -8px var(--glow); }

/* rose window */
.rose { position: relative; width: 100%; margin: 0; display: grid; gap: 1.1rem; justify-items: center; min-width: 0; }
.rose::before {
  content: "";
  position: absolute;
  z-index: -1;
  top: 0;
  left: 50%;
  width: min(100%, var(--rose, 560px));
  aspect-ratio: 1;
  translate: -50% 0;
  border-radius: 50%;
  background: conic-gradient(var(--g-matutinum), var(--g-laudes), var(--g-prima), var(--g-tertia), var(--g-sexta), var(--g-nona), var(--g-vesperae), var(--g-completorium), var(--g-matutinum));
  filter: blur(80px);
  opacity: 0.38;
  scale: 0.92;
  animation: spin 48s linear infinite;
}
.rose svg {
  width: min(100%, var(--rose, 560px));
  aspect-ratio: 1;
  height: auto;
  overflow: visible;
  transform: perspective(1100px) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
  transition: transform 0.6s var(--ease);
  animation: rose-in 1.8s var(--ease) 0.1s backwards;
}

@keyframes rose-in { from { opacity: 0; scale: 0.84; rotate: -24deg; } }

.rose .lead { fill: none; stroke: var(--lead); stroke-width: 1.5; stroke-linejoin: round; }
.rose .rim { fill: var(--bg-2); stroke: color-mix(in oklab, var(--gilt) 55%, var(--lead)); stroke-width: 2.4; }
.rose .ground { fill: var(--lead); }
.rose .tick { stroke: var(--gilt); stroke-width: 0.8; }
.rose .tick.major { stroke-width: 1.6; }
.rose .bead { fill: var(--gilt); stroke: var(--lead); stroke-width: 1; }
.rose .bead.alt { fill: var(--vest); }
.rose .petal { cursor: pointer; outline: none; transform-box: view-box; transform-origin: 0 0; animation: petal-in 1s var(--ease) backwards; animation-delay: calc(0.45s + var(--i, 0) * 0.08s); }
.rose .petal path.glass { stroke: var(--lead); stroke-width: 1.8; stroke-linejoin: round; opacity: 0.86; transition: opacity 0.3s ease; animation: breathe 6s ease-in-out infinite; animation-delay: calc(var(--i, 0) * -0.75s); }
.rose .petal .gem { fill: var(--gilt); stroke: var(--lead); stroke-width: 1.2; }
.rose .petal:hover path.glass, .rose .petal:focus-visible path.glass { opacity: 1; animation: none; }
.rose .petal:focus-visible .glass { stroke: var(--vest); stroke-width: 3; }
.rose .petal.now .glass { opacity: 1; stroke: var(--gilt); stroke-width: 2.6; animation: none; }
.rose .petal.now .halo { opacity: 0.8; animation: halo 3.2s ease-in-out infinite; }
.rose .halo { opacity: 0; filter: url(#rose-glow); }
.rose .tre { stroke: var(--lead); stroke-width: 1.2; }
.rose .boss { fill: var(--bg-2); stroke: var(--lead); stroke-width: 1.8; }
.rose .inner path { stroke: var(--lead); stroke-width: 1; }
.rose .core { fill: var(--gilt); stroke: var(--lead); stroke-width: 1.2; }
.rose .hand { stroke: var(--gilt); stroke-width: 2.2; stroke-linecap: square; }
.rose .hand-tip { fill: var(--gilt); stroke: var(--lead); stroke-width: 1; }
.rose .hand-pulse { fill: none; stroke: var(--gilt); stroke-width: 0.8; transform-box: fill-box; transform-origin: center; animation: ping 2.6s ease-out infinite; }
.rose .sun { mix-blend-mode: screen; pointer-events: none; }
.rose .msg { fill: var(--gilt-hi); stroke: var(--lead); stroke-width: 0.6; }
.rose .label { font-family: var(--font-display); font-size: 7.5px; fill: var(--ink); text-anchor: middle; dominant-baseline: middle; pointer-events: none; }
.rose .spin { transform-box: view-box; transform-origin: 0 0; animation: spin 240s linear infinite; }

/* the instrument ring outside the stone */
.rose .hud-ring { fill: none; stroke: var(--edge); stroke-width: 0.6; }
.rose .hud-tick { stroke: var(--muted); stroke-width: 0.6; opacity: 0.7; }
.rose .hud-dash { fill: none; stroke: var(--vest); stroke-width: 0.9; stroke-dasharray: 0.9 3.2; opacity: 0.55; transform-box: view-box; transform-origin: 0 0; animation: spin 90s linear infinite; }
.rose .hud-arcs { transform-box: view-box; transform-origin: 0 0; animation: spin-back 70s linear infinite; }
.rose .hud-arcs path { fill: none; stroke: var(--vest); stroke-width: 1.4; stroke-linecap: round; opacity: 0.7; filter: url(#rose-glow-soft); }
.rose .hud-arcs path.gilt { stroke: var(--gilt); opacity: 0.55; }
.rose .hud-num { font-family: var(--font-mono); font-size: 5.4px; font-weight: 600; letter-spacing: 0.06em; fill: var(--muted); text-anchor: middle; dominant-baseline: central; }
.rose .hud-num.major { fill: var(--gilt); }

@keyframes petal-in { from { opacity: 0; scale: 0.55; } }
@keyframes breathe { 50% { opacity: 0.66; } }
@keyframes halo { 50% { opacity: 0.35; } }
@keyframes ping { from { scale: 1; opacity: 0.9; } to { scale: 3.4; opacity: 0; } }

/* ---------- offices (sections) ---------- */

.office { padding-block: 0 clamp(4rem, 8vw, 6.5rem); }

.office-head {
  display: grid;
  grid-template-columns: 7rem minmax(0, 1fr);
  gap: 0.4rem 1.5rem;
  margin-bottom: clamp(2rem, 5vw, 3.5rem);
}
.folio {
  position: relative;
  grid-row: span 2;
  font-family: var(--font-mono);
  font-size: var(--step--1);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  padding-top: 1.2rem;
  align-self: start;
}
.folio::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: linear-gradient(90deg, var(--vest), color-mix(in oklab, var(--vest) 20%, transparent));
  box-shadow: 0 0 12px var(--glow);
  transform-origin: left;
  transition: transform 1.1s var(--ease) 0.25s;
}
.office-head.rv:not(.in) .folio::before { transform: scaleX(0); }
.office-head h2 { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.2rem 1.1rem; }
.office-head h2 .latin { font-size: var(--step-3); line-height: 0.9; }
.office-head h2 .latin::first-letter { color: var(--vest); text-shadow: 0 0 26px var(--glow), 0 0 2px var(--vest); }
.office-head h2 .vulgar { font-size: var(--step-2); color: var(--muted); }
.office-lede { grid-column: 2; max-width: var(--measure); margin-top: 0.6rem; color: color-mix(in oklab, var(--ink) 88%, var(--muted)); }

@media (max-width: 640px) {
  .office-head { grid-template-columns: minmax(0, 1fr); }
  .folio { grid-row: auto; padding-top: 0.5rem; justify-self: start; }
  .office-lede { grid-column: 1; }
}

/* ---------- arrival on scroll ---------- */

.rv { transition: opacity 0.9s var(--ease), translate 0.9s var(--ease), filter 0.9s var(--ease); transition-delay: var(--d, 0ms); }
:root[data-motion="on"] .rv:not(.in) { opacity: 0; translate: 0 28px; filter: blur(5px); }

/* ---------- rubrics ---------- */

.rubrics {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: clamp(1.5rem, 4vw, 3rem);
}
@media (max-width: 760px) { .rubrics { grid-template-columns: minmax(0, 1fr); } }

.rubric {
  position: relative;
  isolation: isolate;
  display: grid;
  grid-template-columns: 4.9rem minmax(0, 1fr);
  gap: 0.9rem;
  padding: 1.6rem 1rem 1.8rem;
}
.rubric::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: linear-gradient(90deg, color-mix(in oklab, var(--vest) 70%, transparent), var(--rule) 45%, transparent);
  transform-origin: left;
  transition: transform 1.2s var(--ease) 0.15s;
}
.rubric.rv:not(.in)::before { transform: scaleX(0); }
.rubric::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    radial-gradient(380px circle at var(--mx, 0) var(--my, 0), var(--tint), transparent 70%),
    linear-gradient(180deg, rgba(255, 255, 255, 0.02), transparent);
  opacity: 0;
  transition: opacity 0.4s ease;
}
.rubric:hover::after { opacity: 1; }
.rubric:target::after { opacity: 1; background: linear-gradient(90deg, var(--ins), transparent 75%); }
.rubric .num {
  font-family: var(--font-display);
  font-size: 2.3rem;
  line-height: 0.95;
  color: var(--vest);
  text-shadow: 0 0 18px color-mix(in oklab, var(--vest) 30%, transparent);
  transition: text-shadow 0.4s ease, translate 0.4s var(--ease);
}
.rubric:hover .num { translate: 4px 0; text-shadow: 0 0 22px var(--glow), 0 0 2px var(--vest); }
.rubric-body { display: grid; gap: 0.6rem; align-content: start; min-width: 0; padding-right: 2rem; }
.rubric h3 { font-size: var(--step-1); font-weight: 600; line-height: 1.3; color: var(--vest); }
.rubric code { white-space: normal; overflow-wrap: anywhere; }

.paid {
  font-family: var(--font-mono);
  font-size: var(--step--1);
  line-height: 1.5;
  color: var(--muted);
  border-left: 2px solid var(--gilt);
  box-shadow: -6px 0 14px -10px var(--gilt);
  padding-left: 0.7rem;
  margin-top: 0.2rem;
}
.paid span { text-transform: uppercase; letter-spacing: 0.12em; color: var(--gilt); margin-right: 0.3em; }

.pilcrow {
  position: absolute;
  top: 1.35rem;
  right: 0.6rem;
  width: 2rem;
  height: 2rem;
  display: grid;
  place-items: center;
  font: 1.1rem / 1 var(--font-voice);
  color: var(--muted);
  background: rgba(255, 255, 255, 0.02);
  border: 1px solid var(--edge);
  cursor: pointer;
  opacity: 0.6;
  transition: opacity 0.3s ease, color 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease, background-color 0.3s ease;
}
.rubric:hover .pilcrow, .beast:hover .pilcrow, .pilcrow:focus-visible { opacity: 1; }
.pilcrow:hover { color: var(--vest); background: var(--tint); border-color: var(--vest); box-shadow: 0 0 16px -4px var(--glow); }

/* ---------- the missal: the rubrics as a book ---------- */

/* liturgy.js builds this around the list of rubrics. Without the script, the list above is
   the whole of it. */
.missal {
  --rim: 9px;
  --pad-x: clamp(1.4rem, 3.2vw, 2.9rem);
  position: relative;
  overflow-x: clip;
  padding-top: 1rem;
}
.missal.single { --pad-x: 1.25rem; }
.book {
  position: relative;
  width: min(calc(100% - 2 * var(--rim) - 24px), 1060px);
  height: var(--book-h, 640px);
  margin-inline: auto;
  perspective: 2600px;
  perspective-origin: 50% 35%;
  touch-action: pan-y;
  transition: translate 1.15s var(--ease);
}
.missal:not(.open):not(.single) .book { translate: -25% 0; }
.missal.instant, .missal.instant * { transition: none !important; }

/* the spine, and the ribbon hanging out of the book */
.book::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  z-index: 3;
  width: 2px;
  translate: -1px 0;
  pointer-events: none;
  background: linear-gradient(180deg, transparent, rgba(0, 0, 0, 0.75) 6%, rgba(0, 0, 0, 0.75) 94%, transparent);
  box-shadow: 0 0 22px 8px rgba(0, 0, 0, 0.35);
  transition: opacity 0.45s ease;
}
.book::after {
  content: "";
  position: absolute;
  top: calc(100% - 18px);
  left: calc(50% + 2.2rem);
  width: 12px;
  height: 74px;
  background: linear-gradient(180deg, color-mix(in oklab, var(--vest) 50%, #000), var(--vest) 55%, color-mix(in oklab, var(--vest) 65%, #000));
  clip-path: polygon(0 0, 100% 0, 100% 100%, 50% 84%, 0 100%);
}

/* the boards, and the paper with its gilt fore-edge */
.board, .cover {
  position: absolute;
  top: calc(-1 * var(--rim));
  bottom: calc(-1 * var(--rim));
  left: 50%;
  width: calc(50% + var(--rim));
}
.board {
  z-index: 0;
  background: linear-gradient(150deg, #1c1734, #0b0915);
  border: 1px solid color-mix(in oklab, var(--gilt) 28%, transparent);
  box-shadow: 0 50px 90px -50px #000, 0 0 70px -36px var(--glow);
}
.sheet { position: absolute; top: 0; bottom: 0; z-index: 1; width: 50%; }
.sheet.left { left: 0; transition: opacity 0.45s ease; }
.sheet.right { left: 50%; }
.sheet.left, .face.l {
  background:
    linear-gradient(270deg, rgba(0, 0, 0, 0.55), rgba(0, 0, 0, 0.14) 7%, transparent 16%),
    radial-gradient(110% 90% at 40% 35%, rgba(255, 255, 255, 0.04), transparent 70%),
    repeating-linear-gradient(180deg, transparent 0 31px, rgba(196, 186, 255, 0.035) 31px 32px),
    linear-gradient(190deg, #1c1833, #110e21);
}
.sheet.right, .face.r {
  background:
    linear-gradient(90deg, rgba(0, 0, 0, 0.55), rgba(0, 0, 0, 0.14) 7%, transparent 16%),
    radial-gradient(110% 90% at 60% 35%, rgba(255, 255, 255, 0.04), transparent 70%),
    repeating-linear-gradient(180deg, transparent 0 31px, rgba(196, 186, 255, 0.035) 31px 32px),
    linear-gradient(170deg, #1c1833, #110e21);
}
.sheet::after {
  content: "";
  position: absolute;
  top: 3px;
  bottom: 3px;
  background: repeating-linear-gradient(90deg, color-mix(in oklab, var(--gilt) 50%, #15122a) 0 1px, #08070e 1px 2px);
  transition: width 0.6s ease;
}
.sheet.left::after { right: 100%; width: calc(var(--stack-l, 0) * 2px); }
.sheet.right::after { left: 100%; width: calc(var(--stack-r, 0) * 2px); }

/* pages */
.missal .rubrics { display: block; margin: 0; padding: 0; }
.missal .page {
  position: absolute;
  top: 0;
  left: 50%;
  z-index: 2;
  width: 50%;
  height: 100%;
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  padding: 3.4rem var(--pad-x) 2.2rem;
  transition: opacity 0.45s ease;
}
.missal .page.at-left { left: 0; }
.missal .page[hidden] { pointer-events: none; }
.missal .page[hidden]:not([hidden="until-found"]) { display: none !important; }
.missal .book.measuring .page { content-visibility: visible !important; height: auto !important; }
.missal .book.measuring .page[hidden] { display: flex !important; }
.missal:not(.settled) .sheet.left,
.missal:not(.settled) .book::before,
.missal:not(.settled) .page.at-left:not(.leaf .page) { opacity: 0; }

/* running heads */
.missal .rubric::before, .missal .index::before {
  content: "Rubricae";
  position: absolute;
  top: 1.4rem;
  left: var(--pad-x);
  right: var(--pad-x);
  height: auto;
  padding-bottom: 0.55rem;
  border-bottom: 1px solid var(--rule);
  background: none;
  transform: none;
  transition: none;
  font: 600 0.66rem / 1 var(--font-mono);
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--muted);
  opacity: 0.7;
}
.missal .rubric.at-right::before { content: "Code Liturgy"; text-align: right; }
.missal .index::before { content: "Index"; }

/* a rubric as a page: an illuminated numeral, the rule, and its cost as a footnote */
.missal .rubric .num {
  align-self: flex-start;
  font-size: 3.3rem;
  line-height: 0.85;
  margin-bottom: 0.3rem;
  padding: 0.45rem 0.7rem 0.55rem;
  border: 1px solid color-mix(in oklab, var(--gilt) 55%, transparent);
  outline: 1px solid color-mix(in oklab, var(--gilt) 22%, transparent);
  outline-offset: 3px;
  background: radial-gradient(circle at 50% 40%, var(--tint), transparent 75%);
}
.missal .rubric-body { flex: 1; display: flex; flex-direction: column; gap: 0.8rem; padding-right: 0; }
.missal .rubric h3 { font-size: clamp(1.3rem, 1.9vw, 1.6rem); }
.missal .paid { margin-top: auto; padding: 0.9rem 0 0; border-left: 0; border-top: 1px solid var(--rule); box-shadow: none; }
.missal .paid span { display: block; margin-bottom: 0.25rem; }
.missal .pilcrow { top: 3.4rem; right: var(--pad-x); }

.missal .index h3 { font-size: clamp(2rem, 3vw, 2.5rem); line-height: 1; }
.missal .index h3::first-letter { color: var(--vest); text-shadow: 0 0 20px var(--glow); }
.index-list { list-style: none; margin: 0; padding: 0; display: grid; }
.index-list li + li { border-top: 1px solid var(--rule); }
.index-list a {
  display: grid;
  grid-template-columns: 2.7rem minmax(0, 1fr);
  gap: 0.5rem;
  align-items: baseline;
  margin-inline: -0.5rem;
  padding: 0.32rem 0.5rem;
  font-size: 0.94rem;
  line-height: 1.35;
  text-decoration: none;
  color: color-mix(in oklab, var(--ink) 84%, var(--muted));
  transition: background-color 0.25s ease, color 0.25s ease;
}
.index-list a:hover { color: var(--ink); background: var(--tint); text-shadow: none; }
.index-list .n { font-family: var(--font-display); font-size: 1.15rem; color: var(--vest); transition: text-shadow 0.25s ease; }
.index-list a:hover .n { text-shadow: 0 0 12px var(--glow); }
.missal.single .index-list a { font-size: 0.88rem; }

.missal .finis { justify-content: center; align-items: center; gap: 1.3rem; text-align: center; }
.finis-text { font-family: var(--font-voice); font-size: var(--step-2); line-height: 1.25; max-width: 22ch; }
.missal .finis .actions { justify-content: center; }
.finis-close {
  font: 500 var(--step--1) / 1 var(--font-mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  background: none;
  border: 0;
  border-bottom: 1px dashed var(--edge);
  padding: 0.3rem 0;
  cursor: pointer;
}
.finis-close:hover { color: var(--vest); border-color: var(--vest); }

/* the cover, hinged at the spine; it lifts a little under the pointer */
.cover {
  z-index: 10;
  transform-origin: 0 50%;
  transform-style: preserve-3d;
  transition: transform 1.15s cubic-bezier(0.62, 0.04, 0.26, 1);
}
.missal.open .cover { transform: rotateY(-180deg); }
.missal.settled .cover { z-index: 0; }
.missal:not(.open) .cover:hover { transform: rotateY(-10deg); transition-duration: 0.7s; }
.cover .face, .leaf .face {
  position: absolute;
  inset: 0;
  overflow: hidden;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
}
.face.back { transform: rotateY(180deg); }
.cover .face.front {
  background:
    radial-gradient(90% 70% at 30% 18%, rgba(255, 255, 255, 0.07), transparent 60%),
    radial-gradient(70% 60% at 75% 90%, var(--tint), transparent 70%),
    linear-gradient(150deg, #201a3c, #0d0a1a 72%);
  border: 1px solid color-mix(in oklab, var(--gilt) 45%, transparent);
  box-shadow: inset 0 0 70px rgba(0, 0, 0, 0.6), inset 0 0 0 1px rgba(0, 0, 0, 0.5);
}
.endpaper {
  background:
    radial-gradient(circle at 22% 28%, color-mix(in oklab, var(--g-matutinum) 34%, transparent), transparent 38%),
    radial-gradient(circle at 76% 58%, color-mix(in oklab, var(--g-vesperae) 28%, transparent), transparent 40%),
    radial-gradient(circle at 38% 86%, color-mix(in oklab, var(--g-tertia) 24%, transparent), transparent 36%),
    radial-gradient(circle at 80% 14%, color-mix(in oklab, var(--g-prima) 18%, transparent), transparent 30%),
    repeating-radial-gradient(circle at 50% 50%, rgba(255, 255, 255, 0.03) 0 1px, transparent 1px 7px),
    #0e0b1b;
  border: 1px solid color-mix(in oklab, var(--gilt) 30%, transparent);
}
/* light on the cover as it turns: the outside darkens, the endpaper brightens as it lands */
.cover .face::after { content: ""; position: absolute; inset: 0; pointer-events: none; transition: opacity 0.6s ease 0.55s; }
.cover .face.front::after { background: linear-gradient(90deg, rgba(0, 0, 0, 0.55), rgba(0, 0, 0, 0.2)); opacity: 0; }
.cover .face.back::after { background: linear-gradient(270deg, rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.2)); opacity: 1; transition-delay: 0s; }
.missal.open .cover .face.front::after { opacity: 1; transition-delay: 0s; }
.missal.open .cover .face.back::after { opacity: 0; transition-delay: 0.55s; }

.cover-art {
  position: absolute;
  inset: 1.25rem 1.9rem 1.25rem 1.25rem;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 0.55rem;
  padding: 1.5rem 1.5rem 5.5rem;
  text-align: center;
  border: 1px solid color-mix(in oklab, var(--gilt) 50%, transparent);
  outline: 1px solid color-mix(in oklab, var(--gilt) 22%, transparent);
  outline-offset: -8px;
  background:
    radial-gradient(circle, var(--gilt) 0 2px, transparent 2.5px) left 14px top 14px / 10px 10px no-repeat,
    radial-gradient(circle, var(--gilt) 0 2px, transparent 2.5px) right 14px top 14px / 10px 10px no-repeat,
    radial-gradient(circle, var(--gilt) 0 2px, transparent 2.5px) left 14px bottom 14px / 10px 10px no-repeat,
    radial-gradient(circle, var(--gilt) 0 2px, transparent 2.5px) right 14px bottom 14px / 10px 10px no-repeat;
}
.cover-rose { width: min(8.5rem, 42%); height: auto; filter: drop-shadow(0 0 22px var(--glow)); animation: spin 140s linear infinite; }
.cover-rose .cr-rim { fill: #0a0912; stroke: color-mix(in oklab, var(--gilt) 70%, transparent); stroke-width: 2; }
.cover-rose .cr-petal { stroke: #030207; stroke-width: 2.5; stroke-linejoin: round; }
.cover-rose .cr-core { fill: var(--gilt); stroke: #030207; stroke-width: 2.5; }
.cover-kicker { margin-top: 0.6rem; font: 600 0.72rem / 1 var(--font-mono); letter-spacing: 0.42em; text-transform: uppercase; color: var(--gilt); }
.cover-title {
  font-size: clamp(3rem, 6vw, 4.4rem);
  line-height: 0.9;
  background: linear-gradient(180deg, var(--gilt-hi), var(--gilt) 55%, #8a6a1c);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  filter: drop-shadow(0 0 18px color-mix(in oklab, var(--gilt) 35%, transparent));
}
.cover-sub { font-family: var(--font-voice); font-style: italic; font-size: var(--step-1); color: var(--muted); }
.cover-open {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding: 0 0 2.4rem;
  color: inherit;
  background: none;
  border: 0;
  cursor: pointer;
}
.cover-open span {
  font: 600 var(--step--1) / 1 var(--font-mono);
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--ink);
  padding: 0.7rem 1.2rem 0.7rem 1.45rem;
  background: var(--tint);
  border: 1px solid color-mix(in oklab, var(--vest) 70%, transparent);
  box-shadow: 0 0 24px -6px var(--glow);
  transition: border-color 0.3s ease;
  animation: beckon 2.8s ease-in-out infinite;
}
.cover-open:hover span { border-color: var(--vest); }
.cover-open:focus-visible { outline: 2px solid var(--vest); outline-offset: -8px; }
@keyframes beckon { 50% { box-shadow: 0 0 34px -2px var(--glow); } }
.clasp {
  position: absolute;
  z-index: 2;
  top: 50%;
  right: 0;
  width: 20px;
  height: 72px;
  translate: 0 -50%;
  pointer-events: none;
  background: linear-gradient(90deg, #5a4614, var(--gilt) 45%, #7a5d18);
  border-radius: 4px 0 0 4px;
  box-shadow: -3px 0 10px rgba(0, 0, 0, 0.5), 0 0 16px -4px var(--gilt);
}
.clasp::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 5px;
  width: 8px;
  height: 8px;
  translate: 0 -50%;
  border-radius: 50%;
  background: var(--vest);
  box-shadow: 0 0 8px var(--vest);
}

/* turning leaves */
.leaf { position: absolute; top: 0; z-index: 30; width: 50%; height: 100%; transform-style: preserve-3d; pointer-events: none; }
.leaf.fwd { left: 50%; transform-origin: 0 50%; }
.leaf.bwd { left: 0; transform-origin: 100% 50%; }
.leaf .face { box-shadow: inset 0 0 0 1px rgba(196, 186, 255, 0.06), 0 0 40px -16px var(--glow); }
.missal .leaf .face > .page { left: 0; width: 100%; height: 100%; }
.shade { position: absolute; inset: 0; z-index: 3; pointer-events: none; opacity: 0; }
.face.r .shade { background: linear-gradient(90deg, rgba(0, 0, 0, 0.75), rgba(0, 0, 0, 0.3)); }
.face.l .shade { background: linear-gradient(270deg, rgba(0, 0, 0, 0.75), rgba(0, 0, 0, 0.3)); }
.cast { position: absolute; inset: 0; z-index: 4; pointer-events: none; opacity: 0; background: radial-gradient(30% 60% at 50% 50%, rgba(0, 0, 0, 0.5), transparent 70%); }

/* a page corner that curls under the pointer */
.corner { position: absolute; bottom: 0; z-index: 6; width: 4.5rem; height: 4.5rem; padding: 0; background: none; border: 0; cursor: pointer; }
.corner.prev { left: 0; }
.corner.next { right: 0; }
.corner::before { content: ""; position: absolute; bottom: 0; width: 0.9rem; height: 0.9rem; transition: width 0.35s var(--ease), height 0.35s var(--ease); }
.corner.prev::before { left: 0; background: linear-gradient(to top right, var(--bg) 50%, #2e2850 50%, #1b1731 80%); box-shadow: 6px -6px 14px -4px rgba(0, 0, 0, 0.6); }
.corner.next::before { right: 0; background: linear-gradient(to top left, var(--bg) 50%, #2e2850 50%, #1b1731 80%); box-shadow: -6px -6px 14px -4px rgba(0, 0, 0, 0.6); }
.corner:hover::before { width: 2.8rem; height: 2.8rem; }
.missal:not(.settled) .corner { display: none; }

/* one page at a time on a narrow screen */
.missal.single .book { width: calc(100% - var(--rim) - 12px); margin-inline: 0 auto; perspective: 1600px; }
.missal.single .book::before, .missal.single .sheet.left { display: none; }
.missal.single .book::after { left: 1.4rem; }
.missal.single .board, .missal.single .cover { left: 0; width: calc(100% + var(--rim)); }
.missal.single .sheet.right, .missal.single .page, .missal.single .leaf { left: 0; width: 100%; }
.missal.single .leaf { transform-origin: 0 50%; }
.missal.single .page { padding: 3.2rem var(--pad-x) 1.6rem; }
.missal.single.settled .cover { visibility: hidden; }
.missal.single .cast { background: linear-gradient(90deg, rgba(0, 0, 0, 0.55), transparent 45%); }

/* the ribbon of pages */
.missal-nav { display: flex; align-items: center; justify-content: center; gap: 0.6rem; margin-top: 4.4rem; }
.turn {
  flex: none;
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  font: 1.5rem / 1 var(--font-voice);
  color: var(--ink);
  background: rgba(255, 255, 255, 0.025);
  border: 1px solid var(--edge);
  cursor: pointer;
  transition: color 0.25s ease, border-color 0.25s ease, box-shadow 0.25s ease, opacity 0.25s ease;
}
.turn:hover:not(:disabled) { color: var(--vest); border-color: var(--vest); box-shadow: 0 0 20px -6px var(--glow); }
.turn:disabled { opacity: 0.3; cursor: default; }
.ribbon { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; justify-content: center; gap: 0.2rem; }
.ribbon button {
  min-width: 2.2rem;
  height: 2.2rem;
  padding: 0 0.45rem;
  font: 1.05rem / 1 var(--font-display);
  color: var(--muted);
  background: none;
  border: 1px solid transparent;
  cursor: pointer;
  transition: color 0.25s ease, border-color 0.25s ease, background-color 0.25s ease;
}
.ribbon button.to-index { font: 600 0.7rem / 1 var(--font-mono); letter-spacing: 0.14em; text-transform: uppercase; }
.ribbon button:hover { color: var(--ink); border-color: var(--edge); }
.ribbon button[aria-current] { color: var(--vest); background: var(--tint); border-color: color-mix(in oklab, var(--vest) 60%, transparent); text-shadow: 0 0 10px var(--glow); }
.missal-foot { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.4rem 1.5rem; margin-top: 0.9rem; font-family: var(--font-mono); font-size: var(--step--1); color: var(--muted); }
.folio-count { letter-spacing: 0.1em; color: var(--ink); }
@media (max-width: 760px) {
  .missal-nav { flex-wrap: wrap; }
  .ribbon { order: 3; flex-basis: 100%; }
}

.sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* ---------- hours ---------- */

.hours {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 2.5rem clamp(1.25rem, 3vw, 2.25rem);
}
@media (max-width: 1000px) { .hours { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 540px) { .hours { grid-template-columns: minmax(0, 1fr); } }

.hora { display: grid; gap: 0.5rem; align-content: start; min-width: 0; position: relative; container-type: inline-size; }
.hora .lancet { width: 100%; max-width: 9.5rem; aspect-ratio: 100 / 150; height: auto; overflow: visible; margin-bottom: 0.4rem; }
.l-glass { fill: var(--glass); opacity: 0.5; }
.l-light { fill: var(--glass); }
.l-gem { fill: var(--gilt); }
.l-lead { fill: none; stroke: var(--lead); stroke-width: 3.2; stroke-linejoin: round; }
.shine-a { stop-color: var(--shine); stop-opacity: 1; }
.shine-b { stop-color: var(--shine); stop-opacity: 0; }

/* a sheen that crosses each window in turn, and the pool of coloured light it casts */
.hora::before {
  content: "";
  position: absolute;
  z-index: 1;
  top: 0;
  left: 0;
  width: min(100cqw, 9.5rem);
  aspect-ratio: 100 / 150;
  pointer-events: none;
  background: linear-gradient(105deg, transparent 38%, rgba(255, 255, 255, 0.4) 50%, transparent 62%) no-repeat;
  background-size: 300% 100%;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 150'%3E%3Cpath d='M6 150V64Q6 18 50 3Q94 18 94 64V150Z'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 150'%3E%3Cpath d='M6 150V64Q6 18 50 3Q94 18 94 64V150Z'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
  mix-blend-mode: overlay;
  animation: sheen 8s ease-in-out infinite;
  animation-delay: calc(var(--i, 0) * 0.55s);
  transition: translate 0.5s var(--ease);
}
.hora::after {
  content: "";
  position: absolute;
  z-index: -1;
  top: calc(min(100cqw, 9.5rem) * 1.5 - 1.4rem);
  left: -1.5rem;
  width: calc(min(100cqw, 9.5rem) + 3rem);
  height: 3rem;
  pointer-events: none;
  background: radial-gradient(closest-side, color-mix(in oklab, var(--glass) 60%, transparent), transparent);
  filter: blur(4px);
  opacity: 0.3;
  transition: opacity 0.6s ease;
}
@keyframes sheen {
  0%, 55% { background-position: 120% 0; }
  100% { background-position: -40% 0; }
}

.hora-time { font-family: var(--font-mono); font-size: var(--step--1); color: var(--muted); letter-spacing: 0.06em; }
.hora h3 { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 0.6rem; }
.hora h3 .latin { font-size: 2rem; line-height: 1; transition: color 0.3s ease, text-shadow 0.3s ease; }
.hora h3 .vulgar { font-size: var(--step-1); color: var(--muted); }
.hora-rite { font-weight: 600; color: var(--vest); }
.hora p:last-child { color: color-mix(in oklab, var(--ink) 88%, var(--muted)); }

.hora .lancet { transition: filter 0.5s ease, translate 0.5s var(--ease); filter: saturate(0.6) brightness(0.9) drop-shadow(0 0 10px color-mix(in oklab, var(--glass) 25%, transparent)); }
.hora:hover .lancet, .hora:hover::before { translate: 0 -5px; }
.hora:hover .lancet { filter: saturate(1) brightness(1.05) drop-shadow(0 0 16px color-mix(in oklab, var(--glass) 55%, transparent)); }
.hora:hover::after { opacity: 0.6; }
.hora:hover h3 .latin { text-shadow: 0 0 18px color-mix(in oklab, var(--glass) 60%, transparent); }
.hora.is-now .lancet { filter: saturate(1.15) drop-shadow(0 0 18px var(--glass)); animation: lit 4s ease-in-out infinite; }
.hora.is-now::after { opacity: 0.95; animation: pool 4s ease-in-out infinite; }
.hora.is-now .hora-time::after {
  content: "nunc";
  margin-left: 0.6rem;
  padding: 0.1rem 0.5rem;
  color: var(--vest);
  background: var(--tint);
  border: 1px solid color-mix(in oklab, var(--vest) 70%, transparent);
  box-shadow: 0 0 14px -4px var(--glow);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.14em;
}
.hours:not(.reading) .hora:target h3 .latin { color: var(--vest); }
@keyframes lit { 50% { filter: saturate(1.25) brightness(1.08) drop-shadow(0 0 26px var(--glass)); } }
@keyframes pool { 50% { opacity: 0.6; } }

/* liturgy.js sets the hours in a compartment of the box: the windows stand in a row at the
   back, each on its sill, with a slip of dark paper tucked under each sill. The chosen hour's
   slip is lifted out of the box into the reading view, in front of it, and a shaft of its glass
   falls on it. Without the script, the list above is all there is. --x is the middle of the
   chosen window, --px the same point on the paper, --lit its glass. */
@property --x { syntax: "<length>"; inherits: true; initial-value: 0px; }
@property --px { syntax: "<length>"; inherits: true; initial-value: 0px; }
@property --lit { syntax: "<color>"; inherits: true; initial-value: transparent; }

.horae-stage {
  /* the box as seen from the front: the face of its dividers, and the depth of its walls */
  --rail: clamp(7px, 1.1vw, 14px);
  --wall: clamp(9px, 2.1vw, 28px);
  --ceil: clamp(12px, 2.6vw, 34px);
  --floor: clamp(16px, 3.4vw, 44px);
  position: relative;
  transition: --x 0.75s var(--ease), --px 0.75s var(--ease), --lit 0.75s ease;
}

.compartment {
  position: relative;
  padding: var(--rail);
  background:
    linear-gradient(180deg, rgba(203, 184, 143, 0.07), transparent 2px),
    linear-gradient(100deg, var(--box-face), var(--box-face-lo) 55%, var(--box-face));
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.85), 0 50px 90px -50px #000;
}
/* the engraved label on the lintel */
.compartment .label {
  position: absolute;
  z-index: 3;
  top: calc(var(--rail) / 2);
  left: 50%;
  translate: -50% -50%;
  padding: 0.2rem 0.8rem 0.1rem;
  font: 400 1rem / 1 var(--font-display);
  letter-spacing: 0.04em;
  color: var(--sepia-2);
  background: linear-gradient(180deg, #17130f, #0d0b09);
  border: 1px solid rgba(203, 184, 143, 0.2);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.7), inset 0 1px 0 rgba(203, 184, 143, 0.08);
  text-shadow: 0 -1px 0 #000, 0 1px 0 rgba(203, 184, 143, 0.12);
}

/* the inside: the back wall, lined with dark paper, and the four walls in perspective */
.recess {
  position: relative;
  padding: var(--ceil) var(--wall) var(--floor);
  background:
    radial-gradient(60% 70% at 50% 45%, color-mix(in oklab, var(--lit) 7%, transparent), transparent),
    url("paper.png") 0 0 / 128px,
    radial-gradient(120% 90% at 50% 40%, var(--box), #050404);
  box-shadow: inset 0 0 0 1px #000;
}
.recess::before, .recess::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
}
/* the ceiling and the floor, joined along the left edge where they have no width */
.recess::before {
  background:
    linear-gradient(180deg, #030202, #0b0907) top / 100% var(--ceil) no-repeat,
    linear-gradient(180deg, color-mix(in oklab, var(--lit) 12%, #1c1611), #0e0b09) bottom / 100% var(--floor) no-repeat;
  clip-path: polygon(0 0, 100% 0, calc(100% - var(--wall)) var(--ceil), var(--wall) var(--ceil), 0 0, 0 100%, var(--wall) calc(100% - var(--floor)), calc(100% - var(--wall)) calc(100% - var(--floor)), 100% 100%, 0 100%);
}
/* the side walls, joined along the bottom edge */
.recess::after {
  background:
    linear-gradient(90deg, #17120e, #0b0908) left / var(--wall) 100% no-repeat,
    linear-gradient(270deg, #17120e, #0b0908) right / var(--wall) 100% no-repeat;
  clip-path: polygon(0 0, var(--wall) var(--ceil), var(--wall) calc(100% - var(--floor)), 0 100%, 100% 100%, calc(100% - var(--wall)) calc(100% - var(--floor)), calc(100% - var(--wall)) var(--ceil), 100% 0);
}

.arcade {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: repeat(8, minmax(0, 1fr));
  gap: clamp(0.3rem, 1.4vw, 1.25rem);
  container-type: inline-size;
}
.lancet-tab {
  position: relative;
  display: grid;
  justify-items: center;
  align-content: start;
  min-width: 0;
  padding: 1.4rem 0 0.2rem;
  font: inherit;
  color: var(--muted);
  background: none;
  border: 0;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.compartment.rv.in .lancet-tab { animation: rise 0.9s var(--ease) backwards; animation-delay: calc(0.1s + var(--i, 0) * 0.07s); }
.lancet-tab .pane { position: relative; z-index: 2; display: block; width: min(100%, 4.75rem); }
.lancet-tab .lancet {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 60 / 168;
  overflow: visible;
  filter: saturate(0.55) brightness(0.62) drop-shadow(0 0 8px color-mix(in oklab, var(--glass) 15%, transparent));
  transition: filter 0.5s ease;
}
/* the sheen crosses each window in turn */
.lancet-tab .pane::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(105deg, transparent 38%, rgba(255, 255, 255, 0.4) 50%, transparent 62%) no-repeat;
  background-size: 300% 100%;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 60 168'%3E%3Cpath d='M4 168V48Q4 12 30 2Q56 12 56 48V168Z'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 60 168'%3E%3Cpath d='M4 168V48Q4 12 30 2Q56 12 56 48V168Z'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
  mix-blend-mode: overlay;
  animation: sheen 8s ease-in-out infinite;
  animation-delay: calc(var(--i, 0) * 0.55s);
}
.l-quarry { fill: color-mix(in oklab, var(--glass) 55%, var(--gilt-hi)); opacity: 0.75; }
.l-lead.thin { stroke-width: 2.4; }
.lancet-tab .l-gem { fill: var(--gem, var(--gilt)); }

/* the sill each window stands on */
.sill {
  position: relative;
  z-index: 1;
  display: block;
  width: calc(min(100%, 4.75rem) + 0.6rem);
  max-width: calc(100% + 0.3rem);
  height: 0.45rem;
  background: linear-gradient(180deg, #3a3024, #1a1510 45%, #0c0a08);
  box-shadow: 0 3px 5px rgba(0, 0, 0, 0.8);
}

/* the slip tucked under it, with its hour written on it */
.slip {
  position: relative;
  z-index: 0;
  display: grid;
  justify-items: center;
  gap: 0.3rem;
  width: min(90%, 6.6rem);
  margin-top: -0.3rem;
  padding: 0.75rem 0.15rem 0.55rem;
  rotate: var(--tilt, 0deg);
  transform-origin: 50% 0;
  background:
    url("paper.png") 0 0 / 128px,
    radial-gradient(1.4rem 1rem at 78% 72%, rgba(120, 86, 44, 0.16), transparent),
    linear-gradient(175deg, var(--stock-hi), var(--stock-lo));
  box-shadow: 0 4px 7px -2px rgba(0, 0, 0, 0.85), inset 0 0 0 1px rgba(203, 184, 143, 0.06);
  transition: translate 0.4s var(--ease), background-color 0.3s ease;
}
.tab-name { font: 400 1.15rem / 1 var(--font-display); color: var(--sepia); white-space: nowrap; transition: color 0.3s ease; }
.tab-time { font: 0.64rem / 1 var(--font-mono); letter-spacing: 0.04em; color: var(--sepia-2); }
.nunc {
  position: absolute;
  top: 0.2rem;
  font: 600 0.6rem / 1 var(--font-mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gilt);
  text-shadow: 0 0 10px color-mix(in oklab, var(--gilt) 60%, transparent);
  opacity: 0;
  transition: opacity 0.4s ease;
}

.lancet-tab:hover .lancet { filter: saturate(0.85) brightness(0.85) drop-shadow(0 0 12px color-mix(in oklab, var(--glass) 35%, transparent)); }
/* under the pointer the slip is drawn out a little, as if to be taken */
.lancet-tab:hover .slip { translate: 0 0.3rem; }
.lancet-tab:hover .tab-name { color: var(--vest); }
.lancet-tab.now { --gem: var(--gilt-hi); }
.lancet-tab.now .nunc { opacity: 1; animation: breathe 3s ease-in-out infinite; }
.lancet-tab.now .tab-time { color: var(--gilt); }
.lancet-tab[aria-selected="true"] .lancet { filter: saturate(1.15) brightness(1.05) drop-shadow(0 0 18px var(--glass)); animation: lit 4s ease-in-out infinite; }
/* the lifted slip leaves its place under the sill, a little darker where it lay */
.lancet-tab[aria-selected="true"] .slip { background: rgba(0, 0, 0, 0.3); box-shadow: inset 0 0 0 1px rgba(203, 184, 143, 0.07); translate: none; }
.lancet-tab[aria-selected="true"] .slip > * { visibility: hidden; }
.lancet-tab:focus-visible { outline-offset: 0; }

/* the shaft of light from the chosen window down to the lifted slip */
.beam {
  position: absolute;
  left: 0;
  z-index: 1;
  width: calc(var(--lw, 4rem) * 2.6);
  translate: calc(var(--x) - 50%) 0;
  pointer-events: none;
  background: linear-gradient(180deg, color-mix(in oklab, var(--lit) 50%, transparent), color-mix(in oklab, var(--lit) 18%, transparent) 80%, color-mix(in oklab, var(--lit) 10%, transparent));
  clip-path: polygon(31% 0, 69% 0, 100% 100%, 0 100%);
  mix-blend-mode: screen;
  filter: blur(5px);
  opacity: 0.6;
}

/* the reading view: the slip held out in front of the box, over the lower rail */
.hora-paper {
  position: relative;
  z-index: 2;
  margin: calc(-1 * var(--rail) + 3px) calc(var(--rail) + var(--wall) - 0.5rem) 0;
}
.paper {
  rotate: var(--tilt, 0deg);
  filter: drop-shadow(0 12px 26px rgba(0, 0, 0, 0.85)) drop-shadow(0 2px 3px rgba(0, 0, 0, 0.7));
}
/* Dark stock with its grain, a little foxing and green light, the pool of the
   chosen glass at the top, a hand-cut top edge and a torn foot. The inks are measured against
   the stock, light included. */
.paper-sheet {
  --ink: var(--sepia);
  --muted: var(--sepia-2);
  --rule: rgba(203, 184, 143, 0.16);
  --edge: rgba(203, 184, 143, 0.24);
  position: relative;
  padding: clamp(1.6rem, 3.5vw, 2.5rem) clamp(1.1rem, 4vw, 3rem) 1.6rem;
  color: var(--ink);
  background:
    var(--tear-rim) left bottom / 200px 14px repeat-x,
    url("paper.png") 0 0 / 128px,
    radial-gradient(26rem 9rem at var(--px) 0, color-mix(in oklab, var(--lit) 8%, transparent), transparent 75%),
    radial-gradient(3rem 2.2rem at 91% 78%, rgba(120, 86, 44, 0.14), transparent),
    radial-gradient(2rem 1.6rem at 6% 22%, rgba(120, 86, 44, 0.12), transparent),
    radial-gradient(5rem 3rem at 64% 96%, rgba(120, 86, 44, 0.1), transparent),
    radial-gradient(45% 70% at 0% 100%, color-mix(in oklab, var(--vest) 4%, transparent), transparent),
    linear-gradient(172deg, var(--stock-hi), var(--stock) 45%, var(--stock-lo));
  -webkit-mask:
    linear-gradient(#000 0 0) top / 100% calc(100% - 13px) no-repeat,
    var(--tear) left bottom / 200px 14px repeat-x;
  mask:
    linear-gradient(#000 0 0) top / 100% calc(100% - 13px) no-repeat,
    var(--tear) left bottom / 200px 14px repeat-x;
  clip-path: polygon(0 2px, 38% 0, 71% 1px, 100% 3px, calc(100% - 1px) 100%, 1px 100%);
  container-type: inline-size;
}
/* where the light falls, the paper's top edge catches it */
.paper-sheet::after {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 2px;
  pointer-events: none;
  background: linear-gradient(90deg, transparent calc(var(--px) - 8rem), color-mix(in oklab, var(--lit) 70%, transparent) var(--px), transparent calc(var(--px) + 8rem));
}

.hours.reading { display: block; }
.hours.reading .hora {
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.5fr);
  grid-template-rows: auto auto 1fr;
  grid-template-areas: "time rite" "name rite" "name body";
  gap: 0.6rem clamp(1.5rem, 5cqw, 4rem);
  min-height: var(--hora-h, 0px);
  scroll-margin-top: var(--lift, 0px);
  container-type: normal;
}
.hours.reading .hora::before, .hours.reading .hora::after, .hours.reading .hora > .lancet { display: none; }
.hours.reading .hora[hidden] { min-height: 0; gap: 0; }
.hours.reading .hora[hidden]:not([hidden="until-found"]) { display: none !important; }
.hours.reading .hora-time { grid-area: time; }
.hours.reading .hora h3 { grid-area: name; flex-direction: column; align-items: flex-start; gap: 0.35rem; }
.hours.reading .hora h3 .latin { font-size: clamp(2.6rem, 6cqw, 3.6rem); text-shadow: 0 0 1px color-mix(in oklab, var(--ink) 40%, transparent); }
.hours.reading .hora h3 .latin::first-letter { color: var(--vest); }
.hours.reading .hora-rite { grid-area: rite; align-self: end; font: 400 var(--step-2) / 1.25 var(--font-voice); color: var(--ink); text-wrap: balance; }
.hours.reading .hora-rite::before { content: "℟. "; color: var(--vest); }
.hours.reading .hora p:last-child { grid-area: body; max-width: 60ch; font: 400 1.22rem / 1.5 var(--font-voice); color: var(--ink); }
.hours.reading .hora code { color: var(--ink); background: rgba(0, 0, 0, 0.28); }
.hours.reading .hora.is-now .hora-time::after { background: none; box-shadow: none; }
.paper-sheet.measuring .hora { min-height: 0 !important; }

.hora-nav { display: flex; justify-content: space-between; gap: 1rem; margin-top: 1.4rem; padding-top: 0.6rem; border-top: 1px solid var(--rule); }

@container (max-width: 63rem) {
  .tab-name .rest { display: none; }
}
@container (max-width: 30rem) {
  .tab-name { font-size: 1rem; }
  .tab-time { font-size: 0.56rem; letter-spacing: 0; }
  .slip { padding-inline: 0; gap: 0.25rem; }
}
@container (max-width: 40rem) {
  .hours.reading .hora { grid-template-columns: minmax(0, 1fr); grid-template-rows: none; grid-template-areas: "time" "name" "rite" "body"; }
  .hours.reading .hora h3 { flex-direction: row; flex-wrap: wrap; align-items: baseline; gap: 0 0.7rem; }
  .hours.reading .hora-rite { align-self: start; }
}
/* on a phone the lifted slip takes the whole width */
@media (max-width: 540px) {
  .hora-paper { margin-inline: 0; }
}

/* ---------- bestiary ---------- */

.beasts {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(1.25rem, 3vw, 2rem);
}
@media (max-width: 860px) { .beasts { grid-template-columns: minmax(0, 1fr); } }

.beast {
  display: grid;
  grid-template-columns: 6.5rem minmax(0, 1fr);
  gap: 1.25rem;
  padding: 1.4rem 1.4rem 1.5rem;
  transition: translate 0.45s var(--ease), box-shadow 0.45s ease, border-color 0.45s ease;
}
.beast, .beast-recto, .beast-verso {
  background:
    radial-gradient(520px circle at var(--mx, 50%) var(--my, -40%), var(--tint), transparent 62%),
    linear-gradient(160deg, var(--panel-hi), var(--panel) 62%);
}
/* the edge lights up where the pointer is */
.beast::after, .beast-recto::after, .beast-verso::after {
  content: "";
  position: absolute;
  inset: -1px;
  padding: 1px;
  pointer-events: none;
  background: radial-gradient(240px circle at var(--mx, 50%) var(--my, -40%), var(--vest), transparent 70%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
  opacity: 0;
  transition: opacity 0.4s ease;
}
.beast:hover { translate: 0 -3px; box-shadow: 8px 8px 0 -1px color-mix(in oklab, var(--vest) 22%, transparent), 0 34px 70px -36px rgba(0, 0, 0, 0.95), 0 0 40px -22px var(--glow); }
.beast:hover::after { opacity: 1; }
.beast:hover::before { --k: 22px; opacity: 1; }
.beast:target { outline: 2px solid var(--vest); outline-offset: 5px; }
.sigil { width: 6.5rem; height: 6.5rem; display: block; transition: rotate 2.4s var(--ease), filter 0.6s ease; }
.beast:hover .sigil { rotate: 36deg; filter: drop-shadow(0 0 10px var(--glow)); }
.beast-body { display: grid; gap: 0.25rem; align-content: start; min-width: 0; padding-right: 1.6rem; }
.beast h3 { font-family: var(--font-display); font-weight: 400; font-size: 2.05rem; line-height: 1; }
.binomial { font-family: var(--font-voice); font-style: italic; font-size: var(--step-1); color: var(--vest); margin-bottom: 0.6rem; }
.beast dl { margin: 0; display: grid; grid-template-columns: 5.4rem minmax(0, 1fr); gap: 0.45rem 0.9rem; font-size: 0.97rem; line-height: 1.5; }
.beast dt { font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); padding-top: 0.2rem; }
.beast dd { margin: 0; min-width: 0; color: color-mix(in oklab, var(--ink) 90%, var(--muted)); }
.beast dd code { white-space: normal; overflow-wrap: anywhere; }
.beast dt:nth-of-type(3) + dd { font-weight: 500; color: var(--ink); }
.beast .pilcrow { top: 1.2rem; right: 1.2rem; }

@media (max-width: 520px) {
  .beast { grid-template-columns: minmax(0, 1fr); }
  .sigil { width: 5rem; height: 5rem; }
  .beast dl { grid-template-columns: minmax(0, 1fr); gap: 0.1rem; }
  .beast dd { margin-bottom: 0.45rem; }
}

/* liturgy.js turns each plate into a card: the sigil, the name and the binomial on the recto,
   the habitat, signs, ward and sighting on the verso. Without the script, each plate shows
   everything at once. The glass moves from the plate to the two sides of the card. */
.beast.card {
  grid-template-columns: minmax(0, 1fr);
  padding: 0;
  background: none;
  border: 0;
  box-shadow: none;
  perspective: 1800px;
  cursor: pointer;
}
.beast.card::before, .beast.card::after { content: none; }
.beast.card:hover { box-shadow: none; }
.beast-leaf {
  position: relative;
  display: grid;
  min-height: var(--face-h, 0px);
  transform-style: preserve-3d;
  transition: transform 0.85s cubic-bezier(0.62, 0.04, 0.26, 1);
}
.beast-recto, .beast-verso {
  grid-area: 1 / 1;
  min-width: 0;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
  transition: box-shadow 0.45s ease;
}
.beast-verso { transform: rotateY(180deg); }
.beast-verso[hidden]:not([hidden="until-found"]) { display: none !important; }
.beast.turned .beast-leaf { transform: rotateY(-180deg); }
/* the card rises a little as it turns */
.beast.turning .beast-leaf { animation: card-lift 0.85s cubic-bezier(0.62, 0.04, 0.26, 1); }
@keyframes card-lift { 50% { translate: 0 -0.5rem 3rem; } }
.beast.card:hover .beast-recto, .beast.card:hover .beast-verso { box-shadow: 8px 8px 0 -1px color-mix(in oklab, var(--vest) 22%, transparent), 0 34px 70px -36px rgba(0, 0, 0, 0.95), 0 0 40px -22px var(--glow); }
.beast.card:hover .beast-recto::after, .beast.card:hover .beast-verso::after { opacity: 1; }
.beast.card:hover .beast-recto::before, .beast.card:hover .beast-verso::before { --k: 22px; opacity: 1; }
/* under the pointer the card lifts at its edge, as if about to be turned */
@media (hover: hover) and (pointer: fine) {
  :root[data-motion="on"] .beast.card:hover .beast-leaf { transform: rotateY(-7deg); }
  :root[data-motion="on"] .beast.card.turned:hover .beast-leaf { transform: rotateY(-173deg); }
}

.beast-recto {
  display: grid;
  justify-items: center;
  align-content: center;
  gap: 0.3rem;
  padding: 2rem 1.5rem 3.6rem;
  text-align: center;
}
.beast-recto .sigil { width: 8.5rem; height: 8.5rem; margin-bottom: 1rem; }
.beast-recto h3 { font-size: 2.45rem; }
.beast-recto .binomial { margin: 0; }

.beast-verso {
  display: grid;
  align-content: start;
  gap: 1.1rem;
  padding: 1.2rem 1.4rem 3.6rem;
}
.beast-head {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  padding: 0 2.8rem 0.9rem 0;
  border-bottom: 1px solid var(--rule);
  font: 400 1.55rem / 1 var(--font-display);
}
.sigil.seal { width: 3rem; height: 3rem; flex: none; }
.beast-verso dl { cursor: auto; }

.beast.card .pilcrow { z-index: 3; }
.verte {
  position: absolute;
  right: 1.2rem;
  bottom: 1.1rem;
  z-index: 3;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.4rem 0.75rem;
  font: 600 0.72rem / 1 var(--font-mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
  background: rgba(255, 255, 255, 0.02);
  border: 1px solid var(--edge);
  cursor: pointer;
  transition: opacity 0.3s ease, color 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease, background-color 0.3s ease;
}
.verte-turn { font-size: 0.95rem; letter-spacing: 0; transition: scale 0.85s var(--ease); }
.beast.turned .verte-turn { scale: -1 1; }
.beast.card:hover .verte, .verte:focus-visible { color: var(--vest); border-color: color-mix(in oklab, var(--vest) 55%, transparent); }
.verte:hover { background: var(--tint); border-color: var(--vest); box-shadow: 0 0 16px -4px var(--glow); }
/* the buttons stand off the card while it turns */
.beast.turning .pilcrow, .beast.turning .verte { opacity: 0; }

/* each card is as tall as the longer of its two sides */
.beasts.measuring .beast-leaf { min-height: 0 !important; }
.beasts.measuring .beast-recto, .beasts.measuring .beast-verso { align-self: start; }
.beasts.measuring .beast-verso[hidden] { content-visibility: visible !important; display: grid !important; }

@media (max-width: 520px) {
  .beast-recto { padding-inline: 1.1rem; }
  .beast-recto .sigil { width: 7rem; height: 7rem; }
  .beast-recto h3 { font-size: 2.1rem; }
  .beast-verso { padding-inline: 1.1rem; }
}

/* ---------- credo ---------- */

.credo-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.08fr);
  gap: clamp(2rem, 5vw, 4rem);
  align-items: start;
}
@media (max-width: 960px) { .credo-grid { grid-template-columns: minmax(0, 1fr); } }

.creed { display: grid; gap: 1.2rem; min-width: 0; }
.creed-open { font-family: var(--font-voice); font-size: var(--step-2); line-height: 1.25; }
.creed-lines { margin: 0; padding: 0; list-style: none; display: grid; gap: 0.75rem; counter-reset: creed; }
.creed-lines li {
  font-family: var(--font-voice);
  font-size: 1.32rem;
  line-height: 1.38;
  padding-left: 2.9rem;
  position: relative;
  counter-increment: creed;
}
.creed-lines li::before {
  content: counter(creed, upper-roman);
  position: absolute;
  left: 0;
  top: 0.1rem;
  font-family: var(--font-display);
  font-size: 1.2rem;
  color: var(--vest);
  text-shadow: 0 0 12px var(--glow);
  transition: translate 0.4s var(--ease);
}
.creed-lines li:hover::before { translate: 4px 0; }
.creed-lines code { font-size: 0.72em; white-space: normal; }
.codes {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.08em;
  color: var(--gilt);
  background: color-mix(in oklab, var(--gilt) 8%, transparent);
  border: 1px solid color-mix(in oklab, var(--gilt) 60%, transparent);
  box-shadow: 0 0 12px -4px color-mix(in oklab, var(--gilt) 60%, transparent);
  padding: 0 0.4rem;
  vertical-align: 0.2em;
  white-space: nowrap;
}

/* liturgy.js says the creed line by line: the line nearest the middle of the screen is lit,
   the ones already said stay half lit, and the rest wait in the dark. Only the light changes. */
.creed.reciting .creed-lines { gap: 1.6rem; }
.creed.reciting > .creed-open, .creed.reciting .creed-lines > li { opacity: 0.3; transition: opacity 0.6s ease; }
.creed.reciting .creed-lines > li { isolation: isolate; }
.creed.reciting > .said, .creed.reciting .creed-lines > .said { opacity: 0.58; }
.creed.reciting > .saying, .creed.reciting .creed-lines > .saying { opacity: 1; }
.creed.reciting .creed-lines > li::after {
  content: "";
  position: absolute;
  z-index: -1;
  inset: -0.45rem -0.6rem -0.45rem -0.9rem;
  pointer-events: none;
  background: linear-gradient(90deg, var(--tint), transparent 75%);
  border-left: 2px solid var(--vest);
  box-shadow: -10px 0 18px -12px var(--glow);
  opacity: 0;
  transition: opacity 0.6s ease;
}
.creed.reciting .creed-lines > li.saying::after { opacity: 1; }
.creed.reciting .creed-lines > li::before { transition: translate 0.4s var(--ease), text-shadow 0.6s ease; }
.creed.reciting .creed-lines > li.saying::before { text-shadow: 0 0 16px var(--vest), 0 0 2px var(--vest); }
.creed.reciting .saying .codes { box-shadow: 0 0 18px -2px color-mix(in oklab, var(--gilt) 70%, transparent); }
/* the probatio stays in view while the creed is said beside it */
@media (min-width: 961px) and (min-height: 820px) {
  .creed.reciting ~ .probatio { position: sticky; top: calc(env(safe-area-inset-top, 0px) + 5rem); }
}

.confiteor { position: relative; padding-top: 1rem; display: grid; gap: 0.4rem; max-width: var(--measure); }
.confiteor::before { content: ""; position: absolute; inset: 0 0 auto; height: 1px; background: linear-gradient(90deg, var(--vest), var(--edge) 40%, transparent); }
.confiteor h3 { font-family: var(--font-display); font-weight: 400; font-size: 1.9rem; line-height: 1; color: var(--vest); text-shadow: 0 0 18px var(--glow); }

.probatio { display: grid; gap: 0.9rem; min-width: 0; }
.probatio > h3 { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 0.8rem; }
.probatio > h3 .latin { font-size: 2.3rem; line-height: 1; }
.probatio > h3 .vulgar { font-size: var(--step-1); color: var(--muted); }
.probatio-controls {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  padding: 0.3rem;
  width: fit-content;
  max-width: 100%;
  background: rgba(255, 255, 255, 0.02);
  border: 1px solid var(--edge);
}

.chip {
  font: 500 var(--step--1) / 1.2 var(--font-mono);
  color: var(--muted);
  background: transparent;
  border: 1px solid transparent;
  padding: 0.5rem 0.75rem;
  cursor: pointer;
  transition: color 0.3s ease, background-color 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease;
}
.chip code { background: none; border: 0; padding: 0; font-size: 1em; color: inherit; }
.chip:hover { color: var(--ink); border-color: var(--edge); }
.chip[aria-pressed="true"] {
  color: var(--ink);
  background: var(--tint);
  border-color: color-mix(in oklab, var(--vest) 70%, transparent);
  box-shadow: 0 0 20px -6px var(--glow), inset 0 0 14px -8px var(--vest);
}

.codebox { min-width: 0; }
.codebox-title {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  color: var(--muted);
  padding: 0.55rem 1rem;
  border-bottom: 1px solid var(--rule);
  background: rgba(255, 255, 255, 0.02);
}
.led { display: inline-flex; align-items: center; gap: 0.5em; color: var(--vest); text-transform: uppercase; }
.led::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: currentColor; box-shadow: 0 0 8px currentColor; animation: led 1.8s ease-in-out infinite; }
.led.bad { color: var(--err); }
.led.bad::before { animation-duration: 0.7s; }
@keyframes led { 50% { opacity: 0.35; } }

.code {
  margin: 0;
  padding: 0.9rem 0;
  overflow-x: auto;
  font-family: var(--font-mono);
  font-size: 0.84rem;
  line-height: 1.65;
  tab-size: 4;
}
.code code { background: none; border: 0; padding: 0; font-size: 1em; color: var(--ink); white-space: pre; display: block; }
.code code:not(.numbered) { padding-inline: 1rem; }
.code .ln { display: block; padding-inline: 0 1rem; min-width: max-content; }
.code .ln::before {
  content: attr(data-n);
  display: inline-block;
  width: 2.6rem;
  padding-right: 0.9rem;
  text-align: right;
  color: var(--muted);
  opacity: 0.55;
}
.code .ln.del { text-decoration: line-through; text-decoration-color: var(--err); color: var(--muted); background: linear-gradient(90deg, transparent 2.6rem, color-mix(in oklab, var(--err) 12%, transparent) 2.6rem); animation: struck 0.7s var(--ease) backwards; }
.code .ln.del::before { content: "−"; color: var(--err); opacity: 1; }
.code .ln.ins { background: var(--ins); box-shadow: inset 2px 0 0 var(--vest); animation: inserted 0.7s var(--ease) backwards; }
.code .ln.ins::before { content: "+"; color: var(--vest); opacity: 1; }
.code .kw { color: var(--syn-kw); font-weight: 600; }
.code .ty { color: var(--syn-ty); }
.code .nm { color: var(--syn-num); }
.code .at { color: var(--syn-attr); }
.code .err { text-decoration: underline wavy var(--err); text-decoration-thickness: 1.5px; text-underline-offset: 3px; text-decoration-skip-ink: none; animation: alarm 1.6s ease-in-out infinite; }
@keyframes struck { from { opacity: 0.2; background-color: color-mix(in oklab, var(--err) 35%, transparent); } }
@keyframes inserted { from { opacity: 0; translate: -10px 0; background-color: color-mix(in oklab, var(--vest) 40%, transparent); } }
@keyframes alarm { 50% { text-shadow: 0 0 12px color-mix(in oklab, var(--err) 80%, transparent); } }

.out {
  font-family: var(--font-mono);
  font-size: 0.82rem;
  line-height: 1.6;
  border-top: 1px solid var(--edge);
  background: rgba(0, 0, 0, 0.28);
  padding: 0.75rem 1rem 0.85rem;
  overflow-wrap: anywhere;
}
.out-line { animation: wipe 0.6s steps(24, end) 0.15s backwards; }
.out-line.bad { color: var(--err); text-shadow: 0 0 14px color-mix(in oklab, var(--err) 40%, transparent); }
.out-line.good { color: var(--vest); text-shadow: 0 0 14px var(--glow); }
.out-exit { color: var(--muted); animation: fade 0.3s ease 0.75s backwards; }
@keyframes wipe { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
.note { font-size: var(--step--1); color: var(--muted); }
.note code { white-space: normal; }

/* ---------- examen ---------- */

.examen-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
  gap: clamp(2rem, 5vw, 4rem);
  align-items: start;
}
@media (max-width: 860px) { .examen-grid { grid-template-columns: minmax(0, 1fr); } }

.examen ol { list-style: none; margin: 0; padding: 0; counter-reset: exam; }
.examen li {
  counter-increment: exam;
  display: grid;
  grid-template-columns: 3.3rem 1.6rem minmax(0, 1fr);
  align-items: start;
  gap: 0.75rem;
  padding: 0.85rem 0.6rem;
  border-top: 1px solid var(--rule);
  transition: background-color 0.35s ease;
}
.examen li:last-child { border-bottom: 1px solid var(--rule); }
.examen li:hover { background: linear-gradient(90deg, var(--tint), transparent 80%); }
.examen li::before {
  content: counter(exam, upper-roman);
  font-family: var(--font-display);
  font-size: 1.35rem;
  line-height: 1.1;
  color: var(--vest);
  text-shadow: 0 0 12px color-mix(in oklab, var(--vest) 35%, transparent);
}
.examen label { cursor: pointer; line-height: 1.45; transition: color 0.35s ease; }
.examen input {
  appearance: none;
  -webkit-appearance: none;
  width: 1.4rem;
  height: 1.4rem;
  margin: 0.08rem 0 0;
  border: 1px solid color-mix(in oklab, var(--vest) 60%, transparent);
  background: rgba(255, 255, 255, 0.025);
  box-shadow: inset 0 0 10px -4px var(--glow);
  display: grid;
  place-content: center;
  cursor: pointer;
  transition: border-color 0.3s ease, box-shadow 0.3s ease;
}
.examen input::after {
  content: "";
  width: 0.62rem;
  height: 0.62rem;
  background: var(--vest);
  box-shadow: 0 0 10px var(--vest);
  rotate: 45deg;
  scale: 0;
  transition: scale 0.3s cubic-bezier(0.3, 1.7, 0.5, 1);
}
.examen input:hover { border-color: var(--vest); }
.examen input:checked { border-color: var(--vest); box-shadow: 0 0 16px -3px var(--glow), inset 0 0 10px -4px var(--glow); }
.examen input:checked::after { scale: 1; }
.examen input:checked + label { color: var(--muted); }

.verdict {
  position: sticky;
  top: calc(env(safe-area-inset-top, 0px) + 5.5rem);
  display: grid;
  gap: 1rem;
  justify-items: center;
  text-align: center;
  padding: 1.75rem 1.5rem 1.6rem;
}
.dial { position: relative; width: min(12rem, 70%); aspect-ratio: 1; display: grid; place-items: center; }
.dial svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.dial-track { fill: none; stroke: rgba(255, 255, 255, 0.05); stroke-width: 7; }
.dial-seg { fill: none; stroke: rgba(255, 255, 255, 0.08); stroke-width: 7; transition: stroke 0.5s ease, filter 0.5s ease; }
.dial-seg.lit { stroke: var(--c); filter: drop-shadow(0 0 4px var(--c)); }
.dial-inner { fill: none; stroke: var(--edge); stroke-width: 0.8; stroke-dasharray: 1 3.6; transform-box: view-box; transform-origin: 0 0; animation: spin 60s linear infinite; }
.verdict-count { position: relative; font-family: var(--font-display); font-size: clamp(3.6rem, 8vw, 5rem); line-height: 0.8; color: var(--vest); text-shadow: 0 0 26px var(--glow); }
.verdict-count .of { color: var(--muted); font-size: 0.42em; margin-left: 0.08em; text-shadow: none; }
.verdict-count.tick #examen-count { display: inline-block; animation: tick 0.45s cubic-bezier(0.3, 1.6, 0.5, 1); }
.verdict-text { font-family: var(--font-voice); font-size: var(--step-2); line-height: 1.25; text-wrap: balance; }
.verdict.gloria { animation: glory 1.4s ease 2; }
@keyframes tick { from { scale: 1.35; } }
@keyframes glory { 50% { border-color: var(--vest); box-shadow: var(--echo), 0 0 60px -6px var(--glow); } }

/* liturgy.js asks the questions one at a time in a single glass panel: the dial, the question,
   then Yes or Not yet. At the end come the count, the verdict and the questions answered Not
   yet. "Show all" goes back to the list above, which is also all there is without the script.
   The form and the verdict give their parts to the panel, which sets them in this order. */
.examen-grid.one {
  grid-template-columns: minmax(0, 1fr);
  justify-items: center;
  gap: 1.4rem;
  max-width: 48rem;
  margin-inline: auto;
  padding: clamp(1.75rem, 4vw, 2.75rem) clamp(1.1rem, 4vw, 3rem);
  text-align: center;
}
.examen-grid.one .verdict, .examen-grid.one .examen { display: contents; }
.examen-grid.one .verdict::before { content: none; }
.examen-grid.one .dial { order: 1; width: min(11rem, 60%); }
.examen-grid.one .verdict-text { order: 2; max-width: 30ch; }
.exam-left { order: 3; }
.examen-grid.one .examen ol { order: 4; justify-self: stretch; text-align: left; }
.exam-answers { order: 5; }
.examen-grid.one #examen-reset { order: 6; }
.exam-nav { order: 7; }
.examen-grid.one.gloria { animation: glory 1.4s ease 2; }

.dial-now, .exam-answers, .exam-left { display: none; }
.examen-grid.asking .verdict-count, .examen-grid.asking .verdict-text, .examen-grid.asking #examen-reset { display: none; }
.examen-grid.asking .dial-now { display: grid; }
.examen-grid.asking .exam-answers { display: flex; }
.examen-grid.done.has-left .exam-left { display: block; }

/* the question being asked: its numeral stands in the dial */
.dial-now { position: relative; justify-items: center; gap: 0.55rem; }
.dial-now-n { font-family: var(--font-display); font-size: clamp(3rem, 7vw, 4.2rem); line-height: 0.8; color: var(--vest); text-shadow: 0 0 26px var(--glow); }
.dial-now .of { font: 0.7rem / 1 var(--font-mono); letter-spacing: 0.16em; text-transform: uppercase; color: var(--muted); }
.dial-seg.no { stroke: rgba(255, 255, 255, 0.22); stroke-dasharray: 1.5 2.5; }
.dial-seg.now { stroke: color-mix(in oklab, var(--c) 60%, transparent); animation: breathe 2.2s ease-in-out infinite; }

.examen-grid.asking .examen li {
  grid-template-columns: minmax(0, 1fr);
  justify-items: center;
  padding: 0.3rem 0 0.2rem;
  border: 0;
  background: none;
  text-align: center;
}
.examen-grid.asking .examen li::before, .examen-grid.asking .examen input { display: none; }
.examen-grid.asking .examen label {
  max-width: 32ch;
  font: 400 var(--step-2) / 1.3 var(--font-voice);
  color: var(--ink);
  pointer-events: none;
}
.examen-grid.one .examen li[hidden] { padding-block: 0; border: 0; }
.examen li[hidden]:not([hidden="until-found"]) { display: none !important; }
.examen-grid.done .examen ol { border-bottom: 1px solid var(--rule); }
.examen-grid.done .examen li:last-child { border-bottom: 0; }

.exam-answers { flex-wrap: wrap; justify-content: center; gap: 0.9rem; }
.exam-answers .btn { min-width: 9rem; }
.exam-left { justify-self: stretch; text-align: left; font: 0.75rem / 1.4 var(--font-mono); letter-spacing: 0.14em; text-transform: uppercase; color: var(--gilt); }

.exam-nav { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.4rem 1.6rem; }
.examen-grid:not(.one) .exam-nav { justify-content: flex-start; margin-top: 1.2rem; }
.examen-grid:not(.one) .exam-back, .examen-grid.first .exam-back { display: none; }
.exam-link {
  font: 600 0.72rem / 1 var(--font-mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  background: none;
  border: 0;
  border-bottom: 1px solid var(--edge);
  padding: 0.45rem 0 0.35rem;
  cursor: pointer;
  transition: color 0.3s ease, border-color 0.3s ease, text-shadow 0.3s ease;
}
.exam-link:hover { color: var(--vest); border-color: var(--vest); text-shadow: 0 0 14px var(--glow); }

.missal .explicit {
  font-family: var(--font-display);
  font-size: clamp(3rem, 7vw, 4.8rem);
  line-height: 0.9;
  background: linear-gradient(100deg, var(--vest) 0%, var(--vest) 30%, var(--gilt-hi) 45%, var(--gilt) 50%, var(--vest) 62%, var(--vest) 100%);
  background-size: 260% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  filter: drop-shadow(0 0 22px var(--glow));
  animation: shimmer 9s linear infinite 3s;
}
.small { font-size: var(--step--1); color: var(--muted); }

/* ---------- toast ---------- */

.toast {
  position: fixed;
  left: 50%;
  bottom: calc(24px + env(safe-area-inset-bottom, 0px));
  translate: -50% 0;
  z-index: 50;
  font: 600 var(--step--1) / 1.3 var(--font-mono);
  color: var(--ink);
  background: color-mix(in oklab, var(--bg-2) 82%, transparent);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border: 1px solid color-mix(in oklab, var(--vest) 70%, transparent);
  box-shadow: var(--echo), 0 0 34px -8px var(--glow);
  padding: 0.75rem 1.1rem;
  max-width: calc(100vw - 32px);
  animation: toast-in 0.45s cubic-bezier(0.2, 0.9, 0.3, 1.2);
}
@keyframes toast-in { from { opacity: 0; translate: -50% 14px; scale: 0.96; } }

/* ---------- stillness ---------- */

:root[data-motion="still"] *,
:root[data-motion="still"] *::before,
:root[data-motion="still"] *::after { animation: none !important; }
:root[data-motion="still"] .rv,
:root[data-motion="still"] .rv::before,
:root[data-motion="still"] .rv .folio::before { transition: none !important; }
:root[data-motion="still"] .beast-leaf, :root[data-motion="still"] .verte-turn { transition: none; }
:root[data-motion="still"] .horae-stage, :root[data-motion="still"] .slip { transition: none; }

/* Before the script has run, the system setting decides. */
@media (prefers-reduced-motion: reduce) {
  :root:not([data-motion]) *,
  :root:not([data-motion]) *::before,
  :root:not([data-motion]) *::after { animation: none !important; }
}
