/* Series editorial hub. Banner backdrop = publisher hue (gradients.css) + ghosted cover. */
.series-hub-banner {
  position: relative; overflow: hidden; border-radius: 16px;
  margin: 0 0 18px; padding: 30px 28px 26px; isolation: isolate;
  background: linear-gradient(120deg,
      var(--series-publisher-deep),
      var(--series-publisher-mid) 70%,
      var(--series-publisher-shift));
}
.series-hub-bg {
  position: absolute; inset: 0; z-index: 0;
  background-size: cover; background-position: center 26%;
  filter: blur(34px) saturate(1.1); transform: scale(1.3);
  opacity: .34; mix-blend-mode: luminosity;
}
.series-hub-shade {
  position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(105deg, color-mix(in srgb, var(--series-banner-shade-start) 66%, transparent), color-mix(in srgb, var(--series-banner-shade-end) 30%, transparent));
}
.series-hub-row { position: relative; z-index: 2; display: flex; gap: 24px; align-items: flex-start; }
.series-hub-cover {
  width: 130px; height: 195px; flex: none; object-fit: cover;
  border-radius: 8px; box-shadow: 0 12px 34px color-mix(in srgb, var(--shadow-ink) 50%, transparent);
}
.series-hub-main { color: var(--on-image); min-width: 0; }
/* Banner entrance. The banner is the whole first screen, so it is where an
   arrival is felt: the ghosted backdrop settles, the cover lifts in, and the
   header lines follow the title in reading order. Fill is `backwards`, never
   `both` -- a held final transform would leave every line a stacking context.
   The h1 never moves: it carries a view-transition-name, and a rise inside the
   cross-page morph would fight it. The cover animates transform only, so the
   LCP candidate's paint is not held behind an opacity ramp. Each duration is
   --motion-slow (test_series_hub_motion_browser's ceiling); the sequence is in
   the delays. The tokens collapse under reduced motion; the block below also
   drops the animations outright, as the rest of this file does. */
.series-hub-bg { animation: series-hub-bg-settle var(--motion-slow) var(--ease-enter) backwards; }
.series-hub-cover { animation: series-hub-cover-lift var(--motion-slow) var(--ease-enter) backwards; }
.series-hub-main > :is(.series-hub-byline, .series-hub-meta, .series-hub-actions,
                       .series-hub-desc-wrap, .series-hub-pills, .series-hub-price),
.series-hub-side {
  animation: cc-rise-in var(--motion-slow) var(--ease-enter) backwards;
  animation-delay: calc(var(--series-hub-step, 0) * 55ms);
}
.series-hub-main > .series-hub-byline { --series-hub-step: 1; }
.series-hub-main > .series-hub-meta { --series-hub-step: 2; }
.series-hub-main > .series-hub-actions { --series-hub-step: 3; }
.series-hub-main > .series-hub-desc-wrap { --series-hub-step: 3; }
.series-hub-main > :is(.series-hub-pills, .series-hub-price),
.series-hub-side { --series-hub-step: 4; }
@keyframes series-hub-bg-settle { from { opacity: 0; transform: scale(1.42); } }
@keyframes series-hub-cover-lift { from { transform: translateY(var(--motion-rise-distance)) scale(.96); } }
@media (prefers-reduced-motion: reduce) {
  .series-hub-bg,
  .series-hub-cover,
  .series-hub-main > :is(.series-hub-byline, .series-hub-meta, .series-hub-actions,
                         .series-hub-desc-wrap, .series-hub-pills, .series-hub-price),
  .series-hub-side { animation: none; }
}
.series-edit-toggle {
  position: absolute; z-index: 3; top: 16px; right: 16px;
  width: 38px; height: 38px; display: inline-grid; place-items: center;
  border: 1px solid color-mix(in srgb, var(--on-image) 34%, transparent); border-radius: 8px;
  background: color-mix(in srgb, var(--on-image) 16%, transparent); color: var(--on-image);
  box-shadow: 0 8px 24px color-mix(in srgb, var(--shadow-ink) 24%, transparent);
  backdrop-filter: blur(8px);
  transition: background .15s ease, border-color .15s ease, transform .15s ease;
}
.series-edit-toggle:hover,
.series-edit-toggle:focus-visible {
  background: color-mix(in srgb, var(--on-image) 26%, transparent); border-color: color-mix(in srgb, var(--on-image) 58%, transparent);
  color: var(--on-image); transform: translateY(-1px);
}
.series-hub-eyebrow {
  font-size: 11px; letter-spacing: .14em; text-transform: uppercase;
  color: color-mix(in srgb, var(--on-image) 72%, transparent); font-weight: 700; margin: 0;
}
.series-hub-title {
  font-size: clamp(24px, 4vw, 34px); font-weight: 800; letter-spacing: -.015em;
  line-height: 1.05; color: var(--on-image); margin: 5px 0 4px;
}
.series-hub-byline { font-size: 14px; font-weight: 600; color: var(--on-image); opacity: .95; margin: 0; }
/* Creator links sit on the cover/publisher ground in both themes (GH-594).
   The local scrim keeps bright covers readable without changing publisher hues. */
.series-hub-byline a,
.series-hub-byline a:visited {
  color: var(--on-image);
  --focus-ring: var(--on-image);
  background-color: color-mix(in srgb, var(--series-banner-shade-start) 66%, transparent);
  /* Shaped as a tag, not a 2px text highlight: the scrim is a contrast floor
     that cannot go, so it reads as a deliberate credit rather than a stray
     selection box around the name. */
  padding: 2px 7px;
  border-radius: 6px;
  line-height: 1.9;
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.series-hub-byline a:hover,
.series-hub-byline a:focus-visible {
  color: var(--on-image);
  text-decoration-thickness: 2px;
}
.series-hub-meta { font-size: 13px; color: color-mix(in srgb, var(--on-image) 82%, transparent); margin: 6px 0 0; }
.series-hub-meta .series-hub-link { font-weight: 600; }
.series-hub-desc-wrap { margin-top: 14px; }
.series-hub-desc {
  font-size: 14px; line-height: 1.55; color: color-mix(in srgb, var(--on-image) 92%, transparent);
  max-width: 640px; margin: 0;
}
/* The mobile synopsis disclosure (GH-113). Hidden by default: the clamp only
   exists under 640px, so on desktop this button would offer to expand text
   that is already whole. */
.series-hub-desc-toggle {
  display: none;
  align-items: center;
  /* The site's mobile floor is 44px on BOTH axes; "More" is only ~38px of text,
     so the width needs stating explicitly or the hit box lands under it. */
  min-height: 44px;
  min-width: 44px;
  margin: 2px 0 0;
  padding: 0;
  border: 0;
  background: none;
  color: var(--on-image);
  font: inherit;
  font-weight: 700;
  text-decoration: underline;
  cursor: pointer;
}

/* Subscribe, recommend and manage share one row in the banner's ink.

   Mobile audit 2026-10-02 (/series/black-hammer-universe, 390px): signed in
   this row measured 170px beside the cover -- a 44px Subscribe over an 82px
   boxed recommendations widget over a 44px Manage subscriptions. It is one
   flex row now, at every width: the two buttons on the first line, then a
   muted line carrying the reader count (only above zero) and Manage (only
   once subscribed). The subscribe island and the recommendations host each
   wrap an Alpine scope, so their children cannot be DOM siblings; `display:
   contents` makes them items of this row anyway, and the zero-height ::after
   at order 1 is the line break between the buttons (order 0) and the
   follow-ups (orders 2-4). Measured on the rendered page at 390px: 170px ->
   44px fresh, 112px subscribed and recommended (two 44px lines and the
   count line between them); 69px at desktop width. */
.series-hub-actions {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px;
  margin: 16px 0 0;
}
.series-hub-actions > * { margin: 0; }
.series-hub-subscribe,
.series-hub-recommendations { display: contents; }
.series-hub-actions::after { content: ""; flex-basis: 100%; height: 0; order: 1; }
.series-hub-actions-note {
  order: 2;
  margin: 0;
  font-size: 12.5px;
  line-height: 1.3;
  color: color-mix(in srgb, var(--on-image) 72%, transparent);
}
.series-hub-actions-note.skel-error { color: var(--on-image); font-weight: 600; }
.series-hub-actions-note.skel-error button {
  margin-left: 6px; padding: 0; border: 0; background: none; font: inherit;
  color: inherit; text-decoration: underline; cursor: pointer;
}
.series-hub-subscribe-error {
  flex-basis: 100%; order: 4; margin: 4px 0 0; font-size: 12px; font-weight: 600; color: var(--on-image);
}
.series-hub-manage {
  order: 3;
  color: color-mix(in srgb, var(--on-image) 72%, transparent);
  font-size: 12.5px;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.series-hub-manage:hover,
.series-hub-manage:focus-visible { color: var(--on-image); }
/* The Recommend button is sized like its Bootstrap neighbour so the two read
   as one pair; the inks are the on-image set the subscribe opt-out below uses. */
.series-hub-recommendations .series-hub-recommend {
  --recommendation-accent: var(--on-image);
  --recommendation-fg: var(--on-image);
  --recommendation-bg: color-mix(in srgb, var(--on-image) 10%, transparent);
  --recommendation-border: color-mix(in srgb, var(--on-image) 55%, transparent);
  --recommendation-hover-fg: var(--series-banner-ink);
  --recommendation-hover-bg: color-mix(in srgb, var(--on-image) 92%, transparent);
  --recommendation-hover-border: color-mix(in srgb, var(--on-image) 72%, transparent);
  --recommendation-hover-transform: none;
  --recommendation-min-height: 0;
  --recommendation-padding: .375rem .75rem;
  --recommendation-font-size: 1rem;
  --recommendation-radius: var(--bs-btn-border-radius, .375rem);
  line-height: 1.5;
  font-weight: 600;
}
.series-hub-recommendations .series-hub-recommend.active { font-weight: 600; }
/* GH-535. The signed-out hub used to spend ~180px on a recommendations box
   whose only actionable control was a sign-in link, directly under a second
   sign-in CTA. Signed out the widget is now a single muted line (signing in is
   the action, so the line says so), and the subscribe prompt moved below the
   byline/meta so the series facts come before the account ask. */
.series-hub-subscribe-signin { margin: 0 0 6px; }
/* Mobile audit 2026-09-22. The banner is a photographic ground in BOTH themes
   -- the shade gradient and the --on-image ink are theme-independent, which is
   why the title is white on light paper too. This was the one control still
   wearing Bootstrap's THEMED .btn-outline-primary, so it painted brand violet
   on that ground: ~1.2:1 in light mode, and unmeasurable in principle, because
   the backdrop is whichever cover the series happens to have. axe/Lighthouse
   cannot see it either -- the contrast rule abstains over a background image,
   so the banner had no automated coverage at all.

   The long guard is not decoration. styles.css:1640 themes EVERY outline button
   `body:not(.auth-page):not(.profile-page):not(.target-theme) .btn-outline-primary`,
   which is specificity (0,4,1) -- more than any plain descendant selector this
   sheet can write, so a `.series-hub-subscribe-signin .btn` rule sets
   --bs-btn-color and still loses `color` to it (measured: the custom property
   flipped to on-image white while the computed colour stayed brand violet). The banner
   opts OUT of that theming, so the opt-out is written at that rule's own
   weight plus this one's scope.

   Not gated behind a media query: the ground is dark at every width. */
body:not(.auth-page):not(.profile-page):not(.target-theme) .series-hub-subscribe-signin .btn-outline-primary,
body:not(.auth-page):not(.profile-page):not(.target-theme) .series-hub-subscribe .btn-outline-primary {
  color: var(--on-image);
  border-color: color-mix(in srgb, var(--on-image) 55%, transparent);
  background-color: color-mix(in srgb, var(--on-image) 10%, transparent);
}
body:not(.auth-page):not(.profile-page):not(.target-theme) .series-hub-subscribe-signin .btn-outline-primary:hover,
body:not(.auth-page):not(.profile-page):not(.target-theme) .series-hub-subscribe .btn-outline-primary:hover,
body:not(.auth-page):not(.profile-page):not(.target-theme) .series-hub-subscribe-signin .btn-outline-primary:focus-visible,
body:not(.auth-page):not(.profile-page):not(.target-theme) .series-hub-subscribe .btn-outline-primary:focus-visible {
  color: var(--on-image);
  border-color: var(--on-image);
  background-color: color-mix(in srgb, var(--on-image) 22%, transparent);
}
.series-hub-recommend-signin {
  color: color-mix(in srgb, var(--on-image) 72%, transparent);
  font-size: 12.5px;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.series-hub-recommend-signin:hover,
.series-hub-recommend-signin:focus-visible { color: var(--on-image); }
.series-hub-overlap-link { margin: 8px 0 0; }
.series-hub-overlap-link a {
  color: color-mix(in srgb, var(--on-image) 72%, transparent);
  font-size: 13px;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.series-hub-overlap-link a:hover,
.series-hub-overlap-link a:focus-visible { color: var(--on-image); }
/* Edit mode — frosted panel (state palette for the always-dark banner/cards) */
.series-edit-panel {
  position: relative; z-index: 2; margin: 8px 0 12px; padding: 14px 16px;
  max-width: 600px; border-radius: 12px;
  background: color-mix(in srgb, var(--series-edit-panel-bg) 55%, transparent);
  border: 1px solid color-mix(in srgb, var(--on-image) 16%, transparent);
  backdrop-filter: blur(6px);
}
.series-edit-panel__head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; margin-bottom: 12px;
}
.series-edit-panel__title {
  font-size: 10px; letter-spacing: .09em; text-transform: uppercase;
  font-weight: 800; color: var(--series-gold);
}
.series-edit-done {
  font-size: 12px; font-weight: 700; color: var(--on-image);
  border: 1px solid color-mix(in srgb, var(--on-image) 35%, transparent); border-radius: 999px;
  padding: 4px 14px; background: color-mix(in srgb, var(--on-image) 8%, transparent);
  transition: background .15s ease, border-color .15s ease;
}
.series-edit-done:hover, .series-edit-done:focus-visible {
  background: color-mix(in srgb, var(--on-image) 22%, transparent); border-color: color-mix(in srgb, var(--on-image) 60%, transparent); color: var(--on-image);
}
/* Sits with Done at the right of the panel head rather than being spread to the
   middle by the head's space-between. On the banner image, so --on-image. */
.series-edit-history {
  margin-left: auto; font-size: 12px; font-weight: 700; text-decoration: none;
  color: var(--on-image); opacity: .82; transition: opacity .15s ease;
}
.series-edit-history:hover, .series-edit-history:focus-visible {
  opacity: 1; color: var(--on-image); text-decoration: underline;
}
.series-inline-field { margin: 0 0 10px; }
.series-inline-field:last-child { margin-bottom: 0; }
.series-inline-label {
  display: block; margin: 0 0 4px; font-size: 9.5px; line-height: 1.1;
  text-transform: uppercase; letter-spacing: .09em; font-weight: 800;
  color: color-mix(in srgb, var(--on-image) 62%, transparent);
}
.series-inline-row { display: flex; gap: 8px; align-items: center; }
.series-inline-row--start { align-items: flex-start; }
.series-inline-input {
  min-width: 0; width: 100%; border: 1px solid color-mix(in srgb, var(--on-image) 28%, transparent);
  border-radius: 8px; padding: 7px 10px;
  background: color-mix(in srgb, var(--on-image) 13%, transparent); color: var(--on-image);
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--on-image) 8%, transparent);
}
.series-inline-input::placeholder { color: color-mix(in srgb, var(--on-image) 46%, transparent); }
.series-inline-input:focus {
  outline: none; border-color: color-mix(in srgb, var(--on-image) 76%, transparent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--on-image) 16%, transparent);
}
.series-inline-input--title { font-size: 16px; font-weight: 800; }
.series-inline-input--error { border-color: color-mix(in srgb, var(--series-error) 90%, transparent); }
.series-inline-textarea { min-height: 84px; resize: vertical; line-height: 1.45; }
.series-inline-actions { display: inline-flex; gap: 6px; align-items: center; flex: none; }
.series-inline-apply,
.series-inline-undo {
  width: 30px; height: 30px; flex: none; display: inline-grid; place-items: center;
  border: 1px solid color-mix(in srgb, var(--on-image) 25%, transparent); border-radius: 8px;
  background: color-mix(in srgb, var(--on-image) 10%, transparent); color: color-mix(in srgb, var(--on-image) 55%, transparent);
  transition: background .15s ease, border-color .15s ease, color .15s ease, box-shadow .15s ease;
}
.series-inline-undo { color: color-mix(in srgb, var(--on-image) 80%, transparent); }
.series-inline-undo:hover, .series-inline-undo:focus-visible {
  background: color-mix(in srgb, var(--on-image) 22%, transparent); border-color: color-mix(in srgb, var(--on-image) 60%, transparent); color: var(--on-image);
}
.series-inline-apply:disabled { cursor: not-allowed; }
.series-inline-apply.is-dirty {
  background: var(--series-gold); border-color: var(--series-gold); color: var(--series-gold-ink);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--series-gold) 28%, transparent);
}
.series-inline-apply.is-dirty:not(:disabled):hover,
.series-inline-apply.is-dirty:not(:disabled):focus-visible {
  background: var(--series-gold-hover); border-color: var(--series-gold-hover); color: var(--series-gold-ink);
}
.series-inline-apply.is-saving { animation: sed-pulse 1s ease infinite; }
.series-inline-apply.is-saved {
  background: color-mix(in srgb, var(--series-success) 22%, transparent); border-color: color-mix(in srgb, var(--series-success) 60%, transparent); color: var(--series-success-fg);
}
.series-inline-hint {
  margin-top: 3px; font-size: 10.5px; font-weight: 700; color: var(--series-success-fg);
}
@keyframes sed-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .45; } }
@media (prefers-reduced-motion: reduce) {
  .series-inline-apply.is-saving { animation: none; opacity: .6; }
}
.series-hub-pills { margin-top: 14px; }
.series-hub-pill {
  display: inline-block; border-radius: 999px; padding: 4px 12px; font-size: 11.5px;
  margin: 0 6px 6px 0; background: color-mix(in srgb, var(--on-image) 16%, transparent); color: var(--on-image);
  backdrop-filter: blur(5px);
}
.series-hub-pill--solid { background: color-mix(in srgb, var(--on-image) 92%, transparent); color: var(--series-banner-ink); font-weight: 600; }
a.series-hub-pill--link { cursor: pointer; text-decoration: none; transition: background .15s ease, border-color .15s ease; }
a.series-hub-pill--link:hover { background: color-mix(in srgb, var(--on-image) 30%, transparent); }

.series-hub-facts {
  display: flex; flex-wrap: wrap; gap: 26px;
  padding: 12px 4px 0; margin-bottom: 20px; font-size: 12.5px; color: var(--text-muted);
}
.series-hub-facts--after-editions { display: none; }
.series-hub-facts b { color: var(--text); }
.series-hub-fact-label {
  display: block; font-size: 10px; text-transform: uppercase; letter-spacing: .08em;
  color: var(--series-text-faint); font-weight: 700; margin-bottom: 2px;
}

.series-hub-section-title { font-size: 19px; font-weight: 800; letter-spacing: -.01em; margin: 8px 0 6px; }
/* Heading row: the title with the Lines/Timeline switch beside it. The switch
   used to be pushed to the far end of a full-width row, which put it over the
   jump rail's column — a dozen pixels above that card's top edge, so it read as
   a mis-stacked header of the RAIL rather than a control of this section, with
   a screen-wide gap between it and the heading it belongs to. Beside the
   heading it has a visible owner and cannot collide with the rail at any width.
   Wraps rather than shrinks, so a narrow screen keeps both at full size. */
.series-hub-editions-head {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px 14px;
  margin: 6px 0 16px;
}
.series-hub-editions-head .series-hub-section-title { margin: 0; }

/* The Lines/Table/Timeline switch is the shared cc-tabs `pill` variant
   (cc_tabs.css): a two-state pill in the page's own vocabulary — the same
   translucent fill, hairline border and 999px radius as the jump rail and its
   fold buttons — rather than the black-filled `segment` slab. The skin used to
   live here as `.series-hub-view-tabs`; GH-534 moved it to the primitive so the
   Discussion block's Hot/New/Top sort, directly under this switch, is the same
   control. `.series-hub-view-tabs` stays on the markup as the test hook only. */

/* The Table view's Title cell (GH-527). The search table's `.results-table-title`
   is a 350px nowrap ellipsis, sized for a results list whose columns compete;
   here the title is the widest thing on the row and the cell has the room, so
   it wraps to two lines instead of cutting off at ~45 characters. A two-line
   max-height (not the line-clamp property: test_css_shared_primitives pins that
   property to this file's mobile block, for the synopsis) keeps a very long
   subtitle from turning a row into a paragraph. The Vol. cell is narrow and
   never breaks its `Vol. 12` / `1956–1962` in two. The title's button reset
   leaves the shared :focus-visible outline intact and fills the cell so long
   wrapped titles retain one clear focus target on phone and desktop. */
.series-hub-table-sort { display: none; }
@media (max-width: 640px), (max-width: 900px) and (pointer: coarse) {
  .series-hub-table-sort {
    display: grid;
    gap: .35rem;
    margin-bottom: .75rem;
  }
  .series-hub-table-sort label {
    color: var(--text);
    font-size: .875rem;
    font-weight: 500;
  }
  .series-hub-table-sort select {
    width: 100%;
    min-width: 0;
    min-height: 44px;
    padding: .5rem .65rem;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    background: var(--surface);
    color: var(--text);
    font: inherit;
    font-size: 1rem;
  }
}
.series-hub-table-details-trigger {
  text-decoration: none;
  display: block;
  width: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.series-hub-table .results-table-title {
  display: block;
  max-width: none;
  white-space: normal;
  overflow: hidden;
  line-height: 1.3;
  max-height: 2.6em;
}
.series-hub-table .series-hub-table-volume {
  width: 1%;
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
}
.series-hub-group { margin-bottom: 18px; scroll-margin-top: 80px; }
.series-hub-group:target { animation: sfmt-flash 1.2s ease; border-radius: 8px; }
@keyframes sfmt-flash { 0% { background: color-mix(in srgb, var(--series-target-flash) 18%, transparent); } 100% { background: transparent; } }
@media (prefers-reduced-motion: reduce) { .series-hub-group:target { animation: none; } }
.series-hub-group-title {
  font-size: 12px; text-transform: uppercase; letter-spacing: .07em; font-weight: 700;
  color: var(--text-muted); margin: 16px 0 10px;
  border-bottom: 1px solid var(--border); padding-bottom: 5px;
}
/* Per-line subheaders (DC Finest: Batman / Wonder Woman / Events …). One rule
   runs out from the label so the break reads at a glance while scrolling a
   99-volume page; the count tells the reader how long the run is. */
.series-hub-line + .series-hub-line { margin-top: 26px; }
/* A folded section is a row in a directory, not a section of a page. At 26px
   apart, Collapse all on the Epic Collection umbrella still leaves 88 headings
   spread over several screens of mostly gap. :has() is progressive — where it
   is unsupported the page keeps the roomier spacing rather than breaking. */
.series-hub-line:has(.series-hub-line-toggle.is-collapsed)
  + .series-hub-line:has(.series-hub-line-toggle.is-collapsed) { margin-top: 6px; }
/* The wrapper carries the jump-rail anchor, so it — not the heading — owns the
   landing offset under the sticky site header. */
.series-hub-line { scroll-margin-top: 80px; }
.series-hub-line-title {
  font-size: 13px; text-transform: uppercase; letter-spacing: .06em; font-weight: 800;
  color: var(--text); margin: 0 0 12px;
}
.series-hub-line-chev { color: var(--text-dim); }
/* "Misc" is the leftovers, not a line DC publishes — it should not read as
   loud as Batman does. */
.series-hub-line-title--misc { color: var(--text-muted); font-weight: 700; }
.series-hub-line-toggle::after {
  content: ''; flex: 1 1 auto; height: 1px; background: var(--border);
}
.series-hub-line-count {
  font-size: 11px; font-weight: 700; letter-spacing: 0;
  color: var(--text-muted);
  padding: 1px 7px; border-radius: 999px;
  background: color-mix(in srgb, var(--text-muted) 12%, transparent);
}
/* Format subgroups inside a shared-universe line (Massive-Verse: Radiant
   Black's Deluxe Editions, then its trades). Quieter than the line heading
   above them: no rule, muted ink. */
.series-hub-format + .series-hub-format { margin-top: 18px; }
.series-hub-format-title {
  display: flex; align-items: center; gap: 8px;
  font-size: 12px; font-weight: 700; letter-spacing: .02em;
  color: var(--text-muted); margin: 0 0 10px;
}
.series-hub-format-count {
  font-size: 11px; color: var(--text-dim);
}
.series-hub-format-toggle { gap: 8px; }
.series-hub-format-chev { font-size: 10px; }

/* Editions column + sticky jump rail. The rail is a flex sibling rather than a
   float: a sticky float only reserves space where it started, so every grid
   below it would slide underneath. */
.series-hub-editions-layout { display: flex; align-items: flex-start; gap: 22px; }
.series-hub-editions-main { flex: 1 1 auto; min-width: 0; }
.series-hub-jump {
  order: 2; flex: 0 0 186px;
  position: sticky; top: 84px;
  max-height: calc(100vh - 108px); overflow-y: auto; overscroll-behavior: contain;
  padding: 10px; border: 1px solid var(--border); border-radius: 12px;
  background: color-mix(in srgb, var(--text) 3%, transparent);
}
.series-hub-jump-title {
  font-size: 10px; text-transform: uppercase; letter-spacing: .08em;
  font-weight: 700; color: var(--text-muted); margin: 0 0 6px 6px;
}
/* Fold-all controls sit in the rail's header rather than by the page title:
   they act on the same sections the rail lists, and a reader reaching for
   "collapse everything" is already looking at the list of everything. */
.series-hub-jump-head { margin-bottom: 8px; }
.series-hub-jump-folds { display: flex; flex-wrap: wrap; gap: 4px; margin: 0 0 2px 4px; }
.series-hub-jump-fold {
  font-size: 11px; font-weight: 700; letter-spacing: .01em;
  color: var(--text-muted); background: none;
  border: 1px solid var(--border); border-radius: 999px;
  padding: 2px 9px; cursor: pointer;
  transition: background var(--motion-fast, .12s) ease, color var(--motion-fast, .12s) ease;
}
.series-hub-jump-fold:hover:not(:disabled) {
  background: color-mix(in srgb, var(--text) 8%, transparent); color: var(--text);
}
/* Disabled means "already the whole page", not "unavailable" — it stays legible
   so the pair still reads as the current state rather than as broken controls. */
.series-hub-jump-fold:disabled { opacity: .42; cursor: default; }
.series-hub-jump-list { list-style: none; margin: 0; padding: 0; }
/* Group label — the timeline's bands, or the format buckets. Present only on a
   page with more than one group, where the same heading name can appear twice. */
.series-hub-jump-group + .series-hub-jump-group { margin-top: 10px; }
.series-hub-jump-group-title {
  font-size: 9.5px; text-transform: uppercase; letter-spacing: .09em;
  font-weight: 800; color: var(--text-dim); margin: 0 0 3px 8px;
}
.series-hub-jump-link {
  display: flex; align-items: center; gap: 8px;
  padding: 5px 8px; border-radius: 7px;
  font-size: 12.5px; font-weight: 600; color: var(--text); text-decoration: none;
  transition: background var(--motion-fast, .12s) ease;
}
.series-hub-jump-link:hover { background: color-mix(in srgb, var(--text) 8%, transparent); }
.series-hub-jump-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.series-hub-jump-count { flex: 0 0 auto; font-size: 10.5px; font-weight: 700; color: var(--text-muted); }
.series-hub-jump-link--misc { color: var(--text-muted); font-weight: 500; }
/* A folded section still lists — the link unfolds it — but reads quieter, so
   the rail doubles as a map of what is currently open. */
.series-hub-jump-link.is-collapsed .series-hub-jump-name { opacity: .55; }

/* Below the rail's breakpoint there is no room beside the grid: the same list
   becomes a wrapping chip row above it, so narrow screens keep the jump nav. */
@media (max-width: 991px) {
  .series-hub-editions-layout { display: block; }
  .series-hub-jump {
    position: static; max-height: none; overflow: visible;
    margin-bottom: 14px;
  }
  .series-hub-jump-list { display: flex; flex-wrap: wrap; gap: 6px; }
  .series-hub-jump-link {
    border: 1px solid var(--border); border-radius: 999px; padding: 4px 10px;
  }
  .series-hub-jump-name { max-width: 42vw; }
}

.series-member-snackbar {
  position: fixed; bottom: max(18px, var(--safe-bottom)); left: 50%; transform: translateX(-50%);
  z-index: 1030;
  display: flex; align-items: center; gap: 10px;
  padding: 9px 12px 9px 16px;
  background: color-mix(in srgb, var(--series-snackbar-bg) 92%, transparent); color: var(--on-image);
  border: 1px solid color-mix(in srgb, var(--on-image) 18%, transparent); border-radius: 999px;
  box-shadow: 0 12px 32px color-mix(in srgb, var(--shadow-ink) 35%, transparent);
  backdrop-filter: blur(8px);
  max-width: calc(100vw - 24px);
}
.series-member-snackbar__count {
  display: inline-grid; place-items: center;
  min-width: 20px; height: 20px; padding: 0 6px;
  border-radius: 999px; background: color-mix(in srgb, var(--on-image) 18%, transparent);
  font-size: 11px; font-weight: 800;
}
.series-member-snackbar__label { font-size: 12.5px; font-weight: 600; white-space: nowrap; }
.series-member-snackbar__save,
.series-member-snackbar__discard {
  border-radius: 999px; font-size: 11.5px; font-weight: 700;
  padding: 5px 14px; border: 0;
  transition: background .15s ease, border-color .15s ease, opacity .15s ease;
}
.series-member-snackbar__save { background: var(--series-gold); color: var(--series-gold-ink); }
.series-member-snackbar__save:not(:disabled):hover,
.series-member-snackbar__save:not(:disabled):focus-visible { background: var(--series-gold-hover); }
.series-member-snackbar__discard {
  background: transparent; color: color-mix(in srgb, var(--on-image) 85%, transparent);
  border: 1px solid color-mix(in srgb, var(--on-image) 35%, transparent);
}
.series-member-snackbar__discard:not(:disabled):hover,
.series-member-snackbar__discard:not(:disabled):focus-visible {
  background: color-mix(in srgb, var(--on-image) 14%, transparent); color: var(--on-image);
}
.series-member-snackbar__save:disabled,
.series-member-snackbar__discard:disabled { opacity: .55; cursor: not-allowed; }
.series-member-strip {
  position: absolute; top: 0; left: 0; right: 0; z-index: 3;
  display: flex; align-items: center; justify-content: center; gap: 4px;
  padding: 3px 6px; font-size: 10px; font-weight: 800; letter-spacing: .06em;
  line-height: 1.2; text-transform: uppercase;
  box-shadow: 0 2px 8px color-mix(in srgb, var(--shadow-ink) 28%, transparent);
}
.series-member-strip::before { font-weight: 800; }
.series-member-strip[data-marker-state="pinned"]   { background: color-mix(in srgb, var(--series-gold) 92%, transparent); color: var(--series-gold-ink); }
.series-member-strip[data-marker-state="pinned"]::before   { content: "★"; }
.series-member-strip[data-marker-state="added"]    { background: color-mix(in srgb, var(--series-success) 92%, transparent); color: var(--series-success-ink); }
.series-member-strip[data-marker-state="added"]::before    { content: "+"; }
.series-member-strip[data-marker-state="removed"]  { background: color-mix(in srgb, var(--series-danger) 92%, transparent); color: var(--on-image); }
.series-member-strip[data-marker-state="removed"]::before  { content: "−"; }
.series-member-strip[data-marker-state="unpinned"] { background: color-mix(in srgb, var(--series-neutral) 90%, transparent); color: var(--on-image); }
.comic-card-cover.series-member-removed img,
.comic-card-cover.series-member-removed .comic-card-noimg { filter: grayscale(.75) brightness(.72); }
/* While a strip shows, nudge top-anchored cover badges below it (bottom-anchored
   badges — reconciled/secondary — are unaffected). Base rules stay in styles.css.
   Left-anchored: the member controls (top: 32px, right-anchored) occupy the
   right edge in edit mode, so a right-anchored badge at top: 26px would sit
   underneath them. */
.comic-card-cover.has-member-marker .comic-card-owned-badge {
  top: 26px; right: auto; left: 6px;
}
.series-member-controls {
  position: absolute; right: 8px; top: 32px; z-index: 4;
  display: inline-flex; gap: 6px;
}
.series-member-control {
  width: 34px; height: 34px; display: inline-grid; place-items: center;
  border: 1px solid color-mix(in srgb, var(--on-image) 34%, transparent); border-radius: 999px;
  background: color-mix(in srgb, var(--series-control-bg) 62%, transparent); color: var(--on-image);
  box-shadow: 0 8px 20px color-mix(in srgb, var(--shadow-ink) 25%, transparent);
  backdrop-filter: blur(6px);
  transition: background .15s ease, border-color .15s ease, transform .15s ease;
}
.series-member-control:hover,
.series-member-control:focus-visible {
  background: color-mix(in srgb, var(--series-control-bg) 85%, transparent); border-color: color-mix(in srgb, var(--on-image) 70%, transparent);
  color: var(--on-image); transform: translateY(-1px);
}

/* ── Curated-set badge (inside the dark banner) ────────────────────────── */
.badge.bg-accent-canonical {
  background-color: var(--accent-canonical) !important;
  color: var(--on-image);
}
.series-hub-complete-badge {
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border-strong);
}
.series-hub-curated-badge,
.series-hub-complete-badge {
  display: inline-block; margin-bottom: 6px;
  font-size: 10px; letter-spacing: .09em; text-transform: uppercase;
  border-radius: 4px; padding: 3px 8px; font-weight: 700;
}

/* ── Pinned / featured covers strip (below the facts bar) ──────────────── */
.series-featured {
  margin: 0 0 20px;
}
.series-featured__label {
  font-size: 10px; text-transform: uppercase; letter-spacing: .08em;
  font-weight: 700; color: var(--series-text-faint); margin-bottom: 10px;
}
.series-featured__row {
  display: flex; flex-wrap: wrap; gap: 10px;
}
.series-featured__cover img {
  width: 80px; height: 120px; object-fit: cover;
  border-radius: 6px; box-shadow: 0 4px 12px color-mix(in srgb, var(--shadow-ink) 18%, transparent);
  display: block; transition: transform .15s ease;
}
.series-featured__cover:hover img {
  transform: translateY(-3px);
}

.series-hub-link {
  color: var(--on-image); font-weight: 700; text-decoration-color: color-mix(in srgb, var(--on-image) 42%, transparent);
}
.series-hub-link:hover,
.series-hub-link:focus-visible {
  color: var(--on-image); text-decoration-color: var(--on-image);
}

.publisher-imprint-toggles {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  margin: 0 0 20px; padding: 2px 0;
}
.publisher-imprint-toggle {
  display: inline-flex; align-items: center; gap: 7px;
  min-height: 34px; border: 1px solid var(--border);
  border-radius: 8px; padding: 5px 10px;
  background: var(--surface);
  color: var(--text); font-size: 12.5px; font-weight: 700;
  cursor: pointer; text-decoration: none;
  transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease;
}
.publisher-imprint-toggle input {
  width: 14px; height: 14px; margin: 0; accent-color: var(--series-publisher-control);
}
.publisher-imprint-toggle:hover,
.publisher-imprint-toggle:focus-visible,
.publisher-imprint-toggle:focus-within,
.publisher-imprint-toggle.is-active {
  border-color: var(--series-publisher-control-border);
  box-shadow: 0 6px 16px color-mix(in srgb, var(--shadow-ink) 8%, transparent);
  color: var(--text);
  transform: translateY(-1px);
}
.publisher-imprint-canonical {
  margin-right: 10px; font-size: 12px; font-weight: 700;
  color: var(--text-muted);
}
.publisher-imprint-submit {
  min-height: 34px;
}

@media (max-width: 640px) {
  /* GH-113. The stacked, centred banner spent 1.75 phone screens before the
     first edition -- on a page whose whole purpose is the editions list.
     Float rather than flex-column: the title, byline and stats wrap BESIDE the
     cover, and the synopsis and pills then reclaim the full banner width once
     they clear it. A flex row would trap both in a ~190px column instead,
     which wrapped the pills from one row to four. */
  .series-hub-row { display: block; text-align: left; }
  .series-hub-row::after { content: ""; display: block; clear: both; }
  .series-hub-cover {
    float: left; width: 104px; height: 156px; margin: 0 14px 10px 0;
  }
  .series-hub-banner { padding: 20px 18px 18px; }
  /* Mobile audit 2026-09-22: 4 lines of synopsis is 133px, the single largest
     block in the banner, and it sits between the reader and the editions list
     the page exists for. Two lines still carry the "what is this run" answer;
     the rest is one tap away on the disclosure GH-113 already built. Measured:
     -66px. */
  .series-hub-desc {
    text-align: left;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
  }
  /* Undoing every part of the clamp, or "More" expands nothing. */
  .series-hub-desc.is-expanded {
    display: block;
    -webkit-line-clamp: none;
    line-clamp: none;
    overflow: visible;
  }
  .series-hub-desc-toggle { display: inline-flex; }
  /* GH-535. Compact copy must not create compact hit areas: both signed-out
     account actions keep the site's 44px phone target without restoring the
     old boxed recommendation widget. */
  .series-hub-subscribe-signin .btn,
  .series-hub-subscribe .btn,
  .series-hub-recommendations .series-hub-recommend,
  .series-hub-recommend-signin,
  .series-hub-manage {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }
  /* Beside the 104px floated cover a phone has ~212px for the row. The widest
     pair is the subscribed + recommended one, Unsubscribe + Recommended, which
     fits one line at 13px with 10px side padding (measured 92 + 110 + 8); the
     two signed-out prompts need 337px and still wrap. The row gap is
     tightened so a wrap costs the 44px target and no more. */
  .series-hub-actions { row-gap: 0; column-gap: 8px; margin-top: 10px; }
  .series-hub-subscribe .btn,
  .series-hub-recommendations .series-hub-recommend {
    padding-inline: 10px;
    font-size: 13px;
    white-space: nowrap;
  }
  .series-hub-actions-note { padding-block: 6px 2px; }
  /* The facts row repeats what the banner already states (creators, years) and
     is secondary to the list. Switch DOM copies at the breakpoint so keyboard
     focus and screen-reader order match the visual order on both layouts. */
  .series-hub-facts--before-editions { display: none; }
  .series-hub-facts--after-editions { display: flex; }
  .series-edit-panel { text-align: left; }
  .series-edit-toggle { top: 12px; right: 12px; }
}

/* GH-115. The format pills are the series page's format navigation, and at
   25px they were the smallest real navigation on the site. Same treatment as
   the issues chips: the pill keeps its size, a transparent ::after carries the
   44px target, and the row's own margin (6px) plus the added row-gap keeps
   neighbouring areas from crossing. */
@media (max-width: 640px) {
  /* 19px, not 18: the pill is 25px tall, so 18 gives a 43px pitch and the
     expanded areas overlap by 1px -- measured, the pills came back at 43. The
     gap has to be 44 minus the pill's own height. */
  .series-hub-pills { display: flex; flex-wrap: wrap; row-gap: 19px; }
  .series-hub-pill { position: relative; margin: 0 6px 0 0; }
  .series-hub-pill::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    height: 44px;
    transform: translateY(-50%);
  }
}

/* GH-232. The server-rendered edition list: the page's only /edition/ links
   for a crawler that does not run scripts, and the whole of the page for a
   reader with JavaScript off or a failed data call. Styled plainly on purpose
   -- it is a readable index, not a second grid, and a reader who reaches it
   has no working grid to match. */
.series-hub-fallback {
  margin: 24px 0 8px;
}
.series-hub-fallback__title {
  font-size: 1.25rem;
  margin: 0 0 12px;
  color: var(--text);
}
.series-hub-fallback__list {
  margin: 0;
  padding-left: 1.5em;
  color: var(--text);
}
.series-hub-fallback__row {
  margin-bottom: 6px;
  line-height: 1.5;
}
.series-hub-fallback__link {
  color: var(--text);
}
.series-hub-fallback__meta {
  color: var(--text-muted);
  font-size: 0.875rem;
  margin-left: 6px;
}
.series-hub-fallback__more {
  margin: 12px 0 0;
  color: var(--text-muted);
}


/* --- "Buy the whole run" (series_price_total.js) ---------------------------
   The run price closes the banner rather than standing as a card of its own
   between the banner and the grid: it is a fact about the series, like the
   years and the edition count above it, so it wears the banner's ink. One
   hairline separates it from the identity above; the total, its qualifiers and
   a "Per store" toggle read as one line. The retailer chips -- the breakdown
   of that total, and the controls that leave a store out -- fold behind the
   toggle at every width. The headline never folds: price, edition count,
   shipping and the list comparison are the facts a collector decides on, and
   DESIGN.md forbids a layout hiding those. An ignored chip is struck through
   and dimmed rather than removed, so it can be pressed back on.

   The ground is the banner's shade over cover art in BOTH themes, so every ink
   here is --on-image, never the page's themed --text ramp. */
.series-price-total {
  margin: 16px 0 0; padding: 12px 0 0;
  border-top: 1px solid color-mix(in srgb, var(--on-image) 24%, transparent);
  color: var(--on-image);
  display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 14px;
}
.series-price-total__runs { flex: 1 1 auto; min-width: 0; }
.has-multiple-runs .series-price-total__runs { flex-basis: 100%; }
.has-multiple-runs .series-price-total__run:first-of-type { margin-top: 6px; }
/* The three folds (summary, comparison, stores) animate through theme.css's
   cc-motion-collapse; its inner clips, so give focus rings room to show. */
.series-price-total .cc-motion-collapse-inner { overflow: clip; overflow-clip-margin: 4px; }
/* Several edition types, folded: "Compendium $9.98   Hardcover $68.98 ..." */
.series-price-total__summary-fold { flex: 1 1 auto; min-width: 0; }
.series-price-total__summary {
  margin: 0;
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 16px;
  font-size: 12.5px; color: color-mix(in srgb, var(--on-image) 82%, transparent);
}
.series-price-total__summary strong {
  font-size: 15px; font-weight: 700; color: var(--on-image); font-variant-numeric: tabular-nums;
}
.series-price-total__headline {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 14px;
}
.series-price-total__run + .series-price-total__run {
  border-top: 1px solid color-mix(in srgb, var(--on-image) 16%, transparent);
}
.series-price-total__format {
  margin: 0; min-width: 130px; font-size: 12.5px; font-weight: 700; color: var(--on-image);
}
.series-price-total__title {
  margin: 0; font-size: 10.5px; text-transform: uppercase; letter-spacing: .08em;
  font-weight: 700; color: color-mix(in srgb, var(--on-image) 72%, transparent);
}
.series-price-total__scope { flex-basis: 100%; margin: 6px 0; font-size: 12px; }
/* The chooser: one summary line that reads as a control ("Editions · 5 of 5
   selected · Edit"), and a compact list -- checkbox, title, the edition's own
   best price, a Details link -- on a single row per book. */
.series-price-total__selection {
  margin: 8px 0; font-size: 12.5px; color: var(--on-image);
  border: 1px solid color-mix(in srgb, var(--on-image) 22%, transparent);
  border-radius: 8px; background: color-mix(in srgb, var(--on-image) 6%, transparent);
}
.series-price-total__selection summary {
  display: flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 12px;
  list-style: none; cursor: pointer; border-radius: 8px;
}
.series-price-total__selection summary::-webkit-details-marker { display: none; }
.series-price-total__selection summary:hover { background: color-mix(in srgb, var(--on-image) 8%, transparent); }
.series-price-total__selection-label { font-weight: 700; }
.series-price-total__selection-count { color: color-mix(in srgb, var(--on-image) 80%, transparent); font-variant-numeric: tabular-nums; }
.series-price-total__selection-edit {
  display: inline-flex; align-items: center; gap: 4px; margin-left: auto; font-weight: 700;
}
.series-price-total__selection-edit .bi { font-size: 11px; transition: transform var(--motion-med, .2s) ease; }
.series-price-total__selection[open] .series-price-total__selection-edit .bi { transform: rotate(180deg); }
.series-price-total__selection-edit-open,
.series-price-total__selection[open] .series-price-total__selection-edit-closed { display: none; }
.series-price-total__selection[open] .series-price-total__selection-edit-open { display: inline; }
.series-price-total__selection-body { padding: 8px 12px; }
.series-price-total__selection-body > .series-price-total__hint { margin: 0; }
.series-price-total__selection-actions { display: flex; flex-wrap: wrap; gap: 4px 16px; margin: 2px 0 4px; }
.series-price-total__select {
  min-height: 36px; padding: 0; border: 0; background: none; color: var(--on-image); font: inherit;
  font-weight: 700; text-decoration: underline; text-underline-offset: 2px; cursor: pointer;
}
.series-price-total__choices { list-style: none; padding: 0; margin: 0; max-height: 420px; overflow-y: auto; }
.series-price-total__choice-row {
  display: flex; align-items: center; gap: 12px;
  border-top: 1px solid color-mix(in srgb, var(--on-image) 14%, transparent);
}
.series-price-total__choice {
  display: flex; flex: 1 1 auto; align-items: center; gap: 10px; min-width: 0; min-height: 44px;
  padding: 4px 0; cursor: pointer;
}
.series-price-total__choice input { flex: 0 0 auto; width: 18px; height: 18px; accent-color: var(--on-image); }
.series-price-total__choice-text { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.series-price-total__choice-row:not(.is-selected) .series-price-total__choice-title { color: color-mix(in srgb, var(--on-image) 80%, transparent); }
.series-price-total__choice small { display: block; opacity: .8; font-size: 11.5px; }
.series-price-total__choice-price {
  flex: 0 0 auto; font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap;
}
.series-price-total__choice-price.is-unavailable { font-weight: 400; color: color-mix(in srgb, var(--on-image) 72%, transparent); }
.series-price-total__edition-link {
  flex: 0 0 auto; display: inline-flex; align-items: center; min-height: 44px; color: inherit; font-size: 11.5px;
}
.series-price-total__selection summary:focus-visible,
.series-price-total__choice input:focus-visible,
.series-price-total__edition-link:focus-visible,
.series-price-total__select:focus-visible { outline: 2px solid var(--on-image); outline-offset: 2px; }
/* Folds with the chips beneath the price line, so opening the stores never
   pushes "Hide stores" off the price line onto a row of its own. */
.series-price-total__hint {
  margin: 4px 0 0; font-size: 11.5px; color: color-mix(in srgb, var(--on-image) 72%, transparent);
}
.series-price-total__figure {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 10px; margin: 0;
  font-size: 12.5px; color: color-mix(in srgb, var(--on-image) 82%, transparent);
}
.series-price-total__details {
  display: contents;
}
.series-price-total__amount {
  font-size: 19px; font-weight: 700; color: var(--on-image);
  letter-spacing: -.01em; font-variant-numeric: tabular-nums;
}
.series-price-total__list { color: color-mix(in srgb, var(--on-image) 72%, transparent); }
.series-price-total__chips {
  display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0 0; padding: 0; list-style: none;
}
.series-price-total__chip-item { display: contents; }
.series-price-total__chip,
.series-price-total__reset {
  display: inline-flex; align-items: baseline; gap: 6px;
  padding: 4px 11px; border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--on-image) 30%, transparent);
  background: color-mix(in srgb, var(--on-image) 14%, transparent);
  font: inherit; font-size: 11.5px; line-height: 1.3; color: var(--on-image);
  cursor: pointer; text-align: left;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}
.series-price-total__chip:hover,
.series-price-total__reset:hover {
  border-color: color-mix(in srgb, var(--on-image) 60%, transparent);
  background: color-mix(in srgb, var(--on-image) 22%, transparent);
}
.series-price-total__chip:focus-visible,
.series-price-total__reset:focus-visible,
.series-price-total__outlier-toggle:focus-visible,
.series-price-total__versus-clear:focus-visible,
.series-price-total__disclosure:focus-visible,
.series-price-total__compare:focus-visible {
  outline: 2px solid var(--on-image); outline-offset: 2px;
}
.series-price-total__chip-label { font-weight: 600; }
.series-price-total__chip-summary { color: color-mix(in srgb, var(--on-image) 80%, transparent); }
.series-price-total__chip.is-ignored {
  background: transparent; color: color-mix(in srgb, var(--on-image) 72%, transparent);
}
.series-price-total__chip.is-ignored .series-price-total__chip-label { text-decoration: line-through; }
.series-price-total__reset {
  color: color-mix(in srgb, var(--on-image) 80%, transparent);
  background: transparent; border-style: dashed;
}
.series-price-total__disclosure,
.series-price-total__compare {
  display: inline-flex; align-items: center; justify-content: flex-end;
  min-height: 32px; min-width: 44px; margin-left: auto; padding: 0; border: 0;
  background: none; color: var(--on-image); font: inherit;
  font-size: 12px; font-weight: 700; text-decoration: underline;
  text-underline-offset: 2px; cursor: pointer;
}
/* "2 marked-up books in this total · Leave them out": a standing switch under
   the headline, never inside it (the multi-run headline is a fixed grid). */
.series-price-total__outliers,
.series-price-total__versus {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 10px;
  margin: 2px 0 4px; font-size: 12px;
  color: color-mix(in srgb, var(--on-image) 82%, transparent);
}
.series-price-total__outlier-toggle,
.series-price-total__versus-clear {
  padding: 0; border: 0; background: none; color: var(--on-image); font: inherit;
  font-weight: 700; text-decoration: underline; text-underline-offset: 2px; cursor: pointer;
}
/* ?compare=<retailer>: one store's basket against the rest, under the headline. */
.series-price-total__versus { flex-direction: column; align-items: flex-start; gap: 0; }
.series-price-total__versus p { margin: 0; }
.series-price-total__versus-verdict { color: var(--on-image); font-weight: 700; }
/* The followed "Buy the run" link's banner: names the store and the next
   step for as long as the comparison is on, so the landing is never silent. */
.series-price-total__landing {
  flex: 1 1 100%; margin: 0 0 10px; padding: 10px 12px;
  border: 1px solid color-mix(in srgb, var(--on-image) 40%, transparent);
  border-left-width: 4px; border-radius: 8px;
  background: color-mix(in srgb, var(--on-image) 10%, transparent);
}
.series-price-total__landing:focus { outline: none; }
.series-price-total__landing:focus-visible { outline: 2px solid var(--on-image); outline-offset: 2px; }
.series-price-total__landing p { margin: 0; }
.series-price-total__landing-title { font-size: 14px; }
.series-price-total__landing-title .bi { margin-right: 4px; }
.series-price-total__landing-text { margin-top: 2px !important; font-size: 12.5px; color: color-mix(in srgb, var(--on-image) 85%, transparent); }
.series-price-total__landing-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 16px; margin-top: 8px; }
.series-price-total__landing-select {
  min-height: 36px; padding: 6px 12px; border: 0; border-radius: 6px; cursor: pointer;
  background: var(--on-image); color: color-mix(in srgb, var(--on-image) 7%, var(--shadow-ink)); font: inherit; font-weight: 700;
}
.series-price-total__landing-select:focus-visible { outline: 2px solid var(--on-image); outline-offset: 2px; }
.series-price-total__choice small.series-price-total__choice-focus { opacity: 1; font-weight: 700; }
.series-price-total.is-compare-landing .series-price-total__landing { animation: series-compare-landing 0.8s ease-out 3; }
@keyframes series-compare-landing {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--on-image) 70%, transparent); }
  100% { box-shadow: 0 0 0 10px transparent; }
}
@media (prefers-reduced-motion: reduce) {
  .series-price-total.is-compare-landing .series-price-total__landing {
    animation: none; box-shadow: 0 0 0 3px var(--on-image);
  }
}
/* GH-1025: the estimate confirms an edit. A figure that changed under the
   reader drops in from just above (seriesPriceTick adds .is-ticking, never on
   load), and a ticked edition's box pops. Both stay within --motion-med so a
   run of quick edits never queues up motion. inline-block: a transform has
   no effect on an inline box. */
.series-price-total__tick { display: inline-block; }
.series-price-total__tick.is-ticking {
  animation: series-price-tick var(--motion-med) var(--ease-enter);
}
@keyframes series-price-tick {
  from { opacity: .3; transform: translateY(calc(var(--motion-rise-distance) * -.4)); }
  to { opacity: 1; transform: none; }
}
.series-price-total__choice input.is-popping {
  animation: series-price-choice-pop var(--motion-med) var(--ease-standard);
}
@keyframes series-price-choice-pop {
  0%, 100% { transform: scale(1); }
  45% { transform: scale(1.2); }
}
@media (prefers-reduced-motion: reduce) {
  .series-price-total__tick.is-ticking,
  .series-price-total__choice input.is-popping { animation: none; }
}
/* The receipt and the "Edit" chooser open with motion a reader can see.
   Both already grew (the shared cc-motion-collapse and ::details-content
   rules), but on the front-loaded --ease-standard a 1,500px receipt reaches
   80% of its height in the first quarter of --motion-slow, and the reader
   only ever sees the top ~300px of it: measured on the live page, the visible
   slice filled in about two frames, which reads as a snap. So these two
   folds take a symmetric curve, spreading the growth over the whole
   duration, and their contents unfold row by row (opacity and a short drop,
   stepped 40ms apart), so the motion happens where the reader is looking
   whatever the panel's height. Fill is `backwards`: nothing keeps a
   transform afterwards. The chooser's curve names the strip's class too, to
   outrank theme.css's `details:not(...)::details-content` at (0,1,2). */
.series-price-total__stores.cc-motion-collapse,
.series-price-total details.series-price-total__selection::details-content {
  transition-timing-function: cubic-bezier(.45, 0, .2, 1);
}
.series-price-total__stores.is-open > .cc-motion-collapse-inner > :is(.series-price-total__hint, .series-price-total__chips),
.series-price-total__stores.is-open .series-receipt > *,
.series-price-total__selection[open] :is(.series-price-total__selection-actions, .series-price-total__choice-row) {
  animation: series-fold-row-in var(--motion-slow) var(--ease-enter) backwards;
  animation-delay: calc(var(--series-fold-step, 0) * 40ms);
}
.series-price-total__stores.is-open .series-price-total__chips,
.series-price-total__selection[open] .series-price-total__choice-row:nth-child(1) { --series-fold-step: 1; }
.series-price-total__stores.is-open .series-receipt > :nth-child(1),
.series-price-total__selection[open] .series-price-total__choice-row:nth-child(2) { --series-fold-step: 2; }
.series-price-total__stores.is-open .series-receipt > :nth-child(-n+3):not(:nth-child(1)),
.series-price-total__selection[open] .series-price-total__choice-row:nth-child(3) { --series-fold-step: 3; }
.series-price-total__stores.is-open .series-receipt > :nth-child(4),
.series-price-total__selection[open] .series-price-total__choice-row:nth-child(4) { --series-fold-step: 4; }
.series-price-total__stores.is-open .series-receipt > :nth-child(5),
.series-price-total__selection[open] .series-price-total__choice-row:nth-child(5) { --series-fold-step: 5; }
.series-price-total__stores.is-open .series-receipt > :nth-child(n+6),
.series-price-total__selection[open] .series-price-total__choice-row:nth-child(n+6) { --series-fold-step: 6; }
@keyframes series-fold-row-in {
  from { opacity: 0; transform: translateY(calc(var(--motion-rise-distance) * -.8)); }
}
@media (prefers-reduced-motion: reduce) {
  .series-price-total__stores.is-open > .cc-motion-collapse-inner > :is(.series-price-total__hint, .series-price-total__chips),
  .series-price-total__stores.is-open .series-receipt > *,
  .series-price-total__selection[open] :is(.series-price-total__selection-actions, .series-price-total__choice-row) {
    animation: none;
  }
}
/* Several edition types: aligned comparison rows, one per type. */
.has-multiple-runs .series-price-total__title { margin-bottom: 2px; }
.has-multiple-runs .series-price-total__headline {
  display: grid;
  grid-template-columns: minmax(110px, 160px) minmax(90px, max-content) minmax(0, 1fr) 90px;
  align-items: center; gap: 0 16px; padding: 2px 0;
}
.has-multiple-runs .series-price-total__format {
  grid-column: 1; grid-row: 1; min-width: 0; overflow-wrap: anywhere;
}
.has-multiple-runs .series-price-total__figure:not(.series-price-total__empty) { display: contents; }
.has-multiple-runs .series-price-total__amount {
  grid-column: 2; grid-row: 1; text-align: right; font-size: 17px;
}
.has-multiple-runs .series-price-total__details {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 10px;
  grid-column: 3; grid-row: 1; min-width: 0;
  font-size: 12px; color: color-mix(in srgb, var(--on-image) 82%, transparent);
  font-variant-numeric: tabular-nums;
}
.has-multiple-runs .series-price-total__disclosure { grid-column: 4; grid-row: 1; }
.has-multiple-runs .series-price-total__hint { margin: 0 0 4px; }
.has-multiple-runs .series-price-total__chips { margin: 0; padding-bottom: 10px; }
.has-multiple-runs .series-price-total__empty { grid-column: 2 / 4; grid-row: 1; }
.has-multiple-runs .series-price-total__empty .series-price-total__amount {
  font-size: 12.5px; text-align: left;
}
@media (max-width: 640px) {
  .series-price-total { padding-top: 10px; }
  .series-price-total__amount { font-size: 18px; }

  /* Mobile audit 2026-09-22 measured the old card at 201px on a 390px phone,
     97px with the chips folded. In the banner it is one hairline, a title row
     and the headline. Only the per-store BREAKDOWN of the total the headline
     states is behind the toggle; the headline itself has no collapse hook. */
  .series-price-total:not(.has-multiple-runs) { display: block; }
  /* Several types: Compare sits in the title row, the totals wrap beneath. */
  .series-price-total__compare { order: 1; min-height: 44px; margin-left: auto; }
  .series-price-total__summary-fold { order: 2; flex-basis: 100%; }
  .series-price-total__runs { order: 3; }

  /* Each edition type has its own headline and retailer disclosure. Keep the
     format beside its toggle, with the price facts on the next line. */
  .series-price-total__headline { align-items: center; }
  .series-price-total__format { order: 0; }
  .series-price-total__figure { order: 2; flex: 1 0 100%; }

  .series-price-total__disclosure {
    order: 1;
    display: inline-flex;
    min-height: 44px;
    margin-left: auto;
  }

  /* Keep the receipt control in flow below the selection's price facts. */
  .series-price-total__headline.is-single-run .series-price-total__disclosure {
    position: static;
    order: 3;
  }

  .has-multiple-runs .series-price-total__headline {
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 0 12px; padding: 8px 0 2px;
  }
  .has-multiple-runs .series-price-total__details { grid-column: 1; grid-row: 2; }
  .has-multiple-runs .series-price-total__disclosure { grid-column: 2; grid-row: 2; }
  .has-multiple-runs .series-price-total__hint { margin-top: 8px; }
  .has-multiple-runs .series-price-total__empty { grid-column: 1; grid-row: 2; }

  /* A REAL 44px box, not GH-115's transparent ::after: GH-529 established that
     a hit area carried by a pseudo-element is invisible to the probe that
     judges this floor (scripts/mobile_audit_probe.py reads the button's own
     getBoundingClientRect). Free here -- these chips only render once the
     reader has opened the disclosure, so the added height never lands on the
     first screen. */
  .series-price-total__outlier-toggle,
  .series-price-total__versus-clear,
  .series-price-total__select {
    display: inline-flex; align-items: center; min-height: 44px;
  }
  .series-price-total__chips { gap: 8px; }
  .series-price-total__chip,
  .series-price-total__reset {
    min-height: 44px;
    align-items: center;
    padding: 4px 14px;
  }
}

/* Itemized purchase plan: ordinary surface tokens keep long receipts legible
   within the image-backed banner in both themes. */
.series-receipt {
  margin: 16px 0; padding: 20px; max-width: 56rem;
  background: var(--surface); color: var(--text); border-radius: 10px;
  font-size: 14px; line-height: 1.5;
}
.series-receipt h4 { margin: 0 0 4px; font: inherit; font-size: 18px; font-weight: 700; }
.series-receipt h5 { margin: 0 0 12px; font: inherit; font-size: 16px; font-weight: 700; }
.series-receipt__note, .series-receipt small { color: var(--text-muted); }
.series-receipt__note { margin: 0; max-width: 65ch; }
.series-receipt small { display: block; font-size: 12px; }
.series-receipt__store, .series-receipt__missing {
  margin-top: 24px; padding-top: 20px; border-top: 1px solid var(--border);
}
.series-receipt__items { list-style: none; margin: 0; padding: 0; }
.series-receipt__items li + li { margin-top: 12px; }
.series-receipt__line { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 16px; }
.series-receipt__line > div { min-width: 0; overflow-wrap: anywhere; }
.series-receipt a { color: var(--text); text-decoration: underline; text-underline-offset: 3px; }
.series-receipt a:hover { color: var(--brand); }
.series-receipt a:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; }
.series-receipt__money, .series-receipt dd { font-variant-numeric: tabular-nums; text-align: right; }
.series-receipt__totals { margin: 16px 0 0; }
.series-receipt__totals > div { display: flex; justify-content: space-between; gap: 16px; margin-top: 4px; }
.series-receipt dt { font-weight: 400; }
.series-receipt dd { margin: 0; }
.series-receipt__store-total dt, .series-receipt__store-total dd { font-weight: 700; }
.series-receipt__grand { margin-top: 24px; padding-top: 16px; border-top: 1px solid var(--border-strong); }
@media (max-width: 640px) {
  .series-receipt { padding: 16px; }
  .series-receipt__line { gap: 12px; }
}
