/* STM Journals — the whole front end.

   One hand-written stylesheet, no framework and no build step. That is a
   deliberate constraint, not a shortcut: every page has to be legible and
   navigable with no JavaScript, because that is what Google Scholar, the DOAJ
   reviewer and a screen reader actually receive. A framework would also be a
   second thing to keep in step with a Django template at cutover.

   Order: tokens, resets, typography, layout, header/footer, components,
   page-specific rules, responsive, dark mode, print.

   Everything is expressed in tokens so the identity can be changed in one
   place. If you change a colour, check its contrast against --bg and --bg-alt
   before committing -- the values below are chosen to clear WCAG AA. */

/* Tokens --------------------------------------------------------------- */

/* The palette is the live theme's own `:root`, copied value for value from
   journals.stmjournals.com/journal/<slug>/ rather than re-invented:

     --primary-color   #2c3e50    --brand-primary    #7a4db5
     --secondary-color #34495e    --brand-secondary  #e8944a
     --text-medium     #5a6c7d    --bg-secondary     #f8f9fa
     --text-light      #95a5a6    --bg-tertiary      #ecf0f1
     --border-color    #ddd       --border-light     #e8e8e8

   Grey page, white cards, slate type, purple as the one colour that means
   "this is a link or this matters", warm orange only where something is being
   pointed at. An author arriving from the old site should not have to wonder
   whether this is the same publisher.

   Two of those values cannot carry text and are not asked to. #e8944a is 2.4:1
   on white and --text-light #95a5a6 is 2.6:1 -- both far below the 4.5:1 floor.
   The orange lives on as --accent-bright for borders, rules and hover states;
   where the warm colour has to set type, --accent (5.9:1) does it, and every
   place the theme used --text-light for words this uses --faint instead. */

:root {
  /* Ink and paper. */
  --ink: #2c3e50;          /* the theme's slate: 11:1 on white, 10.4:1 on grey */
  --muted: #5a6c7d;        /* the theme's --text-medium, 5.4:1 */
  /* Metadata, never load-bearing -- but still clears 4.5:1 on --bg-alt,
     because "decorative" is not a licence to make text unreadable. This is
     where the theme's unreadable --text-light would have gone. */
  --faint: #5f6d7d;
  --bg: #ffffff;
  --bg-alt: #f8f9fa;       /* the theme's --bg-secondary: the page ground */
  --bg-sink: #ecf0f1;      /* the theme's --bg-tertiary: chips, inputs */
  --rule: #e8e8e8;         /* --border-light */
  --rule-strong: #dddddd;  /* --border-color */
  --slate-deep: #34495e;   /* --secondary-color: the footer */
  /* Type on the slate footer. The theme uses white at 60% for the fine print,
     which lands near 4:1 -- these are lifted until both clear AA. */
  --on-slate: #dfe5ec;
  --on-slate-faint: #b9c4d1;

  /* Brand. The purple clears AA on white (5.9:1) at body size, so unlike most
     brand colours it can be the link colour as well as the accent -- which is
     what the live theme does, and why the two read as one site. */
  --brand: #7a4db5;
  --brand-deep: #4a2b78;
  --brand-tint: #f3eefa;
  --link: #7a4db5;
  --link-hover: #4a2b78;
  --accent: #8a5a1f;       /* the warm colour, dark enough to set type in */
  --accent-bright: #e8944a; /* --brand-secondary: borders, rules, hover only */
  --accent-tint: #fdf4e9;
  --oa: #14653f;
  --oa-tint: #e9f5ef;
  --metric-bg: #e6f1fb;    /* the theme's metric cards, rgb(230 241 251) */
  /* The blue the metric cards were already tinted with, dark enough to set a
     mark in. The fourth colour in the sidebar's action rows; it has no tint of
     its own because --metric-bg is exactly it. */
  --info: #1c5aa0;
  --info-deep: #14406f;    /* its hover, the same step the brand takes */
  /* Retraction, and nothing else. The palette had no red at all, so the one
     state a reader must not miss was being drawn in the same amber as a
     paywall notice. */
  --danger: #b3261e;

  /* The theme's three shadows, verbatim. It leans on soft shadow rather than
     hard borders, which is most of why it reads as current. */
  --shadow-soft: 0 1px 3px rgba(0, 0, 0, .12);   /* --shadow-light: resting card */
  --shadow-card: 0 4px 6px rgba(0, 0, 0, .1);    /* --shadow-medium: hover */
  --shadow-lift: 0 4px 20px rgba(122, 77, 181, .1); /* the sidebar's purple lift */

  /* Type. Serif to read, sans to navigate -- the split a journal reader
     expects, and it keeps long abstracts comfortable at 42rem. Inter is the
     live site's face and is used when the reader already has it; it is not
     fetched from Google, because a font request on every page is a third party
     watching every reader for the sake of a small difference in shape. */
  --serif: Georgia, "Iowan Old Style", "Times New Roman", serif;
  --sans: Inter, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
  --measure: 42rem;        /* ~85 characters: the readable line length */
  --page: 68rem;

  /* A 1.2 scale from 1rem, rounded to something a browser renders crisply. */
  --t-xs: .75rem;
  --t-sm: .8125rem;
  --t-base: 1rem;
  --t-md: 1.125rem;
  --t-lg: 1.375rem;
  --t-xl: 1.75rem;
  --t-2xl: 2.25rem;

  --s-1: .25rem;
  --s-2: .5rem;
  --s-3: .75rem;
  --s-4: 1rem;
  --s-5: 1.5rem;
  --s-6: 2rem;
  --s-7: 3rem;
  --s-8: 4rem;

  /* The page card's inset -- see `main`. Redefined at the phone breakpoint. */
  --pad: var(--s-6);

  /* The theme's three radii: 6px on an article card, 8px on a section or a
     control, 12px on a sidebar card, a metric card or a pill. */
  --radius: 6px;
  --radius-md: 8px;
  --radius-lg: 12px;
}

/* Reset ---------------------------------------------------------------- */

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

body {
  margin: 0;
  /* Grey ground, white cards -- the live theme's arrangement. The content
     surfaces are drawn below by `main` and by `.journal-main > section`. */
  background: var(--bg-alt);
  color: var(--ink);
  /* Long-form academic prose in a serif at 16px is the reading baseline;
     everything chrome-like opts into --sans below. */
  font: var(--t-base)/1.65 var(--serif);
  text-rendering: optimizeLegibility;
}

img, svg { max-width: 100%; height: auto; }

/* Typography ----------------------------------------------------------- */

h1, h2, h3, h4,
.brand, .byline, .where, .kicker, .stats, nav, table, button, input, select,
.result-count, .pagination, .tag-list, .badge, .chip, .button {
  font-family: var(--sans);
}

h1 { font-size: var(--t-xl); line-height: 1.2; letter-spacing: -.015em; margin: 0 0 var(--s-3); }
h2 { font-size: var(--t-lg); line-height: 1.3; margin: var(--s-6) 0 var(--s-3); }
h3 { font-size: var(--t-md); line-height: 1.35; margin: var(--s-5) 0 var(--s-2); }
h4 { font-size: var(--t-base); margin: var(--s-4) 0 var(--s-1); }

p { margin: 0 0 var(--s-4); }

a { color: var(--link); text-underline-offset: .15em; }
a:hover { color: var(--link-hover); }

/* One visible focus style everywhere. Keyboard users navigate this site the
   same way a screen reader does, and the browser default is invisible on the
   dark header. */
a:focus-visible, button:focus-visible, input:focus-visible,
select:focus-visible, summary:focus-visible {
  outline: 2px solid var(--link);
  outline-offset: 2px;
  border-radius: 2px;
}

.muted { color: var(--muted); }
.faint { color: var(--faint); }
.lead { font-size: var(--t-md); color: var(--muted); line-height: 1.55; }
.stats { color: var(--muted); font-size: var(--t-sm); }
.small { font-size: var(--t-sm); }

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

.skip { position: absolute; left: -9999px; }
.skip:focus {
  left: var(--s-2); top: var(--s-2);
  z-index: 20;
  padding: var(--s-2) var(--s-4);
  background: var(--ink);
  color: var(--bg);
  border-radius: var(--radius);
}

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

/* The theme's `.content-section`: a white card on the grey ground, 8px, a
   hairline and the light shadow. Every page gets one by default; the journal
   page opts out below because it draws a card per section instead, and a card
   inside a card is just a thicker border. */
main {
  /* A 1rem gutter at every width, matching the header's and the footer's own
     padding, so the card's edges line up with the brand and the footer columns
     instead of running to the glass. */
  width: min(var(--page), 100% - var(--s-4) * 2);
  margin: var(--s-5) auto var(--s-7);
  /* --pad is the page card's inset. The hero bleeds to the card's edge by
     negating it, so the two are declared once and shrink together on a phone
     rather than drifting apart in a media query. */
  padding: var(--pad);
  background: var(--bg);
  border: 1px solid var(--rule);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-soft);
}
body.page-journal main {
  background: none;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  /* Its sections draw their own cards, so this only needs the gutter, which
     `width` above already provides. */
  padding: var(--s-5) 0 var(--s-7);
}

.breadcrumb {
  max-width: var(--page);
  margin: 0 auto;
  padding: var(--s-3) var(--s-4) 0;
  font-family: var(--sans);
  font-size: var(--t-xs);
}
.breadcrumb ol {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-1) var(--s-2);
  margin: 0; padding: 0;
  color: var(--faint);
}
.breadcrumb li + li::before { content: "›"; margin-right: var(--s-2); color: var(--rule-strong); }
.breadcrumb a { color: var(--muted); }

/* Header --------------------------------------------------------------- */

/* White and sticky, the way the live site's `.jhn-nav` is: slate labels, purple
   on hover, one hairline underneath. It follows the reader down the page
   because the search box is in it and a reader who has scrolled into an
   archive is exactly the reader who wants to search. */
.site-header {
  position: sticky;
  top: 0;
  z-index: 101;
  background: var(--bg);
  color: var(--ink);
  border-bottom: 1px solid var(--rule);
}
.header-inner {
  max-width: var(--page);
  margin: 0 auto;
  padding: var(--s-3) var(--s-4);
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: var(--s-3) var(--s-5);
}

.brand { margin: 0; display: flex; align-items: center; gap: var(--s-3); }
.brand a { color: var(--ink); text-decoration: none; display: flex; align-items: center; gap: var(--s-3); }
.brand .logo { flex: none; color: var(--brand); }
.brand .name { font-size: var(--t-md); font-weight: 700; letter-spacing: -.01em; line-height: 1.15; }
.brand .tagline {
  display: block;
  font-weight: 400;
  font-size: var(--t-xs);
  color: var(--muted);
  letter-spacing: .01em;
}

.header-search { display: flex; gap: var(--s-2); width: min(24rem, 100%); margin: 0; }
.header-search input { flex: 1; min-width: 0; }
.header-search button { flex: none; }

/* The menu button. Off the page entirely on a desktop, where the nav is always
   open; below 44rem it is the only thing standing between the reader and eleven
   links. The checkbox is moved off-screen rather than `display: none`, because a
   hidden input cannot be focused and the button has to be reachable by tab. */
.nav-toggle { position: absolute; opacity: 0; pointer-events: none; }
.nav-button { display: none; }

.site-nav {
  grid-column: 1 / -1;
  border-top: 1px solid var(--rule);
  padding-top: var(--s-2);
  overflow-x: auto;
  scrollbar-width: thin;
}
.site-nav ul {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-5);
  margin: 0; padding: 0;
}
.site-nav a {
  color: var(--ink);
  font-size: var(--t-sm);
  font-weight: 500;
  text-decoration: none;
  padding: var(--s-1) 0;
  border-bottom: 2px solid transparent;
}
.site-nav a:hover, .site-nav a[aria-current] { color: var(--brand); border-bottom-color: var(--brand); }

/* Pushed to the far end of the same row rather than given a place of its own in
   the header grid: on a phone the nav already wraps, so the account simply
   wraps with it instead of costing a third header line. */
.site-nav .account {
  margin-left: auto;
  display: flex;
  align-items: baseline;
  gap: var(--s-3);
}
.site-nav .account form { margin: 0; }
.site-nav .who { font-size: var(--t-sm); color: var(--muted); font-weight: 500; }

/* Sign out has to be a POST -- a link would let any page on the internet sign a
   reader out with an image tag -- so it is a button that has been asked to stop
   looking like one. */
.linkish {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  font-size: var(--t-sm);
  font-weight: 500;
  color: var(--ink);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.linkish:hover { color: var(--brand); }

/* Forms and controls --------------------------------------------------- */

input[type="search"], input[type="text"], input[type="email"], select, textarea {
  font-family: var(--sans);
  font-size: var(--t-sm);
  padding: .45rem .6rem;
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--ink);
  max-width: 100%;
}

/* The theme's filled control: solid brand purple, 4px, weight 500, a little
   letter-spacing. White on #7a4db5 is 5.9:1. */
button, .button {
  display: inline-block;
  font-family: var(--sans);
  font-size: var(--t-sm);
  font-weight: 500;
  letter-spacing: .3px;
  line-height: 1.4;
  padding: .5rem 1.1rem;
  border: 1px solid var(--brand);
  border-radius: 4px;
  background: var(--brand);
  color: #fff;
  text-decoration: none;
  cursor: pointer;
  transition: background .2s ease, border-color .2s ease, transform .2s ease, box-shadow .2s ease;
}
button:hover, .button:hover { background: var(--link-hover); border-color: var(--link-hover); color: #fff; }

/* `.action-btn`: an outlined control that fills with slate and slides three
   pixels right on hover. The slide is the theme's, and it earns its place --
   in a column of five near-identical links it says which one is live. */
.button.secondary {
  background: var(--bg);
  color: var(--ink);
  border: 1.5px solid var(--rule-strong);
  border-radius: var(--radius-md);
  padding: .55rem 1rem;
}
.button.secondary:hover {
  background: var(--ink);
  border-color: var(--ink);
  color: #fff;
  transform: translateX(3px);
  box-shadow: 0 2px 8px rgba(122, 77, 181, .15);
}
.button.block { display: block; width: 100%; text-align: center; }
.button.small { padding: .2rem .55rem; font-size: var(--t-sm); }

/* How to cite: the citation itself reads as a quotation, not as a control, so
   it keeps the serif face and only the export links look clickable. */
.citation-text {
  font-size: var(--t-sm);
  line-height: 1.5;
  padding-left: var(--s-2);
  border-left: 2px solid var(--rule-strong);
}
.export-list { display: flex; flex-wrap: wrap; gap: var(--s-1); margin: 0; }

/* Inline reader -------------------------------------------------------- */

.reader-head { display: flex; flex-wrap: wrap; gap: var(--s-2); align-items: baseline;
  justify-content: space-between; }
.reader-head h1 { font-size: var(--t-md); margin: 0; flex: 1 1 20rem; }
.reader-actions { display: flex; gap: var(--s-2); margin: 0; }
/* Tall enough that a page of the paper is legible without scrolling the frame
   and the page at once, which is the thing that makes framed PDFs unbearable. */
.reader-frame {
  width: 100%;
  height: min(85vh, 60rem);
  margin: var(--s-3) 0 var(--s-2);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius);
  background: var(--bg-alt);
}

/* Badges and chips ----------------------------------------------------- */

.oa, .badge {
  display: inline-block;
  padding: 0 .4rem;
  border: 1px solid currentColor;
  border-radius: 2px;
  font-family: var(--sans);
  font-size: var(--t-xs);
  letter-spacing: .04em;
  text-transform: uppercase;
  white-space: nowrap;
}
.oa { color: var(--oa); background: var(--oa-tint); margin-left: var(--s-1); }
.badge.subscription { color: var(--muted); background: var(--bg-sink); }

/* The theme's `.keyword-tag`: a soft grey lozenge that fills with brand purple
   under the pointer. 12px rather than a full pill, so a long keyword still
   reads as a rectangle of words and not a capsule. */
.chip {
  display: inline-block;
  padding: .3rem .7rem;
  border: 1px solid var(--rule);
  border-radius: 12px;
  background: var(--bg-sink);
  font-size: var(--t-sm);
  color: var(--muted);
  text-decoration: none;
  transition: background .2s ease, color .2s ease, border-color .2s ease;
}
a.chip:hover { background: var(--brand); border-color: var(--brand); color: #fff; }

/* Panels and cards ----------------------------------------------------- */

.panel {
  background: var(--bg-alt);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  padding: var(--s-5);
}
.panel h2:first-child, .panel h3:first-child { margin-top: 0; }

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  gap: var(--s-4);
  list-style: none;
  margin: 0; padding: 0;
}
/* Every raised surface in the theme moves two pixels toward the reader and
   deepens its shadow rather than changing colour, so hover never restates
   what the colours already say. */
.card {
  border: 1px solid var(--rule);
  border-radius: var(--radius-md);
  padding: var(--s-5);
  background: var(--bg);
  box-shadow: var(--shadow-soft);
  transition: box-shadow .2s ease, transform .2s ease;
}
.card:hover { box-shadow: var(--shadow-card); transform: translateY(-2px); }
.card h3 { margin: 0 0 var(--s-2); font-size: var(--t-base); }
.card p { margin: 0; font-size: var(--t-sm); color: var(--muted); }

/* Listings ------------------------------------------------------------- */

.article-list, .journal-list, .issues, .author-index, .domain-index, .tag-list {
  list-style: none; margin: 0; padding: 0;
}

/* An article in a listing is a card, and the cards sit apart rather than being
   divided by a rule -- a hairline between two six-line blocks stops reading as
   a separator and starts reading as a border nobody meant to draw. */
.article-list { display: grid; gap: var(--s-4); }

.article-card {
  padding: var(--s-5);
  border: 1px solid var(--rule);
  border-radius: var(--radius-md);
  background: var(--bg);
  box-shadow: var(--shadow-soft);
  transition: box-shadow .2s ease, transform .2s ease;
}
.article-card:hover { box-shadow: var(--shadow-card); transform: translateY(-2px); }

/* The tag row is set in colour rather than in pills: four lozenges above every
   title turns a listing into a field of chips, and the words are already short
   and shouted. Colour does the sorting, the words do the saying. */
.card-tags {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-3);
  margin: 0 0 var(--s-3);
  font-family: var(--sans);
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
}
.card-tags .tag-published { color: var(--oa); }
.card-tags .tag-draft { color: var(--muted); }
.card-tags .tag-retracted { color: var(--danger); }
.card-tags .tag-aop { color: var(--info); }
/* Same green as the status tag beside it, and that is fine: the two are always
   in the same order, so the row reads as a sentence rather than as a code. The
   green is the site's open-access green, which a reader has already met on the
   article page -- worth more than a colour that merely differs. */
.card-tags .tag-open { color: var(--oa); }
.card-tags .tag-subscription { color: var(--accent); }
.card-tags .tag-type { color: var(--brand); }
/* The track tags, and the reason they are links: a special-issue or conference
   paper has a collection page behind it, and a reader who notices the badge is
   asking what else is in there. --info is already the "this is a different kind
   of thing" colour on this row, worn by "Ahead of print". */
.card-tags .tag-special, .card-tags .tag-conference { color: var(--info); }
.card-tags a.tag-special, .card-tags a.tag-conference { text-decoration-thickness: 1px; }
/* Pushed to the far end of the row: it is the one item here a reader scans down
   a column for, and a ragged date column is not scannable. */
.card-date {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: var(--s-1);
  font-weight: 400;
  letter-spacing: .02em;
  text-transform: none;
  color: var(--faint);
}
.card-date .icon { width: 14px; height: 14px; }

/* Set in the ink, not the link colour: in a list of twenty, twenty purple
   headlines is a wall of links. It underlines and takes the brand on hover,
   which is where a reader looks for the answer to "can I click this". */
.article-card .title {
  display: block;
  margin-bottom: var(--s-2);
  font-family: var(--serif);
  font-size: var(--t-md);
  font-weight: 700;
  line-height: 1.35;
  color: var(--ink);
  text-decoration: none;
}
.article-card .title:hover { color: var(--brand); text-decoration: underline; }

.article-card .byline { margin: 0 0 var(--s-3); }
.article-card .byline em { color: var(--muted); font-style: italic; }

/* Clamped to three lines. `truncatewords` in the template already caps what is
   sent; this caps what is shown, so cards in a column end level whether the
   abstract runs to short words or long ones.

   The clamp sits on the inner span, not on this padded box. Chrome ellipsises
   line three but still lays out line four, and on a padded element that fourth
   line paints into the padding-bottom -- a half-height row of clipped text
   sitting below the tint, which reads as a rendering fault rather than as a
   truncation. An unpadded clamp box ends exactly where the third line does. */
.card-abstract {
  margin: 0 0 var(--s-3);
  padding: var(--s-3) var(--s-4);
  border-left: 3px solid var(--info);
  border-radius: 0 var(--radius) var(--radius) 0;
  background: var(--bg-alt);
  font-size: var(--t-sm);
  line-height: 1.6;
  color: var(--muted);
}
.card-abstract .clamp {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  overflow: hidden;
}
.card-abstract strong { color: var(--ink); }

.card-source {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  margin: 0;
  padding-top: var(--s-3);
  border-top: 1px solid var(--rule);
  font-family: var(--sans);
  font-size: var(--t-sm);
  color: var(--muted);
}
.card-source em { font-style: italic; }
/* The journal name is a link but not an invitation -- the button beside it is
   the invitation. It keeps the link colour and takes its underline on hover. */
.card-source a:not(.button) { text-decoration: none; }
.card-source a:not(.button):hover { text-decoration: underline; }
/* `auto` rather than leaning on space-between: once the source line wraps to
   two rows the button is the only item left on its row, and space-between has
   nothing to push it against. */
.card-source .source-line { flex: 1 1 18rem; }
/* The one blue control on the site. A listing's job is to send the reader into
   an article, so this button is not competing with the purple ones around it --
   it is the only thing on the card that is meant to be pressed. */
.card-source .button {
  flex: none;
  margin-left: auto;
  background: var(--info);
  border-color: var(--info);
}
.card-source .button:hover { background: var(--info-deep); border-color: var(--info-deep); }

.byline, .where {
  margin: var(--s-1) 0 0;
  font-family: var(--sans);
  font-size: var(--t-sm);
  color: var(--muted);
  line-height: 1.5;
}
.byline { color: var(--ink); }

.journal-list li { padding: var(--s-1) 0; }
.issues { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.issues li { border: 1px solid var(--rule); border-radius: var(--radius); background: var(--bg-alt); }
.issues a { display: block; padding: .3rem .7rem; text-decoration: none; font-family: var(--sans); font-size: var(--t-sm); }
.issues li:hover { border-color: var(--link); }
.issues .special { display: block; padding: 0 .7rem .3rem; font-size: var(--t-xs); color: var(--muted); }

table.journals { width: 100%; border-collapse: collapse; font-size: var(--t-sm); }
table.journals th, table.journals td {
  text-align: left;
  padding: var(--s-3) var(--s-2);
  border-bottom: 1px solid var(--rule);
  vertical-align: top;
}
table.journals th { font-size: var(--t-xs); text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }
table.journals tbody tr:hover { background: var(--bg-alt); }
table.journals .num { text-align: right; font-variant-numeric: tabular-nums; }
.abbrev { display: block; color: var(--faint); font-size: var(--t-xs); }

/* Both currencies are list prices, not a conversion of each other, so they are
   stacked rather than joined with a slash -- one line per figure reads as two
   prices, "₹7,900 / $299" reads as an exchange rate. */
.price .inr, .price .usd { display: block; font-variant-numeric: tabular-nums; }
.price .usd { color: var(--muted); font-size: var(--t-xs); }

/* The same two figures inside a button. They go under the label rather than
   after it -- run on, "Buy this article ₹1,800 $149" sets as one mangled
   number -- and the dollar line is dimmed with `opacity` rather than `--muted`
   because this button inverts to white-on-ink on hover, where a fixed grey
   would go from quiet to unreadable. */
.button .price { display: block; margin-top: .15rem; font-weight: 400; }
.button .price .inr { font-size: var(--t-base); }
.button .price .usd { color: inherit; opacity: .7; }

/* Journal covers ------------------------------------------------------- */

/* 258 journals and not one cover image uploaded. Rather than 258 broken
   images or 258 grey boxes, a cover is drawn from the journal's own initials
   on a hue derived from its slug -- stable, distinct, and replaced the moment
   a real cover lands in `Journal.cover`. */
.cover {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 3 / 4;
  width: 100%;
  border-radius: var(--radius);
  border: 1px solid var(--rule);
  background: linear-gradient(160deg, hsl(var(--hue, 210) 45% 32%), hsl(var(--hue, 210) 55% 18%));
  color: #fff;
  font-family: var(--sans);
  font-weight: 700;
  font-size: var(--t-lg);
  letter-spacing: .06em;
  text-align: center;
  overflow: hidden;
}
.cover img { width: 100%; height: 100%; object-fit: cover; }

.cover .initials { padding: 0 .2rem; }

/* The masthead and the section strip are one white card in two pieces: the head
   rounds its top corners and drops its bottom edge, the strip picks the edge up
   and rounds the bottom. Two elements, one surface. */
.journal-head {
  display: grid;
  grid-template-columns: 8rem minmax(0, 1fr);
  gap: var(--s-5);
  align-items: start;
  background: var(--bg);
  border: 1px solid var(--rule);
  border-bottom: 0;
  border-radius: var(--radius-md) var(--radius-md) 0 0;
  box-shadow: var(--shadow-soft);
  padding: var(--s-6) var(--s-6) var(--s-5);
}
.journal-head h1 { margin-top: 0; }
/* The theme's `.quick-actions`, laid across instead of down because here they
   sit under the title rather than in the rail. */
.journal-actions { display: flex; flex-wrap: wrap; gap: var(--s-2); margin: var(--s-4) 0 0; }
/* Editor-written prose, so it gets a measure and nothing else. */
.journal .description, .page .body { max-width: var(--measure); }

/* An editorial page and its rail. Same two columns as a journal's, and for the
   same reason: prose is capped at `--measure` because it is unreadable wider,
   which inside a 68rem card left a third of the width white. What belongs in
   that space is the reader's next step -- these pages are the commonest Google
   landing on the site and used to end at the footer. */
.page-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 20rem;
  gap: var(--s-7);
  align-items: start;
}
/* Twenty numbered sections in the privacy policy: a sticky panel that long
   would run off the bottom of the screen and take its last entries with it. */
/* Unnumbered, though it is an `ol`: half these pages number their own sections
   in the heading text -- "1. Introduction" -- and a marker beside that reads
   "1. 1. Introduction". The order is in the markup for anyone listening to it;
   it does not need to be drawn twice. */
.toc-list {
  max-height: calc(100vh - 8rem);
  overflow-y: auto;
  margin-bottom: 0;
}
/* Clear of the sticky header, or a jumped-to heading lands underneath it.
   Same figure the journal's own section links use. */
.page .body [id] { scroll-margin-top: 5.5rem; }

/* Home ----------------------------------------------------------------- */

/* The live theme's hero is not a colour field -- it is `--gradient-subtle`,
   #f8f9fa to #ffffff at 135deg, with the type in slate and a hairline under it.
   The restraint is the point: on a publisher's home page the loudest thing
   should be the journals, not the banner. */
.hero {
  background: linear-gradient(135deg, var(--bg-alt) 0%, var(--bg) 100%);
  color: var(--ink);
  margin: calc(var(--pad) * -1) calc(var(--pad) * -1) var(--s-6);
  padding: var(--s-7) var(--s-5);
  border-bottom: 1px solid var(--rule);
  border-radius: var(--radius-md) var(--radius-md) 0 0;
  text-align: center;
}
.hero-inner { max-width: var(--measure); margin: 0 auto; }
.hero h1 { font-size: var(--t-2xl); font-weight: 600; letter-spacing: -.5px; margin-bottom: var(--s-4); }
.hero .lead { color: var(--muted); margin-bottom: var(--s-5); }
.hero-search { display: flex; gap: var(--s-2); justify-content: center; flex-wrap: wrap; }
.hero-search input { flex: 1 1 20rem; font-size: var(--t-base); padding: .6rem .8rem; }
.hero-search button { font-size: var(--t-base); padding: .6rem 1.2rem; }

/* `.hero-stats`: white cards that auto-fit at 200px, the figure in brand purple
   at 2.2rem, the label small and grey, and a two-pixel lift under the pointer. */
/* Four figures, laid out as a whole number of rows. `auto-fit` at 11rem could
   only get three across the 42rem hero, which left "Open access" stranded on a
   row of its own -- it read as a footnote to the other three rather than as the
   fourth of four. */
.figures {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--s-4);
  margin: var(--s-6) auto 0;
  padding: 0;
  list-style: none;
  max-width: var(--page);
}
.figures li {
  background: var(--bg);
  border: 1px solid var(--rule);
  border-radius: var(--radius-md);
  padding: var(--s-6) var(--s-5);
  transition: box-shadow .2s ease, transform .2s ease;
}
.figures li:hover { box-shadow: var(--shadow-card); transform: translateY(-2px); }
.figures a { text-decoration: none; display: block; }
.figures a:hover .label { color: var(--brand); }
.figures .n { display: block; font-family: var(--sans); font-size: var(--t-xl); font-weight: 700; color: var(--brand); line-height: 1.1; }
.figures .label { font-size: var(--t-sm); color: var(--muted); margin-top: var(--s-2); display: block; }

.section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-4);
  flex-wrap: wrap;
  /* The theme's `.section-title` rule: two pixels of --bg-tertiary, not a
     hairline. It is what separates a heading from a paragraph at a glance. */
  border-bottom: 2px solid var(--bg-sink);
  padding-bottom: var(--s-3);
  margin-top: var(--s-7);
}
.section-head h2 { margin: 0 0 var(--s-2); font-weight: 600; }
.section-head a { font-family: var(--sans); font-size: var(--t-sm); }

/* The subject cards carry their journal links inline. Six is where a card
   stops being scannable; the rest are one click away on the subject page. */
.card .journal-list { margin-top: var(--s-3); font-size: var(--t-sm); }
.card .journal-list li { padding: .15rem 0; }
.card .more { margin-top: var(--s-2); font-size: var(--t-sm); font-family: var(--sans); }

.audience {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: var(--s-4);
  margin: var(--s-6) 0 0;
}

/* Article -------------------------------------------------------------- */

/* Two columns on a desktop: the paper itself keeps a readable measure and the
   things a reader *does* (download, cite, share) sit beside it rather than
   pushing the abstract down the page. One column on a phone, actions first --
   on a phone the download button is the whole point of the visit. */
.article-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 17rem;
  gap: var(--s-7);
  align-items: start;
}
.article { max-width: var(--measure); min-width: 0; }
.article h1 { font-family: var(--serif); font-size: var(--t-xl); line-height: 1.25; }
.article-aside { position: sticky; top: var(--s-4); display: grid; gap: var(--s-4); }
.article-aside .panel { padding: var(--s-4); }

.kicker {
  font-family: var(--sans);
  font-size: var(--t-sm);
  color: var(--muted);
  margin: 0 0 var(--s-2);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-2);
}
.kicker .type { text-transform: capitalize; }

.retraction {
  border-left: 4px solid var(--accent);
  background: var(--accent-tint);
  padding: var(--s-3) var(--s-4);
  margin: 0 0 var(--s-4);
  color: var(--accent);
  border-radius: 0 var(--radius) var(--radius) 0;
}

.authors { list-style: none; margin: var(--s-4) 0; padding: 0; font-size: var(--t-sm); font-family: var(--sans); }
.authors li { margin-bottom: var(--s-1); }
.authors .name { font-weight: 600; }
.authors a.name { text-decoration: none; }
.authors a.name:hover { text-decoration: underline; }
.authors .affiliation { display: block; color: var(--muted); font-size: var(--t-xs); }
.corresponding { color: var(--accent); }

dl.citation, dl.journal-meta, dl.author-meta {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: var(--s-1) var(--s-4);
  font-family: var(--sans);
  font-size: var(--t-sm);
  margin: var(--s-4) 0;
  padding: var(--s-3) 0;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}
dl.citation dt, dl.journal-meta dt, dl.author-meta dt { color: var(--muted); }
dl.citation dd, dl.journal-meta dd, dl.author-meta dd { margin: 0; }
dl.author-meta { border: 0; padding: 0; }

.abstract { font-size: var(--t-md); line-height: 1.7; }
.abstract p:first-child { margin-top: 0; }

.keywords ul { list-style: none; display: flex; flex-wrap: wrap; gap: var(--s-2); margin: 0; padding: 0; }

.fulltext-access {
  margin: var(--s-6) 0;
  padding: var(--s-4);
  background: var(--bg-alt);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
}
.fulltext-access h2 { margin-top: 0; }
.fulltext-access p:last-child { margin-bottom: 0; }

/* In the sidebar the panel already draws the box, and the definition list
   already sits under its own heading, so both drop their own framing. */
.article-aside .fulltext-access { margin: 0; padding: 0; background: none; border: 0; }
.article-aside .panel h2 { font-family: var(--sans); font-size: var(--t-xs);
  text-transform: uppercase; letter-spacing: .06em; color: var(--muted); margin-bottom: var(--s-3); }
.article-aside dl.citation { margin: 0; padding: 0; border: 0; grid-template-columns: 1fr;
  gap: 0; font-size: var(--t-xs); }
.article-aside dl.citation dt { margin-top: var(--s-2); }
.article-aside dl.citation dd { font-size: var(--t-sm); }

.references ol { padding-left: var(--s-5); font-size: var(--t-sm); color: var(--muted); }
.references li { margin-bottom: var(--s-2); }
/* A resolver link on its own line: it is the one part of a reference that is
   worth clicking, and buried mid-sentence nobody sees it. */
.references .doi { display: block; word-break: break-all; }
/* Any link in a reference, not just the DOI: a bare URL in an author's own
   citation text has no space in it to wrap at, and one long one pushed the
   whole phone layout 368px sideways. */
.references a { overflow-wrap: anywhere; }
.references .count { font-weight: 400; }

details.collapsible > summary {
  cursor: pointer;
  font-family: var(--sans);
  font-size: var(--t-md);
  font-weight: 600;
  padding: var(--s-2) 0;
}
details.collapsible[open] > summary { border-bottom: 1px solid var(--rule); margin-bottom: var(--s-3); }

/* Editorial board ------------------------------------------------------ */

/* Cards rather than a list: a board entry is four or five short lines, and a
   reader scans this page looking for one name or one institution. */
.board {
  list-style: none;
  padding: 0;
  margin: var(--s-4) 0 var(--s-6);
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr));
  gap: var(--s-4);
}
.board-member {
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: var(--s-4);
  background: var(--bg-alt);
  font-size: var(--t-sm);
}
.board-member p { margin: 0 0 var(--s-1); }
.board-member .name { font-family: var(--sans); font-weight: 600; font-size: var(--t-base); }
.board-member .designation { color: var(--ink); }
.board-member .where, .board-member .expertise { color: var(--muted); font-family: var(--sans); }
.board-member .expertise { font-style: italic; }
.board-member .profiles { display: flex; flex-wrap: wrap; gap: var(--s-3); margin-top: var(--s-2); }
.board-group h2 { border-bottom: 1px solid var(--rule); padding-bottom: var(--s-2); }

/* Calls for papers, special issues, conferences ------------------------ */

/* One column, not the card grid the subject pages use. A call is read, not
   scanned: the scope runs to a paragraph and the deadline has to be legible at
   a glance, and neither survives being squeezed into a 15rem tile. */
.call-list { display: grid; gap: var(--s-4); list-style: none; margin: var(--s-5) 0; padding: 0; }
.call-card {
  padding: var(--s-5);
  border: 1px solid var(--rule);
  border-radius: var(--radius-md);
  background: var(--bg);
  box-shadow: var(--shadow-soft);
  transition: box-shadow .2s ease, transform .2s ease;
}
.call-card:hover { box-shadow: var(--shadow-card); transform: translateY(-2px); }
/* An open call with a date on it is the one thing on these pages that expires,
   so it gets the only edge marking anywhere in the listing. */
.call-card.has-deadline { border-left: 3px solid var(--brand); }
.call-card h2 { margin: 0 0 var(--s-2); font-size: var(--t-md); }
.call-card h2 a { text-decoration: none; }
.call-card h2 a:hover { text-decoration: underline; }
.call-card .kicker { margin-bottom: var(--s-2); }
.call-card .kicker .tag { font-size: var(--t-xs); letter-spacing: .06em; text-transform: uppercase; }

.call-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-3);
  margin: var(--s-4) 0 0;
  font-family: var(--sans);
  font-size: var(--t-sm);
  color: var(--muted);
}
/* Pushes the button to the far end on a wide card and lets it fall below on a
   phone, without a media query for either. */
.call-meta .button { margin-left: auto; }
.call-meta .deadline { color: var(--accent); font-weight: 600; }
.call-meta .deadline.open { color: var(--muted); font-weight: 400; }

.propose { margin-top: var(--s-6); }
/* Editor-entered prose, held to a readable measure: the scope of a call runs
   long and the page is otherwise as wide as the browser. */
.prose { max-width: 68ch; }

/* The status of a call, wherever it is printed. Same three words in the same
   three colours on the list, the card and the collection page. */
.tag-open { color: var(--oa); }
.tag-closed { color: var(--muted); }
.tag-published { color: var(--brand); }
.kicker .tag-special, .kicker .tag-conference { color: var(--info); font-weight: 600; }

/* Search and browse ---------------------------------------------------- */

.search-form { margin: var(--s-4) 0 var(--s-5); }
.search-form .row { display: flex; gap: var(--s-2); align-items: center; flex-wrap: wrap; margin: 0 0 var(--s-3); }
.search-form .row label { font-family: var(--sans); font-size: var(--t-sm); color: var(--muted); }
.search-form .row input[type="search"] { flex: 1; min-width: 14rem; font-size: var(--t-base); }

.filters {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-2) var(--s-3);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  background: var(--bg-alt);
  padding: var(--s-3) var(--s-4);
}
.filters legend { font-family: var(--sans); font-size: var(--t-xs); text-transform: uppercase; letter-spacing: .05em; color: var(--muted); padding: 0 var(--s-1); }
.filters label { font-family: var(--sans); font-size: var(--t-xs); color: var(--muted); }
/* A label and the control it names are one flex item, not two. Loose, the row
   wrapped between them: "Sort" finished one line and its menu started the
   next, next to Apply, so the word labelled the wrong thing. */
.filters .field { display: flex; align-items: center; gap: var(--s-2); min-width: 0; }
.filters select { max-width: 13rem; }
.filters .clear { font-family: var(--sans); font-size: var(--t-sm); }

.result-count { font-size: var(--t-sm); color: var(--muted); }
.notice {
  border-left: 4px solid var(--link);
  background: var(--brand-tint);
  padding: var(--s-3) var(--s-4);
  font-size: var(--t-sm);
  border-radius: 0 var(--radius) var(--radius) 0;
}

.no-results .hints { font-size: var(--t-sm); padding-left: var(--s-5); }
/* The same lozenge as `.chip`, as a list. The colour flips on the li rather
   than the a so the whole tag is a target, not just its text. */
.tag-list { display: flex; flex-wrap: wrap; gap: var(--s-2); margin: var(--s-3) 0 0; }
.tag-list li {
  border: 1px solid var(--rule);
  border-radius: 12px;
  background: var(--bg-sink);
  padding: .3rem .7rem;
  font-family: var(--sans);
  font-size: var(--t-sm);
  color: var(--muted);
  transition: background .2s ease, border-color .2s ease;
}
.tag-list li a { text-decoration: none; }
.tag-list li:hover { background: var(--brand); border-color: var(--brand); }
.tag-list li:hover a { color: #fff; }

.pagination {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  margin: var(--s-5) 0;
  font-family: var(--sans);
  font-size: var(--t-sm);
}
/* Greyed out, not invisible: --rule-strong is a border colour and reads at
   1.6:1 against paper. */
.pagination .disabled { color: var(--faint); }

.alphabet ul { list-style: none; display: flex; flex-wrap: wrap; gap: var(--s-2); margin: var(--s-3) 0; padding: 0; font-size: var(--t-sm); font-family: var(--sans); }
.alphabet a { text-decoration: none; padding: .1rem .35rem; border-radius: 2px; }
.alphabet a[aria-current] { font-weight: 700; background: var(--brand-tint); color: var(--brand-deep); }

.author-index { columns: 3 15rem; column-gap: var(--s-6); font-size: var(--t-sm); font-family: var(--sans); }
.author-index li { break-inside: avoid; margin-bottom: var(--s-1); }
.domain-index li { padding: var(--s-3) 0; border-bottom: 1px solid var(--rule); }
.domain-index p { margin: var(--s-1) 0 0; font-size: var(--t-sm); }

/* Footer --------------------------------------------------------------- */

/* The theme's `.footer`: the slate `--secondary-color` full-bleed, white type,
   3rem of air above the columns. It is the one dark band on the page and it
   ends it -- everything above is white cards on grey. */
.site-footer {
  background: var(--slate-deep);
  padding: var(--s-7) var(--s-4) var(--s-5);
  margin-top: var(--s-7);
  font-family: var(--sans);
  font-size: var(--t-sm);
  color: var(--on-slate);
}
.footer-inner {
  max-width: var(--page);
  margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: var(--s-5);
}
.footer-col h2 { font-size: var(--t-xs); text-transform: uppercase; letter-spacing: .06em; margin: 0 0 var(--s-3); color: #fff; }
.footer-col ul { list-style: none; padding: 0; margin: 0; }
.footer-col li { margin-bottom: var(--s-1); break-inside: avoid; line-height: 1.8; }
.footer-col a { color: var(--on-slate); text-decoration: none; }
.footer-col a:hover { color: #fff; text-decoration: underline; }
.footer-bottom {
  max-width: var(--page);
  margin: var(--s-5) auto 0;
  padding-top: var(--s-4);
  border-top: 1px solid rgba(255, 255, 255, .12);
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-4);
  justify-content: space-between;
  font-size: var(--t-xs);
  color: var(--on-slate-faint);
}
.footer-bottom a { color: var(--on-slate); }

.page-index { columns: 2 18rem; column-gap: var(--s-6); list-style: none; padding: 0; }
.page-index li { break-inside: avoid; margin-bottom: var(--s-1); }


/* Journal page --------------------------------------------------------- */

/* Laid out like the live site: the journal down the middle, the things an
   author came to do beside it. The sidebar is markup *after* the main column
   and moved here by grid, so a phone, a screen reader and Scholar all get the
   papers before the panels. */
/* The per-journal strip the live site carries under the title. It scrolls
   sideways rather than wrapping to three rows on a phone, and it keeps a
   bottom rule so it reads as navigation and not as a paragraph of links. */
.journal-nav {
  background: var(--bg);
  border: 1px solid var(--rule);
  border-radius: 0 0 var(--radius-md) var(--radius-md);
  box-shadow: var(--shadow-soft);
  padding: 0 var(--s-6);
  overflow-x: auto;
  scrollbar-width: thin;
}
.journal-nav ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  gap: var(--s-5);
  white-space: nowrap;
}
.journal-nav a {
  display: block;
  padding: var(--s-3) 0;
  font-family: var(--sans);
  font-size: var(--t-sm);
  font-weight: 600;
  color: var(--muted);
  text-decoration: none;
  border-bottom: 2px solid transparent;
}
.journal-nav a:hover { color: var(--brand); border-bottom-color: var(--brand); }

/* `.main-content`: 1fr and a 320px rail, 3rem apart. */
.journal-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 20rem;
  gap: var(--s-7);
  align-items: start;
  margin-top: var(--s-6);
}
/* The theme's `.content-section`, verbatim: white, 8px, 2rem of padding, a
   hairline and the light shadow, stacked down the grey page. */
.journal-main > section {
  background: var(--bg);
  border: 1px solid var(--rule);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-soft);
  padding: var(--s-6);
  margin-bottom: var(--s-6);
}
/* Anchored from the strip above. The header is sticky, so a jump has to clear
   its height or it parks the heading underneath the navigation. */
.journal-main > section[id] { scroll-margin-top: 5.5rem; }
.journal-main > section > h2 {
  margin: 0 0 var(--s-5);
  font-size: var(--t-lg);
  font-weight: 600;
  border-bottom: 2px solid var(--bg-sink);
  padding-bottom: var(--s-3);
}
/* Nested headings inside the archive are structure, not section titles, so they
   do not take the rule. */
.journal-main > section .volume h3 { border-bottom: 0; }
.section-sub { color: var(--faint); font-size: var(--t-sm); margin: calc(var(--s-4) * -1) 0 var(--s-4); }

/* The four counts. Every one is a query against this database, which is why
   there is no turnaround time here -- see the template. */
/* The theme's `.metrics-container`: cards centred in a row, 20px apart, each
   capped at 280px so three of them do not stretch across a wide screen. Below
   650px the theme drops them to full width; the auto-fit does that on its own. */
.metric-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 17.5rem));
  justify-content: center;
  gap: 20px;
}
/* `.metric-card`: pale blue, 12px, 30px of padding all round. */
.metric-grid li {
  background: var(--metric-bg);
  border: 0;
  border-radius: var(--radius-lg);
  padding: 30px var(--s-5);
  text-align: center;
}
.metric-grid .figure {
  display: block;
  font-family: var(--sans);
  font-weight: 700;
  /* The live site sets these at 2.5em. They are the one thing on the page that
     is meant to be read from across a room, and shrinking them to fit a tidy
     scale is what made the old draft look like a spreadsheet. */
  font-size: var(--t-2xl);
  color: var(--ink);
  line-height: 1.1;
}
.metric-grid .label {
  display: block;
  margin-top: var(--s-1);
  font-size: var(--t-xs);
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .05em;
}

/* The theme's `.journal-details` / `.detail-row`: label bold on the left, value
   right-aligned, a hairline between rows and no box around the whole thing.
   The theme sets the value in --text-light, which is 2.6:1 and unreadable, so
   this uses --muted (5.4:1) -- same grey to the eye, legible to everyone. */
dl.info-table {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  gap: 0;
  margin: 0;
  font-size: var(--t-sm);
}
dl.info-table dt,
dl.info-table dd {
  margin: 0;
  padding: var(--s-3) var(--s-2);
  border-bottom: 1px solid var(--rule);
}
dl.info-table dt { font-family: var(--sans); font-weight: 600; color: var(--ink); }
dl.info-table dd { color: var(--muted); text-align: right; }
dl.info-table dd:last-of-type, dl.info-table dt:last-of-type { border-bottom: 0; }

/* The board preview: enough to answer "who runs this journal", with the full
   masthead one link away. */
.editor-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: var(--s-3);
}
.editor-list li {
  border: 1px solid var(--rule);
  border-left: 3px solid var(--brand);
  border-radius: var(--radius);
  padding: var(--s-3) var(--s-4);
}
.editor-list .role {
  margin: 0;
  font-size: var(--t-xs);
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--faint);
}
.editor-list .name { margin: var(--s-1) 0 0; font-weight: 600; }
.editor-list .where { margin: var(--s-1) 0 0; font-size: var(--t-sm); color: var(--muted); }

/* Latest papers, as cards rather than the one-line rows used in listings:
   this is a shop window, and an abstract snippet is what sells a read. */
/* The live theme's article card, down to the 3px purple edge that warms to
   orange under the pointer. It is the one piece of motion on the page and it
   does a job: on a list of eight near-identical titles it tells you which row
   your click will land on. */
/* Latest articles and Ahead of print, one card and two tabs ------------- */

/* Two radios and their labels, no script and no anchors. Anchors were the
   first attempt and they were wrong: following one makes the browser scroll to
   the panel, so every switch jumped the page. A radio changes nothing but its
   own checked state, so the card stays exactly where the reader left it.

   The radios are zero-sized and transparent but stay in the flow, right where
   the tab bar is. That detail is the whole fix: clicking a label focuses its
   radio, and the browser scrolls a newly focused control into view -- so a
   radio parked off-screen with `position: absolute` drags the page to it every
   time a tab is pressed. Kept in place, there is nothing to scroll to. They
   are not `display: none`, which would take them out of the tab order; Tab
   still reaches the group and the arrow keys still move between the tabs.

   Both panels are always in the document, and the papers in the hidden one
   also appear in the visible one flagged "Ahead of print", so nothing on this
   page exists only behind a tab -- not for Scholar and not for a reader whose
   stylesheet failed to load. */
.tab-radio {
  appearance: none;
  -webkit-appearance: none;
  float: left;
  width: 0; height: 0;
  margin: 0; padding: 0;
  border: 0;
  opacity: 0;
}
.tab-bar {
  display: flex;
  gap: var(--s-1);
  margin: 0 0 var(--s-5);
  border-bottom: 2px solid var(--bg-sink);
  overflow-x: auto;
  scrollbar-width: thin;
}
.tab-bar label {
  flex: none;
  padding: var(--s-3) var(--s-4);
  margin-bottom: -2px;
  border-bottom: 2px solid transparent;
  font-family: var(--sans);
  font-size: var(--t-sm);
  font-weight: 600;
  color: var(--muted);
  white-space: nowrap;
  cursor: pointer;
  transition: color .2s ease, border-color .2s ease;
}
.tab-bar label:hover { color: var(--brand); }
/* The h2 above each panel is hidden, so the standfirst has no heading to sit
   under and does not need the pull-up that `.section-sub` normally carries. */
.tab-panel .section-sub { margin-top: 0; }

.papers .tab-panel { display: none; }
#tab-latest:checked ~ .tab-panel.panel-latest,
#tab-aop:checked ~ .tab-panel.panel-aop { display: block; }

#tab-latest:checked ~ .tab-bar label[for="tab-latest"],
#tab-aop:checked ~ .tab-bar label[for="tab-aop"] {
  color: var(--brand);
  border-bottom-color: var(--brand);
}
/* The control the reader operates is the label, so the focus ring has to be
   drawn there -- the radio it belongs to has no size and cannot show one. */
#tab-latest:focus-visible ~ .tab-bar label[for="tab-latest"],
#tab-aop:focus-visible ~ .tab-bar label[for="tab-aop"] {
  outline: 2px solid var(--link);
  outline-offset: 2px;
  border-radius: 2px;
}


.journal-aside, .page-aside { position: sticky; top: var(--s-4); display: grid; gap: var(--s-4); }
/* `.sidebar-card`: no side or bottom border at all -- a 2px slate cap, 12px
   corners and a soft shadow are what hold it together. Under the pointer the
   shadow turns purple and the card rises two pixels. */
.journal-aside .panel, .page-aside .panel {
  border: 0;
  border-top: 2px solid var(--ink);
  border-radius: var(--radius-lg);
  padding: var(--s-5);
  background: var(--bg);
  box-shadow: 0 2px 12px rgba(0, 0, 0, .06);
  transition: box-shadow .3s ease, transform .3s ease;
  overflow-wrap: anywhere;
}
.journal-aside .panel:hover, .page-aside .panel:hover { box-shadow: var(--shadow-lift); transform: translateY(-2px); }
/* `.sidebar-title`: a 4px purple bar, then the label at reading size. Cheaper
   than an icon font and it survives with images off. */
.journal-aside .panel h2, .page-aside .panel h2 {
  margin: 0 0 var(--s-4);
  font-size: var(--t-md);
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink);
  display: flex;
  align-items: center;
  gap: var(--s-2);
}
.journal-aside .panel h2::before, .page-aside .panel h2::before {
  content: "";
  flex: none;
  width: 4px;
  height: 20px;
  border-radius: 2px;
  background: var(--brand);
}
.journal-aside .panel p, .page-aside .panel p { margin: 0 0 var(--s-2); }
.journal-aside .panel p:last-child, .page-aside .panel p:last-child { margin-bottom: 0; }
.link-list { list-style: none; margin: 0 0 var(--s-3); padding: 0; font-size: var(--t-sm); }
.link-list li { padding: var(--s-1) 0; }

/* Quick actions: a tinted row each, icon then label, left-aligned.

   Four outlined buttons in a column all look like the same control, and the
   reader has to read all four to find the one they came for. Giving each its
   own tint and its own mark makes the card scannable by shape and colour before
   it is read -- and the colour is never the only signal, because the label is
   right there and the mark differs too.

   The tints are the palette's existing four, so both schemes come free: each
   one is a token that already has a dark-mode value. */
.action-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-2); }
.action-list .action {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  border-radius: var(--radius-md);
  background: var(--bg-alt);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--t-sm);
  font-weight: 500;
  text-decoration: none;
  transition: transform .2s ease, box-shadow .2s ease;
}
.action-list .action .icon { flex: none; color: var(--muted); }
/* Nudged rather than recoloured on hover: the tint is carrying the identity of
   the row, so changing it would make the row look like a different action. */
.action-list .action:hover { transform: translateX(2px); box-shadow: var(--shadow-soft); }
/* Scoped under `.action-list` for specificity, not for tidiness: the two rules
   above are `.action-list .action` and `.action-list .action .icon`, and a bare
   `.action-upload` would lose to both -- silently, leaving four identical grey
   rows that look like the tints were never written. */
.action-list .action-upload   { background: var(--metric-bg); }
.action-list .action-upload   .icon { color: var(--info); }
.action-list .action-editor   { background: var(--oa-tint); }
.action-list .action-editor   .icon { color: var(--oa); }
.action-list .action-reviewer { background: var(--brand-tint); }
.action-list .action-reviewer .icon { color: var(--brand); }
.action-list .action-idea     { background: var(--accent-tint); }
.action-list .action-idea     .icon { color: var(--accent); }

/* The current issue: the volume and issue line is the fact, the button below is
   the way there. */
.panel-issue .issue-line { font-weight: 600; font-size: var(--t-md); }
.panel-issue .button { margin-top: var(--s-4); }

/* A contact is a person, so the card is centred around a mark of one: name in
   weight, role under it in the muted tone, and the two ways to reach them as
   one list so they align with each other rather than each finding its own left
   edge. */
.panel-contact { text-align: center; }
.journal-aside .panel-contact h2 { justify-content: flex-start; text-align: left; }
.journal-aside .panel p.avatar {
  width: 48px;
  height: 48px;
  margin: 0 auto var(--s-3);
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--brand);
  color: #fff;
}
.journal-aside .panel p.avatar .icon { width: 26px; height: 26px; }
.journal-aside .panel p.contact-name {
  font-weight: 600; font-size: var(--t-md); margin-bottom: 0;
}
.journal-aside .panel p.contact-role { margin-bottom: 0; }
.journal-aside .panel p.contact-address { margin-bottom: 0; }
.contact-list {
  list-style: none; margin: var(--s-3) 0 0; padding: 0;
  display: grid; gap: var(--s-2);
  font-size: var(--t-sm);
}
/* Centred as a block but each line left-aligned inside it, so a long address
   and a short phone number share one left edge instead of forming a diamond. */
.panel-contact .contact-list {
  justify-content: center;
  text-align: left;
}
.contact-list li { display: flex; align-items: center; gap: var(--s-2); }
.contact-list .icon { flex: none; color: var(--brand); }

/* The APID card and a live notice are the two things in this rail that are an
   offer rather than a fact, so they get the brand tint and a purple cap to
   separate them from the reference cards above. */
.journal-aside .panel-apid, .journal-aside .panel-notice {
  background: var(--brand-tint);
  border-top-color: var(--brand);
}
.button.block { display: block; width: 100%; text-align: center; }
.more { font-family: var(--sans); font-size: var(--t-sm); font-weight: 600; text-decoration: none; }
.more:hover { text-decoration: underline; }

/* Responsive ----------------------------------------------------------- */


/* Three breakpoints, each with one job. 60rem takes the sidebar out from
   beside the content, 44rem turns the remaining rows into stacks, 30rem is the
   small phone, where anything still side by side has to give up. Nothing is
   hidden at any width: a page that drops its navigation on a phone drops it
   for Scholar too, and half this site's readers arrive on one. */

@media (max-width: 60rem) {
  .article-layout { grid-template-columns: 1fr; gap: var(--s-5); }
  /* The sidebar drops below the journal, which is the order it is written in. */
  .journal-layout, .page-layout { grid-template-columns: 1fr; gap: var(--s-5); }
  .journal-aside, .page-aside { position: static; }
  /* Actions above the paper on a phone: the reader came for the PDF. */
  .article-aside { position: static; order: -1; }
  .article { max-width: none; }
  /* The theme's own tablet step: a section's padding comes in from 2rem. */
  :root { --pad: var(--s-5); }
  .journal-main > section { padding: var(--s-5); }
  .journal-head { padding: var(--s-5) var(--s-5) var(--s-4); }
  .journal-nav { padding: 0 var(--s-5); }
}

@media (max-width: 44rem) {
  :root { --t-xl: 1.5rem; --t-2xl: 1.85rem; --pad: var(--s-4); }
  /* The header on a phone: name and menu button on one row, search under it,
     nav only when asked for. Open at all times it stood 316px tall -- 37% of
     the screen, three wrapped rows of links, on every page, above everything
     the reader actually came for. */
  .header-inner { grid-template-columns: 1fr auto; }
  /* The tagline wraps to two lines beside a 40px logo and says, in 10px type,
     what the home page says under the title in 30px. The name alone identifies
     the site; the strapline is not what a phone reader needs at the top of
     every page. */
  .brand .tagline { display: none; }
  .header-search { width: 100%; grid-column: 1 / -1; }
  .nav-button {
    display: inline-flex;
    align-items: center;
    gap: var(--s-2);
    font-family: var(--sans);
    font-size: var(--t-sm);
    font-weight: 500;
    color: var(--ink);
    border: 1.5px solid var(--rule-strong);
    border-radius: var(--radius-md);
    padding: .4rem .7rem;
    cursor: pointer;
  }
  /* Three lines drawn with a border and two shadows rather than three elements:
     the label has one child to spare and this needs no more. */
  .nav-button .bars {
    width: 1rem;
    height: 2px;
    background: currentColor;
    box-shadow: 0 -5px currentColor, 0 5px currentColor;
  }
  .nav-toggle:focus-visible + .nav-button { outline: 2px solid var(--link); outline-offset: 2px; }
  .nav-toggle:checked + .nav-button { background: var(--bg-alt); }
  .site-nav { display: none; }
  .nav-toggle:checked ~ .site-nav { display: block; }
  /* Open, it is a list rather than a wrapped row: eleven links in three ragged
     rows are harder to hit and harder to read than eleven lines. */
  .site-nav ul { flex-direction: column; gap: 0; }
  .site-nav li { border-bottom: 1px solid var(--rule); }
  .site-nav a { display: block; padding: var(--s-3) 0; border-bottom: 0; }
  .site-nav .account { margin-left: 0; border-bottom: 0; padding-top: var(--s-2); }
  .hero { padding: var(--s-6) var(--s-4); }
  /* The header's own search box is sticky and two inches above this one. The
     hero repeated it, so a phone reader met the same field twice before any
     content -- the wide screen has room for the gesture, a phone does not. */
  .hero-search { display: none; }
  /* A card inside a 1rem gutter with 2rem of its own padding leaves a 360px
     phone about 250px of line, which is four or five words. The cards keep
     their edges and give up the padding instead. */
  .journal-main > section, .journal-head, .journal-nav { padding-left: var(--s-4); padding-right: var(--s-4); }
  .journal-head { grid-template-columns: 5rem minmax(0, 1fr); gap: var(--s-4); }
  .journal-actions { width: 100%; }
  .journal-actions .button { flex: 1 1 12rem; text-align: center; }
  /* Anchored sections clear a header that is two rows tall down here. */
  .journal-main > section[id], .page .body [id] { scroll-margin-top: 7.5rem; }
  /* Two up, not one: four numbers stacked singly ran to 460px of scrolling
     before a phone reader reached any content at all. */
  .figures { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-3); }
  .figures li { padding: var(--s-5) var(--s-4); }
  .card-grid { grid-template-columns: 1fr; }
  /* Twenty-five subject cards, each listing six journal titles that wrap to two
     lines apiece: 9,800px of one section, eleven phone screens before the
     reader reaches anything else. Stacked in a single column the list inside a
     card stops being a scan and becomes the page. The subject name is itself a
     link to the page that carries the same titles laid out to be read, and the
     count above stays, so nothing here is the only route to anything. */
  .card .journal-list, .card .more { display: none; }
  .reader-frame { height: 70vh; }
  .author-index { columns: 1; }
  .filters { flex-direction: column; align-items: stretch; }
  /* Stacked, each pair becomes label-above-control rather than one long row. */
  .filters .field { flex-direction: column; align-items: stretch; gap: var(--s-1); }
  .filters select, .filters button { width: 100%; max-width: none; }
  dl.citation, dl.journal-meta { grid-template-columns: 1fr; }
  dl.citation dt, dl.journal-meta dt { margin-top: var(--s-2); }
  /* The particulars become label-above-value; 12rem of label leaves nothing
     for an ISSN on a phone. */
  dl.info-table { grid-template-columns: 1fr; }
  dl.info-table dt { border-bottom: 0; padding-bottom: 0; background: none; }
  /* Right-aligned values read as a column only while there is a label to their
     left; stacked, they have to start where the label starts. */
  dl.info-table dd { padding-top: var(--s-1); text-align: left; }
  .metric-grid { grid-template-columns: repeat(2, 1fr); gap: var(--s-3); }
  .metric-grid li { padding: var(--s-5) var(--s-3); }
  .page-index { columns: 1; }
  /* A four-column table does not fit a phone; each row becomes a block and the
     column headings move into the cells via data-label. */
  table.journals thead { display: none; }
  table.journals, table.journals tbody, table.journals tr, table.journals td { display: block; width: 100%; }
  table.journals tr { border-bottom: 1px solid var(--rule); padding: var(--s-3) 0; }
  table.journals td { border: 0; padding: 0; }
  table.journals td[data-label]:not(:first-child)::before { content: attr(data-label) ": "; color: var(--muted); }
  /* 258 titles, and below the title its subject, its ISSN and its article count
     each on a line of their own: four lines a row, 39,000px of page. The three
     particulars flow together on one or two lines instead, which is how they
     would be read aloud anyway. Only where the cells are short -- a price or a
     package name needs its own line. */
  table.journals.compact-rows td[data-label]:not(:first-child) {
    display: inline-block;
    /* Undoing the `width: 100%` two rules up: it is what makes a stacked cell a
       full-width line, and it is what an inline-block cell must not have, or
       three of them sit inline and still take a line each. */
    width: auto;
    margin-right: var(--s-3);
    font-size: var(--t-sm);
  }
  /* And the abbreviation runs on from the title rather than taking a line of its
     own. It is five characters of the title said shorter; on a 324px column that
     line is nearly always half empty anyway. */
  table.journals.compact-rows .abbrev { display: inline; margin-left: .4rem; }
  /* Except where the first cell is data too, not the row's name. */
  table.journals.prices-only td[data-label]::before { content: attr(data-label) ": "; color: var(--muted); }
  table.journals .num { text-align: left; }
}

/* The small phone. Two things are still side by side at 44rem that stop
   working around 480px: the cover beside the journal title, and the metric
   cards two-up. The theme drops its own metrics to full width at 650px. */
@media (max-width: 30rem) {
  :root { --t-lg: 1.15rem; --t-xl: 1.35rem; --t-2xl: 1.6rem; }
  .journal-head { grid-template-columns: 1fr; justify-items: start; }
  .journal-head .cover { width: 6rem; }
  .metric-grid { grid-template-columns: 1fr; }
  /* The field and its button stay on one line. Stacked they cost a third header
     row on every page, and "Search" is 5rem wide -- a 390px phone has it. */
  .header-search button { padding-left: .8rem; padding-right: .8rem; }
  .journal-actions .button { flex: 1 1 100%; }
  .footer-bottom { justify-content: flex-start; }
  /* A pill that has to wrap is no longer a pill; let long DOIs and ISSNs
     break rather than push the card wider than the screen. */
  .breadcrumb ol, .kicker { overflow-wrap: anywhere; }
}

/* Dark mode ------------------------------------------------------------ */

/* Same rules, different token values. Nothing below the token block is
   duplicated, which is the only way this stays true as pages are added. */
@media (prefers-color-scheme: dark) {
  :root {
    --ink: #e6edf5;
    --muted: #a7b6c7;
    --faint: #8595a8;
    /* The light scheme is white cards on a grey ground. Inverted, the ground
       has to be the darker of the two and the card the lifted one, so these
       two swap roles rather than simply darkening -- otherwise every card
       reads as a hole in the page. */
    --bg: #161e28;
    --bg-alt: #0f151c;
    --bg-sink: #1c2531;
    --rule: #26313e;
    --rule-strong: #3a4657;
    /* The footer stays the one distinct band; on a dark page it separates by
       going lighter, which is the same gesture the other way up. */
    --slate-deep: #1c2733;
    --on-slate: #cdd8e4;
    --on-slate-faint: #9aa9ba;

    /* The purple has to travel in the other direction here: light enough to
       read as text on a dark ground, which the brand value is not. */
    --brand: #b492e0;
    --brand-deep: #2a1c3d;
    --brand-tint: #221a2f;
    --link: #c3a6ea;
    --link-hover: #d9c6f3;
    --accent: #e0a86b;
    --accent-bright: #e8944a;
    --accent-tint: #2a2018;
    --oa: #6cc79b;
    --oa-tint: #14261e;
    --metric-bg: #172231;
    --info: #7fb2e8;
    /* Lighter on hover here, not darker: on a dark ground a control advances by
       brightening, the same way it recedes by darkening on a light one. */
    --info-deep: #a8cbf0;
    --danger: #f0857c;
    /* Shadow does nothing on a dark ground -- a lift there is a lighter
       surface, not a darker halo -- so the cards carry their border instead. */
    --shadow-soft: none;
    --shadow-card: none;
    --shadow-lift: none;
  }
  /* With no shadow to raise them, the borderless surfaces need an edge. */
  .journal-aside .panel, .page-aside .panel { border: 1px solid var(--rule); border-top: 2px solid var(--brand); }
  .journal-aside .panel:hover, .page-aside .panel:hover { border-color: var(--rule-strong); border-top-color: var(--brand); }
  .metric-grid li { border: 1px solid var(--rule); }
  .site-footer { border-top: 1px solid var(--rule); }
  .footer-bottom { border-top-color: var(--rule); }
  /* An article card already sits on --bg and there is no shadow here to deepen,
     so hover has to be a change of surface. Not --bg-alt: that is the page
     ground in this scheme, and the card would sink into it rather than lift. */
  .article-card:hover { background: var(--bg-sink); }
  /* The abstract block borrows --bg-alt, which is darker than the card it sits
     on here -- correct on paper, inverted on a dark ground. */
  .card-abstract { background: var(--bg-sink); }
  /* The link colour is light in this scheme, so filled buttons need dark text
     rather than the white they carry on paper. */
  button, .button, button:hover, .button:hover { color: #0f151c; }
  .button.secondary { color: var(--link); }
  /* Same reason: a keyword filling with the light purple needs dark type. */
  a.chip:hover, .tag-list li:hover a { color: #0f151c; }
  .alphabet a[aria-current] { color: var(--ink); }
  .cover { background: linear-gradient(160deg, hsl(var(--hue, 210) 40% 26%), hsl(var(--hue, 210) 45% 14%)); }
}

/* Print ---------------------------------------------------------------- */

/* Readers print abstracts. The chrome is noise on paper, and a printed link
   showing only "here" is useless -- so URLs are spelled out. */
@media print {
  .site-header, .site-footer, .breadcrumb, .article-aside, .page-aside,
  .search-form, .pagination, .skip { display: none; }
  body { font-size: 11pt; color: #000; background: #fff; }
  main { max-width: none; padding: 0; }
  a { color: #000; text-decoration: underline; }
  .article a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 9pt; word-break: break-all; }
}
