/* ============================================================
   THE DECORUM STANDARD — havesomedecorum.com

   ART DIRECTION: "The Monogram" over "The Register".

   The shell is B. A twelve column grid, type that starts at column
   two and never at column one, flush ruled rows instead of cards,
   and the engraved DS mark blown up and cropped by the page edge.
   The tension is deliberate: a Victorian blackletter mark holding
   still inside a flat modernist grid.

   The working pages are C. A ruled document, not a page. Density is
   the luxury. Whitespace is used where it means something and never
   as padding for comfort.

   THINGS THAT ARE BANNED HERE, because they are what a templated
   site looks like and this one has already drifted twice:
     - cards, boxes, rounded corners, drop shadows
     - a row of three equal tiles
     - fade-up-on-scroll
     - centred body copy
     - a heading, a paragraph and two buttons, repeated down the page

   Palette and type are lifted from the shipped card build
   (06-build-scripts/plates_lib.py, fonts.py). Lora reads, Poppins
   labels. That split is the same one used inside the guide PDFs.
   ============================================================ */

:root {
  --bone:   #f4efe6;
  --bone-2: #ede7da;
  --rule:   #d9d1c3;
  --rule-2: #c8bfad;   /* the heavier rule, used once per document */
  --camel:  #9c7b4a;
  --gold:   #c9a268;
  --char:   #26251f;
  --navy:   #13233f;
  --stone:  #8a8377;
  --set:    #4a473f;   /* body copy that is not display */

  /* Light text on a navy ground. This was --bone-2, which is the second
     PAPER: the two are the same colour on a light theme and nothing alike
     on a dark one. Separating them is what lets dark mode be nothing but
     a token flip. */
  --on-navy: var(--bone-2);
  /* the header nav ink, navy on paper and the paper's ink on dark */
  --nav-ink: var(--navy);
  /* which monogram the paper watermark uses */
  --wm-mark: url("/assets/wm-dark.png");

  --rule-navy: rgba(237, 231, 218, 0.24);

  /* THE SCALE. Six steps and nothing else. Every rule below points at one
     of these. If a new size feels necessary, one of the six is being used
     in the wrong place. There were twenty-two sizes here before this; that
     is what a page with too many fonts on it is actually made of. */
  --t-d1:    clamp(2.25rem, 1.3rem + 4vw, 4.5rem);      /* page title, one per page */
  --t-d2:    clamp(1.625rem, 1.2rem + 1.8vw, 2.5rem);   /* section title */
  --t-d3:    clamp(1.125rem, 1.05rem + 0.55vw, 1.4375rem); /* sub title, register row */
  --t-read:  1.125rem;                                  /* the one reading size */
  --t-meta:  0.9375rem;                                 /* short annotation, sans */
  --t-label: 0.6875rem;                                 /* uppercase label, sans */

  --serif: "Lora", Georgia, "Times New Roman", serif;
  --sans:  "Poppins", -apple-system, BlinkMacSystemFont, "Helvetica Neue", sans-serif;
  --mono:  ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  --pad:  clamp(1rem, 2.4vw, 2.25rem);   /* the document margin */
  --colgap: clamp(1rem, 1.6vw, 1.5rem);
  --read: 34rem;
}

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

/* The UA rule for [hidden] is display:none at specificity 0,1,0, so any author
   rule that sets display on the same element beats it. That is exactly what
   happened: .scrim { display: block } inside the phone media query left the
   scrim covering the whole viewport at z-index 90 while it was still hidden,
   and it swallowed every tap on the site. Nothing on mobile was clickable.
   This is the guard, not a style choice. */
[hidden] { display: none !important; }
html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* clip, not hidden: hidden on the root kills position: sticky, which the
     document head depends on. This is a backstop, not the fix. */
  overflow-x: clip;
}

body {
  margin: 0;
  padding: 0 var(--pad) var(--pad);
  background: var(--bone);
  color: var(--char);
  font-family: var(--sans);
  font-weight: 300;
  font-size: 1rem;   /* document default, not a scale step */
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
:focus-visible { outline: 2px solid var(--camel); outline-offset: 2px; }

.skip { position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--navy); color: var(--on-navy); padding: 0.75rem 1.25rem; }
.skip:focus { left: 0; }

/* ============================================================
   1. DOCUMENT HEAD
   Three part masthead with the heavy rule under it, then the nav on
   its own hairline. Straight off the Record card.
   ============================================================ */

.dochead { position: sticky; top: 0; z-index: 50; background: var(--bone); }

.dochead__top {
  display: grid; grid-template-columns: 1fr auto 1fr; gap: 1rem; align-items: center;
  padding-block: 0.75rem 0.5rem; border-bottom: 2px solid var(--char);
}

.dochead__nav {
  display: flex; justify-content: space-between; gap: 1rem; flex-wrap: wrap;
  padding-block: 0.7rem; border-bottom: 1px solid var(--rule);
}

.micro {
  margin: 0; font-size: var(--t-label); font-weight: 400; letter-spacing: 0.24em;
  text-transform: uppercase; color: var(--stone-ink); white-space: nowrap;
}

.micro--ink { color: var(--char); }
.micro--camel { color: var(--camel-ink); }
.dochead__top .r { text-align: right; }
/* lifted with the nav. At 11px grey under a 14px navy row it read as
   something left over rather than as the masthead. */
.dochead__top .micro { font-size: 0.75rem; letter-spacing: 0.2em; }
.dochead__top .house { color: var(--nav-ink); }
.dochead__top .house b { font-weight: 500; color: var(--camel-ink); }

/* The nav was 11px warm grey at 0.24em, the widest tracking on the site.
   Wide tracking at a small size is what made it read as a caption rather than
   as navigation: the letters stop forming words at a glance. Bigger, tighter,
   and navy, which also takes it from 4.70:1 against the paper to 13.68:1. */
.dochead__nav a { font-size: 0.875rem; letter-spacing: 0.13em; font-weight: 500;
  text-transform: uppercase; color: var(--nav-ink); padding-bottom: 2px;
  border-bottom: 1px solid transparent; }
.dochead__nav a:hover, .dochead__nav a[aria-current="page"] { color: var(--nav-ink);
  border-bottom-color: var(--camel); }
.dochead__nav .grp { display: flex; gap: clamp(0.875rem, 2.4vw, 2.25rem); flex-wrap: wrap; }

/* The three part masthead does not fit on a phone. The centre line and the
   register are both nowrap, so at 375px they pushed the document to 657px
   wide and the whole site scrolled sideways. Below tablet the head keeps the
   house name and the register only, and labels are allowed to wrap. */
@media (max-width: 46rem) {
  .dochead__top { grid-template-columns: 1fr auto; }
  .dochead__top .micro--ink { display: none; }
  .micro { white-space: normal; }
  .register__cap { flex-wrap: wrap; }
}

/* ============================================================
   2. GRID
   Twelve columns. Content starts at two. Column one is the margin
   the whole composition hangs off, and it stays empty.
   ============================================================ */

.g12 { display: grid; grid-template-columns: repeat(12, 1fr); gap: 0 var(--colgap); }

/* on narrow screens the offset collapses, the grid does not */
.c2-12 { grid-column: 1 / -1; }
.c2-8  { grid-column: 1 / -1; }
.c7-13 { grid-column: 1 / -1; }
.c2-7  { grid-column: 1 / -1; }
.c8-13 { grid-column: 1 / -1; }
.c2-13 { grid-column: 1 / -1; }

@media (min-width: 56rem) {
  .c2-12 { grid-column: 2 / 12; }
  .c2-8  { grid-column: 2 / 8; }
  .c7-13 { grid-column: 7 / 13; }
  .c2-7  { grid-column: 2 / 7; }
  .c8-13 { grid-column: 8 / 13; }
  .c2-13 { grid-column: 2 / 13; }
}

.band { padding-block: clamp(2.5rem, 6vw, 5.5rem); }
.band--tight { padding-block: clamp(1.75rem, 3.5vw, 3rem); }

/* a navy strip runs the full width of the document, edge to edge */
.strip { margin-inline: calc(-1 * var(--pad)); padding: clamp(1.75rem, 4vw, 3.25rem) var(--pad); }
.strip .micro { color: var(--gold); }

/* ============================================================
   3. TYPE
   ============================================================ */

.kick { margin: 0 0 1rem; padding-top: 0.75rem; border-top: 1px solid var(--camel);
  font-size: var(--t-label); letter-spacing: 0.26em; text-transform: uppercase; color: var(--camel-ink);
  display: inline-block; }

.display {
  margin: 0; font-family: var(--serif); font-weight: 400;
  font-size: var(--t-d1); line-height: 0.99; letter-spacing: -0.028em;
}

.display em { font-style: italic; color: var(--camel-ink); }
.display--sm { font-size: var(--t-d2); line-height: 1.08; }
.display--xs { font-size: var(--t-d3); line-height: 1.25; }

.refuse { margin: 0; font-family: var(--serif); font-style: italic;
  font-size: var(--t-d3); color: var(--stone-ink); }

/* long form reads in Lora, the same as every finished guide */
.prose { max-width: var(--read); font-family: var(--serif); font-weight: 400;
  font-size: var(--t-read); line-height: 1.62; color: var(--char); }
.prose > * { margin-block: 0; }
.prose > * + * { margin-top: 1.125rem; }
.prose > h2 { margin-top: clamp(2.25rem, 4vw, 3rem); font-family: var(--serif); font-weight: 400;
  font-size: var(--t-d2); line-height: 1.14; letter-spacing: -0.015em; }
.prose > h3 { margin-top: 2rem; font-family: var(--sans); font-weight: 500; font-size: var(--t-label);
  letter-spacing: 0.3em; text-transform: uppercase; color: var(--camel-ink); }
.prose a { border-bottom: 1px solid var(--camel); }
.prose strong { font-weight: 500; }
.strip .prose, .navy .prose { color: var(--on-navy); }

/* the camel left rule. a definition, a quoted line, or a short list that
   is the spine of the section it sits in. */
.mark { border-left: 2px solid var(--camel); padding-left: clamp(1rem, 2vw, 1.5rem); }
.mark p { margin: 0; font-family: var(--serif); font-weight: 400;
  font-size: var(--t-d3); line-height: 1.35; }
.mark p + p { margin-top: 0.625rem; }
.strip .mark, .navy .mark { border-left-color: var(--gold); }

/* the small set block. Poppins, tight, used for asides and specs */
/* short annotation only. two or three lines. anything longer reads badly in
   a sans at this width and belongs in .prose or .cols, which are Lora. */
.set { margin: 0; font-size: var(--t-meta); line-height: 1.6; color: var(--set); max-width: 40ch; }
.strip .set { color: rgba(237, 231, 218, 0.74); }

/* ============================================================
   4. THE WATERMARK

   The DS mark is a permanent watermark, not a decoration dropped on
   one section. It is painted as a fixed background layer, so it holds
   still in the viewport while the bands scroll over it, and each band
   reveals only the part of it that it currently covers.

   That is also what makes it change lighting on its own. Paper bands
   paint the charcoal cut, navy bands paint the bone cut, so the mark
   reads dark on bone and light on blue and appears to shift as a strip
   passes across it. No script, no second element.

   Opacity is the wash layer, not the file, so it is tuned here:
   a higher wash alpha means a fainter mark.
   ============================================================ */

:root {
  --wm-size: auto 128vh;                       /* taller than the viewport, so it always crops */
  --wm-pos: right -22vw center;                /* bleeds off the right edge, as it did before */
  /* The wash sets how faint the mark is: higher alpha, fainter mark. The
     target is that you can see it and know it is there, and it never
     competes with type. Navy is pushed furthest because a bone mark on a
     navy ground sits in the same tonal register as bone text, which is the
     worst case on the site. */
  --wm-paper: rgba(244, 239, 230, 0.955);      /* mark reads at ~4.5% */
  --wm-paper-2: rgba(237, 231, 218, 0.958);     /* ~4% */
  --wm-navy: rgba(19, 35, 63, 0.979);          /* ~2%, faintest of the three */
}

body {
  background-image: linear-gradient(var(--wm-paper), var(--wm-paper)), var(--wm-mark);
  background-attachment: scroll, fixed;
  background-repeat: no-repeat, no-repeat;
  background-position: center, var(--wm-pos);
  background-size: cover, var(--wm-size);
}

/* .paper is the same ground as the document, so it stays transparent and
   lets the body watermark through rather than painting over it. */
.paper { background: transparent; }

/* The ground sets the text colour for everything inside it. This rule went
   missing in the watermark refactor and only showed up on headings, because
   every other element on navy happened to carry its own override. */
.strip, .navy { color: var(--on-navy); }

.paper-2 {
  background-color: var(--bone-2);
  background-image: linear-gradient(var(--wm-paper-2), var(--wm-paper-2)), var(--wm-mark);
  background-attachment: scroll, fixed;
  background-repeat: no-repeat, no-repeat;
  background-position: center, var(--wm-pos);
  background-size: cover, var(--wm-size);
}

.strip, .navy {
  background-color: var(--navy);
  background-image: linear-gradient(var(--wm-navy), var(--wm-navy)), url("/assets/wm-light.png");
  background-attachment: scroll, fixed;
  background-repeat: no-repeat, no-repeat;
  background-position: center, var(--wm-pos);
  background-size: cover, var(--wm-size);
}

/* iOS Safari treats fixed attachment as scroll and repaints badly with it,
   so below tablet the mark rides with the page instead of holding still. */
@media (max-width: 52rem) {
  body, .paper-2, .strip, .navy { background-attachment: scroll, scroll; }
  :root { --wm-size: auto 90vh; --wm-pos: right -30vw center; }
}

/* The ghosted numeral. Same idea as the watermark, flattened into a single
   section rather than the whole document. .stage is the positioning context
   it needs; the two only ever appear together. */

.stage { position: relative; overflow: hidden; }
.stage > *:not(.bignum) { position: relative; z-index: 1; }

.bignum {
  position: absolute; right: -0.06em; bottom: -0.3em; margin: 0;
  /* exception: decorative, not read */
  font-family: var(--serif); font-size: clamp(11rem, 26vw, 22rem); line-height: 0.7;
  color: rgba(38, 37, 31, 0.055); pointer-events: none; user-select: none;
}

.strip .bignum, .navy .bignum { color: rgba(237, 231, 218, 0.07); }

/* ============================================================
   5. THE REGISTER
   The ruled index. This is the workhorse and it replaces every card
   grid on the site.
   ============================================================ */

.register { margin: 0; padding: 0; list-style: none; }

.register__cap {
  display: flex; justify-content: space-between; align-items: baseline; gap: 1rem;
  padding-bottom: 0.5rem; border-bottom: 1px solid var(--char);
}

.reg { display: grid; grid-template-columns: 2.25rem 1fr; gap: 0.25rem 0.875rem;
  padding: 0.75rem 0; border-bottom: 1px solid var(--rule); align-items: baseline; }

.reg__n { margin: 0; font-size: var(--t-label); letter-spacing: 0.14em; color: var(--camel-ink); }
.reg__t { margin: 0; font-family: var(--serif); font-weight: 400; font-size: var(--t-d3); line-height: 1.3; }
.reg__m { grid-column: 2; margin: 0; font-size: var(--t-label); letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--stone-ink); }

@media (min-width: 46rem) {
  .reg { grid-template-columns: 2.5rem 1fr auto; gap: 0.875rem; }
  .reg__m { grid-column: 3; text-align: right; }
}

a.reg:hover { background: rgba(156, 123, 74, 0.07); }
a.reg:hover .reg__t { color: var(--camel-ink); }

.strip .register__cap, .navy .register__cap { border-bottom-color: var(--on-navy); }
.strip .reg, .navy .reg { border-bottom-color: var(--rule-navy); }
.strip .reg__n, .navy .reg__n { color: var(--gold); }
.strip .reg__t, .navy .reg__t { color: var(--on-navy); }
.strip .reg__m, .navy .reg__m { color: rgba(237, 231, 218, 0.66); }

/* the wide register, used where a row carries a full sentence */
.reg--wide { grid-template-columns: 2.25rem 1fr; }
@media (min-width: 56rem) {
  .reg--wide { grid-template-columns: 2.5rem 17rem 1fr; }
  .reg--wide .reg__m { grid-column: 3; text-align: left; font-size: var(--t-meta);
    letter-spacing: 0; text-transform: none; color: var(--set); max-width: 62ch; }
  .strip .reg--wide .reg__m, .navy .reg--wide .reg__m { color: rgba(237, 231, 218, 0.7); }
}

/* ============================================================
   6. RULED ROW
   The B footer device. Flush columns divided by vertical hairlines,
   never boxes.
   ============================================================ */

.ruled { display: grid; grid-template-columns: 1fr; border-top: 1px solid var(--rule); }
@media (min-width: 52rem) { .ruled--3 { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 52rem) { .ruled--4 { grid-template-columns: repeat(4, 1fr); } }
@media (min-width: 52rem) { .ruled--2 { grid-template-columns: repeat(2, 1fr); } }

.ruled > * { padding: 1.5rem 1.5rem 1.5rem 0; border-bottom: 1px solid var(--rule); }
@media (min-width: 52rem) {
  .ruled > * { border-right: 1px solid var(--rule); border-bottom: 0; }
  .ruled > *:last-child { border-right: 0; }
  .ruled > * + * { padding-left: 1.5rem; }
}

.ruled h3 { margin: 0.625rem 0 0.375rem; font-family: var(--serif); font-weight: 400;
  font-size: var(--t-d3); }
.ruled p { margin: 0; font-size: var(--t-meta); color: var(--stone-ink); max-width: 36ch; }
.ruled a:hover h3 { color: var(--camel-ink); }
.strip .ruled, .navy .ruled { border-top-color: var(--rule-navy); }
.strip .ruled > *, .navy .ruled > * { border-right-color: var(--rule-navy); border-bottom-color: var(--rule-navy); }
.strip .ruled p, .navy .ruled p { color: rgba(237, 231, 218, 0.6); }

/* ============================================================
   7. RECORD
   Ten era sheets, scrolled left to right. Each sheet is a ruled
   document carrying its two finished cards.
   ============================================================ */

.deck { display: grid; gap: clamp(2.5rem, 5vw, 3.5rem); }

@media (min-width: 62rem) {
  .deck {
    grid-auto-flow: column; grid-auto-columns: min(72rem, 86vw);
    overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x proximity;
    margin-inline: calc(-1 * var(--pad)); padding: 0 var(--pad) 1.5rem;
    scrollbar-color: var(--rule) transparent;
  }
  .era { scroll-snap-align: start; }
}

.era { position: relative; overflow: hidden; }
.era__head { display: grid; grid-template-columns: 1fr auto; gap: 0.5rem 1rem; align-items: end;
  padding-bottom: 0.5rem; border-bottom: 2px solid var(--char); }
.era__sub { margin: 0.25rem 0 0; font-family: var(--serif); font-style: italic; color: var(--stone-ink); }

.era__cards { display: grid; gap: clamp(0.875rem, 2vw, 1.5rem); margin-top: clamp(1.25rem, 2.5vw, 2rem); }
@media (min-width: 46rem) { .era__cards { grid-template-columns: 1fr 1fr; } }

.card { margin: 0; }
.card img { width: 100%; height: auto; border: 1px solid var(--rule); background: var(--bone);
  transition: border-color 160ms ease; }
.card a:hover img { border-color: var(--camel); }
.card figcaption { margin-top: 0.5rem; font-family: var(--mono); font-size: var(--t-label);
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--stone-ink); }

/* ============================================================
   8. CONTROLS
   A rule and a word. No filled pills, no icons.
   ============================================================ */

.act {
  display: inline-block; font-size: var(--t-label); font-weight: 500; letter-spacing: 0.24em;
  text-transform: uppercase; padding-bottom: 0.4375rem;
  border-bottom: 1px solid var(--camel); color: var(--char);
  transition: color 150ms ease, border-color 150ms ease;
}

.act:hover { color: var(--camel-ink); }
.act--solid { border: 1px solid var(--char); background: var(--char); color: var(--bone);
  padding: 0.875rem 1.5rem; }
.act--solid:hover { background: var(--camel); border-color: var(--camel); color: var(--bone); }
.strip .act, .navy .act { color: var(--on-navy); border-bottom-color: var(--gold); }
.strip .act:hover, .navy .act:hover { color: var(--gold); }
.strip .act--solid, .navy .act--solid { background: var(--on-navy); border-color: var(--on-navy); color: var(--navy); }
.strip .act--solid:hover, .navy .act--solid:hover { background: var(--gold); border-color: var(--gold); }

.acts { display: flex; gap: clamp(1.5rem, 3vw, 2.75rem); flex-wrap: wrap; align-items: center; }

.mailto { font-family: var(--serif); font-size: var(--t-d3);
  border-bottom: 1px solid var(--camel); padding-bottom: 3px; overflow-wrap: anywhere; }
.strip .mailto, .navy .mailto { border-bottom-color: var(--gold); }

/* ============================================================
   9. DOCUMENT FOOT
   ============================================================ */

.docfoot { border-top: 2px solid var(--char); padding-top: 1.25rem; margin-top: clamp(2.5rem, 5vw, 4rem); }
.docfoot__cols { display: grid; gap: 1.75rem; }
@media (min-width: 52rem) { .docfoot__cols { grid-template-columns: 1.7fr 1fr 1fr 1.1fr; gap: 2rem; } }
/* On one column the four groups keep their desktop max-widths, which leaves
   every block hugging the left edge with a third of the screen empty beside
   it. Centre the stack and let the capped paragraphs centre with it. */
@media (max-width: 52rem) {
  .docfoot__cols { text-align: center; }
  .docfoot__cols p, .docfoot__cols ul { margin-inline: auto; }
  .docfoot__base { text-align: center; }
}
.docfoot ul { list-style: none; margin: 0.75rem 0 0; padding: 0; }
.docfoot li + li { margin-top: 0.4375rem; }
.docfoot a { font-size: var(--t-meta); color: var(--char); }
.docfoot a:hover { color: var(--camel-ink); }
.docfoot__base { margin-top: 2rem; padding-top: 0.875rem; border-top: 1px solid var(--rule);
  display: grid; gap: 0.625rem; }

.disclosure { margin: 0; font-size: var(--t-meta); line-height: 1.55; color: var(--stone-ink); max-width: 78ch; }

/* ============================================================
   10. UTILITIES
   These are declared last on purpose. .inset has the same specificity
   as the component rules it has to beat, so order is what decides it.
   ============================================================ */

/* Everything on a page shares one left and one right edge. The stage sets
   it at column two, so registers and ruled rows have to match or the eye
   reads two competing margins down the page.

   Doubled selector on purpose. This is a utility that has to beat component
   rules, and components keep getting appended below it, which at equal
   specificity means the component wins and the block silently goes flush
   left. That happened three times before this. .inset.inset is specificity
   0,2,0 and cannot be undone by a single class rule wherever it sits in the
   file, so ordering stops mattering. */
@media (min-width: 56rem) {
  /* one track plus one gap: the exact left edge of column two, derived from
     the same numbers the grid uses. 8.333% was close but not equal, so an
     inset block and a .c2-* block sat two pixels apart, and the gap moved
     with the viewport because one was a percentage and the other was not. */
  .inset.inset { margin-inline: calc((100% - 11 * var(--colgap)) / 12 + var(--colgap)); }
}

.flush-r { text-align: right; }
.hr { border: 0; border-top: 1px solid var(--rule); margin: 0; }
.hr--heavy { border-top: 2px solid var(--char); }
.mt-1 { margin-top: 0.75rem; } .mt-2 { margin-top: 1.5rem; }
.mt-3 { margin-top: 2.25rem; } .mt-4 { margin-top: 3.25rem; }

/* ============================================================
   11. THE RECORD TIMELINE
   The century runs left to right. One rule, ten years on it, and the
   plates fan out from the year you are pointing at.
   ============================================================ */

.timeline {
  position: relative;
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  margin-inline: calc(-1 * var(--pad));
  padding: clamp(15rem, 34vh, 22rem) var(--pad) clamp(4rem, 8vh, 6rem);
  scrollbar-width: none;
}

.timeline::-webkit-scrollbar { display: none; }

.timeline__inner { position: relative; display: flex; align-items: flex-start; width: max-content; }

/* The century draws itself in from the left. Note the order: everything
   here is VISIBLE by default and only hidden once JS has armed it. If the
   script never runs, or the page loads in a background tab where the first
   frame never paints, the timeline is still fully readable. */
.timeline__rule {
  position: absolute; left: 0; right: 0; top: 0; height: 1px;
  background: var(--rule-2); transform-origin: left center;
}

.timeline.is-armed .timeline__rule { transform: scaleX(0); }

.timeline.is-drawn .timeline__rule {
  transform: scaleX(1);
  transition: transform 1100ms cubic-bezier(.22, .9, .24, 1);
}

/* a year on the rule */
.yr {
  position: relative;
  flex: none;
  width: clamp(15rem, 23vw, 22rem);
  padding-top: 2.25rem;
  scroll-snap-align: center;
  display: block;
}

.yr::before {
  content: "";
  position: absolute; left: 0; top: 0; width: 1px; height: 1.25rem;
  background: var(--camel); transform-origin: top center;
}

.timeline.is-armed .yr::before { transform: scaleY(0); }
.timeline.is-ready .yr::before { transform: scaleY(1); transition: transform 420ms ease-out; }

.yr__no    { margin: 0; font-size: var(--t-label); letter-spacing: 0.26em; text-transform: uppercase; color: var(--stone-ink); }
.yr__year  { margin: 0.375rem 0 0; font-family: var(--serif); font-weight: 400;
             font-size: var(--t-d2); line-height: 1; letter-spacing: -0.02em;
             transition: color 220ms ease; }
.yr__sub   { margin: 0.5rem 0 0; font-family: var(--serif); font-style: italic;
             font-size: var(--t-read); color: var(--stone-ink); max-width: 22ch;
             opacity: 0; transform: translateY(6px);
             transition: opacity 320ms ease, transform 320ms ease; }
.yr__enter { margin: 0.875rem 0 0; font-size: var(--t-label); letter-spacing: 0.26em;
             text-transform: uppercase; color: var(--camel-ink);
             opacity: 0; transition: opacity 320ms ease 60ms; }

/* without JS there is no hover state to reveal them, so show them outright */
.timeline:not(.is-armed) .yr__sub,
.timeline:not(.is-armed) .yr__enter { opacity: 1; transform: none; }

.yr:hover .yr__year, .yr.is-open .yr__year { color: var(--camel-ink); }
.timeline .yr.is-open > .yr__sub { opacity: 1; transform: none; }
.timeline .yr.is-open > .yr__enter { opacity: 1; transform: none; }

/* The years rise onto the rule in sequence, once armed. Scoped to <p> so it
   never touches .stills, whose own opacity is driven by the hover state. */
.timeline.is-armed .yr > p { opacity: 0; transform: translateY(14px); }
.timeline.is-ready .yr > .yr__no,
.timeline.is-ready .yr > .yr__year {
  opacity: 1; transform: none;
  transition: opacity 620ms ease, transform 620ms cubic-bezier(.22,.9,.24,1);
}
.timeline.is-ready .yr > .yr__sub,
.timeline.is-ready .yr > .yr__enter { transform: none; }

.timeline.is-ready .yr:nth-child(1) > p  { transition-delay: 0ms; }
.timeline.is-ready .yr:nth-child(2) > p  { transition-delay: 70ms; }
.timeline.is-ready .yr:nth-child(3) > p  { transition-delay: 140ms; }
.timeline.is-ready .yr:nth-child(4) > p  { transition-delay: 210ms; }
.timeline.is-ready .yr:nth-child(5) > p  { transition-delay: 280ms; }
.timeline.is-ready .yr:nth-child(6) > p  { transition-delay: 350ms; }
.timeline.is-ready .yr:nth-child(7) > p  { transition-delay: 420ms; }
.timeline.is-ready .yr:nth-child(8) > p  { transition-delay: 490ms; }
.timeline.is-ready .yr:nth-child(9) > p  { transition-delay: 560ms; }
.timeline.is-ready .yr:nth-child(10) > p { transition-delay: 630ms; }

/* the plates, stacked above the rule until the year is pointed at */
.stills { position: absolute; left: 0; bottom: calc(100% + 1.5rem); width: clamp(9rem, 13vw, 12.5rem); }
.stills img {
  position: absolute; bottom: 0; left: 0; width: 100%; height: auto;
  border: 1px solid var(--rule); background: var(--bone);
  box-shadow: 0 1px 0 rgba(38,37,31,.06);
  opacity: 0; transform: translateY(26px) rotate(0deg);
  transition: opacity 480ms ease, transform 620ms cubic-bezier(.22,.9,.24,1);
}

.yr.is-open .stills img { opacity: 1; }
.yr.is-open .stills img:nth-child(1) { transform: translate(0, 0) rotate(-2.4deg); transition-delay: 0ms; }
.yr.is-open .stills img:nth-child(2) { transform: translate(5.5rem, -2.25rem) rotate(2.1deg); transition-delay: 90ms; }

.timeline__hint { display: flex; justify-content: space-between; gap: 1rem;
  padding-top: 0.75rem; border-top: 1px solid var(--rule); }

@media (max-width: 56rem) {
  .timeline { padding-top: clamp(11rem, 26vh, 15rem); }
  .yr { width: 14rem; }
  .stills { width: 7.5rem; }
}

/* ============================================================
   12. AN ERA PAGE
   The plate, at web scale. Set in that era's own typeface, because
   the decade's voice is part of what is being shown.
   ============================================================ */

.era-title {
  margin: 0; font-family: var(--era-display), var(--serif); font-weight: 400;
  /* exception: the decade's own face at its own plate size, one per page */
  font-size: clamp(2.5rem, 7vw, var(--era-size, 5.5rem)); line-height: 1;
  letter-spacing: var(--era-track, 0);
}

.era-sub { margin: 0.625rem 0 0; font-family: var(--serif); font-style: italic;
  font-size: var(--t-d3); color: var(--stone-ink); }

.era-body { font-family: var(--era-body), var(--sans); }

/* the record line under a plate */
.record { border-top: 1px solid var(--rule); padding-top: 0.875rem; }
.record__line { margin: 0.625rem 0 0; font-family: var(--era-display), var(--serif);
  font-size: var(--t-d3); line-height: 1.35; max-width: 34ch; }
.record__meta { display: flex; justify-content: space-between; gap: 1rem; flex-wrap: wrap;
  margin-top: 1.25rem; padding-top: 0.75rem; border-top: 1px solid var(--rule); }

/* the lettered and numbered callouts, as they read on plate B */
.callout { list-style: none; margin: 0.875rem 0 0; padding: 0; }
.callout li { display: grid; grid-template-columns: 1.5rem 1fr; gap: 0.875rem;
  padding: 0.5rem 0; border-bottom: 1px solid var(--rule); align-items: baseline; }
.callout .k { font-family: var(--mono); font-size: var(--t-label); letter-spacing: 0.06em; color: var(--camel-ink); }
.callout .v { font-family: var(--era-body), var(--sans); font-size: var(--t-meta); color: var(--set); }

/* the six statements the room was making */
.statements { display: grid; gap: 0; border-top: 1px solid var(--rule); }
@media (min-width: 46rem) { .statements { grid-template-columns: repeat(3, 1fr); } }
.statements > div { padding: 1.125rem 1.25rem 1.125rem 0; border-bottom: 1px solid var(--rule); }
@media (min-width: 46rem) {
  .statements > div { border-right: 1px solid var(--rule); }
  .statements > div:nth-child(3n) { border-right: 0; }
  .statements > div:not(:nth-child(3n+1)) { padding-left: 1.25rem; }
}
.statements .l { margin: 0; font-size: var(--t-label); letter-spacing: 0.22em;
  text-transform: uppercase; color: var(--camel-ink); }
.statements .v { margin: 0.5rem 0 0; font-family: var(--era-display), var(--serif);
  font-size: var(--t-d3); line-height: 1.4; }

.plate-fig { margin: 0; }
.plate-fig img { width: 100%; height: auto; border: 1px solid var(--rule); background: var(--bone); }
.plate-fig figcaption { margin-top: 0.5rem; font-family: var(--mono); font-size: var(--t-label);
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--stone-ink); }

/* previous and next decade */
.eranav { display: grid; grid-template-columns: 1fr 1fr; border-top: 2px solid var(--char); }
.eranav a { padding: 1.5rem 0; }
.eranav a:last-child { text-align: right; padding-left: 1.5rem; }
.eranav .t { margin: 0.5rem 0 0; font-family: var(--serif); font-size: var(--t-d3); }
.eranav a:hover .t { color: var(--camel-ink); }

/* ============================================================
   13. COLUMNS
   Long form runs across the whole page in newspaper columns rather
   than sitting in one narrow strip with half the sheet empty. The
   column count is set by measure, not by number, so it lands on four
   on a wide screen and one on a phone without any breakpoints.
   ============================================================ */

.cols {
  /* A column always starts on a new paragraph, never mid-sentence. That is
     what break-inside does. The count is passed in per block as --cols and
     capped by column-width, so a three paragraph section makes three columns
     rather than four with one left empty, and a phone makes one. */
  column-count: var(--cols, 3);
  column-width: 15rem;
  column-gap: clamp(1.25rem, 2.4vw, 2.25rem);
  column-rule: 1px solid var(--rule);
  font-family: var(--era-body, var(--serif));
  font-size: var(--t-read);
  line-height: 1.6;
  color: var(--char);
}

.cols p { margin: 0 0 1.0625rem; break-inside: avoid; -webkit-column-break-inside: avoid; }
.cols p:last-child { margin-bottom: 0; }
.strip .cols { color: var(--on-navy); column-rule-color: var(--rule-navy); }

/* the serif reading variant, for pages with no era face of their own */
.cols--serif { font-family: var(--serif); }

/* ============================================================
   14. THE TIMELINE SCROLLBAR
   Always visible. Without it there is no way to know the century
   runs to the right, and a hidden native bar tells you nothing.
   Draggable, clickable, and it doubles as a progress read.
   ============================================================ */

.tlbar {
  position: relative;
  height: 3px;
  margin-top: 1.5rem;
  background: var(--rule);
  cursor: pointer;
  touch-action: none;
}

.tlbar__thumb {
  position: absolute; left: 0; top: -1px; height: 5px;
  background: var(--camel);
  min-width: 2.5rem;
  transition: background 150ms ease;
}

.tlbar:hover .tlbar__thumb, .tlbar.is-dragging .tlbar__thumb { background: var(--char); }

.tlbar__ends { display: flex; justify-content: space-between; gap: 1rem; margin-top: 0.625rem; }

/* ============================================================
   15. THE ROSE

   A four point navigation star, tall on the vertical axis, standing in
   the middle of the principles band with its north and south points
   breaking out through the top and bottom edges into the sections
   either side. The four principles sit close in around the waist.

   The layering is the whole trick. A section background paints early
   and a section's plain text paints just after it, and there is no
   z-index that lands between the two. So every section's content is
   lifted into a positioned layer at z-index 1, and the star sits at 0:
   above every background it crosses, below every word.

   Because the points cross both grounds, the star is drawn in gold on
   both halves rather than bone. Bone would be invisible the moment a
   point left the navy.
   ============================================================ */

main > section > * { position: relative; z-index: 1; }

.rose-band {
  position: relative;
  min-height: clamp(30rem, 68vh, 46rem);
  display: grid;
  align-content: center;
}

/* Equal arms. All four points leave the band: north and south through the
   top and bottom edges, east and west out past the text columns to the
   page edges. Sized by width so the horizontal reach is the fixed thing;
   the vertical bleed follows from it.

   An earlier version elongated the vertical axis so the horizontal points
   would not collide with the copy. That was solving a problem that does
   not exist here, because the star is already beneath every word on the
   page, and it produced a dagger rather than a compass. */
.rose__star {
  position: absolute;
  z-index: 0;
  left: 50%; top: 50%;
  width: min(104vw, 88rem);
  height: auto;
  transform: translate(-50%, -50%);
  pointer-events: none;
}

/* it covers a lot of ground now, so it carries less weight per square inch */
.rose__solid { fill: var(--gold); fill-opacity: 0.6; }
.rose__hair { fill: none; stroke: var(--gold); stroke-width: 2; stroke-opacity: 0.5; }

.rose {
  list-style: none; margin: 0; padding: 0;
  display: grid;
  gap: clamp(2.25rem, 5vw, 3.5rem);
}

.rose__q { align-content: start; }
.rose__q h3 { max-width: 17ch; }
.rose__q .set { max-width: 30ch; }

@media (max-width: 62rem) {
  /* On one column there is no middle for a compass to sit in the middle of.
     Blown up to 150vw behind the stack it stopped being a mark and became a
     dark smear with the copy sitting on its arms. So below the two-column
     breakpoint it stops being a background and becomes what it is: a mark,
     small, centred, at the head of the four points it belongs to. */
  .rose-band { display: block; }
  .rose__star {
    position: static;
    transform: none;
    display: block;
    width: clamp(4.5rem, 20vw, 7rem);
    margin: 0 auto clamp(2.25rem, 8vw, 3.25rem);
    opacity: 1;
  }
  /* and the four become a register: a numeral, a rule, and the point.
     Capped and centred, because one column across a tablet runs the measure
     out to about ninety characters, which is half again what anyone reads
     comfortably. On a phone the cap is wider than the screen and does
     nothing. */
  .rose { gap: 0; max-width: 38rem; margin-inline: auto; }
  .rose__q { padding-block: clamp(1.5rem, 5vw, 2rem); }
  .rose__q + .rose__q { border-top: 1px solid rgba(244, 239, 230, 0.16); }
  .rose__q:first-child { padding-top: 0; }
  .rose__q:last-child { padding-bottom: 0; }
  .rose__q h3, .rose__q .set { max-width: none; }
}

@media (min-width: 62rem) {
  .rose {
    grid-template-columns: 1fr 1fr;
    /* equal tracks so the row boundary lands exactly on the rose's centre.
       Without this the taller quadrant sets row one's height, the boundary
       drifts off centre, and the horizontal arms cut through copy. */
    grid-template-rows: 1fr 1fr;
    column-gap: clamp(5.5rem, 10vw, 9.5rem);
    row-gap: clamp(4.5rem, 9vw, 8rem);
  }
  .rose__q--nw { grid-area: 1 / 1; }
  .rose__q--ne { grid-area: 1 / 2; }
  .rose__q--sw { grid-area: 2 / 1; }
  .rose__q--se { grid-area: 2 / 2; }

  /* Both sides have to hug the star equally. The columns are equal, but the
     copy inside them is left aligned, so without this the left blocks sit
     against the far edge of their column while the right blocks sit against
     the gap: one side a quarter of the page from the centre, the other
     touching it. The block is pushed to the column's inner edge; the text
     inside it stays left aligned, because that is about reading, not
     composition. */
  .rose__q--nw, .rose__q--sw { justify-self: end; }
  .rose__q--ne, .rose__q--se { justify-self: start; }
  .rose__q { max-width: 30ch; }

  /* Pushing the block to the inner edge was only half of it. Inside the
     block the type stayed left aligned, so the left pair met the star with a
     ragged edge while the right pair met it with a flush one, and the two
     sides read as different distances from the centre even though the boxes
     were symmetrical. The left pair now sets to the right, and every child
     with a max-width is pushed to the block's right edge, or an h3 capped at
     17ch would align to 17ch from the wrong side. */
  .rose__q--nw, .rose__q--sw { text-align: right; }
  .rose__q--nw > *, .rose__q--sw > * { margin-left: auto; }

  /* The headings run two lines or three depending on the principle, so the
     paragraph under a two line heading started a line above the paragraph
     next to it and the four blocks read as unaligned. Reserving three lines
     of heading puts every paragraph on the same line.

     Subgrid would express this better, but it needs each quadrant to span
     several parent tracks, and the rose's two rows have to stay equal or the
     boundary drifts off the star's centre and the horizontal arms cut
     through the copy. bin/check.py enforces that. Three lines it is: if a
     principle ever needs four, this number moves with it. */
  .rose__q h3 { min-height: 3.75em; }   /* 3 x the 1.25 line-height */
}

/* ============================================================
   16. THE DRAWER
   Phone navigation. Five items do not fit across a 393px screen, so
   below tablet the nav row is replaced by a burger and the menu slides
   in from the left.

   Sized for an iPhone 14 Pro, 393 x 852. Every target in here clears
   44px, which the desktop nav does not and cannot without wrecking the
   masthead.
   ============================================================ */

/* The drawer used to live entirely inside the phone breakpoint, because the
   burger was the only thing that could open it. The floating menu opens it at
   every width now, so the panel itself is unconditional and only the burger
   stays phone-only. Closed state is the `hidden` attribute, which a class
   selector would otherwise beat, hence the explicit [hidden] rule. */
.burger { display: none; }
.drawer[hidden], .scrim[hidden] { display: none; }

@media (max-width: 52rem) {
  .dochead__nav { display: none; }

  .burger {
    display: flex; align-items: center; gap: 0.75rem;
    width: 100%; min-height: 3rem;
    padding: 0.5rem 0; margin: 0;
    background: none; border: 0; border-bottom: 1px solid var(--rule);
    /* the burger IS the navigation on a phone, so it matches what the nav
       row became on a desktop rather than staying at the old caption size */
    color: var(--nav-ink); cursor: pointer;
    font-family: var(--sans); font-size: 0.875rem; font-weight: 500;
    letter-spacing: 0.13em; text-transform: uppercase;
  }

  .burger__bars { display: grid; gap: 4px; width: 1.125rem; }
  .burger__word { line-height: 1; }
  .burger__bars i { display: block; height: 1px; background: var(--nav-ink); transition: transform 260ms ease, opacity 200ms ease; }
  .burger[aria-expanded="true"] .burger__bars i:nth-child(1) { transform: translateY(5px) rotate(45deg); }
  .burger[aria-expanded="true"] .burger__bars i:nth-child(2) { opacity: 0; }
  .burger[aria-expanded="true"] .burger__bars i:nth-child(3) { transform: translateY(-5px) rotate(-45deg); }

}

.scrim {
  display: block; position: fixed; inset: 0; z-index: 90;
  background: rgba(18, 22, 28, 0.5);
  opacity: 0; transition: opacity 320ms ease;
}
.scrim.is-open { opacity: 1; }

/* left to right, and it holds its own scroll if the list ever grows */
.drawer {
  display: flex; flex-direction: column;
  position: fixed; z-index: 95;
  top: 0; bottom: 0; left: 0;
  width: min(20rem, 86vw);
  padding: max(1.25rem, env(safe-area-inset-top)) 1.5rem
           max(1.5rem, env(safe-area-inset-bottom));
  background: var(--navy); color: var(--on-navy);
  overflow-y: auto; overscroll-behavior: contain;
  transform: translateX(-100%);
  transition: transform 380ms cubic-bezier(.22, .9, .24, 1);
}
.drawer.is-open { transform: none; }
.drawer:focus { outline: none; }

.drawer__top { display: flex; justify-content: space-between; align-items: center;
  gap: 1rem; padding-bottom: 1rem; border-bottom: 1px solid var(--rule-navy); }
.drawer__top .micro { color: var(--on-navy); white-space: nowrap; }
.drawer__top .micro b { color: var(--gold); font-weight: 500; }

.drawer__close { min-height: 2.75rem; padding: 0 0.25rem; background: none; border: 0;
  color: var(--gold); font-family: var(--sans); font-size: var(--t-label);
  letter-spacing: 0.24em; text-transform: uppercase; cursor: pointer; }

.drawer__list { list-style: none; margin: 0; padding: 0; }
.drawer__list a {
  display: grid; grid-template-columns: 2rem 1fr; gap: 1rem; align-items: baseline;
  min-height: 3.5rem; padding: 1rem 0;
  border-bottom: 1px solid var(--rule-navy);
}
.drawer__n { font-family: var(--mono); font-size: var(--t-label); color: var(--gold); }
.drawer__t { font-family: var(--serif); font-size: var(--t-d3); line-height: 1.2; }
.drawer__list a[aria-current="page"] .drawer__t { color: var(--gold); }

.drawer__guide { display: block; margin-top: auto; padding-top: 1.5rem; }
.drawer__guide .micro { color: rgba(237, 231, 218, 0.66); }
.drawer__guide-t { margin: 0.5rem 0 0.375rem; font-family: var(--serif);
  font-size: var(--t-d3); color: var(--on-navy); }

/* the sequence runs off transitions, so honour the setting properly */
@media (prefers-reduced-motion: reduce) {
  .drawer, .scrim, .burger__bars i, .fl { transition: none; }
}

/* the page must not scroll behind an open drawer */
body.is-locked { overflow: hidden; }

/* ============================================================
   17. PHONE LEGIBILITY
   A phone gets read outdoors, one-handed, at whatever brightness the
   screen happens to be on. The mid tones that hold up on a monitor go
   milky in daylight, so the secondary text darkens below tablet.

   Tokens only. Nothing here changes a rule, so the composition is
   identical and only the ink gets heavier.
   ============================================================ */

@media (max-width: 52rem) {
  :root {
    --set: #33312b;        /* was #4a473f. 11.4:1 on bone, up from 8.0 */
    --stone-ink: #4f4b45;  /* was #6f6a5f. 7.6:1, up from 4.7 */
    --camel-ink: #5f4829;  /* was #7f6339. 7.5:1, up from 4.9 */
    --stone-lift: #b3ada0; /* secondary on navy, lifted for the same reason */
  }

  /* Poppins at 300 is thin on a phone. One step up costs nothing and it is
     the single biggest readability gain outdoors. */
  body { font-weight: 400; }
  .set, .ruled p, .disclosure, .reg--wide .reg__m { font-weight: 400; }
}


/* ============================================================
   18. THE ROOM PAGES

   Twelve pages, one per room, carrying a chapter of the guide in full. The
   whole point is that a man searching "what to wear to a funeral" lands on
   something he can read, rather than on a download.

   The download itself sits at the top right and the bottom right, so it is
   in reach whether he has decided in ten seconds or read the lot.
   ============================================================ */

/* the header: title left, download right, and they stack on a phone */
.rm-head { display: flex; flex-wrap: wrap; align-items: flex-end;
           justify-content: space-between; gap: 1.5rem clamp(1.5rem, 4vw, 3rem); }
.rm-h1 { font-size: clamp(2rem, 1.2rem + 3.2vw, 3.5rem); }
.rm-dl { margin: 0; flex-shrink: 0; }
.rm-what { font-size: var(--t-d3); font-family: var(--serif); color: var(--set); }
.rm-top .kick a { color: inherit; border-bottom: 1px solid var(--rule-2); }
.rm-top .kick a:hover { color: var(--camel-ink); }

/* the plates. Navy sheets on bone paper, so they carry their own edge. */
.rm-plate { margin: 0; }
.rm-plate + .rm-plate { margin-top: var(--colgap); }
@media (min-width: 56rem) { .rm-plate + .rm-plate { margin-top: 0; } }
.rm-plate img { display: block; width: 100%; height: auto;
                border: 1px solid var(--rule-2); background: var(--navy); }
.rm-plate figcaption { margin-top: 0.625rem; color: var(--stone-ink); }

/* the chapter itself */
.rm-body { max-width: 46rem; }
.rm-sec { padding-block: clamp(1.5rem, 3.5vw, 2.25rem); }
.rm-sec + .rm-sec { border-top: 1px solid var(--rule); }
.rm-sec__h { margin: 0 0 0.75rem; }
.rm-sec__b { font-family: var(--serif); font-size: var(--t-read); line-height: 1.62;
             color: var(--char); }
.rm-sec__b > * { margin: 0; }
.rm-sec__b > * + * { margin-top: 1rem; }
.rm-lede { font-size: var(--t-d3); line-height: 1.35; }
.rm-q { margin: 1.25rem 0 0; padding-left: 1.125rem; border-left: 2px solid var(--camel);
        font-style: italic; color: var(--set); }

/* How to act is a list of pairs, so it is set as one */
.rm-acts { display: grid; gap: 1.125rem; }
/* a label and its instruction are one thing. Do not let a print or a column
   split them apart. */
.rm-act { break-inside: avoid; }
.rm-act__k { margin: 0 0 0.2rem; font-family: var(--sans); font-weight: 500;
             font-size: var(--t-label); letter-spacing: 0.14em; text-transform: uppercase;
             color: var(--camel-ink); }
.rm-act__v { margin: 0; }

/* previous and next, because twelve rooms should feel like one thing */
.rm-near { display: grid; gap: 1px; background: var(--rule); border-block: 1px solid var(--rule); }
@media (min-width: 42rem) { .rm-near { grid-template-columns: 1fr 1fr; } }
.rm-near__a { display: grid; gap: 0.35rem; padding: 1.25rem 0.25rem; background: var(--bone);
              text-decoration: none; color: inherit; transition: background 0.2s ease; }
.rm-near__a:hover { background: var(--bone-2); }
.rm-near__a--n { text-align: left; }
@media (min-width: 42rem) { .rm-near__a--n { text-align: right; padding-inline: 0.25rem; } }
.rm-near__t { font-family: var(--serif); font-size: var(--t-d3); }

/* ============================================================
   19. NIGHT PAPER

   Dark mode is not a grey theme. The ground is the charcoal ink deepened,
   so it reads as the same paper at night, and the navy strips do not move
   at all. A navy plate on navy paper has nothing to sit against, and the
   twenty-four plates are the one asset here nothing else has.

   It is nothing but a token flip. That is deliberate: it is what lets the
   same values serve the system setting and the reader's own choice without
   a single rule being written twice. Sections 1 through 18 never learn that
   dark mode exists.

   Three ways in, in order of authority:
     data-theme="dark"    the reader chose night
     data-theme="light"   the reader chose day, and it beats the system
     the system setting   when the reader has expressed no preference
   ============================================================ */
:root {
  /* the night values, written once */
  --dk-bone: #14130e;      /* the char hue deepened, not a neutral grey */
  --dk-bone-2: #1a1913;
  --dk-rule: #34322a;
  --dk-rule-2: #47443a;
  --dk-char: #efe9dd;      /* what was the ground is now the ink */
  --dk-set: #cdc7b8;
  --dk-stone: #a09a8c;
  --dk-stone-ink: #a8a294;
  /* camel is a dark brown and disappears on dark paper. Gold, already the
     accent on every navy ground, takes over. */
  --dk-camel: #c9a268;
  /* The same 0.955 veil that makes the mark a whisper on bone lets it shout
     here, because a bone mark against near black is a far bigger jump than a
     charcoal mark against bone. */
  --dk-wm-paper: rgba(20, 19, 14, 0.975);
  --dk-wm-paper-2: rgba(26, 25, 19, 0.972);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bone: var(--dk-bone); --bone-2: var(--dk-bone-2);
    --rule: var(--dk-rule); --rule-2: var(--dk-rule-2);
    --char: var(--dk-char); --set: var(--dk-set);
    --stone: var(--dk-stone); --stone-ink: var(--dk-stone-ink);
    --camel: var(--dk-camel); --camel-ink: var(--dk-camel);
    --on-navy: var(--dk-char);
    --nav-ink: var(--dk-char);
    --wm-mark: url("/assets/wm-light.png");
    --wm-paper: var(--dk-wm-paper); --wm-paper-2: var(--dk-wm-paper-2);
  }
}

:root[data-theme="dark"] {
  --bone: var(--dk-bone); --bone-2: var(--dk-bone-2);
  --rule: var(--dk-rule); --rule-2: var(--dk-rule-2);
  --char: var(--dk-char); --set: var(--dk-set);
  --stone: var(--dk-stone); --stone-ink: var(--dk-stone-ink);
  --camel: var(--dk-camel); --camel-ink: var(--dk-camel);
  --on-navy: var(--dk-char);
  --nav-ink: var(--dk-char);
  --wm-mark: url("/assets/wm-light.png");
  --wm-paper: var(--dk-wm-paper); --wm-paper-2: var(--dk-wm-paper-2);
}

/* ============================================================
   20. THE TOGGLE

   Day and night, in the register's own voice: a small mark and a word. The
   word says what the button will DO, not what is currently on, because a
   control labelled with its own state is the oldest confusion in interface
   design.

   It appears twice, in the nav row and in the phone drawer, because the nav
   row is not on screen below tablet. Both are driven by the same handler.
   ============================================================ */
.tog {
  display: inline-flex; align-items: center; gap: 0.5rem;
  margin: 0 0 0 clamp(0.875rem, 2.4vw, 2.25rem); padding: 0 0 2px;
  background: none; border: 0; border-bottom: 1px solid transparent;
  font-family: var(--sans); font-size: 0.875rem; font-weight: 500;
  letter-spacing: 0.13em; text-transform: uppercase;
  color: var(--nav-ink); cursor: pointer;
}
.tog:hover { border-bottom-color: var(--camel); }

/* half filled, which is the universal mark for contrast and is drawn rather
   than borrowed from an emoji font that renders differently everywhere */
.tog__m {
  width: 0.75rem; height: 0.75rem; border-radius: 50%;
  border: 1px solid currentColor;
  background: linear-gradient(90deg, currentColor 50%, transparent 50%);
}
[data-theme="dark"] .tog__m { transform: rotate(180deg); }

/* the word swaps between Day and Night, so it is held to the width of the
   longer one and the row does not jump when it changes */
.tog__w { min-width: 3.4em; text-align: left; }

/* Also unconditional now. Once the drawer is reachable from mid-page at any
   width, the header toggle has scrolled away, and the drawer is the only
   place left to change day or night. */
.drawer__tog { display: block; padding: 0.875rem 0 0; }
.drawer__tog .tog { margin: 0; color: var(--on-navy); }
.drawer__tog .tog:hover { border-bottom-color: var(--gold); }

/* every decade, on every decade page */
.decades { display: flex; flex-wrap: wrap; gap: 0.5rem 1.5rem; margin-top: 0.875rem; }
.decades a { font-family: var(--sans); font-size: var(--t-meta); font-weight: 400;
  letter-spacing: 0.06em; color: var(--stone-ink);
  padding-bottom: 2px; border-bottom: 1px solid transparent; }
.decades a:hover { color: var(--char); border-bottom-color: var(--camel); }
.decades a[aria-current="page"] { color: var(--char); border-bottom-color: var(--camel); }

/* ============================================================
   21. CONSENT

   Clarity records sessions, so it does not start until the reader says yes.
   The notice sits at the foot of the page rather than across the middle of
   it: this site does not put anything between a man and what he came to
   read, and a modal that blocks the page would be the first thing to
   contradict the argument the page is making.

   Allow and No thanks are the same size, the same weight and one tab apart.
   A decline that is harder to reach than an accept is not a choice.
   ============================================================ */
.consent {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 2147482000;          /* under the door, which lifts before this matters */
  background: var(--bone-2);
  border-top: 1px solid var(--rule-2);
  padding: clamp(0.875rem, 2vw, 1.25rem) var(--pad);
}
.consent[hidden] { display: none; }

.consent__in {
  display: flex; flex-wrap: wrap; align-items: center;
  justify-content: space-between; gap: 0.875rem clamp(1.5rem, 4vw, 3rem);
  max-width: 72rem; margin-inline: auto;
}

.consent__t {
  margin: 0; max-width: 60ch;
  font-family: var(--sans); font-weight: 300;
  font-size: var(--t-meta); line-height: 1.55; color: var(--set);
}

.consent__acts { display: flex; gap: 0.75rem; margin: 0; flex-shrink: 0; }

.consent__b {
  font-family: var(--sans); font-size: var(--t-label); font-weight: 500;
  letter-spacing: 0.16em; text-transform: uppercase;
  padding: 0.6875rem 1.25rem; cursor: pointer;
  background: none; color: var(--char);
  border: 1px solid var(--rule-2);
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.consent__b:hover { border-color: var(--camel); color: var(--camel-ink); }
.consent__b--yes { background: var(--char); border-color: var(--char); color: var(--bone); }
.consent__b--yes:hover { background: var(--camel); border-color: var(--camel); color: var(--bone); }

.docfoot__base a { border-bottom: 1px solid var(--rule-2); }
.docfoot__base a:hover { color: var(--camel-ink); }

/* cache key d88ce34b was poisoned at the edge during a deploy race. See bin/verify_live.py */

/* ============================================================
   22. THE FLOATING MENU

   The header is sticky in intent but not in fact: body { overflow-x: hidden }
   further up makes the body a scroll container and silently kills position
   sticky. Rather than unpick that, the navigation comes back on its own
   terms. Once the masthead is well off screen a navy pill rises out of the
   bottom margin, and pressing it widens the pill until the whole nav row is
   sitting inside it.

   Bottom centre, not top centre. Top centre is exactly where the text column
   is, and anything parked there cuts a hole through the middle of a sentence.
   The bottom margin is empty by construction and it is where a thumb already
   is on a phone.

   The width is animated, which is normally a bad idea, but it is one element
   with nothing beneath it in flow, and width is the whole effect: the row
   has to look like it came out of the pill rather than appearing over it.
   overflow: hidden is what makes that read, by clipping the row until there
   is room for it.
   ============================================================ */

.fl {
  position: fixed; left: 50%; bottom: 1.75rem; z-index: 80;
  /* set from the trigger's real width on load, so the collapsed pill is
     exactly as wide as its contents in whatever font actually rendered */
  width: var(--fl-shut, 7rem);
  display: flex; align-items: center;
  background: var(--navy); color: var(--on-navy);
  border-radius: 999px; overflow: hidden;
  box-shadow: 0 6px 24px rgba(19, 35, 63, 0.28);
  opacity: 0; visibility: hidden; transform: translate(-50%, 2rem);
  transition: width 420ms cubic-bezier(.22, .9, .24, 1),
              transform 380ms cubic-bezier(.22, .9, .24, 1),
              opacity 300ms ease, visibility 380ms;
}
.fl.is-in { opacity: 1; visibility: visible; transform: translate(-50%, 0); }
.fl.is-open { width: min(72rem, calc(100vw - 2 * var(--pad))); }

/* the trigger keeps its own width so the mark never shifts as the pill grows */
.fl__t {
  flex: 0 0 auto; display: flex; align-items: center; gap: 0.5rem;
  padding: 0.5625rem 1.25rem 0.5625rem 0.875rem;
  background: none; border: 0; color: inherit; cursor: pointer;
  font-family: var(--sans); font-size: 0.6875rem; font-weight: 500;
  letter-spacing: 0.18em; text-transform: uppercase; white-space: nowrap;
}
.fl__m { display: block; width: 1.75rem; height: auto; opacity: 0.95; }
.fl__w { min-width: 3.2em; text-align: left; }
.fl__t:focus-visible { outline: 2px solid var(--gold); outline-offset: -4px; }

/* The row. visibility, not display, so it is out of the tab order and off the
   accessibility tree while it is shut without collapsing the layout the width
   animation is measured against. It fades in only once the pill has opened
   far enough to hold it, and leaves immediately on the way back. */
.fl__nav {
  display: flex; align-items: center; justify-content: space-between;
  flex: 1 1 auto; gap: clamp(0.875rem, 2.4vw, 2.25rem);
  padding-right: 1.5rem; white-space: nowrap;
  opacity: 0; visibility: hidden;
  transition: opacity 180ms ease, visibility 180ms;
}
.fl.is-open .fl__nav {
  opacity: 1; visibility: visible;
  transition: opacity 240ms ease 180ms, visibility 240ms 180ms;
}
.fl__grp { display: flex; align-items: center; gap: clamp(0.875rem, 2vw, 2rem); }

/* the nav row's own type, on navy instead of on paper */
.fl__nav a {
  font-size: 0.8125rem; letter-spacing: 0.13em; font-weight: 500;
  text-transform: uppercase; color: var(--on-navy);
  padding-bottom: 2px; border-bottom: 1px solid transparent;
}
.fl__nav a:hover, .fl__nav a[aria-current="page"] { border-bottom-color: var(--gold); }
.fl__nav a[aria-current="page"] { color: var(--gold); }
.fl__nav .tog { margin: 0; color: var(--on-navy); }
.fl__nav .tog:hover { border-bottom-color: var(--gold); }

/* At full size the row wants about 1130px, so on anything short of a large
   desktop it was being clipped by the pill's own overflow: hidden and the
   Night toggle simply fell off the end. It tightens instead of falling back,
   because falling back to the drawer on a 1200px laptop is not a desktop
   experience. Measured, not guessed: bin/check.py asserts it fits. */
@media (max-width: 82rem) {
  .fl__nav { gap: 1rem; padding-right: 1.125rem; }
  .fl__grp { gap: 1rem; }
  .fl__nav a { font-size: 0.75rem; letter-spacing: 0.09em; }
}

/* Below this even the tight row does not fit, so the pill goes back to being
   a button that opens the phone drawer. The JS reads the same breakpoint. */
@media (max-width: 62rem) {
  .fl.is-open { width: var(--fl-shut, 7rem); }
  .fl__nav { display: none; }
}

@media (max-width: 52rem) {
  .fl { bottom: max(1.25rem, env(safe-area-inset-bottom)); }
}

/* an open drawer means the pill has done its job */
body.is-locked .fl { opacity: 0; visibility: hidden; }

/* On night paper the navy pill sits on near black and loses its edge, and a
   drop shadow does nothing on a dark ground. The gold hairline gives it a
   boundary instead. This is the one place dark mode needs more than the
   token flip, because the pill is the only navy element that floats over the
   paper rather than being a strip anchored to it. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .fl {
    border: 1px solid rgba(201, 162, 104, 0.42);
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.55);
  }
}
:root[data-theme="dark"] .fl {
  border: 1px solid rgba(201, 162, 104, 0.42);
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.55);
}
