/* JSB Coins — shared stylesheet
 * Detail page styles extracted from the original akragas-punic-quarter-shekel.html
 * static prototype. Catalog grid styles added below (used by /JSB_Coins/index.php).
 *
 * THEMING (2026-07-25). Every colour in this file is a var(--token) defined in
 * the :root block below; the dark palette re-declares those tokens under
 * :root[data-theme="dark"]. Nothing else in the file knows about themes.
 *
 * The theme is chosen by a tiny inline script in page_header() (jsb_coins_render.py)
 * that runs BEFORE first paint and stamps a CONCRETE value — "light" or "dark" —
 * onto <html data-theme>, resolving the stored "auto" preference against the OS
 * setting at that moment. That is why there is no @media (prefers-color-scheme)
 * block here: by the time CSS applies, the choice is already a literal attribute.
 * Consequence: with JavaScript disabled the attribute is absent and the light
 * palette applies, which is the safe default.
 *
 * ADDING A COLOUR: add a token here and a dark counterpart below — never a raw
 * hex in a rule, or it will be wrong in one of the two themes. (The only raw
 * literals left are #000 borders inside @media print, which is always light.)
 */

:root {
  color-scheme: light;

  /* Surfaces */
  --bg: #fdfcf8;                /* page ground (parchment) */
  --surface: #fff;              /* cards, inputs */
  --surface-card: #fffdf7;
  --surface-input: #fffdf8;
  --panel-bg: #faf6ec;          /* SVG "Enlarge" panel */
  --surface-sunken: #f2ece0;    /* <pre>, code, image backing */
  --surface-tint: #f7f0e2;      /* summary block, filter bar */
  --surface-tint2: #f6f2e6;     /* want budget / want note */
  --surface-tint-hover: #f0e6d0;
  --chip-bg: #f0efe9;
  --open-bg: #fffbe8;           /* open-threads callout */
  --ok-bg: #e5f0d8;
  --warn-bg: #f1ebd5;
  --err-bg: #fbeaea;
  --info-bg: #e8eef5;

  /* Ink */
  --ink: #1e1a14;               /* body text */
  --ink-strong: #2e1f0a;        /* h1, card headers */
  --ink-accent: #5a3e1b;        /* h2/h3, labels, dt */
  --ink-quote: #4a3a26;
  --ink-caption: #6a5a42;
  --ink-credit: #7a6a52;
  --muted-strong: #555;
  --muted: #666;
  --muted2: #777;
  --muted3: #888;
  --muted4: #999;
  --muted-neutral: #5a5a5a;
  --muted-faint: #a09a88;
  --on-accent: #fff;            /* text ON a gold badge/button — stays white */
  --on-dark: #eee;              /* lightbox caption, always over a dark scrim */

  /* Brand */
  --link: #7a5c2e;
  --gold: #8b6914;              /* badges, accent rules, primary button */
  --link-hot: #7a2e12;          /* hover/focus on Enlarge + panel close */
  --rule-hot: #a8763e;
  --verdigris: #4a7a6b;         /* the collapsed "Image source & licence" summary */

  /* Rules & borders */
  --rule: #c9b48a;
  --rule-soft: #e0d8c8;
  --rule-soft2: #ece4d0;
  --rule-soft3: #ddd6c4;
  --rule-card: #e0d6bd;
  --rule-chip: #d9d4c4;
  --rule-chip2: #d4d0c2;
  --rule-table: #ddd;
  --rule-open: #e0cd96;
  --rule-err: #e0b4b4;
  --rule-ok: #aac68f;

  /* Status inks (wanted list, catalogue refs, login errors) */
  --ok-ink: #3d6017;
  --warn-ink: #6b5519;
  --err-ink: #8a2b2b;
  --info-ink: #2f4a63;
  --info-border: #a9c0d6;
  --chip-ink: #6a675c;
  --avoid-ink: #7d3a2a;
  --appeal-bg: #f7e6ee;
  --appeal-ink: #8a3560;
  --appeal-rule: #d9aec5;
  --prio1: #9c3b1b;
  --prio2: #b06a1c;
  --prio45: #9a8d6f;

  /* Article feature banner — dark by design in BOTH themes, so these barely
     move; it is meant to contrast the parchment catalog and preview the
     article page's own dark look. */
  --banner-bg: #2e3a3f;
  --banner-border: #1f282c;
  --banner-rule: #3c4a50;
  --banner-title: #f2f3f0;
  --banner-lede: #aeb6b5;
  --banner-accent: #c58f4b;

  /* Semi-opaque chip floating ON TOP of a body-figure SVG, so it must follow
     the theme even though the SVG under it is filtered, not re-coloured. */
  --enlarge-bg: rgba(250,246,236,.92);

  /* Reader text-size controls (the "Aa" panel). The two levers are INDEPENDENT
     by construction, and the units are what make that true — change one and the
     levers start dragging each other again:

       --fs-scale   multiplies the page base: body { calc(1rem * --fs-scale) }.
                    Running prose is sized in `em`, so it inherits this and
                    nothing else. Prose rules must NOT reference --fs-small.

       --fs-small   scales captions, credits, chips, labels, counts and dates.
                    Those rules are sized in `rem`, NOT `em` — rem is anchored
                    to the root, so the body lever cannot reach them.

     `em` was the whole problem before 2026-08-07: every caption inherited the
     body scale and then multiplied --fs-small on top, so the body lever moved
     captions too, while prose that had been classified as "small print" (want
     card notes, why-passed reasoning, lot lines) moved with the CAPTION lever.
     Both defaults are 1, and the coefficients were re-derived from measured
     pixel sizes, so an untouched browser renders exactly as it did before. */
  --fs-scale: 1;
  --fs-small: 1;

  /* Inline-SVG body figures (Cowork's timelines) hardcode near-black ink on a
     near-white ground, so CSS variables cannot reach them. In dark mode they
     are inverted instead — see the dark block. */
  --svg-figure-filter: none;
}

:root[data-theme="dark"] {
  color-scheme: dark;

  --bg: #17140f;
  --surface: #201c15;
  --surface-card: #211d16;
  --surface-input: #1b1813;
  --panel-bg: #221e17;
  --surface-sunken: #262117;
  --surface-tint: #241f16;
  --surface-tint2: #241f16;
  --surface-tint-hover: #2c261a;
  --chip-bg: #262319;
  --open-bg: #2a2416;
  --ok-bg: #1e2a16;
  --warn-bg: #2a2416;
  --err-bg: #2e1a1a;
  --info-bg: #17212b;

  --ink: #e8e2d4;
  --ink-strong: #f2ead8;
  --ink-accent: #d8b877;        /* headings become warm gold, not dark brown */
  --ink-quote: #cfc6b2;
  --ink-caption: #b6ac95;
  --ink-credit: #b0a68f;
  --muted-strong: #a9a294;
  --muted: #a09a8c;
  --muted2: #9a9486;
  --muted3: #948e80;
  --muted4: #8a8478;
  --muted-neutral: #9a9a9a;
  --muted-faint: #7d786c;
  /* --gold lightens in dark mode, so white text on a gold badge would drop to
     ~2.6:1. Flip the badge text to dark ink instead (~8.9:1). --on-dark is
     unchanged: it only ever sits on the lightbox's dark scrim. */
  --on-accent: #1a1610;

  --link: #d2a869;
  --gold: #c79a3f;
  --link-hot: #e08a5a;
  --rule-hot: #b8894f;
  --verdigris: #6fb39c;

  --rule: #4a3f2a;
  --rule-soft: #3a3225;
  --rule-soft2: #3a3225;
  --rule-soft3: #3a3225;
  --rule-card: #3d3527;
  --rule-chip: #3a3428;
  --rule-chip2: #3a3428;
  --rule-table: #3a3630;
  --rule-open: #5a4a22;
  --rule-err: #6b3a3a;
  --rule-ok: #46602c;

  --ok-ink: #a8cf7a;
  --warn-ink: #d9bc74;
  --err-ink: #e29a9a;
  --info-ink: #9dc0e0;
  --info-border: #35506b;
  --chip-ink: #b5b0a2;
  --avoid-ink: #e0a08e;
  /* Priority badges carry dark ink (see --on-accent), and the badge text is
     small bold caps — so these are lightened past the first guess to clear
     4.5:1 rather than settling for the large-text 3:1 allowance.
     P1 4.63 · P2 5.41 · P4/5 5.34. */
  --appeal-bg: #2b1b25;
  --appeal-ink: #e0a3c4;
  --appeal-rule: #5c3a4c;
  --prio1: #cf6040;
  --prio2: #c07f2a;
  --prio45: #968b70;

  --enlarge-bg: rgba(38,33,25,.92);

  /* 95% of the ink in Cowork's 65 inlined timelines is greyscale, so a straight
     invert reads correctly; hue-rotate(180deg) puts the ~4% of saturated accent
     colours (blue/amber/orange/green/pink) back near their original hues. */
  --svg-figure-filter: invert(1) hue-rotate(180deg);
}

/* ---------- Detail page ---------- */
body.coin-detail {
  font-family: Georgia, serif;
  font-size: calc(1rem * var(--fs-scale));
  max-width: 920px;
  margin: 0 auto;
  padding: 2em 1.5em;
  color: var(--ink);
  line-height: 1.7;
  background: var(--bg);
}

body.coin-detail h1 {
  font-size: 1.65em;
  border-bottom: 3px solid var(--link);
  padding-bottom: .4em;
  color: var(--ink-strong);
  margin-bottom: .25em;
}

body.coin-detail h2 {
  font-size: 1.1em;
  color: var(--ink-accent);
  border-bottom: 1px solid var(--rule);
  padding-bottom: .2em;
  margin-top: 2.2em;
  letter-spacing: .03em;
  text-transform: uppercase;
}

.breadcrumb {
  font-size: calc(.85rem * var(--fs-small));
  margin-bottom: 1em;
}
.breadcrumb a { color: var(--link); text-decoration: none; }
.breadcrumb a:hover { text-decoration: underline; }

.subtitle {
  color: var(--muted2);
  font-style: italic;
  font-size: .93em;
  margin-bottom: 1.8em;
}

.summary {
  background: var(--surface-tint);
  border-left: 4px solid var(--gold);
  padding: 1em 1.3em;
  border-radius: 0 8px 8px 0;
  margin: 1.3em 0;
}
.summary p { margin: .35em 0; font-size: .97em; }

/* Private money line (Cost / Est. value) — only rendered behind auth. A left
   accent + muted tone signals "owner-only" without shouting. */
.summary p.private-money {
  margin-top: .5em;
  padding-left: .6em;
  border-left: 3px solid var(--gold);
  color: var(--ink-accent);
}
.summary p.private-money .as-of { color: var(--muted3); font-style: italic; font-size: .9em; }
/* The authored point estimate inside the est.-value range. */
.summary p.private-money .est-median { color: var(--ink-caption); font-size: .92em; }
/* This coin's own prior auction result: the sale reference, and the evidence
   that identified the coin with that lot. Both deliberately quieter than the
   figure — the number is the point, the provenance is the justification. */
.summary p.private-money .own-sale-ref { color: var(--ink-caption); font-size: .9em; }
.summary p.private-money .own-sale-match { color: var(--muted3); font-size: .85em; font-style: italic; }
/* Auction hammer beside the all-in Cost. Quieter than the figure it qualifies:
   the all-in is what John paid, the hammer is context for it. */
.summary p.private-money .hammer { color: var(--ink-caption); font-size: .92em; }

.two-col {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.6em;
  margin: 1.4em 0;
}
.two-col figure { margin: 0; text-align: center; }
.two-col img {
  max-width: 100%;
  border-radius: 6px;
  box-shadow: 0 2px 8px rgba(0,0,0,.22);
}

/* Round wells for the coin faces, opt-in per specimen via `circular_wells`
   (2026-08-11-specimen-circular-wells.md). The treatment is Cowork's, proven on
   articles/antony-legions: square box, 50% radius, object-fit:cover, a hairline
   ring and a small hover lift.
   The ARTICLE version uses that page's own tokens (--hairline, --flan-deep,
   --bronze); those do not exist on the site, so the site tokens closest in role
   are used here — do not copy the article's declaration across verbatim.
   Only obverse/reverse ever get this: a detail shot is a deliberate crop and an
   edge view is a long thin strip, so DISC_VIEWS in jsb_coins_specimen.py keeps
   them out. */
/* NOT scoped to .two-col: the same flag drives the specimen page's figures AND
   the type page's specimen thumbnails, and John noticed the mismatch in a
   single click — square in the list, round on the coin's own page
   (2026-08-11-type-page-specimen-thumbs.md). One rule, both places. */
.disc {
  display: block;
  width: 100%;
  aspect-ratio: 1;
  border-radius: 50%;
  overflow: hidden;
  border: 2px solid var(--rule-soft);
  background: var(--surface-sunken);
  transition: transform 160ms ease, border-color 160ms ease;
}
.disc img {
  width: 100%;
  height: 100%;
  /* CONTAIN, not cover (John, 2026-08-11: "now you made it so that the image is
     cropped too much. previous way the type page showed coin in well was
     better"). cover fills the circle by centre-cropping, which eats flan on any
     face that is not square. contain fits the whole picture inside the well and
     lets the well's own ground show above and below it.
     For a properly re-cropped square face the two are IDENTICAL, so this costs
     nothing where the images are already right and rescues every face where
     they are not — which is why it beats maintaining a list of coins whose
     images are safe to crop. */
  object-fit: contain;
  display: block;
  /* The ring is the frame now; the rectangular image's own radius, drop shadow
     and max-height would all fight the circle — max-height in particular would
     letterbox the thumbnail into an oval on the type page. */
  border-radius: 0;
  box-shadow: none;
  max-width: none;
  max-height: none;
}
a:hover .disc { transform: scale(1.05); border-color: var(--gold); }
@media (prefers-reduced-motion: reduce) {
  .disc { transition: none; }
  a:hover .disc { transform: none; }
}
/* SPECIFICITY, not duplication. The card thumbnails carry their own sizing —
   `.coin-card .coin-images a img` (0,3,1) and a `body.coin-type` variant
   (0,4,1) — both of which outrank a bare `.disc img` (0,1,1). The result was
   the two pages disagreeing about the SAME image: the specimen page filled the
   circle and cropped, while the type page kept height:auto and sat the picture
   letterboxed inside the circle, uncropped. John caught it by clicking through.
   These selectors exist only to win that contest; the declarations are the same
   ones .disc img already sets. */
.coin-card .coin-images a .disc img,
body.coin-type .coin-card .coin-images a .disc img,
.specimen-card .coin-images a .disc img {
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  object-fit: contain;
}
.two-col figcaption {
  font-size: calc(.8rem * var(--fs-small));
  color: var(--muted);
  margin-top: .4em;
  font-style: italic;
}
/* Rich captions (Related Coin Images): long match-evidence + mandatory image
   credit, shown in full. Left-aligned and upright so they stay readable, with
   the credit/link legible. */
.two-col figcaption.rich {
  font-style: normal;
  text-align: left;
  font-size: calc(.82rem * var(--fs-small));
  line-height: 1.5;
}
.two-col figcaption.rich a {
  color: var(--link);
  text-decoration: underline;
  word-break: break-word;
}

.prov-list { margin: .4em 0; padding-left: 1.6em; }
.prov-list li { margin: .35em 0; }

table.tags { border-collapse: collapse; width: 100%; font-size: .88em; margin: .8em 0; }
table.tags td { padding: .55em .75em; vertical-align: top; border: 1px solid var(--rule-table); }
/* Zebra striping removed: the <pre> inside the transcript cell already
   provides the label-vs-transcript contrast, so the stripe just made the
   first row's label look special and shaded the rest. */
.tag-lbl { font-weight: bold; color: var(--ink-accent); width: 25%; white-space: nowrap; }

pre {
  font-family: monospace;
  font-size: .85em;
  background: var(--surface-sunken);
  padding: .5em .9em;
  border-radius: 4px;
  margin: .3em 0;
  white-space: pre-wrap;
}

.open {
  background: var(--open-bg);
  border: 1px solid var(--rule-open);
  border-radius: 8px;
  padding: 1em 1.3em;
}
.open ol { margin: .3em 0; padding-left: 1.4em; }
.open li { margin: .3em 0; font-size: .92em; }

.note {
  font-size: calc(.78rem * var(--fs-small));
  color: var(--muted4);
  border-top: 1px solid var(--rule-soft);
  padding-top: .7em;
  margin-top: 2.5em;
}

/* Markdown body (historical context) — keep close to the rest of the page. */
body.coin-detail h3 {
  font-size: 1em;
  color: var(--ink-accent);
  margin-top: 1.6em;
  margin-bottom: .3em;
}
body.coin-detail h4 {
  font-size: .95em;
  color: var(--ink-accent);
  margin-top: 1.3em;
  margin-bottom: .2em;
}
body.coin-detail blockquote {
  border-left: 3px solid var(--rule);
  margin: .8em 0;
  padding: .2em 1em;
  color: var(--ink-quote);
  font-style: italic;
}
/* weight_note shown as a smaller qualifier after the structured weight value. */
body.coin-detail .phys-note {
  font-size: .9em;
  color: var(--ink-caption);
}
/* Shown above an auction photograph standing in for the owner's own photos, on
   a coin that has been won but not yet delivered. The label matters: without it
   a visitor would reasonably read the auction house's image as John's. All
   colour via tokens so it follows the light/dark toggle. */
body.coin-detail .photo-pending {
  margin: 0 0 .8em;
  padding: .45em .8em;
  border-left: 3px solid var(--rule);
  background: var(--panel-bg);
  color: var(--ink-caption);
  font-size: calc(.9rem * var(--fs-small));
  font-style: italic;
}
/* "Earlier descriptions" section: verbatim auction/dealer cataloguing. */
body.coin-detail .earlier-desc { margin: 0 0 1.4em; }
body.coin-detail .earlier-desc:last-child { margin-bottom: 0; }
body.coin-detail h3.ed-label {
  margin: 0 0 .2em;
  font-size: 1em;
  font-weight: 600;
}
body.coin-detail .earlier-desc blockquote p { margin: .4em 0; }
body.coin-detail .earlier-desc blockquote p:first-child { margin-top: 0; }
body.coin-detail .earlier-desc blockquote p:last-child { margin-bottom: 0; }
body.coin-detail .ed-credit {
  margin: .3em 0 0;
  font-size: calc(.85rem * var(--fs-small));
  color: var(--ink-credit);
}
body.coin-detail code {
  font-family: monospace;
  background: var(--surface-sunken);
  padding: .05em .35em;
  border-radius: 3px;
  font-size: .9em;
}
body.coin-detail ul, body.coin-detail ol { padding-left: 1.6em; }
body.coin-detail li { margin: .25em 0; }

@media (max-width: 620px) {
  .two-col { grid-template-columns: 1fr; }
}

/* ---------- Catalog index ---------- */
body.coin-catalog {
  font-family: Georgia, serif;
  font-size: calc(1rem * var(--fs-scale));
  max-width: 1200px;
  margin: 0 auto;
  padding: 2em 1.5em;
  color: var(--ink);
  background: var(--bg);
}

body.coin-catalog h1 {
  font-size: 1.65em;
  border-bottom: 3px solid var(--link);
  padding-bottom: .4em;
  color: var(--ink-strong);
  margin-bottom: .25em;
}

body.coin-catalog .subtitle {
  color: var(--muted2);
  font-style: italic;
  font-size: .93em;
  margin-bottom: 1.4em;
}

/* Link button to the Articles page. The banners themselves used to live on the
   catalog; this replaced them (2026-07-26) so the catalog opens on coins. Styled
   as a quiet dark chip that echoes the banner ground it leads to, rather than as
   a loud primary button competing with the coin grid. */
.articles-cta { margin: .2em 0 1.4em; }
.articles-link {
  display: inline-block;
  background: var(--banner-bg);
  border: 1px solid var(--banner-border);
  border-radius: 8px;
  padding: .55em 1.1em;
  color: var(--banner-accent);
  text-decoration: none;
  font-size: .92em;
  letter-spacing: .02em;
  transition: box-shadow .18s ease, transform .18s ease;
}
.articles-link:hover {
  box-shadow: 0 4px 14px rgba(0,0,0,.25);
  transform: translateY(-1px);
  text-decoration: underline;
}
.articles-link:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

/* Informational / historical articles — a stack of compact dark "banner"
   teasers below the catalog masthead, each a miniature of the article's own
   hero: mono eyebrow + title + lede on the left, a small graphic on the right,
   the whole banner a link. The dark ground deliberately contrasts the parchment
   catalog and previews the destination page's look. */
.feature-strip { margin: .5em 0 1.6em; }

.feature-banner {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 1.4em;
  align-items: center;
  background: var(--banner-bg);
  border: 1px solid var(--banner-border);
  border-radius: 8px;
  padding: 1.1em 1.35em;
  text-decoration: none;
  transition: box-shadow .18s ease, transform .18s ease;
}
.feature-banner + .feature-banner { margin-top: .8em; }
.feature-banner:hover {
  box-shadow: 0 6px 18px rgba(0,0,0,.28);
  transform: translateY(-1px);
}
.feature-banner .fb-eyebrow {
  font-family: "SF Mono", Menlo, Consolas, monospace;
  font-size: calc(.68rem * var(--fs-small));
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--banner-accent);
  margin: 0 0 .45em;
}
.feature-banner .fb-title {
  font-size: 1.5em;
  font-weight: bold;
  color: var(--banner-title);
  letter-spacing: .02em;
  line-height: 1.1;
  margin: 0 0 .4em;
}
.feature-banner .fb-lede {
  margin: 0;
  font-size: .92em;
  font-style: normal;
  color: var(--banner-lede);
  max-width: 54ch;
}
.feature-banner .fb-cta {
  display: inline-block;
  margin-top: .7em;
  font-size: calc(.8rem * var(--fs-small));
  letter-spacing: .04em;
  color: var(--banner-accent);
}
.feature-banner:hover .fb-cta { text-decoration: underline; }

/* The miniature strike graphic (right column). */
.feature-banner .fb-graphic {
  align-self: stretch;
  display: flex;
  align-items: center;
  padding-left: 1.2em;
  border-left: 1px solid var(--banner-rule);
}
.feature-banner .fb-svg {
  display: block;
  width: 118px;
  height: auto;
}
/* Image-graphic variant (a coin, a map…) — small, rounded, capped. */
.feature-banner .fb-img {
  display: block;
  width: 96px;
  height: 96px;
  object-fit: cover;
  border-radius: 6px;
  box-shadow: 0 2px 6px rgba(0,0,0,.3);
}
/* Hover "strike": hammer and punch drop, as on the live article. */
.feature-banner .fb-hammer,
.feature-banner .fb-punch {
  transition: transform .5s cubic-bezier(.4, 0, 1, 1);
}
.feature-banner:hover .fb-hammer { transform: translateY(16px); }
.feature-banner:hover .fb-punch  { transform: translateY(11px); }

@media (prefers-reduced-motion: reduce) {
  .feature-banner:hover .fb-hammer,
  .feature-banner:hover .fb-punch { transform: none; }
}

/* Narrow screens: stack graphic under the text, like the article hero. */
@media (max-width: 620px) {
  .feature-banner {
    grid-template-columns: 1fr;
    gap: 1em;
  }
  .feature-banner .fb-graphic {
    padding-left: 0;
    border-left: 0;
    border-top: 1px solid var(--banner-rule);
    padding-top: 1em;
    justify-content: center;
  }
  .feature-banner .fb-svg { width: 140px; }
}

/* "Show more" expander — CSS-only, driven by a visually hidden checkbox (small
   overflow) or radio group (two-step reveal) so overflow articles work without
   JS. Collapsed banners live in .fb-hidden / .fb-g1 / .fb-g2. */
.feature-strip .fb-more-toggle,
.feature-strip .fb-state {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  clip: rect(0 0 0 0);
  overflow: hidden;
}
/* spacing above each collapsed group's banners (collapses through the wrapper
   div to the banner above, so no double gap) */
.feature-strip .fb-hidden .feature-banner,
.feature-strip .fb-g1 .feature-banner,
.feature-strip .fb-g2 .feature-banner { margin-top: .8em; }

.feature-strip .fb-hidden,
.feature-strip .fb-g1,
.feature-strip .fb-g2 { display: none; }
.feature-strip .fb-more-toggle:checked ~ .fb-hidden { display: block; }
.feature-strip #fb-step:checked ~ .fb-g1,
.feature-strip #fb-all:checked ~ .fb-g1,
.feature-strip #fb-all:checked ~ .fb-g2 { display: block; }

.feature-strip .fb-more-label {
  display: block;
  text-align: center;
  margin-top: .9em;
  padding: .55em;
  font-size: .9em;
  font-weight: bold;
  color: var(--link);
  background: var(--surface-tint);
  border: 1px dashed var(--rule);
  border-radius: 8px;
  cursor: pointer;
  user-select: none;
  transition: background .15s ease, color .15s ease;
}
.feature-strip .fb-more-label:hover { background: var(--surface-tint-hover); color: var(--ink-accent); }
.feature-strip .fb-more-close { display: none; }
.feature-strip .fb-more-toggle:checked ~ .fb-more-label .fb-more-open { display: none; }
.feature-strip .fb-more-toggle:checked ~ .fb-more-label .fb-more-close { display: inline; }
.feature-strip .fb-more-toggle:focus-visible ~ .fb-more-label {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}

/* Two-step control: a row of labels, only the ones valid for the current
   radio state are shown. */
.feature-strip .fb-controls {
  display: flex;
  flex-wrap: wrap;
  gap: .6em;
  margin-top: .9em;
}
.feature-strip .fb-controls .fb-more-label {
  display: none;
  flex: 1 1 12em;
  margin-top: 0;
}
.feature-strip #fb-collapsed:checked ~ .fb-controls .fb-ctl-step,
.feature-strip #fb-collapsed:checked ~ .fb-controls .fb-ctl-all,
.feature-strip #fb-step:checked ~ .fb-controls .fb-ctl-all,
.feature-strip #fb-step:checked ~ .fb-controls .fb-ctl-fewer,
.feature-strip #fb-all:checked ~ .fb-controls .fb-ctl-fewer { display: block; }
.feature-strip .fb-state:focus-visible ~ .fb-controls {
  outline: 2px solid var(--gold);
  outline-offset: 4px;
  border-radius: 8px;
}

#filter-bar {
  background: var(--surface-tint);
  border: 1px solid var(--rule);
  border-radius: 8px;
  padding: .7em 1em;
  margin-bottom: 1.4em;
  display: flex;
  flex-wrap: wrap;
  gap: .8em 1.2em;
  align-items: center;
  font-size: .9em;
}
#filter-bar label   { font-weight: bold; color: var(--ink-accent); margin-right: .3em; }
/* Count beside the Recent Acquisitions controls. Says "showing 10 of 97" when
   the view is truncated and just "97 specimens" when it is not, so the page
   never quietly hides most of the collection. */
#filter-bar .filter-count {
  color: var(--ink-caption);
  font-size: calc(.9rem * var(--fs-small));
  font-style: italic;
  margin-left: .4em;
}
#filter-bar select,
#filter-bar input[type="text"] {
  padding: .25em .4em;
  font-size: .9em;
  font-family: inherit;
  border: 1px solid var(--rule);
  background: var(--surface);
  border-radius: 4px;
}
#filter-bar input[type="text"] { min-width: 16em; }

.catalog-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 20px;
}

.coin-card {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: 8px;
  padding: 14px 16px 16px;
  box-shadow: 0 2px 6px rgba(0,0,0,.08);
  display: flex;
  flex-direction: column;
}

.coin-header {
  font-size: 1.05em;
  font-weight: bold;
  color: var(--ink-strong);
  margin-bottom: .25em;
}
.coin-header a { color: inherit; text-decoration: none; }
.coin-header a:hover { text-decoration: underline; }

.coin-meta {
  color: var(--ink-accent);
  font-size: calc(.85rem * var(--fs-small));
  margin-bottom: .6em;
}

.coin-text-block {
  font-size: .9em;
  margin: .3em 0;
}
.coin-text-block .label,
.coin-ref     .label { font-weight: bold; color: var(--ink-accent); }
.coin-ref { font-size: .85em; margin: .3em 0 .4em; }

.coin-images {
  margin-top: .6em;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: .8em;
}
.coin-image-block { text-align: center; }
.coin-image-block img {
  max-width: 100%;
  height: auto;
  max-height: 200px;
  border-radius: 6px;
  background: var(--surface-sunken);
  box-shadow: 0 2px 6px rgba(0,0,0,.18);
  transition: transform .15s ease, box-shadow .15s ease;
}
.coin-image-block img:hover {
  transform: translateY(-1px);
  box-shadow: 0 4px 10px rgba(0,0,0,.28);
}
.coin-caption { font-size: calc(.8rem * var(--fs-small)); color: var(--muted); margin-top: .3em; font-style: italic; }
.coin-caption .view-label { font-weight: bold; }

/* Card images — used by the catalog index hero and the obverse/reverse pair
   on type-page specimen lists + recent acquisitions. Without these caps the
   renderer's bare <a><img></a> would display at natural JPEG width (~1200px). */
.coin-card .hero {
  display: block;
  text-align: center;
  margin: .6em 0 .4em;
}
.coin-card .hero img {
  max-width: 100%;
  max-height: 220px;
  width: auto;
  height: auto;
  border-radius: 6px;
  background: var(--surface-sunken);
  box-shadow: 0 2px 6px rgba(0,0,0,.18);
  transition: transform .15s ease, box-shadow .15s ease;
}
.coin-card .hero img:hover {
  transform: translateY(-1px);
  box-shadow: 0 4px 10px rgba(0,0,0,.28);
}
.coin-card .coin-images a {
  display: block;
  text-align: center;
}
.coin-card .coin-images a img {
  max-width: 100%;
  max-height: 180px;
  width: auto;
  height: auto;
  border-radius: 6px;
  background: var(--surface-sunken);
  box-shadow: 0 2px 6px rgba(0,0,0,.18);
  transition: transform .15s ease, box-shadow .15s ease;
}
.coin-card .coin-images a img:hover {
  transform: translateY(-1px);
  box-shadow: 0 4px 10px rgba(0,0,0,.28);
}

/* Type page has more headroom per card than the catalog grid — let the
   obverse/reverse pair render larger. */
body.coin-type .coin-card .coin-images a img {
  max-height: 500px;
}

/* A coin catalogued from the auction house's photograph, not yet delivered:
   ONE image standing in for the pair. The grid is 1fr 1fr for a real
   obverse+reverse, so a lone image lands in the left column at half width —
   and these are ~2.08:1 crops showing BOTH sides, so half width made them
   half the size they should be. One column, full width, for the single-image
   case only; a real pair is untouched. */
.coin-images.auction-photo {
  grid-template-columns: 1fr;
}
.coin-card .coin-images.auction-photo a img,
.specimen-card .coin-images.auction-photo a img {
  width: 100%;
  max-width: 100%;
  height: auto;
}
/* The pair-sized max-heights would crop a full-width 2:1 image; let its own
   aspect ratio decide the height instead. */
body.coin-catalog .coin-card .coin-images.auction-photo a img,
body.coin-type .coin-card .coin-images.auction-photo a img,
body.coin-catalog .specimen-card .coin-images.auction-photo a img {
  max-height: none;
}

/* ---------- Wanted: collapse to title ---------- */
/* The header is the click target, so it must look like one. */
body.coin-wanted .want-header {
  cursor: pointer;
  position: relative;
  padding-right: 1.6em;   /* room for the chit */
}
body.coin-wanted .want-header:hover { background: var(--surface-tint); }
body.coin-wanted .want-header:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}
/* Links and buttons inside the header keep their own cursor — the JS lets their
   clicks through, so the pointer should not promise a collapse. */
body.coin-wanted .want-header a,
body.coin-wanted .want-header button { cursor: pointer; }

/* The chit: a rotating caret rather than swapped glyphs, so there is no reflow
   and no second character to keep in step with the state. */
body.coin-wanted .want-chit {
  position: absolute;
  right: .35em;
  top: 50%;
  width: .5em;
  height: .5em;
  margin-top: -.35em;
  border-right: 2px solid var(--ink-caption);
  border-bottom: 2px solid var(--ink-caption);
  transform: rotate(45deg);
  transition: transform 120ms ease;
}
body.coin-wanted .want-card.collapsed .want-chit {
  transform: rotate(-45deg);
  margin-top: -.15em;
}
body.coin-wanted .want-card.collapsed .want-body { display: none; }
/* Collapsed cards sit tighter so a long list reads as an index. */
body.coin-wanted .want-card.collapsed { padding-bottom: .2em; }

/* ---------- Reports page (private) ---------- */
/* All colour via existing tokens, so light/dark and the text-size control work
   with no new plumbing. */
/* Every page body must carry this or the "Body text" lever silently does
   nothing on it — Reports shipped without it and the lever was dead here until
   2026-08-07. 1rem at the default scale, so this changed no rendered size. */
body.coin-reports { font-size: calc(1rem * var(--fs-scale)); }
body.coin-reports .report-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 1em;
  margin: 1.2em 0 2em;
}
body.coin-reports .report-card {
  border: 1px solid var(--rule-card);
  border-radius: 8px;
  padding: .9em 1em;
  background: var(--panel-bg);
}
body.coin-reports .rc-label {
  font-size: calc(.85rem * var(--fs-small));
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--ink-caption);
}
body.coin-reports .rc-value {
  font-size: 1.5em;
  font-weight: bold;
  color: var(--ink-accent);
  margin: .15em 0 .2em;
}
/* The coverage line is the point of these cards, not decoration: a total with
   no "51 of 97" beside it reads as a total for the whole collection. */
body.coin-reports .rc-note {
  font-size: calc(.85rem * var(--fs-small));
  color: var(--ink-caption);
}
body.coin-reports .report-note {
  font-size: calc(.9rem * var(--fs-small));
  color: var(--ink-caption);
  font-style: italic;
  margin: -.4em 0 .8em;
}
body.coin-reports .report-table {
  border-collapse: collapse;
  width: 100%;
  margin-bottom: 2em;
}
body.coin-reports .report-table th,
body.coin-reports .report-table td {
  border-bottom: 1px solid var(--rule-table);
  padding: .4em .7em;
  text-align: left;
}
body.coin-reports .report-table th {
  background: var(--surface-tint);
  color: var(--ink-accent);
  font-size: .9em;
}
/* Numeric columns right-align; the first column is always the label. */
body.coin-reports .report-table td:not(:first-child),
body.coin-reports .report-table th:not(:first-child) { text-align: right; }
body.coin-reports .report-table tbody tr:hover { background: var(--surface-sunken); }

/* Collapsed derivation help. <details> is native — no JS, nothing runs unless
   it is opened, and it costs nothing when closed. */
body.coin-reports .report-help {
  border: 1px solid var(--rule-soft);
  border-radius: 8px;
  padding: .5em .9em;
  margin: 0 0 2em;
  background: var(--surface-tint);
}
body.coin-reports .report-help > summary {
  cursor: pointer;
  font-weight: bold;
  color: var(--ink-accent);
  font-size: .95em;
}
body.coin-reports .report-help[open] > summary { margin-bottom: .6em; }
body.coin-reports .report-help h3 {
  font-size: 1em;
  color: var(--ink-accent);
  margin: 1em 0 .4em;
}
body.coin-reports .report-help code {
  background: var(--surface-sunken);
  padding: .05em .35em;
  border-radius: 3px;
  font-size: .92em;
}
/* Derivation is on the card's title attribute, so the cursor should say so. */
body.coin-reports .report-card[title] { cursor: help; }

/* ---------- Type page ---------- */
body.coin-type {
  font-family: Georgia, serif;
  font-size: calc(1rem * var(--fs-scale));
  max-width: 920px;
  margin: 0 auto;
  padding: 2em 1.5em;
  color: var(--ink);
  line-height: 1.7;
  background: var(--bg);
}
body.coin-type h1 {
  font-size: 1.65em;
  border-bottom: 3px solid var(--link);
  padding-bottom: .4em;
  color: var(--ink-strong);
  margin-bottom: .25em;
}
body.coin-type h2 {
  font-size: 1.1em;
  color: var(--ink-accent);
  border-bottom: 1px solid var(--rule);
  padding-bottom: .2em;
  margin-top: 2.2em;
  letter-spacing: .03em;
  text-transform: uppercase;
}
body.coin-type h3 {
  font-size: 1em;
  color: var(--ink-accent);
  margin-top: 1.6em;
  margin-bottom: .3em;
}

dl.type-facts {
  margin: .8em 0 0;
  display: grid;
  grid-template-columns: max-content 1fr;
  column-gap: 1em;
  row-gap: .25em;
  font-size: .92em;
}
dl.type-facts dt { font-weight: bold; color: var(--ink-accent); }
dl.type-facts dd { margin: 0; }

.type-map {
  margin: 1.6em 0;
  text-align: center;
}
/* Each map (main + inset) is its own <figure>. */
.type-map figure { margin: 0 0 1.2em; }
.type-map .type-map-inset { margin-top: 1em; }
.type-map img {
  max-width: 100%;
  border-radius: 6px;
  box-shadow: 0 2px 8px rgba(0,0,0,.22);
}
/* Inset is a tighter zoom — cap displayed width so it doesn't dominate. */
.type-map .type-map-inset img {
  max-width: 540px;
  width: 100%;
}
.type-map .map-caption {
  margin: .7em auto 0;
  max-width: 600px;
  font-size: calc(.9rem * var(--fs-small));
  color: var(--muted-strong);
  font-style: italic;
  text-align: left;
}
.type-map .map-caption p { margin: .3em 0; }

ul.references-docs { list-style: disc; padding-left: 1.4em; }
ul.references-docs li { margin: .6em 0; font-size: .93em; }
ul.references-docs .ref-citation {
  color: var(--muted-strong);
  font-size: .88em;
  font-style: italic;
}

ul.catalogue-refs {
  list-style: none;
  padding: 0;
  margin: .6em 0 0;
}
ul.catalogue-refs li {
  padding: .25em 0;
  font-size: .94em;
}
.ref-role {
  display: inline-block;
  /* .6768rem, not .72rem: was .72em inside ul.catalogue-refs li (.94em). */
  font-size: calc(.6768rem * var(--fs-small));
  text-transform: uppercase;
  letter-spacing: .04em;
  border-radius: 4px;
  padding: .1em .5em;
  margin-left: .3em;
  vertical-align: 1px;
}
.ref-role-current     { background: var(--ok-bg); color: var(--ok-ink); border: 1px solid var(--rule-ok); }
.ref-role-superseded  { background: var(--warn-bg); color: var(--warn-ink); border: 1px solid var(--rule); font-style: italic; }
.ref-note {
  font-size: .85em;
  color: var(--muted2);
  font-style: italic;
  margin-left: .35em;
}

.spec-count {
  display: inline-block;
  background: var(--gold);
  color: var(--on-accent);
  /* .735rem, not .7rem: was .7em inside .coin-header (1.05em). */
  font-size: calc(.735rem * var(--fs-small));
  padding: .15em .55em;
  border-radius: 12px;
  vertical-align: middle;
  margin-left: .35em;
  letter-spacing: .05em;
}
.suffix { color: var(--link); font-style: italic; font-size: .85em; }

.footer-link {
  margin-top: 2.5em;
  padding-top: .8em;
  border-top: 1px solid var(--rule-soft);
  font-size: .9em;
  color: var(--ink-accent);
}

/* ---------- Recent acquisitions ---------- */
.specimen-card .recent-date {
  display: inline-block;
  font-size: calc(.78rem * var(--fs-small));
  font-weight: bold;
  color: var(--ink-accent);
  background: var(--surface-tint);
  border: 1px solid var(--rule);
  border-radius: 4px;
  padding: .1em .55em;
  margin-bottom: .4em;
  letter-spacing: .03em;
}
.recent-actions {
  margin-top: .6em;
  font-size: .85em;
  text-align: right;
}
.recent-actions a { color: var(--link); }

/* ---------- Regions view ---------- */
section.region-block {
  margin-top: 2em;
}
.region-totals {
  font-size: calc(.7rem * var(--fs-small));
  font-weight: normal;
  color: var(--muted2);
  letter-spacing: 0;
  text-transform: none;
  font-style: italic;
}
ul.region-list {
  list-style: none;
  padding: 0;
  margin: .6em 0 0;
}
ul.region-list > li {
  padding: .55em 0;
  border-bottom: 1px solid var(--rule-soft2);
}
ul.region-list .region-meta {
  font-size: .85em;
  color: var(--ink-accent);
  margin-top: .15em;
}

/* ---------- Mobile (phones, narrow tablets) ----------
 * Aggressive: this is the "at a dealer, holding my phone" use case —
 * quick browse, not deep read. Compact thumbs, terser layout, no two-
 * column anything. Use !important on the image caps because the
 * desktop rules and the mobile rules tie on specificity and we want
 * the mobile cap to win unambiguously regardless of CSS source order.
 */
@media (max-width: 720px) {
  body.coin-detail,
  body.coin-type,
  body.coin-catalog {
    padding: .8em .6em;
  }

  /* Headings tighter. */
  body.coin-detail h1,
  body.coin-type h1,
  body.coin-catalog h1 {
    font-size: 1.3em;
  }

  /* Specimen page (coin.php) — .two-col collapses to 1 column at 620px.
     Cap heights so each photo stays a tidy phone-frame and the page
     doesn't scroll forever. */
  body.coin-detail .two-col img {
    max-height: 320px !important;
    width: auto;
  }

  /* Catalog index — small thumbs, two-side-by-side. */
  body.coin-catalog .coin-card .coin-images a img {
    max-height: 90px !important;
  }

  /* Type page "My specimens" cards — bigger than catalog, smaller than
     desktop. Override the 500px desktop rule unambiguously. */
  body.coin-type .coin-card .coin-images a img {
    max-height: 180px !important;
  }

  /* Recent acquisitions feed — same compact style as the catalog. */
  body.coin-catalog .specimen-card .coin-images a img {
    max-height: 120px !important;
  }

  /* Text-size widget tucks closer to the corner on a phone, matching the
     articles' reader at 12px/12px. The panel follows it up. */
  .fs-btn { right: 12px; bottom: 12px; }
  .fs-panel { right: 12px; bottom: 68px; min-width: min(17em, calc(100vw - 24px)); }

  /* Single auction photo standing in for the pair spans the full card, so the
     pair-sized caps above would crop it. Those carry !important, so this must
     too — specificity alone would lose to them. */
  body.coin-catalog .coin-card .coin-images.auction-photo a img,
  body.coin-type .coin-card .coin-images.auction-photo a img,
  body.coin-catalog .specimen-card .coin-images.auction-photo a img {
    max-height: none !important;
  }

  /* Type-level map — must not dominate. */
  .type-map img {
    max-height: 220px !important;
  }

  /* Filter bar: stack the search box on its own row. */
  #filter-bar input[type="text"] {
    min-width: 0;
    flex: 1 1 100%;
  }

  /* Tag transcriptions: break the table into stacked label + body
     rows instead of trying to keep two columns. */
  table.tags,
  table.tags tbody,
  table.tags tr {
    display: block;
    width: 100%;
  }
  table.tags td {
    display: block;
    width: auto;
    border: none;
    padding: .25em 0;
    background: transparent !important;
  }
  table.tags td.tag-lbl {
    padding-top: .9em;
    padding-bottom: .1em;
    border-top: 1px solid var(--rule);
    width: auto;
    white-space: normal;
  }
  table.tags tr:first-child td.tag-lbl {
    border-top: none;
    padding-top: 0;
  }
  table.tags pre {
    font-size: .82em;
    padding: .4em .6em;
  }

  /* Catalogue references / region list / DL facts — keep compact. */
  dl.type-facts {
    grid-template-columns: max-content 1fr;
    column-gap: .6em;
    font-size: .88em;
  }
  ul.catalogue-refs li { font-size: .9em; }
  ul.references-docs li { font-size: .88em; }
}

/* ---------- Top bar: theme toggle + Log in/out ---------- */
/* One flex row in the page corner. page_header() emits the toggle before the
   auth bar so the auth state stays rightmost where it has always been. */
.top-bar {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: .9em;
  margin: 0 0 .3em;
  /* Kept relative although the text-size panel no longer anchors here (it went
     fixed, bottom-right, on 2026-08-06). Harmless, and other absolutely-placed
     children would still expect it. */
  position: relative;
}
.top-bar .auth-bar { margin: 0; }

/* Collection search, top-left of every page. The bar is flex-end, so
   margin-right:auto pins this left and leaves the theme toggle and the
   Log in/Log out control exactly where they were on the right. */
.site-search {
  margin: 0 auto 0 0;
  display: flex;
  min-width: 0;              /* let it shrink before the bar wraps */
}
.site-search input[type="search"] {
  font-family: inherit;
  font-size: calc(.82rem * var(--fs-small));
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: 4px;
  padding: .2em .6em;
  width: 20ch;
  max-width: 42vw;
  line-height: 1.6;
}
.site-search input[type="search"]:focus {
  outline: none;
  border-color: var(--link);
  width: 30ch;               /* room to read a longer query while typing */
}
.site-search input[type="search"]::placeholder { color: var(--ink-caption); opacity: .85; }
@media (max-width: 520px) {
  .site-search input[type="search"] { width: 14ch; }
  .site-search input[type="search"]:focus { width: 18ch; }
}
.filter-status { margin-left: auto; }

/* Coin / Type / Essay scope boxes, beside the search input. */
.search-scopes {
  display: flex;
  align-items: center;
  gap: .55em;
  margin-left: .6em;
  font-size: calc(.74rem * var(--fs-small));
  color: var(--ink-caption);
  white-space: nowrap;
}
.search-scopes .scope {
  display: inline-flex;
  align-items: center;
  gap: .22em;
  cursor: pointer;
}
.search-scopes input[type="checkbox"] {
  margin: 0;
  cursor: pointer;
  width: auto;          /* never inherit the text field's width */
  flex: 0 0 auto;
}
@media (max-width: 700px) {
  .search-scopes { gap: .4em; font-size: calc(.68rem * var(--fs-small)); }
}

/* Essay hits. Articles are not coin cards, so they get their own block above
   the grid — otherwise a search for "Legions" drops its single best result. */
.essay-results {
  margin: 0 0 1.6em;
  padding: .9em 1.1em;
  border-left: 3px solid var(--accent, #8a6d3b);
  background: var(--surface-tint, rgba(127,127,127,.06));
}
.essay-results h2 { margin: 0 0 .5em; font-size: 1.02em; }
.essay-count {
  font-weight: 400;
  font-size: .85em;
  color: var(--ink-caption);
}
.essay-hit { margin: .7em 0; }
.essay-hit a { font-weight: 600; }
.return-to-search {
  font-weight: 600;
}
.essay-hit p {
  margin: .2em 0 0;
  font-size: calc(.88rem * var(--fs-small));
  color: var(--ink-caption);
  line-height: 1.5;
}

.theme-toggle {
  font-family: inherit;
  font-size: calc(.8rem * var(--fs-small));
  color: var(--link);
  background: transparent;
  border: 1px solid var(--rule);
  border-radius: 4px;
  padding: .15em .6em;
  cursor: pointer;
  line-height: 1.6;
  white-space: nowrap;
}
.theme-toggle:hover { background: var(--surface-tint); }
.theme-toggle:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
/* Label is swapped by lightbox.js; the glyph keeps the button a stable width. */
.theme-toggle .tt-glyph { margin-right: .35em; }


/* ---------- Reader text-size panel ("Aa") ---------- */
/* Floating bottom-right, matching the articles' Aa widget (John, 2026-08-06:
   "just like the articles Aa button works"). Same 18px/18px offsets and the
   same 44px circular target, so the control sits in the same place whichever
   part of the site you are on.

   It is `fixed`, so it leaves .top-bar's flex flow entirely — the theme toggle
   and the auth link close up beside each other, which is why no placeholder is
   needed. A SOLID background is not decoration here: floating over body text,
   the old transparent button would have been unreadable. */
.fs-btn {
  position: fixed;
  right: 18px;
  bottom: 18px;
  z-index: 9000;
  width: 44px;
  height: 44px;
  font-family: Georgia, serif;
  font-size: 17px;
  font-weight: bold;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: 999px;
  cursor: pointer;
  line-height: 1;
  box-shadow: 0 4px 18px rgba(0,0,0,.22);
}
.fs-btn:hover { background: var(--surface-tint); }
.fs-btn:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

.fs-panel {
  /* Fixed too, and anchored to the button rather than to .top-bar: an absolute
     panel would resolve against the page box now that its trigger has left the
     flow, and land at the top of the document. Opens UPWARD — 18px offset plus
     the 44px button plus a small gap. */
  position: fixed;
  bottom: 74px;
  right: 18px;
  z-index: 9000;
  min-width: 17em;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: 6px;
  box-shadow: 0 6px 20px rgba(0,0,0,.28);
  padding: .7em .8em .6em;
  text-align: left;
}
.fs-panel[hidden] { display: none; }
.fs-row {
  display: flex;
  align-items: center;
  gap: .5em;
  padding: .3em 0;
}
.fs-label { flex: 1 1 auto; font-size: .88em; color: var(--ink); }
.fs-now {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .8em;
  color: var(--muted3);
  min-width: 4.4em;
  text-align: right;
}
.fs-controls { display: flex; gap: .25em; }
.fs-step {
  font-family: inherit;
  font-size: .95em;
  line-height: 1;
  width: 1.9em;
  height: 1.9em;
  color: var(--link);
  background: var(--surface-tint);
  border: 1px solid var(--rule);
  border-radius: 4px;
  cursor: pointer;
}
.fs-step:hover { background: var(--surface-tint-hover); }
.fs-step:focus-visible { outline: 2px solid var(--gold); outline-offset: 1px; }
.fs-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .6em;
  margin-top: .5em;
  padding-top: .5em;
  border-top: 1px solid var(--rule-soft);
}
.fs-reset {
  font-family: inherit;
  font-size: .8em;
  color: var(--link);
  background: transparent;
  border: 1px solid var(--rule);
  border-radius: 4px;
  padding: .2em .6em;
  cursor: pointer;
}
.fs-reset:hover { background: var(--surface-tint); }
.fs-note { font-size: .74em; color: var(--muted3); font-style: italic; }

/* ---------- Auth: corner Log in/out link + login page ---------- */
.auth-bar {
  text-align: right;
  font-size: calc(.8rem * var(--fs-small));
  margin: 0 0 .3em;
}
.auth-bar .auth-state { color: var(--muted4); font-style: italic; margin-right: .7em; }
.auth-link {
  color: var(--link);
  text-decoration: none;
  border-bottom: 1px solid transparent;
}
.auth-link:hover { border-bottom-color: var(--link); }

body.coin-login {
  font-family: Georgia, serif;
  background: var(--bg);
  color: var(--ink);
  min-height: 100vh;
  margin: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2em 1.2em;
}
.login-card {
  width: 100%;
  max-width: 380px;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: 10px;
  box-shadow: 0 4px 14px rgba(0,0,0,.1);
  padding: 1.8em 1.7em 1.6em;
}
.login-card h1 {
  font-size: 1.2em;
  color: var(--ink-strong);
  border-bottom: 3px solid var(--link);
  padding-bottom: .35em;
  margin: 0 0 .6em;
}
.login-lede { font-size: .9em; color: var(--ink-accent); margin: 0 0 1.2em; line-height: 1.5; }
.login-card label {
  display: block;
  font-weight: bold;
  color: var(--ink-accent);
  font-size: calc(.85rem * var(--fs-small));
  margin-bottom: .3em;
}
.login-card input[type="password"] {
  width: 100%;
  padding: .55em .6em;
  font-size: 1em;
  font-family: inherit;
  border: 1px solid var(--rule);
  border-radius: 5px;
  background: var(--surface-input);
  margin-bottom: 1em;
}
.login-card button {
  width: 100%;
  padding: .6em;
  font-size: .95em;
  font-family: inherit;
  font-weight: bold;
  color: var(--on-accent);
  background: var(--gold);
  border: 0;
  border-radius: 5px;
  cursor: pointer;
}
.login-card button:hover { background: var(--link); }
.login-error {
  background: var(--err-bg);
  border: 1px solid var(--rule-err);
  color: var(--err-ink);
  font-size: calc(.85rem * var(--fs-small));
  padding: .5em .7em;
  border-radius: 5px;
  margin: 0 0 1em;
}
.login-back { margin: 1.1em 0 0; font-size: calc(.82rem * var(--fs-small)); text-align: center; }
.login-back a { color: var(--link); text-decoration: none; }
.login-back a:hover { text-decoration: underline; }

/* ---------- Body graphics (historical-context figures) ----------
   Cowork drops a graphic in coins/<slug>/graphics/ and references it in the
   type body; render_type_body() wraps it in <figure class="body-figure">.
   Kept small (click to zoom via the lightbox); caption sits below. */
.body-figure {
  margin: 1.4em auto;
  max-width: 500px;
  text-align: center;
}
.body-figure img {
  max-width: 100%;
  height: auto;
  border-radius: 4px;
  box-shadow: 0 1px 4px rgba(0,0,0,.25);
}
.body-figure figcaption {
  margin-top: .5em;
  font-size: calc(.82rem * var(--fs-small));
  font-style: italic;
  color: var(--ink-caption);
  text-align: left;
  line-height: 1.4;
}
.body-figure figcaption a { color: var(--link); }

/* Per-figure image credit, collapsed. The pattern the Alexander essay proved
   and John asked for site-wide (2026-09-02): a small teal monospace summary
   under the caption, the attribution (markdown, linked) only on demand. Sits
   inside figcaption wherever there is one, so lightbox.js strips it (clone,
   remove details) before lifting the caption into the zoomed view. The full
   list stays on credits.php, reached from every page's footer. */
details.sources {
  margin: .4em 0 0;
  font-size: calc(.8rem * var(--fs-small));
  font-style: normal;
  text-align: left;
}
details.sources summary {
  cursor: pointer;
  color: var(--verdigris);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: calc(.68rem * var(--fs-small));
  letter-spacing: .08em;
  list-style-position: inside;
}
details.sources summary:hover { text-decoration: underline; }
details.sources .srclist { margin-top: .4em; color: var(--ink-credit); line-height: 1.45; overflow-wrap: anywhere; }
details.sources .srclist p { margin: .3em 0; font-size: inherit; }
details.sources .srclist a { color: var(--link); }
/* Centred figures (coin faces, two-col) keep the summary centred too. */
.two-col details.sources, figure.want-example details.sources { text-align: center; }
figure.want-example details.sources .srclist { text-align: left; }
/* Under a map the credit aligns with the map-caption box above it. */
.type-map details.sources { margin: .35em auto 0; max-width: 600px; }
/* On a comparanda card, under the photos. */
.coin-card.comparandum details.sources { margin: .4em 0 0; }

/* Zoom-in cursor cue on any lightbox-enabled image link (tagged by lightbox.js). */
a.lb-zoom { cursor: zoom-in; }

/* Inline-SVG body figure (figure.svg-figure): the .svg is inlined (not an <img>)
   so its embedded <a href> coin links work. Sized like a raster figure; the
   viewBox handles scaling. An "Enlarge" button (added by lightbox.js) opens a
   larger cloned copy — click-to-zoom is NOT used here so link clicks navigate. */
.body-figure.svg-figure { position: relative; }
.body-figure.svg-figure svg {
  width: 100%;
  height: auto;
  display: block;
  /* none in light; invert+hue-rotate in dark (see :root[data-theme="dark"]). */
  filter: var(--svg-figure-filter);
}
.body-figure.svg-figure .enlarge {
  position: absolute;
  top: .3em;
  right: .3em;
  font-size: calc(.72rem * var(--fs-small));
  font-family: Georgia, serif;
  color: var(--ink-accent);
  background: var(--enlarge-bg);
  border: 1px solid var(--rule);
  border-radius: 3px;
  padding: .2em .5em;
  cursor: pointer;
}
.body-figure.svg-figure .enlarge:hover,
.body-figure.svg-figure .enlarge:focus-visible {
  color: var(--link-hot);
  border-color: var(--rule-hot);
  outline: none;
}

/* Enlarge panel overlay for inline-SVG figures (a light, scrollable panel —
   SVG diagrams can be wide — distinct from the dark image lightbox above). */
.lb-panel-overlay {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 3vmin;
  background: rgba(18,22,26,.84);
}
.lb-panel-overlay[hidden] { display: none; }
.lb-panel {
  position: relative;
  background: var(--panel-bg);
  border-radius: 3px;
  width: min(1200px, 96vw);
  max-height: 94vh;
  overflow: auto;
  padding: clamp(1.5rem, 3vw, 2.6rem);
  box-shadow: 0 24px 70px rgba(0,0,0,.55);
}
.lb-panel-close {
  position: absolute;
  top: .6rem;
  right: .6rem;
  font-size: calc(.78rem * var(--fs-small));
  font-family: Georgia, serif;
  color: var(--ink-accent);
  background: var(--surface-sunken);
  border: 1px solid var(--rule);
  border-radius: 3px;
  padding: .3em .6em;
  cursor: pointer;
}
.lb-panel-close:hover,
.lb-panel-close:focus-visible { color: var(--link-hot); border-color: var(--rule-hot); outline: none; }
.lb-panel-body figure { margin: 0; max-width: none; }
.lb-panel-body svg { width: 100%; height: auto; filter: var(--svg-figure-filter); }
.lb-panel-body figcaption { margin-top: 1em; font-size: calc(.85rem * var(--fs-small)); font-style: italic; color: var(--ink-caption); }

/* ---------- Image lightbox overlay (lightbox.js) ---------- */
.lb-overlay {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 3vmin;
  background: rgba(0,0,0,.86);
}
.lb-overlay[hidden] { display: none; }
body.lb-open { overflow: hidden; }
.lb-figure {
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  max-width: 96vw;
  max-height: 96vh;
  /* A LONG CAPTION USED TO BE CLIPPED WITH NO WAY TO REACH IT. The image took
     up to 88vh of a 96vh box, leaving the caption about 8vh, and nothing here
     handled overflow — so the tail of a six-line caption simply vanished and
     neither scrolling nor resizing the window helped. Found 2026-09-01 on the
     New Style reverse. Two fixes, because either alone is unsatisfying: the
     figure now scrolls, AND a captioned image is capped lower so the first
     lines are visible without scrolling at all. */
  overflow-y: auto;
  overscroll-behavior: contain;
  padding-bottom: .6em;
}
/* Neither child may be squeezed by the flex box; the container scrolls instead. */
.lb-figure > * { flex: 0 0 auto; }
.lb-img {
  max-width: 96vw;
  /* No caption: the image keeps the full height it always had. */
  max-height: 88vh;
  object-fit: contain;
  border-radius: 3px;
  box-shadow: 0 4px 24px rgba(0,0,0,.5);
  cursor: default;
}
/* Captioned: give the caption room before anything has to scroll. */
.lb-figure.lb-has-cap .lb-img { max-height: 70vh; }
.lb-cap {
  margin-top: .7em;
  max-width: 70ch;
  color: var(--on-dark);
  font-size: calc(.85rem * var(--fs-small));
  font-style: italic;
  text-align: center;
  line-height: 1.4;
}
.lb-close {
  position: fixed;
  top: 2vmin;
  right: 2vmin;
  width: 2em;
  height: 2em;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: rgba(255,255,255,.15);
  /* Sits on the dark lightbox scrim in BOTH themes, so it wants --on-dark,
     not --on-accent (which flips to dark ink on the lighter dark-mode gold). */
  color: var(--on-dark);
  font-size: 1.6em;
  line-height: 1;
  cursor: pointer;
}
.lb-close:hover { background: rgba(255,255,255,.3); }

/* ---------- Wanted list (private view) ---------- */
/* The whole wanted.php page is auth-gated; these styles never render for an
   anonymous visitor. Palette follows the catalog's warm browns, with the
   priority badge carrying the only strong colour so a P1 reads at a glance. */
.want-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 1.2em;
  margin-top: 1.2em;
}
.want-card {
  background: var(--surface-card);
  border: 1px solid var(--rule-card);
  border-radius: 6px;
  padding: 1em 1.1em;
  box-shadow: 0 1px 3px rgba(0,0,0,.06);
}
.want-card.want-status-acquired { opacity: .75; border-color: var(--rule-ok); }
.want-card.want-status-passed   { opacity: .6;  font-style: italic; }

.want-header {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: .45em;
  margin-bottom: .5em;
}
.want-header h3 {
  margin: 0;
  flex: 1 1 auto;
  font-size: 1.08em;
}
/* Opens this want on its own page. Deliberately quiet — it sits on every card,
   so it must not compete with the priority badge or a LIVE chip. */
.want-open {
  flex: 0 0 auto;
  text-decoration: none;
  color: var(--muted3);
  border: 1px solid var(--rule-card);
  border-radius: 4px;
  padding: 0 .4em;
  font-size: 1em;
  line-height: 1.5;
}
.want-open:hover { color: var(--link); border-color: var(--gold); }
.want-open:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

/* The single-want page: same markup as a card, given room. */
.want-card-detail {
  max-width: 860px;
  margin: 1.2em auto 0;
  padding: 1.4em 1.6em;
}
.want-card-detail .want-example img { max-height: 460px; }
.want-card-detail .cmp-grid { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
.want-card-detail .cmp-photo img { max-height: 190px; }
.want-card-detail .want-body > summary { font-size: 1em; }
.want-card-detail .want-items { display: grid; grid-template-columns: 1fr 1fr; gap: 0 1.4em; }
@media (max-width: 720px) {
  .want-card-detail { padding: 1em 1.1em; }
  .want-card-detail .want-items { grid-template-columns: 1fr; }
}
.want-priority {
  display: inline-block;
  background: var(--gold);
  color: var(--on-accent);
  font-size: calc(.72rem * var(--fs-small));
  font-weight: bold;
  padding: .15em .5em;
  border-radius: 12px;
}
.want-priority-1 { background: var(--prio1); }
.want-priority-2 { background: var(--prio2); }
.want-priority-4,
.want-priority-5 { background: var(--prio45); }
.want-kind,
.want-status-chip {
  display: inline-block;
  font-size: calc(.72rem * var(--fs-small));
  text-transform: uppercase;
  letter-spacing: .04em;
  border-radius: 4px;
  padding: .1em .5em;
}
.want-kind-type_gap { background: var(--info-bg); color: var(--info-ink); border: 1px solid var(--info-border); }
.want-kind-upgrade  { background: var(--warn-bg); color: var(--warn-ink); border: 1px solid var(--rule); }
/* STUDY — a coin wanted for what it documents, where the very condition that
   disqualifies it everywhere else is the reason to buy. Green, so it reads as
   its own category rather than a variant of gap or upgrade. */
.want-kind-study    { background: var(--ok-bg); color: var(--ok-ink); border: 1px solid var(--rule-ok); }
/* APPEAL — wanted simply because John would like to own it: taste, not a gap
   in the story. Its own colour so it doesn't read as any of the other three. */
.want-kind-appeal   { background: var(--appeal-bg); color: var(--appeal-ink); border: 1px solid var(--appeal-rule); }
/* SALE — the card IS one auction, not a coin. Uses the live/urgent accent,
   because that is what it behaves like: it matters intensely for a few days
   and becomes a price record afterwards. */
.want-kind-bidsheet { background: var(--open-bg); color: var(--prio1); border: 1px solid var(--rule-open); font-weight: bold; }
/* SWEEP — a dated report, sibling to a sale card: a working document rather
   than a want. Neutral, so it doesn't compete with the urgent Sale badge. */
.want-kind-sweep    { background: var(--chip-bg); color: var(--chip-ink); border: 1px solid var(--rule-chip); font-weight: bold; }
/* ACQUIRED — bought, but not yet weighed, measured and photographed. Green:
   this is the only card whose contents are always a completed purchase. */
.want-kind-acquired { background: var(--ok-bg); color: var(--ok-ink); border: 1px solid var(--rule-ok); font-weight: bold; }
.want-status-chip   { background: var(--chip-bg); color: var(--chip-ink); border: 1px solid var(--rule-chip2); }

.want-links {
  font-size: .88em;
  margin-bottom: .5em;
}
.want-links a { color: var(--link); }

/* "An upgrade on <specimen>" — given its own block rather than a chip in the
   links row, because the trailing clause (it ADDS a specimen, it does not
   replace one) is the point and needs room to be read. */
.want-upgrade-of {
  font-size: .88em;
  margin: -.2em 0 .6em;
  padding: .35em .6em;
  border-left: 3px solid var(--rule-ok);
  background: var(--ok-bg);
  border-radius: 0 4px 4px 0;
}
.want-upgrade-of a { color: var(--link); }
.want-upgrade-note { color: var(--muted-strong); font-style: italic; }

.want-facts {
  margin: .4em 0 .6em;
  display: grid;
  grid-template-columns: auto 1fr;
  gap: .12em .7em;
  font-size: .9em;
}
.want-facts dt { color: var(--muted3); }
.want-facts dd { margin: 0; }

/* Money — only ever emitted behind is_authenticated(). */
.want-budget {
  background: var(--surface-tint2);
  border-left: 3px solid var(--gold);
  padding: .4em .7em;
  margin: .5em 0;
  font-size: .92em;
}
.want-budget-label {
  text-transform: uppercase;
  /* .7176rem, not .78rem: was .78em inside .want-budget (.92em). */
  font-size: calc(.7176rem * var(--fs-small));
  letter-spacing: .05em;
  color: var(--gold);
  margin-right: .4em;
}
.want-price-note { color: var(--muted2); font-style: italic; font-size: .92em; }

/* Catalogue hints: the reference numbers a want is an example of, each with
   a museum photograph (hot-linked; this view is auth-gated) and its census.
   Thumbnails hide with the Show-images switch; the numbers stay. */
.want-refs { margin: .2em 0 .7em; }
.want-refs h4 { margin: 0 0 .3em; font-size: .9em; color: var(--muted3); font-weight: 600; }
.want-refs ul { list-style: none; margin: 0; padding: 0; }
.wref { display: flex; gap: .7em; align-items: flex-start; padding: .35em 0; border-top: 1px solid var(--rule-soft); }
.wref:first-child { border-top: 0; }
.wref-pics { flex: 0 0 auto; display: flex; gap: 4px; }
.wref-pics[hidden] { display: none; }
.wref-pics img {
  width: 56px; height: 56px; object-fit: contain;
  border-radius: 50%; background: var(--surface-sunken);
}
.wref-text { min-width: 0; font-size: .9em; line-height: 1.4; }
.wref-title { font-weight: 600; }
.wref-facts { margin-left: .5em; color: var(--muted2); }
.wref-ctrl { color: var(--muted2); font-size: .95em; }
.wref-note { font-style: italic; color: var(--ink-caption); }
.wref-census { color: var(--muted3); font-size: .92em; }
.want-card-detail .wref-pics img { width: 84px; height: 84px; }

/* Card "what to look for" photo. Full card width with a capped height so a tall
   image can't dominate the card; the <figure> wraps image + caption + source so
   the "Show images" switch hides them as one unit. */
.want-example {
  margin: .2em 0 .7em;
  text-align: center;
}
.want-example[hidden] { display: none; }
.want-example img {
  max-width: 100%;
  max-height: 260px;
  width: auto;
  height: auto;
  border-radius: 5px;
  background: var(--surface-sunken);
  box-shadow: 0 2px 6px rgba(0,0,0,.18);
}
.want-example-cap {
  margin-top: .45em;
  font-size: calc(.84rem * var(--fs-small));
  font-style: italic;
  color: var(--ink-caption);
  text-align: left;
  line-height: 1.45;
}
.want-example-missing {
  font-size: calc(.8rem * var(--fs-small));
  color: var(--muted3);
  font-style: italic;
  padding: .5em;
  border: 1px dashed var(--rule);
  border-radius: 4px;
}
.want-example-missing code { font-style: normal; }

/* All / Gaps / Upgrades — a filter; and Show images — a display switch. Kept
   visually distinct so the switch never reads as a fourth facet. */
.want-kind-filter { gap: .35em; display: flex; }
.wf-btn {
  font-family: inherit;
  font-size: .9em;
  color: var(--link);
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: 4px;
  padding: .25em .8em;
  cursor: pointer;
}
.wf-btn:hover { background: var(--surface-tint-hover); }
.wf-btn[aria-pressed="true"] {
  background: var(--gold);
  border-color: var(--gold);
  color: var(--on-accent);
  font-weight: bold;
}
/* "Live now" filters on a different axis from the kind buttons — deadline, not
   category — so it carries the same warm accent the LIVE chip does, to read as
   the urgent one in the row. */
.wf-btn-live { color: var(--prio1); border-color: var(--prio1); }
.wf-btn-live[aria-pressed="true"] {
  background: var(--prio1);
  border-color: var(--prio1);
  color: var(--on-accent);
}
.wf-btn:focus-visible,
.wf-toggle:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

.wf-toggle {
  display: inline-flex;
  align-items: center;
  gap: .45em;
  font-family: inherit;
  font-size: .9em;
  color: var(--ink-accent);
  background: transparent;
  border: 0;
  padding: .25em .2em;
  cursor: pointer;
}
.wf-toggle-box {
  width: 1.9em;
  height: 1.05em;
  border-radius: 1em;
  background: var(--rule-chip);
  border: 1px solid var(--rule);
  position: relative;
  transition: background .15s ease;
}
.wf-toggle-box::after {
  content: "";
  position: absolute;
  top: 50%;
  left: .12em;
  transform: translateY(-50%);
  width: .78em;
  height: .78em;
  border-radius: 50%;
  background: var(--surface);
  transition: left .15s ease;
}
.wf-toggle[aria-pressed="true"] .wf-toggle-box { background: var(--gold); }
.wf-toggle[aria-pressed="true"] .wf-toggle-box::after { left: calc(100% - .9em); }

/* Live-sale links — the ONE thing on a card with a deadline, so it sits at the
   top and is the only element styled for attention. An entry past its
   last_useful_date is not deleted; it goes muted and points at the sold archive
   instead (the renderer decides, comparing against today at render time). */
.wl-live-row { display: flex; flex-direction: column; gap: .3em; margin: 0 0 .55em; }

/* live_links subsections. A sweep card carries one line per lot so every lot
   number is directly clickable, which makes a big block long — the Pilate flood
   ran to fourteen lines. A GROUP marker in live_links turns the block into a
   collapsible subsection; 10+ lots collapse by default (GROUP_COLLAPSE_AT in
   jsb_coins_wanted.py). Deliberately the same chit vocabulary as the per-card
   collapse, so one gesture means one thing everywhere on this page. */
.wl-group { margin: 0 0 .5em; }
.wl-group-header {
  display: flex;
  align-items: center;
  gap: .45em;
  width: 100%;
  padding: .25em .1em;
  background: none;
  border: 0;
  border-bottom: 1px solid var(--hairline, var(--rule-soft));
  cursor: pointer;
  text-align: left;
  color: var(--ink-accent);
  /* rem, not em: this is a label on the CAPTION lever. See --fs-small. */
  font-size: calc(.8rem * var(--fs-small));
  font-weight: bold;
}
.wl-group-header:hover { color: var(--link); }
.wl-group-chit {
  flex: 0 0 auto;
  width: .5em;
  height: .5em;
  border-right: 1.8px solid currentColor;
  border-bottom: 1.8px solid currentColor;
  transform: rotate(45deg);
  transition: transform .12s ease;
}
.wl-group.collapsed .wl-group-chit { transform: rotate(-45deg); }
.wl-group-title { flex: 1 1 auto; }
.wl-group-count {
  flex: 0 0 auto;
  color: var(--muted3);
  font-weight: normal;
}
.wl-group.collapsed .wl-group-body { display: none; }
.wl-group-body { padding-top: .4em; }
.wl-live {
  display: block;
  text-decoration: none;
  border-radius: 4px;
  padding: .4em .6em;
  font-size: .85em;
  line-height: 1.35;
}
.wl-live-open {
  background: var(--open-bg);
  border: 1px solid var(--rule-open);
  color: var(--ink);
}
.wl-live-open:hover { border-color: var(--gold); }
.wl-live-flag {
  display: inline-block;
  background: var(--prio1);
  color: var(--on-accent);
  /* .612rem, not .72rem: was .72em inside .wl-live (.85em). */
  font-size: calc(.612rem * var(--fs-small));
  font-weight: bold;
  text-transform: uppercase;
  letter-spacing: .06em;
  border-radius: 3px;
  padding: .1em .45em;
  margin-right: .45em;
  vertical-align: 1px;
}
.wl-live-label { font-weight: bold; }
.wl-live-when {
  display: block;
  /* .748rem, not .88rem: was .88em inside .wl-live (.85em). */
  font-size: calc(.748rem * var(--fs-small));
  color: var(--muted-strong);
  margin-top: .15em;
}
.wl-live-open .wl-live-when { color: var(--ink-accent); font-weight: bold; }
/* Ended: same shape, no flag, deliberately quiet — it is history now. */
.wl-live-ended {
  background: transparent;
  border: 1px dashed var(--rule);
  color: var(--muted-strong);
}
.wl-live-ended .wl-live-label { font-weight: normal; font-style: italic; }
.wl-live-ended:hover { border-style: solid; border-color: var(--link); }


/* Lot photo inside the live box — lets a lot be triaged from the card without
   opening the sale. Obeys the Show images toggle like every other want photo. */
.wl-live-photo { display: block; margin-top: .45em; }
.wl-live-photo[hidden] { display: none; }
.wl-live-photo img {
  display: block;
  width: 100%;
  height: auto;
  max-height: 200px;
  object-fit: contain;
  border-radius: 3px;
  background: var(--surface-sunken);
}
.wl-live-nophoto {
  display: block;
  margin-top: .4em;
  font-size: calc(.8rem * var(--fs-small));
  font-style: italic;
  color: var(--muted3);
}

/* Judging notes — the standing lesson about the type. */
.want-notes { margin-top: .7em; }
.want-notes > summary { cursor: pointer; font-size: .9em; color: var(--link); }
.want-notes p { font-size: .88em; line-height: 1.55; margin: .5em 0; }

/* The evaluation log: every lot looked at, and why it was passed. */
.want-evals { margin-top: .5em; }
.want-evals > summary { cursor: pointer; font-size: .9em; color: var(--link); }
ul.wev-list { list-style: none; margin: .4em 0 0; padding: 0; }
.wev {
  border-left: 2px solid var(--rule-card);
  padding: .35em 0 .35em .7em;
  margin-bottom: .5em;
}
.wev-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: .4em; }
.wev-date { font-size: calc(.78rem * var(--fs-small)); color: var(--muted3); font-family: ui-monospace, Menlo, monospace; }
.wev-verdict {
  font-size: calc(.7rem * var(--fs-small));
  font-weight: bold;
  text-transform: uppercase;
  letter-spacing: .06em;
  border-radius: 3px;
  padding: .1em .45em;
}
.wev-pass  { background: var(--warn-bg); color: var(--warn-ink); border: 1px solid var(--rule); }
.wev-acted { background: var(--ok-bg);   color: var(--ok-ink);   border: 1px solid var(--rule-ok); }
.wev-lot { font-size: .84em; font-weight: bold; flex: 1 1 12em; }
a.wev-lot { color: var(--link); text-decoration: none; }
a.wev-lot:hover { text-decoration: underline; }
a.wev-lot:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
/* Photo of the evaluated lot. Sized modestly — it is evidence for the
   verdict above it, not the card's headline image. */
.wev-photo { display: block; margin-top: .45em; }
.wev-photo img { max-width: 100%; max-height: 150px; width: auto;
  border-radius: 3px; background: var(--surface-sunken); }
/* The stored lot photos run to 2000px for most houses, so the thumbnail
   is a click-to-zoom target; lightbox.js adds .lb-zoom (cursor: zoom-in). */
.wev-photo a { display: block; }
.wev-why { font-size: .82em; color: var(--muted-strong); line-height: 1.5; margin-top: .25em; }


/* "updated <date>" — a want added or reviewed within FRESH_DAYS. Quiet: it
   marks recency, it is not a call to action. */
.want-fresh {
  display: inline-block;
  font-size: calc(.7rem * var(--fs-small));
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--ok-ink);
  background: var(--ok-bg);
  border: 1px solid var(--rule-ok);
  border-radius: 3px;
  padding: .1em .45em;
}

/* Missing ceiling on an APPEAL want — the category where discipline fails, so
   this one is deliberately loud, unlike every other note on the card. */
.want-nobudget {
  background: var(--err-bg);
  border: 1px solid var(--rule-err);
  border-left: 3px solid var(--prio1);
  color: var(--err-ink);
  border-radius: 0 4px 4px 0;
  padding: .45em .7em;
  margin: .5em 0;
  font-size: .85em;
  line-height: 1.45;
}
.want-nobudget code { background: none; font-size: .95em; }

/* Saved-search links — durable queries (a lot link dies the day after the
   sale), shown as small outlined buttons above the watch-venue chips. */
.wl-search-links {
  display: flex;
  flex-wrap: wrap;
  gap: .35em;
  margin: 0 0 .45em;
}
.wl-search-link {
  display: inline-block;
  font-size: .8em;
  line-height: 1.35;
  color: var(--link);
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: 4px;
  padding: .22em .6em;
  text-decoration: none;
}
.wl-search-link:hover { background: var(--surface-tint-hover); text-decoration: underline; }
.wl-search-link:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

/* Price comparables — sold lots as a cheapest-first ladder. AUTH-GATED: the
   photos are (c) CNG, kept for private research only, hence the credit line
   and the independent is_authenticated() check in render_comparables(). */
.want-comparables { margin-top: .7em; }
.want-comparables h4 {
  margin: .6em 0 .3em;
  font-size: .82em;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--gold);
}
.cmp-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: .5em;
}
.cmp-tile {
  display: block;
  text-decoration: none;
  color: inherit;
  border: 1px solid var(--rule-card);
  border-radius: 5px;
  padding: .4em .5em;
  background: var(--surface-card);
}
.cmp-tile:hover { border-color: var(--gold); }
.cmp-tile:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.cmp-photo { display: block; margin-bottom: .3em; }
.cmp-photo[hidden] { display: none; }
.cmp-photo img {
  width: 100%;
  height: auto;
  max-height: 110px;
  object-fit: contain;
  border-radius: 3px;
  background: var(--surface-sunken);
}
.cmp-hammer {
  display: block;
  font-weight: bold;
  font-size: .95em;
  color: var(--ink-strong);
}
.cmp-note {
  display: block;
  font-size: calc(.76rem * var(--fs-small));
  color: var(--muted-strong);
  line-height: 1.35;
}
/* With photos off the tiles are pure text, so let them run in a tighter row. */
.cmp-tile-noimg .cmp-note { font-size: calc(.74rem * var(--fs-small)); }
.cmp-price-note {
  margin: .5em 0 .2em;
  font-size: calc(.82rem * var(--fs-small));
  color: var(--ink-caption);
  line-height: 1.45;
}
.cmp-credit {
  margin: .2em 0 0;
  font-size: calc(.72rem * var(--fs-small));
  font-style: italic;
  color: var(--muted3);
  line-height: 1.4;
}

.want-items { margin-top: .6em; }
.want-item-block h4 {
  margin: .6em 0 .25em;
  font-size: .82em;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--gold);
}
ul.want-list { margin: 0; padding-left: 1.2em; font-size: .9em; }
ul.want-list li { padding: .1em 0; }
ul.want-chips { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: .35em; }
.want-chip {
  background: var(--chip-bg);
  border: 1px solid var(--rule-chip);
  border-radius: 3px;
  padding: .12em .5em;
  font-size: calc(.84rem * var(--fs-small));
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}
.want-item-avoid ul.want-list li { color: var(--avoid-ink); }

.want-body { margin-top: .7em; }
.want-body > summary {
  cursor: pointer;
  font-size: .9em;
  color: var(--link);
}
.want-body .body-figure { max-width: 100%; }

.want-resolution {
  margin-top: .6em;
  font-size: .88em;
  color: var(--muted-neutral);
  border-top: 1px dotted var(--rule-soft3);
  padding-top: .4em;
}
.want-added { margin-top: .4em; font-size: .8em; color: var(--muted-faint); }

.want-history { margin-top: 2em; }
.want-history > summary {
  cursor: pointer;
  font-size: 1.05em;
  color: var(--link);
  padding: .4em 0;
}

/* The private cross-link shown on a type page when an open want targets it. */
.want-note {
  background: var(--surface-tint2);
  border-left: 3px solid var(--gold);
  padding: .5em .8em;
  margin: 1em 0;
  font-size: .92em;
}
.want-note-label {
  display: block;
  text-transform: uppercase;
  font-size: calc(.75rem * var(--fs-small));
  letter-spacing: .05em;
  color: var(--gold);
  margin-bottom: .2em;
}
.want-note ul { margin: 0; padding-left: 1.2em; }
.nav-private { font-style: italic; }

/* ---------- Wanted page body ----------
   This was missing entirely until 2026-07-27: body.coin-wanted matched no rule,
   so the page rendered in Times with no padding and no background, and only
   looked right because the cards style themselves. No max-width on purpose —
   the grid is meant to fill a wide screen. */
body.coin-wanted {
  font-family: Georgia, serif;
  font-size: calc(1rem * var(--fs-scale));
  margin: 0;
  padding: 1.4em 1.5em 2em;
  color: var(--ink);
  background: var(--bg);
  line-height: 1.6;
}

/* ---------- John Docs index ----------
   One card per markdown file in JohnDocs/. The folder is listed at request
   time, so a new file appears here with no code change. */
.doc-list { display: grid; gap: .8em; margin-top: 1.2em; }
.doc-card {
  display: block;
  text-decoration: none;
  color: inherit;
  background: var(--surface-card);
  border: 1px solid var(--rule-card);
  border-left: 3px solid var(--gold);
  border-radius: 6px;
  padding: .9em 1.1em;
  transition: border-color .15s ease, transform .15s ease;
}
.doc-card:hover { border-color: var(--gold); transform: translateY(-1px); }
.doc-card:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.doc-title {
  display: block;
  font-size: 1.05em;
  font-weight: bold;
  color: var(--ink-strong);
}
.doc-lede {
  display: block;
  margin-top: .25em;
  font-size: .88em;
  color: var(--muted-strong);
  line-height: 1.5;
}
.doc-meta {
  display: block;
  margin-top: .4em;
  font-size: calc(.76rem * var(--fs-small));
  color: var(--muted3);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}

/* ---------- Generic markdown page (John Docs) ----------
   A whole .md file rendered straight to HTML, so it needs styling for elements
   the coin pages never produce: real tables, fenced code blocks, hr rules. The
   existing table rules are scoped to .tags (tag transcriptions), so they don't
   reach here. */
body.coin-tasks {
  font-family: Georgia, serif;
  font-size: calc(1rem * var(--fs-scale));
  max-width: 900px;
  margin: 0 auto;
  padding: 2em 1.5em;
  color: var(--ink);
  line-height: 1.7;
  background: var(--bg);
}
body.coin-tasks h1 {
  font-size: 1.65em;
  border-bottom: 3px solid var(--link);
  padding-bottom: .4em;
  color: var(--ink-strong);
  margin-bottom: .25em;
}
.md-page h2 {
  font-size: 1.12em;
  color: var(--ink-accent);
  border-bottom: 1px solid var(--rule);
  padding-bottom: .2em;
  margin-top: 2em;
  letter-spacing: .03em;
  text-transform: uppercase;
}
.md-page h3 { font-size: 1em; color: var(--ink-accent); margin: 1.5em 0 .3em; }
.md-page h4 { font-size: .95em; color: var(--ink-accent); margin: 1.2em 0 .2em; }
.md-page p { margin: .7em 0; }
.md-page ul, .md-page ol { padding-left: 1.5em; }
.md-page li { margin: .3em 0; }
.md-page hr { border: 0; border-top: 1px solid var(--rule-soft); margin: 2em 0; }
.md-page a { color: var(--link); }
.md-page blockquote {
  border-left: 3px solid var(--rule);
  margin: .8em 0;
  padding: .2em 1em;
  color: var(--ink-quote);
}
.md-page code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  background: var(--surface-sunken);
  padding: .08em .35em;
  border-radius: 3px;
  font-size: .88em;
  word-break: break-word;
}
.md-page pre {
  background: var(--surface-sunken);
  border: 1px solid var(--rule-soft);
  border-radius: 5px;
  padding: .8em 1em;
  overflow-x: auto;
  font-size: .86em;
  line-height: 1.5;
}
.md-page pre code { background: none; padding: 0; font-size: 1em; }
/* Tables carry most of the content here, so they get real treatment. Wrapped in
   an overflow rule rather than shrinking text, so a long path stays readable. */
.md-page table {
  border-collapse: collapse;
  width: 100%;
  margin: 1em 0;
  font-size: .9em;
  display: block;
  overflow-x: auto;
}
.md-page thead th {
  background: var(--surface-tint);
  color: var(--ink-accent);
  text-align: left;
  font-size: .82em;
  text-transform: uppercase;
  letter-spacing: .05em;
  padding: .5em .7em;
  border-bottom: 2px solid var(--rule);
}
.md-page td {
  padding: .5em .7em;
  border-bottom: 1px solid var(--rule-soft);
  vertical-align: top;
}
.md-page tbody tr:last-child td { border-bottom: 0; }

/* ---------- Print pass (all pages) ---------- */
@media print {
  /* Always print the LIGHT palette, whatever the screen theme is: printing a
     dark page wastes ink and reads badly. Re-declaring the tokens here beats
     :root[data-theme="dark"] because @media print applies later in the cascade
     at equal specificity. The SVG filter is reset too, or inverted timelines
     would print as white-on-white. */
  :root, :root[data-theme="dark"] {
    color-scheme: light;
    --bg: #fdfcf8;            --surface: #fff;
    --surface-card: #fffdf7;  --surface-input: #fffdf8;
    --panel-bg: #faf6ec;      --surface-sunken: #f2ece0;
    --surface-tint: #f7f0e2;  --surface-tint2: #f6f2e6;
    --surface-tint-hover: #f0e6d0;
    --chip-bg: #f0efe9;       --open-bg: #fffbe8;
    --ok-bg: #e5f0d8;         --warn-bg: #f1ebd5;
    --err-bg: #fbeaea;        --info-bg: #e8eef5;
    --ink: #1e1a14;           --ink-strong: #2e1f0a;
    --ink-accent: #5a3e1b;    --ink-quote: #4a3a26;
    --ink-caption: #6a5a42;   --ink-credit: #7a6a52;
    --muted-strong: #555;     --muted: #666;
    --muted2: #777;           --muted3: #888;
    --muted4: #999;           --muted-neutral: #5a5a5a;
    --muted-faint: #a09a88;
    --link: #7a5c2e;          --gold: #8b6914;
    --link-hot: #7a2e12;      --rule-hot: #a8763e;
    --rule: #c9b48a;          --rule-soft: #e0d8c8;
    --rule-soft2: #ece4d0;    --rule-soft3: #ddd6c4;
    --rule-card: #e0d6bd;     --rule-chip: #d9d4c4;
    --rule-chip2: #d4d0c2;    --rule-table: #ddd;
    --rule-open: #e0cd96;     --rule-err: #e0b4b4;
    --rule-ok: #aac68f;
    --ok-ink: #3d6017;        --warn-ink: #6b5519;
    --err-ink: #8a2b2b;       --info-ink: #2f4a63;
    --info-border: #a9c0d6;   --chip-ink: #6a675c;
    --avoid-ink: #7d3a2a;
    --prio1: #9c3b1b;         --prio2: #b06a1c;   --prio45: #9a8d6f;
    --svg-figure-filter: none;
    --enlarge-bg: rgba(250,246,236,.92);
  }
  .top-bar, .theme-toggle, .fs-btn, .fs-panel { display: none; }
  .lb-overlay { display: none !important; }
  body { background: var(--surface); max-width: none; padding: 0; }
  body.coin-catalog { background: var(--surface); }
  #filter-bar { display: none; }
  .breadcrumb, .footer-link, .recent-actions, .auth-bar { display: none; }
  .coin-card { box-shadow: none; border: 1px solid #000; page-break-inside: avoid; }
  .two-col img { max-height: none; }
  a { color: inherit; text-decoration: none; }
  /* Catalog grid: 2 columns for letter-size print */
  .catalog-grid { grid-template-columns: 1fr 1fr; gap: 10mm; }
  /* Wanted list is meant to be printed and carried into a saleroom: keep a want
     on one page and drop the disclosure triangles. The <details> elements are
     forced open by the page's own beforeprint handler — CSS alone can't do it
     reliably across browsers. */
  .want-grid { grid-template-columns: 1fr 1fr; gap: 8mm; }
  .want-card { box-shadow: none; border: 1px solid #000; page-break-inside: avoid; opacity: 1; }
  .want-body > summary, .want-history > summary { display: none; }
  /* Keep the example photo on the saleroom copy — that is the whole point of
     it — but cap it harder than on screen so a card still fits a column. Force
     it visible even if "Show images" is currently off on screen. */
  .want-example, .want-example[hidden] { display: block !important; }
  .want-example img { max-height: 45mm; }
  .want-kind-filter, .wf-toggle { display: none; }
  h1, h2, h3 { page-break-after: avoid; }
  pre { white-space: pre-wrap; word-break: break-word; }
}

/* ---- Live-lot ordering switch (added 2026-08-30, John's request) ----------
   A sweep card lists its lots in RANK order, grouped, which is what you want
   when deciding. During the live session you want the opposite: the order the
   auctioneer will call them in, so a lot ten away can be seen coming. Both
   orderings are rendered server-side and this only chooses between them, so a
   click can never leave a half-sorted list on screen. */
.wl-order-switch {
  display: flex;
  gap: 0;
  margin: 0 0 .5em;
}
.wl-order-btn {
  background: none;
  border: 1px solid var(--rule);
  color: var(--muted-strong);
  cursor: pointer;
  padding: .18em .7em;
  /* rem, not em: a control label, on the caption lever. See --fs-small. */
  font-size: calc(.72rem * var(--fs-small));
  font-weight: bold;
  letter-spacing: .03em;
}
.wl-order-btn:first-child { border-radius: 4px 0 0 4px; }
.wl-order-btn:last-child  { border-radius: 0 4px 4px 0; border-left: 0; }
.wl-order-btn:hover { color: var(--link); border-color: var(--link); }
.wl-order-btn.is-on {
  background: var(--prio1);
  border-color: var(--prio1);
  color: var(--on-accent);
}
.wl-order[hidden] { display: none; }

.wl-bylot-head {
  margin: 0 0 .4em;
  font-size: calc(.748rem * var(--fs-small));
  color: var(--muted-strong);
}
.wl-bylot {
  list-style: none;
  margin: 0 0 .55em;
  padding: 0;
  /* The whole point of this view is a scannable column of lot numbers, so the
     rows are tight and the numbers are tabular. */
  border-top: 1px solid var(--hairline, var(--rule-soft));
}
.wl-bylot-row { border-bottom: 1px solid var(--hairline, var(--rule-soft)); }
.wl-bylot-link {
  display: flex;
  align-items: baseline;
  gap: .6em;
  padding: .3em .2em;
  text-decoration: none;
  color: var(--ink);
  font-size: .85em;
  line-height: 1.3;
}
.wl-bylot-link:hover { background: var(--open-bg); }
.wl-bylot-no {
  flex: 0 0 auto;
  min-width: 4.2em;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-weight: bold;
  color: var(--ink-accent);
  font-variant-numeric: tabular-nums;
}
.wl-bylot-text { flex: 1 1 auto; }
/* An ended lot stays in the list — position in the calling order is still
   information — but goes quiet, matching .wl-live-ended. */
.wl-bylot-row.is-ended .wl-bylot-link { color: var(--muted-strong); }
.wl-bylot-row.is-ended .wl-bylot-text { font-style: italic; }

/* The money column in the by-lot view. Added 2026-08-31: the view shipped
   without it, because _short_label keeps a label's FIRST clause (grade and
   measurements) and the price lives in the next sentence — so the one view
   built for a live session was the one view with no prices in it. */
.wl-bylot-price {
  flex: 0 0 auto;
  margin-left: auto;
  padding-left: .7em;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-variant-numeric: tabular-nums;
  font-weight: bold;
  color: var(--ink-accent);
  white-space: nowrap;
}
.wl-bylot-row.is-ended .wl-bylot-price { color: var(--muted3); font-weight: normal; }
@media (max-width: 30em) {
  /* Narrow screens: let the text wrap under the number rather than squeezing
     the price off the row — the price is the reason the row exists. */
  .wl-bylot-link { flex-wrap: wrap; }
  .wl-bylot-text { flex: 1 1 100%; order: 3; padding-left: 4.8em; }
  .wl-bylot-price { margin-left: auto; }
}

/* Lot number and current bid, lifted out of a live chip's prose (John,
   2026-08-31: "the LOT NUMBER needs to stand out as well as the current BID -
   all the white text is too much"). A sweep label is a paragraph, and the two
   things a live room needs from it are the number being called and the money.
   Amber is var(--ink-accent) — the same colour the "closes <date>" line already
   uses on an open chip, so the chip has one accent colour and not two. */
.wl-hl-lot,
.wl-hl-money {
  color: var(--ink-accent);
  font-weight: bold;
}
.wl-hl-money {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}


/* ---------- Site Credits ---------- */
/* Credits moved off the coin pages on 2026-09-01 and onto credits.php; this is
   the small footer link that makes them discoverable, plus the page itself.
   NOT flex on the <li>: the first version did that, which turned every inline
   element — each link, each text node — into its own flex column and shattered
   the words ("Pho to:", "licens ed"). A hanging indent keeps it as flowing
   prose that wraps normally. */
.site-credits-link {
  margin: 2.2em 0 .4em;
  font-size: calc(.72rem * var(--fs-small));
  color: var(--ink-caption);
  text-align: center;
}
.cr-intro { max-width: 66ch; }
.cr-glance {
  max-width: 66ch;
  margin: 1.5em 0 2.5em;
  padding: 1em 1.2em;
  border-left: 3px solid var(--rule);
  background: var(--bg-inset, transparent);
}
.cr-glance h2 { margin-top: 0; font-size: 1.05em; }
.cr-glance ul { margin: .4em 0 0; padding-left: 1.1em; }
.cr-glance li { margin: .3em 0; font-size: calc(.92rem * var(--fs-small)); }
.cr-key dl { margin: .6em 0 0; }
.cr-key dt {
  font-weight: 600;
  margin-top: .7em;
}
.cr-key dd {
  margin: .15em 0 0;
  padding-left: 0;
  font-size: calc(.92rem * var(--fs-small));
  line-height: 1.5;
}
.cr-count { font-weight: 400; color: var(--ink-caption); }
.cr-keynote {
  margin: 1em 0 0;
  font-size: calc(.88rem * var(--fs-small));
  color: var(--ink-caption);
}
.cr-type {
  margin: 2em 0;
  scroll-margin-top: 1.5em;      /* arriving via #slug, don't butt the viewport */
}
/* Arrived from a coin page's footer link: say so, or the reader lands in a wall
   of 95 sections with no idea which one they were sent to. */
.cr-type:target {
  padding: .6em 1em;
  margin-left: -1em;
  border-left: 3px solid var(--accent, #8a6d3b);
  background: var(--bg-inset, rgba(127,127,127,.08));
}
.cr-type h2 { margin-bottom: .2em; font-size: 1.1em; }
.cr-list { list-style: none; padding-left: 0; margin: .5em 0 0; }
.cr-list li {
  margin: .55em 0;
  padding-left: 1.4em;
  text-indent: -1.4em;
  line-height: 1.55;
  overflow-wrap: break-word;     /* only a too-long URL breaks, never a word */
}
.cr-what {
  font-style: italic;
  color: var(--ink-caption);
}
.cr-what::after { content: " \2014 "; font-style: normal; }

/* Catalog search status: says what the box can currently reach (card text only,
   or full text once search_index.php has loaded) and the hit count while
   filtering. Without it, "no results" is ambiguous — the user cannot tell a
   real miss from an index that has not arrived. */
.search-status {
  margin-left: .6em;
  font-size: calc(.8rem * var(--fs-small));
  color: var(--ink-caption);
  white-space: nowrap;
}

/* ---------- "In the Price corpus" / "In Crawford" / "In RIC" (type page, when the card has a ref_id) ----------
   Price / Crawford / RIC via PELLA / CRRO / OCRE: the entry, the museum census, the weight strip, and
   a row of museum comparanda in the same .coin-card markup as John's own
   specimens so the two read as peers. Credits for the museum photographs are
   on credits.php, not here (2026-09-01 rule). */
.ref-corpus h2 .ref-role {
  margin-left: .6em;
  vertical-align: middle;
  background: var(--surface-tint2);
  color: var(--ink-accent);
  border: 1px solid var(--rule);
}
.ref-corpus .ref-facts {
  display: flex;
  flex-wrap: wrap;
  gap: 0 2.5em;
  align-items: start;
}
.ref-corpus dl.type-facts.controls dt.head,
.ref-corpus dl.type-facts.controls dd.head {
  grid-column: 1 / -1;
  color: var(--muted2);
  font-weight: normal;
  font-style: italic;
  margin-bottom: -.15em;
}
.ref-corpus dl.type-facts.controls dd.head { display: none; }
.ref-corpus .corpus-line { margin: .9em 0 .3em; font-size: .95em; }
.ref-corpus .mine-line { margin: .2em 0 .4em; font-size: .95em; color: var(--ink-accent); }
.ref-corpus h2 a.ref-role { text-decoration: none; }
.ref-corpus h2 a.ref-role:hover,
.ref-corpus h2 a.ref-role:focus-visible { color: var(--link-hot); border-color: var(--rule-hot); }
.ref-corpus .ref-check.private {
  border-left: 3px solid var(--gold);
  padding-left: .6em;
  color: var(--ink-accent);
  font-size: .92em;
}
.ref-corpus h3 { margin: 1.4em 0 .2em; }

/* Weight strip: rug plot of every recorded weight, John's coin(s) marked.
   Wrapped in figure.svg-figure so lightbox.js adds "⤢ Enlarge" (the panel
   shows it at double width, which is where the ticks separate). It draws in
   theme colours already, so it opts out of the body-figure sizing, centring
   and dark-mode invert; the Enlarge button sits beside the strip, not over
   the "mine" label. */
.ref-corpus .weight-figure {
  margin: .2em 0 .4em;
  max-width: 660px;
  text-align: left;
  display: flex;
  align-items: flex-end;
  gap: .6em;
}
.ref-corpus .body-figure.weight-figure svg,
.lb-panel-body .weight-figure svg { filter: none; }
.ref-corpus .weight-figure .enlarge { position: static; flex: none; margin-bottom: .1em; }
.lb-panel-body .weight-figure { display: block; max-width: none; }
.lb-panel-body .weight-figure .weight-strip { max-width: none; }
.ref-corpus .weight-figure figcaption { display: none; }
.lb-panel-body .weight-figure figcaption { display: block; font-style: normal; }
.weight-strip {
  display: block;
  width: 100%;
  max-width: 600px;
  height: auto;
  flex: 1 1 auto;
  min-width: 0;
}
.weight-strip .ticks line { stroke: var(--ink-accent); stroke-opacity: .35; stroke-width: 1.2; }
.weight-strip .mine line { stroke: var(--gold); stroke-width: 2.5; }
.weight-strip .mine text {
  fill: var(--ink-accent);
  font-size: 10px;
  text-anchor: middle;
  font-weight: bold;
}
.weight-strip text.ax { fill: var(--muted2); font-size: 9.5px; }
.weight-strip text.ax.mid { text-anchor: middle; }
.weight-strip text.ax.end { text-anchor: end; }

/* Comparanda: smaller than John's specimen cards on the type page — six
   350 px museum photographs at 500 px tall would swamp the essay. */
.catalog-grid.comparanda { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
body.coin-type .coin-card.comparandum .coin-images a img { max-height: 160px; }
.coin-card.comparandum .coin-header { font-size: .95em; }

/* ---------- Reference finder (private) ----------
   Search over the Price / Crawford / RIC tables to settle a card's catalogue
   number. Thumbnails here are the museums' own, hot-linked — allowed because
   the page is private; the public type pages serve downloaded, credited copies. */
body.coin-finder { font-size: calc(1rem * var(--fs-scale)); }
body.coin-finder .finder-form {
  background: var(--surface-tint);
  border: 1px solid var(--rule-soft);
  border-radius: 8px;
  padding: .6em .9em .3em;
  margin: .8em 0 1.2em;
}
body.coin-finder .ff-row {
  display: flex;
  flex-wrap: wrap;
  gap: .4em 1.2em;
  align-items: center;
  margin-bottom: .5em;
}
body.coin-finder .ff-row label {
  display: inline-flex;
  align-items: center;
  gap: .35em;
  font-size: calc(.9rem * var(--fs-small));
  color: var(--ink-accent);
}
body.coin-finder .ff-row label.ff-wide { flex: 1 1 22em; }
body.coin-finder .ff-row label.ff-wide input { flex: 1 1 auto; }
body.coin-finder .ff-row input[type="text"],
body.coin-finder .ff-row select {
  padding: .25em .4em;
  font-size: .95em;
  font-family: inherit;
  border: 1px solid var(--rule);
  background: var(--surface);
  color: var(--ink);
  border-radius: 4px;
}
body.coin-finder .ff-row button {
  padding: .3em 1em;
  font-family: inherit;
  font-size: .95em;
  background: var(--gold);
  color: var(--on-accent);
  border: 0;
  border-radius: 4px;
  cursor: pointer;
}
body.coin-finder .ff-clear { font-size: calc(.85rem * var(--fs-small)); }
body.coin-finder .finder-hint,
body.coin-finder .finder-count {
  color: var(--ink-caption);
  font-size: calc(.92rem * var(--fs-small));
}
body.coin-finder .finder-mine { color: var(--ink-accent); }
body.coin-finder .finder-results {
  border-collapse: collapse;
  width: 100%;
  margin-bottom: 1.5em;
}
body.coin-finder .finder-results td {
  border-bottom: 1px solid var(--rule-table);
  padding: .5em .6em;
  vertical-align: top;
}
body.coin-finder .fr-thumb { width: 84px; padding-left: 0 !important; }
body.coin-finder .fr-thumb img {
  width: 80px;
  height: 80px;
  object-fit: contain;
  background: var(--surface-sunken);
  border-radius: 50%;
  display: block;
}
body.coin-finder .fr-thumb.two { width: 176px; white-space: nowrap; }
body.coin-finder .fr-thumb.two img { display: inline-block; vertical-align: middle; }
body.coin-finder .fr-thumb.two a + a img { margin-left: 8px; }
body.coin-finder .fr-head { font-weight: bold; color: var(--ink-strong); }
body.coin-finder .fr-head a { color: inherit; }
body.coin-finder .fr-head .fr-ext,
body.coin-finder .fr-head .mine {
  font-weight: normal;
  font-size: calc(.85rem * var(--fs-small));
  margin-left: .7em;
}
body.coin-finder .fr-head .mine { color: var(--gold); }
body.coin-finder .fr-facts { color: var(--ink-accent); font-size: .95em; margin-top: .1em; }
body.coin-finder .fr-legend { font-variant: small-caps; letter-spacing: .03em; margin-top: .15em; }
body.coin-finder .fr-desc,
body.coin-finder .fr-ctrl {
  color: var(--ink-caption);
  font-size: calc(.88rem * var(--fs-small));
  margin-top: .15em;
}
body.coin-finder .fr-id { margin-top: .25em; }
body.coin-finder .fr-id code,
body.coin-finder .subtitle code {
  font-size: .85em;
  background: var(--surface-sunken);
  padding: .05em .35em;
  border-radius: 3px;
  user-select: all;   /* one click selects the whole ref_id line for the card */
}
body.coin-finder .fr-count {
  width: 11em;
  text-align: right;
  color: var(--ink-caption);
  font-size: calc(.88rem * var(--fs-small));
  white-space: nowrap;
}
body.coin-finder .finder-raw { margin: 1.5em 0; }
body.coin-finder .finder-raw summary { cursor: pointer; color: var(--ink-accent); }
body.coin-finder .finder-raw-table { border-collapse: collapse; font-size: calc(.85rem * var(--fs-small)); }
body.coin-finder .finder-raw-table th,
body.coin-finder .finder-raw-table td {
  border-bottom: 1px solid var(--rule-table);
  padding: .2em .6em;
  text-align: left;
  vertical-align: top;
}
body.coin-finder .finder-raw-table th { color: var(--ink-accent); font-weight: normal; white-space: nowrap; }
@media (max-width: 600px) {
  body.coin-finder .fr-count { width: auto; white-space: normal; text-align: left; }
  body.coin-finder .fr-thumb { width: 56px; }
  body.coin-finder .fr-thumb img { width: 52px; height: 52px; }
}
