/*
 * Site styles: a private-library look. Warm paper, dark ink, a bottle-green accent and
 * a brass highlight. Type is old print rather than app UI (DR-028 #2): IM Fell English,
 * cut from 17th-century Fell types, for the name and headings, its small caps for
 * buttons and labels, and Alegreya Sans, a calligraphic sans, for reading. The fonts
 * are vendored and served from this site, since nothing loads from outside the LAN.
 * Corners are nearly square and shadows short, like card stock rather than glass.
 * Colours are variables, so the dark theme (the device's setting) only swaps them.
 */

:root {
  --paper: #f6f1e7;
  --page: #fffdf8;
  --ink: #2a2520;
  --ink-soft: #6b6157;
  --rule: #e3d9c8;
  --accent: #2f5d50;
  --accent-strong: #234a3f;
  --accent-soft: #e4eee9;
  --brass: #a8782f;
  --brass-soft: #f6ead3;
  --danger: #a3341f;
  --danger-soft: #fbe7e2;
  --warn: #9a6a12;
  --warn-soft: #fdf3dc;
  --ok: #2f6b3a;
  --ok-soft: #e7f2e4;
  --shadow: 0 1px 0 rgb(42 37 32 / 10%), 0 3px 8px -4px rgb(42 37 32 / 22%);
  --radius: 3px;
  --serif: "IM Fell English", "Iowan Old Style", Palatino, Georgia, serif;
  --caps: "IM Fell English SC", "IM Fell English", Palatino, Georgia, serif;
  --sans: "Alegreya Sans", "Gill Sans", "Segoe UI", system-ui, sans-serif;
  /* Numbers standing on their own: IM Fell has only old-style figures, which rise and
     fall and ink unevenly, so counts and amounts use the plain face's even ones */
  --figures: "Alegreya Sans", "Gill Sans", "Segoe UI", system-ui, sans-serif;
  color-scheme: light;
}

@media (prefers-color-scheme: dark) {
  :root {
    --paper: #1b1917;
    --page: #24211e;
    --ink: #ece5d8;
    --ink-soft: #a89f92;
    --rule: #3a352f;
    --accent: #7fb8a4;
    --accent-strong: #9ccbb9;
    --accent-soft: #223731;
    --brass: #d6a55a;
    --brass-soft: #3a2f1e;
    --danger: #f08a73;
    --danger-soft: #3d221c;
    --warn: #e7b65c;
    --warn-soft: #3a2f19;
    --ok: #8fcf98;
    --ok-soft: #1f3322;
    --shadow: 0 1px 0 rgb(0 0 0 / 35%), 0 3px 8px -4px rgb(0 0 0 / 60%);
    color-scheme: dark;
  }
}

/* Page */

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

/* The body is its own stacking context, so the painted backdrop and the sparks (z-index
   below 0) always draw over its background; dark-mode extensions such as Dark Reader give
   <html> a background too, and the body's then covered them as far down as the content */
body {
  isolation: isolate;
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 1.0625rem;
  /* Even figures everywhere: Alegreya Sans defaults to old-style ones */
  font-variant-numeric: lining-nums;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

main {
  max-width: 64rem;
  margin: 0 auto;
  padding: 1.5rem 0.85rem 4rem;
}

/* One form field: label, help and input, spaced from the next and from the buttons */
.field {
  margin-bottom: 1.15rem;
}

.stacked .field {
  margin-bottom: 1.15rem;
}

.field + .actions,
.stacked .field + .actions,
.picture-form .actions {
  margin-top: 0.4rem;
}

h1,
h2,
h3 {
  font-family: var(--serif);
  font-weight: 400;
  line-height: 1.2;
  color: var(--ink);
}

h1 {
  margin: 0.25rem 0 0.75rem;
  font-size: clamp(1.7rem, 3.5vw, 2.3rem);
  letter-spacing: -0.01em;
}

h2 {
  margin: 2rem 0 0.75rem;
  padding-bottom: 0.3rem;
  border-bottom: 1px solid var(--rule);
  font-size: 1.35rem;
}

h3 {
  margin: 1.5rem 0 0.5rem;
  font-size: 1.1rem;
}

a {
  color: var(--accent);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}

a:hover {
  color: var(--accent-strong);
}

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

/* Header (DR-028 #3): the name, the universal search and you on the first row; your
   pages on a second row under the name */

.site-header {
  position: relative;
  /* Above the page, so its menus open over covers and cards */
  z-index: 30;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas:
    "name search you"
    "nav nav nav";
  gap: 0.55rem 1.5rem;
  align-items: center;
  padding: 0.7rem max(0.85rem, calc((100% - 64rem) / 2 + 0.85rem)) 0;
  --band: var(--accent-strong);
  background: var(--band);
  color: #f3ecdf;
  border-bottom: 3px double var(--brass);
}

@media (prefers-color-scheme: dark) {
  .site-header {
    --band: #16201d;
  }
}

.site-name {
  grid-area: name;
  display: inline-flex;
  gap: 0.6rem;
  align-items: center;
  font-family: var(--serif);
  font-size: 1.55rem;
  font-weight: 400;
  letter-spacing: 0.01em;
  color: #f8f1e3;
  text-decoration: none;
  white-space: nowrap;
}

.site-name:hover {
  color: #fff;
}

/* The mark: a book at the centre of a nexus. Hovered, light runs out along the threads
   and the nodes flare one after another */
.site-mark {
  width: 2.5rem;
  height: auto;
  overflow: visible;
}

.mark-web path {
  fill: none;
  stroke: currentColor;
  stroke-width: 1;
  opacity: 0.4;
}

.mark-web .mark-cross {
  opacity: 0.2;
}

.mark-threads path {
  stroke: currentColor;
  stroke-width: 1.4;
  stroke-linecap: round;
  stroke-dasharray: 14;
  stroke-dashoffset: 0;
}

.mark-nodes circle {
  fill: var(--brass);
  transform-box: fill-box;
  transform-origin: center;
}

.mark-book path {
  fill: none;
  stroke: #f8f1e3;
  stroke-width: 1.6;
  stroke-linejoin: round;
  stroke-linecap: round;
}


.site-name:hover .mark-threads path {
  animation: thread-run 1.6s ease-in-out infinite;
  animation-delay: calc(var(--i) * 0.12s);
}

.site-name:hover .mark-nodes circle {
  animation: node-flare 1.6s ease-in-out infinite;
  animation-delay: calc(var(--i) * 0.12s + 0.3s);
}

@keyframes thread-run {
  0% {
    stroke-dashoffset: 0;
  }

  50% {
    stroke-dashoffset: 28;
  }

  100% {
    stroke-dashoffset: 28;
  }
}

@keyframes node-flare {
  0%,
  100% {
    transform: scale(1);
    filter: none;
  }

  25% {
    transform: scale(1.45);
    filter: drop-shadow(0 0 3px #ffd98a);
  }
}

/* The universal search (DR-020): a pale pill in the green band */
.header-search {
  grid-area: search;
  display: flex;
  gap: 0.4rem;
  align-items: center;
  width: 100%;
  max-width: 36rem;
  margin: 0;
}

.header-search input[type="search"] {
  flex: 1;
  min-width: 0;
  padding: 0.5rem 1rem;
  border: 1px solid transparent;
  border-radius: 2px;
  background: rgb(255 253 248 / 92%);
  color: #2a2520;
}

.header-search input[type="search"]::placeholder {
  color: #7a7066;
}

.header-search input[type="search"]:focus {
  border-color: var(--brass);
  box-shadow: 0 0 0 3px rgb(168 120 47 / 35%);
}

.header-search button {
  padding: 0.45rem 0.9rem;
  border-color: rgb(255 255 255 / 40%);
  background: rgb(255 255 255 / 10%);
  color: #f8f1e3;
}

/* Search and Scan stand the same height side by side */
.header-search .book-button,
.header-search .scan-button {
  box-sizing: border-box;
  height: 2.2rem;
}

.header-search .scan-button {
  display: flex;
  align-items: center;
  padding-block: 0;
}

.header-search .scan-button[hidden] {
  display: none;
}

.header-search button:hover {
  background: rgb(255 255 255 / 20%);
  color: #fff;
}

.header-search button[type="submit"] {
  border-color: var(--brass);
  background: var(--brass);
  color: #fffaf0;
}

.header-search button[type="submit"]:hover {
  background: #b98a3f;
}

/* The search button: an open book seen from below (DR-022 #2). Hovered, its pages flip
   from cover to cover over and over and sparkles fly out of it; while searching the pages
   keep flipping (DR-028 #4) */
.header-search .book-button {
  position: relative;
  display: flex;
  gap: 0.45rem;
  align-items: center;
  padding: 0.2rem 0.9rem 0.2rem 0.65rem;
  overflow: visible;
}

.book-button-label {
  font-family: var(--caps);
  font-size: 1.05rem;
  font-weight: 400;
  letter-spacing: 0.03em;
}

.book-button svg {
  width: 2.2rem;
  height: auto;
  overflow: visible;
}

.book-button path {
  fill: none;
  stroke: currentColor;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.book-button .book-cover {
  stroke-width: 2.4;
}

.book-button .book-spine {
  stroke-width: 1.6;
}

/* At rest the six pages fan across the book */
.book-button .book-page {
  stroke-width: 1.3;
  opacity: 0.9;
  transform-box: view-box;
  transform-origin: 18px 22px;
  transform: rotate(calc(-38deg + var(--i) * 15deg));
}

.book-button:hover .book-page,
.book-button:focus-visible .book-page,
.book-button.is-busy .book-page {
  animation: page-flip 1.5s cubic-bezier(0.45, 0.05, 0.4, 1) infinite;
  animation-delay: calc(var(--i) * 0.25s - 1.5s);
}

/* Each page lies on the left cover, flips over to the right, then slips back unseen */
@keyframes page-flip {
  0% {
    opacity: 0;
    transform: rotate(-46deg);
  }

  8% {
    opacity: 0.95;
  }

  55% {
    opacity: 0.95;
    transform: rotate(46deg);
  }

  70%,
  100% {
    opacity: 0;
    transform: rotate(46deg);
  }
}

/* Sparkles: four-pointed glints that fly up and out of the pages and fade */
.book-sparks {
  position: absolute;
  top: 0.2rem;
  left: 1.75rem;
  width: 0;
  height: 0;
  pointer-events: none;
}

.book-sparks i {
  position: absolute;
  width: 0.55rem;
  height: 0.55rem;
  margin: -0.275rem;
  background: #fff6d8;
  clip-path: polygon(50% 0, 62% 38%, 100% 50%, 62% 62%, 50% 100%, 38% 62%, 0 50%, 38% 38%);
  filter: drop-shadow(0 0 2px #ffe08a);
  opacity: 0;
}

.book-sparks i:nth-child(1) { --x: -1.3rem; --y: -1.1rem; --d: 0s; }
.book-sparks i:nth-child(2) { --x: 1.2rem; --y: -1.3rem; --d: 0.25s; }
.book-sparks i:nth-child(3) { --x: -0.4rem; --y: -1.6rem; --d: 0.5s; }
.book-sparks i:nth-child(4) { --x: 1.6rem; --y: -0.5rem; --d: 0.75s; }
.book-sparks i:nth-child(5) { --x: -1.7rem; --y: -0.3rem; --d: 1s; }
.book-sparks i:nth-child(6) { --x: 0.5rem; --y: -1.7rem; --d: 1.25s; }

.book-button:hover .book-sparks i,
.book-button:focus-visible .book-sparks i {
  animation: sparkle-fly 1.5s ease-out infinite;
  animation-delay: var(--d);
}

@keyframes sparkle-fly {
  0% {
    opacity: 0;
    transform: translate(0, 0.6rem) scale(0.2) rotate(0);
  }

  20% {
    opacity: 1;
  }

  100% {
    opacity: 0;
    transform: translate(var(--x), var(--y)) scale(1) rotate(90deg);
  }
}

@media (prefers-reduced-motion: reduce) {
  .book-button .book-page,
  .book-sparks i,
  .mark-threads path,
  .mark-nodes circle {
    animation: none !important;
  }
}

/* The camera drops down under the header */
.header-search .scan-panel {
  position: absolute;
  top: calc(100% + 3px);
  left: 50%;
  z-index: 10;
  width: min(34rem, calc(100% - 1.5rem));
  padding: 0.75rem;
  border: 1px solid var(--rule);
  border-radius: 0 0 var(--radius) var(--radius);
  background: var(--page);
  color: var(--ink);
  box-shadow: var(--shadow);
  transform: translateX(-50%);
}

.header-search .scan-panel button {
  border-color: var(--accent);
  background: var(--page);
  color: var(--accent);
}

/* Your pages: small caps on the band's second row. Hovered, a sharp line of light rises
   up each side and sparks drift up through the button like a fire's (DR-028 #3) */
.site-nav {
  grid-area: nav;
  display: flex;
  flex-wrap: wrap;
  gap: 0 0.25rem;
  align-items: stretch;
  margin-left: -0.9rem;
}

.site-nav a {
  position: relative;
  display: inline-flex;
  align-items: center;
  padding: 0.35rem 0.9rem 0.5rem;
  overflow: hidden;
  color: #e9e0cf;
  font-family: var(--caps);
  font-size: 1.1rem;
  letter-spacing: 0.04em;
  text-decoration: none;
  white-space: nowrap;
  transition: color 0.2s, text-shadow 0.2s;
}

.site-nav a::before,
.site-nav a::after {
  content: "";
  position: absolute;
  bottom: 0;
  width: 1px;
  height: 100%;
  background: linear-gradient(0deg, transparent, #ffe2a0 30%, #fff 55%, transparent);
  box-shadow: 0 0 6px 1px rgb(255 205 110 / 75%);
  opacity: 0;
  transform: scaleY(0);
  transform-origin: bottom;
  transition: transform 0.35s cubic-bezier(0.2, 0.8, 0.3, 1), opacity 0.2s;
}

.site-nav a::before {
  left: 0;
}

.site-nav a::after {
  right: 0;
}

.site-nav a:hover,
.site-nav a:focus-visible {
  color: #fff;
  text-shadow: 0 0 10px rgb(255 214 130 / 70%);
}

.site-nav a:hover::before,
.site-nav a:hover::after,
.site-nav a:focus-visible::before,
.site-nav a:focus-visible::after {
  opacity: 1;
  transform: scaleY(1);
  animation: edge-glow 1.4s ease-in-out 0.35s infinite alternate;
}

@keyframes edge-glow {
  to {
    box-shadow: 0 0 10px 2px rgb(255 205 110 / 95%);
  }
}

/* The page you're on keeps a short brass rule beneath it */
.site-nav a[aria-current="page"] {
  color: #fff;
}

.site-nav a[aria-current="page"] .nav-label {
  box-shadow: 0 2px 0 var(--brass);
}

.nav-label {
  position: relative;
  z-index: 1;
}

.nav-sparks {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.nav-sparks i {
  position: absolute;
  bottom: -0.2rem;
  left: var(--x);
  width: var(--s);
  height: var(--s);
  border-radius: 50%;
  background: #ffd58a;
  box-shadow: 0 0 4px 1px rgb(255 170 60 / 80%);
  opacity: 0;
}

.nav-sparks i:nth-child(1) { --x: 12%; --s: 3px; --d: 0s; --t: 1.3s; --w: 4px; }
.nav-sparks i:nth-child(2) { --x: 27%; --s: 2px; --d: 0.45s; --t: 1.1s; --w: -5px; }
.nav-sparks i:nth-child(3) { --x: 41%; --s: 3px; --d: 0.9s; --t: 1.5s; --w: 3px; }
.nav-sparks i:nth-child(4) { --x: 55%; --s: 2px; --d: 0.2s; --t: 1.2s; --w: -3px; }
.nav-sparks i:nth-child(5) { --x: 68%; --s: 3px; --d: 0.7s; --t: 1.4s; --w: 5px; }
.nav-sparks i:nth-child(6) { --x: 80%; --s: 2px; --d: 1.1s; --t: 1s; --w: -4px; }
.nav-sparks i:nth-child(7) { --x: 90%; --s: 2px; --d: 0.35s; --t: 1.6s; --w: 2px; }

.site-nav a:hover .nav-sparks i,
.site-nav a:focus-visible .nav-sparks i {
  animation: spark-rise var(--t) ease-out var(--d) infinite;
}

@keyframes spark-rise {
  0% {
    opacity: 0;
    transform: translate(0, 0) scale(1);
  }

  15% {
    opacity: 1;
  }

  60% {
    transform: translate(var(--w), -1.6rem) scale(0.8);
  }

  100% {
    opacity: 0;
    transform: translate(calc(var(--w) * -0.5), -2.6rem) scale(0.3);
  }
}

@media (prefers-reduced-motion: reduce) {
  .nav-sparks i,
  .site-nav a::before,
  .site-nav a::after {
    animation: none !important;
  }
}

/* You, top right: an avatar that opens Account and Sign out */
.user-menu {
  grid-area: you;
  justify-self: end;
  position: relative;
  margin: 0;
}

.user-menu > summary {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  padding: 0.2rem 0.7rem 0.2rem 0.2rem;
  border-radius: 2px;
  background: rgb(255 255 255 / 10%);
  color: #f3ecdf;
  font-size: 0.92rem;
  list-style: none;
  cursor: pointer;
}

.user-menu > summary::-webkit-details-marker {
  display: none;
}

.user-menu > summary::after {
  content: "";
  width: 0.4rem;
  height: 0.4rem;
  margin-left: 0.1rem;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
  transition: transform 0.15s;
}

.user-menu[open] > summary::after {
  transform: translateY(1px) rotate(-135deg);
}

.user-menu > summary:hover {
  background: rgb(255 255 255 / 18%);
}

/* Profile pictures and icons (DR-021): round, with a brass ring */
.avatar {
  display: block;
  flex: none;
  width: 1.9rem;
  height: 1.9rem;
  border: 1.5px solid var(--brass);
  border-radius: 50%;
  object-fit: cover;
}

.avatar.medium {
  width: 3rem;
  height: 3rem;
}

.avatar.large {
  width: 5rem;
  height: 5rem;
  border-width: 2.5px;
  box-shadow: var(--shadow);
}

.avatar-icon g {
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.user-menu-items {
  position: absolute;
  top: calc(100% + 0.5rem);
  right: 0;
  z-index: 20;
  display: grid;
  min-width: 11rem;
  padding: 0.35rem;
  border: 1px solid var(--rule);
  border-top: 2px solid var(--brass);
  border-radius: var(--radius);
  background: var(--page);
  box-shadow: var(--shadow);
}

.user-menu-items a,
.user-menu-items button {
  display: block;
  width: 100%;
  padding: 0.5rem 0.75rem;
  border: none;
  border-radius: 6px;
  background: none;
  color: var(--ink);
  font: inherit;
  text-align: left;
  text-decoration: none;
}

/* Menu items: hovered, a fleuron slides in at the left (DR-028 #2) */
.user-menu-items a,
.user-menu-items button,
.more-menu-items a {
  position: relative;
  transition: padding-left 0.18s, background 0.15s, color 0.15s;
}

.user-menu-items a::before,
.user-menu-items button::before,
.more-menu-items a::before {
  content: "\2766";
  position: absolute;
  left: 0.45rem;
  color: var(--brass);
  opacity: 0;
  transform: translateX(-0.4rem);
  transition: opacity 0.18s, transform 0.18s;
}

.user-menu-items a:hover,
.user-menu-items button:hover,
.more-menu-items a:hover {
  padding-left: 1.6rem;
  background: var(--accent-soft);
  color: var(--accent-strong);
}

.user-menu-items a:hover::before,
.user-menu-items button:hover::before,
.more-menu-items a:hover::before {
  opacity: 1;
  transform: none;
}

.user-menu-items form {
  margin: 0;
  border-top: 1px solid var(--rule);
  padding-top: 0.35rem;
  margin-top: 0.35rem;
}

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

/* Small type */

.muted,
.helptext {
  color: var(--ink-soft);
}

.crumbs {
  margin: 0 0 0.25rem;
  color: var(--ink-soft);
  font-size: 0.9rem;
}

.crumbs a {
  color: var(--ink-soft);
}

.subtitle {
  margin-top: -0.4rem;
  font-family: var(--serif);
  font-size: 1.15rem;
  font-style: italic;
  color: var(--ink-soft);
}

.description {
  max-width: 42rem;
  font-family: var(--serif);
  font-size: 1.05rem;
}

/* Notices */

.messages {
  list-style: none;
  margin: 0 0 1rem;
  padding: 0;
}

.messages li + li {
  margin-top: 0.5rem;
}

.notice,
.warning {
  padding: 0.65rem 0.9rem;
  border: 1px solid transparent;
  border-left-width: 4px;
  border-radius: 6px;
}

.notice {
  border-color: var(--ok-soft);
  border-left-color: var(--ok);
  background: var(--ok-soft);
}

.warning {
  border-color: var(--warn-soft);
  border-left-color: var(--warn);
  background: var(--warn-soft);
}

.warning p:first-child,
.notice p:first-child {
  margin-top: 0;
}

.warning p:last-child,
.notice p:last-child {
  margin-bottom: 0;
}

.error,
.errorlist {
  color: var(--danger);
}

.errorlist {
  margin: 0.2rem 0;
  padding: 0;
  list-style: none;
  font-size: 0.92rem;
}

.ok {
  color: var(--ok);
}

/* Buttons: links styled as buttons and a form's own submit are the main action;
   buttons in rows (Remove, Skip) stay quiet. Each is a small printed label: square
   corners, small caps, and a second hairline rule inside the border, which turns brass
   when hovered (DR-028 #2) */

.button,
.button-quiet,
button {
  --plate-gap: var(--page);
  --plate-rule: color-mix(in srgb, var(--accent) 28%, transparent);
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.38rem 1.05rem 0.44rem;
  border: 1px solid var(--accent);
  border-radius: 2px;
  background: var(--page);
  color: var(--accent);
  font-family: var(--caps);
  font-size: 1.05rem;
  font-weight: 400;
  letter-spacing: 0.03em;
  line-height: 1.3;
  text-decoration: none;
  cursor: pointer;
  box-shadow: inset 0 0 0 2px var(--plate-gap), inset 0 0 0 3px var(--plate-rule);
  transition: background 0.15s, color 0.15s, border-color 0.15s, box-shadow 0.15s;
}

.button-quiet:hover,
button:hover {
  --plate-gap: var(--accent-soft);
  --plate-rule: var(--brass);
  background: var(--accent-soft);
  color: var(--accent-strong);
}

.button:active,
button:active {
  transform: translateY(1px);
}

/* Buttons drawn some other way keep their own look */
ul.tags button,
.view-switch button,
.shelf-dots button,
.user-menu-items button,
.cover-option,
.cover-change,
.picker-close,
.switch-save {
  box-shadow: none;
}

.button,
.stacked > button[type="submit"] {
  --plate-gap: var(--accent);
  --plate-rule: rgb(255 236 200 / 45%);
  background: var(--accent);
  border-color: var(--accent);
  color: #fdf9f0;
}

.button:hover,
.stacked > button[type="submit"]:hover {
  --plate-gap: var(--accent-strong);
  --plate-rule: var(--brass);
  background: var(--accent-strong);
  border-color: var(--accent-strong);
  color: #fff;
}

@media (prefers-color-scheme: dark) {
  .button,
  .stacked > button[type="submit"] {
    --plate-rule: rgb(16 32 27 / 45%);
    color: #10201b;
  }
}

button:disabled {
  opacity: 0.55;
  cursor: default;
}

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 0.75rem;
  align-items: center;
}

.actions form {
  margin: 0;
}

/* Forms */

.stacked fieldset {
  margin: 0 0 1.25rem;
  padding: 1rem 1.25rem 0.5rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--page);
  box-shadow: var(--shadow);
}

.stacked legend {
  padding: 0 0.4rem;
  font-family: var(--serif);
  font-size: 1.1rem;
  font-weight: 400;
}

.stacked label {
  display: block;
  margin-bottom: 0.2rem;
  font-weight: 600;
  font-size: 0.92rem;
}

.stacked div {
  margin-bottom: 0.8rem;
}

/* Django's field groups come without a wrapper: a label after another field's box gets
   the same space above it as a wrapped field would */
.stacked :is(input, select, textarea, .helptext, .errorlist, .field, div, fieldset) + label,
.stacked :is(input, select, textarea, .helptext, .errorlist) + :is(.field, fieldset) {
  margin-top: 0.9rem;
}

/* A file picker: a dashed drop area with a soft tab, unlike the solid buttons */
input[type="file"] {
  display: block;
  width: 100%;
  max-width: 30rem;
  margin: 0.25rem 0 0.75rem;
  padding: 0.55rem;
  border: 1.5px dashed var(--rule);
  border-radius: var(--radius);
  background: var(--paper);
  color: var(--ink-soft);
  font-size: 0.9rem;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
}

input[type="file"]:hover {
  border-color: var(--brass);
  background: var(--brass-soft);
}

input[type="file"]::file-selector-button {
  margin-right: 0.8rem;
  padding: 0.4rem 0.85rem;
  border: none;
  border-radius: 6px;
  background: var(--brass-soft);
  color: var(--ink);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  box-shadow: inset 0 -2px 0 rgb(0 0 0 / 8%);
}

input[type="file"]:hover::file-selector-button {
  background: var(--brass);
  color: #fffaf0;
}

/* Browsers count pointing at a field's label as pointing at the field: while its label
   is the thing under the pointer, the picker stays as it is (owner, 2026-11-04) */
:has(> label:hover) > input[type="file"]:hover {
  border-color: var(--rule);
  background: var(--paper);
}

:has(> label:hover) > input[type="file"]:hover::file-selector-button {
  background: var(--brass-soft);
  color: var(--ink);
}

input:not([type="checkbox"], [type="radio"], [type="hidden"], [type="file"]),
select,
textarea {
  padding: 0.45rem 0.6rem;
  border: 1px solid var(--rule);
  border-radius: 6px;
  background: var(--page);
  color: var(--ink);
  font: inherit;
  transition: border-color 0.15s, box-shadow 0.15s;
}

input:not([type="checkbox"], [type="radio"], [type="hidden"], [type="file"]):focus,
select:focus,
textarea:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
  outline: none;
}

.stacked input:not([type="checkbox"], [type="radio"], [type="hidden"]),
.stacked select,
.stacked textarea {
  width: 100%;
  max-width: 32rem;
}

/* Fields are inline by default, so a button after the last one would sit beside it on
   its baseline; in a stacked form each field and the button get a line of their own */
.stacked input:not([type="checkbox"], [type="radio"], [type="hidden"]),
.stacked select,
.stacked textarea {
  display: block;
}

input[type="checkbox"],
input[type="radio"] {
  accent-color: var(--accent);
}

/* Lookup and filter rows: fields and button side by side when they fit */

.lookup-form {
  display: flex;
  flex-wrap: wrap;
  gap: 0 0.75rem;
  align-items: end;
}

.lookup-form input:not([type="checkbox"], [type="radio"], [type="hidden"]) {
  width: 16rem;
}

/* A label beside its field (Started: on Start reading) sits level with it, and the two
   wrap onto a new line together; a note or button in that row sits level too */
.inline-field {
  display: flex;
  gap: 0.5rem;
  align-items: center;
}

.inline-field label,
.lookup-form > .inline-field {
  margin: 0;
}

.lookup-form:has(> .inline-field) {
  gap: 0.6rem 1rem;
  align-items: center;
}

.lookup-form:has(> .inline-field) > p {
  margin: 0;
}

/* Search your library (DR-019 #4): a card with a brass edge, unlike the header search */
.library-search {
  margin: 1.25rem 0 1.5rem;
  padding: 1rem 1.25rem;
  border: 1px solid var(--rule);
  border-left: 4px solid var(--brass);
  border-radius: var(--radius);
  background: var(--page);
  box-shadow: var(--shadow);
}

.library-search-row label {
  display: block;
  margin-bottom: 0.35rem;
  font-family: var(--serif);
  font-size: 1.1rem;
  font-weight: 400;
}

.library-search-field {
  display: flex;
  gap: 0.5rem;
}

.library-search-field input[type="search"] {
  flex: 1;
  min-width: 0;
}

/* The Filter panel: folded away, its options in titled groups (DR-019 #5) */
.filter-panel {
  margin: 0.9rem 0 0;
}

.filter-panel > summary {
  display: inline-flex;
  gap: 0.4rem;
  align-items: center;
  padding: 0.3rem 0.85rem;
  border: 1px solid var(--rule);
  border-radius: 2px;
  color: var(--accent);
  font-weight: 600;
  list-style: none;
  cursor: pointer;
}

.filter-panel > summary::-webkit-details-marker {
  display: none;
}

.filter-panel > summary::before {
  content: "\25B8";
  transition: transform 0.15s;
}

.filter-panel[open] > summary::before {
  transform: rotate(90deg);
}

.filter-groups {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  gap: 1rem;
  margin-top: 1rem;
}

.filter-group {
  margin: 0;
  padding: 0.75rem 1rem 0.25rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--paper);
}

.filter-group legend {
  padding: 0 0.35rem;
  font-family: var(--serif);
  font-weight: 400;
}

.filter-field {
  margin-bottom: 0.7rem;
}

.filter-field label {
  display: block;
  margin-bottom: 0.2rem;
  color: var(--ink-soft);
  font-size: 0.88rem;
  font-weight: 600;
}

.filter-field select,
.filter-field input {
  width: 100%;
}

.filter-actions {
  display: flex;
  gap: 0.75rem;
  align-items: center;
  margin-top: 1rem;
}

.filter-actions button {
  --plate-gap: var(--accent);
  --plate-rule: rgb(255 236 200 / 45%);
  background: var(--accent);
  border-color: var(--accent);
  color: #fdf9f0;
}

@media (prefers-color-scheme: dark) {
  .filter-actions button {
    color: #10201b;
  }
}

/* Panels and settings rows (account page, Add a book, new library) */
.panel {
  margin: 1.25rem 0;
  padding: 1rem 1.25rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--page);
  box-shadow: var(--shadow);
}

.panel > h2:first-child {
  margin-top: 0.25rem;
}

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

.settings-list li {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1rem;
  align-items: center;
  justify-content: space-between;
  padding: 0.65rem 0;
  border-top: 1px solid var(--rule);
}

.settings-name {
  font-weight: 600;
}

.settings-form {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  margin: 0;
}

.settings-form select {
  max-width: 20rem;
}

/* A date (or a limitation) on one line: each label level with the box beside it */
.date-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 0.75rem;
  align-items: center;
}

.stacked .date-row label {
  margin-bottom: 0;
}

.date-row .date-label {
  flex-basis: 100%;
  font-weight: 600;
  font-size: 0.92rem;
}

.date-row input:not([type="checkbox"]) {
  width: 6rem;
}

/* The date's labels sit beside their boxes, so no space above them; the Circa box lines
   up with the middle of the date boxes */
.stacked .date-row :is(input, select) + label {
  margin-top: 0;
}

.date-row input[type="checkbox"] {
  align-self: center;
}

.stacked table.rows {
  width: 100%;
  border-collapse: collapse;
}

/* A select and a text box side by side are one height */
.stacked table.rows :is(input, select) {
  width: 100%;
  height: 2.6rem;
  margin: 0;
}

.stacked table.rows th {
  padding-bottom: 0.3rem;
  text-align: left;
  font-size: 0.9rem;
  color: var(--ink-soft);
}

.stacked table.rows td {
  padding: 0.2rem 0.4rem 0.2rem 0;
}

details {
  margin: 1rem 0;
}

details summary {
  cursor: pointer;
  color: var(--accent);
  font-weight: 600;
}

/* Book lists: each book a card, its cover alongside */

.book-list {
  display: grid;
  gap: 0.75rem;
  margin: 1rem 0;
  padding: 0;
  list-style: none;
}

.book-list li {
  padding: 0.85rem 1rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--page);
  box-shadow: var(--shadow);
  transition: border-color 0.15s, transform 0.15s;
}

.book-list li:hover {
  border-color: var(--brass);
}

.book-list li strong {
  font-family: var(--serif);
  font-size: 1.08rem;
}

.book-list li a {
  text-decoration: none;
}

.book-list li a:hover {
  text-decoration: underline;
}

.book-list li.with-cover {
  display: flex;
  gap: 1rem;
  align-items: flex-start;
}

.book-list li.actions {
  justify-content: space-between;
}

.book-list li .grow {
  flex: 1;
}

.book-list li .actions {
  margin-top: 0.5rem;
}

/* Working: a spinner on busy buttons and while results load (DR-020) */
.spinner {
  display: inline-block;
  width: 0.95em;
  height: 0.95em;
  border: 2px solid currentcolor;
  border-right-color: transparent;
  border-radius: 50%;
  vertical-align: -0.12em;
  animation: spin 0.7s linear infinite;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

@media (prefers-reduced-motion: reduce) {
  .spinner {
    animation-duration: 2s;
  }
}

.loading {
  display: flex;
  gap: 0.6rem;
  align-items: center;
  padding: 1rem 1.25rem;
  border: 1px dashed var(--rule);
  border-radius: var(--radius);
  color: var(--ink-soft);
}

.is-busy {
  cursor: progress;
  opacity: 0.85;
}

/* Covers and photos */

img.cover,
img.thumb {
  flex: none;
  width: 4.25rem;
  height: auto;
  border-radius: 3px;
  box-shadow: 0 1px 2px rgb(0 0 0 / 25%), 2px 3px 8px rgb(0 0 0 / 15%);
}

img.cover.large {
  display: block;
  width: auto;
  max-width: 12rem;
  max-height: 18rem;
  margin: 0.75rem 0 1rem;
  border-radius: 4px;
}

/* A book's page: the cover beside its title, synopsis and ratings */
.book-head {
  display: flex;
  gap: 1.5rem;
  align-items: flex-start;
  margin-bottom: 1rem;
}

.book-head img.cover.large {
  flex: none;
  margin: 0.3rem 0 0;
  box-shadow: 0 1px 2px rgb(0 0 0 / 25%), 4px 6px 18px rgb(0 0 0 / 22%);
}

.book-head-text {
  flex: 1;
  min-width: 0;
}

.title-row {
  display: flex;
  gap: 1rem;
  align-items: flex-start;
  justify-content: space-between;
}

.title-row h1 {
  margin-bottom: 0.15rem;
}

.byline {
  margin: 0.2rem 0 0.75rem;
  color: var(--ink-soft);
  font-family: var(--serif);
  font-size: 1.1rem;
  font-style: italic;
}

.synopsis {
  max-width: 42rem;
  margin: 0 0 1rem;
  line-height: 1.6;
}

.ratings {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 2.5rem;
  margin: 0;
}

.ratings dt {
  color: var(--ink-soft);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.ratings dd {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  margin: 0.2rem 0 0;
}

/* Five stars, filled to --stars (0 to 5) */
.stars {
  --percent: calc(var(--stars, 0) / 5 * 100%);
  display: inline-block;
  font-size: 1.15rem;
  line-height: 1;
  letter-spacing: 0.1em;
}

.stars::before {
  content: "\2605\2605\2605\2605\2605";
  background: linear-gradient(90deg, var(--brass) var(--percent), var(--rule) var(--percent));
  background-clip: text;
  -webkit-background-clip: text;
  color: transparent;
}

/* A round icon button, like the book page's Your reading */
.icon-button {
  display: grid;
  flex: none;
  place-items: center;
  width: 3rem;
  height: 3rem;
  border: 1.5px solid var(--accent);
  border-radius: 50%;
  background: var(--page);
  color: var(--accent);
  box-shadow: var(--shadow);
  transition: background 0.15s, color 0.15s, transform 0.15s;
}

.icon-button:hover {
  background: var(--accent);
  color: var(--page);
  transform: translateY(-1px);
}

.icon-button svg {
  width: 1.6rem;
  height: 1.6rem;
}

/* The book page's Start reading, a button in a form of its own */
.icon-form {
  flex: none;
  margin: 0;
}

button.icon-button {
  padding: 0;
  letter-spacing: 0;
}

/* A library: actions on the left, value and tools on the right */
.library-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1.5rem;
  align-items: center;
  justify-content: space-between;
  margin: 0.5rem 0 1.25rem;
}

.library-bar .actions {
  margin: 0;
}

.library-tools {
  display: flex;
  gap: 0.6rem 1.25rem;
  align-items: center;
  margin-left: auto;
}

.collection-value {
  margin: 0;
  text-align: right;
}

.collection-value-label {
  display: block;
  color: var(--ink-soft);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* Amounts in the plain face with even, lining figures: the old face's italic numerals
   rose and fell and inked unevenly, which made totals hard to read */
.collection-value-amount {
  display: block;
  color: var(--brass);
  font-family: var(--sans);
  font-size: 1.5rem;
  font-variant-numeric: lining-nums tabular-nums;
  font-weight: 600;
  letter-spacing: 0.01em;
  line-height: 1.15;
}

.collection-value-amount small {
  margin-left: 0.2rem;
  color: var(--ink-soft);
  font-family: var(--sans);
  font-size: 0.75rem;
  font-style: normal;
  font-weight: 500;
  letter-spacing: 0.05em;
}

.money {
  color: var(--brass);
  font-family: var(--sans);
  font-variant-numeric: lining-nums tabular-nums;
  font-weight: 600;
}

.icon-link {
  position: relative;
  display: grid;
  place-items: center;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 50%;
  color: var(--ink-soft);
  transition: background 0.15s, color 0.15s;
}

.icon-link:hover {
  background: var(--accent-soft);
  color: var(--accent-strong);
}

.icon-link svg {
  width: 1.4rem;
  height: 1.4rem;
}

.icon-link .badge {
  position: absolute;
  top: 0;
  right: -0.1rem;
  min-width: 1.15rem;
  padding: 0 0.3rem;
  border-radius: 999px;
  background: var(--danger);
  color: #fff;
  font-size: 0.7rem;
  font-weight: 700;
  line-height: 1.15rem;
  text-align: center;
}

.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
  gap: 0.9rem;
  padding: 0;
  list-style: none;
}

.gallery img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 6px;
  box-shadow: var(--shadow);
}

.photo-pending {
  display: flex;
  flex-direction: column;
  justify-content: center;
  aspect-ratio: 4 / 3;
  padding: 0.5rem;
  border: 1px dashed var(--rule);
  border-radius: 6px;
  background: var(--page);
  color: var(--ink-soft);
}

.photo-large img {
  max-width: 100%;
  height: auto;
  border-radius: 6px;
  box-shadow: var(--shadow);
}

/* Camera scanner (DR-016): the live picture, one barcode at a time */
.scan-panel {
  flex-basis: 100%;
}

.scan-panel video {
  display: block;
  width: 100%;
  max-width: 32rem;
  border-radius: var(--radius);
  background: #000;
}

/* Facts about a book: label and value side by side */

.facts {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.35rem 1.25rem;
  max-width: 46rem;
  padding: 1rem 1.25rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--page);
  box-shadow: var(--shadow);
}

.facts dt {
  color: var(--ink-soft);
  font-size: 0.92rem;
  font-weight: 600;
}

.facts dd {
  margin: 0;
}

@media (max-width: 34rem) {
  .facts {
    grid-template-columns: 1fr;
    gap: 0;
  }

  .facts dd {
    margin-bottom: 0.45rem;
  }
}

/* Markers and tags */

.marker {
  display: inline-block;
  margin-left: 0.4rem;
  padding: 0.05rem 0.55rem;
  border-radius: 999px;
  background: var(--brass-soft);
  color: var(--brass);
  font-family: var(--sans);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  vertical-align: middle;
}

ul.tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
  margin: 0.5rem 0 1rem;
  padding: 0;
  list-style: none;
}

/* A tag is a little luggage label in its colour, with a punched hole at the left
   (DR-029 #6); without a colour it takes the theme's soft accent */
ul.tags li {
  --tag: var(--accent-soft);
  --tag-ink: var(--accent-strong);
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.1rem;
  padding: 0.12rem 0.15rem 0.12rem 1.15rem;
  border-radius: 2px 3px 3px 2px;
  background: var(--tag);
  color: var(--tag-ink);
  font-size: 0.95rem;
  clip-path: polygon(0.55rem 0, 100% 0, 100% 100%, 0.55rem 100%, 0 50%);
}

ul.tags li::before {
  content: "";
  position: absolute;
  left: 0.55rem;
  width: 0.3rem;
  height: 0.3rem;
  border-radius: 50%;
  background: var(--paper);
  box-shadow: inset 0 0 0 1px rgb(0 0 0 / 15%);
}

ul.tags a {
  color: inherit;
  text-decoration: none;
  font-weight: 500;
}

ul.tags a:hover {
  color: inherit;
  text-decoration: underline;
}

ul.tags form {
  margin: 0;
}

ul.tags button {
  padding: 0 0.4rem;
  border: none;
  background: transparent;
  color: inherit;
  font-family: var(--sans);
  font-size: 1.05rem;
  line-height: 1.3;
  opacity: 0.7;
}

ul.tags button:hover {
  background: rgb(0 0 0 / 12%);
  color: inherit;
  opacity: 1;
}

ul.plain {
  padding: 0;
  list-style: none;
}

/* Sections with their own heading anchor */

section[id] {
  scroll-margin-top: 1rem;
}

.conflict {
  margin-bottom: 1.25rem;
  padding: 0.25rem 1.25rem 0.75rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--page);
  box-shadow: var(--shadow);
}

.conflict h2 {
  border-bottom: none;
}

/* The wishlist row on a book page, clear of the tags above it */
#wishlist {
  margin-top: 1.5rem;
}

/* A library's books (DR-022 #3): tiles or the condensed list, with a switch, and the
   sort beside it */
.library-tools {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 0.9rem;
  align-items: center;
  justify-content: flex-end;
  margin: -0.25rem 0 0.75rem;
}

.library-sort {
  display: inline-flex;
  gap: 0.45rem;
  align-items: center;
  color: var(--ink-soft);
  font-size: 0.9rem;
}

.library-sort select {
  height: 2.3rem;
  padding-block: 0;
}

.view-switch {
  display: flex;
  justify-content: flex-end;
  gap: 0.25rem;
  margin: 0;
}

.view-switch button {
  display: grid;
  place-items: center;
  width: 2.3rem;
  height: 2.3rem;
  padding: 0;
  border: 1px solid var(--rule);
  background: var(--page);
  color: var(--ink-soft);
}

.view-switch button svg {
  width: 1.25rem;
  height: 1.25rem;
}

.view-switch button[aria-pressed="true"] {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--accent-strong);
}

.book-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr));
  gap: 1.75rem 1.25rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.book-tile {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  color: var(--ink);
  text-decoration: none;
}

.book-tile:hover {
  text-decoration: none;
}

.tile-book {
  position: relative;
  display: block;
  aspect-ratio: 2 / 3;
  margin-bottom: 0.5rem;
  border-radius: 2px 5px 5px 2px;
  box-shadow: 0 1px 2px rgb(0 0 0 / 25%), 3px 5px 14px rgb(42 37 32 / 22%);
  transform-origin: left center;
  transition: transform 0.25s ease, box-shadow 0.25s ease;
}

/* The spine's crease and a sheen across the cover make it read as a book */
.tile-book::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(
    90deg,
    rgb(0 0 0 / 22%) 0,
    rgb(255 255 255 / 18%) 3%,
    rgb(0 0 0 / 10%) 6%,
    transparent 10%,
    transparent 85%,
    rgb(255 255 255 / 8%) 100%
  );
  pointer-events: none;
}

.book-tile:hover .tile-book,
.book-tile:focus-visible .tile-book {
  transform: perspective(600px) rotateY(-14deg) translateY(-3px);
  box-shadow: 0 1px 2px rgb(0 0 0 / 25%), 10px 12px 22px rgb(42 37 32 / 28%);
}

.tile-book img {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: inherit;
  object-fit: cover;
}

.tile-count {
  position: absolute;
  right: 0.35rem;
  bottom: 0.35rem;
  z-index: 1;
  padding: 0 0.4rem;
  border-radius: 999px;
  background: rgb(20 18 16 / 75%);
  color: #f6ead3;
  font-family: var(--figures);
  font-size: 0.75rem;
  font-variant-numeric: lining-nums tabular-nums;
  font-weight: 600;
}

.tile-title {
  font-family: var(--serif);
  font-weight: 400;
  line-height: 1.25;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
}

.book-tile:hover .tile-title {
  color: var(--accent-strong);
}

.tile-author {
  color: var(--ink-soft);
  font-size: 0.85rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* A coverless book: cloth boards with the title stamped in gilt */
.cloth-cover {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  height: 100%;
  padding: 18% 10% 12%;
  border-radius: inherit;
  background:
    repeating-linear-gradient(45deg, rgb(255 255 255 / 4%) 0 2px, transparent 2px 4px),
    linear-gradient(160deg, var(--cloth-light), var(--cloth));
  color: #e9cf8f;
  font-family: var(--serif);
  text-align: center;
  box-shadow: inset 0 0 0 4px rgb(0 0 0 / 12%), inset 0 0 0 5px rgb(233 207 143 / 45%);
}

.cloth-0 { --cloth: #2f5d50; --cloth-light: #3d7465; }
.cloth-1 { --cloth: #6e2a2a; --cloth-light: #8a3a37; }
.cloth-2 { --cloth: #263a5e; --cloth-light: #34507d; }
.cloth-3 { --cloth: #4a3b2a; --cloth-light: #66523b; }
.cloth-4 { --cloth: #4b2f5a; --cloth-light: #654077; }
.cloth-5 { --cloth: #3e4a2a; --cloth-light: #57663b; }

.cloth-title {
  font-size: 0.95rem;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: 0.02em;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 4;
  overflow: hidden;
}

.cloth-author {
  font-size: 0.7rem;
  font-variant: small-caps;
  letter-spacing: 0.08em;
}

.book-table {
  width: 100%;
  border-collapse: collapse;
  background: var(--page);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow: hidden;
}

.book-table th {
  padding: 0.6rem 0.75rem;
  border-bottom: 1px solid var(--rule);
  color: var(--ink-soft);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-align: left;
  text-transform: uppercase;
}

.book-table td {
  padding: 0.45rem 0.75rem;
  border-bottom: 1px solid var(--rule);
  vertical-align: middle;
}

.book-table tr:last-child td {
  border-bottom: none;
}

.book-table tbody tr:hover {
  background: var(--accent-soft);
}

.book-table-cover {
  width: 3.25rem;
}

.book-table-cover img,
.book-table-cover .cloth-cover {
  display: block;
  width: 2.5rem;
  height: 3.75rem;
  padding: 0;
  border-radius: 2px;
  object-fit: cover;
  box-shadow: 0 1px 2px rgb(0 0 0 / 25%);
}

.book-table a {
  color: var(--ink);
  text-decoration: none;
}

.book-table a:hover {
  color: var(--accent-strong);
  text-decoration: underline;
}

.book-table-author {
  display: block;
  color: var(--ink-soft);
  font-size: 0.9rem;
}

.book-table-series {
  color: var(--ink-soft);
  font-family: var(--serif);
  font-style: italic;
}

/* Theme picker: a swatch of each theme */
.theme-picker fieldset {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: 1rem;
  margin: 0 0 1rem;
  padding: 0;
  border: none;
}

.theme-choice {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  padding: 0.75rem;
  border: 1.5px solid var(--rule);
  border-radius: var(--radius);
  cursor: pointer;
  transition: border-color 0.15s, box-shadow 0.15s;
}

.theme-choice input {
  position: absolute;
  opacity: 0;
}

.theme-choice:has(input:checked) {
  border-color: var(--brass);
  box-shadow: 0 0 0 3px var(--brass-soft);
}

.theme-choice:has(input:focus-visible) {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.theme-swatch {
  display: flex;
  gap: 0.35rem;
  align-items: flex-end;
  height: 5rem;
  margin-bottom: 0.4rem;
  padding: 1.4rem 0.75rem 0.5rem;
  position: relative;
  border-radius: 6px;
  overflow: hidden;
}

.swatch-band {
  position: absolute;
  inset: 0 0 auto;
  height: 0.9rem;
}

.swatch-book {
  width: 1.4rem;
  height: 2.6rem;
  border-radius: 1px 3px 3px 1px;
}

.swatch-book:nth-child(3) {
  height: 3rem;
}

.theme-swatch-bookish {
  background: #f6f1e7;
}

.theme-swatch-bookish .swatch-band {
  background: #234a3f;
  border-bottom: 2px solid #a8782f;
}

.theme-swatch-bookish .swatch-book:nth-child(2) { background: #2f5d50; }
.theme-swatch-bookish .swatch-book:nth-child(3) { background: #6e2a2a; }
.theme-swatch-bookish .swatch-book:nth-child(4) { background: #a8782f; }

.theme-swatch-galactic {
  background:
    radial-gradient(1px 1px at 20% 30%, #fff, transparent),
    radial-gradient(1px 1px at 70% 60%, #fff, transparent),
    radial-gradient(1.5px 1.5px at 85% 25%, #cfe3ff, transparent),
    radial-gradient(1px 1px at 45% 80%, #fff, transparent),
    radial-gradient(ellipse at 75% 30%, rgb(140 82 255 / 55%), transparent 60%),
    radial-gradient(ellipse at 20% 90%, rgb(40 170 220 / 40%), transparent 55%),
    #070a1a;
}

.theme-swatch-galactic .swatch-band {
  background: rgb(15 18 40 / 80%);
  border-bottom: 1px solid rgb(160 140 255 / 50%);
}

.theme-swatch-galactic .swatch-book:nth-child(2) { background: #6b5bd6; }
.theme-swatch-galactic .swatch-book:nth-child(3) { background: #2bb3d9; }
.theme-swatch-galactic .swatch-book:nth-child(4) { background: #e6c46a; }

.theme-swatch-fire {
  background:
    radial-gradient(1.5px 1.5px at 25% 40%, #ffc56b, transparent),
    radial-gradient(1px 1px at 65% 25%, #ff8a3d, transparent),
    radial-gradient(1.5px 1.5px at 85% 50%, #ffd98a, transparent),
    radial-gradient(ellipse 80% 55% at 50% 110%, rgb(255 90 20 / 60%), transparent 70%),
    #140a06;
}

.theme-swatch-fire .swatch-band {
  background: #1d0f09;
  border-bottom: 1px solid rgb(255 140 60 / 70%);
}

.theme-swatch-fire .swatch-book:nth-child(2) { background: #8a2a12; }
.theme-swatch-fire .swatch-book:nth-child(3) { background: #e0661f; }
.theme-swatch-fire .swatch-book:nth-child(4) { background: #ffcb57; }

/* The home page tome (DR-023): a leather-bound book with gilt lettering. Hovered, its
   cover swings open and a leaf turns again and again through the library's covers
   (static/js/tome.js). The cover's and leaf's timings match tome.js. */
.home-hero {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem 2.5rem;
  align-items: center;
  margin: 0.5rem 0 2.5rem;
}

.tome {
  --tome-w: 12.5rem;
  --tome-h: 17.5rem;
  --gilt: linear-gradient(180deg, #f9e7ad 0%, #d4a24a 42%, #f6dc94 55%, #a8742a 100%);
  --leather: #5a2a18;
  /* Painted leather, paper and spine (DR-043) over the colours they replace */
  --tome-cover: url("/static/img/generated/tome/cover-bookish.webp");
  --tome-paper: url("/static/img/generated/tome/page.webp");
  display: block;
  flex: none;
  width: calc(var(--tome-w) * 2 + 1rem);
  height: calc(var(--tome-h) + 1rem);
  padding: 0.5rem 0;
  color: inherit;
  text-decoration: none;
}

.tome:hover {
  text-decoration: none;
}

.tome:focus-visible {
  outline: none;
}

.tome:focus-visible .tome-board {
  box-shadow: 0 0 0 3px var(--page), 0 0 0 6px var(--accent);
}

.tome-book {
  position: relative;
  display: block;
  width: var(--tome-w);
  height: var(--tome-h);
  margin-left: calc(var(--tome-w) / 2 + 0.75rem);
  perspective: 2200px;
  transition: transform 0.9s cubic-bezier(0.45, 0.05, 0.25, 1);
}

.tome.is-open .tome-book {
  transform: translateX(calc(var(--tome-w) / 2));
}

/* Back board and cover share the painted leather, lit a little from the top left */
.tome-board,
.cover-front {
  background:
    radial-gradient(ellipse at 28% 18%, rgb(255 220 180 / 12%), transparent 55%),
    var(--tome-cover) center / 100% 100% no-repeat,
    var(--leather);
}

.tome-board {
  position: absolute;
  inset: -0.35rem -0.45rem -0.35rem 0;
  border-radius: 2px 6px 6px 2px;
  box-shadow: 0 2px 3px rgb(0 0 0 / 30%), 8px 14px 30px rgb(42 37 32 / 35%);
  transition: box-shadow 0.9s;
}

.tome.is-open .tome-board {
  box-shadow: 0 2px 3px rgb(0 0 0 / 30%), 0 18px 34px rgb(42 37 32 / 35%),
    calc(var(--tome-w) * -1) 18px 34px rgb(42 37 32 / 30%);
}

.tome-spine {
  position: absolute;
  top: -0.35rem;
  bottom: -0.35rem;
  left: -1rem;
  width: 1.1rem;
  border-radius: 6px 2px 2px 6px;
  box-shadow: inset -3px 0 4px rgb(0 0 0 / 35%);
  transition: opacity 0.4s;
}

/* The painted spine, with its raised bands and gilt rules, toned to each theme's leather */
.tome-spine {
  background: url("/static/img/generated/tome/spine.webp") center / 100% 100% no-repeat, var(--leather);
}

[data-theme="galactic"] .tome-spine {
  filter: hue-rotate(195deg) saturate(0.8) brightness(0.75);
}

[data-theme="fire"] .tome-spine {
  filter: hue-rotate(-12deg) saturate(1.1) brightness(0.6);
}

.tome.is-open .tome-spine {
  opacity: 0;
}

/* Pages: the right-hand page, and the leaf that turns over it */
.tome-page,
.leaf-front .leaf-layer,
.leaf-flat .leaf-layer,
.cover-inside {
  background:
    linear-gradient(90deg, rgb(90 60 30 / 18%), transparent 12%),
    var(--tome-paper) center / 100% 100% no-repeat,
    #f6eedb;
}

.tome-page {
  position: absolute;
  inset: 0.15rem 0.1rem 0.15rem 0;
  display: grid;
  place-items: center;
  padding: 0;
  border-radius: 0 3px 3px 0;
  /* The edges of the pages beneath */
  box-shadow: 1px 0 0 #e6d8b8, 2px 0 0 #f6eedb, 3px 0 0 #e2d2ae, 4px 0 0 #f3e8d0;
}

/* A cover fills its whole page, cropped rather than squeezed, and a little enlarged so
   a scan's own white border falls outside the page */
.tome-page {
  overflow: hidden;
}

.tome-page img,
.leaf-layer img {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  scale: 1.06;
}

/* The gutter's shade lies over the cover too */
.tome-page:has(img)::before,
.leaf-front .leaf-layer::before,
.leaf-flat .leaf-layer::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(90deg, rgb(40 25 10 / 30%), transparent 9%);
  pointer-events: none;
}

.tome-empty {
  color: #8a7860;
  font-family: var(--serif);
  font-style: italic;
  text-align: center;
}

/* The turning leaf: tome.js builds it from --strips narrow strips, each hinged to the
   one before it, so the page can bend, and turns it frame by frame on a smooth curve:
   the leaf swings about the spine while every strip bends a little more than the one
   before, the free edge leading, then trailing and settling last, as paper does. The
   bend's shade deepens towards the free edge (--shade, set by tome.js). The script sets
   each strip's transform itself, so the browser only moves layers it has already drawn */
.tome-leaf {
  position: absolute;
  inset: 0.15rem 0.1rem 0.15rem 0;
  z-index: 2;
  transform-origin: left center;
  transform-style: preserve-3d;
  visibility: hidden;
  will-change: transform;
}

/* Between turns the page beneath shows the cover whole, without the strips' joins */
.tome-leaf.is-turning {
  visibility: visible;
}

.leaf-strip {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: calc(100% / var(--strips));
  transform-origin: left center;
  transform-style: preserve-3d;
  will-change: transform;
}

/* Each strip hangs from the free edge of the one before */
.leaf-strip .leaf-strip {
  left: 100%;
  width: 100%;
}

/* A face reaches two pixels past its strip, under the next one, showing the same part of
   the picture there, so no seam opens between them */
.leaf-face {
  position: absolute;
  inset: 0 -2px 0 0;
  overflow: hidden;
  backface-visibility: hidden;
}

/* The back a hair behind the front, so its edges never show through the picture */
.leaf-back {
  transform: rotateY(180deg) translateZ(0.5px);
}

/* The whole page behind each strip, shifted so the strip shows its own slice of it
   (100% - 2px is the strip's own width; the back starts those pixels further in) */
.leaf-layer {
  position: absolute;
  top: 0;
  bottom: 0;
  left: calc(var(--from) * (2px - 100%));
  width: calc(var(--strips) * (100% - 2px));
}

.leaf-back > .leaf-layer {
  left: calc(2px + var(--from) * (2px - 100%));
}

.leaf-last > .leaf-front {
  border-radius: 0 3px 3px 0;
}

.leaf-last > .leaf-back {
  border-radius: 3px 0 0 3px;
}

/* The bend's shade: tome.js sets each strip's own --shade */
.leaf-face::after {
  content: "";
  position: absolute;
  inset: 0;
  background: rgb(50 32 15);
  opacity: var(--shade, 0);
  pointer-events: none;
}

.leaf-back::after {
  opacity: calc(var(--shade, 0) * 0.7);
}

/* While the leaf still lies flat it is one whole picture; the strips take over once it
   lifts, where their joins no longer show (tome.js, is-lifted) */
.leaf-flat {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border-radius: 0 3px 3px 0;
  backface-visibility: hidden;
}

.leaf-flat .leaf-layer {
  left: 0;
  width: 100%;
}

.tome-leaf > .leaf-strip,
.tome-leaf.is-lifted .leaf-flat {
  visibility: hidden;
}

.tome-leaf.is-lifted > .leaf-strip {
  visibility: visible;
}

/* The leaf's shadow sweeps across the page beneath */
.tome-page::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(90deg, rgb(42 30 18 / 30%), transparent 60%);
  opacity: 0;
  pointer-events: none;
}

.tome.is-turning .tome-page::after {
  animation: leaf-shadow 1.6s ease-out forwards;
}

@keyframes leaf-shadow {
  0% {
    opacity: 0.9;
  }
  100% {
    opacity: 0;
  }
}

.cover-front,
.cover-inside {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
}

.cover-inside {
  transform: rotateY(180deg);
}

.leaf-back .leaf-layer,
.cover-inside {
  border-radius: 3px 0 0 3px;
  background:
    linear-gradient(270deg, rgb(90 60 30 / 18%), transparent 12%),
    var(--tome-paper) center / 100% 100% no-repeat,
    #f6eedb;
}

/* The left-hand page names the book on the right */
.tome-caption {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  align-items: center;
  justify-content: center;
  height: 100%;
  padding: 1.25rem 1.5rem 1.25rem 1rem;
  color: #3a2a1a;
  font-family: var(--serif);
  text-align: center;
}

.cap-ornament {
  color: #a8742a;
  font-size: 1.4rem;
}

.cap-title {
  font-size: 1.05rem;
  font-style: italic;
  font-weight: 600;
  line-height: 1.25;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 4;
  overflow: hidden;
}

.cap-author {
  color: #7a6448;
  font-size: 0.75rem;
  font-variant: small-caps;
  letter-spacing: 0.08em;
}

/* The cover: leather and gilt outside, a page inside. It drops beneath the turning leaf
   once it is past upright, and comes back above it at the same point when closing. */
.tome-cover {
  position: absolute;
  inset: -0.35rem -0.45rem -0.35rem 0;
  z-index: 3;
  transform-origin: left center;
  transform-style: preserve-3d;
  transition: transform 0.9s cubic-bezier(0.45, 0.05, 0.25, 1), z-index 0s 0.45s;
}

.tome.is-open .tome-cover {
  z-index: 1;
  transform: rotateY(-180deg);
}

/* The board's inside: leather turned in round the edges of the pasted-down page, so the
   open cover keeps its border. Set a hair behind the page so the two never flicker */
.tome-cover::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 6px 2px 2px 6px;
  background:
    radial-gradient(ellipse at 72% 18%, rgb(255 220 180 / 10%), transparent 55%),
    var(--tome-cover) center / 100% 100% no-repeat,
    var(--leather);
  box-shadow: inset -4px 0 6px rgb(0 0 0 / 30%);
  transform: rotateY(180deg) translateZ(-1px);
  backface-visibility: hidden;
}

/* Once open, the inside of the cover is the left-hand page: flush against the spine and
   the same size as the turning leaf, so a turned leaf and the page beneath it match */
.tome.is-open .cover-inside {
  inset: 0.5rem 0.55rem 0.5rem 0;
}

.cover-front {
  display: grid;
  place-items: center;
  border-radius: 2px 6px 6px 2px;
  box-shadow: inset 4px 0 6px rgb(0 0 0 / 30%), inset 0 0 0 1px rgb(255 230 190 / 10%);
}

.tome:hover .cover-front,
.tome:focus-visible .cover-front {
  filter: brightness(1.06);
}

/* The painted covers carry their own corner pieces */
.tome-corners {
  display: none;
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  fill: none;
  stroke: #d6a952;
  stroke-width: 1.2;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
  opacity: 0.85;
}

.tome-corners * {
  vector-effect: non-scaling-stroke;
}

.tome-title {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 0 1rem;
  font-family: var(--serif);
  text-align: center;
  filter: drop-shadow(0 1px 0 rgb(0 0 0 / 55%)) drop-shadow(0 -1px 0 rgb(255 230 180 / 15%));
}

.tome-your,
.tome-library,
.tome-name {
  background: var(--gilt);
  background-clip: text;
  -webkit-background-clip: text;
  color: transparent;
}

.tome-your {
  font-size: 1.35rem;
  font-style: italic;
  line-height: 1;
}

.tome-library {
  font-size: 2.25rem;
  font-variant: small-caps;
  font-weight: 600;
  letter-spacing: 0.1em;
  line-height: 1.1;
}

.tome-flourish {
  width: 7rem;
  margin: 0.35rem 0 0.5rem;
  fill: none;
  stroke: #d6a952;
  stroke-width: 1.3;
  stroke-linecap: round;
}

.tome-name {
  max-width: 9rem;
  font-size: 0.72rem;
  letter-spacing: 0.16em;
  line-height: 1.4;
  text-transform: uppercase;
}

.home-welcome {
  flex: 1 1 16rem;
}

.home-greeting {
  margin: 0;
  color: var(--brass);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.home-welcome h1 {
  margin: 0.1rem 0 0.5rem;
  font-size: 2.4rem;
}

[data-theme="galactic"] .tome {
  --leather: #1b2350;
  --tome-cover: url("/static/img/generated/tome/cover-galactic.webp");
}

[data-theme="fire"] .tome {
  --leather: #3d140b;
  --tome-cover: url("/static/img/generated/tome/cover-fire.webp");
}


/* Embers glowing in the fire edition's leather */
[data-theme="fire"] .cover-front::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background:
    radial-gradient(1.4px 1.4px at 22% 78%, #ffb35c, transparent),
    radial-gradient(1px 1px at 70% 86%, #ff8a3d, transparent),
    radial-gradient(1.2px 1.2px at 82% 64%, #ffcf6b, transparent),
    radial-gradient(ellipse 90% 35% at 50% 100%, rgb(255 110 30 / 28%), transparent 70%);
}


@media (prefers-reduced-motion: reduce) {
  .tome-book,
  .tome-cover,
  .tome.is-turning .tome-page::after {
    animation-duration: 0.01s;
  }
}

@media (max-width: 34rem) {
  .tome {
    --tome-w: 9.5rem;
    --tome-h: 13.5rem;
  }

  .tome-library {
    font-size: 1.7rem;
  }

  .tome-your {
    font-size: 1.1rem;
  }
}

/* Switches (DR-024): a checkbox drawn as a sliding switch. Forms that save on change
   (showcase.js) hide their Save button. */
.switch {
  display: inline-flex;
  gap: 0.5rem;
  align-items: center;
  cursor: pointer;
  font-weight: 500;
}

.switch input {
  position: absolute;
  opacity: 0;
}

.switch-track {
  position: relative;
  flex: none;
  width: 2.5rem;
  height: 1.4rem;
  border-radius: 999px;
  background: var(--rule);
  box-shadow: inset 0 1px 2px rgb(0 0 0 / 20%);
  transition: background 0.2s;
}

.switch-thumb {
  position: absolute;
  top: 0.15rem;
  left: 0.15rem;
  width: 1.1rem;
  height: 1.1rem;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 3px rgb(0 0 0 / 30%);
  transition: transform 0.2s cubic-bezier(0.3, 1.4, 0.5, 1);
}

.switch input:checked + .switch-track {
  background: var(--accent);
}

.switch input:checked + .switch-track .switch-thumb {
  transform: translateX(1.1rem);
}

.switch input:focus-visible + .switch-track {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.switch-form {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  margin: 0;
}

form.is-auto .switch-save {
  display: none;
}

/* Spotlight this book: a card on the copy page that glows gold when on */
.spotlight-panel {
  display: flex;
  gap: 1rem;
  align-items: center;
  margin: 1.25rem 0;
  padding: 0.9rem 1.1rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--page);
  box-shadow: var(--shadow);
  transition: border-color 0.3s, box-shadow 0.3s;
}

.spotlight-panel.is-on {
  border-color: var(--brass);
  box-shadow: 0 0 0 3px var(--brass-soft), var(--shadow);
}

.spotlight-icon {
  flex: none;
  width: 2.2rem;
  height: 2.2rem;
  fill: var(--rule);
  transition: fill 0.3s, transform 0.4s;
}

.spotlight-panel.is-on .spotlight-icon {
  fill: var(--brass);
  transform: rotate(72deg);
  filter: drop-shadow(0 0 6px rgb(214 165 90 / 60%));
}

.spotlight-fields {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: 0.3rem;
}

.spotlight-photo {
  display: flex;
  gap: 0.4rem;
  align-items: center;
  font-size: 0.92rem;
}

/* First-time notes: a friendly card over a soft blur */
.intro-dialog {
  max-width: min(28rem, calc(100% - 2rem));
  padding: 1.5rem 1.75rem 1.25rem;
  border: 1px solid var(--rule);
  border-radius: 4px;
  background: var(--page);
  color: var(--ink);
  box-shadow: 0 20px 60px rgb(0 0 0 / 35%);
  text-align: center;
}

[data-theme="galactic"] .intro-dialog {
  background: #141838;
}

[data-theme="fire"] .intro-dialog,
[data-theme="fire"] .cover-picker {
  background: #22130c;
}


.intro-dialog[open] {
  animation: intro-in 0.35s cubic-bezier(0.2, 0.9, 0.3, 1.2);
}

.intro-dialog::backdrop {
  background: rgb(20 18 16 / 45%);
  backdrop-filter: blur(3px);
}

.intro-dialog h2 {
  margin: 0.25rem 0 0.5rem;
  border: none;
}

.intro-dialog .actions {
  justify-content: center;
  margin-top: 1rem;
}

.intro-art {
  color: var(--accent);
}

.intro-art svg {
  width: 9rem;
  height: auto;
  overflow: visible;
}

.intro-door {
  transform-box: fill-box;
  transform-origin: left center;
  animation: door 1.6s 0.3s ease-in-out both;
}

.intro-art-spotlight {
  color: var(--brass);
}

.intro-beam {
  fill: var(--brass);
  opacity: 0.18;
  animation: beam 2.4s ease-in-out infinite alternate;
}

@keyframes intro-in {
  from {
    opacity: 0;
    transform: translateY(12px) scale(0.96);
  }
}

@keyframes door {
  to {
    transform: scaleX(0.25);
  }
}

@keyframes beam {
  to {
    opacity: 0.4;
  }
}

/* The showcase (DR-024) */
.showcase {
  margin: 2.5rem 0;
}

.showcase-head h2 {
  margin-bottom: 0.2rem;
}

.showcase-head p {
  margin-top: 0;
}

.showcase-sub {
  margin: 1.5rem 0 0.75rem;
  color: var(--ink-soft);
  font-family: var(--sans);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.showcase-empty,
.shelf-empty {
  color: var(--ink-soft);
  font-family: var(--serif);
  font-style: italic;
}

/* Spotlighted books stand at an angle, showing their page edges, and turn to face you */
.spotlight-row {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr));
  gap: 1.75rem 1.5rem;
  margin: 0;
  padding: 0.5rem 0;
  list-style: none;
}

.spot-book {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.6rem;
  outline: none;
  animation: rise 1.6s calc(var(--i) * 180ms) cubic-bezier(0.2, 0.8, 0.3, 1) both;
}

.book3d {
  position: relative;
  display: block;
  width: 7rem;
  aspect-ratio: 2 / 3;
  transform: perspective(700px) rotateY(-28deg);
  transform-style: preserve-3d;
  transition: transform 0.5s cubic-bezier(0.3, 0.8, 0.3, 1);
}

.spot-book:hover .book3d,
.spot-book:focus-visible .book3d {
  transform: perspective(700px) rotateY(0) translateY(-6px) scale(1.04);
}

.book3d-front {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border-radius: 2px 4px 4px 2px;
  box-shadow: 6px 10px 20px rgb(0 0 0 / 30%);
  transform: translateZ(0.6rem);
}

.book3d-front img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.book3d-front::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, rgb(0 0 0 / 22%), rgb(255 255 255 / 15%) 3%, transparent 9%);
}

.book3d-pages {
  position: absolute;
  top: 0.2rem;
  right: 0;
  bottom: 0.2rem;
  width: 1.2rem;
  background: repeating-linear-gradient(90deg, #f7f0dc 0 1px, #e3d6b6 1px 2px);
  transform: translateX(0.6rem) rotateY(90deg);
}

.spot-card {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  max-width: 100%;
  text-align: center;
}

.spot-card strong {
  font-family: var(--serif);
  line-height: 1.25;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
}

.spot-card span {
  color: var(--ink-soft);
  font-size: 0.85rem;
}

.spot-owner {
  display: inline-flex;
  gap: 0.35rem;
  align-items: center;
  justify-content: center;
  margin-top: 0.2rem;
}

.spot-owner .avatar {
  width: 1.3rem;
  height: 1.3rem;
  border-width: 1px;
}

@keyframes rise {
  from {
    opacity: 0;
    transform: translateY(18px);
  }
}

/* Public libraries: one carved bookcase shelf at a time */
.shelf-carousel {
  position: relative;
}

.shelf-track {
  position: relative;
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  border-radius: 12px;
}

.shelf-track::-webkit-scrollbar {
  display: none;
}

.shelf-slide {
  position: relative;
  flex: 0 0 100%;
  padding: 1.1rem 1.5rem 0;
  scroll-snap-align: start;
  border: 10px solid transparent;
  border-image: linear-gradient(180deg, #8a5a32, #5a3519 40%, #3e2410) 1;
  background:
    radial-gradient(ellipse 70% 60% at 50% 0%, rgb(255 210 140 / 22%), transparent 70%),
    repeating-linear-gradient(90deg, rgb(0 0 0 / 0%) 0 38px, rgb(0 0 0 / 6%) 38px 40px),
    linear-gradient(180deg, #4a2c17, #2f1b0d);
  color: #f6ead3;
}

.shelf-head {
  display: flex;
  gap: 0.75rem;
  align-items: center;
  margin-bottom: 1rem;
}

.shelf-head strong {
  display: block;
  font-family: var(--serif);
  font-size: 1.25rem;
}

.shelf-head .muted {
  color: #d9c7a4;
}

.shelf {
  display: flex;
  gap: 0.9rem;
  align-items: flex-end;
  justify-content: center;
  min-height: 9.5rem;
  margin: 0;
  padding: 0 0.5rem;
  list-style: none;
  perspective: 900px;
  /* Clip sideways only, so books can drop in from above */
  overflow-x: clip;
}

.shelf-book {
  position: relative;
  flex: none;
  width: 4.8rem;
  aspect-ratio: 2 / 3;
  border-radius: 2px 4px 4px 2px;
  box-shadow: 0 2px 3px rgb(0 0 0 / 45%), 4px 8px 14px rgb(0 0 0 / 40%);
  transform-origin: center bottom;
}

.shelf-book img,
.shelf-book .cloth-cover {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: inherit;
  object-fit: cover;
}

.shelf-book .cloth-cover {
  padding: 18% 8%;
}

.shelf-book .cloth-title {
  font-size: 0.68rem;
}

.shelf-book.is-spotlight::after {
  content: "\2605";
  position: absolute;
  top: -0.55rem;
  right: -0.45rem;
  display: grid;
  place-items: center;
  width: 1.3rem;
  height: 1.3rem;
  border-radius: 50%;
  background: #d6a952;
  color: #3a2410;
  font-size: 0.75rem;
  box-shadow: 0 0 8px rgb(240 201 106 / 80%);
}

.shelf-carousel.is-live .shelf-slide:not(.is-shown) .shelf-book {
  opacity: 0;
}

.shelf-slide.is-shown .shelf-book {
  animation: twirl 2.3s calc(var(--i) * 260ms) cubic-bezier(0.2, 0.75, 0.25, 1.1) both;
}

/* The plank the books land on, with a lip catching the light */
.shelf-plank {
  height: 1.3rem;
  margin: 0 -1.5rem;
  background:
    linear-gradient(180deg, #b07a46 0, #8a5a32 22%, #6b4122 60%, #4a2c15 100%);
  box-shadow: 0 6px 12px rgb(0 0 0 / 45%);
}

.shelf-dots {
  display: flex;
  gap: 0.5rem;
  justify-content: center;
  margin-top: 0.8rem;
}

.shelf-dots button {
  width: 0.65rem;
  height: 0.65rem;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: var(--rule);
  transition: width 0.3s, background 0.3s;
}

.shelf-dots button[aria-current="true"] {
  width: 1.6rem;
  border-radius: 999px;
  background: var(--brass);
}

@keyframes twirl {
  0% {
    opacity: 0;
    transform: translateY(-6rem) rotateY(540deg) rotateZ(-14deg) scale(0.55);
  }

  55% {
    opacity: 1;
  }

  75% {
    transform: translateY(0.35rem) rotateY(-10deg) rotateZ(1deg) scale(1.03);
  }

  90% {
    transform: translateY(-0.1rem) rotateY(3deg) scale(0.99);
  }

  100% {
    transform: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .spot-book,
  .shelf-slide.is-shown .shelf-book {
    animation: none;
  }
}

/*
 * The bookcase (static/js/showcase.js): one library at a time, three shelves filling
 * spine by spine. Each book shows its cover in the middle first, then turns onto the
 * shelf; once full, a sparkling light runs behind the books.
 */
.shelf-carousel.is-case .shelf-slide:not(.is-current) {
  display: none;
}

.shelf-carousel.is-case .shelf-track {
  overflow: visible;
}

/* A painted bookcase (owner, 2026-11-04): three bays of 255 px in a 1762 by 1049 picture,
   each bay's top at 84 + 282 x its number and its floor 255 px below; books stand
   between x 154 and 1620 (static/img/generated/showcase/, docs/generated-images.md). The
   shelves are placed from those numbers, so the books sit on the painted boards at any
   width */
.bookcase {
  --case-tint: transparent;
  position: relative;
  max-width: 62rem;
  aspect-ratio: 1762 / 1049;
  margin: 0 auto 1.1rem;
  background: url("/static/img/generated/showcase/bookcase-1600.webp") center / 100% 100% no-repeat;
  filter: drop-shadow(0 12px 22px rgb(0 0 0 / 45%));
  transition: opacity 0.6s ease;
}

/* The themes' colour, laid over the wood only (the picture is its own mask) */
.bookcase::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  background: var(--case-tint);
  mix-blend-mode: color;
  -webkit-mask: url("/static/img/generated/showcase/bookcase-1000.webp") center / 100% 100% no-repeat;
  mask: url("/static/img/generated/showcase/bookcase-1000.webp") center / 100% 100% no-repeat;
  pointer-events: none;
}

.bookcase.is-leaving {
  opacity: 0;
}

.bookcase-shelf {
  position: absolute;
  top: calc((84 + var(--i, 0) * 282) / 1049 * 100%);
  right: calc(142 / 1762 * 100%);
  left: calc(154 / 1762 * 100%);
  display: flex;
  gap: 3px;
  align-items: flex-end;
  height: calc(255 / 1049 * 100%);
  padding: 0 0.3rem;
}

.spine {
  position: relative;
  flex: none;
  width: var(--w);
  height: var(--h);
  overflow: hidden;
  border-radius: 2px 2px 1px 1px;
  background:
    linear-gradient(90deg, rgb(0 0 0 / 45%), rgb(255 255 255 / 12%) 22%, rgb(255 255 255 / 0%) 45%, rgb(0 0 0 / 35%)),
    linear-gradient(rgb(20 12 6 / 40%), rgb(20 12 6 / 40%)),
    var(--img, none) 12% 50% / auto 100% no-repeat,
    var(--cloth, #5a3519);
  box-shadow: inset 0 0 0 1px rgb(0 0 0 / 35%), 2px 0 3px rgb(0 0 0 / 35%);
  opacity: 0;
  transform-origin: center bottom;
}

/* Gilt bands near the head and tail of each spine */
.spine::before,
.spine::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  height: 2px;
  background: linear-gradient(90deg, #8a6a2c, #f2d68a, #8a6a2c);
  opacity: 0.85;
}

.spine::before {
  top: 9%;
}

.spine::after {
  bottom: 9%;
}

.spine-title {
  position: absolute;
  inset: 16% 0;
  display: block;
  overflow: hidden;
  color: #f6ead3;
  font-family: var(--serif);
  font-size: calc(0.72rem * max(var(--spine-scale, 1), 0.75));
  line-height: var(--w);
  text-align: center;
  text-overflow: ellipsis;
  text-shadow: 0 1px 2px rgb(0 0 0 / 85%);
  white-space: nowrap;
  writing-mode: vertical-rl;
}

.spine.is-in {
  opacity: 1;
  animation: spine-in 0.45s cubic-bezier(0.2, 0.7, 0.3, 1) both;
}

@keyframes spine-in {
  from {
    opacity: 0;
    transform: perspective(500px) rotateY(-80deg);
  }

  to {
    opacity: 1;
    transform: none;
  }
}

.spine.is-spotlight .spine-title {
  color: #f3d58a;
}

/* The cover held up face-first in the middle, before it turns onto the shelf */
.bookcase-stage {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  perspective: 1200px;
}

.bookcase-face {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 7.5rem;
  aspect-ratio: 2 / 3;
  border-radius: 2px 5px 5px 2px;
  box-shadow: 0 4px 8px rgb(0 0 0 / 50%), 0 18px 40px rgb(0 0 0 / 55%), 0 0 0 1px rgb(255 230 190 / 25%);
  transform: translate(-50%, -50%);
  transform-origin: center center;
  opacity: 0;
}

.bookcase-face img,
.bookcase-face .cloth-cover {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: inherit;
  object-fit: cover;
}

.bookcase-face .cloth-cover {
  padding: 18% 10%;
}

/* Full: a band of light sweeps on the diagonal from the top left to the bottom right
   behind every shelf (showcase.js, shine), seen round the books' edges and between them,
   with sparkles at their heads where it passes */
.bookcase {
  --glow: 255 214 130;
}

.bookcase-sweep {
  --at: -1;
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

.sweep-row {
  position: absolute;
  border-radius: 10px;
  background-image: linear-gradient(
    var(--angle),
    transparent calc(var(--at) * 100% - 16%),
    rgb(var(--glow) / 45%) calc(var(--at) * 100% - 6%),
    rgb(255 246 220 / 85%) calc(var(--at) * 100%),
    rgb(var(--glow) / 45%) calc(var(--at) * 100% + 6%),
    transparent calc(var(--at) * 100% + 16%)
  );
  background-repeat: no-repeat;
  filter: blur(7px);
}

.bookcase-shelf {
  z-index: 1;
}

.bookcase-sparks {
  position: absolute;
  inset: 0;
  z-index: 2;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}

.bookcase-sparks .spark {
  fill: rgb(255 250 232);
  filter: drop-shadow(0 0 3px rgb(var(--glow)));
}

@media (prefers-reduced-motion: reduce) {
  .spine.is-in {
    animation: none;
  }
}

@media (max-width: 34rem) {
  .bookcase {
    background-image: url("/static/img/generated/showcase/bookcase-1000.webp");
  }

  .bookcase-face {
    width: 6rem;
  }
}

[data-theme="galactic"] .bookcase {
  --glow: 190 175 255;
  --case-tint: rgb(58 50 120 / 42%);
}

[data-theme="fire"] .bookcase {
  --glow: 255 150 70;
  --case-tint: rgb(150 60 20 / 45%);
}

/* Galactic: the shelf becomes a floating crystal ledge */
[data-theme="galactic"] .shelf-slide {
  border-image: linear-gradient(180deg, rgb(160 140 255 / 60%), rgb(60 50 140 / 40%)) 1;
  background:
    radial-gradient(ellipse 70% 60% at 50% 0%, rgb(140 120 255 / 28%), transparent 70%),
    linear-gradient(180deg, rgb(20 24 60 / 85%), rgb(8 10 30 / 90%));
}

[data-theme="galactic"] .shelf-plank {
  background: linear-gradient(180deg, rgb(200 190 255 / 75%), rgb(110 90 230 / 55%) 40%, rgb(40 30 110 / 60%));
  box-shadow: 0 0 22px rgb(125 107 255 / 55%);
}

/* Fire: a charred shelf with embers along its edge */
[data-theme="fire"] .shelf-slide {
  border-image: linear-gradient(180deg, rgb(255 140 60 / 55%), rgb(120 40 10 / 45%)) 1;
  background:
    radial-gradient(ellipse 70% 50% at 50% 100%, rgb(255 110 30 / 22%), transparent 70%),
    linear-gradient(180deg, rgb(36 18 10 / 90%), rgb(18 9 5 / 94%));
}

[data-theme="fire"] .shelf-plank {
  background: linear-gradient(180deg, #4a2414, #2a120a 55%, #170904);
  box-shadow: 0 -1px 0 rgb(255 150 70 / 70%), 0 6px 22px rgb(255 100 30 / 35%);
}


@media (max-width: 34rem) {
  .shelf-book {
    width: 4.2rem;
  }

  .shelf {
    gap: 0.5rem;
    justify-content: flex-start;
  }

  .spotlight-panel {
    align-items: flex-start;
  }
}

/* Changing a cover (DR-025): the book page's cover offers itself on hover */
.cover-change {
  position: relative;
  flex: none;
  display: block;
  padding: 0;
  border: none;
  background: none;
  cursor: pointer;
  border-radius: 4px;
}

.cover-change:hover,
.cover-change:focus-visible {
  background: none;
}

.cover-change img.cover.large,
.cover-change .cover-blank {
  margin: 0.3rem 0 0;
  transition: filter 0.25s, transform 0.25s;
}

.cover-blank {
  display: flex;
  width: 10rem;
  height: 15rem;
  border-radius: 4px;
}

.cover-change-label {
  position: absolute;
  inset: auto 0.5rem 0.75rem;
  display: flex;
  gap: 0.35rem;
  align-items: center;
  justify-content: center;
  padding: 0.4rem 0.6rem;
  border-radius: 999px;
  background: rgb(20 18 16 / 78%);
  color: #fff8ea;
  font-size: 0.85rem;
  font-weight: 600;
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 0.2s, transform 0.2s;
  backdrop-filter: blur(4px);
}

.cover-change-label svg {
  width: 1rem;
  height: 1rem;
}

.cover-change:hover .cover-change-label,
.cover-change:focus-visible .cover-change-label {
  opacity: 1;
  transform: none;
}

.cover-change:hover img,
.cover-change:hover .cover-blank {
  filter: brightness(0.85);
  transform: translateY(-2px);
}

.cover-picker {
  width: min(46rem, calc(100% - 2rem));
  max-height: min(44rem, calc(100% - 2rem));
  padding: 0 1.5rem 1.5rem;
  border: 1px solid var(--rule);
  border-radius: 4px;
  background: var(--page);
  color: var(--ink);
  box-shadow: 0 20px 60px rgb(0 0 0 / 35%);
}

[data-theme="galactic"] .cover-picker {
  background: #141838;
}

.cover-picker[open] {
  animation: intro-in 0.3s cubic-bezier(0.2, 0.9, 0.3, 1.1);
}

.cover-picker::backdrop {
  background: rgb(20 18 16 / 45%);
  backdrop-filter: blur(3px);
}

.cover-picker-head {
  position: sticky;
  top: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1rem 0 0.5rem;
  background: inherit;
}

.cover-picker-head h2 {
  margin: 0;
  border: none;
}

.picker-close {
  width: 2.2rem;
  height: 2.2rem;
  padding: 0;
  border-radius: 50%;
  font-size: 1.4rem;
  line-height: 1;
}

.picker-heading {
  margin: 1.1rem 0 0.4rem;
  color: var(--ink-soft);
  font-family: var(--sans);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.picker-note {
  margin: 0 0 0.6rem;
  font-size: 0.9rem;
}

.cover-options {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(6.5rem, 1fr));
  gap: 0.9rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.cover-options form {
  margin: 0;
}

.cover-option {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  align-items: center;
  width: 100%;
  padding: 0.35rem;
  border: 2px solid transparent;
  border-radius: 3px;
  background: none;
  color: var(--ink);
  font-weight: 400;
  transition: border-color 0.15s, transform 0.15s;
}

.cover-option:hover {
  border-color: var(--accent);
  background: var(--accent-soft);
  transform: translateY(-2px);
}

.cover-option img {
  display: block;
  width: 100%;
  aspect-ratio: 2 / 3;
  object-fit: cover;
  border-radius: 3px;
  box-shadow: 0 1px 2px rgb(0 0 0 / 25%), 2px 4px 10px rgb(42 37 32 / 20%);
}

.cover-option.is-current {
  border-color: var(--brass);
  opacity: 1;
  cursor: default;
}

.cover-option.is-busy img {
  animation: pulse 1s ease-in-out infinite alternate;
}

@keyframes pulse {
  to {
    opacity: 0.5;
  }
}

.cover-option-note {
  color: var(--ink-soft);
  font-size: 0.75rem;
  line-height: 1.3;
  text-align: center;
}

.picker-reset {
  margin-top: 1.25rem;
  padding-top: 1rem;
  border-top: 1px solid var(--rule);
}

.dont-warn {
  display: inline-flex;
  gap: 0.4rem;
  align-items: center;
  margin-top: 0.25rem;
  font-size: 0.92rem;
}

/* Library charts (DR-026). Categorical colours are the dataviz reference palette in
   its validated order (light steps on paper; dark steps for dark mode and galactic);
   one-series charts use the theme's accent. */
:root {
  --chart-1: #2a78d6;
  --chart-2: #eb6834;
  --chart-3: #1baf7a;
  --chart-4: #eda100;
  --chart-5: #e87ba4;
  --chart-6: #008300;
  --chart-7: #6250d6;
  --chart-8: #e34948;
  --chart-other: #b9b2a6;
  --chart-accent: var(--accent);
}

@media (prefers-color-scheme: dark) {
  :root {
    --chart-1: #3987e5;
    --chart-2: #d95926;
    --chart-3: #199e70;
    --chart-4: #c98500;
    --chart-5: #d55181;
    --chart-6: #008300;
    --chart-7: #9085e9;
    --chart-8: #e66767;
    --chart-other: #6b655c;
  }
}

:root[data-theme="galactic"],
:root[data-theme="fire"] {
  --chart-1: #3987e5;
  --chart-2: #d95926;
  --chart-3: #199e70;
  --chart-4: #c98500;
  --chart-5: #d55181;
  --chart-6: #008300;
  --chart-7: #9085e9;
  --chart-8: #e66767;
  --chart-other: #5d6088;
}

/* The library's More menu */
.more-menu {
  position: relative;
  margin: 0;
}

.more-menu > summary {
  list-style: none;
  cursor: pointer;
}

.more-menu > summary::-webkit-details-marker {
  display: none;
}

.more-menu > summary svg {
  fill: currentColor;
}

.more-menu-items {
  position: absolute;
  top: calc(100% + 0.35rem);
  right: 0;
  z-index: 20;
  display: grid;
  min-width: 13rem;
  padding: 0.35rem;
  border: 1px solid var(--rule);
  border-top: 2px solid var(--brass);
  border-radius: var(--radius);
  background: var(--page);
  box-shadow: var(--shadow);
}

.more-menu-items a {
  display: flex;
  gap: 0.6rem;
  align-items: center;
  padding: 0.55rem 0.75rem;
  border-radius: 6px;
  color: var(--ink);
  text-decoration: none;
}



.more-menu-items svg {
  width: 1.15rem;
  height: 1.15rem;
}

.charts-head,
.page-head {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  align-items: center;
  justify-content: space-between;
}

.charts-head h1,
.page-head h1 {
  margin: 0;
}

.page-head .button {
  display: inline-flex;
  gap: 0.4rem;
  align-items: center;
}

.page-head .button svg {
  width: 1.1rem;
  height: 1.1rem;
}

/* Headline numbers */
.stat-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr));
  gap: 0.75rem;
  margin: 1.25rem 0;
}

.stat-tile {
  display: flex;
  flex-direction: column;
  padding: 0.85rem 1rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--page);
  box-shadow: var(--shadow);
}

.stat-tile strong {
  color: var(--ink);
  font-family: var(--figures);
  font-size: 1.7rem;
  font-variant-numeric: lining-nums tabular-nums;
  font-weight: 600;
  line-height: 1.15;
}

/* A currency after an amount, small beside it rather than wrapping at full size */
.stat-tile strong small {
  margin-left: 0.25rem;
  color: var(--ink-soft);
  font-size: 0.8rem;
  font-weight: 500;
  letter-spacing: 0.05em;
}

.stat-tile span {
  color: var(--ink-soft);
  font-size: 0.85rem;
}

/* Explore: the controls in one row above the chart */
.chart-controls {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem 1rem;
  margin-bottom: 1rem;
}

/* The menus shrink to the screen rather than push past it */
.chart-controls label,
.chart-controls select {
  min-width: 0;
  max-width: 100%;
}

.chart-controls label {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  color: var(--ink-soft);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.04em;
}

.chart-controls select {
  min-width: 11rem;
  color: var(--ink);
  font-size: 0.95rem;
  font-weight: 400;
  letter-spacing: 0;
}

.chart-canvas {
  position: relative;
  height: 18rem;
}

.chart-explorer .chart-canvas {
  height: 22rem;
}

.chart-empty {
  margin: 2rem 0;
  color: var(--ink-soft);
  font-family: var(--serif);
  font-style: italic;
  text-align: center;
}

.chart-table {
  margin-top: 0.75rem;
  font-size: 0.9rem;
}

.chart-table summary {
  color: var(--ink-soft);
}

.chart-table table {
  width: 100%;
  margin-top: 0.5rem;
  border-collapse: collapse;
}

.chart-table th,
.chart-table td {
  padding: 0.3rem 0.5rem;
  border-bottom: 1px solid var(--rule);
  text-align: left;
}

/* Numbers right-aligned under right-aligned headings, in even lining figures */
.chart-table td,
.chart-table thead th:not(:first-child) {
  font-variant-numeric: lining-nums tabular-nums;
  text-align: right;
  white-space: nowrap;
}

.chart-table th[scope="row"] {
  font-weight: 500;
}

.chart-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 28rem), 1fr));
  gap: 1.25rem;
}

.chart-card {
  padding: 1rem 1.1rem 0.9rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--page);
  box-shadow: var(--shadow);
}

.chart-card-head {
  display: flex;
  gap: 0.5rem;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 0.5rem;
}

.chart-card-head h3 {
  margin: 0;
}

.chart-explore-button {
  padding: 0.2rem 0.6rem;
  font-size: 0.8rem;
}

/* Charts (DR-035): wide cards for the genre rings and page lengths, a taller explorer */
.chart-card.is-wide {
  grid-column: 1 / -1;
}

.chart-card.is-rings .chart-canvas,
.chart-explorer .chart-canvas.is-tall {
  height: min(36rem, 80vw);
  min-height: 20rem;
}

/* The sunburst with its focus panel beside it: the main genre in view and its books'
   2nd genres as bars; the panel drops below the chart on narrow screens */
.sunburst-row.has-focus {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(14rem, 18rem);
  gap: 1rem 1.5rem;
  align-items: center;
}

@media (max-width: 48rem) {
  .sunburst-row.has-focus {
    grid-template-columns: minmax(0, 1fr);
  }
}

.genre-focus {
  padding: 1rem 1.1rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--page) 70%, var(--brass-soft));
}

.genre-focus p {
  margin: 0;
}

.genre-focus-kicker {
  color: var(--brass);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.genre-focus-name {
  font-family: var(--serif);
  font-size: 1.9rem;
  line-height: 1.1;
}

.genre-focus-tally {
  margin-top: 0.15rem !important;
  color: var(--ink-soft);
  font-size: 0.9rem;
}

.genre-focus-heading {
  margin-top: 0.9rem !important;
  color: var(--ink-soft);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.genre-focus-list {
  display: grid;
  gap: 0.4rem;
  margin: 0.45rem 0 0;
  padding: 0;
  list-style: none;
}

.genre-focus-list li {
  display: grid;
  grid-template-columns: minmax(0, 7.5rem) minmax(0, 1fr) 3rem;
  gap: 0.5rem;
  align-items: center;
  font-size: 0.9rem;
}

.genre-focus-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.genre-focus-bar {
  height: 0.6rem;
  border-radius: 999px;
  background: var(--rule);
  overflow: hidden;
}

.genre-focus-bar span {
  display: block;
  height: 100%;
  border-radius: inherit;
}

.genre-focus-amount {
  font-family: var(--figures);
  font-variant-numeric: lining-nums tabular-nums;
  font-weight: 600;
  text-align: right;
}

.genre-focus-hint {
  margin-top: 0.8rem !important;
  color: var(--ink-soft);
  font-size: 0.8rem;
  font-style: italic;
}

.chart-table tr.is-child th {
  padding-left: 1.5rem;
  color: var(--ink-soft);
  font-weight: 400;
}

.chart-table tr.is-parent th {
  font-weight: 600;
}

.chart-card-foot {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1rem;
  align-items: flex-start;
  justify-content: space-between;
}

.chart-card-foot .chart-table {
  flex: 1 1 14rem;
}

.chart-copy {
  display: inline-flex;
  gap: 0.35rem;
  align-items: center;
  margin-top: 0.6rem;
  padding: 0.2rem 0.6rem;
  font-size: 0.8rem;
}

.chart-copy svg {
  width: 1rem;
  height: 1rem;
}

.chart-explorer-head {
  display: flex;
  gap: 1rem;
  align-items: baseline;
  justify-content: space-between;
}

.hide-empty {
  display: inline-flex;
  gap: 0.35rem;
  align-items: center;
  color: var(--ink-soft);
  font-size: 0.8rem;
  white-space: nowrap;
}

/* Two or three choices side by side, as one control */
.segmented {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 0;
  align-items: flex-end;
  margin: 0;
  padding: 0;
  border: 0;
}

.chart-controls .segmented legend {
  margin-bottom: 0.2rem;
  padding: 0;
  color: var(--ink-soft);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.04em;
}

.segmented label,
.chart-controls .segmented label {
  display: inline-flex;
  flex-direction: row;
  padding: 0.35rem 0.75rem;
  border: 1px solid var(--rule);
  background: var(--page);
  color: var(--ink);
  font-size: 0.9rem;
  font-weight: 400;
  letter-spacing: 0;
  cursor: pointer;
}

.segmented label + label {
  border-left: 0;
}

.segmented label:first-of-type {
  border-radius: var(--radius) 0 0 var(--radius);
}

.segmented label:last-of-type {
  border-radius: 0 var(--radius) var(--radius) 0;
}

.segmented input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.segmented label:has(input:checked) {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--page);
}

.segmented label:has(input:focus-visible) {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.segmented label:has(input:disabled) {
  opacity: 0.45;
  cursor: not-allowed;
}

/* Chart colours, one of Customize a chart's options, under its other controls */
.chart-palette {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem 1rem;
  align-items: center;
  margin: 0.75rem 0 1rem;
  padding-top: 0.75rem;
  border-top: 1px solid var(--rule);
}

.chart-piece-colour {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: center;
}

.chart-piece-colour select {
  max-width: 14rem;
}

.chart-palette-title {
  font-family: var(--caps);
}

.chart-palette-gradient {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem 1rem;
  align-items: center;
}

.chart-palette-gradient[hidden] {
  display: none;
}

.chart-palette-hint {
  font-size: 0.85rem;
}

.hue-swatches {
  display: flex;
  gap: 0.3rem;
  margin: 0;
  padding: 0;
  border: 0;
}

.hue-swatch {
  position: relative;
  width: 1.6rem;
  height: 1.6rem;
  border: 2px solid var(--page);
  border-radius: 50%;
  background: linear-gradient(135deg, color-mix(in srgb, var(--swatch, grey) 45%, white), var(--swatch, grey), color-mix(in srgb, var(--swatch, grey) 60%, black));
  box-shadow: 0 0 0 1px var(--rule);
  cursor: pointer;
}

.hue-swatch input {
  position: absolute;
  opacity: 0;
}

.hue-swatch:has(input:checked) {
  box-shadow: 0 0 0 2px var(--ink);
}

.hue-swatch:has(input:focus-visible) {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.link-button {
  padding: 0;
  border: 0;
  background: none;
  box-shadow: none;
  color: var(--accent);
  font: inherit;
  font-size: 0.9rem;
  text-decoration: underline;
  cursor: pointer;
}

/* A piece's own colour */
.colour-dialog {
  max-width: min(30rem, calc(100vw - 2rem));
  padding: 1.1rem 1.25rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--page);
  color: var(--ink);
  box-shadow: var(--shadow);
}

.colour-dialog::backdrop {
  background: rgb(20 16 12 / 35%);
}

.colour-dialog h2 {
  margin-top: 0;
  font-size: 1.2rem;
}

.colour-swatches {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(2rem, 1fr));
  gap: 0.4rem;
}

.colour-swatch {
  aspect-ratio: 1;
  padding: 0;
  border: 2px solid var(--page);
  border-radius: 50%;
  background: var(--swatch);
  box-shadow: 0 0 0 1px var(--rule);
  cursor: pointer;
}

.colour-swatch:hover,
.colour-swatch:focus-visible {
  box-shadow: 0 0 0 2px var(--ink);
}

.colour-dialog-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1rem;
  align-items: center;
  justify-content: space-between;
  margin-top: 1rem;
}

.colour-dialog-row label {
  display: inline-flex;
  gap: 0.4rem;
  align-items: center;
}

.colour-dialog-row form {
  margin: 0;
}

/* Your libraries (DR-027 #5): one row each, with valuation, read and TBR tallies */
.library-rows {
  display: grid;
  gap: 0.75rem;
  margin: 1rem 0 2rem;
  padding: 0;
  list-style: none;
}

.library-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1.5rem;
  align-items: center;
  padding: 0.9rem 1.1rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--page);
  box-shadow: var(--shadow);
}

.library-row-main {
  display: flex;
  flex: 1 1 12rem;
  flex-direction: column;
}

.library-row-name {
  font-family: var(--serif);
  font-size: 1.2rem;
  font-weight: 400;
  text-decoration: none;
}

.library-row-value {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

/* Wide enough for columns: every row shares the list's columns, so the valuations,
   tallies and Default buttons line up from row to row */
@media (min-width: 48rem) {
  .library-rows {
    grid-template-columns: minmax(12rem, 1fr) repeat(4, auto);
  }

  .library-row {
    display: grid;
    grid-column: 1 / -1;
    grid-template-columns: subgrid;
  }

  .library-row-default {
    justify-self: end;
  }
}

.library-stat {
  display: flex;
  flex-direction: column;
  line-height: 1.2;
}

.library-stat-label {
  color: var(--ink-soft);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.library-stat .money small {
  color: var(--ink-soft);
  font-family: var(--sans);
  font-size: 0.7rem;
  font-style: normal;
}

/* A number in a little stamped box, its words beside it in an old-book face */
.tally {
  display: inline-flex;
  gap: 0.45rem;
  align-items: center;
}

.tally-box {
  display: grid;
  place-items: center;
  min-width: 2rem;
  height: 2rem;
  padding: 0 0.4rem;
  border: 1.5px solid var(--brass);
  border-radius: 5px;
  background: var(--brass-soft);
  color: var(--ink);
  font-family: var(--figures);
  font-size: 1rem;
  font-weight: 600;
  font-variant-numeric: lining-nums tabular-nums;
  box-shadow: inset 0 0 0 2px var(--page), 0 1px 2px rgb(0 0 0 / 15%);
}

.tally-label {
  color: var(--ink-soft);
  font-family: var(--serif);
  font-style: italic;
  font-variant: small-caps;
  letter-spacing: 0.04em;
}

.library-row-default {
  margin-left: auto;
}

.library-row-default form {
  margin: 0;
}

.default-badge {
  padding: 0.25rem 0.7rem;
  border: 1px solid var(--brass);
  border-radius: 2px;
  color: var(--brass);
  font-size: 0.8rem;
  font-weight: 600;
}

.small-button {
  padding: 0.25rem 0.7rem;
  font-size: 0.85rem;
}

/* A label over one row of an input and its button, aligned */
.inline-form label {
  display: block;
  margin-bottom: 0.3rem;
  font-weight: 600;
  font-size: 0.92rem;
}

.inline-form-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: stretch;
}

.inline-form-row input {
  flex: 1 1 14rem;
  max-width: 26rem;
}

/* Add this edition, once done */
.added-badge {
  display: inline-flex;
  gap: 0.35rem;
  align-items: center;
  padding: 0.4rem 0.85rem;
  border: 1px solid color-mix(in srgb, var(--ok) 45%, transparent);
  border-radius: 2px;
  background: var(--ok-soft);
  color: var(--ok);
  font-weight: 600;
  animation: intro-in 0.3s ease-out;
}

.added-badge svg {
  width: 1.1rem;
  height: 1.1rem;
}

/* Account settings */
.account-head {
  display: flex;
  gap: 1.25rem;
  align-items: center;
  margin-bottom: 1.25rem;
}

.account-head h1 {
  margin: 0;
}

.account-head p {
  margin: 0.2rem 0 0;
}

.icon-picker fieldset {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin: 0 0 1rem;
  padding: 0;
  border: none;
}

.icon-choice {
  position: relative;
  cursor: pointer;
}

.icon-choice input {
  position: absolute;
  opacity: 0;
}

.icon-choice .avatar {
  border-color: transparent;
  transition: transform 0.15s, box-shadow 0.15s;
}

.icon-choice:hover .avatar {
  transform: translateY(-2px) rotate(-4deg);
}

.icon-choice input:checked + .avatar {
  border-color: var(--brass);
  box-shadow: 0 0 0 3px var(--brass-soft), 0 0 0 5px var(--brass);
}

.icon-choice input:focus-visible + .avatar {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
}

.picture-form {
  margin-top: 1.5rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--rule);
}

/* Phones */

@media (max-width: 34rem) {
  main {
    padding: 1rem 0.9rem 3rem;
  }

  .site-header {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      "name you"
      "search search"
      "nav nav";
    padding: 0.7rem 0.9rem 0;
  }

  .header-search {
    max-width: none;
  }

  .site-nav {
    margin-left: -0.6rem;
  }

  .site-nav a {
    padding-inline: 0.6rem;
  }

  .user-name {
    display: none;
  }

  .book-head {
    flex-direction: column;
  }

  .library-tools {
    width: 100%;
    justify-content: space-between;
  }

  .collection-value {
    text-align: left;
  }

  .lookup-form input:not([type="checkbox"], [type="radio"], [type="hidden"]) {
    width: 100%;
    min-width: 0;
  }

  .lookup-form > div {
    flex: 1 1 100%;
  }
}

/*
 * The galactic theme (DR-022 #1): deep space behind everything, starlight and nebula
 * glow, with panels of dark glass so text stays easy to read. Always dark, whatever the
 * device's setting.
 */
:root[data-theme="galactic"] {
  --paper: #070a1a;
  --page: rgb(18 22 48 / 82%);
  --ink: #eceaff;
  --ink-soft: #a9acd6;
  --rule: rgb(150 150 230 / 22%);
  --accent: #9d8cff;
  --accent-strong: #c2b8ff;
  --accent-soft: rgb(120 100 255 / 18%);
  --brass: #f0c96a;
  --brass-soft: rgb(240 201 106 / 16%);
  --danger: #ff8f8f;
  --danger-soft: rgb(255 100 100 / 14%);
  --warn: #ffd27a;
  --warn-soft: rgb(255 200 90 / 12%);
  --ok: #8ff0c0;
  --ok-soft: rgb(100 240 180 / 12%);
  --shadow: 0 1px 2px rgb(0 0 0 / 40%), 0 6px 22px rgb(0 0 0 / 35%);
  color-scheme: dark;
}

[data-theme="galactic"] body {
  min-height: 100vh;
  background:
    radial-gradient(ellipse 60% 45% at 78% 18%, rgb(130 70 255 / 30%), transparent 70%),
    radial-gradient(ellipse 55% 40% at 12% 75%, rgb(30 160 220 / 22%), transparent 70%),
    radial-gradient(ellipse 40% 30% at 55% 95%, rgb(230 80 180 / 14%), transparent 70%),
    linear-gradient(180deg, #050716 0%, #0a0e26 55%, #060818 100%);
  background-attachment: fixed;
}

/* Two layers of stars, far and near, drifting at different speeds */
[data-theme="galactic"] body::before,
[data-theme="galactic"] body::after {
  content: "";
  position: fixed;
  inset: -50% 0 0;
  z-index: -1;
  pointer-events: none;
  background-repeat: repeat;
}

[data-theme="galactic"] body::before {
  background-image:
    radial-gradient(1px 1px at 12px 30px, #fff, transparent),
    radial-gradient(1px 1px at 80px 120px, rgb(255 255 255 / 80%), transparent),
    radial-gradient(1px 1px at 150px 60px, rgb(200 220 255 / 90%), transparent),
    radial-gradient(1px 1px at 210px 170px, rgb(255 255 255 / 70%), transparent),
    radial-gradient(1px 1px at 40px 200px, rgb(255 240 220 / 80%), transparent),
    radial-gradient(1px 1px at 120px 230px, rgb(255 255 255 / 60%), transparent);
  background-size: 240px 240px;
  opacity: 0.8;
  animation: drift 240s linear infinite;
}

[data-theme="galactic"] body::after {
  background-image:
    radial-gradient(1.6px 1.6px at 60px 80px, #fff, transparent),
    radial-gradient(2px 2px at 300px 260px, rgb(210 225 255 / 95%), transparent),
    radial-gradient(1.4px 1.4px at 420px 90px, rgb(255 235 200 / 90%), transparent),
    radial-gradient(1.8px 1.8px at 190px 400px, #fff, transparent);
  background-size: 520px 520px;
  animation: drift 120s linear infinite, twinkle 12s ease-in-out infinite alternate;
}

@keyframes drift {
  to {
    transform: translateY(50%);
  }
}

@keyframes twinkle {
  from {
    opacity: 0.8;
  }

  to {
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  [data-theme="galactic"] body::before,
  [data-theme="galactic"] body::after {
    animation: none;
  }
}

/* Glints (static/js/glints.js): stars flaring into four-pointed sparkles, and a
   shooting star now and then, over the painted sky and under the page */
.sky-glints {
  position: fixed;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  pointer-events: none;
}

.glint {
  position: absolute;
  width: var(--size);
  height: var(--size);
  margin: calc(var(--size) / -2) 0 0 calc(var(--size) / -2);
  background:
    radial-gradient(circle, #fff 0 7%, color-mix(in srgb, var(--tint) 60%, transparent) 12%, transparent 24%),
    linear-gradient(90deg, transparent 48%, var(--tint) 50%, transparent 52%),
    linear-gradient(0deg, transparent 48%, var(--tint) 50%, transparent 52%);
  -webkit-mask-image: radial-gradient(circle, #000 20%, transparent 72%);
  mask-image: radial-gradient(circle, #000 20%, transparent 72%);
  opacity: 0;
  filter: drop-shadow(0 0 2px var(--tint));
  animation: glint var(--period) ease-in-out var(--delay) infinite;
}

@keyframes glint {
  0%,
  40% {
    opacity: 0;
    transform: scale(0.4) rotate(0deg);
  }

  52% {
    opacity: 0.45;
    transform: scale(1) rotate(20deg);
  }

  64%,
  100% {
    opacity: 0;
    transform: scale(0.5) rotate(40deg);
  }
}

.meteor {
  position: absolute;
  width: 9rem;
  height: 1.5px;
  border-radius: 1px;
  background: linear-gradient(90deg, transparent, rgb(214 226 255 / 45%) 85%, rgb(255 255 255 / 70%));
  opacity: 0;
  transform: rotate(24deg);
  transform-origin: right center;
  animation: meteor 45s linear 12s infinite;
}

@keyframes meteor {
  0%,
  95% {
    opacity: 0;
    translate: 0 0;
  }

  96% {
    opacity: 0.7;
  }

  98.5%,
  100% {
    opacity: 0;
    translate: 22rem 10rem;
  }
}

[data-theme="galactic"] .site-header {
  background: rgb(8 10 30 / 72%);
  border-bottom: 1px solid rgb(160 140 255 / 40%);
  box-shadow: 0 1px 18px rgb(120 90 255 / 25%);
  backdrop-filter: blur(10px);
}

[data-theme="galactic"] .site-header {
  --band: #0b0e28;
}

[data-theme="galactic"] .mark-nodes circle {
  filter: drop-shadow(0 0 3px rgb(240 201 106 / 90%));
}

[data-theme="galactic"] h1 {
  text-shadow: 0 0 18px rgb(157 140 255 / 45%);
}

[data-theme="galactic"] .panel,
[data-theme="galactic"] .book-table,
[data-theme="galactic"] .user-menu-items,
[data-theme="galactic"] .filter-panel,
[data-theme="galactic"] .book-list li {
  backdrop-filter: blur(8px);
}

[data-theme="galactic"] input:not([type="checkbox"], [type="radio"]),
[data-theme="galactic"] select,
[data-theme="galactic"] textarea {
  background: rgb(10 12 32 / 70%);
  color: var(--ink);
  border-color: var(--rule);
}

[data-theme="galactic"] .header-search input[type="search"] {
  background: rgb(236 234 255 / 92%);
  color: #12142e;
}

[data-theme="galactic"] .button,
[data-theme="galactic"] .stacked > button[type="submit"],
[data-theme="galactic"] .filter-actions button {
  --plate-rule: rgb(11 11 30 / 35%);
  color: #0b0b1e;
}

[data-theme="galactic"] .header-search .book-button {
  border-color: rgb(157 140 255 / 70%);
  background: linear-gradient(160deg, #7d6bff, #3e2fb0);
  color: #fff;
  box-shadow: 0 0 14px rgb(125 107 255 / 55%);
}

[data-theme="galactic"] .book-button .book-page {
  filter: drop-shadow(0 0 2px rgb(255 255 255 / 70%));
}

[data-theme="galactic"] .tile-book {
  box-shadow: 0 0 0 1px rgb(160 140 255 / 25%), 0 8px 24px rgb(0 0 0 / 55%);
}

[data-theme="galactic"] .book-tile:hover .tile-book {
  box-shadow: 0 0 0 1px rgb(160 140 255 / 45%), 0 0 26px rgb(125 107 255 / 45%);
}

[data-theme="galactic"] .collection-value-amount,
[data-theme="galactic"] .money {
  text-shadow: 0 0 12px rgb(240 201 106 / 40%);
}

[data-theme="galactic"] .avatar {
  box-shadow: 0 0 10px rgb(240 201 106 / 35%);
}

:root[data-theme="fire"] {
  --chart-other: #6b5246;
}

/*
 * The fire theme (DR-028 #6): soot and charcoal lit from below, ember-orange accents and
 * gold, with sparks rising past the page. Always dark, whatever the device's setting.
 */
:root[data-theme="fire"] {
  --paper: #120b08;
  --page: rgb(33 19 13 / 88%);
  --ink: #f7e8d8;
  --ink-soft: #c9a68c;
  --rule: rgb(255 140 60 / 22%);
  --accent: #ff8f3f;
  --accent-strong: #ffb46e;
  --accent-soft: rgb(255 120 40 / 16%);
  --brass: #ffcb57;
  --brass-soft: rgb(255 200 90 / 14%);
  --danger: #ff7d6b;
  --danger-soft: rgb(255 90 70 / 14%);
  --warn: #ffd27a;
  --warn-soft: rgb(255 200 90 / 12%);
  --ok: #a6e39a;
  --ok-soft: rgb(140 220 120 / 12%);
  --shadow: 0 1px 0 rgb(0 0 0 / 45%), 0 4px 12px -4px rgb(0 0 0 / 70%);
  color-scheme: dark;
}

[data-theme="fire"] body {
  min-height: 100vh;
  background:
    radial-gradient(ellipse 70% 40% at 50% 108%, rgb(255 90 20 / 34%), transparent 70%),
    radial-gradient(ellipse 35% 30% at 8% 100%, rgb(255 140 40 / 20%), transparent 70%),
    radial-gradient(ellipse 35% 30% at 92% 100%, rgb(220 50 20 / 22%), transparent 70%),
    linear-gradient(180deg, #0d0806 0%, #160c08 60%, #1f0d07 100%);
  background-attachment: fixed;
}

/* Two layers of sparks, small and far, larger and near, rising at different speeds */
[data-theme="fire"] body::before,
[data-theme="fire"] body::after {
  content: "";
  position: fixed;
  inset: 0 0 -50%;
  z-index: -1;
  pointer-events: none;
  background-repeat: repeat;
}

[data-theme="fire"] body::before {
  background-image:
    radial-gradient(1px 1px at 20px 40px, #ffb35c, transparent),
    radial-gradient(1px 1px at 110px 150px, rgb(255 200 110 / 85%), transparent),
    radial-gradient(1.2px 1.2px at 170px 70px, #ff8a3d, transparent),
    radial-gradient(1px 1px at 60px 210px, rgb(255 170 80 / 80%), transparent),
    radial-gradient(1px 1px at 220px 120px, rgb(255 220 150 / 70%), transparent);
  background-size: 250px 250px;
  opacity: 0.75;
  animation: embers-rise 90s linear infinite;
}

[data-theme="fire"] body::after {
  background-image:
    radial-gradient(2px 2px at 80px 120px, #ffc56b, transparent),
    radial-gradient(1.6px 1.6px at 330px 300px, #ff7a2e, transparent),
    radial-gradient(2.2px 2.2px at 450px 60px, #ffd98a, transparent),
    radial-gradient(1.8px 1.8px at 210px 430px, #ff9a4a, transparent);
  background-size: 540px 540px;
  animation: embers-rise 45s linear infinite, flicker 2.6s ease-in-out infinite alternate;
}

/* Its own name: a second "rise" replaced the spotlight books' one and left them
   halfway up the page in the fire theme */
@keyframes embers-rise {
  to {
    transform: translateY(-50%);
  }
}

@keyframes flicker {
  0% {
    opacity: 0.5;
  }

  40% {
    opacity: 0.95;
  }

  70% {
    opacity: 0.7;
  }

  100% {
    opacity: 1;
  }
}

[data-theme="fire"] .site-header {
  --band: #1d0f09;
  background: linear-gradient(180deg, #140a06, #24110a);
  border-bottom: 1px solid rgb(255 140 60 / 65%);
  box-shadow: 0 2px 22px rgb(255 100 30 / 30%);
}

/* The mark's nodes become flames that flicker one after another */
.mark-flames {
  display: none;
}

[data-theme="fire"] .mark-nodes {
  display: none;
}

[data-theme="fire"] .mark-flames {
  display: inline;
}

.mark-flames path {
  fill: #ffb347;
  transform-box: fill-box;
  transform-origin: 50% 100%;
  filter: drop-shadow(0 0 2px rgb(255 120 30 / 90%));
  animation: flame-lick 1.4s ease-in-out infinite alternate;
  animation-delay: calc(var(--i) * -0.23s);
}

@keyframes flame-lick {
  0% {
    fill: #ffb347;
    transform: scale(1, 1) skewX(0);
  }

  50% {
    fill: #ff8a2e;
    transform: scale(0.92, 1.12) skewX(-4deg);
  }

  100% {
    fill: #ffd36b;
    transform: scale(1.05, 0.94) skewX(3deg);
  }
}

/* Headings carry a small flame */

[data-theme="fire"] h1 {
  text-shadow: 0 0 18px rgb(255 120 40 / 45%);
}

[data-theme="fire"] .panel,
[data-theme="fire"] .book-table,
[data-theme="fire"] .user-menu-items,
[data-theme="fire"] .more-menu-items,
[data-theme="fire"] .filter-panel,
[data-theme="fire"] .book-list li {
  backdrop-filter: blur(6px);
}

[data-theme="fire"] input:not([type="checkbox"], [type="radio"]),
[data-theme="fire"] select,
[data-theme="fire"] textarea {
  background: rgb(20 10 6 / 75%);
  color: var(--ink);
  border-color: var(--rule);
}

[data-theme="fire"] .header-search input[type="search"] {
  background: rgb(255 240 225 / 94%);
  color: #24110a;
}

[data-theme="fire"] .button,
[data-theme="fire"] .stacked > button[type="submit"],
[data-theme="fire"] .filter-actions button {
  --plate-rule: rgb(36 14 4 / 40%);
  color: #200c04;
}

[data-theme="fire"] .header-search .book-button {
  border-color: rgb(255 170 90 / 70%);
  background: linear-gradient(170deg, #ff9a3c, #c2410f);
  color: #fff7ea;
  box-shadow: 0 0 14px rgb(255 110 30 / 50%);
}

[data-theme="fire"] .tile-book {
  box-shadow: 0 0 0 1px rgb(255 140 60 / 22%), 0 8px 22px rgb(0 0 0 / 60%);
}

[data-theme="fire"] .book-tile:hover .tile-book {
  box-shadow: 0 0 0 1px rgb(255 150 70 / 50%), 0 0 26px rgb(255 110 30 / 45%);
}

[data-theme="fire"] .collection-value-amount,
[data-theme="fire"] .money {
  text-shadow: 0 0 12px rgb(255 180 80 / 40%);
}

[data-theme="fire"] .avatar {
  box-shadow: 0 0 10px rgb(255 140 50 / 40%);
}

@media (prefers-reduced-motion: reduce) {
  [data-theme="fire"] body::before,
  [data-theme="fire"] body::after,
  .mark-flames path {
    animation: none;
  }
}

/*
 * Margin art (DR-028 #7): a line drawing for the theme in each side margin, a different
 * one for each kind of page (home, shelves, reading, desk). Faint at the edge of the
 * window, it fades out completely a fifth of the way into the page's content. The right
 * margin shows the drawing mirrored. Hidden when the margins are too narrow to hold it.
 * Paths are absolute because a url() inside a custom property may resolve against the page.
 */
.margin-art {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
}

.margin-art::before,
.margin-art::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: calc((100vw - 64rem) / 2 + 12.8rem);
  background: var(--art) left center / auto 100% no-repeat;
  opacity: var(--art-opacity, 0.3);
  -webkit-mask-image: linear-gradient(90deg, #000, #000 calc(100% - 16rem), transparent);
  mask-image: linear-gradient(90deg, #000, #000 calc(100% - 16rem), transparent);
}

.margin-art::after {
  right: 0;
  left: auto;
  transform: scaleX(-1);
}

@media (max-width: 76rem) {
  .margin-art::before,
  .margin-art::after {
    display: none;
  }
}

/*
 * Painted backgrounds (DR-043): a theme with a painting shows it behind the whole page
 * instead of the margin drawings. A veil of the theme's paper colour lies over the
 * middle, where the content is, so the painting stays rich at the sides and text reads
 * easily in the centre. Phones and narrow windows get the smaller file.
 */
.margin-art {
  --veil-colour: color-mix(in srgb, var(--paper) 82%, transparent);
  background:
    linear-gradient(
      90deg,
      transparent,
      transparent calc(50% - 42rem),
      var(--veil-colour) calc(50% - 33rem),
      var(--veil-colour) calc(50% + 33rem),
      transparent calc(50% + 42rem),
      transparent
    ),
    var(--backdrop, none) center / cover no-repeat;
}

@media (max-width: 76rem) {
  .margin-art {
    --veil-colour: color-mix(in srgb, var(--paper) 88%, transparent);
  }
}

[data-theme="bookish"] {
  --backdrop: url("/static/img/generated/backgrounds/bookish-aisle-day-v2-1280.webp");
}

@media (min-width: 1300px), (min-resolution: 1.5dppx) {
  [data-theme="bookish"] {
    --backdrop: url("/static/img/generated/backgrounds/bookish-aisle-day-v2-1920.webp");
  }
}

/* The quiet of deep space, a faint galaxy and nebula at its edges; the drifting stars
   still pass over it */
[data-theme="galactic"] {
  --backdrop: url("/static/img/generated/backgrounds/galactic-v2-1280.webp");
}

@media (min-width: 1300px), (min-resolution: 1.5dppx) {
  [data-theme="galactic"] {
    --backdrop: url("/static/img/generated/backgrounds/galactic-v2-1920.webp");
  }
}

[data-theme="galactic"] .margin-art::before,
[data-theme="galactic"] .margin-art::after {
  display: none;
}

/* By night, bookish shows the library after dark, lit from beyond the frame (the first
   two tries had candles and lamps with impossible mountings, DR-043 #5) */
@media (prefers-color-scheme: dark) {
  [data-theme="bookish"] {
    --backdrop: url("/static/img/generated/backgrounds/bookish-aisle-night-v2-1280.webp");
  }
}

@media (prefers-color-scheme: dark) and (min-width: 1300px),
  (prefers-color-scheme: dark) and (min-resolution: 1.5dppx) {
  [data-theme="bookish"] {
    --backdrop: url("/static/img/generated/backgrounds/bookish-aisle-night-v2-1920.webp");
  }
}

/* Fire: a reading room by the hearth. The painting sits under both layers of sparks, so
   they still rise over all of it */
[data-theme="fire"] {
  --backdrop: url("/static/img/generated/backgrounds/fire-1280.webp");
}

@media (min-width: 1300px), (min-resolution: 1.5dppx) {
  [data-theme="fire"] {
    --backdrop: url("/static/img/generated/backgrounds/fire-1920.webp");
  }
}

[data-theme="fire"] .margin-art {
  z-index: -2;
}

/* Candlelight (templates/_candles.html, static/js/candles.js): the lanterns are painted
   into the bookish backgrounds (DR-047 #15); over each painted flame lies a warm glow,
   lightening what is under it, that sways and breathes on its own timing. Still when
   the device asks for less motion */
.candles {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
}

.candle-glow {
  position: absolute;
  width: var(--size);
  height: var(--size);
  margin: calc(var(--size) / -2) 0 0 calc(var(--size) / -2);
  border-radius: 50%;
  background: radial-gradient(
    circle,
    rgb(255 236 180 / 85%) 0,
    rgb(255 196 110 / 45%) 12%,
    rgb(255 160 70 / 16%) 40%,
    transparent 70%
  );
  mix-blend-mode: screen;
  animation: candle-glow 2.3s linear var(--flicker, 0s) infinite;
}

@keyframes candle-glow {
  0%,
  100% {
    opacity: 0.85;
    transform: scale(1);
  }
  9% {
    opacity: 1;
    transform: scale(1.06) translateY(-1%);
  }
  17% {
    opacity: 0.66;
    transform: scale(0.95);
  }
  31% {
    opacity: 0.95;
    transform: scale(1.04) translateX(1%);
  }
  38% {
    opacity: 0.58;
    transform: scale(0.92);
  }
  52% {
    opacity: 1;
    transform: scale(1.07) translateX(-1%);
  }
  66% {
    opacity: 0.74;
    transform: scale(0.97);
  }
  74% {
    opacity: 0.95;
    transform: scale(1.03);
  }
  88% {
    opacity: 0.68;
    transform: scale(0.96);
  }
}

@media (prefers-reduced-motion: reduce) {
  .candle-glow {
    animation: none;
  }
}

/* A painting replaces the margin drawings */
[data-theme="bookish"] .margin-art::before,
[data-theme="bookish"] .margin-art::after,
[data-theme="fire"] .margin-art::before,
[data-theme="fire"] .margin-art::after {
  display: none;
}

[data-art="home"] { --art: url("/static/img/margins/bookish-home.svg"); }
[data-art="shelves"] { --art: url("/static/img/margins/bookish-shelves.svg"); }
[data-art="reading"] { --art: url("/static/img/margins/bookish-reading.svg"); }
[data-art="desk"] { --art: url("/static/img/margins/bookish-desk.svg"); }

[data-theme="galactic"] [data-art="home"] { --art: url("/static/img/margins/galactic-home.svg"); }
[data-theme="galactic"] [data-art="shelves"] { --art: url("/static/img/margins/galactic-shelves.svg"); }
[data-theme="galactic"] [data-art="reading"] { --art: url("/static/img/margins/galactic-reading.svg"); }
[data-theme="galactic"] [data-art="desk"] { --art: url("/static/img/margins/galactic-desk.svg"); }

[data-theme="fire"] [data-art="home"] { --art: url("/static/img/margins/fire-home.svg"); }
[data-theme="fire"] [data-art="shelves"] { --art: url("/static/img/margins/fire-shelves.svg"); }
[data-theme="fire"] [data-art="reading"] { --art: url("/static/img/margins/fire-reading.svg"); }
[data-theme="fire"] [data-art="desk"] { --art: url("/static/img/margins/fire-desk.svg"); }

[data-theme="galactic"] .margin-art,
[data-theme="fire"] .margin-art {
  --art-opacity: 0.5;
}

/* Sepia ink, lightened to stay visible on the dark paper */
@media (prefers-color-scheme: dark) {
  [data-theme="bookish"] .margin-art::before,
  [data-theme="bookish"] .margin-art::after {
    filter: invert(0.8) hue-rotate(180deg);
  }
}

/* Tags on a book or copy (DR-029 #6): Search tags beside New tag */
.tag-tools {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  gap: 1rem 2rem;
  align-items: start;
}

.tag-tools form {
  margin: 0;
}

.tag-tools > form > label {
  display: block;
  margin-bottom: 0.3rem;
  font-weight: 600;
  font-size: 0.92rem;
}

/* The search box and its arrow, over a ticklist that drops down */
.tag-combo {
  position: relative;
  flex: 1 1 13rem;
  max-width: 22rem;
}

.tag-combo-field {
  display: flex;
}

.tag-combo-field input {
  flex: 1;
  min-width: 0;
  border-right: none;
  border-radius: 2px 0 0 2px;
}

.tag-combo-toggle {
  padding: 0 0.6rem;
  border: 1px solid var(--rule);
  border-radius: 0 2px 2px 0;
  background: var(--page);
  color: var(--ink-soft);
  box-shadow: none;
}

.tag-combo-toggle svg {
  width: 0.8rem;
  height: 0.8rem;
  transition: transform 0.15s;
}

.tag-combo.is-open .tag-combo-toggle svg {
  transform: rotate(180deg);
}

.tag-options {
  position: absolute;
  top: calc(100% + 0.25rem);
  left: 0;
  right: 0;
  z-index: 20;
  max-height: 15rem;
  margin: 0;
  padding: 0.3rem;
  overflow-y: auto;
  list-style: none;
  border: 1px solid var(--rule);
  border-top: 2px solid var(--brass);
  border-radius: var(--radius);
  background: var(--page);
  box-shadow: var(--shadow);
}

.tag-options label {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  padding: 0.35rem 0.5rem;
  border-radius: 2px;
  cursor: pointer;
}

.tag-options label:hover,
.tag-options label:has(:focus-visible) {
  background: var(--accent-soft);
}

.tag-options .tag-none {
  padding: 0.35rem 0.5rem;
}

.tag-dot {
  flex: none;
  width: 0.7rem;
  height: 0.7rem;
  border-radius: 50%;
  background: var(--tag, var(--accent-soft));
  box-shadow: inset 0 0 0 1px rgb(0 0 0 / 15%);
}

/* Colour swatches under New tag and on the tag's edit panel */
.tag-colours {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  align-items: center;
  margin: 0.65rem 0 0;
  padding: 0;
  border: none;
}

.tag-colours legend {
  float: left;
  margin-right: 0.4rem;
  color: var(--ink-soft);
  font-size: 0.9rem;
}

.swatch {
  position: relative;
  display: grid;
  place-items: center;
  cursor: pointer;
}

.swatch input[type="radio"] {
  position: absolute;
  opacity: 0;
}

.swatch span[aria-hidden] {
  width: 1.45rem;
  height: 1.45rem;
  border-radius: 50%;
  background: var(--swatch);
  box-shadow: inset 0 0 0 1px rgb(0 0 0 / 18%);
  transition: transform 0.12s;
}

.swatch:hover span[aria-hidden] {
  transform: scale(1.12);
}

.swatch input:checked + span[aria-hidden] {
  box-shadow: 0 0 0 2px var(--page), 0 0 0 4px var(--ink);
}

.swatch input:focus-visible + span[aria-hidden] {
  outline: 3px solid var(--brass);
  outline-offset: 3px;
}

.swatch-none span[aria-hidden] {
  background:
    linear-gradient(135deg, transparent 46%, var(--danger) 46% 54%, transparent 54%),
    var(--page);
}

.swatch-custom input[type="color"] {
  width: 1.9rem;
  height: 1.6rem;
  padding: 0.1rem;
  border: 1px solid var(--rule);
  border-radius: 2px;
  background: var(--page);
  cursor: pointer;
}

.swatch-custom:has(input[type="radio"]:checked) input[type="color"] {
  box-shadow: 0 0 0 2px var(--page), 0 0 0 4px var(--ink);
}

/* A library filtered by a tag: the tag, its count and Edit tag */
.tag-banner {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1rem;
  align-items: center;
  margin: 0.75rem 0 1rem;
}

.tag-banner ul.tags {
  margin: 0;
}

.tag-banner ul.tags li {
  padding-right: 0.7rem;
  font-size: 1.05rem;
}

.tag-edit {
  position: relative;
  margin: 0;
}

.tag-edit > summary {
  list-style: none;
}

.tag-edit > summary::-webkit-details-marker {
  display: none;
}

.tag-edit-form {
  position: absolute;
  top: calc(100% + 0.4rem);
  left: 0;
  z-index: 20;
  width: min(24rem, calc(100vw - 2rem));
  padding: 0.9rem 1rem 1rem;
  border: 1px solid var(--rule);
  border-top: 2px solid var(--brass);
  border-radius: var(--radius);
  background: var(--page);
  box-shadow: var(--shadow);
}

.tag-edit-form > label {
  display: block;
  margin-bottom: 0.3rem;
  font-weight: 600;
  font-size: 0.92rem;
}

/* Your rating (DR-029 #2): five closed books in a row, a brass fill rising in them.
   A half rating fills a book up to a slanted line, top-right to bottom-left. The books
   are a mask, so the fill and the empty board are plain colours under it. */
.rate-and-tbr {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem 1.25rem;
  align-items: center;
}

.book-rating-form {
  display: flex;
  gap: 0.35rem;
  align-items: center;
  margin: 0;
}

.book-rating {
  --book: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 24'%3E%3Cpath fill-rule='evenodd' d='M4 1h13a1 1 0 0 1 1 1v19H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1zM5.4 2v18h.7V2zM7.5 4h8.5v.8H7.5zM7.5 16.4h8.5v.8H7.5zM11.75 6.6l2.1 3.1-2.1 3.1-2.1-3.1z'/%3E%3Cpath d='M3 21.7h15V23H4a1 1 0 0 1-1-1z'/%3E%3C/svg%3E");
  display: inline-flex;
  gap: 0.2rem;
  padding: 0.15rem;
  border-radius: 3px;
  cursor: pointer;
  touch-action: manipulation;
}

.rating-book {
  position: relative;
  width: 1.55rem;
  height: 1.85rem;
  background: color-mix(in srgb, var(--ink-soft) 30%, transparent);
  -webkit-mask: var(--book) center / contain no-repeat;
  mask: var(--book) center / contain no-repeat;
  transition: transform 0.15s;
}

.rating-book-fill {
  position: absolute;
  inset: 0;
  background: linear-gradient(160deg, #f1cf7a, var(--brass) 55%, #8a5f22);
  clip-path: polygon(0 0, 0 0, 0 100%, 0 100%);
  transition: clip-path 0.18s ease-out;
}

.rating-book.is-half .rating-book-fill {
  clip-path: polygon(0 0, 68% 0, 32% 100%, 0 100%);
}

.rating-book.is-full .rating-book-fill {
  clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
}

.book-rating.is-previewing .rating-book-fill {
  opacity: 0.75;
}

.book-rating:hover .rating-book {
  transform: translateY(-1px);
}

/* Saved: the books give a small bow, one after another */
.book-rating.is-saved .rating-book {
  animation: rating-bow 0.45s ease-out;
}

.book-rating.is-saved .rating-book:nth-child(2) { animation-delay: 0.04s; }
.book-rating.is-saved .rating-book:nth-child(3) { animation-delay: 0.08s; }
.book-rating.is-saved .rating-book:nth-child(4) { animation-delay: 0.12s; }
.book-rating.is-saved .rating-book:nth-child(5) { animation-delay: 0.16s; }

@keyframes rating-bow {
  40% {
    transform: translateY(-3px) rotate(-4deg);
  }
}

.rating-clear {
  padding: 0 0.35rem;
  border: none;
  background: none;
  color: var(--ink-soft);
  font-family: var(--sans);
  font-size: 1.15rem;
  box-shadow: none;
}

.rating-clear:hover {
  background: none;
  color: var(--danger);
}

/* + TBR: a bookmark ribbon tab; once on the list it turns brass with a tick */
.tbr-form {
  margin: 0;
}

.tbr-button {
  gap: 0.3rem;
  padding: 0.3rem 0.85rem 0.36rem 0.7rem;
}

.tbr-mark {
  font-family: var(--sans);
  font-weight: 700;
}

.tbr-button.is-on {
  --plate-gap: var(--brass-soft);
  --plate-rule: var(--brass);
  border-color: var(--brass);
  background: var(--brass-soft);
  color: var(--ink);
}

@media (prefers-reduced-motion: reduce) {
  .book-rating.is-saved .rating-book {
    animation: none;
  }
}

/* The synopsis (DR-029 #1): about a paragraph, then Read more opens the rest */
.synopsis-box {
  max-width: 42rem;
  margin: 0.75rem 0 0;
}

.synopsis-box .synopsis {
  margin: 0;
}

.synopsis-box.is-clamped .synopsis {
  display: -webkit-box;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 5;
  line-clamp: 5;
  mask-image: linear-gradient(180deg, #000 70%, transparent);
}

.synopsis-more {
  margin-top: 0.35rem;
  padding: 0.1rem 0;
  border: none;
  background: none;
  color: var(--accent);
  font-size: 1rem;
  box-shadow: none;
}

.synopsis-more:hover {
  background: none;
  text-decoration: underline;
}

.reading-as {
  margin: 0;
}

/* Manual entry (DR-029 #4): author lines, each a name and a role, and Add another */
.stacked fieldset.date-row {
  margin: 0.9rem 0 0.4rem;
  padding: 0;
  border: none;
  background: none;
  box-shadow: none;
}

.field-label {
  display: block;
  margin-bottom: 0.2rem;
  font-weight: 600;
  font-size: 0.92rem;
}

.author-rows {
  display: grid;
  gap: 0.45rem;
  max-width: 32rem;
}

.stacked .author-row {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  margin: 0;
}

.stacked .author-row input {
  flex: 1;
  min-width: 0;
}

.stacked .author-row select {
  flex: none;
  width: auto;
}

.add-row {
  margin-top: 0.55rem;
  padding: 0.2rem 0.7rem;
  font-size: 0.95rem;
}

.stacked .author-rows {
  margin-bottom: 0;
}

/* Search results (DR-030): cover and title open Choose edition; authors and the series
   are links that search for just them */
.search-hits {
  gap: 0.75rem;
}

.book-list .search-hit {
  display: grid;
  grid-template-columns: 4.5rem minmax(0, 1fr);
  gap: 1rem;
  align-items: start;
}

.search-hit-cover .cover,
.search-hit-cover .cover-blank {
  display: block;
  width: 4.5rem;
  height: auto;
  min-height: 6.5rem;
  border-radius: 2px 4px 4px 2px;
  box-shadow: var(--shadow);
  transition: transform 0.2s;
}

.search-hit-cover:hover .cover {
  transform: translateY(-2px) rotate(-1.5deg);
}

.search-hit-text {
  position: relative;
}

.search-hit-title {
  font-family: var(--serif);
  font-size: 1.3rem;
  line-height: 1.2;
  color: var(--ink);
  text-decoration: none;
}

.search-hit-title:hover {
  color: var(--accent-strong);
  text-decoration: underline;
}

.search-hit-authors,
.search-hit-series,
.search-hit-ratings {
  margin: 0.2rem 0 0;
}

.search-hit-series {
  font-family: var(--serif);
  font-style: italic;
}

.search-hit-ratings {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 1rem;
  align-items: center;
  font-size: 0.95rem;
}

.search-hit .actions {
  margin-top: 0.6rem;
}

/* A series' book number, stamped like a library spine label */
.series-number {
  display: inline-grid;
  place-items: center;
  min-width: 2.1rem;
  height: 1.7rem;
  margin-right: 0.5rem;
  padding: 0 0.35rem;
  border: 1px solid var(--brass);
  border-radius: 2px;
  background: var(--brass-soft);
  color: var(--ink);
  font-family: var(--figures);
  font-size: 0.95rem;
  font-variant-numeric: lining-nums tabular-nums;
  font-weight: 600;
  vertical-align: 0.15em;
  box-shadow: inset 0 0 0 2px var(--page);
}

.book-list .search-hit-bare {
  display: block;
  padding: 0.6rem 1rem;
}

.find-kind {
  margin: 0.25rem 0 -0.4rem;
  color: var(--ink-soft);
  font-family: var(--caps);
  font-size: 1.05rem;
  letter-spacing: 0.04em;
}

/* Choose edition's book: genres as small stamped labels */
.genres {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin: 0.75rem 0 0;
  padding: 0;
  list-style: none;
}

.genres li {
  padding: 0.05rem 0.55rem 0.1rem;
  border: 1px solid var(--rule);
  border-radius: 2px;
  color: var(--ink-soft);
  font-family: var(--caps);
  font-size: 0.95rem;
}

.wish-form {
  margin: 0.6rem 0 0;
}

.edition-group {
  margin-top: 1.6rem;
  font-family: var(--caps);
  letter-spacing: 0.03em;
}

.cover-change.is-static {
  cursor: default;
}

@media (max-width: 34rem) {
  .book-list .search-hit {
    grid-template-columns: 3.5rem minmax(0, 1fr);
    gap: 0.75rem;
  }

  .search-hit-cover .cover,
  .search-hit-cover .cover-blank {
    width: 3.5rem;
    min-height: 5rem;
  }
}

/* Browse popular new choices (DR-031 #1): each genre a cloth-bound book with its emblem
   stamped in gilt. Hovered, the book lifts, its board swings open on the pages beneath,
   and the emblem catches the light. */
.browse {
  margin: 2.5rem 0;
}

.genre-shelf {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr));
  gap: 1.4rem 1.1rem;
  margin: 1rem 0 0;
  padding: 0;
  list-style: none;
}

.genre-book {
  position: relative;
  display: block;
  aspect-ratio: 3 / 4;
  perspective: 900px;
  color: #f3dfa8;
  text-decoration: none;
  transition: transform 0.35s cubic-bezier(0.2, 0.8, 0.3, 1);
}

.genre-pages,
.genre-board {
  position: absolute;
  inset: 0;
  border-radius: 2px 6px 6px 2px;
}

/* The first page under the board: plain book paper, white with the faintest warmth,
   shaded into the gutter at the hinge */
.genre-pages {
  inset: 3% 2% 3% 6%;
  background:
    linear-gradient(90deg, rgb(90 70 40 / 22%), rgb(90 70 40 / 6%) 7%, transparent 16%),
    #fbf8f0;
  box-shadow: 0 10px 18px -8px rgb(0 0 0 / 45%);
}

.genre-board {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding: 0 0.5rem 9%;
  overflow: hidden;
  /* The painted cover (DR-043), with the hinge shaded at the left */
  background:
    linear-gradient(90deg, rgb(0 0 0 / 30%) 0 5%, rgb(255 255 255 / 7%) 5% 6%, transparent 6%),
    var(--tile) center / cover no-repeat,
    var(--cloth);
  box-shadow:
    inset 0 0 0 1px rgb(0 0 0 / 30%),
    0 8px 16px -6px rgb(0 0 0 / 55%);
  transform-origin: left center;
  transition: transform 0.45s cubic-bezier(0.2, 0.8, 0.3, 1), box-shadow 0.45s, filter 0.45s;
  backface-visibility: hidden;
}

/* A sheen that crosses the gilt when the book is picked up */
.genre-board::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(105deg, transparent 35%, rgb(255 236 190 / 22%) 50%, transparent 65%);
  background-size: 250% 100%;
  background-position: 120% 0;
  pointer-events: none;
  transition: background-position 1.2s ease;
}

.genre-name {
  position: relative;
  padding: 0.15rem 0.55rem;
  border-block: 1px solid rgb(243 223 168 / 55%);
  font-family: var(--caps);
  font-size: 1rem;
  line-height: 1.15;
  letter-spacing: 0.04em;
  text-align: center;
  background: color-mix(in srgb, var(--cloth) 70%, rgb(0 0 0 / 55%));
  text-shadow: 0 1px 0 rgb(0 0 0 / 50%);
}

.genre-book:hover,
.genre-book:focus-visible {
  transform: translateY(-6px);
}

.genre-book:hover .genre-board,
.genre-book:focus-visible .genre-board {
  transform: rotateY(-26deg);
  filter: brightness(1.08);
  box-shadow:
    inset 0 0 0 1px rgb(0 0 0 / 30%),
    14px 12px 22px -8px rgb(0 0 0 / 55%);
}

.genre-book:hover .genre-board::after,
.genre-book:focus-visible .genre-board::after {
  background-position: -20% 0;
}

@media (prefers-reduced-motion: reduce) {
  .genre-book,
  .genre-board,
  .genre-board::after {
    transition: none;
  }
}

/* A genre's page: the other genres as small cloth labels, then the books */
.genre-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 0.5rem 0 1.5rem;
}

.genre-strip a {
  padding: 0.15rem 0.6rem 0.2rem;
  border-radius: 2px;
  background: var(--cloth);
  color: #f3dfa8;
  font-family: var(--caps);
  font-size: 0.98rem;
  text-decoration: none;
  opacity: 0.8;
  transition: opacity 0.15s, transform 0.15s;
}

.genre-strip a:hover,
.genre-strip a[aria-current="page"] {
  opacity: 1;
  transform: translateY(-1px);
}

.genre-strip a[aria-current="page"] {
  box-shadow: 0 0 0 2px var(--paper), 0 0 0 3px var(--brass);
}

.browse-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr));
  gap: 1.5rem 1.1rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.browse-more,
.browse-note {
  grid-column: 1 / -1;
}

.browse-book {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  color: var(--ink);
  text-decoration: none;
}

.browse-cover {
  display: block;
  aspect-ratio: 2 / 3;
  margin-bottom: 0.35rem;
  overflow: hidden;
  border-radius: 2px 5px 5px 2px;
  background: var(--rule);
  box-shadow: var(--shadow);
  transition: transform 0.25s, box-shadow 0.25s;
}

.browse-cover img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.browse-book:hover .browse-cover {
  transform: translateY(-3px) rotate(-1deg);
  box-shadow: 0 10px 22px -8px rgb(0 0 0 / 45%);
}

.browse-title {
  font-family: var(--serif);
  font-size: 1.02rem;
  line-height: 1.2;
}

.browse-book:hover .browse-title {
  color: var(--accent-strong);
  text-decoration: underline;
}

.browse-author,
.browse-rating {
  color: var(--ink-soft);
  font-size: 0.9rem;
}

/* The seasonal shelf (DR-031 #3): the holiday's colours along a shelf of covers that
   lean in one after another */
.season {
  --season: var(--brass);
  --season-2: var(--accent);
  margin: 2.25rem 0;
  padding: 1.1rem 1.25rem 1.25rem;
  border: 1px solid var(--rule);
  border-top: 3px solid var(--season);
  border-radius: var(--radius);
  background:
    radial-gradient(ellipse 60% 80% at 100% 0%, color-mix(in srgb, var(--season) 16%, transparent), transparent 70%),
    var(--page);
  box-shadow: var(--shadow);
}

.season-halloween { --season: #e2711d; --season-2: #5b2a86; }
.season-christmas { --season: #b3242e; --season-2: #2f6b3a; }
.season-valentines-day { --season: #c2416b; --season-2: #8c2f39; }
.season-lunar-new-year { --season: #c8102e; --season-2: #d4a017; }
.season-presidents-day { --season: #2b4c7e; --season-2: #b22234; }
.season-juneteenth { --season: #b3242e; --season-2: #2f6b3a; }

.season-head h2 {
  margin: 0.1rem 0 0.25rem;
  padding: 0;
  border: none;
}

.season-head .muted {
  margin: 0 0 1rem;
}

.season-shelf {
  display: grid;
  grid-auto-columns: 7.5rem;
  grid-auto-flow: column;
  gap: 1rem;
  margin: 0;
  padding: 0.25rem 0.1rem 1rem;
  overflow-x: auto;
  list-style: none;
  border-bottom: 6px solid color-mix(in srgb, var(--season-2) 55%, #3b2a1a);
  scroll-snap-type: x proximity;
}

.season-shelf li {
  scroll-snap-align: start;
  animation: lean-in 0.5s cubic-bezier(0.2, 0.9, 0.3, 1.15) both;
  animation-delay: calc(var(--i) * 0.06s);
}

@keyframes lean-in {
  from {
    opacity: 0;
    transform: translateY(14px) rotate(4deg);
  }
}

@media (prefers-reduced-motion: reduce) {
  .season-shelf li {
    animation: none;
  }
}

/* Authors (DR-032): a cloth monogram, Favorite, and stats as stamped tallies */
.author-head {
  display: flex;
  gap: 1.25rem;
  align-items: center;
  margin: 0.5rem 0 1rem;
}

.author-head h1 {
  margin: 0.1rem 0 0.2rem;
}

.author-head-text .muted {
  margin: 0 0 0.6rem;
}

.monogram {
  display: grid;
  flex: none;
  background:
    radial-gradient(ellipse at 30% 25%, rgb(255 255 255 / 16%), transparent 60%),
    var(--cloth, var(--accent));
  place-items: center;
  width: 5.5rem;
  height: 5.5rem;
  border-radius: 50%;
  color: #f3dfa8;
  font-family: var(--caps);
  font-size: 1.9rem;
  letter-spacing: 0.04em;
  text-shadow: 0 1px 0 rgb(0 0 0 / 40%);
  box-shadow:
    inset 0 0 0 4px rgb(0 0 0 / 15%),
    inset 0 0 0 5px rgb(243 223 168 / 55%),
    var(--shadow);
}

.author-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1.5rem;
  margin: 0 0 1.5rem;
  padding: 0;
  list-style: none;
}

.favorite-form {
  margin: 0;
}

.favorite-button svg {
  width: 1.15rem;
  height: 1.15rem;
}

.favorite-button svg path:first-child {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linejoin: round;
}

.favorite-heart {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.2;
  transform-box: fill-box;
  transform-origin: center;
}

.favorite-button.is-on {
  --plate-gap: var(--brass-soft);
  --plate-rule: var(--brass);
  border-color: var(--brass);
  background: var(--brass-soft);
  color: var(--ink);
}

.favorite-button.is-on svg path:first-child {
  fill: var(--brass);
  stroke: var(--brass);
}

.favorite-button.is-on .favorite-heart {
  fill: #b3242e;
  stroke: #b3242e;
  animation: heart-beat 1.6s ease-in-out 1;
}

.favorite-button:not(.is-on):hover .favorite-heart {
  fill: color-mix(in srgb, #b3242e 45%, transparent);
}

@keyframes heart-beat {
  20% {
    transform: scale(1.35);
  }

  40% {
    transform: scale(1);
  }
}

/* Favorites: sort tabs, then a card per author */
.sort-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 0.9rem;
  align-items: baseline;
  margin: 0 0 1.25rem;
}

.sort-tabs a {
  font-family: var(--caps);
  font-size: 1.05rem;
  text-decoration: none;
}

.sort-tabs a[aria-current] {
  color: var(--ink);
  box-shadow: 0 2px 0 var(--brass);
}

.favorite-cards {
  display: grid;
  gap: 0.9rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.favorite-card {
  display: flex;
  gap: 1.1rem;
  align-items: center;
  padding: 1rem 1.25rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--page);
  box-shadow: var(--shadow);
}

.favorite-card .monogram {
  width: 4rem;
  height: 4rem;
  font-size: 1.4rem;
}

.favorite-card h2 {
  margin: 0;
  padding: 0;
  border: none;
  font-size: 1.4rem;
}

.favorite-card h2 a {
  color: var(--ink);
  text-decoration: none;
}

.favorite-card h2 a:hover {
  color: var(--accent-strong);
  text-decoration: underline;
}

.favorite-card .muted {
  margin: 0.1rem 0 0.6rem;
}

.favorite-card .author-stats {
  margin: 0;
}

@media (max-width: 34rem) {
  .favorite-card,
  .author-head {
    align-items: flex-start;
  }

  .monogram {
    width: 4rem;
    height: 4rem;
    font-size: 1.4rem;
  }
}

/* Delete library (DR-033 #1): the trash icon is a button; hovered it warns in red */
button.icon-link {
  padding: 0;
  border: none;
  background: none;
  box-shadow: none;
}

button.icon-link:hover {
  background: var(--danger-soft);
  color: var(--danger);
}

.button.button-danger {
  --plate-gap: var(--danger);
  --plate-rule: rgb(255 236 220 / 45%);
  border-color: var(--danger);
  background: var(--danger);
  color: #fff8f2;
}

.button.button-danger:hover {
  --plate-gap: color-mix(in srgb, var(--danger) 82%, #000);
  border-color: color-mix(in srgb, var(--danger) 82%, #000);
  background: color-mix(in srgb, var(--danger) 82%, #000);
}

/* Upload library (DR-034) ----------------------------------------------------------- */

/* Someone searching a shelf in a round frame (DR-034, DR-043): a lantern's light moves
   along the shelf; each book in turn is drawn out while its pages riffle open above,
   then goes back. One book every 1.4 seconds, round the seven and again. */
.seeker {
  position: relative;
  display: block;
  flex: none;
  width: 3rem;
  height: 3rem;
  overflow: hidden;
  border-radius: 50%;
  background:
    radial-gradient(ellipse 90% 70% at 50% 100%, rgb(255 190 110 / 18%), transparent 70%),
    linear-gradient(180deg, #2a1a0e, #1a0f07);
}

.seeker-large {
  width: 8rem;
  height: 8rem;
  border: 2px solid var(--brass);
  box-shadow: var(--shadow), 0 0 0 4px color-mix(in srgb, var(--brass) 18%, transparent);
}

.seeker-row {
  position: absolute;
  left: 12%;
  right: 12%;
  bottom: 24%;
  display: flex;
  gap: 1.6%;
  align-items: flex-end;
  height: 36%;
}

.seeker-spine {
  flex: 1;
  height: 86%;
  border-radius: 1px 1px 0 0;
  background:
    linear-gradient(180deg, transparent 14%, rgb(240 200 120 / 70%) 14% 18%, transparent 18% 80%, rgb(240 200 120 / 70%) 80% 84%, transparent 84%),
    var(--spine, #6e2a2a);
  box-shadow: inset -1px 0 0 rgb(0 0 0 / 35%);
  transform-origin: 50% 100%;
  animation: seeker-pull 9.8s ease-in-out calc(var(--i) * 1.4s) infinite;
}

.seeker-spine:nth-child(2) { --spine: #263a5e; height: 100%; }
.seeker-spine:nth-child(3) { --spine: #3e4a2a; height: 78%; }
.seeker-spine:nth-child(4) { --spine: #8a5a32; height: 94%; }
.seeker-spine:nth-child(5) { --spine: #4b2f5a; height: 82%; }
.seeker-spine:nth-child(6) { --spine: #2f5d50; height: 97%; }
.seeker-spine:nth-child(7) { --spine: #6b4f2a; height: 88%; }

/* A book drawn out and tipped toward the light, then slid back */
@keyframes seeker-pull {
  0%,
  14.29%,
  100% {
    transform: none;
  }

  2.86%,
  10.00% {
    transform: translateY(-34%) rotate(-7deg);
  }
}

.seeker-plank {
  position: absolute;
  left: 6%;
  right: 6%;
  bottom: 18%;
  height: 6%;
  border-radius: 1px;
  background: linear-gradient(180deg, #b07a46, #6b4122 60%, #4a2c15);
}

/* The lantern's light, moving to each book in turn */
.seeker-light {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 16.5%;
  width: 0;
  animation: seeker-light 9.8s ease-in-out infinite;
}

.seeker-light::before {
  content: "";
  position: absolute;
  top: 18%;
  left: -1.6em;
  width: 3.2em;
  height: 70%;
  background: radial-gradient(ellipse 50% 50% at 50% 55%, rgb(255 214 140 / 50%), transparent 70%);
  font-size: calc(1px * 12);
  mix-blend-mode: screen;
}

.seeker-large .seeker-light::before {
  font-size: calc(1px * 30);
}

@keyframes seeker-light {
  0.00%,
  11.43% {
    left: 16.5%;
  }

  14.29%,
  25.71% {
    left: 27.1%;
  }

  28.57%,
  40.00% {
    left: 37.7%;
  }

  42.86%,
  54.29% {
    left: 48.3%;
  }

  57.14%,
  68.57% {
    left: 58.9%;
  }

  71.43%,
  82.86% {
    left: 69.5%;
  }

  85.71%,
  97.14% {
    left: 80.1%;
  }

  100% {
    left: 16.5%;
  }
}

/* Pages riffling open above the shelf while each book is out */
.seeker-open {
  position: absolute;
  top: 9%;
  left: 50%;
  width: 2.2em;
  height: 1.3em;
  font-size: 12px;
  transform: translateX(-50%);
  opacity: 0;
  animation: seeker-open 1.4s ease-in-out infinite;
  background:
    linear-gradient(90deg, rgb(0 0 0 / 0%) 48%, rgb(120 90 50 / 55%) 50%, rgb(0 0 0 / 0%) 52%),
    linear-gradient(180deg, #fbf5e6, #e9dcbc);
  border-radius: 2px 2px 3px 3px;
  box-shadow: 0 1px 3px rgb(0 0 0 / 50%), 0 0 10px rgb(255 214 140 / 40%);
  perspective: 60px;
}

.seeker-large .seeker-open {
  font-size: 26px;
}

.seeker-leaf {
  position: absolute;
  top: 6%;
  bottom: 6%;
  left: 50%;
  width: 46%;
  background: linear-gradient(90deg, #f3e8cf, #fffaf0);
  transform-origin: 0 50%;
  animation: seeker-leaf 0.35s linear infinite;
}

@keyframes seeker-open {
  0%,
  12%,
  80%,
  100% {
    opacity: 0;
    transform: translateX(-50%) translateY(20%) scale(0.7);
  }

  24%,
  66% {
    opacity: 1;
    transform: translateX(-50%) translateY(0) scale(1);
  }
}

@keyframes seeker-leaf {
  to {
    transform: rotateY(-180deg);
  }
}

@media (prefers-reduced-motion: reduce) {
  .seeker-spine,
  .seeker-light,
  .seeker-leaf {
    animation: none;
  }

  .seeker-open {
    animation: none;
    opacity: 1;
    transform: translateX(-50%);
  }
}

/* Floating at the right edge of every page while a list is matched (DR-034 #4): see-
   through until hovered; the label and progress show only while hovered or focused */
.import-indicator {
  position: fixed;
  right: 0.9rem;
  bottom: 5.5rem;
  z-index: 40;
  display: block;
  color: var(--ink);
  text-decoration: none;
}

.import-indicator-icon {
  display: grid;
  place-items: center;
  width: 4rem;
  height: 4rem;
  border: 1.5px solid var(--brass);
  border-radius: 50%;
  background: var(--page);
  box-shadow: var(--shadow), 0 0 0 3px color-mix(in srgb, var(--brass) 25%, transparent);
  transition: transform 0.2s ease;
}

.import-indicator-icon .seeker {
  width: 100%;
  height: 100%;
}

/* A finished list with lines not matched: the reader rests, with a red ! on its frame */
.import-indicator-icon {
  position: relative;
}

.import-indicator-alert {
  position: absolute;
  top: -0.2rem;
  right: -0.2rem;
  display: grid;
  place-items: center;
  width: 1.15rem;
  height: 1.15rem;
  border: 2px solid var(--page);
  border-radius: 50%;
  background: #c0392b;
  color: #fff;
  font-family: var(--figures);
  font-size: 0.75rem;
  font-weight: 800;
  line-height: 1;
  box-shadow: 0 1px 3px rgb(0 0 0 / 35%);
}

/* A finished list rests: the shelf scene holds still */
.import-indicator.has-misses .seeker * {
  animation: none;
}

.import-missed-head {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1rem;
  align-items: center;
  justify-content: space-between;
}

.import-missed-head h3 {
  margin: 0;
}

.import-missed-head .button {
  display: inline-flex;
  gap: 0.4rem;
  align-items: center;
}

.import-missed-head .button svg {
  width: 1.1rem;
  height: 1.1rem;
}

.import-indicator:hover .import-indicator-icon,
.import-indicator:focus-visible .import-indicator-icon {
  transform: scale(1.06);
}

.import-indicator-tip {
  position: absolute;
  right: calc(100% + 0.6rem);
  bottom: 0.4rem;
  display: none;
  width: 15rem;
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--page);
  box-shadow: var(--shadow);
  font-size: 0.9rem;
}

.import-indicator:hover .import-indicator-tip,
.import-indicator:focus-visible .import-indicator-tip {
  display: grid;
  gap: 0.35rem;
}

.import-indicator-tip strong {
  font-family: var(--caps);
  font-weight: normal;
}

/* Progress bars on the indicator and the upload's page */
.import-indicator progress,
.import-progress progress {
  width: 100%;
  height: 0.6rem;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--paper);
  overflow: hidden;
  appearance: none;
}

.import-indicator progress::-webkit-progress-bar,
.import-progress progress::-webkit-progress-bar {
  background: var(--paper);
}

.import-indicator progress::-webkit-progress-value,
.import-progress progress::-webkit-progress-value {
  background: var(--accent);
  transition: width 0.4s ease;
}

.import-indicator progress::-moz-progress-bar,
.import-progress progress::-moz-progress-bar {
  background: var(--accent);
}

/* The upload form beside what the list needs */
.import-help {
  display: grid;
  grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr);
  gap: 1.5rem;
  align-items: start;
  margin-bottom: 2rem;
}

.import-help h2 {
  margin-top: 0;
}

.import-columns {
  padding-left: 1.4rem;
}

.import-form {
  display: grid;
  gap: 0.6rem;
  padding: 1rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--page);
  box-shadow: var(--shadow);
}

.import-form label {
  font-family: var(--caps);
}

/* A list with reading columns for several people: whose are yours */
.reader-choice {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.2rem;
  margin: 0;
  padding: 0.6rem 0.8rem;
  border: 1px solid var(--brass);
  border-radius: var(--radius);
}

.reader-choice legend {
  padding: 0 0.3rem;
  font-weight: 600;
}

.reader-choice label {
  display: inline-flex;
  gap: 0.35rem;
  align-items: center;
  font-family: inherit;
}

@media (max-width: 720px) {
  .import-help {
    grid-template-columns: minmax(0, 1fr);
  }
}

.import-uploads {
  padding: 0;
  list-style: none;
}

.import-uploads li {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1rem;
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--rule);
}

.import-uploads-running {
  color: var(--accent);
}

/* An upload's page */
.import-progress {
  margin: 1rem 0 2rem;
}

.import-progress-head {
  display: flex;
  gap: 1.25rem;
  align-items: center;
  padding: 1rem 1.25rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--page);
  box-shadow: var(--shadow);
}

.import-progress-head h2 {
  margin: 0 0 0.25rem;
}

.import-progress:not(.is-matching) .seeker * {
  animation: none;
}

.import-counts {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem 0.9rem;
  margin: 0.5rem 0 0;
}

.import-count.is-added {
  color: var(--ok);
}

.import-count.is-held {
  color: var(--ink-soft);
}

.import-count.is-partial {
  color: #a8662a;
}

.import-count.is-missing {
  color: var(--warn);
}

.import-rows {
  padding: 0;
  list-style: none;
}

.import-rows li {
  display: flex;
  gap: 0.9rem;
  align-items: baseline;
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--rule);
}

.import-row-number {
  flex: none;
  width: 4.5rem;
  color: var(--ink-soft);
  font-family: var(--figures);
  font-size: 0.85rem;
  font-variant-numeric: lining-nums tabular-nums;
}

.import-matched summary {
  cursor: pointer;
  font-family: var(--caps);
}

@media (max-width: 600px) {
  .import-progress-head {
    flex-direction: column;
    align-items: stretch;
    text-align: center;
  }

  .import-progress-head .seeker {
    margin: 0 auto;
  }

  .import-indicator {
    right: 0.5rem;
    bottom: 4rem;
  }

  .import-indicator-icon {
    width: 3.25rem;
    height: 3.25rem;
  }
}

.import-progress-head .grow,
.import-rows .grow {
  flex: 1;
  min-width: 0;
}

/* Feedback (DR-036) */
.feedback-form textarea {
  display: block;
  width: 100%;
  resize: vertical;
}

.count-badge {
  margin-left: 0.3rem;
  padding: 0.05rem 0.45rem;
  border-radius: 999px;
  background: var(--brass);
  color: var(--page);
  font-size: 0.75rem;
}

.feedback-list {
  display: grid;
  gap: 0.75rem;
  margin: 1rem 0;
  padding: 0;
  list-style: none;
}

.feedback-item {
  padding: 0.9rem 1.1rem;
  border: 1px solid var(--rule);
  border-left: 4px solid var(--brass);
  border-radius: var(--radius);
  background: var(--page);
  box-shadow: var(--shadow);
}

.feedback-item.is-reviewed {
  border-left-color: var(--rule);
}

.feedback-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 0.75rem;
  align-items: baseline;
}

.feedback-message {
  margin: 0.5rem 0 0.75rem;
  font-family: var(--serif);
  font-size: 1.05rem;
  white-space: normal;
}

.feedback-photos {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin: 0 0 0.85rem;
  padding: 0;
  list-style: none;
}

.feedback-photos img {
  display: block;
  width: 9rem;
  height: 7rem;
  object-fit: cover;
  border: 1px solid var(--rule);
  border-radius: 4px;
  box-shadow: var(--shadow);
}

.feedback-reviewed summary {
  cursor: pointer;
  font-family: var(--caps);
}

/*
 * Series tracker (DR-039): a card per series with its books in reading order on a
 * shelf-like row. Owned books stand in full colour; missing ones are faded with a
 * dashed outline; books still to come carry a brass ribbon. Filters above narrow every
 * card to one kind of book.
 */
.series-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 1.25rem 0 1rem;
}

.series-filter {
  display: inline-flex;
  gap: 0.45rem;
  align-items: center;
  padding: 0.35rem 0.85rem;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--page);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 0.9rem;
  cursor: pointer;
}

.series-filter span {
  min-width: 1.4rem;
  padding: 0 0.35rem;
  border-radius: 999px;
  background: var(--brass-soft);
  color: var(--ink);
  font-variant-numeric: lining-nums tabular-nums;
  text-align: center;
}

.series-filter[aria-pressed="true"] {
  border-color: var(--brass);
  background: var(--brass);
  color: var(--page);
}

.series-filter[aria-pressed="true"] span {
  background: var(--page);
}

.series-cards {
  display: grid;
  gap: 1.1rem;
}

.series-card {
  padding: 1rem 1.1rem 0.6rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--page);
  box-shadow: var(--shadow);
}

.series-card.is-loading {
  opacity: 0.7;
}

.series-card-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 0.2rem 1rem;
  align-items: baseline;
}

.series-card-head h2 {
  margin: 0;
  font-size: 1.3rem;
}

.series-tally {
  color: var(--ink-soft);
  font-size: 0.9rem;
}

.series-progress {
  grid-column: 1 / -1;
  height: 4px;
  margin-top: 0.4rem;
  overflow: hidden;
  border-radius: 2px;
  background: var(--rule);
}

.series-progress span {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, var(--brass), var(--accent));
}

.series-books {
  display: flex;
  gap: 0.9rem;
  margin: 0;
  padding: 0.9rem 0.1rem 0.6rem;
  overflow-x: auto;
  list-style: none;
  scroll-snap-type: x proximity;
}

.series-book {
  flex: none;
  width: 6.5rem;
  scroll-snap-align: start;
}

.series-book-link {
  display: grid;
  gap: 0.3rem;
  color: inherit;
  text-decoration: none;
}

.series-cover {
  position: relative;
  display: block;
  aspect-ratio: 2 / 3;
  border-radius: 2px 4px 4px 2px;
  box-shadow: var(--shadow);
  transition: transform 0.2s ease;
}

.series-cover img {
  width: 100%;
  height: 100%;
  border-radius: inherit;
  object-fit: cover;
}

.series-cover .cloth-title {
  font-size: 0.7rem;
  line-height: 1.15;
}

a.series-book-link:hover .series-cover,
a.series-book-link:focus-visible .series-cover {
  transform: translateY(-3px);
}

.series-number {
  position: absolute;
  top: 0.3rem;
  left: -0.3rem;
  padding: 0.05rem 0.4rem;
  border-radius: 2px;
  background: var(--ink);
  color: var(--page);
  font-family: var(--sans);
  font-size: 0.72rem;
  font-weight: 600;
  box-shadow: var(--shadow);
}

.series-book-title {
  display: -webkit-box;
  overflow: hidden;
  /* Two whole lines: in a grid item Chrome measured the clamped box short and cut the
     second line through the middle */
  max-height: calc(2 * 1.25em);
  font-family: var(--serif);
  font-size: 0.88rem;
  line-height: 1.25;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  align-self: start;
}

.series-state {
  font-family: var(--sans);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.series-book.is-read .series-state { color: var(--ok); }
.series-book.is-unread .series-state { color: var(--accent); }
.series-book.is-missing .series-state { color: var(--danger); }
.series-book.is-upcoming .series-state { color: var(--warn); }

.series-book.is-missing .series-cover {
  outline: 1.5px dashed color-mix(in srgb, var(--danger) 60%, transparent);
  outline-offset: 2px;
  box-shadow: none;
}

.series-book.is-missing .series-cover > * {
  opacity: 0.45;
  filter: grayscale(0.7);
}

.series-book.is-missing .series-cover .series-number {
  opacity: 1;
  filter: none;
}

.series-book.is-upcoming .series-cover::after {
  content: "";
  position: absolute;
  top: -3px;
  right: 0.5rem;
  width: 0.7rem;
  height: 1.6rem;
  background: var(--brass);
  clip-path: polygon(0 0, 100% 0, 100% 100%, 50% 78%, 0 100%);
}

/* The filters narrow every card to one kind of book */
.series-cards[data-filter="missing"] .series-book:not(.is-missing),
.series-cards[data-filter="unread"] .series-book:not(.is-unread),
.series-cards[data-filter="upcoming"] .series-book:not(.is-upcoming) {
  display: none;
}

.series-note {
  margin-top: 1.5rem;
}

@media (prefers-reduced-motion: reduce) {
  .series-cover {
    transition: none;
  }
}

/*
 * New releases on the home page (DR-040): two shelves side by side, your favourite
 * authors' new books and your libraries' authors', then the new books in your series
 * with the series tracker in the corner. Books still to come carry a brass ribbon.
 */
.new-releases {
  margin: 2.25rem 0;
}

.new-releases h2 {
  margin-bottom: 0.75rem;
}

.release-columns {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.25rem;
}

.release-column,
.new-in-series {
  min-width: 0;
  padding: 0.9rem 1rem 0.4rem;
  border: 1px solid var(--rule);
  border-top: 3px solid var(--brass);
  border-radius: var(--radius);
  background: var(--page);
  box-shadow: var(--shadow);
}

.release-column h3 {
  margin: 0 0 0.6rem;
  color: var(--ink-soft);
  font-family: var(--sans);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.release-head {
  display: flex;
  gap: 1rem;
  align-items: baseline;
  justify-content: space-between;
}

.release-head h2 {
  margin: 0 0 0.6rem;
}

.release-corner {
  color: var(--ink-soft);
  font-family: var(--sans);
  font-size: 0.85rem;
  white-space: nowrap;
}

.release-shelf {
  display: grid;
  grid-auto-columns: 6.5rem;
  grid-auto-flow: column;
  gap: 0.9rem;
  margin: 0;
  padding: 0.25rem 0.1rem 0.9rem;
  overflow-x: auto;
  list-style: none;
  scroll-snap-type: x proximity;
}

.release-shelf li {
  scroll-snap-align: start;
  animation: rise 0.6s calc(var(--i) * 60ms) cubic-bezier(0.2, 0.8, 0.3, 1) both;
}

.release-book {
  display: grid;
  gap: 0.3rem;
  color: inherit;
  text-decoration: none;
}

.release-cover {
  position: relative;
  display: block;
  aspect-ratio: 2 / 3;
  border-radius: 2px 4px 4px 2px;
  box-shadow: var(--shadow);
  transition: transform 0.2s ease;
}

.release-cover img {
  width: 100%;
  height: 100%;
  border-radius: inherit;
  object-fit: cover;
}

.release-cover .cloth-title {
  font-size: 0.7rem;
  line-height: 1.15;
}

a.release-book:hover .release-cover,
a.release-book:focus-visible .release-cover {
  transform: translateY(-3px);
}

.release-year {
  position: absolute;
  bottom: 0.35rem;
  left: -0.3rem;
  padding: 0.05rem 0.4rem;
  border-radius: 2px;
  background: var(--ink);
  color: var(--page);
  font-family: var(--sans);
  font-size: 0.72rem;
  font-weight: 600;
  box-shadow: var(--shadow);
}

.release-book.is-upcoming .release-year {
  background: var(--brass);
  color: #1d1408;
}

.release-book.is-upcoming .release-cover::after {
  content: "";
  position: absolute;
  top: -3px;
  right: 0.5rem;
  width: 0.7rem;
  height: 1.6rem;
  background: var(--brass);
  clip-path: polygon(0 0, 100% 0, 100% 100%, 50% 78%, 0 100%);
}

.release-title {
  display: -webkit-box;
  overflow: hidden;
  /* Two whole lines: in a grid item Chrome measured the clamped box short and cut the
     second line through the middle */
  max-height: calc(2 * 1.25em);
  font-family: var(--serif);
  font-size: 0.88rem;
  line-height: 1.25;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  align-self: start;
}

.release-author {
  overflow: hidden;
  color: var(--ink-soft);
  font-size: 0.78rem;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.release-empty {
  margin: 0.25rem 0 0.9rem;
  color: var(--ink-soft);
  font-family: var(--serif);
  font-style: italic;
}

@media (max-width: 760px) {
  .release-columns {
    grid-template-columns: minmax(0, 1fr);
  }
}

@media (prefers-reduced-motion: reduce) {
  .release-shelf li {
    animation: none;
  }

  .release-cover {
    transition: none;
  }
}

/*
 * Do I own it? (DR-041): built for a phone in a bookshop. A big box and Scan button,
 * then one clear answer: green for yes, brass for another edition, plain for no.
 */
.own {
  max-width: 36rem;
}

.own-form {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin: 1.25rem 0;
}

.own-form input[type="search"] {
  flex: 1 1 14rem;
  min-height: 2.9rem;
  font-size: 1.1rem;
}

.own-form button {
  min-height: 2.9rem;
}

.own-scan {
  display: inline-flex;
  gap: 0.4rem;
  align-items: center;
}

.own-scan svg {
  width: 1.3rem;
  height: 1.3rem;
}

.own-answer {
  --own: var(--ink-soft);
  --own-soft: var(--paper);
  padding: 1.1rem 1.2rem;
  border: 1px solid var(--rule);
  border-left: 6px solid var(--own);
  border-radius: var(--radius);
  background: var(--page);
  box-shadow: var(--shadow);
  animation: rise 0.4s cubic-bezier(0.2, 0.8, 0.3, 1) both;
}

.own-answer.is-owned { --own: var(--ok); --own-soft: var(--ok-soft); }
.own-answer.is-other_edition { --own: var(--brass); --own-soft: var(--brass-soft); }
.own-answer.is-not_owned { --own: var(--danger); --own-soft: var(--danger-soft); }

.own-verdict {
  display: flex;
  gap: 0.6rem;
  align-items: center;
  margin: 0 0 0.4rem;
  font-family: var(--serif);
  font-size: 1.6rem;
  line-height: 1.2;
}

.own-mark {
  display: grid;
  flex: none;
  place-items: center;
  width: 2.4rem;
  height: 2.4rem;
  border-radius: 50%;
  background: var(--own-soft);
  color: var(--own);
  font-family: var(--sans);
  font-size: 1.4rem;
  font-weight: 700;
}

.own-title {
  margin: 0 0 0.6rem;
}

.own-flags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 0 0 0.6rem;
}

.own-flag {
  padding: 0.15rem 0.6rem;
  border-radius: 999px;
  background: var(--brass-soft);
  font-size: 0.85rem;
}

.own-flag.is-read {
  background: var(--ok-soft);
  color: var(--ok);
}

.own-copies {
  display: grid;
  gap: 0.4rem;
  margin: 0.6rem 0 0;
  padding: 0;
  list-style: none;
}

.own-copies a {
  display: grid;
  padding: 0.55rem 0.7rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  color: inherit;
  text-decoration: none;
}

.own-copies a:hover,
.own-copies a:focus-visible {
  border-color: var(--own);
}

.own-add {
  margin-top: 0.6rem;
}

@media (prefers-reduced-motion: reduce) {
  .own-answer {
    animation: none;
  }
}

/* Password reset and account recovery (DR-046) */
.narrow-panel {
  max-width: 34rem;
}

.login-help {
  margin-top: 1rem;
}

.people-list {
  display: grid;
  gap: 0;
  margin: 1rem 0;
  padding: 0;
  list-style: none;
}

.people-list li {
  display: flex;
  gap: 1rem;
  align-items: center;
  padding: 0.75rem 0;
  border-bottom: 1px solid var(--rule);
}

.people-list form {
  margin: 0;
}

.reset-made {
  border-left: 4px solid var(--brass);
}

.reset-link {
  width: 100%;
  font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: 0.85rem;
}

/* Site search (DR-020): a work shown by its English edition notes its first title, and a
   search read past a slip of the keyboard says so */
.search-hit-original {
  display: block;
  color: var(--ink-soft);
  font-size: 0.82rem;
}

.search-meant {
  padding: 0.5rem 0.8rem;
  border-left: 3px solid var(--brass);
  background: var(--brass-soft);
}

/* The upload page: the list shown, then the form for another (DR-047 #9) */
.import-shown {
  margin-bottom: 2.5rem;
}

.import-shown > h2 {
  margin-bottom: 0.2rem;
}

.import-another {
  padding-top: 1.5rem;
  border-top: 1px solid var(--rule);
}

/* Whose reading a page shows: you or one of the library's readers (DR-047 #10) */
.reader-switch {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  align-items: center;
  margin: 0.4rem 0 0.8rem;
}

.reader-switch-label {
  margin-right: 0.3rem;
  color: var(--ink-soft);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.reader-switch a {
  padding: 0.15rem 0.75rem;
  border: 1px solid var(--rule);
  border-radius: 999px;
  color: var(--ink);
  text-decoration: none;
}

.reader-switch a:hover {
  border-color: var(--accent);
}

.reader-switch a[aria-current] {
  border-color: var(--accent);
  background: var(--accent);
  color: var(--page);
}

.readers-panel {
  margin: 1.5rem 0 2rem;
}

.readers-add input {
  flex: 1;
  min-width: 0;
}

.readers-list {
  padding: 0;
  list-style: none;
}

.readers-list li {
  display: flex;
  gap: 0.8rem;
  align-items: center;
  padding: 0.6rem 0;
  border-bottom: 1px solid var(--rule);
}

.readers-list .grow {
  flex: 1;
}

.readers-list form {
  margin: 0;
}

.avatar-initial {
  display: grid;
  flex: none;
  place-items: center;
  width: 2.2rem;
  height: 2.2rem;
  border-radius: 50%;
  background: var(--accent-soft);
  color: var(--accent-strong);
  font-family: var(--caps);
}

/* Sign in: the two fields one above the other, their boxes the same width */
.sign-in-form {
  max-width: 22rem;
}

/* The library opened from a piece of a chart: what it shows, and the way back */
.chart-piece-banner {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.2rem;
  align-items: baseline;
  margin: 0 0 1rem;
  padding: 0.6rem 0.9rem;
  border-left: 4px solid var(--brass);
  border-radius: var(--radius);
  background: var(--brass-soft);
}

.chart-piece-banner > span {
  flex: 1;
}

/* Mark as read (owner, 2026-11-04): a tick in a circle, faint until read. Clicked, the
   ring draws round, the circle fills, the tick draws in, the button pops and six sparks
   fly out; read, it stays filled */
.read-mark-form {
  flex: none;
  margin: 0;
}

button.read-mark {
  position: relative;
  display: grid;
  place-items: center;
  width: 3rem;
  height: 3rem;
  padding: 0;
  border: 1.5px solid var(--accent);
  border-radius: 50%;
  background: var(--page);
  color: var(--accent);
  box-shadow: var(--shadow);
  overflow: visible;
  transition: background 0.25s, color 0.25s;
}

button.read-mark:hover:not(:disabled) {
  background: var(--accent-soft);
}

button.read-mark:disabled {
  opacity: 1;
  cursor: default;
}

.read-mark svg {
  width: 1.7rem;
  height: 1.7rem;
  overflow: visible;
}

.read-mark-ring {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-dasharray: 82;
  stroke-dashoffset: 0;
  transform: rotate(-90deg);
  transform-origin: center;
  opacity: 0.35;
}

.read-mark-tick {
  fill: none;
  stroke: currentColor;
  stroke-width: 2.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 20;
  stroke-dashoffset: 0;
  opacity: 0.55;
}

/* Read: filled, the tick in the page's colour */
button.read-mark.is-read {
  background: var(--accent);
  color: var(--page);
}

.read-mark.is-read .read-mark-ring,
.read-mark.is-read .read-mark-tick {
  opacity: 1;
}

/* The moment it is marked */
button.read-mark.is-marking {
  animation: read-mark-pop 0.42s cubic-bezier(0.3, 1.6, 0.5, 1) 0.42s both;
}

.read-mark.is-marking .read-mark-ring {
  opacity: 1;
  animation: read-mark-ring 0.42s ease-out both;
}

.read-mark.is-marking .read-mark-tick {
  opacity: 1;
  animation: read-mark-tick 0.3s ease-out 0.38s both;
}

@keyframes read-mark-ring {
  from {
    stroke-dashoffset: 82;
  }
  to {
    stroke-dashoffset: 0;
  }
}

@keyframes read-mark-tick {
  from {
    stroke-dashoffset: 20;
  }
  to {
    stroke-dashoffset: 0;
  }
}

@keyframes read-mark-pop {
  0% {
    transform: scale(1);
  }
  45% {
    transform: scale(1.18);
  }
  75% {
    transform: scale(0.95);
  }
  100% {
    transform: scale(1);
  }
}

.read-mark-sparks {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.read-mark-sparks i {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 5px;
  height: 5px;
  margin: -2.5px;
  border-radius: 50%;
  background: var(--brass);
  opacity: 0;
}

.read-mark.is-marking .read-mark-sparks i {
  animation: read-mark-spark 0.55s ease-out 0.5s both;
}

.read-mark-sparks i:nth-child(1) { --a: 0deg; }
.read-mark-sparks i:nth-child(2) { --a: 60deg; }
.read-mark-sparks i:nth-child(3) { --a: 120deg; }
.read-mark-sparks i:nth-child(4) { --a: 180deg; }
.read-mark-sparks i:nth-child(5) { --a: 240deg; }
.read-mark-sparks i:nth-child(6) { --a: 300deg; }

@keyframes read-mark-spark {
  0% {
    opacity: 0;
    transform: rotate(var(--a)) translateY(-0.9rem) scale(1);
  }
  15% {
    opacity: 1;
  }
  100% {
    opacity: 0;
    transform: rotate(var(--a)) translateY(-1.9rem) scale(0.4);
  }
}

/* On a library tile: smaller, in the cover's top right corner */
.book-tiles > li {
  position: relative;
}

.read-mark-form.is-small {
  position: absolute;
  top: 0.35rem;
  right: 0.35rem;
  z-index: 2;
}

.read-mark-form.is-small button.read-mark {
  width: 2rem;
  height: 2rem;
  border-width: 1.2px;
}

.read-mark-form.is-small .read-mark svg {
  width: 1.15rem;
  height: 1.15rem;
}

/* An unread book's corner button stays quiet until the tile is pointed at */
.book-tiles > li .read-mark:not(.is-read) {
  opacity: 0.85;
}

@media (prefers-reduced-motion: reduce) {
  button.read-mark.is-marking,
  .read-mark.is-marking .read-mark-ring,
  .read-mark.is-marking .read-mark-tick,
  .read-mark.is-marking .read-mark-sparks i {
    animation: none;
  }
}

/* The book page's round buttons, side by side in the title row */
.book-head-buttons {
  display: flex;
  flex: none;
  gap: 0.6rem;
  align-items: flex-start;
}

/* A long list of tick boxes in two columns, as Manual entry's special editions */
.check-columns div[id] {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.2rem 1.5rem;
}

@media (max-width: 34rem) {
  .check-columns div[id] {
    grid-template-columns: 1fr;
  }
}

/* A wishlist book's links: shop searches and the person's own, then Add a link */
.wish-links {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 0.5rem;
  align-items: center;
  margin-top: 0.4rem;
}

.wish-link,
.wish-link > a {
  font-size: 0.88rem;
}

a.wish-link,
.wish-link.is-own {
  display: inline-flex;
  gap: 0.25rem;
  align-items: center;
  padding: 0.1rem 0.6rem;
  border: 1px solid var(--rule);
  border-radius: 999px;
  text-decoration: none;
}

.wish-link.is-own form {
  margin: 0;
}

button.wish-link-remove {
  padding: 0 0.2rem;
  border: none;
  background: none;
  box-shadow: none;
  color: var(--ink-soft);
  font-size: 1rem;
  line-height: 1;
}

.wish-link-add summary {
  font-size: 0.88rem;
  cursor: pointer;
}

.wish-link-add form {
  margin-top: 0.4rem;
}
