/* ============================================================================
   comics.css — the library on comics.html and the three shelves.

   Linked only by the comics pages, after site.css and mobile.css. Everything
   here is scoped under .clib or a cx- prefix, so it cannot reach the rest of
   the site.

   Shape: a billboard at the top, a row of browse-by modes under it, then
   horizontal shelves. Picking a mode re-shelves the whole library — Series
   gives one shelf per series, Character one per character, and so on. That is
   the "categories" mechanic, and it is one click rather than a new page.

   Shelves scroll by drag, wheel and keyboard, with a fade at each end and the
   next cover deliberately half-visible. No arrow buttons: this site does not
   put arrows on things you press.
   ========================================================================== */

.clib { position:relative; z-index:1; max-width:1500px; margin:0 auto; padding:0 clamp(1rem,3.5vw,2.6rem) 5rem; }

/* ── the notice that the shelves are seeded ─────────────────────────────── */
.clib-note {
  display:flex; align-items:flex-start; gap:.7rem; max-width:820px; margin:0 0 1.5rem;
  border-left:2px solid rgba(224,187,82,.45); padding:.55rem 0 .55rem .9rem;
  font-size:.95rem; line-height:1.6; color:rgba(241,236,224,.62);
}
.clib-note b { color:var(--gold-lt); font-weight:600; }

/* ── billboard ──────────────────────────────────────────────────────────────
   Same two-card idea as the store: the newest book on the left at scale, and
   the coming-soon frame on the right. One fixed row height so the row does not
   resize as covers of different shapes land in it. */
/* One fixed row height, the same reasoning as the store's billboard: without
   it the right-hand card's image has nothing to size against, grows to the
   art's natural height, and drags the whole row down with it. */
.cbb { display:grid; grid-template-columns:minmax(0,1.55fr) minmax(0,1fr); grid-template-rows:430px;
  grid-auto-rows:0; gap:1.1rem; align-items:stretch; margin:0 0 2.6rem; }
.cbb-main, .cbb-soon { height:430px; }
.cbb-main {
  position:relative; overflow:hidden; border-radius:16px; display:flex; align-items:flex-end;
  border:1px solid rgba(var(--cx-rgb,31,154,166), .42);
  background:linear-gradient(160deg, rgba(var(--cx-rgb,31,154,166), .16), rgba(11,13,17,.94));
  box-shadow:0 22px 60px rgba(0,0,0,.55);
}
.cbb-art { position:absolute; inset:0; }
.cbb-art img { width:100%; height:100%; object-fit:cover; object-position:var(--cx-focus,50% 18%); display:block; transform:scale(1.02); transition:transform 1.2s cubic-bezier(.22,1,.36,1); }
.cbb-main:hover .cbb-art img { transform:scale(1.06); }
/* the copy has to sit on artwork, so it gets its own floor rather than relying
   on the art being dark in the bottom third */
.cbb-scrim { position:absolute; inset:0; background:
  linear-gradient(90deg, rgba(8,9,12,.94) 0%, rgba(8,9,12,.82) 34%, rgba(8,9,12,.12) 68%, transparent 100%),
  linear-gradient(0deg, rgba(8,9,12,.92) 0%, transparent 46%); }
.cbb-body { position:relative; z-index:2; padding:2rem 2.2rem 2.1rem; max-width:640px; }
.cbb-kick { font-family:'Oswald',sans-serif; font-weight:600; font-size:.56rem; letter-spacing:.34em; text-transform:uppercase; color:var(--cx-c,var(--teal-lt)); }
.cbb-title { font-family:'Oswald',sans-serif; font-weight:700; font-size:clamp(1.9rem,4.4vw,3.1rem); line-height:1; letter-spacing:.02em; text-transform:uppercase; color:var(--paper); margin:.55rem 0 0; }
.cbb-meta { display:flex; flex-wrap:wrap; align-items:center; gap:.5rem; margin-top:.9rem; }
.cbb-copy { font-size:1.02rem; line-height:1.65; color:rgba(241,236,224,.76); margin:.9rem 0 1.3rem; max-width:520px; }
.cbb-acts { display:flex; flex-wrap:wrap; gap:.6rem; }

/* the coming-soon frame, straight off the store's */
.cbb-soon { position:relative; display:grid; grid-template-rows:minmax(0,1fr) auto; overflow:hidden; border-radius:16px;
  border:1px solid rgba(224,187,82,.4); background:linear-gradient(160deg, rgba(224,187,82,.10), rgba(11,13,17,.92)); }
.cbb-soon-img { position:relative; min-height:0; overflow:hidden; background:#0b0d11; }
.cbb-soon-img img { width:100%; height:100%; object-fit:cover; object-position:50% 16%; display:block; transition:transform .4s ease; }
.cbb-soon:hover .cbb-soon-img img { transform:scale(1.04); }
.cbb-soon-body { padding:1.2rem 1.35rem 1.45rem; display:flex; flex-direction:column; align-items:flex-start; }
.cbb-soon-tag { font-family:'Oswald',sans-serif; font-weight:700; font-size:.5rem; letter-spacing:.2em; text-transform:uppercase;
  color:var(--ink); background:linear-gradient(180deg,var(--gold-lt),var(--gold)); padding:.24rem .6rem; border-radius:100px; }
.cbb-soon-kick { font-family:'Oswald',sans-serif; font-weight:600; font-size:.54rem; letter-spacing:.3em; text-transform:uppercase; color:var(--teal-lt); margin-top:.7rem; }
.cbb-soon-name { font-family:'Oswald',sans-serif; font-weight:700; font-size:1.3rem; letter-spacing:.04em; text-transform:uppercase; color:var(--paper); margin-top:.35rem; line-height:1.05; }
.cbb-soon-copy { font-size:.95rem; line-height:1.6; color:rgba(241,236,224,.72); margin:.6rem 0 1.1rem; }
.cbb-soon .cx-btn { margin-top:auto; }
@media (max-width:1050px){ .cbb { grid-template-columns:1fr; grid-template-rows:auto; grid-auto-rows:auto; }
  .cbb-main, .cbb-soon { height:auto; } .cbb-main { min-height:340px; } .cbb-soon-img { height:230px; } }

/* ── buttons and pills ──────────────────────────────────────────────────── */
.cx-btn { display:inline-flex; align-items:center; gap:.5rem; font-family:'Oswald',sans-serif; font-weight:600; font-size:.7rem;
  letter-spacing:.2em; text-transform:uppercase; text-decoration:none; border-radius:100px; padding:.65rem 1.45rem; cursor:pointer;
  border:1px solid transparent; transition:filter .2s, transform .15s, background .25s, border-color .2s, color .2s; }
.cx-btn.solid { color:var(--ink); background:linear-gradient(100deg,#b88f37,#ddb64f 40%,#f5e089 54%,#ddb64f 68%,#b88f37); background-size:200% auto; box-shadow:0 2px 18px rgba(224,187,82,.32); }
.cx-btn.solid:hover { filter:brightness(1.06); transform:translateY(-2px); }
.cx-btn.ghost { color:var(--paper); background:rgba(11,13,17,.55); border-color:rgba(241,236,224,.28); }
.cx-btn.ghost:hover { color:var(--gold-lt); border-color:rgba(224,187,82,.55); background:rgba(224,187,82,.08); transform:translateY(-2px); }
.cx-btn[disabled], .cx-btn.is-off { opacity:.5; pointer-events:none; }

.cx-pill { font-family:'Oswald',sans-serif; font-weight:600; font-size:.52rem; letter-spacing:.18em; text-transform:uppercase;
  border-radius:100px; padding:.28rem .68rem; white-space:nowrap; }
.cx-pill.tier   { color:var(--ink); background:linear-gradient(180deg,var(--gold-lt),var(--gold)); }
.cx-pill.soon   { color:var(--teal-lt); border:1px solid rgba(63,198,210,.5); }
.cx-pill.holder { color:rgba(241,236,224,.6); border:1px solid rgba(241,236,224,.24); }
.cx-pill.lus    { color:var(--ink); background:var(--cx-c,var(--teal-lt)); }

/* ── browse-by bar ──────────────────────────────────────────────────────────
   The mechanic: these do not filter, they re-shelve. Pick Character and the
   whole library reorganises into one shelf per character. */
.cx-modes { display:flex; flex-wrap:wrap; align-items:center; gap:.5rem; margin:0 0 .5rem; }
.cx-modes-lab { font-family:'Oswald',sans-serif; font-weight:600; font-size:.54rem; letter-spacing:.3em; text-transform:uppercase; color:var(--muted); margin-right:.4rem; }
.cx-mode { font-family:'Oswald',sans-serif; font-weight:600; font-size:.66rem; letter-spacing:.18em; text-transform:uppercase;
  color:rgba(241,236,224,.74); background:rgba(255,255,255,.03); border:1px solid rgba(241,236,224,.16);
  border-radius:100px; padding:.5rem 1.1rem; cursor:pointer; transition:color .2s, border-color .2s, background .2s, transform .15s; }
.cx-mode:hover { color:var(--gold-lt); border-color:rgba(224,187,82,.45); transform:translateY(-1px); }
.cx-mode[aria-pressed="true"] { color:var(--ink); background:linear-gradient(100deg,#b88f37,#ddb64f 45%,#f5e089 56%,#ddb64f 70%,#b88f37); border-color:transparent; }
.cx-count { margin-left:auto; font-family:'Oswald',sans-serif; font-weight:500; font-size:.6rem; letter-spacing:.22em; text-transform:uppercase; color:var(--muted); }

/* ── shelves ────────────────────────────────────────────────────────────── */
.cx-shelf { margin:2.4rem 0 0; }
.cx-shelf-h { display:flex; align-items:baseline; gap:.8rem; margin:0 0 .85rem; }
.cx-shelf-t { font-family:'Oswald',sans-serif; font-weight:700; font-size:1.12rem; letter-spacing:.08em; text-transform:uppercase; color:var(--paper); }
.cx-shelf-t .dot { color:var(--cx-c,var(--gold)); }
.cx-shelf-s { font-size:.92rem; color:rgba(241,236,224,.5); }
.cx-shelf-n { margin-left:auto; font-family:'Oswald',sans-serif; font-size:.58rem; letter-spacing:.22em; text-transform:uppercase; color:var(--muted); }

/* the rail. overflow-x with the fades painted by the wrapper, so the fade does
   not scroll away with the contents */
.cx-rail-w { position:relative; }
.cx-rail-w::before, .cx-rail-w::after { content:''; position:absolute; top:0; bottom:14px; width:56px; pointer-events:none; z-index:2; opacity:0; transition:opacity .25s; }
.cx-rail-w::before { left:0;  background:linear-gradient(90deg, var(--ink) 8%, transparent); }
.cx-rail-w::after  { right:0; background:linear-gradient(270deg, var(--ink) 8%, transparent); }
.cx-rail-w.at-start::after, .cx-rail-w.mid::after { opacity:1; }
.cx-rail-w.mid::before, .cx-rail-w.at-end::before { opacity:1; }
.cx-rail { display:flex; gap:.9rem; overflow-x:auto; scroll-behavior:smooth; padding:.2rem .1rem 14px; scrollbar-width:none; -ms-overflow-style:none; cursor:grab; }
.cx-rail::-webkit-scrollbar { display:none; }
.cx-rail.dragging { cursor:grabbing; scroll-behavior:auto; }
.cx-rail.dragging .cx-card { pointer-events:none; }

/* ── a cover ────────────────────────────────────────────────────────────────
   No cover files exist yet, so the card composes one out of cast art: the art
   cover-fitted behind a floor gradient, the reading's canon colour as a top
   edge and a corner glow, and the title plate over it. A real `cover` in the
   data drops straight into the same frame and the composition falls away. */
.cx-card {
  --cx-rgb:31,154,166; --cx-c:var(--teal-lt);
  position:relative; flex:0 0 auto; width:210px; border:0; padding:0; text-align:left; cursor:pointer;
  background:none; font:inherit; color:inherit; transition:transform .28s cubic-bezier(.22,1,.36,1);
}
.cx-card:hover, .cx-card:focus-visible { transform:translateY(-6px); outline:none; }
.cx-cover {
  position:relative; aspect-ratio:2/3; width:100%; overflow:hidden; border-radius:11px; background:#06070a;
  border:1px solid rgba(var(--cx-rgb), .4); box-shadow:0 10px 26px rgba(0,0,0,.5);
  transition:border-color .25s, box-shadow .25s;
}
.cx-card:hover .cx-cover, .cx-card:focus-visible .cx-cover { border-color:rgba(var(--cx-rgb), .95); box-shadow:0 18px 40px rgba(0,0,0,.62), 0 0 34px rgba(var(--cx-rgb), .3); }
.cx-cover img { width:100%; height:100%; object-fit:cover; object-position:var(--cx-focus,50% 20%); display:block; transition:transform .5s cubic-bezier(.22,1,.36,1); }
.cx-card:hover .cx-cover img { transform:scale(1.07); }
/* the floor the title sits on, plus a wash of the reading's colour from the top */
.cx-cover::before { content:''; position:absolute; inset:0; z-index:1; pointer-events:none;
  background:linear-gradient(0deg, rgba(6,7,10,.96) 2%, rgba(6,7,10,.55) 26%, transparent 52%),
             linear-gradient(180deg, rgba(var(--cx-rgb), .3), transparent 34%); }
/* the reading's colour as a hairline along the top edge */
.cx-cover::after { content:''; position:absolute; left:0; right:0; top:0; height:3px; z-index:3; pointer-events:none;
  background:linear-gradient(90deg, transparent, rgb(var(--cx-rgb)) 22%, rgb(var(--cx-rgb)) 78%, transparent); }
.cx-plate { position:absolute; left:0; right:0; bottom:0; z-index:2; padding:.85rem .85rem .9rem; }
.cx-ser, .cx-name, .cx-no { display:block; }
.cx-ser { font-family:'Oswald',sans-serif; font-weight:600; font-size:.52rem; letter-spacing:.24em; text-transform:uppercase; color:var(--cx-c); }
.cx-name { font-family:'Oswald',sans-serif; font-weight:700; font-size:1.02rem; line-height:1.1; letter-spacing:.02em; text-transform:uppercase; color:var(--paper); margin-top:.2rem; }
.cx-no { font-family:'Oswald',sans-serif; font-weight:500; font-size:.58rem; letter-spacing:.18em; text-transform:uppercase; color:rgba(241,236,224,.55); margin-top:.28rem; }
.cx-flag { position:absolute; top:.55rem; left:.55rem; z-index:3; font-size:.45rem; letter-spacing:.14em; padding:.24rem .5rem; }
.cx-mark { position:absolute; top:.55rem; right:.55rem; z-index:3; font-family:'Oswald',sans-serif; font-weight:700; font-size:.44rem;
  letter-spacing:.16em; text-transform:uppercase; color:rgba(241,236,224,.7); background:rgba(6,7,10,.72);
  border:1px solid rgba(241,236,224,.2); border-radius:3px; padding:.16rem .34rem; }

/* the empty shelf, for a tier with nothing on it yet */
.cx-empty { border:1px dashed rgba(224,187,82,.3); border-radius:12px; padding:2.6rem 1.6rem; text-align:center;
  background:rgba(255,255,255,.015); }
.cx-empty h3 { font-family:'Oswald',sans-serif; font-weight:700; font-size:1.1rem; letter-spacing:.08em; text-transform:uppercase; color:var(--paper); }
.cx-empty p { font-size:1rem; line-height:1.65; color:rgba(241,236,224,.6); max-width:460px; margin:.6rem auto 0; }

/* ── detail panel ───────────────────────────────────────────────────────── */
.cx-modal { position:fixed; inset:0; z-index:1200; display:none; }
.cx-modal.on { display:block; }
.cx-modal-scrim { position:absolute; inset:0; background:rgba(4,5,7,.9); }
.cx-modal-box { position:relative; z-index:2; max-width:900px; margin:min(9vh,90px) auto 0; width:calc(100% - 2rem);
  max-height:82vh; overflow:auto; border-radius:16px; border:1px solid rgba(var(--cx-rgb,31,154,166), .5);
  background:linear-gradient(160deg, rgba(var(--cx-rgb,31,154,166), .12), rgba(11,13,17,.97));
  box-shadow:0 30px 80px rgba(0,0,0,.7); display:grid; grid-template-columns:280px minmax(0,1fr); gap:1.6rem; padding:1.6rem; }
@media (max-width:760px){ .cx-modal-box { grid-template-columns:1fr; } }
.cx-modal-cover { position:relative; aspect-ratio:2/3; overflow:hidden; border-radius:11px; border:1px solid rgba(var(--cx-rgb,31,154,166), .45); background:#06070a; }
.cx-modal-cover img { width:100%; height:100%; object-fit:cover; object-position:var(--cx-focus,50% 20%); }
.cx-modal-kick { font-family:'Oswald',sans-serif; font-weight:600; font-size:.54rem; letter-spacing:.3em; text-transform:uppercase; color:var(--cx-c,var(--teal-lt)); }
.cx-modal-t { font-family:'Oswald',sans-serif; font-weight:700; font-size:1.9rem; line-height:1.05; letter-spacing:.02em; text-transform:uppercase; color:var(--paper); margin:.4rem 0 0; }
.cx-modal-meta { display:flex; flex-wrap:wrap; gap:.45rem; margin-top:.85rem; }
.cx-modal-copy { font-size:1rem; line-height:1.7; color:rgba(241,236,224,.76); margin:1rem 0; }
.cx-modal-sub { font-family:'Oswald',sans-serif; font-weight:600; font-size:.52rem; letter-spacing:.26em; text-transform:uppercase; color:var(--muted); margin-top:1.1rem; }
.cx-cast { display:flex; flex-wrap:wrap; gap:.5rem; margin-top:.55rem; }
.cx-cast a { display:inline-flex; align-items:center; gap:.45rem; text-decoration:none; font-family:'Oswald',sans-serif; font-weight:600;
  font-size:.6rem; letter-spacing:.14em; text-transform:uppercase; color:var(--paper);
  border:1px solid rgba(241,236,224,.2); border-radius:100px; padding:.3rem .7rem .3rem .3rem; transition:border-color .2s, background .2s; }
.cx-cast a:hover { border-color:rgba(224,187,82,.55); background:rgba(224,187,82,.08); }
.cx-cast img { width:24px; height:24px; border-radius:50%; object-fit:cover; object-position:50% 18%; }
/* the cast chip wears that character's reading */
.cx-cast a .lus-dot { width:7px; height:7px; border-radius:50%; background:var(--dot,var(--teal-lt)); box-shadow:0 0 8px var(--dot,var(--teal-lt)); }
.cx-modal-acts { display:flex; flex-wrap:wrap; gap:.6rem; margin-top:1.4rem; }
.cx-close { position:absolute; top:.7rem; right:.8rem; z-index:4; width:38px; height:38px; border-radius:50%; cursor:pointer;
  border:1px solid rgba(241,236,224,.26); background:rgba(6,7,10,.7); color:var(--paper); font-size:1.3rem; line-height:1; }
.cx-close:hover { color:var(--gold-lt); border-color:rgba(224,187,82,.6); }

@media (prefers-reduced-motion: reduce) {
  .cx-card, .cx-cover img, .cbb-art img { transition:none !important; }
  .cx-rail { scroll-behavior:auto; }
}

/* the detail panel locks the page behind it */
body.cx-lock { overflow:hidden; }

/* ── Store-shaped header ─────────────────────────────────────────────────────
   These pages used to open on a full-height cinematic hero with the library
   below it, which meant a screen of scrolling before you saw a single cover.
   They now open the way the store does: a short title band, then straight into
   the billboard.

   padding-top is deliberately NOT set here. site.css pins every page title to
   one height site-wide with a .head{padding-top:…} longhand; this sheet loads
   after it, so a `padding` shorthand would win and knock the comics pages off
   that shared line. Longhands for the other three sides only. */
.hero-zone { position:relative; }
/* Lives INSIDE .head and fills it, the way store.html and the characters hub
   bound theirs — the fan ends where the title block ends, above whatever the
   page puts next. No mask: every hero on the site clips at its container, and
   this one is not the exception. The old height:660px was the whole problem —
   it knew nothing about the page and on Get Access it fell 176px inside the
   Orbital frame. */
.hero-fx { position:absolute; inset:0; overflow:hidden; z-index:-1; pointer-events:none; }
.head-rays { position:absolute; top:44%; left:50%; width:132vmax; height:132vmax; transform:translate(-50%,-50%); pointer-events:none;
  background: repeating-conic-gradient(from 0deg at 50% 50%, rgba(224,187,82,0.055) 0deg 1deg, transparent 1deg 7deg),
              repeating-conic-gradient(from 3deg at 50% 50%, rgba(31,154,166,0.04) 0deg .6deg, transparent .6deg 9deg);
  -webkit-mask: radial-gradient(circle at center, #000 9.5%, transparent 98.6%);
          mask: radial-gradient(circle at center, #000 9.5%, transparent 98.6%);
  will-change:transform; animation:headRays 120s linear infinite; }
@keyframes headRays { from { transform:translate(-50%,-50%) rotate(0deg); } to { transform:translate(-50%,-50%) rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .head-rays { animation:none; } }

.head { position:relative; z-index:1; overflow:hidden; text-align:center;
  padding-right:1.5rem; padding-bottom:1.2rem; padding-left:1.5rem; }
.head .eyebrow { font-family:'Oswald',sans-serif; font-weight:500; text-transform:uppercase; color:var(--teal-lt); }
.head h1 { font-family:'Oswald',sans-serif; font-weight:700; letter-spacing:.04em; text-transform:uppercase;
  background:linear-gradient(100deg,var(--gold-dk),var(--gold) 30%,var(--gold-lt) 50%,var(--gold) 70%,var(--gold-dk));
  -webkit-background-clip:text; background-clip:text; -webkit-text-fill-color:transparent; }
.head .rule { width:min(280px,60vw); height:2px; margin:1rem auto; background:linear-gradient(90deg,transparent,var(--gold) 25%,var(--teal) 75%,transparent); }
.head .head-sub { color:rgba(241,236,224,.68); font-size:1.05rem; line-height:1.6; max-width:620px; margin:0 auto; }
/* the hub's three routes, directly under its title */
.head .cm-cta { margin-top:1.5rem; }
/* the library now starts right under the title band rather than a screen down */
.clib { padding-top:1.1rem; }

/* ============================================================================
   PREMIUM PASS — the billboard carousel, the shelf banners, and the motion
   that makes the whole thing read as a storefront rather than a page.
   Everything below overrides the base rules above by source order.
   ========================================================================== */

/* ── billboard: three newest, crossfading ──────────────────────────────────
   Slides stack in the same box and cross-fade. visibility rides along with
   opacity so a faded-out slide cannot be tabbed into. */
.cbb-main { display:block; }
.cbb-slide { position:absolute; inset:0; display:flex; align-items:flex-end;
  opacity:0; visibility:hidden; transition:opacity .9s ease, visibility 0s linear .9s; }
.cbb-slide.is-on { opacity:1; visibility:visible; transition:opacity .9s ease, visibility 0s; }

/* a very slow push in on the art. 20s against a 7s slide means the movement is
   never resolved while you are looking at it, which is the point — it should
   read as depth, not as an animation */
.cbb-slide .cbb-art img { animation:cbbKen 20s ease-out both; transform:none; }
@keyframes cbbKen { from { transform:scale(1.015); } to { transform:scale(1.11); } }
.cbb-main:hover .cbb-art img { transform:none; }

/* the copy arrives in order rather than all at once */
.cbb-slide.is-on .cbb-body > * { animation:cbbUp .65s cubic-bezier(.22,1,.36,1) both; }
.cbb-slide.is-on .cbb-body > *:nth-child(1) { animation-delay:.05s; }
.cbb-slide.is-on .cbb-body > *:nth-child(2) { animation-delay:.12s; }
.cbb-slide.is-on .cbb-body > *:nth-child(3) { animation-delay:.19s; }
.cbb-slide.is-on .cbb-body > *:nth-child(4) { animation-delay:.26s; }
.cbb-slide.is-on .cbb-body > *:nth-child(5) { animation-delay:.33s; }
@keyframes cbbUp { from { opacity:0; transform:translateY(16px); } to { opacity:1; transform:none; } }

/* the frame follows whichever reading is on screen */
.cbb-main { border-color:rgba(var(--cx-rgb,31,154,166), .45); transition:border-color .9s ease; }

/* Dots are a progress bar, not decoration: the active one fills over exactly
   the interval, so the wait is visible and hovering visibly pauses it. */
.cbb-dots { position:absolute; right:1.4rem; bottom:1.4rem; z-index:5; display:flex; align-items:center; gap:.45rem; }
.cbb-dot { width:24px; height:4px; padding:0; border:0; border-radius:100px; cursor:pointer; position:relative; overflow:hidden;
  background:rgba(241,236,224,.3); transition:width .4s cubic-bezier(.22,1,.36,1), background .3s; }
.cbb-dot:hover { background:rgba(241,236,224,.55); }
.cbb-dot.on { width:66px; background:rgba(241,236,224,.2); }
.cbb-dot.on::after { content:''; position:absolute; inset:0; transform-origin:left;
  background:linear-gradient(90deg, var(--gold), var(--gold-lt));
  animation:cbbFill 7s linear both; }
@keyframes cbbFill { from { transform:scaleX(0); } to { transform:scaleX(1); } }
.cbb-main:hover .cbb-dot.on::after, .cbb-main:focus-within .cbb-dot.on::after { animation-play-state:paused; }

/* ── shelf banners ─────────────────────────────────────────────────────────
   The store's category bars, built at read time instead of baked, because
   these shelves are generated from data and there is no fixed list to bake. */
.cx-shelf-h { display:none; }
.cx-banner {
  position:relative; display:flex; align-items:center; width:100%; height:106px; margin:0 0 .95rem;
  padding:0; overflow:hidden; border-radius:12px; cursor:pointer; text-align:left; background:#0b0d11;
  border:1px solid rgba(var(--cx-rgb,31,154,166), .3); font:inherit; color:inherit;
  transition:border-color .25s, box-shadow .25s, transform .2s;
}
.cx-banner:hover, .cx-banner:focus-visible {
  border-color:rgba(var(--cx-rgb,31,154,166), .8); transform:translateY(-2px); outline:none;
  box-shadow:0 12px 32px rgba(0,0,0,.5), 0 0 30px rgba(var(--cx-rgb,31,154,166), .2);
}
.cx-banner-art { position:absolute; inset:0; }
.cx-banner-art img { width:100%; height:100%; object-fit:cover; object-position:var(--cx-focus,50% 16%); display:block;
  opacity:.9; transition:transform .6s cubic-bezier(.22,1,.36,1); }
.cx-banner:hover .cx-banner-art img { transform:scale(1.06); }
/* the art is behind the words, so the words get their own floor */
.cx-banner-scrim { position:absolute; inset:0; background:
  linear-gradient(90deg, rgba(8,9,12,.97) 0%, rgba(8,9,12,.9) 32%, rgba(8,9,12,.4) 64%, rgba(8,9,12,.12) 100%),
  linear-gradient(0deg, rgba(var(--cx-rgb,31,154,166), .16), transparent 72%); }
.cx-banner-edge { position:absolute; left:0; top:0; bottom:0; width:4px;
  background:linear-gradient(180deg, rgb(var(--cx-rgb,31,154,166)), rgba(var(--cx-rgb,31,154,166), .22)); }
.cx-banner-in { position:relative; z-index:2; padding:0 1.5rem; display:flex; flex-direction:column; gap:.28rem; min-width:0; }
.cx-banner .cx-shelf-t { display:block; font-size:1.3rem; }
.cx-banner .cx-shelf-s { display:block; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:46ch; }
.cx-banner-r { position:relative; z-index:2; margin-left:auto; padding:0 1.4rem; display:flex; align-items:center; gap:1.1rem; flex:none; }
.cx-banner-all { font-family:'Oswald',sans-serif; font-weight:600; font-size:.56rem; letter-spacing:.22em; text-transform:uppercase;
  color:var(--gold-lt); border:1px solid rgba(224,187,82,.42); border-radius:100px; padding:.42rem .95rem; white-space:nowrap;
  transition:color .2s, background .2s, border-color .2s; }
.cx-banner:hover .cx-banner-all { color:var(--ink); background:var(--gold-lt); border-color:transparent; }
@media (max-width:760px){
  .cx-banner { height:82px; }
  .cx-banner .cx-shelf-t { font-size:1.05rem; }
  .cx-banner .cx-shelf-s, .cx-banner .cx-shelf-n { display:none; }
  .cx-banner-in, .cx-banner-r { padding:0 1rem; }
}

/* ── rails ─────────────────────────────────────────────────────────────────
   Snap so a flick lands on a cover instead of between two, and let the banner
   open the shelf out into a grid when a rail is longer than a glance. */
.cx-rail { scroll-snap-type:x proximity; scroll-padding-left:.1rem; }
.cx-card { scroll-snap-align:start; }
.cx-rail.grid { flex-wrap:wrap; overflow:visible; scroll-snap-type:none; cursor:default; }
.cx-rail-w.open::before, .cx-rail-w.open::after { opacity:0 !important; }

/* shelves arrive as you reach them rather than all being there at once */
.cx-shelf { opacity:0; transform:translateY(20px); transition:opacity .55s ease, transform .55s cubic-bezier(.22,1,.36,1); }
.cx-shelf.in { opacity:1; transform:none; }

/* ── covers ────────────────────────────────────────────────────────────────
   A little more lift, and a sheen that crosses the cover on hover — the one
   flourish that makes a shelf of stills feel like it is made of objects. */
.cx-card:hover, .cx-card:focus-visible { transform:translateY(-10px) scale(1.015); }
.cx-cover { isolation:isolate; }
.cx-cover .sheen { position:absolute; inset:0; z-index:4; pointer-events:none; opacity:0;
  background:linear-gradient(115deg, transparent 38%, rgba(255,255,255,.16) 50%, transparent 62%);
  background-size:230% 100%; background-position:210% 0; }
.cx-card:hover .cx-cover .sheen { opacity:1; animation:cxSheen .9s ease-out; }
@keyframes cxSheen { from { background-position:210% 0; } to { background-position:-70% 0; } }

@media (prefers-reduced-motion: reduce) {
  .cbb-slide .cbb-art img, .cbb-slide.is-on .cbb-body > *, .cbb-dot.on::after,
  .cx-card:hover .cx-cover .sheen { animation:none !important; }
  .cx-shelf { opacity:1; transform:none; }
  .cx-card:hover, .cx-card:focus-visible { transform:none; }
}

/* ── Banner art: a panel, not a full-bleed slice ─────────────────────────────
   Cover-fitting a standing figure across a 106px band crops it to about 7% of
   its height, which lands somewhere around a collarbone. The art is now a
   panel on the right at a sane aspect, fed a square portrait rather than a
   full-body render, and masked so it dissolves into the bar instead of ending
   on a hard edge. Taller too — 132 gives the face room to actually read. */
.cx-banner { height:132px; }
.cx-banner-art { left:auto; width:min(52%, 520px); }
.cx-banner-art img { object-position:var(--cx-focus, 50% 22%); opacity:.95;
  -webkit-mask:linear-gradient(90deg, transparent 0%, #000 46%, #000 100%);
          mask:linear-gradient(90deg, transparent 0%, #000 46%, #000 100%); }
/* the heavy left-to-right wash is no longer needed now the art is inset; what
   is left is a light floor so the words never sit on a bright patch */
.cx-banner-scrim { background:
  linear-gradient(90deg, rgba(8,9,12,.92) 0%, rgba(8,9,12,.72) 38%, rgba(8,9,12,.18) 62%, transparent 82%),
  linear-gradient(0deg, rgba(var(--cx-rgb,31,154,166), .14), transparent 76%); }
@media (max-width:760px){
  .cx-banner { height:92px; }
  .cx-banner-art { width:min(58%, 300px); }
}

/* ── the hosted page's one-line call to action ───────────────────────────── */
.head .head-note { margin:1rem auto 0; max-width:620px; font-size:1rem; line-height:1.6; color:rgba(241,236,224,.6); }
.head .head-note a { color:var(--gold-lt); text-decoration:none; border-bottom:1px solid rgba(224,187,82,.42); transition:color .2s, border-color .2s; }
.head .head-note a:hover { color:var(--paper); border-color:var(--gold-lt); }

/* nothing left over after the carousel, so the frame is copy only */
.cbb-soon.no-img { grid-template-rows:1fr; }
.cbb-soon.no-img .cbb-soon-body { justify-content:center; padding:1.8rem 1.6rem; }

/* ── Banner art, second pass ─────────────────────────────────────────────────
   How much of a face you get is width and height together, not just
   object-position. A square portrait cover-fitted into a W×H panel shows H/W
   of its height — so at 520×132 that was a quarter of the image, and where a
   given portrait puts its face decided whether you got eyes or a mouth.

   Narrower and taller: 430×150 shows about 35% of the portrait, which holds a
   whole face across portraits framed differently. Any that still sits wrong
   takes a bannerFocus in comics-data.js rather than moving this default. */
.cx-banner { height:150px; }
.cx-banner-art { width:min(46%, 430px); }
.cx-banner-art img { object-position:var(--cx-focus, 50% 20%); }
@media (max-width:760px){
  .cx-banner { height:104px; }
  .cx-banner-art { width:min(62%, 260px); }
}

/* The banner strips are cut to 3:1 around the face by build-comic-banners.js,
   so there is nothing left for object-position to get wrong. Centre it. */
.cx-banner-art img { object-position:var(--cx-focus, 50% 50%); }

/* the count and See all sit over the art, so they get a local floor rather
   than relying on whatever happens to be behind that character's head */
.cx-banner-r { background:linear-gradient(90deg, transparent, rgba(8,9,12,.72) 34%, rgba(8,9,12,.86) 100%); padding-left:3rem; }


/* --- Skeleton: the shape of the library before the library exists -----------
   Without this the page paints an empty band and then everything lands at
   once. These are the same boxes at the same sizes, so nothing moves when the
   real content replaces them — only the surface changes. */
.cx-skel { animation:cxSkelIn .2s ease both; }
.cx-skel-bb { display:grid; grid-template-columns:minmax(0,1.55fr) minmax(0,1fr); grid-template-rows:430px; gap:1.1rem; margin:0 0 2.6rem; }
.cx-skel-bar { height:38px; border-radius:100px; width:min(420px,60%); margin:0 0 1.5rem; }
.cx-skel-shelf { height:150px; border-radius:12px; margin:2.4rem 0 .95rem; }
.cx-skel-row { display:flex; gap:.9rem; }
.cx-skel-card { flex:0 0 auto; width:210px; aspect-ratio:2/3; border-radius:11px; }
.cx-skel-bb > *, .cx-skel-bar, .cx-skel-shelf, .cx-skel-card {
  background:linear-gradient(100deg, rgba(255,255,255,.028) 30%, rgba(31,154,166,.09) 50%, rgba(255,255,255,.028) 70%);
  background-size:220% 100%; animation:cxShimmer 1.5s ease-in-out infinite;
  border:1px solid rgba(241,236,224,.06); border-radius:14px;
}
@keyframes cxShimmer { 0%{background-position:130% 0;} 100%{background-position:-30% 0;} }
@keyframes cxSkelIn { from { opacity:0; } to { opacity:1; } }
@media (max-width:1050px){ .cx-skel-bb { grid-template-columns:1fr; grid-template-rows:auto; } .cx-skel-bb > * { height:300px; } }
@media (prefers-reduced-motion: reduce){ .cx-skel-bb > *, .cx-skel-bar, .cx-skel-shelf, .cx-skel-card { animation:none; } }
