/* K. Sampley — author site
   ------------------------------------------------------------------
   Three greens stack to make depth without shadows. Ivory is a guest,
   not a ground. Gold is foil: rules, ornament, and display type only.
   ------------------------------------------------------------------ */

@font-face {
  font-family: 'Cormorant Garamond';
  src: url('/fonts/cormorant-garamond.woff2') format('woff2');
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Cormorant Garamond';
  src: url('/fonts/cormorant-garamond-italic.woff2') format('woff2');
  font-weight: 300 700;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: 'EB Garamond';
  src: url('/fonts/eb-garamond.woff2') format('woff2');
  font-weight: 400 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'EB Garamond';
  src: url('/fonts/eb-garamond-italic.woff2') format('woff2');
  font-weight: 400 600;
  font-style: italic;
  font-display: swap;
}

:root {
  --ink: #0e1a14;
  --forest-mid: #14261d;
  --forest: #1e3a2e;
  --ivory: #f7f3eb;
  --gold: #c9a227;
  --gold-soft: #d9b64a;

  /* Gold on ivory is ~2.1:1 and fails AA, so ivory-ground body copy uses
     forest and ivory-ground accents use this darker gold instead. */
  --gold-on-ivory: #6d5410;

  --ivory-dim: rgba(247, 243, 235, 0.72);
  --ivory-faint: rgba(247, 243, 235, 0.45);
  --hair: rgba(201, 162, 39, 0.28);
  --hair-soft: rgba(247, 243, 235, 0.14);

  --display: 'Cormorant Garamond', 'Cormorant', Georgia, 'Times New Roman', serif;
  --body: 'EB Garamond', Garamond, Georgia, 'Times New Roman', serif;

  --shell: 74rem;
  --gutter: clamp(1.25rem, 5vw, 4.5rem);
  --band-y: clamp(4.5rem, 11vw, 9rem);
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  color-scheme: dark;
  /* Anchors land clear of the sticky masthead. */
  scroll-padding-top: 5.5rem;
}

body {
  margin: 0;
  background: var(--ink);
  color: var(--ivory);
  font-family: var(--body);
  font-size: clamp(1.02rem, 0.42vw + 0.94rem, 1.16rem);
  line-height: 1.78;
  font-feature-settings: 'kern' 1, 'liga' 1, 'onum' 1, 'calt' 1;
  hanging-punctuation: first last;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* Gold thread down the edge of the page. */
* {
  scrollbar-width: thin;
  scrollbar-color: rgba(201, 162, 39, 0.45) transparent;
}

::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}

::-webkit-scrollbar-track {
  background: var(--ink);
}

::-webkit-scrollbar-thumb {
  background: rgba(201, 162, 39, 0.32);
  border: 3px solid var(--ink);
  border-radius: 99px;
}

::-webkit-scrollbar-thumb:hover {
  background: rgba(201, 162, 39, 0.6);
}

/* Grain over everything. Flat hex fills are the single strongest tell that a
   page was machine-made; a few percent of noise removes it. */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 9999;
  pointer-events: none;
  background-image: url('/img/grain.png');
  background-size: 128px 128px;
  opacity: 0.4;
  mix-blend-mode: overlay;
}

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

a {
  color: inherit;
  text-decoration: none;
}

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

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

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--gold);
  color: var(--ink);
  padding: 0.75rem 1.25rem;
  z-index: 10000;
  font-family: var(--body);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-size: 0.75rem;
}
.skip:focus {
  left: 1rem;
  top: 1rem;
}

/* ---------------------------------------------------------------- bands */

.band {
  position: relative;
  padding: var(--band-y) 0;
  overflow: hidden;
}

/* Only two grounds run in page flow. --forest-mid is a surface colour for
   cards and plates, not a band — three near-identical greens stacked in
   sequence is what made the boundaries muddy in the first place. */
.band--ink {
  background: var(--ink);
}
.band--forest {
  background: var(--forest);
}

.band--ivory {
  background: var(--ivory);
  color: var(--forest);
}

/* Low-key lighting, top-lit only.

   This used to darken every edge to rgba(0,0,0,0.4). With three greens this
   close in value, that meant each band's bruised bottom edge met the next
   band's lit top edge, and every boundary read as a muddy seam. The light
   now falls off to transparent instead of to black, so a band is a clean
   field of colour and the step between two of them is the only edge. */
.band--ink::before,
.band--forest::before,
.newsletter::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(
    100% 65% at 50% 0%,
    rgba(255, 255, 255, 0.05) 0%,
    rgba(255, 255, 255, 0) 70%
  );
}

.band--ivory::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(
    110% 70% at 50% 0%,
    rgba(255, 255, 255, 0.55) 0%,
    rgba(255, 255, 255, 0) 75%
  );
}

/* Where two dark bands meet, a gold hairline makes the change deliberate
   instead of accidental. The ivory boundary is already unmistakable, so it
   gets nothing. */
.band + .band,
.band + .entry,
.entry + .entry,
.entry + .band {
  border-top: 1px solid var(--hair-soft);
}

.band--ivory + .band,
.band + .band--ivory,
.entry + .band--ivory,
.band--ivory + .entry {
  border-top: 0;
}

.band > *,
.entry > * {
  position: relative;
  z-index: 1;
}

.shell {
  width: min(100% - var(--gutter) * 2, var(--shell));
  margin-inline: auto;
}

.shell--narrow {
  width: min(100% - var(--gutter) * 2, 46rem);
  margin-inline: auto;
}

/* ----------------------------------------------------------- typography */

h1,
h2,
h3,
h4 {
  font-family: var(--display);
  font-weight: 500;
  margin: 0;
  line-height: 1.04;
  letter-spacing: -0.008em;
  /* Headings break into even lines instead of leaving one orphan word. */
  text-wrap: balance;
}

.display {
  font-size: clamp(3rem, 8.5vw, 6.5rem);
  line-height: 0.94;
  letter-spacing: -0.022em;
}

.title {
  font-size: clamp(2.1rem, 4.4vw, 3.4rem);
  line-height: 1.02;
}

.subtitle {
  font-size: clamp(1.55rem, 2.6vw, 2.15rem);
  line-height: 1.12;
}

.eyebrow {
  font-family: var(--body);
  font-size: 0.74rem;
  font-weight: 500;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--gold);
  margin: 0 0 1.4rem;
  display: block;
}

.band--ivory .eyebrow {
  color: var(--gold-on-ivory);
}

.lede {
  font-family: var(--display);
  font-size: clamp(1.35rem, 2vw, 1.7rem);
  line-height: 1.5;
  font-style: italic;
  color: var(--ivory-dim);
}

p {
  margin: 0 0 1.35em;
  max-width: 62ch;
  /* No single-word last lines. */
  text-wrap: pretty;
}

p:last-child {
  margin-bottom: 0;
}

blockquote {
  position: relative;
  margin: 2.25rem 0;
  padding-left: 2.4rem;
  font-family: var(--display);
  font-style: italic;
  font-size: 1.3em;
  line-height: 1.5;
}

blockquote::before {
  content: '\201C';
  position: absolute;
  left: 0;
  top: -0.28em;
  font-size: 3em;
  line-height: 1;
  color: var(--gold);
  opacity: 0.55;
}

.band--ivory blockquote::before {
  color: var(--gold-on-ivory);
}

/* ------------------------------------------------------------ ornaments */

.rule {
  border: 0;
  height: 1px;
  background: var(--hair);
  margin: 2.5rem 0;
}

.rule--short {
  width: 3.5rem;
  background: var(--gold);
  margin: 1.75rem 0;
}

/* The four-point star beneath the wordmark in her logo, reused as the
   section divider. Her own mark, not a stock flourish. */
.ornament {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1.1rem;
  margin: 0 auto;
  width: min(100%, 22rem);
  color: var(--gold);
}

.ornament::before,
.ornament::after {
  content: '';
  height: 1px;
  flex: 1;
  background: linear-gradient(
    to var(--dir, right),
    rgba(201, 162, 39, 0) 0%,
    rgba(201, 162, 39, 0.55) 100%
  );
}

.ornament::before {
  --dir: right;
  transform-origin: right center;
}
.ornament::after {
  --dir: left;
  transform-origin: left center;
}

/* The rules draw outward from the star as the divider comes into view.
   Gated on JS having run, so the ornament is never left as a lone star if
   the script fails to load. */
@media (prefers-reduced-motion: no-preference) {
  html:not(.no-js) .ornament::before,
  html:not(.no-js) .ornament::after {
    transform: scaleX(0);
    transition: transform 1.1s cubic-bezier(0.22, 0.61, 0.36, 1) 0.15s;
  }

  html:not(.no-js) .ornament.is-in::before,
  html:not(.no-js) .ornament.is-in::after {
    transform: scaleX(1);
  }
}

.ornament svg {
  width: 13px;
  height: 13px;
  flex: none;
  fill: currentColor;
}

/* Star first, rule running right — for page headings, where a centred
   ornament would fight the left-aligned type above it. */
.ornament--left {
  margin: clamp(2.5rem, 5vw, 3.5rem) 0 0;
  width: min(100%, 18rem);
  justify-content: flex-start;
}

.ornament--left::before {
  display: none;
}

/* ------------------------------------------------------- page headings */

.page-head {
  padding-bottom: clamp(3.5rem, 7vw, 5.5rem);
}

.page-head__lede {
  margin-top: 1.75rem;
  max-width: 36ch;
}

/* ------------------------------------------------------------------ nav */

.masthead {
  position: sticky;
  top: 0;
  z-index: 60;
  background: rgba(14, 26, 20, 0.72);
  backdrop-filter: saturate(140%) blur(10px);
  border-bottom: 1px solid transparent;
  transition: background 0.5s ease, border-color 0.5s ease;
}

/* Condenses once the page has moved, so the masthead is generous at rest
   and out of the way while reading. */
.masthead.is-stuck {
  background: rgba(14, 26, 20, 0.93);
  border-bottom-color: var(--hair);
}

.masthead__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  padding: 1.35rem 0;
  transition: padding 0.5s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.masthead.is-stuck .masthead__inner {
  padding: 0.8rem 0;
}

.wordmark {
  transition: color 0.35s ease;
}

.wordmark:hover {
  color: var(--gold);
}

.wordmark {
  font-family: var(--body);
  font-size: 0.86rem;
  font-weight: 500;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--ivory);
  white-space: nowrap;
}

.nav {
  display: flex;
  align-items: center;
  gap: clamp(1.4rem, 3vw, 2.6rem);
}

.nav a {
  font-family: var(--body);
  font-size: 0.76rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ivory-dim);
  padding: 0.35rem 0;
  position: relative;
  transition: color 0.35s ease;
}

.nav a::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: 0;
  height: 1px;
  width: 0;
  background: var(--gold);
  transition: width 0.4s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.nav a:hover,
.nav a[aria-current='page'] {
  color: var(--ivory);
}

.nav a:hover::after,
.nav a[aria-current='page']::after {
  width: 100%;
}

.nav__toggle {
  display: none;
}

/* ----------------------------------------------------------------- hero */

.hero {
  padding: clamp(3.5rem, 9vw, 7rem) 0 clamp(4rem, 10vw, 8rem);
  position: relative;
}

.hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: center;
}

.hero h1 {
  margin: 0;
}

.hero__tagline {
  font-family: var(--display);
  font-style: italic;
  font-size: clamp(1.25rem, 1.9vw, 1.65rem);
  line-height: 1.45;
  color: var(--ivory-dim);
  max-width: 26ch;
  margin: 1.6rem 0 0;
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 1.75rem;
  margin-top: 2.6rem;
}

.hero__mark {
  justify-self: center;
  width: min(100%, 27rem);
  opacity: 0.96;
}

/* --------------------------------------------------- entrance animations */

@keyframes ks-rise {
  from {
    opacity: 0;
    transform: translateY(18px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes ks-settle {
  from {
    opacity: 0;
    transform: scale(0.965);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* Only when JS has confirmed itself — a stalled stylesheet must never leave
   the hero invisible. */
@media (prefers-reduced-motion: no-preference) {
  html:not(.no-js) .hero__intro > * {
    animation: ks-rise 0.9s cubic-bezier(0.22, 0.61, 0.36, 1) both;
  }
  html:not(.no-js) .hero__intro > *:nth-child(1) {
    animation-delay: 0.06s;
  }
  html:not(.no-js) .hero__intro > *:nth-child(2) {
    animation-delay: 0.16s;
  }
  html:not(.no-js) .hero__intro > *:nth-child(3) {
    animation-delay: 0.28s;
  }
  html:not(.no-js) .hero__intro > *:nth-child(4) {
    animation-delay: 0.4s;
  }

  html:not(.no-js) .hero__mark {
    animation: ks-settle 1.5s cubic-bezier(0.22, 0.61, 0.36, 1) 0.1s both;
  }
}

/* --------------------------------------------------------------- buttons */

/* The fill wipes in from the left rather than switching on, so the button
   reads as ink spreading across the page. */
.btn {
  --btn-fill: var(--gold);
  --btn-on: var(--ink);
  --btn-edge: var(--gold);

  position: relative;
  z-index: 0;
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  overflow: hidden;
  font-family: var(--body);
  font-size: 0.78rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  padding: 0.9rem 1.7rem;
  border: 1px solid var(--btn-edge);
  color: var(--btn-edge);
  background: transparent;
  border-radius: 1px;
  cursor: pointer;
  transition: color 0.35s ease, border-color 0.35s ease;
}

.btn::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--btn-fill);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.5s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.btn:hover {
  color: var(--btn-on);
}

.btn:hover::before {
  transform: scaleX(1);
}

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

.btn--quiet {
  --btn-edge: var(--hair-soft);
  --btn-fill: rgba(201, 162, 39, 0.12);
  --btn-on: var(--gold);
  color: var(--ivory-dim);
}

.btn--quiet:hover {
  border-color: var(--gold);
}

.band--ivory .btn {
  --btn-edge: var(--gold-on-ivory);
  --btn-fill: var(--forest);
  --btn-on: var(--ivory);
}

.band--ivory .btn:hover {
  border-color: var(--forest);
}

/* Resting hairline, with a solid gold rule drawn across it on hover. */
.link {
  display: inline-block;
  font-family: var(--body);
  font-size: 0.78rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--gold);
  padding-bottom: 0.35rem;
  border-bottom: 1px solid var(--hair);
  background-image: linear-gradient(var(--gold), var(--gold));
  background-repeat: no-repeat;
  background-size: 0% 1px;
  background-position: 0 100%;
  transition: background-size 0.5s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.link:hover {
  background-size: 100% 1px;
}

.band--ivory .link {
  color: var(--gold-on-ivory);
  border-bottom-color: rgba(109, 84, 16, 0.35);
  background-image: linear-gradient(var(--gold-on-ivory), var(--gold-on-ivory));
}

/* ---------------------------------------------------------------- about */

.about__grid {
  display: grid;
  grid-template-columns: minmax(0, 0.82fr) minmax(0, 1.18fr);
  gap: clamp(2rem, 6vw, 5rem);
  align-items: start;
}

.about__quote {
  font-family: var(--display);
  font-style: italic;
  font-size: clamp(1.9rem, 3.4vw, 2.9rem);
  line-height: 1.14;
  color: var(--forest);
  margin: 0;
  position: sticky;
  top: 7rem;
}

.about__quote::first-letter {
  color: var(--gold-on-ivory);
}

.about__body p {
  color: rgba(30, 58, 46, 0.88);
}

.about__body p:first-of-type::first-letter {
  font-family: var(--display);
  float: left;
  font-size: 3.9em;
  line-height: 0.78;
  padding: 0.06em 0.1em 0 0;
  color: var(--gold-on-ivory);
}

/* ----------------------------------------------------------------- book */

.plate {
  position: relative;
  aspect-ratio: 2 / 3;
  background: var(--forest);
  border: 1px solid var(--hair);
  border-radius: 1px;
  overflow: hidden;
  display: block;
}

.band--forest .plate {
  background: var(--forest-mid);
}

.plate img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* No cover art yet: a set title page rather than a broken image. */
.plate__type {
  position: absolute;
  inset: 0.6rem;
  border: 1px solid var(--hair);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 3.4rem 1.1rem;
  gap: 0.9rem;
}

.plate__series {
  font-size: 0.6rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--gold);
  opacity: 0.85;
}

.plate__title {
  font-family: var(--display);
  font-size: clamp(1.25rem, 2.5vw, 1.75rem);
  line-height: 1.08;
  color: var(--ivory);
}

.plate__star {
  color: var(--gold);
  display: block;
}

.plate__star svg {
  width: 11px;
  height: 11px;
  fill: currentColor;
}

/* Pinned rather than pushed with margin-top:auto — that shoved the title to
   the top of the plate and left a void through the middle. */
.plate__author {
  position: absolute;
  left: 1.1rem;
  right: 1.1rem;
  bottom: 1.5rem;
  font-size: 0.6rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--ivory-faint);
}

/* Spine shading down the binding edge, so a plate reads as an object with
   thickness rather than a flat rectangle. */
.plate::after {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 7%;
  pointer-events: none;
  background: linear-gradient(
    to right,
    rgba(0, 0, 0, 0.3) 0%,
    rgba(0, 0, 0, 0.1) 45%,
    rgba(247, 243, 235, 0.05) 62%,
    rgba(0, 0, 0, 0) 100%
  );
}

a.plate {
  transition: border-color 0.45s ease, transform 0.55s cubic-bezier(0.22, 0.61, 0.36, 1);
}

a.plate:hover {
  border-color: var(--gold);
  transform: translateY(-5px);
}

a.plate:hover .plate__type {
  border-color: rgba(201, 162, 39, 0.5);
}

.plate__type {
  transition: border-color 0.45s ease;
}

/* Light catching the foil as the cover tilts under the cursor. */
@media (prefers-reduced-motion: no-preference) {
  a.plate::before {
    content: '';
    position: absolute;
    inset: -10% -30%;
    z-index: 2;
    pointer-events: none;
    background: linear-gradient(
      115deg,
      rgba(247, 243, 235, 0) 38%,
      rgba(247, 243, 235, 0.08) 48%,
      rgba(201, 162, 39, 0.1) 52%,
      rgba(247, 243, 235, 0) 62%
    );
    transform: translateX(-115%);
    transition: transform 0.95s cubic-bezier(0.22, 0.61, 0.36, 1);
  }

  a.plate:hover::before {
    transform: translateX(115%);
  }
}

.pill {
  display: inline-block;
  font-size: 0.66rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  border: 1px solid var(--gold);
  color: var(--gold);
  padding: 0.35rem 0.85rem;
  border-radius: 1px;
  white-space: nowrap;
}

.pill--wip {
  border-color: var(--hair-soft);
  color: var(--ivory-faint);
}

/* books index */

.entry {
  padding: var(--band-y) 0;
  position: relative;
}

.entry__grid {
  display: grid;
  grid-template-columns: minmax(0, 0.42fr) minmax(0, 1fr);
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: start;
}

.entry__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.9rem 1.25rem;
  margin-bottom: 0.5rem;
}

/* Set in italic rather than letterspaced caps: "Book two of the Of Crowns and
   Corruption series" is unreadable shouted, and reads well set like a
   half-title line. */
.entry__series {
  font-family: var(--display);
  font-style: italic;
  font-size: 1.08rem;
  letter-spacing: 0;
  color: var(--ivory-faint);
  margin: 0.85rem 0 1.9rem;
  display: block;
}

.entry__blurb {
  color: var(--ivory-dim);
}

.entry__hidden {
  font-family: var(--display);
  font-style: italic;
  font-size: 1.3rem;
  line-height: 1.5;
  color: var(--ivory-faint);
  max-width: 46ch;
}

/* content warnings — the one ivory moment on a dark page */

.warnings {
  margin-top: 2.25rem;
  border: 1px solid var(--hair-soft);
  border-radius: 1px;
  background: rgba(247, 243, 235, 0.03);
}

.warnings > summary {
  cursor: pointer;
  list-style: none;
  padding: 0.95rem 1.25rem;
  font-size: 0.74rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ivory-dim);
  display: flex;
  align-items: center;
  gap: 0.75rem;
  transition: color 0.3s ease;
}

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

.warnings > summary:hover {
  color: var(--gold);
}

.warnings > summary::before {
  content: '+';
  font-family: var(--display);
  font-size: 1.2rem;
  line-height: 1;
  color: var(--gold);
}

.warnings[open] > summary::before {
  content: '–';
}

.warnings__panel {
  background: var(--ivory);
  color: var(--forest);
  padding: 1.4rem 1.5rem 1.6rem;
}

.warnings__panel p {
  font-size: 0.92rem;
  color: rgba(30, 58, 46, 0.75);
  margin-bottom: 0.9rem;
}

.warnings__list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.55rem;
}

.warnings__list li {
  font-size: 0.82rem;
  border: 1px solid rgba(30, 58, 46, 0.22);
  border-radius: 1px;
  padding: 0.3rem 0.7rem;
  color: rgba(30, 58, 46, 0.9);
}

/* book detail */

.book__grid {
  display: grid;
  grid-template-columns: minmax(0, 0.5fr) minmax(0, 1fr);
  gap: clamp(2rem, 6vw, 5rem);
  align-items: start;
}

.book__aside {
  position: sticky;
  top: 7rem;
}

.retailers {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 1.5rem;
}

/* Tracks are capped, not fractional. auto-fit with 1fr stretched a lone
   sibling book across the full 74rem shell, which rendered one cover plate
   at roughly four times its intended size. */
.siblings {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(11rem, 14rem));
  gap: clamp(1.5rem, 3vw, 2.75rem);
  margin-top: 2.5rem;
}

/* --------------------------------------------------------------- books grid */

/* Fixed at three so the plates keep their proportions even if the shelf
   holds fewer books — auto-fit would stretch a single title full width. */
.books-teaser {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1.5rem, 3vw, 2.75rem);
  margin-top: 3rem;
}

.teaser__meta {
  margin-top: 1.1rem;
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  align-items: flex-start;
}

.teaser__title {
  font-family: var(--display);
  font-size: 1.35rem;
  line-height: 1.15;
  color: var(--ivory);
}

/* -------------------------------------------------------------- updates */

.posts {
  border-top: 1px solid var(--hair-soft);
  margin-top: 3rem;
}

.post {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 0.28fr) minmax(0, 1fr);
  gap: clamp(1rem, 4vw, 3rem);
  padding: clamp(2rem, 4vw, 3rem) 0;
  border-bottom: 1px solid var(--hair-soft);
  transition: background 0.45s ease;
}

.post::before {
  content: '';
  position: absolute;
  /* Half the page gutter, so the accent always has room to sit outside the
     text. A fixed -1.5rem put it at -4px on a phone, where it never showed. */
  left: calc(var(--gutter) / -2);
  top: 0;
  bottom: -1px;
  width: 1px;
  background: var(--gold);
  transform: scaleY(0);
  transform-origin: top center;
  transition: transform 0.5s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.post:hover {
  background: rgba(247, 243, 235, 0.022);
}

.post:hover::before {
  transform: scaleY(1);
}

.post__date {
  font-size: 0.74rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--gold);
  padding-top: 0.55rem;
}

.post__title {
  font-family: var(--display);
  font-size: clamp(1.6rem, 3vw, 2.2rem);
  line-height: 1.08;
  margin: 0 0 0.85rem;
}

.post__title a {
  background-image: linear-gradient(var(--gold), var(--gold));
  background-repeat: no-repeat;
  background-size: 0% 1px;
  background-position: 0 100%;
  transition: background-size 0.45s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.post__title a:hover {
  background-size: 100% 1px;
}

.post__excerpt {
  color: var(--ivory-dim);
  margin-bottom: 1.25rem;
}

.prose {
  font-size: 1.08em;
}

/* Opens a post the way the About section opens the home page. */
.prose--lead > p:first-of-type::first-letter {
  font-family: var(--display);
  float: left;
  font-size: 3.6em;
  line-height: 0.78;
  padding: 0.06em 0.11em 0 0;
  color: var(--gold);
}

.prose--lead > p:first-of-type {
  text-indent: 0;
}

.prose a {
  color: var(--gold);
  border-bottom: 1px solid var(--hair);
}

.prose a:hover {
  border-bottom-color: var(--gold);
}

.empty {
  font-family: var(--display);
  font-style: italic;
  font-size: 1.5rem;
  color: var(--ivory-faint);
  margin-top: 3rem;
}

/* --------------------------------------------------------- latest note */

/* Given a panel of its own rather than centred text adrift in a dark band,
   and laid out like an entry on /updates so the two read as the same thing. */
.latest {
  display: grid;
  grid-template-columns: minmax(0, 0.22fr) minmax(0, 1fr);
  gap: clamp(1rem, 3vw, 3rem);
  margin-top: 2.25rem;
  padding: clamp(1.75rem, 3.5vw, 3rem);
  border: 1px solid var(--hair);
  border-radius: 2px;
  background: rgba(247, 243, 235, 0.025);
}

.latest__date {
  font-size: 0.74rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--gold);
  padding-top: 0.6rem;
}

.latest__title {
  font-family: var(--display);
  font-size: clamp(1.75rem, 3vw, 2.4rem);
  line-height: 1.06;
  margin: 0 0 1rem;
}

.latest__title a {
  background-image: linear-gradient(var(--gold), var(--gold));
  background-repeat: no-repeat;
  background-size: 0% 1px;
  background-position: 0 100%;
  transition: background-size 0.45s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.latest__title a:hover {
  background-size: 100% 1px;
}

.latest__excerpt {
  color: var(--ivory-dim);
  margin-bottom: 1.6rem;
}

/* ----------------------------------------------------------- newsletter */

/* The newsletter sits at the bottom of every page, under a section whose
   colour depends on how many books or posts happen to exist. Rather than
   pick a fixed ground that sometimes lands on top of an identical one, it
   takes the opposite of whatever precedes it. */
.newsletter {
  background: var(--ink);
}

.band--ink + .newsletter {
  background: var(--forest);
}

.signup {
  display: flex;
  flex-wrap: wrap;
  gap: 0.85rem;
  margin-top: 2rem;
  max-width: 34rem;
}

.signup input[type='email'] {
  flex: 1 1 15rem;
  background: transparent;
  border: 1px solid var(--hair-soft);
  border-radius: 1px;
  color: var(--ivory);
  font-family: var(--body);
  font-size: 1rem;
  padding: 0.85rem 1.1rem;
  transition: border-color 0.35s ease;
}

.signup input[type='email']::placeholder {
  color: var(--ivory-faint);
}

.signup input[type='email']:focus {
  border-color: var(--gold);
  outline: none;
  box-shadow: 0 0 0 3px rgba(201, 162, 39, 0.14);
}

.signup input[type='email']:hover {
  border-color: rgba(247, 243, 235, 0.28);
}

.latest {
  transition: border-color 0.45s ease, background 0.45s ease;
}

.latest:hover {
  border-color: rgba(201, 162, 39, 0.45);
  background: rgba(247, 243, 235, 0.035);
}

.signup__pot {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.signup__note {
  font-size: 0.88rem;
  color: var(--ivory-faint);
  margin-top: 1rem;
}

.notice {
  margin-top: 1.25rem;
  padding: 0.9rem 1.15rem;
  border-left: 2px solid var(--gold);
  background: rgba(201, 162, 39, 0.08);
  font-size: 0.95rem;
  color: var(--ivory);
}

.notice--bad {
  border-left-color: #c96a4a;
  background: rgba(201, 106, 74, 0.1);
}

/* --------------------------------------------------------------- footer */

/* Shares the newsletter band's ground deliberately: the two read as one
   continuous dark base, divided by the ornament rather than by yet another
   near-identical green butted against it. */
.footer {
  background: var(--ink);
  padding: clamp(3rem, 6vw, 4.5rem) 0 2.5rem;
  position: relative;
}

.footer__ornament {
  margin-bottom: clamp(2.75rem, 5vw, 4rem);
}

.footer__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.7fr) minmax(0, 1fr);
  gap: 2.75rem 3rem;
  align-items: start;
}

.footer__mark {
  width: 5.5rem;
  opacity: 0.75;
  margin-bottom: 1.25rem;
}

.footer__blurb {
  color: var(--ivory-dim);
  font-size: 1rem;
  max-width: 24ch;
}

.footer h2 {
  font-family: var(--body);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--gold);
  margin: 0 0 1.1rem;
}

.footer__links {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  align-items: flex-start;
}

.footer__links a {
  color: var(--ivory-dim);
  font-size: 0.98rem;
  transition: color 0.3s ease;
}

.footer__links a:hover {
  color: var(--gold);
}

.socials {
  display: flex;
  gap: 0.85rem;
  flex-wrap: wrap;
}

.socials a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.6rem;
  height: 2.6rem;
  border: 1px solid var(--hair-soft);
  border-radius: 50%;
  color: var(--ivory-dim);
  transition: color 0.35s ease, border-color 0.35s ease,
    transform 0.4s cubic-bezier(0.22, 0.61, 0.36, 1),
    background 0.35s ease;
}

.socials a:hover {
  color: var(--gold);
  border-color: var(--gold);
  background: rgba(201, 162, 39, 0.09);
  transform: translateY(-3px);
}

.socials svg {
  width: 17px;
  height: 17px;
  fill: currentColor;
}

.colophon {
  margin-top: clamp(2.75rem, 5vw, 4rem);
  padding-top: 1.75rem;
  border-top: 1px solid var(--hair-soft);
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 1rem;
  font-size: 0.82rem;
  color: var(--ivory-faint);
}

@media (max-width: 60rem) {
  .footer__grid {
    grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  }
}

/* --------------------------------------------------------------- motion */

.reveal {
  opacity: 0;
  transform: translateY(18px);
}

@media (prefers-reduced-motion: no-preference) {
  .reveal {
    transition: opacity 0.9s cubic-bezier(0.22, 0.61, 0.36, 1),
      transform 0.9s cubic-bezier(0.22, 0.61, 0.36, 1);
  }
  .reveal.is-in {
    opacity: 1;
    transform: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  .reveal {
    opacity: 1;
    transform: none;
  }
  * {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }
}

/* JS off: never leave content invisible. */
.no-js .reveal {
  opacity: 1;
  transform: none;
}

/**
 * The deadline in site.js. Everything below starts at opacity 0 or zero scale
 * and depends on a transition to arrive at its final state — which needs the
 * page to be compositing. This turns the effects off rather than playing
 * them, so the finished state is reached with no animation frames at all.
 * !important is deliberate: this is the safety net, and it has to win.
 */
.reveals-off .reveal {
  opacity: 1 !important;
  transform: none !important;
  transition: none !important;
}

.reveals-off .ornament::before,
.reveals-off .ornament::after {
  transform: none !important;
  transition: none !important;
}

.reveals-off .hero__intro > *,
.reveals-off .hero__mark {
  animation: none !important;
  opacity: 1 !important;
  transform: none !important;
}

/* ----------------------------------------------------------- responsive */

@media (max-width: 60rem) {
  .hero__grid,
  .about__grid,
  .entry__grid,
  .book__grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .books-teaser {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .hero__grid {
    gap: 2.5rem;
  }

  .hero__mark {
    order: -1;
    width: min(78%, 20rem);
    justify-self: start;
  }

  .about__quote,
  .book__aside {
    position: static;
  }

  .about__quote {
    font-size: clamp(1.7rem, 6vw, 2.2rem);
  }

  .entry__grid .plate,
  .book__grid .plate {
    max-width: 17rem;
  }

  .post {
    grid-template-columns: minmax(0, 1fr);
    gap: 0.6rem;
  }

  .post__date {
    padding-top: 0;
  }
}

@media (max-width: 44rem) {
  .books-teaser,
  .siblings {
    grid-template-columns: minmax(0, 1fr);
    max-width: 17rem;
  }

  .masthead__inner {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.75rem;
    padding: 0.85rem 0;
  }

  .nav {
    gap: 1.35rem;
  }

  .nav a {
    font-size: 0.7rem;
    letter-spacing: 0.18em;
  }

  .about__body p:first-of-type::first-letter {
    font-size: 3.2em;
  }
}

/* ------------------------------------------------------------- printing */

@media print {
  body::after,
  .masthead,
  .signup,
  .socials {
    display: none;
  }
  body,
  .band {
    background: #fff;
    color: #000;
  }
}
