/* PUBLICATIONS PAGE — local styles. Prefix: p- */

/* =========================================================
   IN-PAGE SECTION NAV
   =========================================================
   The bar itself is a shared component and lives in styles.css — it is on
   /research/, the homepage, and here since 13 August 2026. What stays with the
   page is this: anchor targets have to clear the site header AND the bar, or
   every jump lands with its heading tucked behind them. The global rule in
   styles.css sets 96px for the header alone; a page carrying the bar needs the
   extra 46. Scoped by loading: pages/publications.css loads only here.

   .p-sections, the sticky containing block wrapping the bar and its
   destinations, deliberately has no rules of its own — same as .r-sections and
   .l-sections. It exists to bound the stick and nothing else, and giving it an
   `overflow` or a `transform` would kill that. */
html { scroll-padding-top: 142px; }

/* --- The one page where the bar needs its own ground --------------------- */
/* .secnav ships --paper-2, and on this page the section directly beneath it,
   .p-themes, is ALSO --paper-2 — byte-identical rgb(230,227,217). The bar
   dissolved into the page, which it does not do on /research/ or the homepage
   because both put --paper underneath it. Fixed 13 August 2026 at Joel's
   instruction.

   --paper-3, not --paper, and the direction is the whole argument. On the other
   two pages the bar sits one step DARKER than the ground it covers; going
   lighter here would separate the bar just as well (1.09 against 1.10, so the
   step is the same either way) but would invert that relationship and leave the
   three bars disagreeing about what a section nav is. Darker keeps one rule
   across the site: the bar is a step down from whatever it sits over.

   The links were measured on the new ground, not assumed: --petrol 7.53:1 and
   --ink 12.96:1, and on the active wash 6.51:1 and 11.20:1. All clear AA.

   NOTE the caveat this does NOT trip. styles.css rejects --paper-3 elsewhere
   because it puts --steel at exactly 4.50:1, with nothing spare. The bar
   carried --steel until the alternating colours landed the same day; it does
   not any more. If a --steel element is ever added to this bar, that rejection
   applies again and this ground has to be re-argued. */
.secnav { background: var(--paper-3); }

/* --- The hero, dark over a photograph since 18 August 2026 --------------- */
/* Joel asked for a background image here in the manner of the research page,
   and the whole colour scheme of this section moved with it: --ink ground,
   --paper type, and both accents swapped for their dark-surface counterparts.
   The numbers in the scrim note below are measured off the composited pixels,
   not off a token pair — --petrol on this ground is 1.72:1 and unusable. */
.p-hero {
  background: var(--ink);
  color: var(--paper);
  padding: 80px 0 72px;
  position: relative;
  overflow: hidden;
  isolation: isolate;     /* keeps the scrim under the text without z-index on everything */
}
.p-hero__bg {
  position: absolute;
  inset: 0;
  z-index: -1;
}
.p-hero__bg img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Bottom. At a 1280px viewport the hero box is 1280x696 and this image scales
     to 1280x853, so there is 157px of VERTICAL slack and none horizontal — the
     horizontal half of this property does nothing at desktop width and bites
     only on narrow viewports. (The same trap as on /research/, where a first
     pass set a horizontal bias that could not have had any effect.)

     Contrast did NOT decide this, and that is worth recording so nobody
     re-derives it. Measured behind the real headline box, worst-case pixel,
     against --paper: top 9.22:1, centre 9.25:1, bottom 9.22:1. The slack is
     157px out of 853 and the headline sits over the middle of the frame at any
     of the three, so the three are the same picture to within a rounding error.

     What decides it is what fills the box: taking the bottom keeps the palm
     line and the grassland, and pushes the empty top of the sky out of frame.
     Sky is the half of this photograph with nothing in it. */
  object-position: 50% 100%;
  display: block;
}
/* THE SCRIM, and why it is shaped the way it is.
   This frame is the inverse of the research hero's. There the picture is
   mid-tone canopy edge to edge and the scrim is a near-flat 0.86/0.74/0.88.
   Here the top third of the source measures 165/255 mean luminance against the
   bottom third's 72 — a bright sky over dark grassland — and the headline sits
   high in the box. A flat scrim either drowns the grass or leaves the sky too
   light for --paper type.

   So it is graded to match: heaviest at the top where the sky is, lifting
   through the middle where the palm line runs, and closing again at the bottom
   so the collage's tiles do not float on bare photograph.

   Measured on the composited pixels behind the real text boxes — the lightest
   pixel under each, which is the worst case for light type. Re-measured at BOTH
   widths on 19 August 2026 under the lightened scrim; desktop 1280x720 shown,
   and 375x812 is looser on every row (the mobile crop takes the big palm at the
   frame's left edge, which is darker than the sky the desktop crop keeps):

     eyebrow     --saffron-lift   4.84:1   AA yes (11px, so small text: 4.5)
     headline    --paper          8.87:1   AA yes, AAA yes (large text)
     headline    --petrol-lift    3.40:1   AA yes for large text (3:1)
     lead        --paper          6.62:1   AA yes (22px, small text: 4.5)

   THE BINDING CONSTRAINT IS THE EYEBROW, NOT THE <em>. This file got that right
   when the others got it wrong: /research/ and /news/ both claimed the <em> was
   binding, and re-measuring on 19 August 2026 found the 11px eyebrow was tighter
   on every scrimmed hero on the site, this one included.

   What changed here on that date is the eyebrow's COLOUR, not the finding. It is
   --saffron-lift now rather than --saffron, which is the fix this note was
   pointing at without naming: the curve was steep near the base token
   (0.85/0.74/0.81 put it at 4.77 and 0.84/0.72/0.80 at 4.49, a fail), so the
   scrim had almost nothing to give. Lifting the eyebrow moved the cap from
   -0.011 to -0.053 of alpha, and the scrim below is the result.

   The scrim is nonetheless LIGHTER than the research page's, and deliberately.
   Structure — the standard deviation of luminance under the headline, higher
   meaning more of the picture visible — keeps this frame ahead of that one by
   about two to one however it is measured. This frame has a horizon in it and
   can afford to be seen; that one is flat canopy and cannot. Both rose in the
   19 August lightening and the ratio between them held.

   The source carries no contrast boost, deliberately — see the docstring in
   tools/make-publications-hero.py, which explains why the research hero's 1.35
   would be actively wrong on this frame. */
.p-hero__bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg,
      rgba(10, 13, 18, 0.81) 0%,
      rgba(10, 13, 18, 0.70) 55%,
      rgba(10, 13, 18, 0.77) 100%);
}
.p-hero__grid {
  display: grid;
  grid-template-columns: 1.15fr 1fr;
  gap: 56px;
  align-items: stretch;
  position: relative;
}
.p-hero__left {
  display: flex;
  flex-direction: column;
  justify-content: center;
}
/* --saffron-lift, not --saffron: at 11px this is small text and needs 4.5:1,
   and it is the binding constraint on this hero. See the scrim note above. */
.p-hero__eyebrow { margin-bottom: 22px; color: var(--saffron-lift); }
.p-hero__title {
  font-family: var(--display);
  font-size: clamp(56px, 7vw, 108px);
  line-height: 0.94;
  letter-spacing: -0.026em;
  font-weight: 400;
  color: var(--paper);
  margin-bottom: 28px;
  text-wrap: balance;
}
/* No accent word here. "Our <em>published works.</em>" was --petrol-lift until
   22 August 2026; Joel asked for every hero headline to read in plain --paper
   with no colour and no italics. The eyebrow above is still the binding
   constraint on this hero — see the scrim note. */
.p-hero__lead {
  font-family: var(--display);
  font-size: clamp(20px, 1.7vw, 23px);
  line-height: 1.4;
  color: var(--paper);
  max-width: 48ch;
  margin-bottom: 16px;
}
/* The Google Scholar link in the lead. It was inheriting the global link rule,
   which is built for light grounds; on the scrim it has to be --paper with the
   underline carrying the "this is a link" job, since a colour shift alone would
   have to come from a dark-surface accent and both of those are spoken for in
   this hero (--saffron on the eyebrow, --petrol-lift on the headline). */
.p-hero__lead a {
  color: var(--paper);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: rgba(239, 236, 228, 0.5);
}
.p-hero__lead a:hover { text-decoration-color: var(--paper); }
.p-hero__body {
  font-size: 15px;
  line-height: 1.6;
  color: var(--steel);
  max-width: 52ch;
  margin-bottom: 32px;
}
/* .p-hero__filters held two tags, "By theme" and "Books". Both went on
   13 August 2026 with the arrival of the sticky section nav, which reaches five
   destinations from anywhere on the page instead of two from the top. The
   global .tag classes they used are not touched — research.njk, post.njk and
   collective.css all still use them. */
/* --- Cover collage in the hero ----------------------------------------- */
/* Replaces the counts-by-type panel that stood here. The count of covers is
   whatever _data/covers.js finds in assets/img/covers/, so this has to lay out
   an unknown number of items: auto-fill with a minimum column width rather
   than a fixed column count, which keeps the tiles a sensible size whether
   there are three of them or thirty.

   Covers are not a uniform shape — journal issues, monographs and edited
   volumes all differ — so each tile fixes the aspect ratio and crops with
   object-fit rather than letting the grid go ragged. */
/* 96px, not 126. At 126 the twenty covers fall into three columns and seven
   rows, which makes the hero about 1400px tall and strands the headline
   vertically centred against a wall of thumbnails. At 96 the same twenty land
   in five columns and four rows, and the collage finishes at roughly the height
   of the text beside it. auto-fill still does the work if the count changes. */
.p-hero__covers {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  gap: 10px;
  align-content: start;
}
/* The tile frame moved to dark-surface values with the hero on 18 August 2026.
   --rule and --paper-2 are light-ground tokens: on the scrimmed photograph the
   border read as a bright box around every cover and the ground behind a
   letterboxed one glowed. These are the same two values .p-book__cover uses in
   the dark books section further down, so the two walls of covers on this page
   are framed alike. */
.p-cover {
  aspect-ratio: 3 / 4;
  overflow: hidden;
  border-radius: 3px;
  border: 1px solid rgba(243,235,221,0.12);
  background: rgba(243,235,221,0.06);
  /* The tiles are a field, not a gallery: a slight lift on hover says the
     collage is one object rather than a set of controls. */
  transition: transform .25s ease, box-shadow .25s ease;
}
.p-cover img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.p-hero__covers:hover .p-cover { opacity: 0.72; }
.p-hero__covers .p-cover:hover {
  opacity: 1;
  transform: translateY(-3px);
  box-shadow: 0 10px 24px rgba(17,21,28,0.16);
}
.p-cover, .p-hero__covers:hover .p-cover { transition: opacity .25s ease, transform .25s ease, box-shadow .25s ease; }

@media (prefers-reduced-motion: reduce) {
  .p-cover { transition: none; }
  .p-hero__covers .p-cover:hover { transform: none; }
}

.p-section-head {
  display: grid;
  grid-template-columns: 1fr 1.5fr;
  gap: 56px;
  align-items: end;
  margin-bottom: 48px;
}
.p-section-head__title { max-width: 22ch; }
.p-section-head__body {
  font-size: 16px;
  line-height: 1.6;
  color: var(--steel);
  max-width: 56ch;
}

/* --- Why the light-surface accent here is --petrol ---------------------- */
/* The "New & recent" section stood here and was deleted on 13 August 2026 at
   Joel's instruction; its ~180 lines of .p-recent rules went with it, and every
   publication it carried is still listed under .p-themes below. Its
   .p-recent-card__kind and .p-recent-card__link — and, before that section moved
   to news.css on 11 August 2026, .p-press-card__outlet and
   .p-press-card__foot__link — were all --saffron on a light ground: 1.88:1 on
   --paper and 1.73:1 on --paper-2. That is the failure named at the top of
   styles.css — --saffron belongs on dark surfaces only, where it is 8.25:1.
   --petrol is the light-surface accent: 9.01:1 on --paper, 8.28:1 on --paper-2.

   The --saffron left in this file is all inside .p-books, which is --ink. That
   is correct and should stay. Measure before moving any of it. */

.p-books {
  background: var(--ink);
  color: var(--paper);
  padding: 96px 0;
  overflow: hidden;
}
.p-books .p-section-head__body { color: rgba(243,235,221,0.7); }
/* The section used to be a two-column layout — intro copy and a metrics panel
   on the left, a 2x2 card grid on the right. It is now a heading over three
   cards running across the page, so the layout and metrics rules are gone and
   this is all that is left of the intro. */
.p-books__head {
  max-width: 46ch;
  margin-bottom: 40px;
}
.p-books__intro__title {
  font-family: var(--display);
  font-size: clamp(32px, 3.4vw, 46px);
  line-height: 1.05;
  letter-spacing: -0.018em;
  font-weight: 400;
  color: var(--paper);
  text-wrap: balance;
}

.p-books__list {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
  align-items: stretch;
}
.p-book {
  padding: 18px;
  border-radius: var(--r-card-lg);
  border: 1px solid rgba(243,235,221,0.12);
  background: rgba(255,255,255,0.04);
  display: flex; flex-direction: column; gap: 18px;
  transition: background .2s, border-color .2s;
}
.p-book:hover {
  background: rgba(255,255,255,0.06);
  border-color: rgba(243,235,221,0.24);
}
/* Was a 4:3 gradient panel with the title set into it, standing in for artwork
   that did not exist. The real covers are portrait, so the ratio flips with
   them: `contain` on a --paper mat rather than `cover`, because a cover cropped
   to fill loses the top or bottom of its own design, and these are not all the
   same shape — a monograph, a journal issue and a special issue. */
.p-book__cover {
  aspect-ratio: 3 / 4;
  border-radius: 4px;
  overflow: hidden;
  background: rgba(243,235,221,0.06);
  border: 1px solid rgba(243,235,221,0.12);
}
.p-book__cover img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}

.p-book__meta { display: flex; flex-direction: column; gap: 10px; }
.p-book__kind {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--saffron);
}
.p-book__title {
  font-family: var(--display);
  font-size: 22px;
  font-weight: 500;
  line-height: 1.15;
  letter-spacing: -0.012em;
  color: var(--paper);
  text-wrap: balance;
}
.p-book__sub {
  font-size: 13px;
  line-height: 1.55;
  color: rgba(243,235,221,0.7);
}
.p-book__foot {
  margin-top: auto;
  padding-top: 14px;
  border-top: 1px solid rgba(243,235,221,0.1);
  display: flex; justify-content: space-between; align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}
.p-book__year {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.14em;
  color: rgba(243,235,221,0.55);
}
.p-book__link {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--saffron);
  display: inline-flex; align-items: center; gap: 8px;
  text-decoration: none;
}
.p-book__link:hover { color: var(--paper); opacity: 1; }

/* --- By thematic area -------------------------------------------------- */
/* Sits on --paper-2, one step down from the --paper-3 of the section nav
   directly above it. It used to be one step down from the hero, which was
   --paper; since 18 August 2026 the hero is dark over a photograph, so the bar
   is now the only thing this section has to distinguish itself from, and the
   step between them still does it.
   --paper-3 was the other candidate and is rejected: it puts --steel at 4.50:1
   exactly, and
   this file has too much history of landing on the line to choose a ground
   with nothing spare. On --paper-2, --steel is 4.94:1 and --ink-soft 10.17:1.

   The section was briefly on --ink; that is why the tokens below are spelled
   out rather than inherited. */
.p-themes {
  padding: 96px 0;
  background: var(--paper-2);
  position: relative;
  overflow: hidden;
}
.p-themes .container { position: relative; z-index: 1; }

.p-theme {
  padding: 36px 0;
  border-top: 1px solid var(--rule-strong);
}
.p-theme:last-child { border-bottom: 1px solid var(--rule-strong); }
.p-theme__head {
  display: grid;
  grid-template-columns: 1fr 1.6fr;
  gap: 56px;
  align-items: start;
  margin-bottom: 28px;
}
/* Same inversion the research line cards had, fixed the same way on 3 August
   2026 so the two pages agree. The category was a 10.5px mono label in
   --saffron — 1.88:1 on --paper, the failure CLAUDE.md names — sitting above a
   38px --ink clause at 15.50:1, so the eye went to the clause and the theme
   itself was the least legible thing in the block.

   Now: quiet mono index in --petrol (9.01:1), category as the h3, clause
   demoted beneath it. */
.p-theme__num {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--petrol);
  margin-bottom: 10px;
}
.p-theme__title {
  font-family: var(--display);
  font-size: clamp(28px, 2.8vw, 38px);
  line-height: 1.08;
  letter-spacing: -0.016em;
  font-weight: 500;
  color: var(--ink);
  text-wrap: balance;
  /* 22ch, not 18ch. The h3 is now the category, and "Indigenous rights to land
     & territory" is 37 characters where the clauses it replaced were shorter. */
  max-width: 22ch;
}
.p-theme__sub {
  font-size: 15px;
  line-height: 1.4;
  font-weight: 500;
  color: var(--ink-soft);
  margin-top: 12px;
  max-width: 40ch;
}
.p-theme__body {
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--steel);
  max-width: 54ch;
  padding-top: 10px;
}
.p-theme__list { display: flex; flex-direction: column; }
.p-pub {
  display: grid;
  grid-template-columns: 64px 1fr auto;
  gap: 28px;
  align-items: center;
  padding: 22px 0;
  border-top: 1px solid var(--rule);
  transition: padding .2s ease;
}
.p-pub:first-child { border-top: 1px solid var(--rule-strong); }
.p-pub:hover { padding-left: 8px; padding-right: 8px; }
.p-pub__year {
  font-family: var(--mono);
  font-size: 13px;
  letter-spacing: 0.06em;
  color: var(--steel);
}
.p-pub__main { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.p-pub__title {
  font-family: var(--display);
  font-size: 19px;
  line-height: 1.25;
  letter-spacing: -0.012em;
  color: var(--ink);
  text-wrap: balance;
}
.p-pub__meta {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--steel);
  display: flex; gap: 14px; flex-wrap: wrap; align-items: center;
}
/* NOT --saffron. It was --saffron here on --paper and measured 1.88:1, the
   failure named at the top of styles.css, and on --paper-2 it is 1.73:1 —
   worse. --petrol is the light-surface accent, 8.28:1 on this ground. It
   matches .p-theme__num, which is fine: one is a per-theme index and this is a
   per-row kind label, different sizes in different places. */
.p-pub__meta__kind { color: var(--petrol); }
.p-pub__meta .dot { color: var(--rule-strong); }
.p-pub__meta__venue {
  font-family: var(--body);
  font-size: 12.5px;
  letter-spacing: 0.005em;
  text-transform: none;
  color: var(--ink-soft);
  font-style: italic;
}
.p-pub__btn {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 9px 16px;
  border-radius: var(--r-pill);
  border: 1px solid var(--rule-strong);
  background: var(--paper);
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-soft);
  transition: background .2s, color .2s, border-color .2s;
  white-space: nowrap;
  text-decoration: none;
}
.p-pub__btn:hover {
  background: var(--ink);
  color: var(--paper);
  border-color: var(--ink);
  opacity: 1;
}
.p-pub__btn svg { width: 11px; height: 11px; }

/* The press section moved to the Radio So'o page on 11 August 2026, renamed
   Recognition & coverage. Its rules went with it, re-prefixed n-, and live in
   news.css. */

@media (max-width: 1100px) {
  .p-hero__grid,
  .p-section-head,
  .p-theme__head { grid-template-columns: 1fr; gap: 32px; }
  .p-books__list { grid-template-columns: 1fr 1fr; }

  /* The horizontal half of object-position finally does something here, and it
     has to. Once the grid stacks, the collage sits below the text instead of
     beside it and the hero goes very tall — 1552px at 375 wide, and 1605 when
     this was written, before the headline lost a line. A 3:2 image
     covering a box that shape is scaled to the HEIGHT, so the crop is a narrow
     vertical slice: 375px out of 2408, one sixth of the frame.

     Centred, that slice lands on open sky and the text sits on almost nothing —
     structure (stdev of luminance behind the text block) 5.07. The left edge of
     this frame is where the big karanda'y palm stands, and taking the slice
     there raises it to 12.60 at 25% and 12.92 at 0%. 25%, because 0% pins the
     picture to the literal edge of the frame and leaves nothing in hand if the
     image is ever re-cut.

     Contrast is unaffected either way and stays well clear. At 375x1605:
     eyebrow --saffron 5.81:1, headline --paper 10.10:1, its <em> --petrol-lift
     5.41:1, lead --paper 9.39:1. Re-measured at 375x1552 on 18 August 2026:
     5.94, 10.30, 5.53, 9.69. All higher than at desktop, because the slice has
     no bright sky in it. */
  .p-hero__bg img { object-position: 25% 100%; }
}
@media (max-width: 720px) {
  .p-books__list,
  .p-pub { grid-template-columns: 1fr; gap: 10px; padding: 18px 0; }
  .p-pub__btn { justify-self: flex-start; }
}
