/* ==========================================================================
   Nectaring, style.css
   One stylesheet for the whole site. Sections are commented so you can find
   your way around. The order is:

     1. Fonts
     2. Colors (light and dark)
     3. Reset and base
     4. Paper texture
     5. Typography
     6. Links and focus states
     7. Ornament and rules
     8. Layout: header, sections, footer
     9. Hero
    10. Listen (the three singles)
    11. About
    12. Contact
    13. Press page
    14. 404 page
    15. Reduced motion
   ========================================================================== */


/* --------------------------------------------------------------------------
   1. FONTS
   Self-hosted, no outside requests. Two families:
   - "IM Fell English": the display face. Digitized from 17th-century types.
     Used for the wordmark, headings, and track titles.
   - "Alegreya": the body face. A readable serif with a little warmth.
   -------------------------------------------------------------------------- */

@font-face {
  font-family: "IM Fell English";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/im-fell-english-latin-400-normal.woff2") format("woff2");
}

@font-face {
  font-family: "IM Fell English";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/im-fell-english-latin-400-italic.woff2") format("woff2");
}

@font-face {
  font-family: "Alegreya";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/alegreya-latin-400-normal.woff2") format("woff2");
}

@font-face {
  font-family: "Alegreya";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/alegreya-latin-400-italic.woff2") format("woff2");
}

@font-face {
  font-family: "Alegreya";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/alegreya-latin-700-normal.woff2") format("woff2");
}


/* --------------------------------------------------------------------------
   2. COLORS
   Aged paper and ink, with four accents used sparingly:
   oxidised green (links), dried red, faded indigo, and khaki (rules/frames).
   Every text color has been checked against WCAG AA (4.5:1 or better on its
   background) in both modes. If you change a value, re-check the contrast.
   -------------------------------------------------------------------------- */

:root {
  --paper:   #F3EDDF;  /* warm aged paper */
  --ink:     #2A231A;  /* near-black with an umber cast (13.3:1) */
  --sepia:   #6B5B45;  /* supporting text (5.6:1) */
  --green:   #3D664C;  /* oxidised green: links (5.6:1) */
  --red:     #8A3B2E;  /* dried red: marks and small accents (6.6:1) */
  --indigo:  #43536B;  /* faded indigo: marks and small accents (6.7:1) */
  --khaki:   #8A835F;  /* khaki: decorative rules and frames only (3.3:1,
                          fine for hairlines, never for text) */
  --khaki-text: #6E6748; /* darker khaki, safe for text if ever needed (4.9:1) */
  --frame:   #4A4030;  /* photo and cover frames */

  /* Neon pink: the one drop of modern ink in the old book, like the
     fluorescent pink pass in a risograph print. Two versions:
     --pink is deep enough to carry text in light mode (5.1:1);
     --pink-bright is the true neon, for ornament, focus rings, and
     text selection only (3.4:1, fine for non-text, never for text). */
  --pink:        #C40068;
  --pink-bright: #F0189C;
}

@media (prefers-color-scheme: dark) {
  :root {
    /* Ink on dark paper: a nocturnal version of the same world. */
    --paper:  #201C16;
    --ink:    #EAE1CC;  /* 13.0:1 */
    --sepia:  #B5A98C;  /* 7.3:1 */
    --green:  #8FB89B;  /* 7.7:1 */
    --red:    #D28E7C;  /* 6.4:1 */
    --indigo: #9DB0CE;  /* 7.7:1 */
    --khaki:  #857C5C;
    --khaki-text: #B3AA82; /* 7.3:1 */
    --frame:  #A3987D;

    /* In the dark the neon gets to be fully itself: 5.3:1, text-safe. */
    --pink:        #FF3EB3;
    --pink-bright: #FF3EB3;
  }
}


/* --------------------------------------------------------------------------
   3. RESET AND BASE
   -------------------------------------------------------------------------- */

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

html {
  /* Keeps in-page jumps (like the skip link) from teleporting. */
  scroll-behavior: smooth;
}

body {
  font-family: "Alegreya", Georgia, "Times New Roman", serif;
  font-size: 1.1875rem;             /* 19px: Alegreya runs small */
  line-height: 1.65;
  color: var(--ink);
  background-color: var(--paper);
  font-feature-settings: "onum";    /* old-style figures: dates and years
                                       sit in the text like it's 1826 */
}

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


/* --------------------------------------------------------------------------
   4. PAPER TEXTURE
   A seamless handmade-paper tile (mottling, fibers, faint laid lines),
   generated for this site and overlaid at very low strength so it never
   touches text contrast. It works over both the light and dark grounds.
   Delete this block to remove the texture, and img/paper-tile.webp with it.
   -------------------------------------------------------------------------- */

body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image: url("../img/paper-tile.webp");
  background-size: 384px 384px;
}

@media (prefers-color-scheme: dark) {
  body::before {
    opacity: 0.55;                  /* quieter grain on the dark ground */
  }
}


/* --------------------------------------------------------------------------
   5. TYPOGRAPHY
   -------------------------------------------------------------------------- */

h1, h2, h3 {
  font-family: "IM Fell English", "Alegreya", Georgia, serif;
  font-weight: 400;                 /* the Fell types have no bold; they
                                       don't need one */
  line-height: 1.15;
  letter-spacing: 0.01em;
}

h2 {
  font-size: 1.9rem;
  margin-bottom: 0.4em;
}

h3 {
  font-size: 1.35rem;
}

p {
  margin-bottom: 1em;
  max-width: 65ch;                  /* comfortable reading measure */
}

.small,
small {
  font-size: 0.875rem;
}

.muted {
  color: var(--sepia);
}


/* --------------------------------------------------------------------------
   6. LINKS AND FOCUS STATES
   Links are oxidised green with a quiet underline. Focus is always visible.
   -------------------------------------------------------------------------- */

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

/* Hover is where the pink lives: links flush hot pink on touch. */
a:hover {
  color: var(--pink);
  text-decoration-color: var(--pink);
  text-decoration-thickness: 2px;
}

a:focus-visible,
button:focus-visible {
  outline: 2px solid var(--pink-bright);
  outline-offset: 3px;
  border-radius: 1px;
}

/* Selecting text inks it in fluorescent pink. */
::selection {
  background: var(--pink-bright);
  color: #2A231A;
}

/* Skip link: hidden until keyboard focus reaches it. */
.skip-link {
  position: absolute;
  left: 0.75rem;
  top: -4rem;
  z-index: 10;
  background: var(--paper);
  color: var(--ink);
  padding: 0.5rem 1rem;
  border: 1px solid var(--ink);
}

.skip-link:focus {
  top: 0.75rem;
}


/* --------------------------------------------------------------------------
   7. ORNAMENT AND RULES
   Hairlines and a small printer's-flower divider. All ornament is inline
   SVG marked aria-hidden in the HTML, so it stays out of screen readers.
   -------------------------------------------------------------------------- */

hr {
  border: 0;
  border-top: 1px solid var(--khaki);
  margin: 3rem auto;
  max-width: 16rem;
}

.fleuron {
  display: block;
  margin: 0 auto;
  width: 7rem;
  overflow: visible;                /* the butterfly's wings may reach a
                                       hair past the ornament's box */
  /* A generous invisible hit area around the ornament, so clicking it
     (three times, say) doesn't require surgeon's aim. The negative
     margins cancel the padding so the layout doesn't shift. */
  padding: 0.75rem 1rem;
  margin-top: -0.75rem;
  margin-bottom: -0.75rem;
  box-sizing: content-box;
}

/* The printer's flowers are printed entirely in the neon pink pass:
   diamond, dot, and flanking rules. The section accents (green, red,
   indigo) now live only in the cover artwork and small marks. */
.fleuron .stroke { stroke: var(--pink-bright); }

/* Ornament animation, always on and very quiet: the rules stretch a
   hair, and the diamond slowly turns, becoming a butterfly at the top
   of each rotation. Time-based CSS, so it runs in every browser.
   All of it stops under prefers-reduced-motion. */
@media (prefers-reduced-motion: no-preference) {
  .fleuron line.stroke {
    transform-box: fill-box;
    transform-origin: center;
  }

  .fleuron path.stroke {
    /* The metamorphosis: the diamond turns, becomes a butterfly at the
       top of the rotation (the pink dot as its body), rests a beat with
       a small wing-pulse, then folds back into a diamond as the turn
       completes. The path morph needs CSS "d" support (Chrome, Edge,
       Firefox); elsewhere the shape simply rotates. */
    transform-box: view-box;
    transform-origin: 70px 12px;
    animation: metamorphosis 14s ease-in-out infinite;
  }

  .fleuron line.stroke {
    animation: line-breathe 3.6s ease-in-out -2.4s infinite alternate;
  }
}

@keyframes metamorphosis {
  0% {
    d: path("M70 3 C72 4.5 74 6 76 7.5 C78 9 80 10.5 82 12 C80 13.5 78 15 76 16.5 C74 18 72 19.5 70 21 C68 19.5 66 18 64 16.5 C62 15 60 13.5 58 12 C60 10.5 62 9 64 7.5 C66 6 68 4.5 70 3 Z");
    transform: rotate(0deg) scale(0.95);
    opacity: 0.8;
  }
  34% {
    d: path("M70 3 C72 4.5 74 6 76 7.5 C78 9 80 10.5 82 12 C80 13.5 78 15 76 16.5 C74 18 72 19.5 70 21 C68 19.5 66 18 64 16.5 C62 15 60 13.5 58 12 C60 10.5 62 9 64 7.5 C66 6 68 4.5 70 3 Z");
    transform: rotate(200deg) scale(1.02);
    opacity: 1;
  }
  44% {
    d: path("M70 5 C73 3 78 1.5 82 3 C82.5 7.5 76 11 72 12 C78 13 80 17 77 20 C74 22.5 70.5 19 70 16 C69.5 19 66 22.5 63 20 C60 17 62 13 68 12 C64 11 57.5 7.5 58 3 C62 1.5 67 3 70 5 Z");
    transform: rotate(360deg) scale(1);
    opacity: 1;
  }
  60% {
    d: path("M70 5 C73 3 78 1.5 82 3 C82.5 7.5 76 11 72 12 C78 13 80 17 77 20 C74 22.5 70.5 19 70 16 C69.5 19 66 22.5 63 20 C60 17 62 13 68 12 C64 11 57.5 7.5 58 3 C62 1.5 67 3 70 5 Z");
    transform: rotate(360deg) scale(1);
    opacity: 1;
  }
  72% {
    d: path("M70 3 C72 4.5 74 6 76 7.5 C78 9 80 10.5 82 12 C80 13.5 78 15 76 16.5 C74 18 72 19.5 70 21 C68 19.5 66 18 64 16.5 C62 15 60 13.5 58 12 C60 10.5 62 9 64 7.5 C66 6 68 4.5 70 3 Z");
    transform: rotate(500deg) scale(1.02);
    opacity: 1;
  }
  100% {
    d: path("M70 3 C72 4.5 74 6 76 7.5 C78 9 80 10.5 82 12 C80 13.5 78 15 76 16.5 C74 18 72 19.5 70 21 C68 19.5 66 18 64 16.5 C62 15 60 13.5 58 12 C60 10.5 62 9 64 7.5 C66 6 68 4.5 70 3 Z");
    transform: rotate(720deg) scale(0.95);
    opacity: 0.8;
  }
}

@keyframes line-breathe {
  from { opacity: 0.45; transform: scaleX(0.86); }
  to   { opacity: 1;    transform: scaleX(1.1); }
}


/* --------------------------------------------------------------------------
   8. LAYOUT: HEADER, SECTIONS, FOOTER
   -------------------------------------------------------------------------- */

.container {
  width: min(100% - 2.5rem, 66rem);
  margin-inline: auto;
}

.site-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding-top: 1.25rem;
  font-size: 0.95rem;
}

.site-header .brand {
  font-family: "IM Fell English", Georgia, serif;
  font-size: 1.05rem;
  color: var(--ink);
  text-decoration: none;
}

.site-header .brand:hover {
  text-decoration: underline;
  text-decoration-color: var(--khaki);
}

.site-header nav a {
  margin-left: 1.25rem;
  font-variant: small-caps;         /* running-head feel, like a chapter
                                       title at the top of an old page */
  letter-spacing: 0.06em;
}

section {
  padding: 3.5rem 0 1rem;
}

.section-head {
  text-align: center;
  margin-bottom: 2.25rem;
}

.section-head h2 {
  margin-bottom: 0.75rem;
}

.site-footer {
  margin-top: 4rem;
  padding: 2rem 0 2.5rem;
  border-top: 1px solid var(--khaki);
  font-size: 0.9rem;
  color: var(--sepia);
  text-align: center;
}

.site-footer p {
  max-width: none;
  margin-bottom: 0.4em;
}

.footer-links a {
  margin: 0 0.6rem;
}


/* --------------------------------------------------------------------------
   9. HERO
   The wordmark dominates. The photograph sits below it like a plate in an
   old field guide, framed and captioned.
   -------------------------------------------------------------------------- */

.hero {
  text-align: center;
  padding: 3.5rem 0 1rem;
}

.hero h1 {
  font-size: clamp(3.4rem, 12vw, 6.5rem);
  margin-bottom: 2rem;
  /* Misregistered second pass: a faint neon ghost of the wordmark,
     offset like a risograph print that didn't quite line up. Echoes the
     chromatic aberration in the cover art. Static here; it drifts
     slightly with the breathing cycle for those without reduced motion. */
  text-shadow: 3px 2px 0 color-mix(in srgb, var(--pink-bright) 30%, transparent);
}

/* On arrival, the wordmark settles like ink drying: it fades in while
   its letterspacing tightens, and the hero photograph fades up after.
   Time-based, so it runs in every browser; off under reduced motion. */
@media (prefers-reduced-motion: no-preference) {
  .hero h1 {
    animation:
      ink-settle 1.1s ease-out both,
      ghost-drift 3.6s ease-in-out 1.1s infinite alternate;
  }

  .hero .plate img {
    animation: fade-up 1s ease-out 0.25s both;
  }
}

@keyframes ink-settle {
  from { opacity: 0; letter-spacing: 0.08em; }
  to   { opacity: 1; letter-spacing: 0.01em; }
}

/* The neon ghost never quite holds still. */
@keyframes ghost-drift {
  from { text-shadow: 2px 1px 0 color-mix(in srgb, var(--pink-bright) 26%, transparent); }
  to   { text-shadow: 4px 3px 0 color-mix(in srgb, var(--pink-bright) 38%, transparent); }
}

@keyframes fade-up {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* "Plate" treatment: double frame, like an illustration tipped into a book. */
.plate {
  margin: 0 auto;
  max-width: 34rem;
}

.plate img {
  border: 1px solid var(--frame);
  outline: 3px solid var(--frame);
  outline-offset: 6px;
  margin: 9px auto;                  /* room for the outer rule, and the
                                        image stays centered even when
                                        narrower than its container */
}


/* --------------------------------------------------------------------------
   10. LISTEN
   Three singles with the artwork shown large. Streaming links are plain
   text links below the grid. No embeds, ever.
   -------------------------------------------------------------------------- */

.singles {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2.5rem;
  max-width: 60rem;
  margin: 0 auto;
}

.single img {
  border: 1px solid var(--frame);
  width: 100%;
}

.single h3 {
  margin-top: 1rem;
  font-style: italic;
}

.single .year {
  font-size: 0.9rem;
  color: var(--sepia);
}

.stream-links {
  text-align: center;
  margin-top: 3rem;
  font-size: 1.05rem;
}

.stream-links p {
  max-width: none;
}

/* Interpunct separators between the platform links, drawn by CSS so they
   never end up in a screen reader's reading order. */
.stream-links a + a::before {
  content: "·";
  color: var(--pink-bright);
  margin: 0 0.75rem 0 0.55rem;
  text-decoration: none;
  display: inline-block;
}

@media (max-width: 44rem) {
  .singles {
    grid-template-columns: 1fr;
    max-width: 21rem;
  }
}


/* --------------------------------------------------------------------------
   11. ABOUT
   Prose at a comfortable measure, with a modest Fell initial.
   -------------------------------------------------------------------------- */

.about-inner {
  /* The block sits centered under the heading: the box is exactly as
     wide as the text measure, so the paragraphs can't drift left
     inside a wider container. */
  max-width: 65ch;
  margin: 0 auto;
}

.about-inner p {
  /* Justified, like a page from an old book. A ragged right edge makes
     centered prose look pushed left; a clean rectangle reads centered. */
  text-align: justify;
  hyphens: auto;
}

.about-figure {
  max-width: 28rem;
  margin: 2.5rem auto 0;
}


/* --------------------------------------------------------------------------
   12. CONTACT
   Deliberately quiet. If you ever add an email signup, this section is
   where it should live: a simple Netlify form (add `netlify` to a <form>)
   dropped in above the contact lines would need no redesign.
   -------------------------------------------------------------------------- */

.contact {
  text-align: center;
  padding-bottom: 0;
}

.contact p {
  max-width: none;
}


/* --------------------------------------------------------------------------
   12b. COMMONPLACE BOOK
   A gathering of writers on the Ozarks and Missouri, shown one at a
   time like an epigraph. JavaScript picks one at random per visit and
   wires the "another" control; without it, the first quote shows.
   -------------------------------------------------------------------------- */

.commonplace {
  text-align: center;
}

.quote-sub {
  font-style: italic;
  margin-top: 0.75rem;
  max-width: none;
}

.quote-list {
  list-style: none;
  max-width: 52ch;
  margin: 0 auto;
  min-height: 11rem;                /* steadies the page while leafing */
}

/* Show only the first quote until JavaScript takes over... */
.quote-list li {
  display: none;
}

.quote-list li:first-child {
  display: block;
}

/* ...then only the active one. */
.quote-list.js li {
  display: none;
}

.quote-list.js li.active {
  display: block;
}

.quote-list blockquote p {
  font-style: italic;
  font-size: 1.15rem;
  line-height: 1.7;
  max-width: none;
  margin-bottom: 0.9rem;
}

.quote-attr {
  font-size: 0.9rem;
  color: var(--sepia);
  font-variant: small-caps;
  letter-spacing: 0.05em;
  max-width: none;
}

.quote-attr cite {
  font-style: italic;
  font-variant: normal;
  letter-spacing: normal;
}

.quote-more {
  max-width: none;
}

.quote-more button {
  background: none;
  border: none;
  padding: 0.25rem 0.75rem;
  font: inherit;
  font-style: italic;
  color: var(--green);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
  text-decoration-color: var(--khaki);
  cursor: pointer;
}

.quote-more button:hover {
  color: var(--pink);
  text-decoration-color: var(--pink);
}

@media (prefers-reduced-motion: no-preference) {
  .quote-list.js li.active {
    animation: quote-in 0.6s ease both;
  }
}

@keyframes quote-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}


/* --------------------------------------------------------------------------
   13. PRESS PAGE
   -------------------------------------------------------------------------- */

.press-main {
  max-width: 44rem;
  margin: 0 auto;
}

.press-main section {
  padding: 2.25rem 0 0;
}

.press-main h2 {
  font-size: 1.6rem;
  border-bottom: 1px solid var(--khaki);
  padding-bottom: 0.35rem;
  margin-bottom: 1rem;
  position: relative;
}

/* A short stroke of the pink pass over the left end of each rule. */
.press-main h2::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -1px;
  width: 3rem;
  height: 2px;
  background: var(--pink-bright);
}

.press-intro {
  text-align: center;
  padding: 3rem 0 0.5rem;
}

.press-intro h1 {
  font-size: clamp(2.4rem, 8vw, 3.6rem);
}

.press-intro .sub {
  font-style: italic;
  color: var(--sepia);
  max-width: none;                  /* let it center under the heading */
}

/* Downloadable photos: thumbnail links to the full-size file. */
.press-photos {
  list-style: none;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.75rem;
}

.press-photos img {
  border: 1px solid var(--frame);
}

.press-photos figcaption {
  margin-top: 0.5rem;
  font-size: 0.875rem;
  color: var(--sepia);
}

.press-art {
  list-style: none;
}

.press-art li {
  margin-bottom: 0.4rem;
}

@media (max-width: 34rem) {
  .press-photos {
    grid-template-columns: 1fr;
  }
}


/* --------------------------------------------------------------------------
   14. 404 PAGE
   -------------------------------------------------------------------------- */

.lost {
  text-align: center;
  padding: 6rem 0;
}

.lost h1 {
  font-size: clamp(2.6rem, 9vw, 4rem);
  margin-bottom: 0.5rem;
}

.lost p {
  max-width: none;
  color: var(--sepia);
  font-style: italic;
}


/* --------------------------------------------------------------------------
   15. SCROLL REVEAL
   Covers, plates, and section heads settle gently into place as they
   scroll into view, like a page coming to rest. Pure CSS scroll-driven
   animation: no JavaScript. Browsers that don't support it (some Firefox
   versions) simply show everything immediately, which is fine. Removed
   entirely under prefers-reduced-motion.
   -------------------------------------------------------------------------- */

/* Images fade and rise; anything carrying text only rises. Text must
   never sit at partial opacity (it would fail the contrast floor for
   anyone whose viewport catches it mid-animation). */
@keyframes settle-fade {
  from {
    opacity: 0;
    transform: translateY(1rem) scale(0.985);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes settle-rise {
  from {
    transform: translateY(1rem);
  }
  to {
    transform: none;
  }
}

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .single img,
    .about-figure img,
    .press-photos img {
      animation: settle-fade linear both;
      animation-timeline: view();
      animation-range: entry 5% entry 45%;
    }

    .single,
    .press-photos li,
    .section-head {
      animation: settle-rise linear both;
      animation-timeline: view();
      animation-range: entry 5% entry 45%;
    }
  }
}


/* --------------------------------------------------------------------------
   15a. FALLBACK REVEAL (Safari before 26, Firefox)
   Those browsers don't support CSS scroll-driven animations, so a tiny
   script (js/reveal.js) recreates the settle and ornament-draw effects:
   it adds .js-reveal to <html> only in browsers that need it, then marks
   elements .in-view as they scroll into sight. With JavaScript disabled,
   .js-reveal never appears and nothing is ever hidden.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: no-preference) {
  .js-reveal .single img,
  .js-reveal .about-figure img,
  .js-reveal .press-photos img {
    opacity: 0;
    transform: translateY(1rem) scale(0.985);
    transition: opacity 0.7s ease, transform 0.7s ease;
  }

  .js-reveal .single.in-view img,
  .js-reveal .about-figure.in-view img,
  .js-reveal .press-photos li.in-view img {
    opacity: 1;
    transform: none;
  }

  .js-reveal .single,
  .js-reveal .press-photos li,
  .js-reveal .section-head {
    transform: translateY(1rem);
    transition: transform 0.7s ease;
  }

  .js-reveal .single.in-view,
  .js-reveal .press-photos li.in-view,
  .js-reveal .section-head.in-view {
    transform: none;
  }

}


/* --------------------------------------------------------------------------
   15b. WIDE SCREENS
   On laptop and desktop screens, let the site breathe: everything scales
   up about 15% and the containers widen. Delete this block to return to
   the tighter layout.
   -------------------------------------------------------------------------- */

@media (min-width: 1150px) {
  html {
    font-size: 115%;
  }

  .container {
    width: min(100% - 3rem, 74rem);
  }

  section {
    padding: 4.5rem 0 1.5rem;
  }

  .plate {
    max-width: 40rem;
  }

  .singles {
    max-width: 68rem;
    gap: 3.25rem;
  }

  .press-main {
    max-width: 48rem;
  }
}


/* --------------------------------------------------------------------------
   15c. HOVER AND MOTION POLISH
   Small, quiet interactions: links ease into their pink, cover frames
   warm on hover, the plates breathe, and the hero drifts gently as you
   begin to scroll. All of it is disabled under prefers-reduced-motion.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: no-preference) {
  a {
    transition: color 0.18s ease, text-decoration-color 0.18s ease;
  }

  .single img,
  .press-photos img {
    transition: border-color 0.3s ease, filter 0.3s ease;
  }

  .single:hover img,
  .press-photos a:hover img,
  .press-photos a:focus-visible img {
    border-color: var(--pink-bright);
    filter: brightness(1.04) saturate(1.05);
  }

  /* The framed plates breathe: the outer rule eases outward on hover. */
  .plate img {
    transition: outline-offset 0.35s ease, outline-color 0.35s ease;
  }

  .plate:hover img {
    outline-offset: 9px;
    outline-color: var(--pink-bright);
  }

  /* The hero plate drifts up slightly slower than the page as you begin
     to scroll: a whisper of parallax, pure CSS. */
  @supports (animation-timeline: scroll()) {
    .hero .plate {
      animation: hero-drift linear both;
      animation-timeline: scroll();
      animation-range: 0 600px;
    }
  }
}

@keyframes hero-drift {
  to {
    transform: translateY(-1.25rem);
  }
}


/* --------------------------------------------------------------------------
   15d. PAGE TRANSITIONS
   Moving between pages cross-fades softly, like a page turning, in
   browsers that support cross-document view transitions (Chrome, Edge).
   Others simply navigate normally. Off under reduced motion.
   -------------------------------------------------------------------------- */

@view-transition {
  navigation: auto;
}

::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 0.45s;
}

@media (prefers-reduced-motion: reduce) {
  @view-transition {
    navigation: none;
  }
}


/* --------------------------------------------------------------------------
   15e. THE FLUORESCENT MODE (easter egg)
   Click any section ornament three times and the site falls into the
   cover art: near-black ground, neon pink ink, acid green links,
   RGB-split headings, slow hue-cycling images, a pulsing magenta glow.
   Three more clicks brings the daylight back. Triggered in js/reveal.js.
   Every text color here still passes WCAG AA; it's a trip, not a trap.
   -------------------------------------------------------------------------- */

html.fluorescent {
  --paper: #150011;   /* blackberry dark */
  --ink: #FF5FC1;     /* neon pink ink (7.4:1) */
  --sepia: #C24E97;   /* supporting pink (4.6:1) */
  --green: #59FFB0;   /* acid green links (15.7:1) */
  --red: #FF2DAD;
  --indigo: #6EF3FF;  /* electric cyan (15.3:1) */
  --khaki: #7A2E63;
  --khaki-text: #FF9BD8;
  --frame: #FF2DAD;
  --pink: #FF2DAD;
  --pink-bright: #FF2DAD;
}

/* Photographs and cover art run hot. */
html.fluorescent img {
  filter: saturate(1.5) contrast(1.08);
}

/* Headings split into misregistered color passes, like the artwork. */
html.fluorescent h1,
html.fluorescent h2,
html.fluorescent h3 {
  text-shadow:
    -3px 0 rgba(89, 255, 176, 0.55),
    3px 0 rgba(255, 45, 173, 0.65);
}

@media (prefers-reduced-motion: no-preference) {
  /* The artwork slowly cycles through the spectrum. */
  html.fluorescent img {
    animation: hue-trip 14s linear infinite;
  }

  /* The color passes never sit still: a stepped glitch jitter. */
  html.fluorescent h1,
  html.fluorescent h2,
  html.fluorescent h3 {
    animation: rgb-jitter 1.6s steps(1, end) infinite;
  }

  /* A magenta glow breathes behind everything. */
  html.fluorescent body::after {
    content: "";
    position: fixed;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    background: radial-gradient(ellipse at 50% 25%,
      rgba(255, 45, 173, 0.30), transparent 65%);
    animation: glow-pulse 4.5s ease-in-out infinite alternate;
  }

  /* The ornaments run quicker in here. */
  html.fluorescent .fleuron path.stroke,
  html.fluorescent .fleuron line.stroke {
    animation-duration: 4s;
  }
}

@keyframes hue-trip {
  from { filter: saturate(1.5) contrast(1.08) hue-rotate(0deg); }
  to   { filter: saturate(1.5) contrast(1.08) hue-rotate(360deg); }
}

@keyframes rgb-jitter {
  0%   { text-shadow: -3px 0 rgba(89, 255, 176, 0.55), 3px 0 rgba(255, 45, 173, 0.65); }
  25%  { text-shadow: -2px 1px rgba(89, 255, 176, 0.55), 2px -1px rgba(255, 45, 173, 0.65); }
  50%  { text-shadow: -4px -1px rgba(110, 243, 255, 0.5), 3px 1px rgba(255, 45, 173, 0.65); }
  75%  { text-shadow: -2px 0 rgba(89, 255, 176, 0.55), 4px 0 rgba(255, 45, 173, 0.55); }
  100% { text-shadow: -3px 0 rgba(89, 255, 176, 0.55), 3px 0 rgba(255, 45, 173, 0.65); }
}

@keyframes glow-pulse {
  from { opacity: 0.35; }
  to   { opacity: 1; }
}


/* --------------------------------------------------------------------------
   16. PRINT
   Writers and radio programmers still print press kits. On paper the site
   becomes plain ink on white: no texture, no ornament, no navigation, and
   every external link spells out its URL so the printed page stays useful.
   -------------------------------------------------------------------------- */

@media print {
  :root {
    --paper: #fff;
    --ink: #000;
    --sepia: #333;
    --green: #000;
    --red: #000;
    --indigo: #000;
    --khaki: #999;
    --khaki-text: #333;
    --frame: #000;
    --pink: #000;
    --pink-bright: #000;
  }

  body {
    background: #fff;
    font-size: 11pt;
  }

  body::before {
    display: none;                  /* no paper texture on actual paper */
  }

  .skip-link,
  .site-header nav,
  .fleuron {
    display: none;
  }

  a {
    color: #000;
  }

  /* Spell out where each link goes. */
  main a[href^="http"]::after {
    content: " (" attr(href) ")";
    font-size: 0.85em;
    color: #333;
    word-break: break-all;
  }

  figure,
  .press-photos li,
  section {
    break-inside: avoid;
  }

  .single img,
  .about-figure img,
  .press-photos img,
  .section-head {
    animation: none;
    opacity: 1;
    transform: none;
  }

  @page {
    margin: 2cm;
  }
}


/* --------------------------------------------------------------------------
   17. REDUCED MOTION
   The site has almost no motion; this removes the little that exists.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    transition: none !important;
    animation: none !important;
  }
}


/* --------------------------------------------------------------------------
   18. CURSOR SPARKLES
   A fluorescent-pink trail behind the cursor, drawn by js/sparkle.js.
   The one purely playful thing on the page, and it uses the same neon ink
   as the ornaments and the selection colour, so it follows dark mode and
   the fluorescent easter egg for free.

   Mouse only, nothing on touch, nothing under reduced motion, and the
   layer never intercepts a click. If you want it gone: delete the script
   tag from the pages and this section.
   -------------------------------------------------------------------------- */

.sparkle-layer {
  position: fixed;
  inset: 0;
  z-index: 9999;
  pointer-events: none;
  overflow: hidden;
}

.sparkle {
  position: absolute;
  display: block;
  margin: -0.5em 0 0 -0.5em;      /* centre the grain on the cursor */
  background: var(--pink-bright);
  /* A four-pointed star, the same shape as the diamond in the fleurons. */
  clip-path: polygon(
    50% 0, 61% 39%, 100% 50%, 61% 61%,
    50% 100%, 39% 61%, 0 50%, 39% 39%
  );
  will-change: transform, opacity;
  animation-name: sparkle-settle;
  animation-timing-function: cubic-bezier(0.2, 0.6, 0.3, 1);
  animation-fill-mode: forwards;
}

/* Ink settling: it drifts a little, turns, and fades out. */
@keyframes sparkle-settle {
  from {
    opacity: 0.95;
    transform: translate(0, 0) scale(1) rotate(0deg);
  }
  to {
    opacity: 0;
    transform: translate(var(--sx, 0), var(--sy, 12px)) scale(0.15) rotate(var(--sr, 90deg));
  }
}
