:root {
  --bg: #f6e3d6;
  --bg-rgb: 246, 227, 214;
  --ink: #200002;
  --muted: #6e5859;
  --cursor-ring: #7a6858;

  --font-mono: "DM Mono", "Courier New", monospace;
  --font-sans: "DM Sans", Georgia, serif;
  --font-display: "Bebas Neue", "Arial Narrow", sans-serif;

  --topbar-h: clamp(3.5rem, 6vw, 4.75rem);
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--ink);
}

/* Proximity (not mandatory) so normal poem reading is never hijacked —
   only .poem-footer opts in as a snap target, and only once scrolling is
   already close to it does the browser pull it fully into view. */
html {
  scroll-snap-type: y proximity;
}

body {
  font-family: var(--font-sans);
  padding: 0 clamp(1.25rem, 3vw, 2.5rem) 6rem;
}

/* --- Top bar --------------------------------------------------------- */

.top-bar {
  position: sticky;
  top: 0;
  z-index: 30;
  height: var(--topbar-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: clamp(1rem, 4vw, 3rem);
  /*background: rgba(var(--bg-rgb), 0.2);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(16px);*/
  font-family: var(--font-mono);
  text-transform: uppercase;
  font-size: clamp(0.7rem, 1vw, 1.1rem);
  letter-spacing: 0.02em;
  transition: color 0.3s ease;
}

/* BB / 2017 / — / 2026 all link home now, as one click target, so they
   need their own internal spacing — same gap the top bar itself uses,
   so it reads identically to when these were plain, unlinked spans. */
.top-bar__brand {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 4vw, 3rem);
  /* Deliberately not .poem-line — that class carries an unconditional
     translateY(14px) meant for the homepage poem-list's scroll-reveal
     (where a matching .is-visible rule resets it), which has nothing to
     reset it here and was quietly dropping this and the mark below down
     by 14px. Just the link-reset bits, none of the transform. */
  color: inherit;
  text-decoration: none;
}

.top-bar__title {
  margin-left: auto;
  margin-right: clamp(1rem, 4vw, 3rem);
}

.top-bar__mark {
  display: block;
  width: 1em;
  height: 1em;
  background: var(--ink);
  flex-shrink: 0;
  transition: background 0.3s ease;
  /* Not .poem-line here either — see .top-bar__brand above. */
  text-decoration: none;
}

/* Toggled by page.js (IntersectionObserver on .poem-footer) once the dark
   footer has scrolled in behind the nav — .top-bar has no background fill
   of its own, so its text would otherwise go dark-on-dark. */
.top-bar.top-bar--on-dark {
  color: var(--bg);
}

.top-bar.top-bar--on-dark .top-bar__mark {
  background: var(--bg);
}

.poem-line {
  color: inherit;
  text-decoration: none;
  /*opacity: 0;*/
  transform: translateY(14px);
  transition: opacity 0.6s ease, transform 0.6s ease;
}


/* --- Layout ------------------------------------------------------------ */

.layout {
  display: grid;
  grid-template-columns: minmax(180px, 320px) minmax(0, 1fr);
  gap: clamp(2rem, 6vw, 7rem);
  align-items: start;
  margin-top: clamp(2.5rem, 8vw, 6rem);
}

.sidebar {
  position: sticky;
  top: calc(var(--topbar-h) + clamp(1.25rem, 2vw, 2rem));
  z-index: 10;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  min-height: min(70vh, 640px);
  /* content-box (overriding the global border-box reset) so this
     padding-bottom adds height below the 70vh/640px content area instead
     of eating into it — title/subtitle/dot keep their original positions,
     and the box just grows taller beneath the dot. That extra height is
     what keeps the dot clear of the footer's top edge once the sidebar
     unsticks (its own bottom edge is what the footer's top touches).
     Overridden by mobile's own padding shorthand below. */
  box-sizing: content-box;
  padding-bottom: 10vh;
}

.sidebar__title {
  margin: 0;
  font-family: var(--font-mono);
  font-weight: 500;
  text-transform: uppercase;
  font-size: clamp(1.75rem, 3vw, 2.5rem);
}

.sidebar__foot {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

.sidebar__subtitle {
  margin: 0;
  font-family: var(--font-mono);
  font-weight: 500;
  text-transform: uppercase;
  color: var(--muted);
  font-size: clamp(1rem, 1.4vw, 1.5rem);
  line-height: 1.4;
}

.dot {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--ink);
}

/* --- Poem column --------------------------------------------------------- */

.poem-column {
  display: flex;
  flex-direction: column;
  gap: clamp(1.5rem, 3.5vw, 2.75rem);
  min-width: 0;
  /* Lives here (not as spacing on .poem-footer) so the extra height counts
     toward .layout's grid row — which is what keeps the sticky sidebar
     pinned through this gap on desktop rather than letting it scroll off
     as soon as the poem text ends. See the matching value on
     .poem-footer's margin-top removal below. */
  margin-bottom: 50vh;
}

@media (max-width: 1024px) {
  .poem-column {
    margin-bottom: 30vh;
  }
}

.poem-block {
  font-family: var(--font-sans);
  font-variation-settings: "opsz" 14;
  font-size: clamp(1rem, 1.3vw, 1.5rem);
  line-height: 1.9;
  max-width: 30em;
}

.poem-block p {
  margin: 0;
}

/* Receives the scroll-linked parallax transform, kept separate from
   .poem-block (which handles the load-in reveal) — same reasoning as
   .pull-quote__parallax below. */
.poem-block__parallax {
  width: 100%;
  will-change: transform;
}

/* --- Pull quote ------------------------------------------------------------ */

.pull-quote {
  position: relative;
  width: 100%;
}

/* Receives the scroll-linked parallax transform, kept separate from
   .pull-quote (which handles the load-in reveal) — see the HTML comment
   above this element for why. */
.pull-quote__parallax {
  width: 100%;
  will-change: transform;
}

.pull-quote__canvas {
  width: 100%;
  height: clamp(180px, 22vw, 340px);
  cursor: none;
}

.pull-quote__canvas canvas {
  display: block;
}

/* Custom circular cursor, drawn as a plain CSS ring (matches the Figma
   "custom-cursor" asset, which is itself just a stroked circle). Positioned
   by pull-quote.js while the pointer is over the quote. */
.pull-quote__cursor {
  position: fixed;
  top: 0;
  left: 0;
  width: 104px;
  height: 104px;
  margin: -52px 0 0 -52px;
  border: 1px solid var(--cursor-ring);
  border-radius: 50%;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.2s ease;
  z-index: 20;
}

.pull-quote__cursor.is-visible {
  opacity: 1;
}

/* --- Load-in reveal --------------------------------------------------------- */
/* Applied to .top-bar, the sidebar title/foot, each poem line, and the
   pull-quote section. page.js staggers transition-delay top-to-bottom in
   DOM order, then flips .is-visible once on load. */

.reveal {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 0.9s ease, transform 0.9s ease;
}

.reveal.is-visible {
  opacity: 1;
  transform: translateY(0);
}

/* --- Footer / next poem -------------------------------------------------------
   Full-viewport, inverted palette (this page's ink becomes the background)
   — a deliberate beat between poems, not a normal page footer. Snaps into
   place via scroll-snap-align below; the nav's colour inversion while
   this is behind it is handled in page.js. */

.poem-footer {
  position: relative;
  min-height: 100vh;
  margin: 0 calc(-1 * clamp(1.25rem, 3vw, 2.5rem)) -6rem;
  padding: clamp(2rem, 6vw, 4rem) clamp(1.25rem, 3vw, 2.5rem);
  display: flex;
  flex-direction: column;
  justify-content: center;
  background: var(--ink);
  color: var(--bg);
  scroll-snap-align: start;
  scroll-margin-top: var(--topbar-h);
}

.poem-footer__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: clamp(1.5rem, 5vw, 4rem);
  flex-wrap: wrap;
}

.poem-footer__tagline {
  margin: 0;
  font-family: var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  font-size: clamp(1.25rem, 2.5vw, 2rem);
}

.poem-footer__next {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 3vw, 2rem);
  color: inherit;
  text-decoration: none;
}

/* Sizing + the hover-scale interaction live here; the gentle idle pulse
   lives one level in, on .poem-footer__next-circle__ring, so the two
   transforms never land on the same element — same split as the
   homepage's "SCROLL" cursor (.scroll-cursor / .scroll-cursor__ring),
   whose pulse this replicates. */
.poem-footer__next-circle {
  width: clamp(140px, 14vw, 210px);
  aspect-ratio: 1;
  transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}

.poem-footer__next-circle__ring {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  border: 1px solid rgba(var(--bg-rgb), 0.5);
  font-family: var(--font-sans);
  font-size: clamp(0.85rem, 1.1vw, 1.05rem);
  line-height: 1.3;
  padding: 1rem;
  transition: border-color 0.4s ease;
  animation: nextCirclePulse 2.4s ease-in-out infinite;
}

@keyframes nextCirclePulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.08); }
}

.poem-footer__next-circle em {
  font-style: normal;
  display: block;
}

.poem-footer__next-arrow {
  position: relative;
  width: clamp(60px, 8vw, 140px);
  height: 1px;
  background: rgba(var(--bg-rgb), 0.5);
  flex-shrink: 0;
  transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1), background 0.4s ease;
}

.poem-footer__next-arrow::after {
  content: "";
  position: absolute;
  right: 0;
  top: 50%;
  width: 9px;
  height: 9px;
  border-right: 1px solid rgba(var(--bg-rgb), 0.5);
  border-top: 1px solid rgba(var(--bg-rgb), 0.5);
  transform: translateY(-50%) rotate(45deg);
  transition: border-color 0.4s ease;
}

.poem-footer__next:hover .poem-footer__next-circle,
.poem-footer__next:focus-visible .poem-footer__next-circle {
  transform: scale(1.06);
}

.poem-footer__next:hover .poem-footer__next-circle__ring,
.poem-footer__next:focus-visible .poem-footer__next-circle__ring {
  border-color: var(--bg);
}

.poem-footer__next:hover .poem-footer__next-arrow,
.poem-footer__next:focus-visible .poem-footer__next-arrow {
  transform: translateX(8px);
  background: var(--bg);
}

.poem-footer__next:hover .poem-footer__next-arrow::after,
.poem-footer__next:focus-visible .poem-footer__next-arrow::after {
  border-color: var(--bg);
}

.poem-footer__copyright {
  position: absolute;
  left: clamp(1.25rem, 3vw, 2.5rem);
  bottom: clamp(1.25rem, 3vw, 2.5rem);
  margin: 0;
  font-family: var(--font-mono);
  text-transform: uppercase;
  font-size: 0.75rem;
  letter-spacing: 0.02em;
  color: rgba(var(--bg-rgb), 0.5);
}

/* --- Accessibility -------------------------------------------------------- */

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

/* Desktop only (mirrors the max-width: 760px mobile breakpoint below) —
   title, subtitle, and poem lines run 15% smaller than the shared base
   size; mobile keeps the original clamp() values untouched. */
@media (min-width: 761px) {
  .sidebar__title {
    font-size: clamp(1.4875rem, 2.55vw, 2.125rem);
  }

  .sidebar__subtitle {
    font-size: clamp(0.85rem, 1.19vw, 1.275rem);
  }

  .poem-block {
    font-size: clamp(0.85rem, 1.105vw, 1.275rem);
  }
}

@media (max-width: 760px) {
  .layout {
    grid-template-columns: 1fr;
  }

  .top-bar {
    /* Unlike desktop (where this stays transparent on purpose), poem text
       scrolls directly behind this on mobile and was illegible through
       it — same full-bleed background-fill treatment as .sidebar below. */
    margin: 0 calc(-1 * clamp(1.25rem, 3vw, 2.5rem)) 0;
    padding: 0 clamp(1.25rem, 3vw, 2.5rem);
    background: var(--bg);
  }

  .sidebar {
    /* Stays sticky here too (matching desktop) rather than static — it
       should hold its position regardless of viewport width. This block
       is tall enough that poem text scrolling directly behind it — the
       mobile layout stacks sidebar above poem-column in the same column,
       unlike desktop's side-by-side columns — makes both illegible, so it
       gets the same background fill as .top-bar above. */
    top: var(--topbar-h);
    min-height: 0;
    flex-direction: column;
    justify-content: flex-start;
    align-items: flex-start;
    gap: 0.75rem;
    margin: 0 calc(-1 * clamp(1.25rem, 3vw, 2.5rem)) 2rem;
    padding: 0.75rem clamp(1.25rem, 3vw, 2.5rem);
    background: var(--bg);
  }

  .sidebar__foot {
    align-items: flex-start;
    text-align: left;
  }

  .dot {
    width: 13px;
    height: 13px;
  }

  .top-bar.top-bar--on-dark {
    /* Desktop's nav has no fill of its own, so inverting just the text
       is enough. Mobile's nav has a solid cream fill (so poem text
       scrolling behind it stays legible), which means that same fill
       needs to flip to the footer's ink colour too — otherwise the
       (also-inverted) light text renders light-on-light. */
    background: var(--ink);
  }

  .poem-footer {
    /* The circle centers in the viewport both ways; the tagline is
       pulled out of this flex flow (position: absolute below) so it can
       stay fixed near the top independently of that centering. */
    justify-content: center;
    align-items: center;
  }

  .poem-footer__tagline {
    /* .poem-footer is position: relative, so this is relative to the
       footer's own box — effectively the viewport, once scroll-snap has
       pulled the footer fully into view. At least 10% of viewport height
       clear of the top so it never sits flush against the (now
       dark-filled) sticky nav above it. */
    position: absolute;
    top: 10vh;
    left: clamp(1.25rem, 3vw, 2.5rem);
    right: clamp(1.25rem, 3vw, 2.5rem);
  }

  .poem-footer__row {
    justify-content: center;
  }

  .poem-footer__next-circle {
    width: clamp(220px, 68vw, 280px);
  }

  .poem-footer__next-arrow {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .pull-quote__cursor {
    display: none;
  }

  .poem-footer__next-circle__ring {
    animation: none;
  }

  .reveal {
    opacity: 1;
    transform: none;
    transition: none;
  }

  html {
    scroll-snap-type: none;
  }

  .poem-footer__next-circle,
  .poem-footer__next-arrow,
  .poem-footer__next-arrow::after {
    transition: none;
  }

  .poem-footer__next:hover .poem-footer__next-circle,
  .poem-footer__next:focus-visible .poem-footer__next-circle {
    transform: none;
  }

  .poem-footer__next:hover .poem-footer__next-arrow,
  .poem-footer__next:focus-visible .poem-footer__next-arrow {
    transform: none;
  }
}
