/* ==========================================================================
   Шляпа — design language: «Бумажки» (Slips)
   --------------------------------------------------------------------------
   The game is played in the evening: green felt, lamplight, and coloured
   paper slips — the brightest things on the table. Ink speaks, slips play.
   The evening is the primary theme; day is a cool porcelain score sheet
   lying on the same table. The game is playful, the score is honest:
   everything that speaks may play, everything that counts stays strict.

   Self-contained on purpose. No CDN, no third-party request. The pages carry
   no JavaScript at all; /play, which is an app rather than a document, is the
   one exception, and it borrows this file wholesale.
   Playfair Display is self-hosted from /assets/fonts (OFL).

   Contents
     1. Fonts
     2. Tokens (evening first, day via prefers-color-scheme: light)
     3. Reset & base
     4. Layout: the table and the sheet
     5. Masthead & footer
     6. Type
     7. Buttons & links
     8. Word slips & appliqué
     9. Sections & figures
    10. Prose (terms, policies)
    11. Data: tables, stat tiles, bar charts
   ========================================================================== */

/* 1. Fonts =============================================================== */

@font-face {
  font-family: "Playfair Display";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/assets/fonts/playfair-cyrillic.woff2") format("woff2");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: "Playfair Display";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/assets/fonts/playfair-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+2000-206F, U+2212;
}
@font-face {
  font-family: "Playfair Display";
  font-style: italic;
  font-weight: 400 700;
  font-display: swap;
  src: url("/assets/fonts/playfair-italic-cyrillic.woff2") format("woff2");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: "Playfair Display";
  font-style: italic;
  font-weight: 400 700;
  font-display: swap;
  src: url("/assets/fonts/playfair-italic-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+2000-206F, U+2212;
}

/* 2. Tokens ==============================================================
   Evening is the default. All contrast ratios are measured, not estimated. */

:root {
  /* -- the room and the felt ------------------------------------------- */
  --mat:          #0B110E;
  --paper:        #17251D;
  --paper-raised: #1E2F25;
  --paper-sunk:   #121C16;

  /* -- ink under lamplight ---------------------------------------------- */
  --ink:       #F1EBDC;   /* 13.4:1 on felt */
  --ink-muted: #9FAC9C;   /*  6.7:1 */
  --rule:      #2C3C31;

  /* -- the brass hat band ------------------------------------------------
     Small and precise: link underlines, active nav, focus rings.
     Never fills, never large surfaces. */
  --brass:      #C9A24B;  /* 6.6:1 on felt */
  --brass-text: #C9A24B;

  /* -- slips -------------------------------------------------------------
     Physical paper: identical day and night. In the evening they are the
     brightest spots on the felt (all >= 7.6:1). Fixed roles: rose —
     navigation, lilac — about the game, honey — words, sky — time. */
  --slip-rose:  #E8A79B;
  --slip-honey: #E3AC3F;
  --slip-sky:   #A9C8D6;
  --slip-lilac: #BFABD6;
  --slip-ink:   #322824;  /* >= 6.8:1 on every slip */

  /* text accents in slip colours: at night, the pastel itself */
  --rose-deep:  #E8A79B;
  --honey-deep: #E3AC3F;
  --sky-deep:   #A9C8D6;
  --lilac-deep: #BFABD6;

  /* -- data marks --------------------------------------------------------
     In the evening the mark is the slip itself; by day it condenses. */
  --mark-honey: #E3AC3F;
  --mark-sky:   #A9C8D6;
  --mark-lilac: #BFABD6;
  --mark-track: #24332A;

  /* -- buttons: the lamplight pill -------------------------------------- */
  --btn-bg: #F1EBDC;
  --btn-fg: #17251D;

  /* -- light ------------------------------------------------------------- */
  --shadow-slip: 0 3px 10px rgba(0, 0, 0, 0.45);
  --shadow-sheet: 0 24px 70px rgba(0, 0, 0, 0.6);
  --lamp: radial-gradient(ellipse 70% 45% at 50% -5%, rgba(241, 235, 220, 0.07), transparent 70%);
  /* slip shadows follow the torn contour: drop-shadow, never box-shadow */
  --slip-filter: drop-shadow(0 2px 2px rgba(0, 0, 0, 0.4)) drop-shadow(0 8px 14px rgba(0, 0, 0, 0.3));
  /* appliqué at the edge of lamplight */
  --decor-o: 0.5;

  /* drawings float on the felt at night; the paper card is a day thing */
  --print-bg: transparent;
  --print-border: transparent;
  --print-pad: 0;
  --print-shadow: none;

  /* -- torn edges: three rip variants, cycled by nth-child --------------- */
  --tear-a: polygon(1% 8%, 9% 2%, 22% 6%, 37% 1%, 52% 5%, 68% 0%, 83% 5%, 95% 1%, 99% 22%, 96% 42%, 100% 63%, 97% 84%, 99% 95%, 85% 92%, 70% 98%, 54% 93%, 38% 99%, 22% 94%, 8% 99%, 2% 88%, 4% 62%, 0% 38%);
  --tear-b: polygon(3% 2%, 18% 7%, 33% 2%, 49% 6%, 64% 1%, 79% 6%, 93% 2%, 98% 14%, 95% 38%, 99% 58%, 96% 80%, 99% 96%, 84% 94%, 68% 99%, 52% 94%, 35% 98%, 19% 93%, 6% 97%, 1% 78%, 4% 55%, 1% 30%);
  --tear-c: polygon(2% 12%, 12% 4%, 27% 8%, 43% 2%, 58% 7%, 74% 2%, 88% 7%, 97% 3%, 99% 28%, 95% 50%, 99% 74%, 96% 94%, 80% 97%, 63% 92%, 46% 98%, 29% 93%, 13% 98%, 3% 93%, 1% 70%, 3% 45%, 0% 22%);

  /* -- torn edges, at the size of a button ------------------------------
     The three above are cut for word-sized paper: their percentages are of
     the box, so the same 5% that bites 3px out of a word slip cuts a 17px
     pennant out of a 340px one. These are the same idea at that scale —
     many small bites, and far less wander along the long sides than across
     the short ones. Five, because no two pieces of paper are torn alike and
     five is enough that a screenful of them does not repeat.

     They began in static/play/app.css, for the slips on its home screen;
     they are here now because /duel needs them too, and a torn edge is part
     of the language rather than of one program. */
  --rip-1: polygon(0% 2.2%, 11.1% 2%, 22.2% 4.2%, 33.3% 4.3%, 44.4% 3.6%, 55.6% 1.5%, 66.7% 1.8%, 77.8% 1.8%, 88.9% 4.5%, 100% 4.4%, 99.6% 33.3%, 99.4% 66.7%, 100% 96.2%, 88.9% 99.1%, 77.8% 99.2%, 66.7% 95.9%, 55.6% 97.2%, 44.4% 95.4%, 33.3% 99.1%, 22.2% 98%, 11.1% 96.3%, 0% 97.4%, 0.1% 66.7%, 0.1% 33.3%);
  --rip-2: polygon(0% 2%, 12.5% 0.3%, 25% 3%, 37.5% 4.3%, 50% 2.5%, 62.5% 3.1%, 75% 1.6%, 87.5% 4.6%, 100% 4.4%, 98.3% 25%, 99.9% 50%, 98.7% 75%, 100% 97.6%, 87.5% 98.8%, 75% 98.5%, 62.5% 98.5%, 50% 99.7%, 37.5% 95.6%, 25% 97.2%, 12.5% 96.6%, 0% 97.2%, 0.5% 75%, 0.6% 50%, 1.2% 25%);
  --rip-3: polygon(0% 1%, 9.1% 1.6%, 18.2% 1.5%, 27.3% 2.3%, 36.4% 1%, 45.5% 1.3%, 54.5% 0.8%, 63.6% 4.1%, 72.7% 4.1%, 81.8% 2.4%, 90.9% 4.3%, 100% 2.2%, 99.3% 33.3%, 99.1% 66.7%, 100% 99.9%, 90.9% 99.7%, 81.8% 99.5%, 72.7% 95.7%, 63.6% 96.5%, 54.5% 96.9%, 45.5% 96.8%, 36.4% 95.3%, 27.3% 97.6%, 18.2% 98.7%, 9.1% 99.1%, 0% 98.9%, 1.6% 66.7%, 0.1% 33.3%);
  --rip-4: polygon(0% 4%, 14.3% 4.3%, 28.6% 2.5%, 42.9% 4%, 57.1% 0.1%, 71.4% 3.9%, 85.7% 3.2%, 100% 2.2%, 98.7% 33.3%, 99.5% 66.7%, 100% 98%, 85.7% 96%, 71.4% 95%, 57.1% 95.2%, 42.9% 96.3%, 28.6% 96.8%, 14.3% 99.2%, 0% 96.2%, 0% 66.7%, 0.4% 33.3%);
  --rip-5: polygon(0% 2.2%, 10% 1.8%, 20% 3.5%, 30% 2.3%, 40% 1.1%, 50% 3.4%, 60% 3.8%, 70% 3.6%, 80% 3.1%, 90% 0.2%, 100% 1.4%, 98.3% 25%, 98.7% 50%, 98.5% 75%, 100% 97.7%, 90% 97.3%, 80% 97.1%, 70% 99.1%, 60% 98.3%, 50% 98%, 40% 95.3%, 30% 96.8%, 20% 96.9%, 10% 97%, 0% 96.2%, 1.8% 75%, 0.3% 50%, 0.2% 25%);

  /* -- type -------------------------------------------------------------
     Playfair speaks, Georgia tells, the system sans counts. */
  --display-face: "Playfair Display", Georgia, "Noto Serif", serif;
  --serif: Georgia, "Iowan Old Style", "Palatino Linotype", "Book Antiqua",
           "Noto Serif", "Liberation Serif", "Times New Roman", serif;
  --sans:  system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue",
           Arial, sans-serif;
  --mono:  ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
           "Liberation Mono", monospace;

  --t-display: clamp(2.9rem, 8vw, 5.1rem);
  --t-title:   clamp(1.9rem, 4vw, 2.7rem);
  --t-section: clamp(1.45rem, 2.6vw, 1.9rem);
  --t-lead:    clamp(1.0625rem, 1.6vw, 1.1875rem);
  --t-body:    1.0625rem;
  --t-small:   0.875rem;
  --t-micro:   0.75rem;

  /* -- space (4px base) -------------------------------------------------- */
  --s1: 0.25rem;  --s2: 0.5rem;   --s3: 0.75rem;  --s4: 1rem;
  --s5: 1.5rem;   --s6: 2rem;     --s7: 3rem;     --s8: 4.5rem;
  --s9: 7rem;

  --measure: 34rem;          /* prose line length, ~70 characters */
  --page: 68rem;             /* outer container */
  --r-card: 10px;
  --r-pill: 999px;
}

/* Day: a porcelain score sheet on the same table. Cool, never cream.
   ------------------------------------------------------------------------
   Two ways for day to come on, and the palette is written twice because CSS
   has no way to share one declaration block between a media query and a
   selector. THE TWO BLOCKS MUST STAY IN STEP — this one is the original,
   and the copy under :root[data-theme="day"] directly below carries the
   pointer back here. Nothing but tokens may live in either.

   1. The system asks for it, and nothing has overridden that. This is the
      whole story for the site, whose pages carry no JavaScript and so have
      no memory of a choice.
   2. /play was told to, by hand. It is an app, it has a switch, and it
      writes data-theme on <html>: "day" or "night" for a choice made,
      nothing at all for "follow the system". */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="night"]) {
    --mat:          #3C4A41;
    --paper:        #F4F5F1;
    --paper-raised: #FBFCF9;
    --paper-sunk:   #EAEDE6;

    --ink:       #1D2823;   /* 13.9:1 on porcelain */
    --ink-muted: #5F6B63;   /*  5.1:1 */
    --rule:      #D8DED4;

    --brass:      #C9A24B;
    --brass-text: #7E621C;  /* 5.3:1 — brass as running text needs depth */

    --rose-deep:  #9C4A43;  /* 5.5:1 */
    --honey-deep: #8A650F;  /* 4.9:1 */
    --sky-deep:   #3F6675;  /* 5.7:1 */
    --lilac-deep: #6B5588;  /* 5.9:1 */

    --mark-honey: #A97812;  /* 3.6:1 as a mark */
    --mark-sky:   #567F8E;  /* 4.0:1 */
    --mark-lilac: #6B5588;  /* 5.9:1 */
    --mark-track: #E2E7DD;

    --btn-bg: #1D2823;
    --btn-fg: #F4F5F1;

    --shadow-slip: 0 2px 6px rgba(29, 40, 35, 0.2);
    --shadow-sheet: 0 24px 70px rgba(10, 16, 13, 0.5);
    --lamp: none;
    --slip-filter: drop-shadow(0 1px 1px rgba(29, 40, 35, 0.2)) drop-shadow(0 5px 10px rgba(29, 40, 35, 0.16));
    --decor-o: 1;

    --print-bg: #FBFCF9;
    --print-border: var(--rule);
    --print-pad: var(--s4);
    --print-shadow: var(--shadow-slip);
  }
}

/* Day asked for by hand, on a device whose system says night. The copy of
   the block above — keep the two in step. */
:root[data-theme="day"] {
  --mat:          #3C4A41;
  --paper:        #F4F5F1;
  --paper-raised: #FBFCF9;
  --paper-sunk:   #EAEDE6;

  --ink:       #1D2823;
  --ink-muted: #5F6B63;
  --rule:      #D8DED4;

  --brass:      #C9A24B;
  --brass-text: #7E621C;

  --rose-deep:  #9C4A43;
  --honey-deep: #8A650F;
  --sky-deep:   #3F6675;
  --lilac-deep: #6B5588;

  --mark-honey: #A97812;
  --mark-sky:   #567F8E;
  --mark-lilac: #6B5588;
  --mark-track: #E2E7DD;

  --btn-bg: #1D2823;
  --btn-fg: #F4F5F1;

  --shadow-slip: 0 2px 6px rgba(29, 40, 35, 0.2);
  --shadow-sheet: 0 24px 70px rgba(10, 16, 13, 0.5);
  --lamp: none;
  --slip-filter: drop-shadow(0 1px 1px rgba(29, 40, 35, 0.2)) drop-shadow(0 5px 10px rgba(29, 40, 35, 0.16));
  --decor-o: 1;

  --print-bg: #FBFCF9;
  --print-border: var(--rule);
  --print-pad: var(--s4);
  --print-shadow: var(--shadow-slip);
}

/* 3. Reset & base ======================================================== */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}

body {
  margin: 0;
  /* Russian words are long and the display size is large; never let a single
     word push the page wider than the viewport. */
  overflow-wrap: break-word;
  background: var(--mat);
  color: var(--ink);
  font-family: var(--serif);
  font-size: var(--t-body);
  line-height: 1.65;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; height: auto; display: block; }

::selection { background: var(--slip-honey); color: var(--slip-ink); }

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

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

/* 4. Layout ==============================================================
   The page is a table in a room. In the evening the sheet IS the felt;
   by day it is the score sheet lying on it. On phones the sheet fills
   the screen; the room shows only around a wide viewport. */

.sheet {
  max-width: 86rem;
  margin-inline: auto;
  background: var(--paper);
  min-height: 100vh;
}
@media (min-width: 64rem) {
  body { padding: var(--s6); }
  .sheet { border-radius: 8px; box-shadow: var(--shadow-sheet); overflow: hidden; }
}

.wrap {
  width: 100%;
  max-width: var(--page);
  margin-inline: auto;
  padding-inline: var(--s5);
}
.wrap--narrow { max-width: 46rem; }

.stack > * + * { margin-top: var(--s4); }
.stack--loose > * + * { margin-top: var(--s6); }

/* 5. Masthead & footer =================================================== */

.masthead { border-bottom: 1px solid var(--rule); }
.masthead__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s3) var(--s5);
  padding-block: var(--s4);
}
.masthead__brand {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  font-family: var(--display-face);
  font-weight: 600;
  font-size: 1.3rem;
  color: var(--ink);
  text-decoration: none;
  margin-right: auto;
}
.masthead__brand::before {
  content: "";
  width: 15px;
  height: 10px;
  background: var(--slip-rose);
  border-radius: 1px 4px 2px 3px;
  clip-path: var(--tear-c);
  transform: rotate(-6deg);
  filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.3));
}
.masthead__brand:hover { color: var(--ink); }
.masthead__nav {
  display: flex;
  flex-wrap: wrap;
  min-width: 0;
  gap: var(--s3) var(--s5);
  font-family: var(--sans);
  font-size: var(--t-small);
}
.masthead__nav a {
  color: var(--ink-muted);
  text-decoration: none;
  border-bottom: 2px solid transparent;
  padding-bottom: 2px;
}
.masthead__nav a:hover,
.masthead__nav a[aria-current="page"] {
  color: var(--ink);
  border-bottom-color: var(--brass);
}

.footer {
  margin-top: var(--s9);
  border-top: 1px solid var(--rule);
  background: var(--paper-sunk);
  font-family: var(--sans);
  font-size: var(--t-small);
  color: var(--ink-muted);
}
.footer__inner {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3) var(--s6);
  padding-block: var(--s6);
}
.footer a { color: var(--ink-muted); }
.footer a:hover { color: var(--ink); }
.footer__spacer { margin-left: auto; }

/* 6. Type ================================================================ */

h1, h2, h3, h4 {
  overflow-wrap: break-word;
  line-height: 1.15;
  margin: 0;
  text-wrap: balance;
}

.display {
  font-family: var(--display-face);
  font-weight: 500;
  font-size: var(--t-display);
  line-height: 1.04;
  letter-spacing: -0.01em;
}
.title { font-family: var(--display-face); font-weight: 600; font-size: var(--t-title); line-height: 1.1; }
.section__title { font-family: var(--display-face); font-weight: 600; font-size: var(--t-section); line-height: 1.15; }

/* The accent word: Playfair italic underlined by hand with wavy brass.
   One per headline, never more. */
.display em, .title em, .section__title em {
  font-style: italic;
  text-decoration: underline wavy var(--brass);
  text-decoration-thickness: 0.045em;
  text-underline-offset: 0.14em;
  text-decoration-skip-ink: none;
}

.lead {
  font-size: var(--t-lead);
  line-height: 1.6;
  max-width: var(--measure);
}
.muted { color: var(--ink-muted); }

/* The section tab: a torn slip in the section's colour instead of a number.
   Lowercase italic, not small caps — tabs speak, they don't count. */
.eyebrow {
  display: flex;
  align-items: center;
  gap: var(--s3);
  font-family: var(--serif);
  font-style: italic;
  font-size: 0.9375rem;
  color: var(--ink-muted);
  margin: 0 0 var(--s4);
}
.eyebrow::before {
  content: "";
  width: 18px;
  height: 11px;
  flex: none;
  background: var(--eb, var(--slip-rose));
  border-radius: 1px 4px 2px 3px;
  clip-path: var(--tear-b);
  transform: rotate(-5deg);
  filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.3));
}
.eyebrow--center { justify-content: center; }
.eyebrow--lilac { --eb: var(--slip-lilac); }
.eyebrow--honey { --eb: var(--slip-honey); }
.eyebrow--sky   { --eb: var(--slip-sky); }
/* A short brass prefix — «beta», «Sombrero», a step number on a page where
   the steps really are a sequence. */
.eyebrow__num { color: var(--brass-text); font-variant-numeric: tabular-nums; }

.rule {
  border: 0;
  border-top: 1px solid var(--rule);
  margin-block: var(--s7);
}

/* 7. Buttons & links ===================================================== */

/* Links: ink underlined with the brass band. Straight at rest; wavy under
   the cursor — the page smiles only when played with. */
a {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: var(--brass);
  text-decoration-thickness: 2px;
  text-underline-offset: 0.2em;
  transition: text-decoration-color 150ms ease;
}
/* No colour here, deliberately. A link keeps its colour from `a` above, and
   anything wearing a link — a button, a slip — keeps the colour its own
   component gave it. `a:hover` is one specificity point heavier than a class,
   so re-stating the ink here (which changed nothing for a link in running
   text) quietly repainted every one of those: the label of «Играть» became
   exactly the colour of the pill under it, 1:1, and a slip you pressed on the
   phone went from 6.8:1 to 1.8:1 for as long as the tap's hover stuck. */
a:hover {
  text-decoration-color: var(--brass-text);
  text-decoration-style: wavy;
  text-decoration-thickness: 1.5px;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s2);
  font-family: var(--sans);
  font-size: var(--t-small);
  font-weight: 600;
  letter-spacing: 0.03em;
  line-height: 1;
  padding: 0.95em 1.8em;
  border-radius: var(--r-pill);
  border: 1px solid transparent;
  text-decoration: none;
  cursor: pointer;
  transition: transform 150ms ease, background-color 150ms ease,
              border-color 150ms ease;
}
.btn:hover { transform: translateY(-2px) rotate(-1deg); }
.btn:active { transform: translateY(0) rotate(0) scale(0.98); }
.btn--primary {
  background: var(--btn-bg);
  border-color: var(--btn-bg);
  color: var(--btn-fg);
}
.btn--ghost {
  background: transparent;
  border-color: var(--rule);
  color: var(--ink);
}
.btn--ghost:hover { border-color: var(--ink); }

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3);
  align-items: center;
}
.btn-row--center { justify-content: center; }

/* 8. Word slips & appliqué ==============================================
   A slip with a word: real paper. Torn edges, a fold crease down the
   middle (it was folded before going into the hat), paper grain, and a
   shadow that follows the torn contour. */

.ws {
  position: relative;
  display: inline-block;
  font-family: var(--serif);
  font-style: italic;
  font-size: 1.125rem;
  color: var(--slip-ink);
  padding: 0.5em 1.05em 0.58em;
  border-radius: 2px 8px 3px 7px;   /* fallback edge if clip-path is unsupported */
  clip-path: var(--tear, var(--tear-a));
  filter: var(--slip-filter);
  /* The tilt goes last, so it is the slip's own centre it turns about: with
     the offset inside the rotation the slip would swing around a point off
     the paper instead of pivoting where it lies. */
  transform: translateY(var(--ty, 0px)) rotate(var(--rot, -2deg));
  transition: transform 180ms ease;
}
.ws::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(103deg, rgba(255,255,255,0) 45%, rgba(50,40,36,0.13) 49.5%, rgba(255,255,255,0.22) 51.5%, rgba(255,255,255,0) 57%),
    linear-gradient(165deg, rgba(255,255,255,0.26), rgba(255,255,255,0) 40%, rgba(50,40,36,0.07)),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.12 0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}
/* Straightened and lifted, from wherever it was lying — the 2px is added to
   the slip's own offset rather than replacing it, so every slip lifts by the
   same 2px and none of them slides sideways on the way up. */
.ws:hover { transform: translateY(calc(var(--ty, 0px) - 2px)) rotate(0deg); }
.ws--rose  { background: var(--slip-rose); }
.ws--lilac { background: var(--slip-lilac); }
.ws--honey { background: var(--slip-honey); }
.ws--sky   { background: var(--slip-sky); }

.ws-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2) var(--s3);
  align-items: center;
}
.ws-row--center { justify-content: center; }
.ws-row > :nth-child(4n+1) { --rot: -3deg;   --tear: var(--tear-a); }
.ws-row > :nth-child(4n+2) { --rot: 2.5deg;  --tear: var(--tear-b); --ty: 3px; }
.ws-row > :nth-child(4n+3) { --rot: -1.5deg; --tear: var(--tear-c); --ty: -2px; }
.ws-row > :nth-child(4n)   { --rot: 3deg;    --tear: var(--tear-b); }

/* The appliqué: cut coloured paper (scissored, not torn) and halftone dot
   patches bleeding off the hero's edges. Desktop only, never under text.
   In the evening the paper sits at the edge of lamplight (--decor-o). */
.decor {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: var(--decor-o);
  display: none;
}
@media (min-width: 60rem) { .decor { display: block; } }
.decor > span { position: absolute; }
.decor .cut { filter: drop-shadow(0 8px 14px rgba(0, 0, 0, 0.2)); }
/* The solid shapes and dot patches are cut-paper hat silhouettes — hats you
   could play from — clipped by the inline <clipPath> defs the landing page
   carries (original paths, drawn for this site). Each felt hat has a tapered
   crown, a creased top and an upturned brim, so the shape reads as a hat with
   no outline to help it. The three at the right overlap on purpose. */
.decor__tophat { background: var(--slip-rose); clip-path: url(#hat-top); width: clamp(21rem, 30vw, 29rem); aspect-ratio: 1; left: -9rem; top: 11%; transform: rotate(-9deg); }
.decor__sombrero { background: var(--slip-sky); clip-path: url(#hat-sombrero); width: clamp(16.5rem, 24vw, 22.5rem); aspect-ratio: 1; right: -7rem; bottom: -2.5rem; transform: rotate(7deg); }
.decor__fedora { background: var(--slip-lilac); clip-path: url(#hat-fedora); width: clamp(11.25rem, 16.5vw, 15rem); aspect-ratio: 1; right: -1.5rem; bottom: 18%; transform: rotate(-8deg); }
/* Lamplight modelling: a crown gleam, a shaded base and the slips' paper
   grain, clipped by the hat shape. The left hat is lit from its right, the
   right cluster from its left — both toward the lamp over the hero.
   --gleam sits on each hat's own crown, which starts at a different height. */
.decor__tophat, .decor__sombrero, .decor__fedora { position: absolute; }
.decor__tophat::after, .decor__sombrero::after, .decor__fedora::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(ellipse 40% 22% at 50% var(--gleam, 14%), rgba(241, 235, 220, 0.34), transparent 70%),
    linear-gradient(var(--light-from, 155deg), rgba(241, 235, 220, 0.20), rgba(241, 235, 220, 0) 45%, rgba(4, 7, 5, 0.30) 97%),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}
.decor__tophat { --light-from: 205deg; --gleam: 13%; }
.decor__sombrero { --gleam: 16%; }
.decor__fedora { --gleam: 26%; }

.decor__dots-honey {
  width: clamp(15rem, 22.5vw, 21.75rem); aspect-ratio: 1; left: -3rem; top: 54%;
  background-image: radial-gradient(circle, var(--slip-honey) 1.4px, transparent 1.9px);
  background-size: 10px 10px;
  clip-path: url(#hat-grad);
  transform: rotate(6deg);
}
.decor__dots-rose {
  width: clamp(12.75rem, 19.5vw, 18rem); aspect-ratio: 1; right: -3.5rem; top: 9%;
  background-image: radial-gradient(circle, var(--slip-rose) 1.3px, transparent 1.8px);
  background-size: 9px 9px;
  clip-path: url(#hat-winter);
  transform: rotate(-5deg);
}

/* 9. Sections & figures ================================================== */

.hero {
  position: relative;
  overflow: hidden;
  padding-block: clamp(var(--s7), 10vh, var(--s9)) var(--s8);
  border-bottom: 1px solid var(--rule);
  background-image: var(--lamp);
}
.hero .wrap { position: relative; z-index: 1; }
.hero__title { max-width: 18ch; }
.hero__lead { margin-top: var(--s5); }
.hero__actions { margin-top: var(--s6); }
.hero__slips { margin-top: var(--s7); }

/* The landing hero sits centered under the lamp. */
.hero--center { text-align: center; }
.hero--center .hero__title { max-width: 15ch; margin-inline: auto; }
.hero--center .hero__lead { margin-inline: auto; }

.section { padding-block: var(--s8); }
.section + .section { border-top: 1px solid var(--rule); }
.section--sunk { background: var(--paper-sunk); }

/* Two-column: words on one side, picture on the other, alternating. */
.split {
  display: grid;
  gap: var(--s6) var(--s7);
  grid-template-columns: 1fr;
  align-items: center;
}
/* Stacked on a phone, the picture goes first whichever side it takes on a
   wide screen: a section opens with its picture rather than with the wall of
   text that pushes the picture off the bottom of the screen. */
.split__media { order: -1; }
@media (min-width: 48rem) {
  .split { grid-template-columns: 1.15fr 0.85fr; gap: var(--s6) var(--s8); }
  .split__media { order: 0; }
  /* Flipped, the columns mirror too: the picture changes sides, it does not
     take the text's width with it. */
  .split--flip { grid-template-columns: 0.85fr 1.15fr; }
  .split--flip .split__media { order: -1; }
}
.split__media img { margin-inline: auto; }

/* Pictures are prints lying on the table: a white paper card, tilted by
   hand — the tilt alternates with the section. The card exists only by
   day: at night transparent drawings float directly on the felt. */
.split__media--slip img {
  background: var(--print-bg);
  border: 1px solid var(--print-border);
  border-radius: 6px;
  padding: var(--print-pad);
  box-shadow: var(--print-shadow);
}
/* The tilt is for the drawings. The photograph is a picture of a room with
   its own horizon in it, and tilting that tilts the room. */
.split__media--slip:not(.split__media--photo) img { transform: rotate(-1.5deg); }
.split--flip .split__media--slip:not(.split__media--photo) img { transform: rotate(1.8deg); }
/* A photograph is a physical print with white baked into its pixels —
   it keeps the card in both themes. */
.split__media--photo img {
  background: #FBFCF9;
  border-color: var(--rule);
  padding: var(--s4);
  box-shadow: var(--shadow-slip);
}

/* The credit under a print: the smallest voice on the page, and a quiet one,
   but a printed one — it was a `title` attribute on the old site, which is to
   say it was not readable at all. */
.credit {
  margin-top: var(--s3);
  text-align: center;
  font-family: var(--sans);
  font-size: var(--t-micro);
  color: var(--ink-muted);
}
/* The licence is one token; "CC BY-" on one line and "SA 3.0" on the next is
   not the name of a licence. */
.credit a { white-space: nowrap; }

/* A note pinned to the page: raised card. */
.slip {
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: var(--r-card);
  padding: var(--s5);
}

/* -- the history ----------------------------------------------------------
   One thread down the page with a torn slip pinned at each moment. This was
   a two-column chronology, dates ranged down the left, which sets a history
   as a table of contents and reads as a list of releases however the entries
   are written. The history is a story about people, so it takes the shape of
   one: a single line, and each moment hung on it in turn. The last moment is
   the present, and its date is the one thing here allowed the brass. */
.timeline {
  margin: 0;
  padding-left: var(--s6);
  list-style: none;
  border-left: 1px solid var(--rule);
}
.timeline__entry { position: relative; }
.timeline__entry + .timeline__entry { margin-top: var(--s7); }
/* The slip pinned on the thread. Out by one gap plus half a slip, which puts
   its middle on the line; no two are torn or laid down alike. */
.timeline__entry::before {
  content: "";
  position: absolute;
  left: calc(-1 * var(--s6) - 9px);
  top: 0.3em;
  width: 18px;
  height: 11px;
  background: var(--slip, var(--slip-rose));
  border-radius: 1px 4px 2px 3px;
  clip-path: var(--tear, var(--tear-b));
  transform: rotate(var(--rot, -5deg));
  filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.3));
}
.timeline__entry:nth-child(4n+1) { --slip: var(--slip-rose);  --tear: var(--tear-a); --rot: -6deg; }
.timeline__entry:nth-child(4n+2) { --slip: var(--slip-honey); --tear: var(--tear-b); --rot: 4deg; }
.timeline__entry:nth-child(4n+3) { --slip: var(--slip-sky);   --tear: var(--tear-c); --rot: -3deg; }
.timeline__entry:nth-child(4n)   { --slip: var(--slip-lilac); --tear: var(--tear-b); --rot: 5deg; }
.timeline__when {
  font-family: var(--sans);
  font-size: var(--t-small);
  color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
  margin: 0 0 var(--s2);
}
.timeline__what { margin: 0; max-width: var(--measure); }
.timeline__entry--now .timeline__when { color: var(--brass-text); font-weight: 600; }

/* The icon of an app the story names. It stands to the left of the entry it
   belongs to and is centred on it, the way a stamp sits beside a paragraph:
   an app icon is a thing shown, not a thing read, and in the column it read
   as another paragraph. Named only in `alt` — big enough to recognise, the
   name under it was a caption for something that does not need one.

   The card is stated here rather than taken from the --print-* tokens, which
   drop it at night. Both icons are transparent PNGs drawn for a light home
   screen — the older one is inked in black outlines — so on the felt they
   would come apart. Like the photograph, an app icon is an object with its
   own frame, and it keeps it in both themes. */
.timeline__entry { display: grid; grid-template-columns: auto minmax(0, 1fr); }
/* The date keeps the entry's left edge, level with its slip on the thread;
   the icon hangs off the entry below it. On entries with no icon the first
   column has nothing in it and collapses, so those dates and entries sit
   where they always did. */
.timeline__when { grid-column: 1 / -1; }
.timeline__what { grid-column: 2; grid-row: 2; }
.app {
  grid-column: 1;
  grid-row: 2;
  align-self: center;
  margin-right: var(--s5);
  width: 88px;
  background: #FBFCF9;
  border: 1px solid var(--rule);
  border-radius: 19px;
  padding: 7px;
  box-shadow: var(--shadow-slip);
  line-height: 0;            /* no descender gap under the picture */
}
.app img { width: 100%; height: auto; }

/* On a phone there is no room beside a paragraph, so the icon goes above it
   instead — still the entry's mark, just stacked. */
@media (max-width: 40rem) {
  .app {
    grid-column: 1 / -1;
    grid-row: 2;
    justify-self: start;
    align-self: start;
    margin: var(--s1) 0 var(--s4);
    width: 64px;
    border-radius: 14px;
    padding: 5px;
  }
  .timeline__what { grid-column: 1 / -1; grid-row: 3; }
}

/* 10. Prose ============================================================== */

.prose { max-width: var(--measure); }
.prose > * + * { margin-top: var(--s4); }
.prose h2 { font-size: var(--t-section); margin-top: var(--s7); }
.prose h3 { font-size: 1.125rem; margin-top: var(--s6); }
.prose ul, .prose ol { padding-left: var(--s5); }
.prose li + li { margin-top: var(--s2); }
.prose strong { font-weight: 700; }
.prose code {
  font-family: var(--mono);
  font-size: 0.9em;
  background: var(--paper-sunk);
  padding: 0.15em 0.35em;
  border-radius: 2px;
}

/* 11. Data ===============================================================
   Everything below is sans + tabular figures: measurement, not voice.
   The score does not smile. */

.data { font-family: var(--sans); }

/* -- table -------------------------------------------------------------- */
.table-scroll { overflow-x: auto; }

.table {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--sans);
  font-size: var(--t-small);
}
/* A table is titled the same way a chart is: a line of prose above it. */
.table caption {
  text-align: left;
  font-family: var(--serif);
  font-size: var(--t-body);
  color: var(--ink);
  padding-bottom: var(--s3);
}
.table th {
  text-align: left;
  font-weight: 600;
  color: var(--ink-muted);
  font-size: var(--t-micro);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: var(--s2);
  border-bottom: 1px solid var(--rule);
  white-space: nowrap;
}
/* Tighter across than down. Three of these tables share one sheet, and the
   column a word needs is the column a word needs — the give has to come from
   the gutters. The rows still breathe; the cells no longer pay 0.75rem twice
   for a four-character number. */
.table td {
  padding: var(--s3) var(--s2);
  border-bottom: 1px solid var(--rule);
  vertical-align: baseline;
}
/* A phone has room for the columns or for the gutters, not both — and now
   that a word holds its line, the four-column table would otherwise hand the
   reader a scrollbar for the last 19px of it. */
@media (max-width: 30rem) {
  .table th, .table td { padding-inline: var(--s1); }
}
.table tbody tr:last-child td { border-bottom: 0; }
.table tbody tr:hover { background: var(--paper-sunk); }
/* Columns of numbers align; standalone values elsewhere stay proportional. */
.table .num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.table .rank { color: var(--ink-muted); width: 1%; font-variant-numeric: tabular-nums; }
/* A word is read, not measured, and a word broken across two lines reads as
   two words. It keeps its line; the enclosing .table-scroll is what gives way
   on a narrow sheet. */
.table .word {
  font-family: var(--serif);
  font-style: italic;
  font-size: 1rem;
  white-space: nowrap;
}

/* -- headline figures ----------------------------------------------------
   A page states its numbers the way a printed almanac does: set straight on
   the paper, ruled apart, caption underneath. Deliberately not a row of
   bordered cards with the label on top — that is a dashboard's idiom, and
   this is a sheet, not a control panel. */
.figures {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: var(--s5) var(--s6);
}
.figure { padding-left: var(--s4); border-left: 1px solid var(--rule); }
.figure__value {
  display: block;
  font-family: var(--sans);
  font-weight: 600;
  font-size: clamp(2.1rem, 4vw, 2.9rem);
  line-height: 1;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}
/* The unit rides with the number, at reading size. */
.figure__unit { font-size: 1rem; font-weight: 400; color: var(--ink-muted); margin-left: 0.15em; }
.figure__label {
  display: block;
  margin-top: var(--s3);
  font-family: var(--sans);
  font-size: var(--t-small);
  color: var(--ink-muted);
}

/* "Show me the table" under a chart: a line of prose, like the captions. */
.disclosure {
  font-family: var(--serif);
  font-size: var(--t-small);
  color: var(--ink-muted);
  cursor: pointer;
}
.disclosure:hover { color: var(--ink); }

/* -- stat tiles --------------------------------------------------------- */
.tile__label {
  font-family: var(--sans);
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
.tile__note {
  font-family: var(--sans);
  font-size: var(--t-small);
  color: var(--ink-muted);
  margin-top: var(--s1);
}

/* -- bar chart ----------------------------------------------------------
   Single-series magnitude: one hue (the slip of the subject), no legend,
   values direct-labelled at the tip. */
.chart { margin-top: var(--s4); }
/* The chart's title is a line of prose, in the reading face — a page of
   small uppercase sans labels reads as a dashboard. Only the units and
   footnotes below a chart stay in the counting face. */
.chart__caption {
  font-family: var(--serif);
  font-size: var(--t-body);
  color: var(--ink);
  margin-bottom: var(--s4);
}

/* The three columns live on the group, not on the row, so that every track
   starts at the same x whatever the labels say. Sized per row, a long label
   stepped its own bar to the right and the chart lost its baseline — the one
   line a reader compares the bars against. */
.bars {
  display: grid;
  grid-template-columns: minmax(2.5rem, max-content) 1fr auto;
  align-items: center;
  gap: 2px var(--s3);              /* the surface gap; not a stroke */
  font-family: var(--sans);
  font-size: var(--t-small);
}
/* Scoped to the group: /play calls its back-button row a .bar too, and that
   one is a box with a margin, not three cells of a chart. */
.bars > .bar { display: contents; }
.bar__label {
  color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
  font-size: var(--t-micro);
  white-space: nowrap;
}
/* No filled track behind the mark: the bars stand on a single ruled axis,
   the way a bar chart is set in print. A grey trough per row is chart-widget
   furniture and puts a second, meaningless rectangle on every line. */
.bar__track {
  display: block;
  position: relative;
  height: 14px;                    /* thin mark, well under the 24px cap */
  border-left: 1px solid var(--rule);
}
.bar__fill {
  /* Must be blockified: width/height do not apply to an inline box. */
  display: block;
  height: 100%;
  background: var(--mark-honey);
  min-width: 1px;
}
.bar__value {
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  font-size: var(--t-micro);
  min-width: 2.5rem;
  text-align: right;
}
.bar--empty .bar__value { color: var(--ink-muted); }
/* A chart takes the slip of its subject: honey (default) for words,
   sky for time, lilac for people. */
.bars--sky .bar__fill { background: var(--mark-sky); }
.bars--lilac .bar__fill { background: var(--mark-lilac); }

/* Two charts side by side on a wide sheet. */
.chart-grid { display: grid; gap: var(--s6); align-items: start; }
.chart-grid > * { min-width: 0; }
@media (min-width: 48rem) { .chart-grid--2 { grid-template-columns: 1fr 1fr; } }

/* -- punchcard -----------------------------------------------------------
   Hour-of-week grid: a dot per (day, hour), sized and weighted by count.
   The evening table's own rhythm — when the hat actually comes out.

   24 across by 7 down wants a landscape sheet, and on a phone it used to
   need a 30rem scroller — which hid the evening, the one part of this chart
   anybody reads. So every cell carries its own (--d, --h) and is placed
   explicitly, and the narrow layout simply transposes the placement: hours
   run down the page, days across. Same markup, no scrolling, at any width. */
.punch {
  display: grid;
  grid-template-columns: max-content repeat(24, minmax(0, 1fr));
  gap: 2px;
  align-items: center;
  justify-items: center;
  font-family: var(--sans);
  font-size: var(--t-micro);
  color: var(--ink-muted);
}
.punch__day { grid-area: var(--d) / 1; justify-self: start; padding-right: var(--s2); }
.punch__cell {
  grid-area: var(--d) / calc(var(--h) + 2);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  aspect-ratio: 1;
}
.punch__hour { grid-area: 8 / calc(var(--h) + 2); }
/* Landscape has room for every third hour only; the rest hold their column. */
.punch__hour--sparse { visibility: hidden; }

@media (max-width: 48rem) {
  .punch { grid-template-columns: max-content repeat(7, minmax(0, 1fr)); }
  .punch__day { grid-area: 1 / calc(var(--d) + 1); justify-self: center; padding-right: 0; }
  .punch__cell { grid-area: calc(var(--h) + 2) / calc(var(--d) + 1); aspect-ratio: auto; height: 1.25rem; }
  .punch__hour { grid-area: calc(var(--h) + 2) / 1; justify-self: end; padding-right: var(--s2); }
  /* A row per hour: there is room to name all of them, and down the side
     they are what tells you which row you are looking at. */
  .punch__hour--sparse { visibility: visible; }
}
.punch__dot {
  /* --v is count/peak, set inline */
  width: calc(0.25rem + var(--v, 0) * 0.85rem);
  height: calc(0.25rem + var(--v, 0) * 0.85rem);
  border-radius: 50%;
  background: var(--mark-sky);
  opacity: calc(0.3 + var(--v, 0) * 0.7);
}
.punch__dot--zero { width: 3px; height: 3px; background: var(--mark-track); opacity: 1; }
.punch__hour { font-variant-numeric: tabular-nums; }

/* -- picked-out words -----------------------------------------------------
   A short list of slips with their numbers underneath. Not a chart: three
   words and what is odd about each, which is all the point needs. */
.picks { list-style: none; padding: 0; margin: 0; display: grid; gap: var(--s4); }
.pick {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--s2) var(--s3);
}
.pick__num {
  font-family: var(--sans);
  font-size: var(--t-small);
  color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
}

/* -- difficulty scale -----------------------------------------------------
   The old gauge, laid flat: a 0-100 track, the confidence band E +- 2D as a
   wash, the measured value as a solid marker. */
.scale { position: relative; margin-top: var(--s2); }
.scale__track { position: relative; height: 14px; background: var(--mark-track); border-radius: 7px; }
.scale__band { position: absolute; top: 0; bottom: 0; background: var(--mark-honey); opacity: 0.35; border-radius: 7px; }
.scale__marker { position: absolute; top: -3px; bottom: -3px; width: 4px; border-radius: 2px; background: var(--mark-honey); }
.scale__labels {
  display: flex;
  justify-content: space-between;
  font-family: var(--sans);
  font-size: var(--t-micro);
  color: var(--ink-muted);
  padding-top: var(--s2);
  font-variant-numeric: tabular-nums;
}

/* Columns, for cycles where reading order is horizontal. */
.columns {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 2px;
  align-items: end;
  height: 8rem;
  padding-top: var(--s4);
  border-bottom: 1px solid var(--rule);
}
/* Grid items floor at their min-content width unless told otherwise, and 24
   of them in a row put a ~430px floor under the whole chart — which on a
   phone widened the track its neighbours share and pushed their values off
   the screen. Every cell in these strips must be free to shrink. */
.column { display: flex; flex-direction: column; justify-content: flex-end; height: 100%; min-width: 0; }
.column__fill {
  display: block;
  background: var(--mark-sky);
  border-radius: 3px 3px 0 0;
  min-height: 2px;
  /* Cap the mark: never fill the slot, let the leftover band be air. */
  width: 100%;
  max-width: 24px;
  margin-inline: auto;
}
.column__labels {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 2px;
  font-family: var(--sans);
  font-size: var(--t-micro);
  color: var(--ink-muted);
  padding-top: var(--s2);
  font-variant-numeric: tabular-nums;
}
/* min-width alone: the label must still be free to spill out of its 4px
   cell, because only every third (or fourteenth) one is shown. nowrap comes
   with it — free to shrink, a two-digit hour would set as two lines. */
.column__label { text-align: center; min-width: 0; white-space: nowrap; }
/* Every third tick stays; the rest would collide. */
.column__label--hidden { visibility: hidden; }

/* Dense variant: one thin column per day over ~three months. */
.columns--dense { gap: 1px; height: 6rem; }
.columns--dense .column__fill { max-width: 8px; border-radius: 2px 2px 0 0; }
.column__labels--dense {
  gap: 1px;
  white-space: nowrap;
  /* A date is wider than its 1fr track; without minmax(0, …) the tracks
     refuse to shrink below the text and the whole row drifts right. */
  grid-auto-columns: minmax(0, 1fr);
}

/* -- search ------------------------------------------------------------- */
.search {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3);
  align-items: center;
}
.search input[type="search"] {
  font-family: var(--serif);
  font-style: italic;
  font-size: var(--t-body);
  color: var(--ink);
  background: var(--paper-raised);
  border: 1px solid var(--rule);
  border-radius: var(--r-pill);
  padding: 0.55em 1.1em;
  min-width: 14rem;
  flex: 1 1 14rem;
}
.search input[type="search"]:focus { border-color: var(--brass); outline: none; }
.search input[type="search"]::placeholder { color: var(--ink-muted); opacity: 1; }

/* -- empty state -------------------------------------------------------- */
.empty {
  color: var(--ink-muted);
  font-style: italic;
  padding-block: var(--s5);
}

/* -- print ---------------------------------------------------------------
   Paper is paper: print gets the day palette on white regardless of the
   screen theme. */
@media print {
  /* The second selector is not decoration: a hand-picked theme is an
     attribute, and an attribute outweighs the bare :root this block would
     otherwise carry — paper would then print in the palette of a screen. */
  :root, :root[data-theme] {
    --mat: #fff; --paper: #fff; --paper-raised: #fff; --paper-sunk: #f2f2f2;
    --ink: #000; --ink-muted: #444; --rule: #ccc;
    --brass: #7E621C; --brass-text: #7E621C;
    --mark-honey: #A97812; --mark-sky: #567F8E; --mark-lilac: #6B5588; --mark-track: #eee;
    --lamp: none; --decor-o: 0;
    --shadow-slip: none; --shadow-sheet: none; --slip-filter: none;
    --print-bg: #fff; --print-border: #ccc; --print-pad: var(--s4); --print-shadow: none;
  }
  .masthead__nav, .footer, .btn, .decor { display: none; }
  body { background: #fff; color: #000; padding: 0; }
  .sheet { box-shadow: none; }
  .section, .hero { padding-block: var(--s5); }
}
