* { box-sizing: border-box; }

body {
  margin: 0;
  background: #141414;
  color: #e8e8e8;
  font: 15px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

header {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 12px;
  padding: 20px 24px;
  border-bottom: 1px solid #2c2c2c;
  /* Reserves the second line that .subbar-left/right are pinned to. The note
     used to be two lines tall and supplied this height on its own; it's one
     line now, so without this the subbar overlaps the title row. */
  min-height: 82px;
}

/* Sits inline in the header row; flex:1 lets it center in the leftover space. */
.note {
  flex: 1;
  text-align: center;
}

.note-main {
  margin: 0;
  font-size: 16px;
  font-weight: 700;
  color: #c8c8c8;
}

/* Subheader under .note-main. Only the Tarot page uses it, but it lives here
   since both pages share this stylesheet. */
.note-sub {
  margin: 2px 0 0;
  font-size: 11px;
  font-weight: 400;
  color: #7a7a7a;
}

/* The note's flex:1 eats the middle, so this lands hard right. */
.visitors {
  flex: 0 0 auto;
  font-size: 13px;
  color: #8a8a8a;
  white-space: nowrap;
}

/* Disclaimer and music link pin to the header's bottom corners. Kept out of the
   flex flow so their widths can't shift the centred note. The header's
   min-height reserves the line they sit on. */
.subbar-left,
.subbar-right {
  position: absolute;
  bottom: 20px;
  font-size: 12px;
  color: #7a7a7a;
  white-space: nowrap;
}

.subbar-left { left: 24px; }
.subbar-right { right: 24px; }

.subbar-left a,
.subbar-right a {
  color: #a8a8a8;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.subbar-left a:hover,
.subbar-right a:hover { color: #e8e8e8; }

h1 {
  margin: 0;
  font-size: 17px;
  font-weight: 600;
  letter-spacing: 0.02em;
}

.count {
  font-size: 13px;
  color: #8a8a8a;
}

/* Pinned rather than placed in the flex flow: as a flex item its width shifted
   the centred note off-centre. Absolute keeps it clear of that entirely.
   Offset from the right edge to clear the visitor count, which sits there. */
/* Wraps the credit link and its subtext as one block so the two stay together
   in the corner. Absolute for the same reason the credit itself was: as a flex
   item its width pushed the centred note off-centre. */
.credit-block {
  position: absolute;
  top: 20px;
  right: 175px;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.credit {
  font-size: 13px;
  color: #8a8a8a;
  white-space: nowrap;
  /* Always underlined so it reads as clickable without needing a hover. */
  text-decoration: underline;
}

.credit:hover {
  color: #d4d4d4;
}

.credit-sub {
  margin-top: 2px;
  font-size: 10px;
  color: #6f6f6f;
  white-space: nowrap;
}

main { padding: 24px; }

/* Divider between sections. The first one needs no rule above it. */
.section + .section {
  margin-top: 32px;
  padding-top: 24px;
  border-top: 1px solid #2c2c2c;
}

.section h2 {
  margin: 0 0 14px;
  font-size: 14px;
  font-weight: 600;
  color: #b4b4b4;
  letter-spacing: 0.02em;

  /* Row so the count, the sensitive note and the reveal-all button sit on the
     title's line. Wraps rather than overflowing on a narrow screen. */
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px;
}

.section-count {
  font-weight: 400;
  color: #7a7a7a;
}

/* Explains the flagged section beside its title, in the same muted grey the
   header's own sub-labels use. */
.section-note {
  font-size: 11px;
  font-weight: 400;
  color: #7a7a7a;
  letter-spacing: 0;
}

/* Uncovers the whole section at once. Pushed to the far end of the heading row
   so it reads as a section-level action, not part of the title. Styled as a
   plain text link, like the header's other inline actions, rather than a button
   chrome the page has nowhere else. */
.reveal-all {
  margin-left: auto;
  padding: 0;
  border: 0;
  background: none;
  color: #a8a8a8;
  font: inherit;
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0;
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}

.reveal-all:hover { color: #e8e8e8; }

.reveal-all[hidden] { display: none; }

/* Masonry-ish columns: images keep their true aspect ratio and flow into
   whichever column has room, instead of being cropped to a uniform cell. */
.grid {
  column-width: 260px;
  column-gap: 12px;
}

.tile {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: #1e1e1e;
  cursor: pointer;
  line-height: 0;
  /* Stop a tile from being split across a column break. */
  break-inside: avoid;
  margin-bottom: 12px;
}

.tile img {
  width: 100%;
  height: auto;
  display: block;
}

.tile:hover img { opacity: 0.82; }

/* Click-to-reveal tile. The thumbnail loads normally and is blurred in place, so
   the tile still reads as an image — shape and colour come through, detail does
   not. The blur is the cover here, so it has to stay heavy. */
.tile.is-hidden {
  position: relative;
  /* Clips the scaled-up image below, so the enlargement can't bleed past the
     tile's edges into its neighbours. */
  overflow: hidden;
}

.tile.is-hidden img {
  /* Scaled up because a blur samples past the edges, which would otherwise show
     as a soft transparent border around the tile. */
  filter: blur(22px) saturate(0.85) brightness(0.55);
  transform: scale(1.15);
}

/* The blur alone can leave a bright image still fairly readable, so a light
   wash sits on top — enough to knock it back without hiding that there's an
   image there at all. */
.veil {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  color: #e4e4e4;
  background: rgba(18, 18, 18, 0.28);
  line-height: 1.3;
  text-align: center;
  padding: 10px;
  /* Keeps the icon and label legible over whatever colour is behind them. */
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.85);
}

.veil svg {
  width: 30px;
  height: 30px;
  opacity: 0.92;
  /* text-shadow doesn't apply to SVG strokes; this is its equivalent. */
  filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.85));
}

.veil-text {
  font-size: 12px;
  letter-spacing: 0.02em;
}

/* Hover hints that clicking does something, without uncovering anything. */
.tile.is-hidden:hover .veil {
  background: rgba(18, 18, 18, 0.16);
  color: #fff;
}

/* Bundle tile: cover on the left, slices of the other pages on the right, so a
   multi-page comic reads as multiple images at a glance. */
.tile.is-bundle {
  position: relative;
  display: block;
  /* Fixed ratio here (unlike single tiles) so both halves share a height. */
  aspect-ratio: 4 / 3;
}

.bundle-row {
  display: flex;
  gap: 2px;
  width: 100%;
  height: 100%;
}

.bundle-cover {
  flex: 0 0 50%;
  overflow: hidden;
  line-height: 0;
}

.bundle-cover img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.bundle-strip {
  flex: 1;
  display: flex;
  gap: 2px;
  overflow: hidden;
}

.bundle-slice {
  flex: 1;
  overflow: hidden;
  line-height: 0;
}

.bundle-slice img {
  width: 100%;
  height: 100%;
  /* Cover + center keeps each slice showing the middle of its page rather than
     an arbitrary edge. */
  object-fit: cover;
  object-position: center;
}

.badge {
  position: absolute;
  top: 6px;
  right: 6px;
  padding: 3px 7px;
  background: rgba(0, 0, 0, 0.75);
  color: #e8e8e8;
  font-size: 11px;
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: 0.02em;
}

.tile:focus-visible {
  outline: 2px solid #e8e8e8;
  outline-offset: 2px;
}

.empty {
  color: #8a8a8a;
  font-size: 14px;
}

/* Lightbox */
.viewer {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.94);
  display: flex;
  align-items: center;
  justify-content: center;
  /* Above everything in the grid. Without this the viewer sits at the default
     level and the tiles' own layered pieces — the reveal veils at z-index 2,
     the bundle badges — paint straight over the open lightbox. It also makes
     this a stacking context, so those inner z-indexes stay contained here. */
  z-index: 100;
}

/* display:flex above outranks the browser default for [hidden], which would
   otherwise keep the viewer on screen permanently. */
.viewer[hidden] { display: none; }

/* Stage wraps the current page plus the peek behind it, so the two can be
   layered without the peek affecting the viewer's centering. */
.stage {
  position: relative;
  display: inline-block;
  line-height: 0;
}

/* The peek only sticks out to the right, so nudge the whole stage left to keep
   the pair looking centred. Kept below half the overhang so a full-width image
   still can't be pushed off the left edge. */
.stage.has-peek {
  transform: translateX(-8%);
}

.stage img {
  /* Narrower than the viewport so the peek's overhang to the right still fits
     on screen instead of being clipped at the edge. */
  max-width: 72vw;
  max-height: 88vh;
  object-fit: contain;
}

#viewerImg {
  position: relative;
  z-index: 1;
}

/* Next page offset to the lower-right so a clear strip of it stays visible.
   Anchored from the right edge (rather than the left) so the exposed amount is
   a predictable fraction of the page width, whatever the image's proportions. */
.peek {
  position: absolute;
  right: -22%;
  top: 22px;
  width: 100%;
  height: 100%;
  z-index: 0;
  opacity: 0.62;
  filter: brightness(0.72);
  pointer-events: none;
}

.peek[hidden] { display: none; }

.pageno {
  position: absolute;
  left: 0;
  bottom: -26px;
  z-index: 2;
  font-size: 13px;
  color: #9a9a9a;
  line-height: 1.4;
}

.pageno[hidden] { display: none; }

/* Lightbox cover, mirroring the grid tile: the image loads and is blurred in
   place rather than withheld. Only #viewerImg is blurred — the peek gets its own
   .is-blurred, since the next page can be flagged when the current one isn't. */
.stage.is-hidden #viewerImg {
  filter: blur(34px) saturate(0.85) brightness(0.55);
  /* Larger than the tile's scale: a blur this wide samples further past the
     edges, and the stage doesn't clip, so the image has to cover its own halo. */
  transform: scale(1.06);
}

/* A flagged next page, blurred behind the current one. */
.peek.is-blurred {
  filter: blur(20px) saturate(0.85) brightness(0.5);
}

.viewer-reveal {
  /* The viewer's own button rule positions absolutely from the viewer edges;
     these override it to centre on the image instead. */
  position: absolute;
  inset: 0;
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  background: rgba(18, 18, 18, 0.28);
  color: #e4e4e4;
  cursor: pointer;
  font: inherit;
  font-size: 13px;
  line-height: 1.3;
  text-align: center;
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.85);
}

.viewer-reveal[hidden] { display: none; }

.viewer-reveal:hover {
  background: rgba(18, 18, 18, 0.16);
  color: #fff;
}

.viewer-reveal svg {
  width: 38px;
  height: 38px;
  opacity: 0.92;
  filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.85));
}

/* Shares the strip below the image with .pageno, anchored to the opposite edge
   so a bundle page can show both without them running into each other. */
.source {
  position: absolute;
  right: 0;
  bottom: -26px;
  z-index: 2;
  display: flex;
  gap: 8px;
  align-items: baseline;
  max-width: 100%;
  font-size: 13px;
  line-height: 1.4;
  /* The stage is line-height:0 for the images; text needs it back. */
  white-space: nowrap;
  overflow: hidden;
}

.source[hidden] { display: none; }

.source-label { color: #9a9a9a; }

/* A credit with no URL — deliberately without the underline, so it doesn't look
   like a link that failed to work. */
.source-name {
  color: #b9b9b9;
  overflow: hidden;
  text-overflow: ellipsis;
}

.source a {
  color: #b9b9b9;
  text-decoration: none;
  border-bottom: 1px solid #4a4a4a;
  overflow: hidden;
  text-overflow: ellipsis;
}

.source a:hover {
  color: #fff;
  border-bottom-color: #8a8a8a;
}

/* The chrome buttons (close/prev/next) only. :not() keeps the full-bleed reveal
   overlay out — it defines its own box, and this rule's edge anchoring and
   30px glyph size would otherwise override it from further down the file. */
.viewer button:not(.viewer-reveal) {
  position: absolute;
  border: 0;
  background: transparent;
  color: #e8e8e8;
  cursor: pointer;
  font-size: 30px;
  line-height: 1;
  padding: 12px 16px;
}

.viewer button:not(.viewer-reveal):hover { color: #fff; }

.close { top: 8px; right: 12px; }
.nav { top: 50%; transform: translateY(-50%); font-size: 44px; }
.prev { left: 4px; }
.next { right: 4px; }

/* Below this the two don't fit side by side, so give each its own full-width
   line and let them stack. */
@media (max-width: 780px) {
  .subbar-left,
  .subbar-right {
    flex: 0 0 100%;
    text-align: left;
  }
  .subbar-left { margin-top: 6px; }
  .subbar-right { margin-top: 2px; }
}

@media (max-width: 600px) {
  main { padding: 12px; }
  .grid { column-width: 150px; column-gap: 8px; }
  .tile { margin-bottom: 8px; }

  /* Too little room to center beside the title — give it its own line. */
  .note { flex: 0 0 100%; }
  .note-main { font-size: 15px; }
  .note-sub { font-size: 10px; }

  /* Not enough width for the page number and a hostname side by side, so the
     source drops onto its own line under it. */
  .source {
    bottom: -44px;
    font-size: 12px;
    max-width: 78vw;
  }

  /* Less width to spare, so a smaller overhang keeps the peek on screen. */
  .stage img { max-width: 78vw; }
  .peek { right: -14%; top: 14px; }
  .stage.has-peek { transform: translateX(-6%); }

  .subbar-left,
  .subbar-right { font-size: 11px; }

  /* Mobile header cleanup. The absolutely-positioned credit block was pinned
     175px from the right to clear the visitor count, which on a narrow screen
     put it straight on top of the title. Rather than reflow every piece into a
     tall stack, drop the two optional bits and pin a short credit to the right.
     Desktop keeps all of it — these overrides are scoped to this breakpoint.
     Tunes is targeted via :has(#tunes) rather than .subbar-right, since the
     Tarot page reuses that class for its "Back to naiteasers" link, which
     must survive. */
  .visitors,
  .credit-sub { display: none; }

  /* The tunes bar goes on mobile, but the language switch lives inside it and
     has to survive. Hiding the bar outright would take the switch with it (a
     descendant of display:none can't be re-shown), so instead the bar stays and
     its tunes text is collapsed, leaving just the switch pinned in the corner.
     font-size:0 on the bar also eats the "/" separator, which only made sense
     next to the tunes link; the switch's own anchor sets its size back. */
  .subbar-right:has(#tunes) { font-size: 0; }
  .subbar-right:has(#tunes) #tunes { display: none; }
  .subbar-right:has(#tunes) .lang-switch a { font-size: 11px; }

  .credit-block {
    top: 20px;
    right: 16px;
  }

  /* Swapped for a short label on mobile: the full name list is too wide to pin
     to the corner without colliding with the title. The real text is collapsed
     to zero width rather than display:none so the link keeps its accessible
     name for screen readers, and the short label is drawn alongside it. */
  .credit {
    font-size: 12px;
    overflow: hidden;
  }

  .credit .credit-full {
    display: inline-block;
    width: 0;
    overflow: hidden;
    white-space: nowrap;
  }

  .credit::after { content: "Website by Tarotfool"; }
}
