/* Syncterface Media — static site
 *
 * Design language: "Tactile Editorial", adapted from the Ink & Iron export
 * (_inkiron/). Taken from it: sharp corners, hairline ink rules, oversized
 * Instrument Serif display type with italic accents, uppercase wide-tracked
 * micro-labels, edge-to-edge gutters instead of a centred column, and inverted
 * dark bands.
 *
 * NOT taken from it: the palette. The export's warm clay (#B45309) is replaced
 * by our steel blue, which comes from the logo, so the identity stays ours.
 * The role mapping is:
 *     paper  -> --paper       (near-identical to the export's #F9F7F2)
 *     ink    -> --ink / --navy
 *     clay   -> --steel       (accent: italic display words, labels, hovers)
 *
 * The export is Tailwind v4. This is hand-written CSS on purpose: Cloudflare's
 * build command must stay empty (see README), so there is no compile step.
 */

:root {
  --navy: #152232;
  --steel: #2f6f95;
  --steel-lt: #7fb3d0;
  --paper: #fbfaf8;
  --paper-alt: #f2efe9;
  --ink: #1d2733;
  --ink-soft: #56616e;
  --line: #e2ddd4;
  --gold: #b8873b;

  /* Tactile Editorial is square-edged; this is the "iron" in the name. */
  --radius: 0px;
  --wrap: 1680px;
  --gutter: clamp(1.25rem, 4vw, 3rem);

  --serif: "Instrument Serif", "Lora", Georgia, "Times New Roman", serif;
  --sans: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;

  --rule: 1px solid var(--line);
  --rule-ink: 1px solid var(--ink);
  --shadow: none;
  --shadow-lg: none;
}

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

/* rem basis. This MUST match the body size: `rem` resolves against <html>,
   not <body>, so setting body to 17px while html stayed at the browser's 16px
   default silently shrank every rem-based rule by ~6% — and the sub-1rem
   content rules compounded it until package features rendered at 14.4px beside
   17px body text. Change this and the body rule together, never one alone. */
html {
  font-size: 17px;
  -webkit-text-size-adjust: 100%; scroll-behavior: smooth;
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
  }
}

/* THE `hidden` ATTRIBUTE MUST ACTUALLY HIDE. `display: none` for [hidden]
   comes from the browser's own stylesheet, and ANY author rule setting
   `display` beats it no matter how weak its selector — so `.card { display:
   flex }` quietly made el.hidden = true a no-op.

   That is not theoretical. It shipped broken: the bookstore filter set the
   attribute on every non-matching card, updated the label to "0 of 45 books",
   and left all 45 cards on screen. `#results` (.grid.cards), the ISBN row on a
   two-binding book and the outstanding-balance row on the package
   confirmation (.meta > div) all failed the same way.

   !important rather than a more specific selector, because the losing side is
   whatever `display` a component happens to declare — every new component
   would reintroduce the bug, which is what the per-component [hidden] rules
   further down this file are all patching one at a time. Toggle visibility
   with el.hidden and this rule, never by writing style.display. */
[hidden] { display: none !important; }

/* ============================================================== motion ====
   Parallax and scroll-reveal come from assets/js/motion.js: one rAF-throttled
   scroll handler writing transforms, plus an IntersectionObserver for reveals.

   Motion is opt-in: `.js-motion` is set on <html> by an inline script in the
   head, and only when the visitor has not asked for reduced motion. With JS
   off, or with reduced motion, every element renders in its final state. That
   script carries a 2.5s failsafe: if motion.js never sets data-motion="ready"
   the class is stripped, so a failed script request cannot leave the page
   permanently blank.

   Testing note: headless Chrome starves requestAnimationFrame entirely, so
   scroll-linked motion cannot be exercised there. Judge it in a real browser.
   ========================================================================= */

.js-motion [data-reveal],
.js-motion [data-reveal-group] > * { opacity: 0; transform: translateY(22px); }
.js-motion [data-reveal].is-revealed,
.js-motion [data-reveal-group].is-revealed > * {
  opacity: 1; transform: none;
  transition: opacity .8s ease, transform .8s cubic-bezier(.22, .61, .36, 1);
}
.js-motion [data-reveal-group].is-revealed > *:nth-child(2) { transition-delay: .07s; }
.js-motion [data-reveal-group].is-revealed > *:nth-child(3) { transition-delay: .14s; }
.js-motion [data-reveal-group].is-revealed > *:nth-child(4) { transition-delay: .21s; }
.js-motion [data-reveal-group].is-revealed > *:nth-child(5) { transition-delay: .28s; }
.js-motion [data-reveal-group].is-revealed > *:nth-child(n+6) { transition-delay: .35s; }
.js-motion [data-parallax] { will-change: transform; }

/* ------------------------------------------------------------ foundation */
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font: 400 1rem/1.6 var(--sans);   /* 1rem == 17px, see the html rule */
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; height: auto; display: block; }
a { color: var(--steel); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { color: var(--ink); }

h1, h2, h3 {
  font-family: var(--serif); font-weight: 400; color: var(--ink);
  margin: 0 0 .4em; letter-spacing: -.02em; line-height: .95;
}
h1 { font-size: clamp(2.9rem, 1.6rem + 6.2vw, 7.5rem); }
h2 { font-size: clamp(2rem, 1.4rem + 2.6vw, 3.4rem); }
h3 { font-family: var(--serif); font-size: 1.35rem; line-height: 1.15; }
p { margin: 0 0 1em; }
em, .italic { font-style: italic; }

/* Edge-to-edge gutters rather than a narrow centred column. */
.wrap {
  width: 100%; max-width: var(--wrap); margin-inline: auto;
  padding-inline: var(--gutter);
}
.wrap.narrow { max-width: calc(820px + 2 * var(--gutter)); }
.col-narrow { max-width: 760px; }
.center { text-align: center; }

.split > *, .contact-grid > *, .detail-grid > *, .grid.cards > *,
.foot-grid > *, .pkgs > * { min-width: 0; }

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--ink); color: var(--paper); padding: .7rem 1.1rem;
}
.skip:focus { left: 0; }

:where(a, button, input, select, summary):focus-visible {
  outline: 2px solid var(--steel); outline-offset: 3px;
}

/* The signature micro-label: tiny, uppercase, widely tracked, in accent. */
.kicker {
  font-size: .7rem; font-weight: 600; text-transform: uppercase;
  letter-spacing: .22em; color: var(--steel); margin: 0 0 1.2rem;
}
.lede { font-size: 1.1rem; line-height: 1.65; color: var(--ink-soft); max-width: 52ch; }

/* ---------------------------------------------------------------- header */
.site-head {
  position: sticky; top: 0; z-index: 50;
  background: rgba(251, 250, 248, .92);
  backdrop-filter: saturate(1.3) blur(10px);
  border-bottom: var(--rule);
}
.head-inner {
  display: flex; align-items: center; gap: clamp(1rem, 3vw, 3rem);
  min-height: 80px; padding-block: .9rem;
}
.brand { flex: none; display: block; }
.brand-img, .brand img { width: 118px; height: auto; }

.nav { margin-left: auto; }
.nav ul { display: flex; gap: clamp(1.4rem, 2.6vw, 2.8rem); list-style: none; margin: 0; padding: 0; }
.nav a {
  color: var(--ink); text-decoration: none;
  font-size: .72rem; font-weight: 500; text-transform: uppercase; letter-spacing: .16em;
  padding: .4rem 0; display: block; transition: color .18s ease;
}
.nav a:hover, .nav a[aria-current] { color: var(--steel); }
.nav a[aria-current] { border-bottom: 1px solid var(--steel); }

/* ------------------------------------------------------- nav submenus ---- */
.nav .has-sub { position: relative; }
.nav-sub-toggle {
  display: inline-flex; align-items: center; gap: .4rem;
  font: 500 .72rem var(--sans); text-transform: uppercase; letter-spacing: .16em;
  color: var(--ink); background: transparent; border: 0; cursor: pointer;
  padding: .4rem 0; transition: color .18s ease;
}
.nav-sub-toggle:hover, .has-sub.open > .nav-sub-toggle { color: var(--steel); }
.has-sub[data-section-current] > .nav-sub-toggle {
  color: var(--steel); border-bottom: 1px solid var(--steel);
}
.nav-sub-toggle svg { transition: transform .18s ease; }
.has-sub.open > .nav-sub-toggle svg { transform: rotate(180deg); }

/* `.nav ul { display: flex }` is specificity (0,1,1) and silently beat a bare
   `.nav-sub { display: none }` at (0,1,0) — the dropdown rendered permanently
   open, inline, as a flex row. Every rule here is scoped under .nav so it
   outranks that one.

   Right-aligned, not left: these are the last items in the bar, so a menu
   growing rightwards runs off the viewport. */
.nav .nav-sub {
  position: absolute; top: calc(100% + .5rem); right: 0; left: auto; z-index: 60;
  min-width: 15rem; margin: 0; padding: .4rem 0; list-style: none;
  background: var(--paper); border: var(--rule-ink);
  display: none; flex-direction: column; gap: 0;
}
.nav .has-sub.open > .nav-sub { display: block; }
/* Hover is a convenience on pointer devices only — click/keyboard drives the
   real state, so touch and keyboard users are never stranded. */
@media (hover: hover) and (min-width: 981px) {
  .nav .has-sub:hover > .nav-sub { display: block; }
}
.nav-sub a {
  display: block; padding: .7rem 1.1rem; letter-spacing: .1em;
  border-bottom: 0; white-space: nowrap;
}
.nav-sub a:hover { background: var(--paper-alt); color: var(--steel); }
.nav-sub a[aria-current] { color: var(--steel); }

.nav-toggle {
  display: none; width: 42px; height: 42px; border: var(--rule-ink);
  background: transparent; cursor: pointer; padding: 12px 10px;
  flex-direction: column; justify-content: space-between;
}
.nav-toggle span { display: block; height: 1px; background: var(--ink); }

@media (max-width: 980px) {
  .nav-toggle { display: flex; margin-left: .4rem; }
  .nav {
    position: absolute; inset: 80px 0 auto; background: var(--paper);
    border-bottom: var(--rule-ink); display: none;
  }
  .nav.open { display: block; }
  .nav ul { flex-direction: column; gap: 0; padding: .5rem var(--gutter) 1.5rem; }
  .nav a { padding: .95rem 0; border-bottom: var(--rule); letter-spacing: .18em; }
  .nav a[aria-current] { border-bottom: var(--rule); color: var(--steel); }

  /* In the mobile sheet the submenu nests inline rather than floating — there
     is no room to overlay, and a dropped panel over a full-width list reads as
     a separate page. */
  .nav .has-sub { position: static; }
  .nav-sub-toggle {
    width: 100%; justify-content: space-between; padding: .95rem 0;
    border-bottom: var(--rule); letter-spacing: .18em;
  }
  .has-sub[data-section-current] > .nav-sub-toggle { border-bottom: var(--rule); }
  .nav .nav-sub {
    position: static; min-width: 0; border: 0; padding: 0 0 .4rem 1rem;
    background: transparent; right: auto;
  }
  .nav .nav-sub a { padding: .75rem 0; font-size: .72rem; }
}
@media (max-width: 480px) {
  .head-inner { min-height: 66px; gap: .5rem; }
  .brand-img, .brand img { width: 142px; }
  .nav { inset: 66px 0 auto; }
  .nav-toggle { width: 38px; height: 38px; padding: 11px 9px; }
}

/* ---------------------------------------------------------------- blocks */
.band { padding-block: clamp(3.5rem, 8vw, 8rem); }
.band.alt { background: var(--paper-alt); }

.section-head {
  display: flex; align-items: end; justify-content: space-between;
  gap: 1.5rem; margin-bottom: clamp(2.5rem, 5vw, 4.5rem); flex-wrap: wrap;
  border-bottom: var(--rule); padding-bottom: 1.4rem;
}
.section-head h2 { margin: 0; font-style: italic; }
/* No `white-space: nowrap` here, deliberately. This label carries a live count
   ("View full catalogue - all 39 titles"), so nowrap made it a rigid box that
   grows with the catalogue AND with any change to the type scale. It sat one
   character inside 320px until the rem basis was corrected, then pushed the
   homepage 31px wide. Wrapping on a narrow screen beats overflowing on one. */
.more {
  font-size: .7rem; font-weight: 500; text-transform: uppercase; letter-spacing: .18em;
  text-decoration: none; color: var(--ink-soft);
}
.more:hover { color: var(--steel); }

/* Inverted page masthead. */
.page-head {
  background: var(--navy); color: var(--paper);
  padding-block: clamp(3.5rem, 8vw, 7rem);
}
.page-head h1 { color: var(--paper); margin-bottom: .3rem; }
.page-head .kicker { color: var(--steel-lt); }
.page-head .lede { color: rgba(251, 250, 248, .62); margin: 0; }

.prose { max-width: 66ch; }
.prose h2 { margin-top: 2.4rem; font-style: italic; }
.prose p { color: var(--ink-soft); line-height: 1.75; }
.narrow.prose, .prose.narrow { max-width: 66ch; }
.archive-note {
  border-left: 2px solid var(--gold); padding: .2rem 0 .2rem 1.4rem;
  font-size: .92rem; color: var(--ink-soft); font-style: italic;
}
.fineprint { font-size: .95rem; color: var(--ink-soft); margin-top: 2rem; }

/* --------------------------------------------------------------- buttons */
/* Square, hairline, invert on hover — the export's defining control. */
.btn {
  display: inline-block; padding: .95rem 2rem; border-radius: 0;
  font: 500 .72rem/1 var(--sans); text-transform: uppercase; letter-spacing: .16em;
  text-decoration: none; border: 1px solid var(--ink); cursor: pointer;
  background: transparent; color: var(--ink);
  transition: background .2s ease, color .2s ease, border-color .2s ease;
}
.btn-primary { background: var(--ink); color: var(--paper); }
.btn-primary:hover { background: var(--steel); border-color: var(--steel); color: var(--paper); }
.btn-ghost { background: transparent; color: var(--ink); }
.btn-ghost:hover { background: var(--ink); color: var(--paper); }
.cta-row { display: flex; gap: .9rem; flex-wrap: wrap; margin: 2rem 0 0; }

/* ------------------------------------------------------------------ hero */
.hero { position: relative; isolation: isolate; overflow: clip; padding-block: clamp(3.5rem, 9vw, 9rem) 0; }
.hero-glow {
  position: absolute; inset: -25% -10% auto; height: 120%; z-index: -1; pointer-events: none;
  background:
    radial-gradient(46rem 30rem at 14% 6%, rgba(127, 179, 208, .20), transparent 62%),
    radial-gradient(30rem 22rem at 92% 0%, rgba(184, 135, 59, .12), transparent 60%);
}
.hero-grain { position: absolute; inset: 0; z-index: -1; pointer-events: none; }

.hero-inner { display: grid; gap: 2.5rem; align-items: end; }
@media (min-width: 900px) {
  .hero-inner { grid-template-columns: repeat(12, 1fr); gap: 3rem; }
  .hero-copy { grid-column: span 8; }
  .hero-aside { grid-column: span 4; }
}
.hero-copy h1 { margin: 0; }
.hero-copy h1 .accent { font-style: italic; color: var(--steel); }
.hero-aside { display: flex; flex-direction: column; gap: 1.6rem; }
.hero-aside .lede { margin: 0; }
.hero-rule { height: 1px; width: 100%; background: var(--line); }
.hero-meta {
  font-size: .7rem; font-weight: 600; text-transform: uppercase;
  letter-spacing: .2em; color: var(--steel); margin: 0;
}
.hero-art { margin-top: clamp(2.5rem, 6vw, 5rem); }
.hero-art picture, .hero-art img { display: block; width: 100%; }
.hero-art img { border: var(--rule); }

/* ------------------------------------------------- inverted showcase band */
.showcase {
  position: relative; isolation: isolate; overflow: clip;
  background: var(--navy); color: var(--paper);
  padding-block: clamp(4rem, 9vw, 8rem);
}
.showcase-bg { position: absolute; inset: -18% 0; z-index: -2; }
.showcase-bg img { width: 100%; height: 100%; object-fit: cover; display: block; }
.showcase::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(100deg, rgba(15, 25, 38, .96) 24%, rgba(21, 34, 50, .78) 100%);
}
.showcase h2 { color: var(--paper); max-width: 16ch; font-style: italic; }
.showcase .kicker { color: var(--steel-lt); }
.showcase p { color: rgba(251, 250, 248, .68); max-width: 50ch; }
.showcase .btn-primary { background: var(--paper); color: var(--ink); border-color: var(--paper); }
.showcase .btn-primary:hover { background: var(--steel-lt); border-color: var(--steel-lt); color: var(--ink); }
.showcase .btn-ghost { border-color: rgba(251, 250, 248, .45); color: var(--paper); }
.showcase .btn-ghost:hover { background: var(--paper); color: var(--ink); }
.showcase-stats {
  display: flex; flex-wrap: wrap; gap: clamp(2rem, 6vw, 5rem);
  margin-top: 3.5rem; padding-top: 2.2rem; border-top: 1px solid rgba(251, 250, 248, .18);
}
.showcase-stats dt {
  font-family: var(--serif); font-size: clamp(2.2rem, 1.4rem + 2.4vw, 3.4rem);
  color: var(--paper); line-height: 1;
}
.showcase-stats dd {
  margin: .6rem 0 0; font-size: .68rem; letter-spacing: .2em;
  text-transform: uppercase; color: rgba(251, 250, 248, .5);
}

/* ----------------------------------------------------------------- cards */
.grid.cards {
  display: grid; gap: clamp(2rem, 4vw, 3.5rem) clamp(1.5rem, 2.5vw, 2.5rem);
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
}
.card { display: flex; flex-direction: column; height: 100%; }
/* Homepage feature row: three large editions, as in the export. */
.grid.cards.feature { grid-template-columns: 1fr; }
@media (min-width: 700px) { .grid.cards.feature { grid-template-columns: repeat(3, 1fr); gap: clamp(2rem, 4vw, 4rem); } }
.grid.cards.feature .card-media { aspect-ratio: 3 / 4; padding: clamp(.9rem, 1.8vw, 1.5rem); }
.grid.cards.feature .card-body h3 { font-size: 1.5rem; }
.card-media {
  display: grid; place-items: center; overflow: hidden;
  /* build.py trims the transparent padding baked into the source PNGs, which
     leaves the mockups roughly 3:4 portrait — so a portrait tile now fits them
     tightly instead of stranding them. Padding is deliberately small: the tile
     is a frame around the cover, not a mount. */
  aspect-ratio: 3 / 4; background: var(--paper-alt); border: var(--rule);
  padding: clamp(.6rem, 1.2vw, 1rem);
  transition: transform .5s cubic-bezier(.22, .61, .36, 1);
}
.card-media:hover { transform: translateY(-8px); }
.card-media picture { display: contents; }
/* Our covers are 3D mockups on a light ground, not flat 2:3 artwork, so they
   are contained inside the tile rather than cropped to fill it. */
 /* Fill the padded box and letterbox inside it. Without width/height the img
    sits at its intrinsic size, which `sizes` pins to the slot width — that is
    what left the covers at two-thirds scale.
    min-height/min-width 0 is required: a grid item defaults to min-height:auto,
    which lets a replaced element push past its track, and overflow:hidden then
    crops the artwork (it clipped the foot off the taller flat covers). */
.card-media img {
  width: 100%; height: 100%; min-width: 0; min-height: 0; object-fit: contain;
}
.card-body { padding-top: 1.1rem; display: flex; flex-direction: column; flex: 1; }
.card-body h3 { font-size: 1.15rem; margin: 0 0 .3rem; }
.card-body h3 a { color: var(--ink); text-decoration: none; }
.card-body h3 a:hover { color: var(--steel); }
.byline { font-size: .92rem; font-style: italic; color: var(--ink-soft); margin: 0 0 .7rem; }
.byline.big { font-size: 1.15rem; margin-bottom: 1.6rem; }
.price { font-size: 1rem; font-weight: 500; color: var(--ink); font-variant-numeric: tabular-nums; }
.muted { color: var(--ink-soft); }
.card-buy {
  display: flex; align-items: center; justify-content: space-between; gap: .75rem;
  margin-top: auto; padding-top: .5rem;
}

/* ----------------------------------------------------------------- chips */
.chips { display: flex; flex-wrap: wrap; gap: 0; border-top: var(--rule); }
.chip {
  display: inline-flex; align-items: baseline; gap: .6rem;
  padding: .9rem 1.5rem .9rem 0; margin-right: 1.5rem;
  text-decoration: none; color: var(--ink); font-size: .95rem;
  border-bottom: var(--rule); flex: 1 1 auto; min-width: 190px;
  transition: color .18s ease;
}
.chip span {
  color: var(--ink-soft); font-size: .72rem; letter-spacing: .12em;
  font-variant-numeric: tabular-nums; margin-left: auto;
}
.chip:hover { color: var(--steel); }

/* ----------------------------------------------------------- split lists */
.split { display: grid; gap: 3rem; align-items: start; }
@media (min-width: 900px) { .split { grid-template-columns: 5fr 6fr; gap: clamp(3rem, 8vw, 7rem); } }

.offer-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0; }
.offer-list li { padding: 1.4rem 0; border-top: var(--rule); }
.offer-list li:last-child { border-bottom: var(--rule); }
.offer-list h3 {
  margin: 0 0 .35rem; font-family: var(--sans); font-size: .78rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: .14em; color: var(--ink);
}
.offer-list p { margin: 0; color: var(--ink-soft); font-size: 1rem; }
.wide-list { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 0 clamp(2rem, 5vw, 4rem); }

.team { list-style: none; margin: 0; padding: 0; display: grid; gap: 0; }
@media (min-width: 820px) { .team { grid-template-columns: 1fr 1fr; gap: 0 clamp(3rem, 7vw, 6rem); } }
.team li { border-top: var(--rule-ink); padding: 1.8rem 0; }
.team h3 { font-size: 1.6rem; margin-bottom: .6rem; }
.team p { color: var(--ink-soft); margin: 0; }

.plain { list-style: none; margin: 0; padding: 0; }
.plain li { margin-bottom: .6rem; }

/* --------------------------------------------------- author spotlight */
.spotlight { display: grid; gap: clamp(2.5rem, 6vw, 5rem); align-items: center; }
/* The portraits are only 151px square, so the image column is narrower than the
   text column — a 1:1 split would leave them adrift in white space. */
@media (min-width: 900px) {
  /* 23rem leaves exactly enough inside the plate's padding for two 132px
     circles side by side; narrower and they wrap into a tall single column. */
  .spotlight { grid-template-columns: minmax(0, 23rem) 1fr; }
  /* Stop the quote running to a 1000px measure on a wide screen. */
  .spotlight > *:not(.spotlight-figure) { max-width: 46rem; }
}
.spotlight-figure { margin: 0; }

/* Founders plate: two circular portraits on the tinted ground used by the book
   tiles, so it reads as part of the same family. */
.founders {
  display: flex; flex-wrap: wrap; gap: 1.5rem;
  justify-content: center; align-items: start;
  background: var(--paper-alt); border: var(--rule);
  padding: clamp(1.5rem, 3vw, 2rem) 1.5rem;
}
.founder { margin: 0; text-align: center; max-width: 132px; }
.founder picture { display: block; }
.founder img {
  width: 132px; height: 132px; border-radius: 50%;
  object-fit: cover; background: var(--paper);
  /* A hairline ring keeps the cut-out from dissolving into the tinted ground. */
  box-shadow: 0 0 0 1px var(--line);
}
.founder figcaption { margin-top: .9rem; }
.founder b {
  display: block; font-family: var(--serif); font-weight: 400; font-size: 1.05rem;
  line-height: 1.15; color: var(--ink);
}
.founder span {
  display: block; margin-top: .3rem; white-space: nowrap;
  font-size: .6rem; text-transform: uppercase; letter-spacing: .14em;
  color: var(--ink-soft);
}
@media (max-width: 380px) {
  .founder, .founder img { width: 112px; max-width: 112px; }
  .founder img { height: 112px; }
}
.spotlight blockquote {
  margin: 0 0 2rem; padding-left: 2rem; border-left: 2px solid var(--steel);
  font-family: var(--serif); font-size: clamp(1.4rem, 1rem + 1.4vw, 2rem);
  font-style: italic; line-height: 1.3; color: var(--ink);
}
.spotlight h2 { margin-bottom: 1.6rem; }

/* --------------------------------------------------------------- filters */
.filters {
  display: flex; gap: clamp(1rem, 3vw, 2.5rem); flex-wrap: wrap; align-items: end;
  margin-bottom: clamp(2rem, 4vw, 3.5rem); padding-bottom: 1.5rem; border-bottom: var(--rule-ink);
}
.field { display: flex; flex-direction: column; gap: .5rem; }
.field label {
  font-size: .66rem; font-weight: 600; color: var(--ink-soft);
  text-transform: uppercase; letter-spacing: .18em;
}
.field input, .field select {
  font: 400 .95rem/1 var(--sans); padding: .7rem .2rem; border: 0;
  border-bottom: var(--rule-ink); border-radius: 0; background: transparent;
  color: var(--ink); min-width: 190px; height: 40px;
}
.field input::placeholder { color: var(--ink-soft); }
.count {
  margin: 0 0 .2rem auto; font-size: .68rem; text-transform: uppercase;
  letter-spacing: .16em; color: var(--ink-soft);
}
.empty { text-align: center; padding: 4rem 0; color: var(--ink-soft); }
.linkish {
  background: none; border: 0; color: var(--steel); text-decoration: underline;
  cursor: pointer; font: inherit; padding: 0;
}

/* ---------------------------------------------------------------- detail */
.crumbs {
  padding: 1.1rem 0; font-size: .68rem; text-transform: uppercase; letter-spacing: .16em;
  color: var(--ink-soft); border-bottom: var(--rule);
}
.crumbs a { text-decoration: none; color: var(--ink-soft); }
.crumbs a:hover { color: var(--steel); }
.crumbs span { margin: 0 .6rem; }
.crumbs em { font-style: normal; color: var(--ink); }

.detail-grid { display: grid; gap: clamp(2.5rem, 6vw, 5rem); align-items: start; }
@media (min-width: 900px) { .detail-grid { grid-template-columns: 5fr 7fr; } }
.detail-cover {
  background: var(--paper-alt); border: var(--rule); padding: clamp(1rem, 2.2vw, 1.75rem);
  display: grid; place-items: center; aspect-ratio: 3 / 4;
}
@media (min-width: 900px) { .detail-cover { position: sticky; top: calc(80px + 2rem); } }
.detail-cover img {
  width: 100%; height: 100%; min-width: 0; min-height: 0; object-fit: contain;
}
.detail-info h1 { font-size: clamp(2.4rem, 1.6rem + 2.8vw, 4rem); margin-bottom: .4rem; }
.detail-price {
  font-family: var(--serif); font-size: 2.2rem; color: var(--ink);
  margin: 0 0 .4rem; font-variant-numeric: tabular-nums;
}
.detail-price.muted { font-size: 1.3rem; font-style: italic; }
.buy-note { font-size: .82rem; color: var(--ink-soft); margin: 1rem 0 0; }

.meta { display: grid; margin: 2.5rem 0 1.5rem; padding: 0; border-top: var(--rule-ink); }
.meta > div {
  display: grid; grid-template-columns: 130px minmax(0, 1fr); gap: 1rem;
  padding: .85rem 0; border-bottom: var(--rule); font-size: .92rem;
}
.meta dt {
  margin: 0; color: var(--ink-soft); font-size: .68rem;
  text-transform: uppercase; letter-spacing: .14em;
}
.meta dd { margin: 0; color: var(--ink); overflow-wrap: anywhere; }
.meta.stack > div { grid-template-columns: 110px minmax(0, 1fr); }
@media (max-width: 520px) {
  .meta > div, .meta.stack > div { grid-template-columns: 1fr; gap: .2rem; }
}

.tags { display: flex; flex-wrap: wrap; gap: .5rem; }
.tag {
  font-size: .66rem; text-transform: uppercase; letter-spacing: .14em;
  border: var(--rule); padding: .45rem .9rem; text-decoration: none; color: var(--ink-soft);
  transition: border-color .18s ease, color .18s ease;
}
.tag:hover { border-color: var(--steel); color: var(--steel); }
.detail .prose { margin-top: clamp(3rem, 6vw, 5rem); }

/* -------------------------------------------------------------- packages */
.pkgs { display: grid; gap: 0; grid-template-columns: repeat(auto-fit, minmax(290px, 1fr)); align-items: stretch; }
.pkg {
  border: var(--rule-ink); margin-left: -1px; padding: clamp(2rem, 3vw, 2.8rem);
  position: relative; display: flex; flex-direction: column; background: transparent;
}
.pkg-featured { background: var(--paper-alt); }
.badge {
  position: absolute; top: 0; right: 0; background: var(--steel); color: var(--paper);
  font-size: .62rem; font-weight: 600; letter-spacing: .18em; text-transform: uppercase;
  padding: .4rem .9rem;
}
.pkg h3 {
  font-family: var(--sans); font-size: .7rem; font-weight: 600; text-transform: uppercase;
  letter-spacing: .2em; color: var(--ink-soft); margin-bottom: .8rem;
}
.pkg-price { font-family: var(--serif); font-size: clamp(2.6rem, 2rem + 1.6vw, 3.6rem); color: var(--ink); margin: 0 0 1.8rem; line-height: 1; }
.ticks { list-style: none; margin: 0 0 2rem; padding: 0; display: grid; gap: 0; flex: 1; }
.ticks li { font-size: 1rem; color: var(--ink-soft); padding: .6rem 0; border-top: var(--rule); }
.pkg .btn { align-self: start; }
/* The full price stays the headline; how it is paid sits under it. Leading with
   the deposit reads as the price of the package to anyone skimming. */
.pkg-price { margin-bottom: .5rem; }
.pkg-terms {
  font-size: .82rem; color: var(--ink-soft); margin: 0 0 1.8rem;
  line-height: 1.5; letter-spacing: .01em;
}
/* Pay in full, or the deposit. Sits between the feature list and the button,
   because it changes what the button says. */
.pkg-pay { display: block; margin: 0 0 1.2rem; }
.pkg-pay-label {
  display: block; font-family: var(--sans); font-size: .68rem; font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase; color: var(--ink-soft);
  margin-bottom: .5rem;
}
.pkg-pay-select {
  font: inherit; font-size: .95rem; color: var(--ink); background: var(--paper);
  border: var(--rule-ink); border-radius: 0; padding: .6rem .7rem; width: 100%;
}
.pkg-pay-select:focus-visible { outline: 2px solid var(--steel); outline-offset: 2px; }
.pkg-cta { margin: 0; display: flex; flex-direction: column; align-items: flex-start; gap: .8rem; }
.pkg-enquire { font-size: .85rem; color: var(--ink-soft); }

/* ------------------------------------------------ package details dialog */
/* Scoped under .pkg-dialog throughout. The bookstore filter bar already owns
   .field, and the manuscript review page has been bitten once by an unscoped
   form rule reshaping a page it was never meant to touch. */
.pkg-dialog { position: fixed; inset: 0; z-index: 95; display: flex;
  align-items: flex-start; justify-content: center; overflow-y: auto; padding: 5vh 1rem; }
.pkg-dialog[hidden] { display: none; }
.pkg-dialog-backdrop { position: fixed; inset: 0; background: rgba(21, 34, 50, .55); }
.pkg-dialog-panel {
  position: relative; width: min(560px, 100%); background: var(--paper);
  border: var(--rule-ink); padding: clamp(1.6rem, 4vw, 2.6rem);
}
.pkg-dialog-open { overflow: hidden; }
.pkg-dialog h2 { font-family: var(--serif); font-size: clamp(1.7rem, 1.3rem + 1.2vw, 2.3rem);
  line-height: 1.1; margin: 0 0 .7rem; }
.pkg-dialog-lede { color: var(--ink-soft); font-size: .95rem; line-height: 1.6; margin: 0 0 1.8rem; }
.pkg-dialog .pkg-field { display: flex; flex-direction: column; gap: .4rem; margin-bottom: 1.4rem; }
.pkg-dialog .pkg-field label {
  font-family: var(--sans); font-size: .68rem; font-weight: 600; letter-spacing: .16em;
  text-transform: uppercase; color: var(--ink-soft);
}
.pkg-dialog .pkg-optional { font-weight: 400; letter-spacing: .08em; opacity: .75; }
.pkg-dialog input, .pkg-dialog textarea {
  font: inherit; font-size: 1rem; color: var(--ink); background: var(--paper);
  border: var(--rule-ink); border-radius: 0; padding: .7rem .8rem; width: 100%;
}
.pkg-dialog textarea { resize: vertical; min-height: 4.5rem; }
.pkg-dialog input:focus-visible, .pkg-dialog textarea:focus-visible {
  outline: 2px solid var(--steel); outline-offset: 2px;
}
.pkg-dialog .pkg-hint { font-size: .8rem; color: var(--ink-soft); margin: 0; }
.pkg-dialog .pkg-error { font-size: .82rem; color: #a3341f; margin: 0; font-weight: 600; }
.pkg-dialog .pkg-error[hidden] { display: none; }
.pkg-dialog-note {
  font-size: .88rem; line-height: 1.6; color: var(--ink); margin: 0 0 1.4rem;
  padding: .9rem 1rem; background: var(--paper-alt); border-left: 3px solid var(--steel);
}
.pkg-dialog-fail {
  font-size: .9rem; line-height: 1.6; color: #a3341f; margin: 0 0 1.2rem;
  padding: .8rem 1rem; border: 1px solid #a3341f;
}
.pkg-dialog-fail[hidden] { display: none; }
.pkg-dialog-actions { display: flex; flex-wrap: wrap; gap: .8rem; align-items: center; }
.pkg-dialog-actions .btn[disabled] { opacity: .6; cursor: progress; }
.pkg-dialog-secure { font-size: .78rem; color: var(--ink-soft); margin: 1.2rem 0 0; }

/* Numbered next steps, used on /publishing/complete/. */
.steps { margin: 1.2rem 0 2rem; padding-left: 1.3rem; display: grid; gap: .8rem; }
.steps li { line-height: 1.65; color: var(--ink); padding-left: .3rem; }

/* ------------------------------------------------------------------- faq */
.faq-sec { margin-bottom: clamp(2.5rem, 5vw, 4rem); }
.faq-sec h2 {
  font-size: 1.5rem; font-style: italic; padding-bottom: 1rem; margin-bottom: 0;
  border-bottom: var(--rule-ink);
}
details { border-bottom: var(--rule); }
summary {
  cursor: pointer; padding: 1.15rem 2.5rem 1.15rem 0; font-weight: 500; color: var(--ink);
  list-style: none; position: relative; font-size: 1rem;
}
summary::-webkit-details-marker { display: none; }
summary::after {
  content: "+"; position: absolute; right: .2rem; top: 1rem;
  font-size: 1.2rem; color: var(--steel); line-height: 1;
}
details[open] summary::after { content: "\2212"; }
details > div { padding: 0 2.5rem 1.4rem 0; }
details p { margin: 0; color: var(--ink-soft); font-size: 1rem; line-height: 1.7; }

/* --------------------------------------------------------------- contact */
.contact-grid { display: grid; gap: clamp(2.5rem, 6vw, 5rem); align-items: start; }
@media (min-width: 900px) { .contact-grid { grid-template-columns: 3fr 2fr; } }
.contact-card { background: var(--paper-alt); border: var(--rule-ink); padding: clamp(1.75rem, 3vw, 2.5rem); }
.contact-card h2 { font-size: 1.3rem; margin-top: 0; font-style: italic; }
.contact-card .meta { border-top: 0; margin: 0; }
.contact-card .meta > div:first-child { border-top: 0; }

/* ---------------------------------------------------------------- footer */
.site-foot { background: var(--navy); color: rgba(251, 250, 248, .66); margin-top: 0; padding-top: clamp(3rem, 6vw, 5rem); font-size: .95rem; }
.foot-grid { display: grid; gap: 2.5rem; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
.foot-brand { max-width: 300px; }
.foot-brand img { width: 150px; margin-bottom: 1.2rem; }
.foot-brand p { color: rgba(251, 250, 248, .5); font-style: italic; }
.site-foot h3 {
  color: var(--paper); font-family: var(--sans); font-size: .68rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: .2em; margin-bottom: 1.1rem;
}
.site-foot a { color: rgba(251, 250, 248, .66); text-decoration: none; }
.site-foot a:hover { color: var(--paper); }
.foot-legal {
  border-top: 1px solid rgba(251, 250, 248, .14); margin-top: clamp(2.5rem, 5vw, 4rem);
  padding: 1.6rem 0; display: flex; justify-content: space-between; gap: 1rem; flex-wrap: wrap;
}
.foot-legal p {
  margin: 0; color: rgba(251, 250, 248, .4);
  font-size: .62rem; text-transform: uppercase; letter-spacing: .18em;
}

/* ============================================================== basket ==== */
.basket-btn {
  position: relative; flex: none; display: grid; place-items: center;
  width: 42px; height: 42px; border: var(--rule-ink); background: transparent;
  color: var(--ink); cursor: pointer; transition: background .18s ease, color .18s ease;
}
.basket-btn:hover { background: var(--ink); color: var(--paper); }
.basket-count {
  position: absolute; top: -7px; right: -7px; min-width: 18px; height: 18px;
  padding: 0 5px; background: var(--steel); color: var(--paper);
  font: 600 10px/18px var(--sans); text-align: center; font-variant-numeric: tabular-nums;
}
@media (max-width: 980px) { .basket-btn { margin-left: auto; } }
@media (max-width: 480px) { .basket-btn { width: 38px; height: 38px; } }

.basket[hidden] { display: none; }
.basket { position: fixed; inset: 0; z-index: 90; }
.basket-backdrop { position: absolute; inset: 0; background: rgba(21, 34, 50, .55); opacity: 0; transition: opacity .24s ease; }
.basket.is-open .basket-backdrop { opacity: 1; }
.basket-panel {
  position: absolute; top: 0; right: 0; bottom: 0; width: min(100%, 430px);
  background: var(--paper); border-left: var(--rule-ink);
  display: flex; flex-direction: column;
  transform: translateX(100%); transition: transform .26s cubic-bezier(.22, .61, .36, 1);
}
.basket.is-open .basket-panel { transform: none; }
@media (prefers-reduced-motion: reduce) { .basket-panel, .basket-backdrop { transition: none; } }
body.basket-open { overflow: hidden; }

.basket-head {
  display: flex; align-items: center; gap: .9rem;
  padding: 1.4rem; border-bottom: var(--rule-ink);
}
.basket-head h2 { margin: 0; font-size: 1.4rem; font-style: italic; }
/* Push the close button to the far right; the empty control sits beside the
   title rather than at the foot of the drawer. */
.basket-head .basket-close { margin-left: auto; }
.basket-close { border: 0; background: none; font-size: 1.8rem; line-height: 1; cursor: pointer; color: var(--ink-soft); padding: 0 .2rem; }
.basket-close:hover { color: var(--ink); }

.basket-lines { list-style: none; margin: 0; padding: 0 1.4rem; overflow-y: auto; flex: 1; }
.basket-empty { color: var(--ink-soft); padding: 2rem 0; text-align: center; font-style: italic; }
.basket-line {
  display: grid; grid-template-columns: 50px minmax(0, 1fr) auto; gap: .1rem .9rem;
  align-items: start; padding: 1.2rem 0; border-bottom: var(--rule);
}
.basket-line img, .basket-noimg {
  grid-row: span 2; width: 50px; height: 45px; object-fit: contain;
  background: var(--paper-alt); border: var(--rule);
}
.basket-line-main { display: flex; flex-direction: column; min-width: 0; }
.basket-line-main a { font-size: .95rem; color: var(--ink); text-decoration: none; }
.basket-line-main a:hover { color: var(--steel); }
.basket-author { font-size: .8rem; font-style: italic; color: var(--ink-soft); }
.basket-price { font-size: .88rem; margin-top: .3rem; font-variant-numeric: tabular-nums; }
.basket-qty { display: flex; align-items: center; border: var(--rule-ink); }
.basket-qty button { width: 26px; height: 28px; border: 0; background: none; cursor: pointer; color: var(--ink); font-size: .95rem; line-height: 1; }
.basket-qty button:hover:not(:disabled) { background: var(--ink); color: var(--paper); }
.basket-qty button:disabled { color: var(--line); cursor: default; }
.basket-qty span { min-width: 24px; text-align: center; font-size: .85rem; font-variant-numeric: tabular-nums; }
.basket-remove {
  grid-column: 3; border: 0; background: none; padding: 0; cursor: pointer; justify-self: end;
  font: 400 .66rem var(--sans); text-transform: uppercase; letter-spacing: .14em;
  color: var(--ink-soft); text-decoration: underline;
}
.basket-remove:hover { color: var(--ink); }

.basket-foot { border-top: var(--rule-ink); padding: 1.3rem 1.4rem 1.6rem; }
.basket-region { display: flex; align-items: center; gap: .8rem; margin-bottom: 1.1rem; }
.basket-region span { font-size: .66rem; text-transform: uppercase; letter-spacing: .16em; color: var(--ink-soft); }
.basket-region select { flex: 1; font: 400 .9rem var(--sans); padding: .5rem .2rem; border: 0; border-bottom: var(--rule-ink); border-radius: 0; background: transparent; }
.basket-totals { margin: 0 0 .6rem; display: grid; gap: .45rem; }
.basket-totals > div { display: flex; justify-content: space-between; font-size: .9rem; }
.basket-totals dt { color: var(--ink-soft); margin: 0; font-size: .68rem; text-transform: uppercase; letter-spacing: .14em; }
.basket-totals dd { margin: 0; font-variant-numeric: tabular-nums; }
.basket-grand { border-top: var(--rule-ink); padding-top: .7rem; margin-top: .3rem; }
.basket-grand dt { color: var(--ink); }
.basket-grand dd { font-family: var(--serif); font-size: 1.5rem; color: var(--ink); }
.basket-hint:empty, .basket-error:empty { display: none; }
.basket-hint { font-size: .78rem; color: var(--steel); margin: 0 0 .8rem; }
.basket-error { font-size: .85rem; color: #8c2f26; border: 1px solid #d9b3ac; padding: .7rem .8rem; margin: 0 0 .8rem; }
.basket-pay { width: 100%; }
.basket-pay:disabled { opacity: .6; cursor: default; }
.basket-secure { font-size: .68rem; text-transform: uppercase; letter-spacing: .1em; color: var(--ink-soft); text-align: center; margin: .9rem 0 0; }

.add-mini {
  border: var(--rule-ink); background: transparent; padding: .4rem .9rem;
  font: 500 .64rem var(--sans); text-transform: uppercase; letter-spacing: .14em;
  color: var(--ink); cursor: pointer; white-space: nowrap;
  transition: background .18s ease, color .18s ease;
}
.add-mini:hover { background: var(--ink); color: var(--paper); }
.add-mini.is-added, .add-to-basket.is-added { background: #1c6b4a; border-color: #1c6b4a; color: var(--paper); }
/* A book in two bindings sends the buyer to the page instead of adding one of
   them on their behalf. It is an <a>, so it needs the line-height and colour a
   <button> was giving it. */
.add-mini-choose { display: inline-block; text-decoration: none; line-height: 1.35; }
.add-mini-choose:hover { color: var(--paper); }

/* ------------------------------------------------------- format chooser */
/* Scoped under .formats. The bookstore filter bar owns .field and the review
   page owns .genre-chip; an unscoped rule here would reshape both. */
.formats {
  border: 0; margin: 0 0 1.6rem; padding: 0; display: grid; gap: 0;
  border-top: var(--rule-ink);
}
.formats legend {
  padding: 0; margin: 0 0 .8rem; font-family: var(--sans); font-size: .68rem;
  font-weight: 600; letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-soft);
}
/* Centred, not baseline: the price is set in the display serif at more than
   twice the label's size, and sharing a baseline with it drops the price
   against the row's bottom rule. */
.format {
  display: flex; align-items: center; gap: .8rem; cursor: pointer;
  padding: .85rem .2rem; border-bottom: var(--rule);
}
.format input { margin: 0; accent-color: var(--steel); flex: none; }
.format-name {
  font-family: var(--sans); font-size: .95rem; color: var(--ink); flex: 1 1 auto;
}
.format-price { font-family: var(--serif); font-size: 1.5rem; color: var(--ink); }
.format:has(input:checked) { background: var(--paper-alt); }
.format:has(input:focus-visible) { outline: 2px solid var(--steel); outline-offset: -2px; }

/* Empty basket — a quiet control beside the drawer title, deliberately not
   competing with Checkout. One press empties; the empty state offers an undo. */
.basket-empty-btn[hidden] { display: none; }
.basket-empty-btn {
  display: inline-flex; align-items: center; gap: .45rem; margin: 0;
  padding: .4rem .6rem; border: var(--rule); background: transparent;
  color: var(--ink-soft); cursor: pointer;
  font: 500 .64rem var(--sans); text-transform: uppercase; letter-spacing: .14em;
  transition: border-color .18s ease, color .18s ease, background .18s ease;
}
.basket-empty-btn:hover { border-color: var(--ink); color: var(--ink); }
.basket-empty-btn svg { flex: none; }
.basket-empty-btn:active { background: var(--ink); color: var(--paper); border-color: var(--ink); }
/* On a narrow drawer the icon carries it, rather than pushing close off the row. */
@media (max-width: 420px) {
  .basket-empty-btn { padding: .4rem .45rem; }
  .basket-empty-btn span { display: none; }
}

.basket-undo {
  border: var(--rule-ink); background: transparent; color: var(--ink);
  padding: .5rem 1rem; cursor: pointer;
  font: 500 .66rem var(--sans); text-transform: uppercase; letter-spacing: .14em;
  transition: background .18s ease, color .18s ease;
}
.basket-undo:hover { background: var(--ink); color: var(--paper); }

/* ======================================================= manuscript review ==
   This page drives a long-running job rather than rendering content, so it has
   two visual states: the submission form, and a live panel that polls.

   Form styling is scoped under .review-form deliberately. A bare `.field` rule
   already exists for the bookstore filter bar (horizontal, fixed height, label
   inside), and this form's fields are a different shape — unscoped rules would
   quietly reshape /books/.

   Overflow watch: a session reference (sesn_01AB…) and a filename are long
   unbreakable strings inside grid and flex children, which is exactly what
   pushes a track wider than the viewport. Hence min-width: 0 on the tracks and
   overflow-wrap on everything that can carry one. */

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* ------------------------------------------------------------ tier chooser */
.tiers {
  display: grid; gap: 1.5rem; margin: 2.5rem 0 0;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  align-items: stretch;
}
.tiers > * { min-width: 0; }

.tier {
  display: flex; flex-direction: column; gap: 1rem; min-width: 0;
  border: var(--rule); padding: clamp(1.4rem, 3vw, 2rem);
  background: var(--paper); position: relative;
  transition: border-color .18s ease;
}
.tier:hover { border-color: var(--ink); }
.tier.is-featured { border: var(--rule-ink); box-shadow: inset 0 0 0 1px var(--ink); }

.tier-badge {
  position: absolute; top: clamp(1.4rem, 3vw, 2rem); right: clamp(1.4rem, 3vw, 2rem);
  font: 600 .62rem var(--sans); text-transform: uppercase; letter-spacing: .14em;
  background: var(--ink); color: var(--paper); padding: .32rem .6rem;
}
.tier-name { font-family: var(--serif); font-size: 1.5rem; margin: 0; line-height: 1; }
.tier-price {
  font-family: var(--serif); font-size: clamp(2.4rem, 2rem + 1.6vw, 3.2rem);
  line-height: 1; margin: 0; font-variant-numeric: tabular-nums;
}
.tier-sum { font-size: .92rem; line-height: 1.6; color: var(--ink-soft); margin: 0; }
.tier-sum b { color: var(--ink); font-weight: 600; }

.tier-features { list-style: none; margin: 0; padding: 0; flex: 1; }
.tier-features li {
  font-size: .9rem; color: var(--ink-soft); padding: .6rem 0;
  border-top: var(--rule); line-height: 1.45;
}

.tier-pick {
  display: block; width: 100%; text-align: center; text-decoration: none;
  font: 500 .7rem var(--sans); text-transform: uppercase; letter-spacing: .16em;
  padding: .85rem 1rem; cursor: pointer;
  border: 1px solid var(--ink); background: transparent; color: var(--ink);
  transition: background .18s ease, color .18s ease;
}
.tier-pick:hover { background: var(--ink); color: var(--paper); }
.tier.is-featured .tier-pick { background: var(--ink); color: var(--paper); }
.tier.is-featured .tier-pick:hover { opacity: .85; }
/* A tier we cannot fulfil automatically must not look like the one we can. */
.tier-pick.is-enquiry { border-style: dashed; }

.tier-caveat {
  display: flex; gap: .9rem; align-items: start;
  border: 1px solid var(--gold); background: #fdf8ef;
  padding: 1.1rem 1.3rem; margin-top: 2rem;
  font-size: .92rem; line-height: 1.65; color: var(--ink);
}
.tier-caveat svg { flex: none; color: var(--gold); margin-top: .15rem; }
.tier-foot {
  display: flex; flex-wrap: wrap; gap: 1rem; justify-content: space-between;
  align-items: baseline; margin-top: 1.6rem;
  font-size: .86rem; color: var(--ink-soft);
}

.ticks.tight li { padding: .45rem 0; }

/* --------------------------------------------------------- entry (state 1)
   One heading, one line, one composer. What is being asked for is a file, and a
   wall of fields in front of that reads as a form to be endured rather than a
   service to be used. Everything else sits behind "Add details" and is revealed
   the moment a manuscript is attached.

   Square edges, not the pill the reference screenshot uses: --radius is 0
   throughout this design system and a lone rounded control would read as
   borrowed from another site. */
.review-band { padding-block: clamp(3rem, 9vh, 7rem); }
.entry { max-width: 44rem; margin-inline: auto; text-align: center; }
.entry[hidden] { display: none; }
.entry h1 {
  font-size: clamp(2.2rem, 1.6rem + 3vw, 3.6rem); line-height: 1.05;
  margin: 0 0 1rem;
}
.entry-sub {
  color: var(--ink-soft); font-size: 1.02rem; line-height: 1.7;
  margin: 0 auto clamp(2rem, 5vw, 3rem); max-width: 40rem;
}

.composer { display: flex; flex-direction: column; gap: 1rem; text-align: left; }

.composer-bar {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center; gap: .5rem;
  border: var(--rule-ink); background: var(--paper); padding: .45rem .5rem;
}
.composer-bar:focus-within { outline: 2px solid var(--steel); outline-offset: 2px; }

.composer-attach {
  display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; flex: none; cursor: pointer;
  border: var(--rule); color: var(--ink-soft);
  transition: border-color .18s ease, color .18s ease, background .18s ease;
}
.composer-attach:hover { border-color: var(--ink); color: var(--ink); }
/* The file input is visually hidden but still focusable, so the keyboard route
   to it is the label — which needs a visible focus ring of its own. */
#review-file:focus-visible + .composer-bar .composer-attach,
.composer-attach:focus-within { outline: 2px solid var(--steel); outline-offset: 2px; }
.composer-attach.has-file { border-color: var(--ink); color: var(--ink); background: var(--paper-alt); }

.composer-input {
  font: 400 1rem/1.5 var(--sans); border: 0; background: transparent;
  color: var(--ink); padding: .6rem .3rem; width: 100%; min-width: 0;
}
.composer-input:focus { outline: none; }
.composer-input::placeholder { color: var(--ink-soft); }

.composer-send {
  display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; flex: none; cursor: pointer;
  border: 1px solid var(--ink); background: var(--ink); color: var(--paper);
  transition: opacity .18s ease;
}
.composer-send:hover { opacity: .82; }
.composer-send:disabled { cursor: default; opacity: .45; }
.composer-send.is-busy svg { display: none; }
.composer-send.is-busy::after {
  content: ""; width: 14px; height: 14px; border: 2px solid currentColor;
  border-right-color: transparent; border-radius: 50%; animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .composer-send.is-busy::after { animation: none; opacity: .6; }
}

.composer-file {
  font: 500 .78rem var(--sans); color: var(--ink); margin: 0;
  padding: .5rem .7rem; background: var(--paper-alt); border-left: 3px solid var(--steel);
  overflow-wrap: anywhere;
}
.composer-file[hidden] { display: none; }

/* Chips: one tap beats a menu, and genre is the single detail worth asking for
   before anything is revealed. */
.genre-chips { display: flex; flex-wrap: wrap; gap: .5rem; }
.genre-chip {
  font: 400 .84rem var(--sans); padding: .45rem .85rem; cursor: pointer;
  border: var(--rule); background: transparent; color: var(--ink-soft);
  transition: border-color .18s ease, color .18s ease, background .18s ease;
}
.genre-chip:hover { border-color: var(--ink); color: var(--ink); }
.genre-chip[aria-pressed="true"] {
  background: var(--ink); border-color: var(--ink); color: var(--paper);
}

.entry-more {
  align-self: start; font: 500 .7rem var(--sans); text-transform: uppercase;
  letter-spacing: .16em; color: var(--ink-soft); cursor: pointer;
  background: transparent; border: 0; border-bottom: var(--rule-ink);
  padding: .3rem 0;
}
.entry-more:hover { color: var(--ink); }

.entry-details { display: flex; flex-direction: column; gap: 1.4rem; }
.entry-details[hidden] { display: none; }
.entry-fields {
  display: grid; gap: 1.2rem; grid-template-columns: repeat(2, minmax(0, 1fr));
}
@media (max-width: 620px) { .entry-fields { grid-template-columns: minmax(0, 1fr); } }

.entry-details .field { display: flex; flex-direction: column; gap: .45rem; }
.entry-details .field-label,
.review-gate .field-label {
  font-size: .66rem; font-weight: 600; color: var(--ink-soft);
  text-transform: uppercase; letter-spacing: .18em;
}
.entry-details .field-label em { font-style: normal; text-transform: none; letter-spacing: .04em; }
.entry-details .field-hint, .review-gate .field-hint {
  font-size: .8rem; color: var(--ink-soft); line-height: 1.5; overflow-wrap: anywhere;
}
.entry-details input[type="text"],
.entry-details input[type="email"] {
  font: 400 .95rem/1.5 var(--sans); padding: .55rem .2rem; border: 0;
  border-bottom: var(--rule-ink); border-radius: 0; background: transparent;
  color: var(--ink); width: 100%; min-width: 0;
}
.entry-details input::placeholder { color: var(--ink-soft); }
.entry-details input:focus-visible { outline: 2px solid var(--steel); outline-offset: 2px; }

.entry-foot { border-top: var(--rule); padding-top: 1.2rem; }
.entry-foot p {
  font-size: .84rem; line-height: 1.65; color: var(--ink-soft); margin: 0 0 .6rem;
}
.entry-foot p:last-child { margin-bottom: 0; }
.entry-foot strong { color: var(--ink); }

/* Checkbox and radio rows: the control stays beside the first line of text. */
.choice {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: .65rem;
  align-items: start; font-size: .9rem; color: var(--ink-soft); line-height: 1.55;
  cursor: pointer;
}
.choice input { margin: .2rem 0 0; accent-color: var(--steel); }

.review-gate {
  border: var(--rule); padding: 1rem 1.1rem; margin: 0;
  display: flex; flex-direction: column; gap: .7rem; background: var(--paper-alt);
}
.review-gate legend { padding: 0 .4rem; }
.review-rights { padding-top: .2rem; }

.review-error { color: #a32020; font-size: .9rem; margin: 0; }
.review-error:empty { display: none; }
.review-notice {
  border: 1px solid var(--gold); background: #fdf8ef; padding: .9rem 1rem;
  font-size: .9rem; line-height: 1.6; color: var(--ink);
}
.review-notice[hidden] { display: none; }

/* ------------------------------------------------------------- live panel */
.review-live[hidden] { display: none; }
.review-live { max-width: 76ch; margin-inline: auto; }

.review-status { border-bottom: var(--rule-ink); padding-bottom: 1.2rem; margin-bottom: 1.6rem; }
.review-state {
  font-family: var(--serif); font-size: clamp(1.6rem, 1.2rem + 1.4vw, 2.4rem);
  line-height: 1.15; margin: 0 0 .4rem;
}
.review-state.is-question { color: var(--gold); }
.review-state.is-done { color: #1c6b4a; }
.review-state.is-failed, .review-state.is-budget { color: #a32020; }
.review-activity { color: var(--ink-soft); margin: 0; font-size: 1rem; }
.review-activity:empty { display: none; }
.review-steps {
  font-size: .74rem; text-transform: uppercase; letter-spacing: .16em;
  color: var(--ink-soft); margin: .6rem 0 0;
}
.review-steps:empty { display: none; }
.review-refline {
  font-size: .8rem; color: var(--ink-soft); margin: 1rem 0 0;
  display: flex; flex-wrap: wrap; gap: .5rem; align-items: baseline;
}
.review-refline code {
  font-size: .78rem; background: var(--paper-alt); padding: .2rem .45rem;
  overflow-wrap: anywhere; min-width: 0;
}

.review-expect {
  font-size: .92rem; line-height: 1.7; color: var(--ink-soft);
  background: var(--paper-alt); padding: 1rem 1.2rem; margin: 0 0 1.8rem;
  border-left: 3px solid var(--steel);
}

/* ---------------------------------------------------------------- thread */
.review-thread { list-style: none; margin: 0; padding: 0; display: grid; gap: 1.4rem; }
.review-msg { border-top: var(--rule); padding-top: 1.1rem; min-width: 0; }
.review-msg.is-author { border-top-color: var(--ink); }
.review-who {
  font: 600 .64rem var(--sans); text-transform: uppercase; letter-spacing: .18em;
  color: var(--ink-soft); margin: 0 0 .5rem;
}
.review-msg.is-author .review-who { color: var(--steel); }
.review-body { overflow-wrap: anywhere; }
.review-body p { color: var(--ink-soft); line-height: 1.75; margin: 0 0 .8rem; }
.review-body h4 {
  font-family: var(--sans); font-size: .82rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: .12em; color: var(--ink);
  margin: 1.4rem 0 .6rem;
}
.review-body ul, .review-body ol { margin: 0 0 .9rem; padding-left: 1.3rem; }
.review-body li { color: var(--ink-soft); line-height: 1.7; margin-bottom: .4rem; }
.review-body code {
  font-size: .86em; background: var(--paper-alt); padding: .1rem .3rem;
  overflow-wrap: anywhere;
}
.review-body strong { color: var(--ink); }

/* ----------------------------------------------------------- deliverables */
.review-files { margin-top: 2.2rem; border-top: var(--rule-ink); padding-top: 1.4rem; }
.review-files[hidden] { display: none; }
.review-files h2 { font-size: 1.4rem; font-style: italic; margin: 0 0 1rem; }
.order-lines-head { font-style: italic; }
.review-files ul { display: grid; gap: .8rem; }
.review-files li {
  display: flex; flex-wrap: wrap; gap: .7rem; align-items: center; min-width: 0;
}
.review-files .btn { overflow-wrap: anywhere; text-align: left; }
.review-size {
  font-size: .72rem; text-transform: uppercase; letter-spacing: .14em; color: var(--ink-soft);
}

.review-reply { margin-top: 2rem; border-top: var(--rule-ink); padding-top: 1.4rem; }
.review-reply[hidden] { display: none; }
.review-reply .field { display: flex; flex-direction: column; gap: .45rem; margin-bottom: 1rem; }
.review-reply .field-label {
  font-size: .66rem; font-weight: 600; color: var(--ink-soft);
  text-transform: uppercase; letter-spacing: .18em;
}
.review-reply textarea {
  font: 400 .95rem/1.6 var(--sans); padding: .7rem; width: 100%; min-width: 0;
  border: var(--rule-ink); border-radius: 0; background: transparent;
  color: var(--ink); resize: vertical;
}

.entry-tier {
  font: 500 .72rem var(--sans); text-transform: uppercase; letter-spacing: .16em;
  color: var(--steel); margin: 0 0 1rem;
}
.entry-tier[hidden] { display: none; }
/* A tier this screen cannot fulfil is a caution, not a confirmation. */
.entry-tier.is-enquiry {
  text-transform: none; letter-spacing: 0; font-size: .92rem; line-height: 1.6;
  color: var(--ink); border: 1px solid var(--gold); background: #fdf8ef;
  padding: .8rem 1rem; text-align: left;
}

/* ------------------------------------------------------- author dashboard */
.author-who {
  font: 500 .72rem var(--sans); text-transform: uppercase; letter-spacing: .16em;
  color: var(--steel); margin: 0 0 1.5rem; overflow-wrap: anywhere;
}
.author-who[hidden] { display: none; }
.author-state { color: var(--ink-soft); }
.author-state[hidden] { display: none; }

.author-list { display: grid; gap: 0; margin: 0 0 2rem; }
.author-review {
  padding: 1.1rem 0; border-top: var(--rule); min-width: 0;
}
.author-review:last-child { border-bottom: var(--rule); }
.author-review-title {
  font-family: var(--serif); font-size: 1.3rem; line-height: 1.2;
  text-decoration: none; overflow-wrap: anywhere;
}
.author-review-meta {
  font-size: .78rem; text-transform: uppercase; letter-spacing: .12em;
  color: var(--ink-soft); margin: .4rem 0 0;
}

/* =========================================================================
   Catalogue editor (/admin/books/)
   Staff-only, so it is plain: a list beside a form, no decoration to maintain.
   `min-width: 0` on both columns because an ISBN and an email are unbreakable
   strings and a grid track defaults to `min-width: auto`.
   ========================================================================= */
.review-notice.is-good { border-color: #1c6b4a; background: #f2f8f4; }
.review-notice.is-warn { border-color: #a32020; background: #fdf3f3; }

.admin-state:empty, .admin-state[hidden] { display: none; }
.admin-state { color: var(--ink-soft); }

.admin-grid { display: grid; gap: 2.4rem; align-items: start; }
@media (min-width: 62rem) {
  .admin-grid { grid-template-columns: minmax(0, 20rem) minmax(0, 1fr); gap: 3rem; }
}
.admin-list-wrap, .admin-form { min-width: 0; }

.admin-list-head {
  display: flex; flex-wrap: wrap; gap: .8rem; align-items: baseline;
  justify-content: space-between; border-bottom: var(--rule-ink); padding-bottom: .6rem;
}
.admin-list-head h2 { margin: 0; font-size: 1.4rem; }
.admin-new { padding: .45rem .9rem; font-size: .78rem; }

.admin-list { margin: 1rem 0 0; max-height: 34rem; overflow-y: auto; }
.admin-list li { margin: 0; border-bottom: var(--rule); }
.admin-row-btn {
  display: block; width: 100%; text-align: left; background: none; border: 0;
  padding: .7rem .2rem; cursor: pointer; font: inherit; color: inherit;
}
.admin-row-btn:hover, .admin-row-btn:focus-visible { background: var(--paper-alt); }
.admin-row-title { display: block; font-family: var(--serif); font-size: 1.05rem; overflow-wrap: anywhere; }
.admin-row-meta {
  display: block; font-size: .72rem; text-transform: uppercase;
  letter-spacing: .12em; color: var(--ink-soft); margin-top: .2rem;
  overflow-wrap: anywhere;
}

.admin-form { display: flex; flex-direction: column; gap: 1.2rem; }
.admin-form[hidden] { display: none; }
.admin-form h2 { margin: 0; overflow-wrap: anywhere; }
.admin-form input[type="file"] { font: inherit; font-size: .9rem; }
.admin-form input[readonly] { background: var(--paper-alt); color: var(--ink-soft); }

.admin-confirm {
  border: 1px solid #a32020; background: #fdf3f3; padding: 1rem 1.1rem;
  display: flex; flex-direction: column; gap: .7rem;
}
.admin-confirm[hidden] { display: none; }
.admin-confirm h3 { margin: 0; font-size: 1.1rem; }
.admin-confirm p { margin: 0; font-size: .9rem; line-height: 1.6; }
