/* ============================================
   Chapterboard: "Publisher's page" (research/ui-direction.md §4.1), on paper.
   Warm paper page with a faint grain, and ink; one ink-blue accent for links and the single
   primary button; Literata for everything read, Public Sans for controls; square corners.
   The board is pictures printed on paper and pinned to a card, overlapping a little, the way
   Warburg pinned prints to his Atlas boards (research/warburg-atlas.md).
   Class names are BEM: block__element--modifier.
   ============================================ */

:root {
  /* --- Colours --- */
  --color-bg: #faf8f3;               /* the page: warm paper */
  --color-sheet: #fffefb;            /* a fresh sheet lying on the page */
  --color-surface: #f1eee6;
  --color-board: #e7e2d6;            /* the card the prints are pinned to */
  --color-print: #fdfbf6;            /* the white margin round each print */
  --color-border: #dcd7cc;           /* hairline rules */
  --color-border-strong: #8a8a8a;    /* input underlines (3:1 or better) */
  --color-accent: #1f3a9e;           /* links and the one primary button */
  --color-accent-hi: #172c78;
  --color-accent-muted: #a9b3dc;     /* link underline at rest */
  --color-text: #16181d;
  --color-text-muted: #545861;
  --color-text-faint: #6b6e75;
  --color-on-accent: #ffffff;
  --color-danger: #b3261e;
  --color-overlay: rgba(22, 24, 29, 0.35);
  --color-skeleton: #e9e5dc;
  --color-scrim: rgba(10, 10, 10, 0.72);
  --color-on-image: #ffffff;
  --color-on-image-muted: rgba(255, 255, 255, 0.78);

  /* --- Spacing (4px baseline) --- */
  --space-xs: 4px;
  --space-sm: 8px;
  --space-md: 12px;
  --space-lg: 16px;
  --space-xl: 24px;
  --space-xxl: 32px;
  --space-xxxl: 64px;

  /* --- Radius: square everywhere --- */
  --radius-sm: 0;

  /* --- Typography --- */
  --font-serif: "Literata", Georgia, "Times New Roman", serif;
  --font-sans: "Public Sans", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-xs: 12px;     /* credits, hex codes, numbers */
  --font-sm: 14px;     /* field labels, hints, board meta */
  --font-md: 16px;     /* UI text, inputs, buttons */
  --font-lg: 18px;     /* chapter text, board summary */
  --font-xl: 22px;     /* section titles */
  --font-xxl: 28px;    /* board title */
  --font-logo: 20px;
  --font-hero: clamp(26px, 4vw, 32px);
  --weight-regular: 400;
  --weight-medium: 600;
  --tracking-caps: 0.06em;   /* only the one caps line: board meta */
  --leading-body: 1.55;
  --leading-read: 1.65;
  --leading-head: 1.2;

  /* --- Layout --- */
  --hit-target: 44px;
  --max-width: 1400px;
  --read-width: 680px;
  --navbar-height: 56px;
  --button-padding: 20px;
  --board-pad: 14px;                 /* card showing round the prints */
  --edge-thin: 3px;                  /* white border of a photo print */
  --edge-plate: 7px;                 /* margin of a plate cut from a book */
  --nudge: 2px;                      /* how far a print sits off its frame */
  --transition-fast: 0.2s ease;

  /* --- Paper --- */
  --shadow-sheet: 0 1px 2px rgba(60, 45, 20, 0.08), 0 4px 14px rgba(60, 45, 20, 0.06);
  --shadow-print: 0 0 0 0.5px rgba(50, 38, 20, 0.12), 0 1px 1px rgba(50, 38, 20, 0.16), 0 2px 4px -1px rgba(50, 38, 20, 0.12);
  --shadow-lift: 0 2px 3px rgba(60, 45, 20, 0.16), 0 12px 24px rgba(60, 45, 20, 0.2);

  color-scheme: light;
}

/* --- Base --- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
html, body { overflow-x: clip; }
body {
  margin: 0;
  background: var(--color-bg) url("paper.png");
  color: var(--color-text);
  font: var(--weight-regular) var(--font-md)/var(--leading-body) var(--font-sans);
  -webkit-font-smoothing: antialiased;
}
[hidden] { display: none !important; }
h1, h2, h3, h4 { font-weight: var(--weight-regular); }
a {
  color: var(--color-accent);
  text-decoration: underline 1px var(--color-accent-muted);
  text-underline-offset: 0.18em;
  transition: text-decoration-color var(--transition-fast);
}
a:hover { text-decoration-color: currentColor; }
::selection { background: var(--color-accent); color: var(--color-on-accent); }
::placeholder { color: var(--color-text-faint); opacity: 1; }
:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }

/* --- Top bar --- */
.topbar {
  position: sticky;
  top: 0;
  z-index: 5;
  height: var(--navbar-height);
  border-bottom: 1px solid var(--color-border);
  background: var(--color-bg) url("paper.png");
}
.topbar__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-lg);
  max-width: var(--max-width);
  height: 100%;
  margin: 0 auto;
  padding: 0 var(--space-lg);
}
.topbar__logo { color: var(--color-text); font: var(--weight-medium) var(--font-logo)/1 var(--font-serif); text-decoration: none; }
.topbar__links { display: flex; align-items: center; gap: var(--space-xl); }
.topbar__link {
  display: inline-flex;
  align-items: center;
  min-height: var(--hit-target);
  padding: 0;
  border: 0;
  background: none;
  color: var(--color-text-faint);
  font: var(--weight-regular) var(--font-md)/1 var(--font-sans);
  text-decoration: none;
  cursor: pointer;
  transition: color var(--transition-fast);
}
.topbar__link:hover,
.topbar__link[aria-current="page"] { color: var(--color-text); }

.main { padding: 0 var(--space-lg) var(--space-xxxl); }

/* --- Fields --- */
.field { display: grid; gap: var(--space-sm); min-width: 0; margin: 0 0 var(--space-xxl); padding: 0; border: 0; }
.field__label {
  display: flex;
  justify-content: space-between;
  gap: var(--space-sm);
  padding: 0;
  color: var(--color-text);
  font: var(--weight-medium) var(--font-sm)/1.3 var(--font-sans);
}
.field__label > span + span { color: var(--color-text-faint); font-weight: var(--weight-regular); font-variant-numeric: tabular-nums; }
.field__textarea,
.field__input {
  width: 100%;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--color-text);
}
/* The chapter goes on a fresh sheet lying on the page */
.field__textarea {
  min-height: 45vh;
  padding: var(--space-lg) var(--space-xl);
  border: 1px solid var(--color-border);
  border-bottom-color: var(--color-border-strong);
  background: var(--color-sheet);
  box-shadow: var(--shadow-sheet);
  font: var(--weight-regular) var(--font-lg)/var(--leading-read) var(--font-serif);
  resize: vertical;
}
.field__textarea::placeholder { font-style: italic; }
.field__input {
  padding: 10px 0;
  border-bottom: 1px solid var(--color-border-strong);
  font: var(--weight-regular) var(--font-md)/1.4 var(--font-sans);
}
/* Focus thickens the bottom rule; padding gives back the extra pixel so nothing jumps */
.field__textarea:focus,
.field__input:focus { outline: none; border-bottom: 2px solid var(--color-accent); }
.field__textarea:focus { padding-bottom: calc(var(--space-lg) - 1px); }
.field__input:focus { padding-bottom: 9px; }
.field__hint { margin: 0; color: var(--color-text-faint); font-size: var(--font-sm); }

/* --- Buttons --- */
.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--hit-target);
  padding: 0 var(--button-padding);
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--color-text);
  font: var(--weight-regular) var(--font-md)/1.2 var(--font-sans);
  cursor: pointer;
  transition: background-color var(--transition-fast), text-decoration-color var(--transition-fast);
}
.button--primary { background: var(--color-accent); color: var(--color-on-accent); font-weight: var(--weight-medium); }
.button--primary:hover { background: var(--color-accent-hi); }
.button--text {
  padding: 0;
  text-decoration: underline 1px var(--color-border-strong);
  text-underline-offset: 4px;
}
.button--text:hover { text-decoration-color: currentColor; }
.button:disabled { opacity: 0.45; cursor: progress; }

/* --- Compose --- */
.compose { max-width: var(--read-width); margin: 0 auto; padding-top: var(--space-xxxl); }
.compose__title { margin: 0 0 var(--space-md); font: var(--weight-regular) var(--font-hero)/var(--leading-head) var(--font-serif); }
.compose__lede { max-width: 60ch; margin: 0 0 var(--space-xxl); color: var(--color-text-muted); }
.compose__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-lg) var(--space-xl); }
.compose__status { min-height: 1.6em; margin: var(--space-xl) 0 0; color: var(--color-text-muted); font-size: var(--font-sm); }
.compose__status--error { color: var(--color-danger); }

/* --- Board header: title on the left, the two board actions on the right --- */
.board-view { max-width: 2000px; margin: 0 auto; padding-top: var(--space-xl); }
.board-view__top { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: var(--space-md) var(--space-xxl); margin-bottom: var(--space-lg); }
.board-view__head { display: grid; gap: var(--space-xs); max-width: var(--read-width); }
.board-view__meta {
  margin: 0;
  color: var(--color-text-faint);
  font: var(--weight-medium) var(--font-xs)/1.5 var(--font-sans);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
}
.board-view__title { margin: 0; font: var(--weight-regular) var(--font-xxl)/var(--leading-head) var(--font-serif); }
.board-view__summary { margin: 0; color: var(--color-text-muted); font: var(--weight-regular) var(--font-md)/1.5 var(--font-serif); }
.board-view__actions { display: flex; flex-wrap: wrap; gap: var(--space-xl); }
/* The look pickers: four small selects that read like the text links beside them */
.board-view__style {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-xs) var(--space-xl);
  margin: 0 0 var(--space-lg);
  color: var(--color-text-faint);
  font-size: var(--font-sm);
}
.pick { display: inline-flex; align-items: center; gap: var(--space-sm); }
.pick__select {
  height: 32px;
  padding: 0 18px 0 0;
  border: 0;
  border-bottom: 1px solid var(--color-border-strong);
  border-radius: 0;
  background: transparent url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%236b6458' stroke-width='1.3'/%3E%3C/svg%3E") right center no-repeat;
  color: var(--color-text);
  font: var(--weight-regular) var(--font-sm)/1 var(--font-sans);
  cursor: pointer;
  appearance: none;
}
.pick__select:hover { border-bottom-color: currentColor; }
.pick__reset { font-size: var(--font-sm); color: var(--color-text-muted); }
.board-view__notice { max-width: 80ch; margin: var(--space-lg) 0 0; color: var(--color-text-faint); font-size: var(--font-sm); }

/* --- Board: a big sheet of card with prints pinned to it, the way Warburg pinned prints to his
   Atlas boards, to scroll through rather than take in at a glance. js/collage.js gives every
   print a frame as fractions of the card, loosely spaced. Frames for wide boards are
   --wx/--wy/--ww/--wh and for tall (phone) boards --tx/--ty/--tw/--th. The content box takes
   the layout's own shape, so no print is squashed. On phones the card runs edge to edge. --- */
.board {
  position: relative;
  box-sizing: content-box;
  width: calc(100% + 2 * var(--space-lg) - 2 * var(--board-pad));
  margin: 0 calc(-1 * var(--space-lg));
  padding: var(--board-pad);
  aspect-ratio: var(--tall-shape, 0.27);
  /* Prints stack among themselves only, so they pass under the top bar when scrolled */
  isolation: isolate;
  /* Card lit a little unevenly, lighter where the light falls */
  background:
    radial-gradient(130% 90% at 35% 25%, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0) 55%, rgba(70, 50, 20, 0.07)),
    url("paper.png") var(--color-board);
  box-shadow: inset 0 0 0 1px rgba(60, 45, 20, 0.06);
}
.board--drop { outline: 2px dashed var(--color-accent); outline-offset: 4px; }

/* --- Rooms (js/rooms.js): what the board is pinned to, and the light and air of the place it
   hangs in. The light lies over the prints too (::after), as real light would: fog greys them,
   sun falls across them, a lamp leaves the edges dark. Some rooms have a second layer (::before)
   that comes and goes, slowly: drops on a window, a candle's flicker, light through water.
   Only its opacity moves, which costs a phone next to nothing, and not at all when motion is
   turned down. Textures are small tiles in css/. Each room also sets the colours of what holds
   the prints up. --- */
.board {
  --pin: #b23a2e;
  --pin-2: #caa24c;
  --tape: rgba(234, 224, 194, 0.82);
  --string: #6d5c45;
  --corner: #24201c;
}
.board::before,
.board::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 40;
  pointer-events: none;
}
.board::before { z-index: 41; }
@keyframes come-and-go { from { opacity: 0.1; } to { opacity: 1; } }
@keyframes flicker {
  0%, 100% { opacity: 0.8; }
  9% { opacity: 0.5; }
  21% { opacity: 0.95; }
  34% { opacity: 0.68; }
  47% { opacity: 1; }
  58% { opacity: 0.56; }
  71% { opacity: 0.88; }
  86% { opacity: 0.62; }
}
@media (prefers-reduced-motion: reduce) {
  .board::before { animation: none !important; }
}
/* Fog: cool grey card, banks of mist over everything */
.board[data-room="fog"] {
  background:
    radial-gradient(130% 90% at 40% 20%, rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0) 60%),
    url("paper.png") #d2d7d9;
}
.board[data-room="fog"]::after {
  background:
    linear-gradient(rgba(236, 240, 242, 0.3), rgba(236, 240, 242, 0) 35%, rgba(236, 240, 242, 0) 75%, rgba(236, 240, 242, 0.2)),
    url("mist.png") center / 100% 100% no-repeat;
}
/* Sun: sun-bleached card, the room in shade, two windows of afternoon light across the wall */
.board[data-room="sun"] { background: url("paper.png") #eedfc4; }
.board[data-room="sun"]::after { background: url("window.png") 70% 30% / cover no-repeat; }
/* Night: black cloth, as Warburg's own boards were, under one lamp */
.board[data-room="night"] {
  background: url("linen.png") #201e1c;
  box-shadow: none;
  --pin: #e2dccd;
  --string: #b9ad98;
}
.board[data-room="night"]::after {
  background:
    radial-gradient(ellipse 60% 55% at 42% 12%, rgba(255, 206, 140, 0.13), rgba(255, 206, 140, 0) 70%),
    radial-gradient(ellipse 95% 85% at 42% 22%, rgba(8, 6, 4, 0) 38%, rgba(8, 6, 4, 0.5));
}
/* Garden: cork, with light through leaves */
.board[data-room="garden"] { background: url("cork.png") #b78c5b; }
.board[data-room="garden"]::after { background: url("leaves.png") center / cover no-repeat; }
/* Archive: linen-covered panel, dim at the edges */
.board[data-room="archive"] { background: url("linen.png") #d6ccb3; --corner: #2b2621; }
.board[data-room="archive"]::after {
  background: radial-gradient(ellipse 95% 85% at 50% 40%, rgba(60, 40, 15, 0) 50%, rgba(60, 40, 15, 0.2));
}
/* City: plaster wall, hard light from above, a building's shadow across it */
.board[data-room="city"] { background: url("plaster.png") #bcb9b2; --tape: rgba(204, 203, 197, 0.88); }
.board[data-room="city"]::after {
  background:
    linear-gradient(103deg, rgba(20, 25, 30, 0) 63%, rgba(20, 25, 30, 0.14) 63.3%),
    linear-gradient(rgba(255, 255, 255, 0.12), rgba(255, 255, 255, 0) 35%, rgba(0, 0, 0, 0.08));
}
/* Gallery: a smooth white wall under track lights */
.board[data-room="gallery"] {
  background:
    radial-gradient(ellipse 16% 62% at 20% -6%, rgba(255, 251, 240, 0.9), rgba(255, 251, 240, 0) 80%),
    radial-gradient(ellipse 16% 62% at 50% -6%, rgba(255, 251, 240, 0.9), rgba(255, 251, 240, 0) 80%),
    radial-gradient(ellipse 16% 62% at 80% -6%, rgba(255, 251, 240, 0.9), rgba(255, 251, 240, 0) 80%),
    #dedcd6;
  box-shadow: none;
}
.board[data-room="gallery"]::after {
  background:
    radial-gradient(ellipse 16% 62% at 20% -6%, rgba(255, 248, 232, 0.16), rgba(255, 248, 232, 0) 80%),
    radial-gradient(ellipse 16% 62% at 50% -6%, rgba(255, 248, 232, 0.16), rgba(255, 248, 232, 0) 80%),
    radial-gradient(ellipse 16% 62% at 80% -6%, rgba(255, 248, 232, 0.16), rgba(255, 248, 232, 0) 80%),
    linear-gradient(rgba(0, 0, 0, 0) 55%, rgba(0, 0, 0, 0.06));
}
/* Rain: the board seen through a wet window, cool and dim, drops on the glass coming and going */
.board[data-room="rain"] { background: url("paper.png") #a2aaae; --tape: rgba(228, 230, 224, 0.8); }
.board[data-room="rain"]::after {
  background:
    url("rain.png") 0 0 / 256px auto,
    linear-gradient(rgba(58, 76, 90, 0.16), rgba(58, 76, 90, 0.3));
}
.board[data-room="rain"]::before {
  background: url("rain.png") 97px 141px / 310px auto;
  animation: come-and-go 7s ease-in-out infinite alternate;
}
/* Snow: white felt in cold light, frost grown in from the window's edges, flakes in the air */
.board[data-room="snow"] { background: url("rough.png") #e5e9ec; --pin: #f6f6f3; --pin-2: #93a3b1; }
.board[data-room="snow"]::after {
  background:
    url("frost.png") center / 100% 100% no-repeat,
    linear-gradient(rgba(186, 208, 230, 0.18), rgba(186, 208, 230, 0.08));
}
.board[data-room="snow"]::before {
  background: url("snow.png") 0 0 / 256px auto;
  animation: come-and-go 9s ease-in-out infinite alternate;
}
/* Desert: sun-baked plaster, light so strong it bleaches the top of the board, and every print
   throws a hard, short shadow */
.board[data-room="desert"] {
  background: linear-gradient(rgba(197, 138, 94, 0.5), rgba(197, 138, 94, 0.5)), url("rough.png"), url("plaster.png") #c58a5e;
  --pin: #2b2420;
  --pin-2: #ece3d2;
}
.board[data-room="desert"]::after {
  background: linear-gradient(170deg, rgba(255, 246, 228, 0.34), rgba(255, 246, 228, 0) 45%, rgba(120, 50, 10, 0.08));
}
.board[data-room="desert"] .print { box-shadow: 5px 7px 0 rgba(95, 40, 10, 0.26); }
/* Candle: a limewashed stone wall lit low from one side by a flame that won't keep still */
.board[data-room="candle"] { background: url("stone.png") #cbbda3; --pin: #c9a24a; --pin-2: #5a3d22; }
.board[data-room="candle"]::after {
  background: radial-gradient(ellipse 80% 75% at 20% 95%, rgba(255, 168, 78, 0.16), rgba(40, 20, 5, 0) 45%, rgba(24, 12, 4, 0.64));
}
.board[data-room="candle"]::before {
  background: radial-gradient(ellipse 60% 55% at 20% 95%, rgba(255, 186, 104, 0.26), rgba(255, 186, 104, 0) 70%);
  animation: flicker 2.6s linear infinite;
}
/* Darkroom: black walls under the red safelight, which turns everything its colour */
.board[data-room="darkroom"] { background: url("linen.png") #1d1413; box-shadow: none; --string: #d9c8b6; }
.board[data-room="darkroom"]::after {
  background:
    radial-gradient(ellipse 75% 60% at 50% 0%, rgba(255, 255, 255, 0.12), rgba(255, 255, 255, 0) 70%),
    radial-gradient(ellipse 100% 90% at 50% 20%, #ff8f78 40%, #b8402c);
  mix-blend-mode: multiply;
}
/* Water: everything lies under shallow water, the light thrown in a moving net across it */
.board[data-room="water"] { background: url("rough.png") #4d8a94; --pin: #ebe4d1; --string: #e2dccb; }
.board[data-room="water"]::after {
  background:
    url("caustics.png") 0 0 / 300px auto,
    linear-gradient(rgba(30, 110, 130, 0.08), rgba(10, 58, 88, 0.26));
}
.board[data-room="water"]::before {
  background: url("caustics.png") 120px 60px / 360px auto;
  animation: come-and-go 3.5s ease-in-out infinite alternate;
}
/* Dream: pastel haze, everything a little too soft and too bright */
.board[data-room="dream"] {
  background:
    radial-gradient(60% 50% at 18% 22%, rgba(255, 196, 220, 0.95), rgba(255, 196, 220, 0) 72%),
    radial-gradient(55% 60% at 84% 72%, rgba(184, 206, 255, 0.95), rgba(184, 206, 255, 0) 72%),
    radial-gradient(40% 45% at 62% 8%, rgba(255, 226, 190, 0.8), rgba(255, 226, 190, 0) 70%),
    url("paper.png") #ebe4f0;
  box-shadow: none;
  --pin: #f3d6e0;
  --pin-2: #c9d8f0;
}
.board[data-room="dream"]::after {
  background:
    radial-gradient(45% 35% at 30% 30%, rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0) 70%),
    radial-gradient(40% 40% at 75% 75%, rgba(255, 240, 250, 0.24), rgba(255, 240, 250, 0) 70%),
    linear-gradient(rgba(255, 250, 255, 0.16), rgba(255, 250, 255, 0.16));
}
.board[data-room="dream"]::before {
  background: radial-gradient(50% 40% at 60% 45%, rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0) 70%);
  animation: come-and-go 6s ease-in-out infinite alternate;
}
/* Attic: bare boards, dim, one shaft of light from a small window with dust turning in it */
.board[data-room="attic"] { background: url("wood.png") #8a6748; --pin: #c9a24a; }
.board[data-room="attic"]::after {
  background:
    linear-gradient(118deg, rgba(255, 220, 150, 0) 30%, rgba(255, 220, 150, 0.2) 38%, rgba(255, 220, 150, 0.2) 50%, rgba(255, 220, 150, 0) 58%),
    radial-gradient(ellipse 95% 85% at 45% 40%, rgba(30, 15, 5, 0) 45%, rgba(30, 15, 5, 0.46));
}
.board[data-room="attic"]::before {
  background: url("dust.png") 0 0 / 256px auto;
  -webkit-mask-image: linear-gradient(118deg, transparent 30%, #000 40%, #000 48%, transparent 58%);
  mask-image: linear-gradient(118deg, transparent 30%, #000 40%, #000 48%, transparent 58%);
  animation: come-and-go 5s ease-in-out infinite alternate;
}
/* Theatre: deep red velvet hanging in folds, one spotlight, the house dark */
.board[data-room="theatre"] {
  background:
    repeating-linear-gradient(90deg, rgba(0, 0, 0, 0.24) 0, rgba(0, 0, 0, 0) 3%, rgba(255, 120, 120, 0.09) 6%, rgba(0, 0, 0, 0) 9%, rgba(0, 0, 0, 0.24) 12%),
    url("rough.png") #6e1218;
  box-shadow: none;
  --pin: #d4af37;
  --pin-2: #1a1a1a;
  --string: #d4af37;
}
.board[data-room="theatre"]::after {
  background: radial-gradient(ellipse 50% 44% at 50% 42%, rgba(255, 236, 200, 0.16), rgba(255, 236, 200, 0) 60%, rgba(8, 0, 0, 0.62));
}

/* Strings a strung board's prints hang from (js/board.js), behind the prints */
.board__strings {
  position: absolute;
  top: var(--board-pad);
  left: var(--board-pad);
  z-index: 0;
  width: calc(100% - 2 * var(--board-pad));
  height: calc(100% - 2 * var(--board-pad));
  overflow: visible;
  pointer-events: none;
  filter: drop-shadow(0 3px 2px rgba(0, 0, 0, 0.22));
}
.board__strings path { fill: none; stroke: var(--string); stroke-width: 1.3; }
.board__strings--wide { display: none; }
@media (min-width: 768px) {
  .board__strings--wide { display: block; }
  .board__strings--tall { display: none; }
}
/* On strings a print swings from its top edge */
.board[data-order="strung"] .print { transform-origin: 50% 0; }

@media (min-width: 768px) {
  :root {
    --board-pad: 40px;
    --edge-thin: 5px;
    --edge-plate: 13px;
    --nudge: 5px;
  }
  .board {
    width: calc(100% - 2 * var(--board-pad));
    margin: 0;
    aspect-ratio: var(--wide-shape, 1.4);
  }
}

/* --- Prints: each sits on its frame, nudged a little off it, and unless the board is tidy some
   hang crooked. Smaller prints lie on top of bigger ones (--z). The paper, grain and soft light
   go over the picture too, so it reads as ink on paper rather than a screen image in a white
   frame. Prints that don't lie flat (.print--uneven) bow off the card a few degrees. --- */
.print {
  --fx: var(--tx);
  --fy: var(--ty);
  --fw: var(--tw);
  --fh: var(--th);
  position: absolute;
  z-index: var(--z, 1);
  top: calc(var(--board-pad) + var(--fy) * (100% - 2 * var(--board-pad)));
  left: calc(var(--board-pad) + var(--fx) * (100% - 2 * var(--board-pad)));
  width: calc(var(--fw) * (100% - 2 * var(--board-pad)));
  height: calc(var(--fh) * (100% - 2 * var(--board-pad)));
  margin: 0;
  background: var(--paper, var(--color-print));
  box-shadow: var(--shadow-print);
  transform:
    translate(calc(var(--nx, 0) * var(--nudge)), calc(var(--ny, 0) * var(--nudge))) rotate(var(--tilt, 0deg))
    perspective(900px) rotateX(var(--warp-x, 0deg)) rotateY(var(--warp-y, 0deg));
  transition: transform var(--transition-fast), box-shadow var(--transition-fast);
}
@media (min-width: 768px) {
  .print { --fx: var(--wx); --fy: var(--wy); --fw: var(--ww); --fh: var(--wh); }
}
/* What lies over each picture, top first: the curl of an uneven print, its creases, the light
   on the paper, age spots, and the paper's grain. Creases show only on prints given a
   --crease-size. Each paper below swaps in its own layers. */
.print::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    var(--curl, none),
    url("crumple.png"),
    linear-gradient(165deg, rgba(255, 255, 255, 0.09), rgba(255, 255, 255, 0) 45%, rgba(70, 50, 20, 0.05)),
    none,
    url("paper.png");
  background-size: 100% 100%, var(--crease-size, 0 0), 100% 100%, 260px auto, auto;
  background-position: 0 0, var(--crease-at, center), 0 0, var(--spots-at, center), 0 0;
  background-repeat: no-repeat, no-repeat, no-repeat, no-repeat, repeat;
  pointer-events: none;
}
/* Smooth: photo paper, no grain, a soft sheen across it, colour as it is */
.board[data-paper="smooth"] .print::after {
  background-image:
    var(--curl, none),
    url("crumple.png"),
    linear-gradient(118deg, rgba(255, 255, 255, 0) 32%, rgba(255, 255, 255, 0.12) 46%, rgba(255, 255, 255, 0) 60%),
    none,
    none;
}
.board[data-paper="smooth"] { --print-filter: none; }
/* Rough: cotton paper with tooth, lit from the top left; colour quieter */
.board[data-paper="rough"] .print::after {
  background-image:
    var(--curl, none),
    url("crumple.png"),
    linear-gradient(160deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0) 40%, rgba(70, 50, 20, 0.08)),
    none,
    url("rough.png");
}
.board[data-paper="rough"] { --print-filter: contrast(0.9) saturate(0.8); }
/* Worn: toned at the edges, spotted with age, faded towards sepia */
.board[data-paper="worn"] .print::after {
  background-image:
    var(--curl, none),
    url("crumple.png"),
    radial-gradient(ellipse at center, rgba(120, 80, 30, 0) 55%, rgba(120, 80, 30, 0.22)),
    url("foxing.png"),
    url("rough.png");
}
.board[data-paper="worn"] { --print-filter: contrast(0.86) saturate(0.65) sepia(0.18); }
/* Instant: a square-ish picture in a white frame with a deep foot, its colour gone warm */
.board[data-paper="instant"] .print::after {
  background-image:
    var(--curl, none),
    url("crumple.png"),
    linear-gradient(125deg, rgba(255, 255, 255, 0) 35%, rgba(255, 255, 255, 0.1) 48%, rgba(255, 255, 255, 0) 60%),
    none,
    url("paper.png");
}
.board[data-paper="instant"] { --print-filter: contrast(0.88) saturate(0.82) sepia(0.14) brightness(1.04); }
/* Newsprint: cheap cream paper, the picture mostly grey and printed as a coarse screen of dots */
.board[data-paper="newsprint"] .print::after {
  background-image:
    var(--curl, none),
    url("crumple.png"),
    linear-gradient(170deg, rgba(255, 255, 255, 0.06), rgba(120, 100, 60, 0.1)),
    radial-gradient(circle, rgba(25, 22, 18, 0.2) 0.7px, rgba(25, 22, 18, 0) 1.3px),
    url("rough.png");
  background-size: 100% 100%, var(--crease-size, 0 0), 100% 100%, 3px 3px, auto;
  background-repeat: no-repeat, no-repeat, no-repeat, repeat, repeat;
}
.board[data-paper="newsprint"] { --print-filter: grayscale(0.85) sepia(0.15) contrast(1.15) brightness(1.03); }
.board[data-paper="newsprint"] .tile__img { mix-blend-mode: multiply; }   /* white is the paper's own cream */
/* Vellum: translucent tracing paper, the picture pale, whatever lies under a print showing through */
.board[data-paper="vellum"] .tile__img { opacity: 0.74; }
.board[data-paper="vellum"] .print { box-shadow: 0 0 0 0.5px rgba(60, 70, 80, 0.12), 0 2px 6px rgba(60, 70, 80, 0.08); }
.board[data-paper="vellum"] .print::after {
  background-image:
    var(--curl, none),
    url("crumple.png"),
    linear-gradient(rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0.1)),
    none,
    url("paper.png");
}
.board[data-paper="vellum"] { --print-filter: contrast(0.85) saturate(0.7) brightness(1.08); }
/* Cyanotype: the picture in Prussian blue (the filter is in index.html), brushed onto
   watercolour paper with ragged edges */
.board[data-paper="cyanotype"] .tile__img {
  filter: url("#cyanotype");
  -webkit-mask: url("brush.png") center / 100% 100% no-repeat;
  mask: url("brush.png") center / 100% 100% no-repeat;
}
.board[data-paper="cyanotype"] .print::after {
  background-image:
    var(--curl, none),
    url("crumple.png"),
    linear-gradient(160deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0) 40%, rgba(40, 50, 70, 0.06)),
    none,
    url("rough.png");
}
/* Torn: pages torn from magazines, glossy, the picture running to a ragged edge with the
   paper's white showing where it tore. js/board.js gives each its two edges. */
.board[data-paper="torn"] .print::after {
  background-image:
    var(--curl, none),
    url("crumple.png"),
    linear-gradient(118deg, rgba(255, 255, 255, 0) 30%, rgba(255, 255, 255, 0.1) 44%, rgba(255, 255, 255, 0) 58%),
    none,
    none;
}
.board[data-paper="torn"] { --print-filter: contrast(1.04) saturate(1.05); }

/* How the print was made: trimmed to the picture, a photo with a thin white border, or a plate
   cut from a book with a wide margin (a little deeper at the foot, as book plates are) */
.tile--trim { padding: 0; }
.tile--border { padding: var(--edge-thin); }
.tile--plate { padding: var(--edge-plate) var(--edge-plate) calc(var(--edge-plate) * 1.4); }
/* An instant print: the frame a share of the print's own width (padding is measured against
   the board, so this works it out from the print's frame) */
.tile--instant {
  --frame: calc(var(--fw) * (100% - 2 * var(--board-pad)));
  padding: calc(var(--frame) * 0.06) calc(var(--frame) * 0.06) calc(var(--frame) * 0.24);
}
.tile--instant .tile__img { outline: 1px solid rgba(0, 0, 0, 0.06); }
/* Pinned only at the top, so its foot lifts off the card a little */
.tile--lifted { box-shadow: var(--shadow-print), 0 10px 12px -10px rgba(50, 38, 20, 0.42); }
/* A torn print has no rectangle to cast a shadow: its white edge and the picture are cut out */
.print.print--torn { background: transparent; box-shadow: none; }
.print--torn .print__edge { position: absolute; inset: 0; background: var(--paper); clip-path: var(--torn-out); }
.print--torn .tile__img { position: relative; clip-path: var(--torn-in); }
.print--torn::after { clip-path: var(--torn-in); }

/* Matte print: blacks a touch lifted, colour a touch quieter */
.tile__img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: var(--color-skeleton);
  filter: var(--print-filter, contrast(0.94) saturate(0.88));
}

/* Pinned prints get a pin through the top */
.tile--pinned::before {
  content: "";
  position: absolute;
  top: 4px;
  left: 50%;
  z-index: 2;
  width: 10px;
  height: 10px;
  margin-left: -5px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #8d9de0, var(--color-accent) 55%, #0f1d55);
  box-shadow: 1px 2px 2px rgba(20, 15, 5, 0.35);
  pointer-events: none;
}

/* --- What holds the prints up (js/board.js): pins pushed in near the edge, tape, clips and
   pegs across it, photo corners round it. Each sits at --across and --down (shares of the
   print, 0 being the left or top edge), turned by --turn; rooms set their colours. --- */
.fix {
  position: absolute;
  z-index: 3;
  top: calc(var(--down) * 100% + (1 - 2 * var(--down)) * var(--inset, 0px));
  left: calc(var(--across) * 100% + (1 - 2 * var(--across)) * var(--inset, 0px));
  transform: translate(-50%, -50%) rotate(var(--turn, 0deg));
  pointer-events: none;
}
.fix--pin {
  --inset: 9px;
  --head: var(--pin);
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, rgba(255, 255, 255, 0.7), rgba(255, 255, 255, 0) 42%), var(--head);
  box-shadow: inset -1px -1px 2px rgba(0, 0, 0, 0.35), 2px 3px 2px rgba(20, 12, 4, 0.35);
}
.fix--pin.fix--other { --head: var(--pin-2); }
/* Masking tape, torn off the roll at both ends */
.fix--tape {
  --inset: 5px;
  width: clamp(30px, 32%, 92px);
  height: 13px;
  background: linear-gradient(rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0) 45%, rgba(0, 0, 0, 0.05)), var(--tape);
  clip-path: polygon(2% 0, 98% 0, 100% 18%, 97% 34%, 100% 52%, 98% 70%, 100% 86%, 97% 100%, 3% 100%, 0 82%, 2% 64%, 0 47%, 3% 30%, 0 14%);
}
/* A bulldog clip, its wire handles folded up */
.fix--clip {
  width: 26px;
  height: 12px;
  margin-top: 3px;
  border-radius: 2px 2px 1px 1px;
  background: linear-gradient(#6a6a6a, #2a2a2a 45%, #141414);
  filter: drop-shadow(1px 2px 1px rgba(0, 0, 0, 0.35));
}
.fix--clip::before {
  content: "";
  position: absolute;
  right: 20%;
  bottom: 75%;
  left: 20%;
  height: 11px;
  border: 1.5px solid #a7a7a7;
  border-bottom: 0;
  border-radius: 3px 3px 0 0;
}
/* A wooden clothes peg: two halves and a spring */
.fix--peg {
  width: 8px;
  height: 30px;
  margin-top: 4px;
  border-radius: 2px;
  background:
    linear-gradient(90deg, rgba(0, 0, 0, 0) 45%, rgba(60, 35, 10, 0.55) 48%, rgba(60, 35, 10, 0.55) 52%, rgba(0, 0, 0, 0) 55%),
    linear-gradient(rgba(0, 0, 0, 0) 40%, #8f8f8f 40%, #d2d2d2 45%, #858585 50%, rgba(0, 0, 0, 0) 50%),
    linear-gradient(90deg, #c49a64, #e3c596 45%, #b88a52);
  filter: drop-shadow(1px 2px 1px rgba(30, 18, 5, 0.35));
}
/* A photo corner: a paper pocket over the print's corner, its point just outside it */
.fix--corner {
  width: 20px;
  height: 20px;
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0) 55%), var(--corner);
  clip-path: polygon(35% 35%, 100% 35%, 35% 100%);
}
/* A kept print's own pin turns ink blue, instead of it getting a second one */
.board[data-fixing="pins"] .tile--pinned::before { display: none; }
.board[data-fixing="pins"] .tile--pinned .fix--pin { --head: var(--color-accent); }
@media (min-width: 768px) {
  .fix--pin { --inset: 12px; width: 14px; height: 14px; }
  .fix--tape { height: 20px; }
  .fix--clip { width: 34px; height: 15px; }
  .fix--clip::before { height: 14px; }
  .fix--peg { width: 10px; height: 40px; margin-top: 6px; }
  .fix--corner { width: 28px; height: 28px; }
}

@media (hover: hover) {
  .tile:hover {
    z-index: 30;
    box-shadow: var(--shadow-lift);
    transform:
      translate(calc(var(--nx, 0) * var(--nudge)), calc(var(--ny, 0) * var(--nudge) - 2px)) rotate(var(--tilt, 0deg))
      perspective(900px) rotateX(var(--warp-x, 0deg)) rotateY(var(--warp-y, 0deg));
  }
  .tile.print--torn:hover { box-shadow: none; }
}
@media (prefers-reduced-motion: reduce) {
  .print { transition: none; }
}

.tile__bar {
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 1;
  padding: var(--space-xxl) var(--space-sm) var(--space-xs);
  background: linear-gradient(transparent, var(--color-scrim));
  color: var(--color-on-image);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--transition-fast);
}
.tile__credit {
  margin: 0;
  overflow: hidden;
  color: var(--color-on-image-muted);
  font-size: var(--font-xs);
  white-space: nowrap;
  text-overflow: ellipsis;
}
.tile__credit a { color: inherit; text-decoration-color: currentColor; }
.tile__actions { display: flex; flex-wrap: wrap; gap: 0 var(--space-md); }
.tile__action {
  min-height: 32px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--color-on-image);
  font: var(--weight-medium) var(--font-sm)/1 var(--font-sans);
  cursor: pointer;
}
.tile__action:hover,
.tile__action--on { text-decoration: underline 1px; text-underline-offset: 4px; }

@media (hover: hover) {
  .tile:hover .tile__bar { opacity: 1; pointer-events: auto; }
}
.tile:focus-within .tile__bar,
.tile--active .tile__bar { opacity: 1; pointer-events: auto; }

/* --- Palette: the chapter's colours as a paint-chip card pinned with the prints; select one to copy it --- */
.palette {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: var(--edge-thin);
}
.palette__swatch {
  display: flex;
  position: relative;
  flex: 1;
  align-items: flex-end;
  min-height: 0;
  padding: var(--space-xs) var(--space-sm);
  border: 0;
  border-radius: 0;
  font: var(--weight-medium) 11px/1 var(--font-sans);
  font-variant-numeric: tabular-nums;
  text-align: left;
  cursor: copy;
}
.palette__hex { opacity: 0; transition: opacity var(--transition-fast); }
.palette:hover .palette__hex,
.palette__swatch:focus-visible .palette__hex { opacity: 0.85; }

/* --- Credits, folded away under the board --- */
.credits { max-width: 900px; margin-top: var(--space-xl); }
.credits__summary {
  display: inline-flex;
  align-items: center;
  min-height: var(--hit-target);
  color: var(--color-text-muted);
  font-size: var(--font-sm);
  list-style: none;
  cursor: pointer;
}
.credits__summary::-webkit-details-marker { display: none; }
.credits__summary::after { content: "+"; margin-left: var(--space-sm); }
details[open] > .credits__summary::after { content: "\2013"; }
.credits__list { margin: 0; padding-left: var(--space-xl); color: var(--color-text-faint); font-size: var(--font-xs); line-height: 1.8; }

/* --- Look further --- */
.further { max-width: 900px; margin-top: var(--space-xxxl); }
.further__title { margin: 0 0 var(--space-sm); font: var(--weight-regular) var(--font-xl)/var(--leading-head) var(--font-serif); }
.further__list { margin: var(--space-xl) 0 0; padding: 0; list-style: none; border-top: 1px solid var(--color-border); }
.further__item {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0 var(--space-xl);
  padding: var(--space-xs) 0;
  border-bottom: 1px solid var(--color-border);
}
.further__query { font: var(--weight-regular) var(--font-lg)/1.3 var(--font-serif); }
.further__links { display: flex; gap: var(--space-xl); }
.further__link { display: inline-flex; align-items: center; min-height: var(--hit-target); font-size: var(--font-sm); }

/* --- Settings: a full-height white sheet from the right edge --- */
.settings {
  width: min(460px, 100vw);
  height: 100dvh;
  max-width: 100vw;
  max-height: 100dvh;
  margin: 0 0 0 auto;
  padding: 0;
  border: 0;
  border-left: 1px solid var(--color-border);
  border-radius: 0;
  background: var(--color-bg) url("paper.png");
  box-shadow: var(--shadow-lift);
  color: var(--color-text);
}
.settings::backdrop { background: var(--color-overlay); }
.settings__form { display: grid; padding: var(--space-xxl) var(--space-xl); }
.settings__title { margin: 0 0 var(--space-xl); font: var(--weight-regular) var(--font-xl)/var(--leading-head) var(--font-serif); }
.settings__msg {
  margin: 0 0 var(--space-xl);
  padding-left: var(--space-md);
  border-left: 2px solid var(--color-accent);
  color: var(--color-text-muted);
  font-size: var(--font-sm);
}
.settings__check { display: flex; align-items: center; gap: var(--space-sm); min-height: 36px; cursor: pointer; }
.settings__check input { width: 16px; height: 16px; margin: 0; accent-color: var(--color-accent); }
.settings__advanced { margin-bottom: var(--space-xl); }
.settings__summary {
  display: inline-flex;
  align-items: center;
  min-height: var(--hit-target);
  font: var(--weight-medium) var(--font-sm)/1 var(--font-sans);
  list-style: none;
  cursor: pointer;
}
.settings__summary::-webkit-details-marker { display: none; }
.settings__summary::after { content: "+"; margin-left: var(--space-sm); }
details[open] > .settings__summary::after { content: "\2013"; }
.settings__actions { display: flex; align-items: center; justify-content: flex-end; gap: var(--space-xl); margin-top: var(--space-xl); }

/* --- Toast: a slip of paper laid over the page --- */
/* The SVG filters in index.html take no room */
.defs { position: absolute; }

.toast {
  position: fixed;
  bottom: max(var(--space-xl), env(safe-area-inset-bottom));
  left: 50%;
  z-index: 10;
  max-width: calc(100vw - var(--space-xxl));
  padding: var(--space-md) var(--space-lg);
  border: 1px solid var(--color-border);
  transform: translateX(-50%) rotate(-0.6deg);
  background: var(--color-sheet);
  box-shadow: var(--shadow-lift);
  color: var(--color-text);
  font-size: var(--font-sm);
}

@media (max-width: 767px) {
  .compose { padding-top: var(--space-xxl); }
  .topbar__links { gap: var(--space-lg); }
}
@media (max-width: 399px) {
  .compose__actions .button--primary { width: 100%; }
}
