/* ── Reset ── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
/* Reading size belongs to the fs-* ladder below, which the reader controls, and this
   is what keeps Blink's text autosizer ("font boosting") from having an opinion about
   it. The autosizer scales a block by how much text it holds, which would enlarge some
   verse groups and not others.

   A guard, not a fix: measured on a Pixel 7 (Android 16) through the app's own WebView,
   with the declaration removed from first layout, every verse group reported the same
   size either way — that WebView already declines to boost a width=device-width page,
   as Chrome does. It is here because that is a per-engine heuristic and this is the one
   line that makes it not matter. */
html {
  scroll-behavior: smooth;
  overscroll-behavior: none;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

/* ── Safe area ──
   Every piece of fixed or sticky chrome offsets itself by these, never by env()
   directly. On the web env() is the answer and these are simply an alias for it.
   In the app it is not: Android's WebView reports safe-area-inset-top as 0 because
   env() tracks display cutouts, not system bars, so a nav that trusted it rendered
   under the clock — visible, and untappable because the status bar took the touches.
   apps/mobile/src/Reader.tsx overwrites these four with insets React Native
   measured, which is the only source that knows about the status and gesture bars.
   MOBILE-PLAN.md §6. */
:root {
  --sa-top: env(safe-area-inset-top, 0px);
  --sa-right: env(safe-area-inset-right, 0px);
  --sa-bottom: env(safe-area-inset-bottom, 0px);
  --sa-left: env(safe-area-inset-left, 0px);
}

/* ── Base ── */
body {
  background: #1a1a1a;
  color: #d8d8d8;
  font-family: system-ui, -apple-system, sans-serif;
  font-size: 15px;
  line-height: 1.6;
  min-height: 100vh;
  touch-action: manipulation;
  /* Theme-aware surfaces for in-page boxes / popups (overridden per theme below) */
  --surface: #0f0f0f;
  --surface-border: #2a2a2a;
  --hover-bg: rgba(255, 255, 255, 0.03);
  --soy-green: #45a366;
  /* ── Reading size ──
     The one place a verse's type size is written down. Everything that carries
     reading text reads these rather than declaring a size of its own, because the
     fs-* levels can only reach an element that has not been given an explicit
     font-size: `.vg` sets the size on the GROUP, but a float-wrap group's text is a
     child <p class="ms-block">, and an explicit size on the child does not inherit.
     That is why the largest A used to move 61 of Genesis's 204 verse groups and
     leave the other 143 exactly where they were. The levels override these four
     variables (below, and again inside the 600px block); nothing overrides
     font-size directly. */
  --vg-size: 1.38rem;
  --vg-lh: 2.25;
  --ms-size: 1.38rem;
  --ms-lh: 2.25;
  --climax-size: clamp(1.1rem, 2.8vw, 1.5rem);
  /* Shared minimalist arrowhead (right-pointing); tinted via currentColor, flipped for
     left. A bare chevron rather than the arrow-with-shaft this used to be: the shaft
     read as dated, and dropping it also lets the glyph sit tighter beside its label.
     The viewBox is the chevron's own bounding box plus a stroke's worth of padding, so
     `mask-size: contain` scales the INK to the element rather than leaving it adrift in
     an oversized 24×24 square. Stroke goes up to 2.2 to compensate — at 1.05em a
     shaft-less chevron drawn at the old 1.6 looks spindly. */
  --arrow-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 13 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 5.5 10.5 12 4 18.5'/%3E%3C/svg%3E");
}

/* Minimalist nav arrow — a masked SVG filled with the current text colour, so it
   adapts to every theme and hover state. Used inline in top-nav links. */
.nav-arrow {
  display: inline-block;
  /* Sized to --arrow-icon's 13:24 viewBox. A square box would centre the chevron and
     leave a quarter-em of dead space either side, reading as a stray word gap. */
  width: 0.58em;
  height: 1.05em;
  vertical-align: -0.16em;
  background-color: currentColor;
  -webkit-mask: var(--arrow-icon) center / contain no-repeat;
          mask: var(--arrow-icon) center / contain no-repeat;
}
.nav-arrow--left { transform: scaleX(-1); }

/* The callout suppression is for the app (MOBILE-PLAN.md §6): long-pressing a link or
   an image otherwise raises the system "open in browser" / "save image" sheet, which is
   the loudest tell that a WebView is a WebView. Text selection is deliberately left
   alone — this is a reader, and people copy verses. */
a { color: inherit; text-decoration: none; -webkit-touch-callout: none; -webkit-tap-highlight-color: transparent; }
button { -webkit-touch-callout: none; -webkit-tap-highlight-color: transparent; }
img { -webkit-touch-callout: none; -webkit-tap-highlight-color: transparent; }

/* ── Page shell ── */
.page {
  max-width: 960px;
  margin: 0 auto;
  padding: 3rem 2rem 8rem;
}

.page--narrow {
  max-width: 900px;
  margin: 0 auto;
  padding: 3rem 2rem 8rem;
}

/* ── Nav bar ── */
.nav {
  max-width: 960px;
  margin: 0 auto;
  padding: calc(1.5rem + var(--sa-top)) 2rem 0;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  border-bottom: 1px solid #2a2a2a;
  padding-bottom: 1rem;
}

.nav--narrow {
  max-width: 680px;
}

/* ── The mark in the middle of the bar ──
   `justify-content: space-between` centres nothing when there is one item to the left of
   the logo and none to its right, so this switches to a three-column grid with an empty
   third column: the middle cell is centred on the bar, not between its neighbours. Works
   whether or not the left cell is filled, which is the difference between the chapter
   index (which keeps its ← Library) and /library (which does not). */
.nav--logo {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  justify-content: initial;
}

.nav-logo {
  grid-column: 2;
  justify-self: center;
  display: flex;
  align-items: center;
}

/* The wordmark is dark artwork — the landing page inverts it to cream the same way
   (pages/index.astro). Themes that paint on light leave it alone. */
/* The mark, masked and filled with the current text colour — the same treatment as
   .nav-arrow above, and for the same reason: it then IS the nav's colour in every theme
   and on hover, with no per-theme rule to keep in step. The file's own #ffedcf is
   irrelevant under a mask, which reads alpha only.

   `logo-mark.svg` is cropped to the ink (see the file), so `mask-size: contain` scales
   the glyph to the box rather than the 600-unit square it was drawn in. Square box: the
   crop is square. 22px against the nav's ~11px uppercase caps — a round glyph needs the
   extra height to carry the same weight as the text beside it. */
.nav-logo__mark {
  display: block;
  width: 25px;
  height: 25px;
  background-color: currentColor;
  -webkit-mask: url('/src/brand/logo-mark.svg') center / contain no-repeat;
          mask: url('/src/brand/logo-mark.svg') center / contain no-repeat;
}

/* 0.82rem rather than the 0.72rem the bar carried for its first year: at arm's length
   on a phone, uppercase 11px with 0.12em tracking is a decoration you squint at, and
   these are the chapter's only controls. .nav-arrow is sized in em, so it grows with
   this on its own; the px icons beside it (.nav-logo__mark, .nav-gallery::before,
   .nav-back__icon) are stepped up to match by hand. */
.nav a {
  font-size: 0.82rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #666;
  transition: color 0.15s;
}

.nav a:hover { color: #d8d8d8; }

.nav-center {
  font-size: 0.82rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #444;
}

.nav-count {
  font-size: 0.82rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: inherit;
  opacity: 0.4;
  white-space: nowrap;
}

/* ── Index header ── */
.site-title {
  font-size: 0.65rem;
  letter-spacing: 0.4em;
  text-transform: uppercase;
  color: #555;
  margin-bottom: 0.5rem;
}

.page-heading {
  font-size: clamp(2rem, 6vw, 3.5rem);
  font-weight: 700;
  letter-spacing: -0.02em;
  color: #f0f0f0;
  line-height: 1.1;
  margin-bottom: 3rem;
}

/* ── Section divider ── */
.section-label {
  font-size: 0.65rem;
  letter-spacing: 0.4em;
  text-transform: uppercase;
  color: #555;
  padding-bottom: 0.6rem;
  border-bottom: 1px solid #2a2a2a;
  margin-bottom: 1.5rem;
}

/* ── Book grid (index page) ── */
.book-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 1px;
  background: #2a2a2a;
  border: 1px solid #2a2a2a;
  margin-bottom: 4rem;
}

.book-card {
  display: flex;
  flex-direction: column;
  padding: 1.6rem 1.4rem;
  background: #1a1a1a;
  cursor: pointer;
  transition: background 0.12s;
  text-decoration: none;
  color: inherit;
}

.book-card:hover { background: #222; }

.book-card__name {
  font-size: 1.1rem;
  font-weight: 600;
  color: #f0f0f0;
  margin-bottom: 0.3rem;
}

.book-card__testament {
  font-size: 0.62rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: #555;
  margin-bottom: 0.8rem;
}

.book-card__desc {
  font-size: 0.95rem;
  color: #777;
  line-height: 1.55;
  flex: 1;
}

.book-card__chapters {
  margin-top: 1rem;
  font-size: 0.62rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: #555;
}

/* ── Chapter list (book index page) ── */
.book-header {
  margin-bottom: 3rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2.5rem;
}
.book-header__main { flex: 1 1 auto; min-width: 0; }

/* ── Gallery entry — a stack of picture frames that fans open on hover ── */
.gallery-cta {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.85rem;
  padding: 0.5rem 0.25rem;
  color: inherit;              /* all tints derive from currentColor -> theme-adaptive */
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
}
.gallery-cta__stack {
  position: relative;
  width: 130px;
  height: 116px;
}
.gallery-cta__frame {
  position: absolute;
  inset: 0;
  margin: auto;
  width: 90px;
  height: 90px;
  border: 1px solid var(--surface-border);
  border-radius: 8px;
  background: var(--surface);
  transition: transform 0.5s cubic-bezier(0.2, 0.85, 0.25, 1), border-color 0.35s ease;
}
.gallery-cta__frame--back {
  transform: rotate(-9deg) translate(-11px, 5px);
  opacity: 0.55;
  border-color: color-mix(in srgb, var(--surface-border) 80%, currentColor);
}
.gallery-cta__frame--mid {
  transform: rotate(6deg) translate(10px, 2px);
  opacity: 0.8;
  border-color: color-mix(in srgb, var(--surface-border) 68%, currentColor);
}
.gallery-cta__frame--front {
  display: flex;
  align-items: center;
  justify-content: center;
  transform: rotate(-2deg);
  border-color: color-mix(in srgb, var(--surface-border) 45%, currentColor);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.28);
}
/* Night's --surface-border is near-black, so lean the back frames harder on
   currentColor to keep the same stacked-border prominence as the other themes. */
body.theme-night .gallery-cta__frame--back {
  border-color: color-mix(in srgb, var(--surface-border) 55%, currentColor);
}
body.theme-night .gallery-cta__frame--mid {
  border-color: color-mix(in srgb, var(--surface-border) 42%, currentColor);
}

.gallery-cta__pic {
  width: 46px;
  height: 46px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0.5;
  transition: stroke 0.35s ease, opacity 0.35s ease;
}
.gallery-cta__pic circle { fill: currentColor; stroke: none; }

/* Fan out + accent tint on hover / keyboard focus */
.gallery-cta:hover .gallery-cta__frame--back,
.gallery-cta:focus-visible .gallery-cta__frame--back { transform: rotate(-15deg) translate(-23px, 7px); }
.gallery-cta:hover .gallery-cta__frame--mid,
.gallery-cta:focus-visible .gallery-cta__frame--mid { transform: rotate(12deg) translate(22px, 4px); }
.gallery-cta:hover .gallery-cta__frame--front,
.gallery-cta:focus-visible .gallery-cta__frame--front {
  transform: rotate(0deg) translateY(-5px);
  border-color: color-mix(in srgb, var(--soy-green) 60%, transparent);
}
.gallery-cta:hover .gallery-cta__pic,
.gallery-cta:focus-visible .gallery-cta__pic { stroke: var(--soy-green); opacity: 1; }
.gallery-cta:hover .gallery-cta__pic circle,
.gallery-cta:focus-visible .gallery-cta__pic circle { fill: var(--soy-green); }

.gallery-cta__text {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.2rem;
}
.gallery-cta__label {
  font-size: 0.72rem;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: color-mix(in srgb, currentColor 60%, transparent);
  transition: color 0.2s ease;
}
.gallery-cta:hover .gallery-cta__label,
.gallery-cta:focus-visible .gallery-cta__label { color: currentColor; }
.gallery-cta__meta {
  font-size: 0.6rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: color-mix(in srgb, currentColor 38%, transparent);
}
.gallery-cta:focus-visible { outline: none; }
.gallery-cta:focus-visible .gallery-cta__stack {
  outline: 2px solid color-mix(in srgb, var(--soy-green) 45%, transparent);
  outline-offset: 8px;
  border-radius: 12px;
}

@media (max-width: 620px) {
  /* Keep the button in its original spot — to the right of the text, stacked
     vertically — by narrowing the description so it clears the button. */
  .book-header { gap: 1.1rem; align-items: center; }
  .book-header__desc { max-width: 18rem; }
  .gallery-cta { padding: 0; gap: 0.65rem; }
  .gallery-cta__stack { width: 100px; height: 90px; }
  .gallery-cta__frame { width: 70px; height: 70px; }
  .gallery-cta__pic { width: 36px; height: 36px; }
  .gallery-cta__label { font-size: 0.66rem; letter-spacing: 0.22em; }
  .gallery-cta__meta { font-size: 0.56rem; }
}

.book-header__testament {
  font-size: 0.62rem;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: #555;
  margin-bottom: 0.4rem;
}

.book-header__title {
  font-size: clamp(2rem, 7vw, 4rem);
  font-weight: 700;
  color: #f0f0f0;
  letter-spacing: -0.02em;
  line-height: 1;
  margin-bottom: 0.8rem;
}

.book-header__desc {
  font-size: 0.9rem;
  color: #666;
  max-width: 520px;
  line-height: 1.6;
}

.chapter-list {
  border: 1px solid #2a2a2a;
  margin-bottom: 3rem;
}

.ch-row {
  display: grid;
  grid-template-columns: 2rem 1fr;
  gap: 1rem 1.4rem;
  padding: 1rem 1.2rem;
  border-bottom: 1px solid #2a2a2a;
  text-decoration: none;
  color: inherit;
  transition: background 0.12s;
  cursor: pointer;
}

.ch-row:last-child { border-bottom: none; }
.ch-row:hover { background: #222; }

.ch-row__num {
  font-size: 0.72rem;
  font-weight: 600;
  color: #555;
  padding-top: 0.15rem;
  text-align: right;
}

.ch-row__body {}

.ch-row__title {
  font-size: 0.88rem;
  font-weight: 600;
  color: #d8d8d8;
  margin-bottom: 0.2rem;
}

.ch-row__desc {
  font-size: 0.9rem;
  color: #666;
  line-height: 1.5;
}

.ch-row.locked {
  opacity: 0.22;
  pointer-events: none;
  cursor: default;
}

/* ── Chapter reading page ── */
.ch-reading-header {
  margin-bottom: 5rem;
}

.ch-reading-header__label {
  font-size: 0.62rem;
  letter-spacing: 0.35em;
  text-transform: uppercase;
  color: #555;
  margin-bottom: 0.5rem;
}

.ch-reading-header__title {
  font-size: clamp(1.7rem, 5.5vw, 2.8rem);
  font-weight: 700;
  color: #f0f0f0;
  letter-spacing: -0.02em;
  line-height: 1.1;
}

.ch-reading-header__hint {
  margin-top: 0.8rem;
  font-size: 0.78rem;
  color: #444;
  font-style: italic;
}

/* ── Verse groups ── */
.vg {
  position: relative;
  font-family: Georgia, serif;
  font-size: var(--vg-size);
  line-height: var(--vg-lh);
  padding: 0.8rem 1rem 0.8rem 2.4rem;
  margin: 0.1rem 0;
  border-left: 2px solid transparent;
  transition: border-color 0.15s, background 0.15s;
  text-align: justify;
  hyphens: auto;
}

/* All direct-child <p> elements inside a verse group flow as one continuous
   justified paragraph, matching manuscript-cell style. The .vg block itself
   provides text-align:justify and hyphens:auto. Float-wrap ms-block restores
   block display below so the float wrap layout is unaffected. */
.vg > p { display: inline; margin: 0; }

.vg:hover {
  border-left-color: #888;
  background: rgba(255,255,255,0.025);
}

/* Paragraph → family-tree jump: small tree icon just outside the right edge of
   a genealogy-dense .vg, vertically centered; links to soy-agaci.html?p=…
   (those people highlighted). */
.tree-jump {
  position: absolute;
  top: 50%;
  right: -1.75rem;
  transform: translateY(-50%);
  width: 1.35rem;
  height: 1.35rem;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--soy-green);
  opacity: 0.55;
  transition: opacity 0.15s;
}
.tree-jump:hover { opacity: 1; }
.tree-jump svg { width: 100%; height: 100%; }
/* Narrow screens: the page padding is all the room there is — pull the icon
   in a bit so it keeps a clear gap from the screen edge. */
@media (max-width: 700px) {
  .tree-jump { right: -1.4rem; width: 1.15rem; height: 1.15rem; }
}

.n {
  font-family: system-ui, -apple-system, sans-serif;
  font-size: 0.58rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  color: #555;
  vertical-align: super;
  margin-right: 0.3em;
  user-select: none;
}

/* ── Climax verse ── */
.climax {
  text-align: center;
  margin: 4rem -0.5rem;
  padding: 3rem 2rem;
  border-top: 1px solid #2a2a2a;
  border-bottom: 1px solid #2a2a2a;
  cursor: default;
  transition: background 0.2s;
}

.climax:hover {
  background: rgba(255,255,255,0.025);
}

.climax > p {
  font-family: Georgia, serif;
  font-size: var(--climax-size);
  font-style: italic;
  line-height: 1.65;
  color: #e0e0e0;
}

/* ── Artwork section ── */
.artwork-section {
  margin-top: 6rem;
  padding-top: 2rem;
  border-top: 1px solid #2a2a2a;
}

.artwork-section__label {
  font-size: 0.62rem;
  letter-spacing: 0.35em;
  text-transform: uppercase;
  color: #444;
  margin-bottom: 1.6rem;
}

.artwork-item + .artwork-item {
  padding-top: 3rem;
  border-top: 1px solid #222;
}

.artwork-img-wrap {
  position: relative;
  cursor: zoom-in;
  overflow: hidden;
  background: transparent;
  line-height: 0;
}

.artwork-img-wrap img {
  display: block;
  max-width: 100%;
  max-height: 70vh;
  width: auto;
  height: auto;
  margin: 0 auto;
  transition: opacity 0.2s;
}

.artwork-img-wrap:hover img { opacity: 0.88; }

.artwork-zoom-hint {
  position: absolute;
  bottom: 0.7rem;
  right: 0.7rem;
  background: rgba(0, 0, 0, 0.72);
  color: #999;
  font-size: 0.6rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 0.28rem 0.55rem;
  border: 1px solid rgba(255, 255, 255, 0.08);
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.15s;
  line-height: 1;
}

.artwork-img-wrap:hover .artwork-zoom-hint { opacity: 1; }

.artwork-caption-wrap {
  padding-top: 1.2rem;
  padding-bottom: 3rem;
}

.artwork-item:last-child .artwork-caption-wrap {
  padding-bottom: 0;
}

.artwork-title {
  font-size: 1.02rem;
  font-weight: 600;
  color: #d8d8d8;
  margin-bottom: 0.2rem;
}

.artwork-meta {
  font-size: 0.68rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: #555;
  margin-bottom: 1rem;
}

.artwork-relevance {
  font-family: Georgia, serif;
  font-size: 1rem;
  line-height: 1.8;
  color: #777;
  font-style: italic;
}

/* ── Artwork carousel (Instagram-style) ── */
/* A fixed-height region showing one artwork at a time. Desktop: ‹ › arrows in the
   side margins. Mobile: horizontal scroll/swipe. Several carousels can stack down a
   chapter, scrolled through vertically. Inner .artwork-item markup is reused as-is. */
.art-carousel {
  --carousel-h: min(960px, calc(100svh - 8rem - var(--sa-top)));
  --art-w: min(1060px, 90vw);     /* max width of the image + caption box */
  position: relative;
  /* The panel is centred in the viewport, so the space above the title is whatever
     100svh has left over — about 13px on a phone, i.e. inside the status bar. The
     inset has to come out of the height budget as well as being padded for, or the
     panel grows past the viewport and centring pushes the title off the top instead
     of down. On the web --sa-top is 0 and both are no-ops. */
  padding-top: var(--sa-top);
  /* Each carousel fills the screen and centres its content. A light JS snapper
     (artworks.js) nudges it to centre only when it's already nearly there, so it
     never traps ordinary scrolling (e.g. reaching the chapter nav below). */
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  /* Break out wider than the 900px reading column: bigger artworks, plus room for
     the arrows to sit beside the image box rather than on top of the artwork. */
  width: min(1240px, 96vw);
  margin-left: 50%;
  transform: translateX(-50%);
}

.art-carousel__title {
  font-size: 0.72rem;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: #6a6a6a;
  text-align: center;
  margin-bottom: 1.1rem;
}

.art-carousel__track {
  display: flex;
  height: var(--carousel-h);
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;              /* Firefox */
  -webkit-overflow-scrolling: touch;
}
.art-carousel__track::-webkit-scrollbar { display: none; }  /* WebKit */

/* Each slide fills the whole track width and snaps into place */
.art-carousel__track .art-slide {
  flex: 0 0 100%;
  width: 100%;
  box-sizing: border-box;
  height: var(--carousel-h);
  scroll-snap-align: center;
  /* One artwork per swipe: a fast flick can't carry momentum past the next slide.
     (Programmatic dot/arrow jumps disable snap mid-animation — see artworks.js — so
     they can still cross several slides at once.) */
  scroll-snap-stop: always;
  display: flex;
  flex-direction: column;
  padding: 0;
  border-top: none;
}
/* Cancel the stacked-view divider between adjacent items when inside a carousel */
.art-carousel__track .artwork-item + .artwork-item {
  padding-top: 0;
  border-top: none;
}

/* Image area — fills the space above the caption band. align-self:center makes the
   wrap shrink to the image itself, so the "Fullscreen" chip hugs the image corner. */
.art-slide .artwork-img-wrap {
  flex: 1 1 auto;
  min-height: 0;
  align-self: center;
  display: flex;
  align-items: center;
  justify-content: center;
  /* The wrap is taller than the image; its black bands close the slider rather than
     zoom (see gallery.js), so only the artwork itself offers the zoom cursor. */
  cursor: default;
}
.art-slide .artwork-img-wrap img {
  cursor: zoom-in;
  width: auto;
  height: auto;
  max-width: var(--art-w);            /* caps landscape width; portraits cap on height */
  max-height: 100%;                   /* override the stacked-view 70vh cap */
  object-fit: contain;
  margin: 0;
}
/* Hovering must not dim the artwork — only reveal the small Fullscreen indicator */
.art-slide .artwork-img-wrap:hover img { opacity: 1; }

/* Caption band below the image (scrolls internally if the text runs long) */
.art-slide .artwork-caption-wrap {
  flex: 0 0 auto;
  width: 100%;
  max-width: var(--art-w);
  margin: 0 auto;
  box-sizing: border-box;
  max-height: 42%;
  overflow-y: auto;
  padding: 1rem 0.4rem 0.2rem;
  text-align: center;
}
.art-slide .artwork-title    { margin-bottom: 0.15rem; }
.art-slide .artwork-meta     { margin-bottom: 0.55rem; }
.art-slide .artwork-relevance { font-size: 0.9rem; line-height: 1.7; }

/* ‹ › nav arrows: each fills the whole margin between the image and the screen
   edge (a big click target), with the glyph centred in that band. Height/width and
   exact left offset are refined per-slide in JS (positionArrows); these values are
   the pre-JS fallback. */
.art-carousel__nav {
  position: absolute;
  top: 0;                            /* CSS fallback; JS refines to the image box */
  height: 100%;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: none;
  background: transparent;
  color: #b0b0b0;
  font-size: 2.4rem;
  line-height: 1;
  cursor: pointer;
  transition: font-size 0.18s ease, text-shadow 0.18s ease, opacity 0.15s;
}
/* Slightly enlarge the ‹ › and give it a soft glow on hover. The band is
   transparent, so only the glyph itself grows — no background flash. */
.art-carousel__nav:hover {
  font-size: 2.9rem;
  text-shadow: 0 0 12px rgba(0, 0, 0, 0.35);
}
body.theme-night .art-carousel__nav:hover { text-shadow: 0 0 14px rgba(255, 255, 255, 0.5); }
/* Fill the side margin between the image box and the carousel edge (JS widens this
   out to the true screen edge once slide dimensions are known). */
.art-carousel__nav--prev { left: 0; width: calc(50% - var(--art-w) / 2); }
.art-carousel__nav--next { right: 0; width: calc(50% - var(--art-w) / 2); }
.art-carousel__nav[disabled] { opacity: 0; pointer-events: none; }

/* Position dots */
.art-carousel__dots {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.45rem;
  margin-top: 1rem;
  color: #888;
}
.art-carousel__dot {
  width: 7px;
  height: 7px;
  padding: 0;
  border: none;
  border-radius: 50%;
  /* A <button> does not inherit `color`; without this it stays the UA default
     (black), so `currentColor` — and the dot — vanished on dark backgrounds.
     Inherit the theme-neutral #888 set on .art-carousel__dots above. */
  color: inherit;
  background: currentColor;
  opacity: 0.35;
  cursor: pointer;
  transition: opacity 0.15s, transform 0.15s;
}
.art-carousel__dot.is-active { opacity: 0.9; transform: scale(1.25); }

/* The way out (built by artworks.js). A centred carousel fills the screen with no
   visible way past it; this is it. Taken out of flow so it costs the panel no height —
   the 100svh budget above is already tight — and shown only while the panel is framing
   the viewport, so it is not permanent chrome on every artwork. */
.art-carousel__exit {
  /* Fixed, so it sits in the corner of the SCREEN: the panel is inset by the reading
     column's padding on a phone, and an absolute corner floated ~32px inland. Safe
     because at most one carousel can be centred at a time — they are 100svh apart and
     the visibility band is 15% of that — so the buttons never stack in this one spot.
     (Desktop keeps `transform: translateX(-50%)` on the panel, which makes it the
     containing block; there the corner is the panel's, a couple of dozen px in.)

     Bottom LEFT: the panel's bottom strip belongs to the dots, and a tap target
     centred there covers them and takes their taps. The insets are the only offset —
     the glyph's own padding is what keeps it off the edge. */
  position: fixed;
  left: var(--sa-left);
  bottom: var(--sa-bottom);
  width: 48px;                       /* a thumb, not a glyph */
  height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: none;
  background: transparent;
  /* The ‹ › arrows' colour, not the title's grey, and — like them — the same in every
     theme: this is chrome over artwork, so it answers to the dark glass the arrows
     already established rather than to the page's text colour. The title's #6a6a6a
     dropped to #444 on the night theme, which on that black is not there at all. */
  color: #b0b0b0;
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s ease, filter 0.18s ease, transform 0.18s ease;
  /* Over the ‹ › bands (5) and the page, under the ⋮ toolbar (800) and both artwork
     overlays (850 / 900) — a fullscreen artwork must not have a stray chevron on it. */
  z-index: 700;
}
.art-carousel__exit.is-visible { opacity: 1; pointer-events: auto; }
/* Grow-and-glow on hover, the same gesture .art-carousel__nav makes — drop-shadow
   rather than text-shadow because this chevron is drawn, not typed. */
.art-carousel__exit:hover {
  transform: scale(1.15);
  filter: drop-shadow(0 0 12px rgba(0, 0, 0, 0.35));
}
body.theme-night .art-carousel__exit:hover { filter: drop-shadow(0 0 14px rgba(255, 255, 255, 0.5)); }
/* A drawn chevron rather than a glyph: 2.6px of stroke carries the same weight as the
   arrows' 2.4rem ‹ ›, where the 1.5px hairline it started as read as a smudge. */
.art-carousel__exit::before {
  content: '';
  width: 16px;
  height: 16px;
  border-right: 2.6px solid currentColor;
  border-bottom: 2.6px solid currentColor;
  transform: translateY(-4px) rotate(45deg);
}

/* Mobile: no arrows — swipe/scroll instead; dots remain */
@media (max-width: 600px) {
  .art-carousel {
    --carousel-h: calc(100svh - 5.5rem - var(--sa-top));
    --art-w: 100%;
    width: auto;
    margin: 0;
    transform: none;
  }
  .art-carousel__nav { display: none; }
}

/* Theme tweaks for the carousel chrome (arrows/dots keep the dark-glass look) */
body.theme-night   .art-carousel__title { color: #444; }
body.theme-paper   .art-carousel__title { color: #999; }

/* ── Fullscreen overlay ── */
.artwork-overlay {
  position: fixed;
  inset: 0;
  background: #000;
  z-index: 900;
  display: flex;
  flex-direction: column;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.22s;
  overflow: hidden;
}

.artwork-overlay.show {
  opacity: 1;
  pointer-events: auto;
}

.artwork-overlay__close {
  position: fixed;
  top: calc(1.2rem + var(--sa-top));
  right: calc(1.5rem + var(--sa-right));
  width: 2.4rem;
  height: 2.4rem;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.55);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 50%;
  color: #ccc;
  font-size: 1.3rem;
  cursor: pointer;
  line-height: 1;
  padding: 0;
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  transition: color 0.15s, background 0.15s;
  z-index: 901;
}

.artwork-overlay__close:hover { color: #fff; background: rgba(0, 0, 0, 0.75); }

/* Image area — fills all space above the caption bar */
.artwork-overlay__inner {
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.artwork-overlay__inner.zoomed { cursor: grab; }
.artwork-overlay__inner.grabbing { cursor: grabbing; }

.artwork-overlay__img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  display: block;
  touch-action: none;
  transform-origin: center center;
  will-change: transform;
}

/* Info bar below the image — wraps to multiple rows when the text is long */
.artwork-overlay__caption {
  flex-shrink: 0;
  min-height: 2.4rem;
  max-height: 28vh;
  display: flex;
  align-items: center;
  justify-content: center;
  /* The overlay is `inset: 0`, so its caption is the one piece of chrome sitting on the
     bottom edge — on a gesture-navigation phone the second line lands under the pill. */
  padding: 0.55rem 1.5rem calc(0.55rem + var(--sa-bottom));
  border-top: 1px solid #111;
  font-size: 0.58rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: #555;
  text-align: center;
  line-height: 1.6;
  overflow-y: auto;
}

/* ── Inline verse note (collapsible) ── */
/* Colours derive from the inherited text colour so the box adapts to any theme */
.vg-note {
  clear: both; /* always below any floated images in the same .vg */
  margin-top: 0.5rem;
  padding-top: 0.5rem;
  border-top: 1px solid color-mix(in srgb, currentColor 13%, transparent);
}

.vg-note > summary {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.3rem 0;
  font-family: system-ui, -apple-system, sans-serif;
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: inherit;
  opacity: 0.38;
  cursor: pointer;
  list-style: none;
  user-select: none;
  transition: opacity 0.15s;
}

.vg-note > summary::-webkit-details-marker { display: none; }

.vg-note > summary::before {
  content: '▶';
  font-size: 0.45rem;
  transition: transform 0.2s;
}

.vg-note[open] > summary::before {
  transform: rotate(90deg);
}

.vg-note > summary:hover { opacity: 0.7; }

.vg-note__body {
  padding: 0.5rem 0 0.2rem;
  font-family: system-ui, -apple-system, sans-serif;
  font-size: 0.9rem;
  line-height: 1.65;
  color: inherit;
  opacity: 0.6;
}

.vg-note__body p { margin: 0; }

/* ── Page transitions (default: slide) ── */
@keyframes pg-in-right  { from { transform: translateX( 55px); opacity: 0; } to { transform: translateX(0); opacity: 1; } }
@keyframes pg-in-left   { from { transform: translateX(-55px); opacity: 0; } to { transform: translateX(0); opacity: 1; } }
@keyframes pg-out-left  { from { transform: translateX(0); opacity: 1; } to { transform: translateX(-55px); opacity: 0; } }
@keyframes pg-out-right { from { transform: translateX(0); opacity: 1; } to { transform: translateX( 55px); opacity: 0; } }

.page-enter-right { animation: pg-in-right  0.34s cubic-bezier(0.22,1,0.36,1) forwards; }
.page-enter-left  { animation: pg-in-left   0.34s cubic-bezier(0.22,1,0.36,1) forwards; }

.page-exit-left   { animation: pg-out-left  0.28s cubic-bezier(0.4,0,1,1) forwards; pointer-events: none; }
.page-exit-right  { animation: pg-out-right 0.28s cubic-bezier(0.4,0,1,1) forwards; pointer-events: none; }

/* ── Bottom chapter navigation ── */
.ch-nav-bottom {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin: 4rem 0 1rem;
  padding-top: 2rem;
  border-top: 1px solid #2a2a2a;
}

.ch-nav-bottom a {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-family: system-ui, -apple-system, sans-serif;
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #555;
  transition: color 0.15s;
  text-decoration: none;
}

.ch-nav-bottom a:hover { color: #d8d8d8; }

.ch-nav-bottom__arrow {
  /* Masked minimalist arrow; font-size:0 hides the literal ←/→ glyph in the markup.
     color (currentColor) is still honoured by every per-theme override below. */
  font-size: 0;
  display: inline-block;
  /* Matches --arrow-icon's 13:24 viewBox — see .nav-arrow. */
  width: 0.62rem;
  height: 1.15rem;
  color: #444;
  background-color: currentColor;
  -webkit-mask: var(--arrow-icon) center / contain no-repeat;
          mask: var(--arrow-icon) center / contain no-repeat;
}
/* Arrow that leads its link (previous / back) points left */
.ch-nav-bottom a > .ch-nav-bottom__arrow:first-child { transform: scaleX(-1); }

.ch-nav-bottom__label {
  font-size: 0.62rem;
  color: #3a3a3a;
  display: block;
  margin-bottom: 0.1rem;
}

/* ── Font size levels (tema-bağımsız):
     0 = küçük (varsayılan) · 1 = orta · 2 = büyük.
     Reading text moves through the --vg/--ms/--climax variables; secondary text
     (captions, meta, chapter rows) keeps its own per-level rules below.
     On DESKTOP level 1 leaves the reading column alone — 1.38rem is already a
     comfortable measure there and the level exists to grow the captions around it.
     On a PHONE that left three buttons driving two sizes, which is what made the
     control read as broken, so the 600px block gives level 1 a real step. ── */
body.fs-2 {
  --vg-size: clamp(1.35rem, 3vw + 0.6rem, 1.7rem);
  --ms-size: clamp(1.35rem, 3vw + 0.6rem, 1.7rem);
  --climax-size: clamp(1.4rem, 3.4vw, 1.8rem);
}

body.fs-1 .artwork-relevance { font-size: 1.12rem; }
body.fs-1 .artwork-meta     { font-size: 0.78rem; }
body.fs-1 .artwork-title    { font-size: 1.12rem; }
body.fs-1 .ch-row__desc     { font-size: 1rem; }
body.fs-1 .book-card__desc  { font-size: 1.05rem; }
body.fs-1 .vg-note__body    { font-size: 1rem; }

body.fs-2 .artwork-relevance{ font-size: 1.24rem; }
body.fs-2 .artwork-meta     { font-size: 0.9rem; }
body.fs-2 .artwork-title    { font-size: 1.24rem; }
body.fs-2 .ch-row__title    { font-size: 1.18rem; }
body.fs-2 .ch-row__desc     { font-size: 1.12rem; }
body.fs-2 .book-card__desc  { font-size: 1.16rem; }
body.fs-2 .vg-note__body    { font-size: 1.1rem; }

/* Info cards. Their text is the one body of reading matter the levels never reached —
   the trigger in the column, and everything inside the card it opens.
   Reaches only the class-styled text. A card's image captions, and the free paragraphs
   in chapters 12/36/44, carry font-size as an inline style attribute straight from the
   content YAML (InfoBox.astro), and an inline style beats any rule here. Scaling those
   too means teaching InfoBox.astro to emit calc(… * var(--ib-scale)) and allowing the
   resulting attribute difference in verify-fidelity.ts. */
body.fs-1 .ib-trigger__text { font-size: 0.94rem; }
body.fs-1 .ib-card__head h3 { font-size: 1.08rem; }
body.fs-1 .ib-card__intro   { font-size: 0.99rem; }
body.fs-1 .ib-entry__tag    { font-size: 0.76rem; }
body.fs-1 .ib-entry p       { font-size: 0.98rem; }

body.fs-2 .ib-trigger__text { font-size: 1.06rem; }
body.fs-2 .ib-card__head h3 { font-size: 1.2rem; }
body.fs-2 .ib-card__intro   { font-size: 1.11rem; }
body.fs-2 .ib-entry__tag    { font-size: 0.84rem; }
body.fs-2 .ib-entry p       { font-size: 1.1rem; }

/* ── Font size toggle button ── */
.fs-toggle {
  position: fixed;
  top: calc(0.85rem + var(--sa-top));
  /* Sit close to the screen edge so the collapsed ⋮ clears the text column on
     narrow screens (at a wider inset its box overlapped the ends of text lines). */
  right: calc(0.75rem + var(--sa-right));
  display: flex;
  align-items: center;
  z-index: 800;
  background: #111;
  border: 1px solid #2a2a2a;
  /* The buttons' own padding used to be the whole box. At the larger glyph sizes below
     that left them flush against the border. */
  padding: 0.1rem 0.15rem;
  user-select: none;
}

.fs-btn {
  background: none;
  border: none;
  color: #444;
  cursor: pointer;
  padding: 0.42rem 0.6rem;
  line-height: 1;
  font-family: Georgia, serif;
  transition: color 0.15s, background 0.15s;
  display: flex;
  align-items: center;
}

.fs-btn:hover  { color: #aaa; background: #1a1a1a; }
.fs-btn.active { color: #d8d8d8; }

.fs-divider {
  width: 1px;
  height: 1.15rem;   /* spans the taller button row */
  background: #2a2a2a;
}

/* ── Font toggle collapse ── */
.fs-main-btns {
  display: flex;
  align-items: center;
  overflow: hidden;
  max-width: 300px;
  opacity: 1;
  transition: max-width 0.24s ease, opacity 0.18s ease;
}

.fs-toggle.scrolled .fs-main-btns {
  max-width: 0;
  opacity: 0;
  pointer-events: none;
}

.fs-btn[data-theme-quick] {
  font-size: 1.1rem;
  padding: 0.34rem 0.7rem;
  letter-spacing: 0;
}

.fs-settings-btn {
  /* Was an inline cssText on the element in artworks.js, which no stylesheet rule could
     reach past. Every sibling's sizing already lives here. */
  font-size: 1.2rem;
  letter-spacing: 0;
  padding: 0.42rem 0.62rem;
  transition: color 0.15s, background 0.15s, opacity 0.2s;
}
/* Collapsed toolbar: the ⋮ is the only affordance left, so lift it out of the very
   dim idle grey used for the expanded icon row — otherwise it's near-invisible on
   the dark themes. (Light themes set their own readable .fs-btn colour already.) */
body:not([class*="theme-"]) .fs-toggle.scrolled .fs-settings-btn,
body.theme-night .fs-toggle.scrolled .fs-settings-btn {
  color: #999;
}

/* ── The account avatar (Phase 9) ──
   Leftmost in .fs-main-btns, so it collapses with the theme buttons on scroll and the
   ⋮ panel's own account entry takes over. Signed out it is dimmed but still live: the
   greying says "not signed in", and the button is how you stop being that. */
.fs-account-btn { padding: 0.42rem 0.62rem; color: #8a8a8a; }
.fs-account-btn svg { display: block; }
.fs-account-btn:hover { color: #d8d8d8; background: #1a1a1a; }
.fs-account-btn--out { opacity: 0.4; }
.fs-account-btn--out:hover { opacity: 0.75; }
.settings-tree--account { --jump-tint: #7f93b4; }

/* ── What a trial does not include ──
   The gallery and the family tree, wherever they are offered: the two ⋮ panel entries,
   the chapter index's gallery poster, and the inline tree-jump icons in the 19 genealogy
   chapters. Greyed and inert — no padlock. The real refusal is in middleware.ts; this is
   only the courtesy of saying so before the tap.

   Named element by element rather than as a bare [data-locked] because the chapter rows
   below carry the same attribute and must NOT be inert. */
.settings-tree[data-locked='true'],
.gallery-cta[data-locked='true'],
.tree-jump[data-locked='true'] {
  opacity: 0.38;
  pointer-events: none;
  cursor: default;
}

/* The chapter rows past the free sample. Dimmed and nothing else: tapping a locked
   chapter is how a reader reaches the purchase page on the web and the native purchase
   screen in the app, so `pointer-events: none` here would take away the only route to
   buying the thing they just asked for. Both clients set the attribute from the same
   applyOwned() in artworks.js. */
a.ch-row[data-locked='true'] {
  opacity: 0.45;
}

/* The chapter rows a paused or interrupted download has not finished. App only — the web
   never sets `data-present`, so this never matches there.

   Same 0.45 and the same tappability as the locked rows above, deliberately: a row can be
   both at once (the free sample past chapter 2, mid-download) and two rules agreeing on
   one value is what stops that reading as a third, darker state. No glyph here either.

   Tapping still has somewhere to go, and it is not the paywall — Reader.tsx's gate sends
   an entitled reader whose chapter is absent to the "not on this device" page, which says
   the download lives in the library and links back to the shelf. */
a.ch-row[data-absent='true'] {
  opacity: 0.45;
}

/* ── Settings panel ── */
.settings-panel {
  display: none;
  position: fixed;
  /* Clears the bottom edge of .fs-toggle: 0.85rem of offset plus the ~2.36rem the
     larger buttons grew the bar to, measured. */
  top: calc(3.4rem + var(--sa-top));
  right: calc(1.5rem + var(--sa-right));
  width: 260px;
  background: #0f0f0f;
  border: 1px solid #2a2a2a;
  z-index: 799;
  padding: 1.1rem;
  animation: panel-in 0.18s ease;
}
.settings-panel.open { display: block; }
@keyframes panel-in {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: translateY(0); }
}
.settings-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 0.9rem; padding-bottom: 0.8rem; border-bottom: 1px solid #1e1e1e;
}
.settings-title {
  font-size: 0.62rem; letter-spacing: 0.25em; text-transform: uppercase; color: #444;
}
.settings-close {
  background: none; border: none; color: #3a3a3a; cursor: pointer;
  font-size: 0.8rem; padding: 0.1rem 0.3rem; transition: color 0.15s;
}
.settings-close:hover { color: #aaa; }
.settings-grid {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.5rem;
}
.theme-card {
  background: none; border: 1px solid #222; cursor: pointer;
  padding: 0; transition: border-color 0.15s; text-align: left;
}
.theme-card:hover  { border-color: #555; }
.theme-card.active { border-color: #888; }

/* Font-size selector (theme-aware via surface vars) */
.settings-section { margin-top: 1.1rem; }
.settings-subtitle {
  font-size: 0.6rem; letter-spacing: 0.18em; text-transform: uppercase;
  color: inherit; opacity: 0.45; margin-bottom: 0.6rem;
}
.fontsize-row { display: flex; gap: 0.5rem; }
.fontsize-btn {
  flex: 1;
  background: transparent;
  border: 1px solid var(--surface-border);
  color: inherit;
  opacity: 0.5;
  cursor: pointer;
  padding: 0.5rem 0;
  border-radius: 2px;
  font-weight: 600;
  line-height: 1;
  transition: border-color 0.15s, opacity 0.15s, background 0.15s;
}
.fontsize-btn--0 { font-size: 0.85rem; }
.fontsize-btn--1 { font-size: 1.05rem; }
.fontsize-btn--2 { font-size: 1.3rem; }
.fontsize-btn:hover { opacity: 0.8; border-color: color-mix(in srgb, currentColor 30%, transparent); }
.fontsize-btn.active { opacity: 1; border-color: color-mix(in srgb, currentColor 45%, transparent); background: var(--hover-bg); }
/* Jump-out links at the top of the Görünüm panel: the family tree, and the gallery
   beside it. One shape, tinted per destination through --jump-tint. */
.settings-tree {
  --jump-tint: var(--soy-green);
  display: flex; align-items: center; gap: 0.6rem;
  width: 100%;
  background: color-mix(in srgb, var(--jump-tint) 8%, transparent);
  border: 1px solid color-mix(in srgb, var(--jump-tint) 40%, transparent);
  color: var(--jump-tint); opacity: 0.95;
  text-decoration: none;
  padding: 0.55rem 0.7rem;
  border-radius: 2px;
  font-size: 0.62rem; letter-spacing: 0.14em; text-transform: uppercase;
  transition: border-color 0.15s, opacity 0.15s, background 0.15s;
}
.settings-tree:hover { opacity: 1; border-color: color-mix(in srgb, var(--jump-tint) 65%, transparent); background: color-mix(in srgb, var(--jump-tint) 15%, transparent); }
.settings-tree__icon { flex-shrink: 0; }
/* Gilt frame rather than the tree's green, so the two read as different places. */
.settings-tree--gallery { --jump-tint: #a8905e; }
.settings-section--tree { margin: 0.85rem 0 1.15rem; }
.settings-section--tree + .settings-section--tree { margin-top: -0.7rem; }

/* Prev/next page navigation at the top of the Görünüm panel */
.settings-nav { display: flex; gap: 0.5rem; margin-top: 0.9rem; }
.settings-nav__btn {
  flex: 1;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--surface-border);
  color: inherit; opacity: 0.6;
  text-decoration: none;
  padding: 0.3rem 0;
  border-radius: 2px;
  font-size: 1.2rem; line-height: 1; font-family: Georgia, serif;
  transition: border-color 0.15s, opacity 0.15s, background 0.15s;
}
.settings-nav__btn:hover { opacity: 1; border-color: color-mix(in srgb, currentColor 40%, transparent); background: var(--hover-bg); }
/* Current chapter label between the ‹ › buttons — frames the row as chapter nav */
.settings-nav__current {
  flex: 1;
  display: flex; align-items: center; justify-content: center;
  font-size: 0.82rem; letter-spacing: 0.04em;
  opacity: 0.85; text-align: center; white-space: nowrap;
  user-select: none;
}
.theme-preview {
  width: 100%; height: 50px; padding: 8px;
  display: flex; flex-direction: column; justify-content: center;
}
.theme-name {
  font-size: 0.58rem; letter-spacing: 0.08em; text-transform: uppercase;
  color: #444; padding: 0.28rem 0.4rem; border-top: 1px solid #1a1a1a;
  text-align: center;
}
.theme-card.active .theme-name { color: #aaa; }
.theme-card:hover .theme-name  { color: #777; }

/* ── Themes: Light ── */
body.theme-light { background: #f5f5f0; color: #1a1a1a; }
body.theme-light .nav              { border-bottom-color: #ddd; }
body.theme-light .nav a            { color: #999; }
body.theme-light .nav a:hover      { color: #1a1a1a; }
body.theme-light .vg               { color: #1a1a1a; }
body.theme-light .vg:hover         { background: rgba(0,0,0,0.03); border-left-color: #bbb; }
body.theme-light .n                { color: #ccc; }
body.theme-light .climax           { border-color: #ddd; }
body.theme-light .climax > p       { color: #1a1a1a; }
body.theme-light .climax:hover     { background: rgba(0,0,0,0.02); }
body.theme-light .artwork-section  { border-top-color: #ddd; }
body.theme-light .artwork-section__label { color: #bbb; }
body.theme-light .artwork-title    { color: #1a1a1a; }
body.theme-light .artwork-meta     { color: #aaa; }
body.theme-light .artwork-relevance{ color: #555; }
body.theme-light .artwork-item + .artwork-item { border-top-color: #eee; }
body.theme-light .artwork-zoom-hint { background: rgba(255,255,255,0.85); color: #666; border-color: rgba(0,0,0,0.1); }
body.theme-light .ch-nav-bottom    { border-top-color: #ddd; }
body.theme-light .ch-nav-bottom a  { color: #aaa; }
body.theme-light .ch-nav-bottom a:hover { color: #1a1a1a; }
body.theme-light .ch-nav-bottom__arrow  { color: #ccc; }
body.theme-light .ch-nav-bottom__label  { color: #ccc; }
body.theme-light .ch-nav-bottom__num    { color: #aaa; }
body.theme-light .ch-reading-header__label { color: #bbb; }
body.theme-light .ch-reading-header__title { color: #111; }
body.theme-light .book-card        { background: #f5f5f0; }
body.theme-light .book-card:hover  { background: #ededea; }
body.theme-light .book-grid        { background: #ddd; border-color: #ddd; }
body.theme-light .book-card__name  { color: #111; }
body.theme-light .book-card__desc  { color: #777; }
body.theme-light .book-card__testament { color: #bbb; }
body.theme-light .book-card__chapters  { color: #bbb; }
body.theme-light .chapter-list     { border-color: #ddd; }
body.theme-light .ch-row           { border-bottom-color: #ddd; }
body.theme-light .ch-row:hover     { background: #ededea; }
body.theme-light .ch-row__num      { color: #bbb; }
body.theme-light .ch-row__title    { color: #1a1a1a; }
body.theme-light .ch-row__desc     { color: #999; }
body.theme-light .section-label    { border-bottom-color: #ddd; color: #bbb; }
body.theme-light .fs-toggle        { background: #f0f0ec; border-color: #ddd; }
body.theme-light .fs-btn           { color: #bbb; }
body.theme-light .fs-btn:hover     { color: #1a1a1a; background: #e8e8e4; }
body.theme-light .fs-btn.active    { color: #1a1a1a; }
body.theme-light .fs-divider       { background: #ddd; }
body.theme-light .settings-panel   { background: #f0f0ec; border-color: #ddd; }
body.theme-light .settings-head    { border-bottom-color: #e0e0d8; }
body.theme-light .settings-title   { color: #bbb; }
body.theme-light .settings-close   { color: #ccc; }
body.theme-light .settings-close:hover { color: #1a1a1a; }
body.theme-light .theme-card       { border-color: #e0e0d8; }
body.theme-light .theme-card:hover { border-color: #aaa; }
body.theme-light .theme-name       { color: #bbb; border-top-color: #e0e0d8; }
body.theme-light .theme-card.active .theme-name { color: #1a1a1a; }

/* ── Themes: Night ── */
/* Pure-black theme. Text tiers are lifted for legibility on #000 while keeping the
   hierarchy: primary reading text ~#dcdcdc, titles ~#d4d4d4, secondary/meta ~#8c–a2,
   verse numbers/labels ~#6f–70, faint chrome (idle nav, dividers) darker still. */
body.theme-night { background: #000; color: #dcdcdc; --surface: #0b0b0b; --surface-border: #1a1a1a; --hover-bg: rgba(255, 255, 255, 0.02); }
body.theme-night .nav              { border-bottom-color: #111; }
body.theme-night .nav a            { color: #6a6a6a; }
body.theme-night .nav a:hover      { color: #eaeaea; }
body.theme-night .vg:hover         { background: rgba(255,255,255,0.015); border-left-color: #444; }
body.theme-night .n                { color: #707070; }
body.theme-night .climax           { border-color: #111; }
body.theme-night .climax > p       { color: #ececec; }
body.theme-night .artwork-section  { border-top-color: #111; }
body.theme-night .artwork-section__label { color: #555; }
body.theme-night .artwork-title    { color: #d4d4d4; }
body.theme-night .artwork-meta     { color: #8c8c8c; }
body.theme-night .artwork-relevance{ color: #a2a2a2; }
body.theme-night .artwork-item + .artwork-item { border-top-color: #111; }
body.theme-night .ch-nav-bottom    { border-top-color: #111; }
body.theme-night .ch-nav-bottom a  { color: #6a6a6a; }
body.theme-night .ch-nav-bottom a:hover { color: #eaeaea; }
body.theme-night .ch-nav-bottom__arrow  { color: #555; }
body.theme-night .ch-nav-bottom__num    { color: #7a7a7a; }
body.theme-night .ch-reading-header__label { color: #6f6f6f; }
body.theme-night .ch-reading-header__title { color: #e4e4e4; }
body.theme-night .book-card        { background: #000; }
body.theme-night .book-card:hover  { background: #080808; }
body.theme-night .book-grid        { background: #0a0a0a; border-color: #0a0a0a; }
body.theme-night .book-card__name  { color: #d4d4d4; }
body.theme-night .book-card__desc  { color: #909090; }
body.theme-night .chapter-list     { border-color: #111; }
body.theme-night .ch-row           { border-bottom-color: #111; }
body.theme-night .ch-row:hover     { background: #060606; }
body.theme-night .ch-row__title    { color: #d4d4d4; }
body.theme-night .ch-row__desc     { color: #909090; }

/* ── Themes: Paper ── */
body.theme-paper { background: #fdfaf0; color: #1c1c1c; --surface: #f5f2e4; --surface-border: #e0dcd0; --hover-bg: rgba(0, 0, 0, 0.03); }
body.theme-paper .nav              { border-bottom-color: #e0dcd0; }
body.theme-paper .nav a            { color: #aaa; font-family: Georgia, serif; }
body.theme-paper .nav a:hover      { color: #1c1c1c; }
body.theme-paper .vg               { color: #1c1c1c; font-family: Georgia, serif; }
body.theme-paper .vg:hover         { background: rgba(0,0,0,0.02); border-left-color: #ccc; }
body.theme-paper .n                { color: #d0ccc0; }
body.theme-paper .climax           { border-color: #e0dcd0; }
body.theme-paper .climax > p       { color: #1c1c1c; font-family: Georgia, serif; }
body.theme-paper .climax:hover     { background: rgba(0,0,0,0.015); }
body.theme-paper .artwork-section  { border-top-color: #e0dcd0; }
body.theme-paper .artwork-section__label { color: #ccc; }
body.theme-paper .artwork-title    { color: #1c1c1c; }
body.theme-paper .artwork-meta     { color: #bbb; }
body.theme-paper .artwork-relevance{ color: #555; font-family: Georgia, serif; }
body.theme-paper .artwork-item + .artwork-item { border-top-color: #e8e4d8; }
body.theme-paper .ch-nav-bottom    { border-top-color: #e0dcd0; }
body.theme-paper .ch-nav-bottom a  { color: #bbb; }
body.theme-paper .ch-nav-bottom a:hover { color: #1c1c1c; }
body.theme-paper .ch-nav-bottom__num { color: #bbb; }
body.theme-paper .ch-reading-header__label { color: #ccc; }
body.theme-paper .ch-reading-header__title { color: #111; }
body.theme-paper .page-heading,
body.theme-paper .book-header__title { color: #111; }
body.theme-paper .book-card        { background: #fdfaf0; }
body.theme-paper .book-card:hover  { background: #f5f2e4; }
body.theme-paper .book-grid        { background: #e0dcd0; border-color: #e0dcd0; }
body.theme-paper .book-card__name  { color: #111; font-family: Georgia, serif; }
body.theme-paper .book-card__desc  { color: #888; font-family: Georgia, serif; }
body.theme-paper .chapter-list     { border-color: #e0dcd0; }
body.theme-paper .ch-row           { border-bottom-color: #e0dcd0; }
body.theme-paper .ch-row:hover     { background: #f5f2e4; }
body.theme-paper .ch-row__title    { color: #1c1c1c; }
body.theme-paper .ch-row__desc     { color: #999; }
body.theme-paper .fs-toggle        { background: #f5f2e4; border-color: #e0dcd0; }
body.theme-paper .fs-btn           { color: #ccc; }
body.theme-paper .fs-btn:hover     { color: #1c1c1c; background: #eceae0; }
body.theme-paper .fs-btn.active    { color: #1c1c1c; }
body.theme-paper .fs-divider       { background: #e0dcd0; }
body.theme-paper .settings-panel   { background: #f5f2e4; border-color: #e0dcd0; }
body.theme-paper .settings-head    { border-bottom-color: #e0dcd0; }
body.theme-paper .settings-title   { color: #ccc; }
body.theme-paper .theme-name       { color: #ccc; border-top-color: #e0dcd0; }
body.theme-paper .theme-card       { border-color: #e0dcd0; }
body.theme-paper .theme-card.active .theme-name { color: #1c1c1c; }

.ch-nav-bottom__num {
  font-size: 1.6rem;
  font-family: Georgia, serif;
  color: #555;
  line-height: 1;
  transition: color 0.15s;
}

.ch-nav-bottom a:hover .ch-nav-bottom__num { color: #d8d8d8; }
.ch-nav-bottom a:hover .ch-nav-bottom__arrow { color: #d8d8d8; }

/* ── Manuscript cell: L-shaped historiated image ──────────────────────────
   The miniature is split into two pieces that reassemble into one rectangle:
   a tall UPRIGHT and a wide FOOT. Both float left at the very top of the flow,
   with the foot cleared flush beneath the upright, so together they form an L.
   ONE continuous block of text then flows around that L: a WIDE column beside
   the narrow upright, a NARROW column beside the wide foot, then FULL WIDTH
   once it clears both. Because the two pieces are sized from a single width and
   keep their natural ratio, the seam is pixel-perfect at EVERY viewport — the
   wrap is fluid, so it needs no breakpoints and never falls back to a band.

   Modular: each cell only sets two custom properties —
     --hist-w     : the upright's rendered width. A clamp() makes it responsive
                    on its own (floor so it never vanishes on phones, ceiling so
                    it never dominates on wide screens) — hence zero media queries.
     --hist-ratio : foot natural width ÷ upright natural width. The foot derives
                    its width from this, which is what keeps the seam gapless.
   The text must be a single .ms-block (verse numbers stay inline); splitting it
   into separate blocks — or placing the foot mid-text — is what breaks the wrap,
   since a float only governs the content that follows it. */
.vg--float-wrap {
  --hist-w: clamp(96px, 25%, 230px);
  --hist-ratio: 1.9314;            /* 1576 / 816 */
  display: flow-root;              /* BFC contains the floats */
}

.hist-float {
  float: left;
  clear: left;                     /* foot stacks flush under the upright */
  display: block;
  margin: 0 0.9em 0 0;             /* gutter to the text; flush bottom = no seam gap */
  cursor: zoom-in;
}
.hist-float--upright { width: var(--hist-w); }
.hist-float--foot {
  width: calc(var(--hist-w) * var(--hist-ratio));
  margin-bottom: 0.5em;            /* breathing room before text drops full width */
}

/* Single miniature (no L) — one floated image the text wraps around. Same
   mechanics, just set --hist-w on the cell to keep it modestly sized. */
.hist-float--solo {
  width: var(--hist-w);
  margin-bottom: 0.4em;
}

/* Right-aligned float: image hugs the right edge, text wraps down its left. */
.hist-float--right {
  float: right;
  clear: right;
  margin: 0 0 0.5em 1.1em;
}

/* Circular float: a square image masked to a circle; text follows the curve
   via shape-outside (one side only — a centred all-around wrap isn't possible
   with floats). The crop is already square, so 50% gives a clean disc. */
.hist-float--circle {
  width: var(--hist-w);
  height: var(--hist-w);
  border-radius: 50%;
  object-fit: cover;
  margin: 0.2em 0 0.5em 0;
  shape-outside: circle(50%);
  shape-margin: 0.85em;
}

/* Circle pinned to the top-right and nudged so it bleeds slightly past the
   reading column's right edge — a deliberate "spilling" design accent.
   transform shifts only the visuals; the text still wraps the float's left
   side at its original box, leaving the spill on the outer (right) side. */
.hist-float--circle.hist-float--bleed-tr {
  float: right;
  clear: right;
  margin: 0.2em 0 0.5em 0.85em;
  transform: translate(1.7rem, -1.1rem);
}
@media (max-width: 600px) {
  /* Cap the doubled circle so it can't exceed the phone column. */
  .hist-float--circle.hist-float--bleed-tr {
    --hist-w: clamp(180px, 62%, 300px);
    transform: translate(0.6rem, -0.5rem);
  }
}


.vg--float-wrap .ms-block {
  display: block;
  margin: 0;
  text-align: justify;
  hyphens: auto;
  /* Stated rather than inherited from .vg, because on a phone a manuscript cell
     reads a step smaller than a plain group. --ms-size carries that step through
     every fs level; see the reading-size block on `body`. */
  font-size: var(--ms-size);
  line-height: var(--ms-lh);
}

/* ── Manuscript frame: 4-piece illuminated border (yaradilis-18) ──
   The source illuminated page is cut into 4 crops that reassemble AROUND the
   verse text, faithful to the original page:
     1 top miniature  ┐ stack flush (clear:left) into the top-left square,
     2 historiated init┘ both at --frame-w;
     3 side ornament    continues down the left margin, narrower;
     the text is ONE .ms-block that wraps to the RIGHT of and BELOW the stack;
     4 foot border      clears below everything, full width.
   Float-only — no grid, no JS — so it stays fluid at every width. */
.vg--ms-frame {
  --frame-w: clamp(136px, 40%, 272px);
  --frame-side-ratio: 0.36;            /* piece 3 width ÷ frame width (side ornament, ×1.2) */
  display: flow-root;                  /* BFC contains the floats */
}
.ms-frame__piece {
  float: left;
  clear: left;                         /* pieces stack flush down the margin */
  display: block;
  margin: 0 0.9em 0 0;                 /* gutter to the text */
}
.ms-frame__top,
.ms-frame__initial { width: calc(var(--frame-w) * 1.2); }   /* 1 + 2 reform the square — main illumination, ×1.2 */
.ms-frame__side {
  width: calc(var(--frame-w) * var(--frame-side-ratio));
  margin-bottom: 0;                    /* touch the foot below — no gap */
}
/* Bottom border band: scaled to half (from full column width down to --frame-w)
   and floated into the same left column as the other pieces. So the two-part
   illumination, the side ornament and the foot stack flush into ONE continuous
   illuminated strip that the text wraps to the right of — the foot sits directly
   under the side ornament (touch), not below the text. (The foot is moved before
   the .ms-block in the HTML so the float can rise to meet the side rather than
   clearing below the full text.) */
.ms-frame__foot {
  float: left;
  clear: left;
  display: block;
  width: var(--frame-w);
  margin: 0 0.9em 0 0;                 /* right gutter to text; flush vertically */
}
[data-zoom-src] { cursor: zoom-in; }
.vg--ms-frame .ms-block {
  display: block;
  margin: 0;
  text-align: justify;
  hyphens: auto;
  /* Stated rather than inherited from .vg, because on a phone a manuscript cell
     reads a step smaller than a plain group. --ms-size carries that step through
     every fs level; see the reading-size block on `body`. */
  font-size: var(--ms-size);
  line-height: var(--ms-lh);
}

/* Wide inline miniature: full-width block (not floated), text flows below.
   Carries .hist-float too so it inherits the click-to-zoom binding. */
.ms-wide {
  float: none;
  clear: both;
  width: 100%;
  margin: 0 0 0.9em;
}

/* The view-mode toggle (theme buttons + ⋮) is fixed to the top-right of the
   VIEWPORT, but the nav is only ~680px wide and centered — so below desktop
   width the right-hand nav link slides under the toggle (iPad included).
   Cluster the nav links on the left and reserve the toggle's footprint until
   the viewport is wide enough that the centered nav clears it on its own. */
@media (max-width: 960px) {
  .nav {
    justify-content: flex-start;
    gap: 1.25rem;
    padding-right: 9rem;   /* tracks the toolbar's width — see .fs-btn sizing */
  }

  /* The logo joins that cluster rather than staying centred. With the toolbar's
     footprint reserved there is no symmetric band left to centre in — at 375px the
     three-column grid squeezed "← Library" until it wrapped onto two lines. Left is
     where every other narrow-viewport nav link in this file already goes. */
  .nav--logo {
    display: flex;
    justify-content: flex-start;
  }

  .nav-logo {
    grid-column: auto;
    justify-self: auto;
  }
}

@media (max-width: 600px) {
  /* Phone reading size: the 1.38rem desktop verse is oversized on a phone, and a
     manuscript cell reads one step smaller again.
     Every level is restated here, level 1 included. It has to be: `body.fs-1` is
     more specific than a bare `body`, so a level left undefined at this breakpoint
     would keep rendering at its DESKTOP size on a phone. And these match the
     desktop fs rules' specificity exactly, so source order is what decides —
     this block must stay below them in the file. */
  body        { --vg-size: 1.08rem; --vg-lh: 1.95; --ms-size: 0.98rem; --ms-lh: 1.85; --climax-size: 1.1rem; }
  body.fs-1   { --vg-size: 1.24rem; --vg-lh: 1.90; --ms-size: 1.14rem; --ms-lh: 1.82; --climax-size: 1.26rem; }
  body.fs-2   { --vg-size: 1.42rem; --vg-lh: 1.85; --ms-size: 1.32rem; --ms-lh: 1.78; --climax-size: 1.45rem; }

  .vg { padding-left: 1.4rem; }
  /* Keep the illuminated square from eating the phone column. */
  .vg--ms-frame { --frame-w: clamp(140px, 44%, 200px); }

  /* In-text miniatures on phone: never wrap text around them. Every float
     (left or right) un-floats and covers a full row, sitting between the
     paragraphs. margin uses !important so any per-image desktop gutter set
     inline (margin-left/right) is neutralised here. */
  .hist-float--right,
  .hist-float--solo,
  .hist-float--mob-full {
    float: none;
    width: 100%;
    max-width: none;
    margin: 0 0 1rem !important;
  }
  /* A circle marked mob-full becomes a full-width disc, text below. */
  .hist-float--circle.hist-float--mob-full {
    height: auto;
    aspect-ratio: 1 / 1;
    border-radius: 50%;
    shape-outside: none;
    transform: none;
  }
  /* Opt-out of the phone un-float: a manuscript margin-strip (e.g. the Babel
     tower cut-out) keeps the strip look on phone instead of going full-width,
     staying floated at half the cell so text still runs alongside it.
     Placed after the un-float rule so it wins the cascade. */
  .hist-float--mob-keep {
    float: right;
    clear: right;
    width: var(--hist-w);
    max-width: 50%;
    margin: 0 0 0.6em 0.9em !important;
  }
}

.ch-nav-bottom__spacer { flex: 1; }

/* ── Context section (collapsible historical notes) ── */
.context-section {
  margin: 3rem 0;
  border-top: 1px solid #2a2a2a;
}

.context-section details {
  padding: 0;
}

.context-section summary {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 1.1rem 0;
  font-family: system-ui, -apple-system, sans-serif;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #444;
  cursor: pointer;
  list-style: none;
  user-select: none;
}

.context-section summary::-webkit-details-marker { display: none; }

.context-section summary::before {
  content: '▶';
  font-size: 0.5rem;
  transition: transform 0.2s;
  color: #555;
}

.context-section details[open] summary::before {
  transform: rotate(90deg);
}

.context-section summary:hover { color: #888; }

.context-body {
  padding: 0.5rem 0 2rem;
  font-family: system-ui, -apple-system, sans-serif;
  font-size: 0.82rem;
  line-height: 1.7;
  color: #777;
}

.context-body h3 {
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #555;
  margin: 1.6rem 0 0.5rem;
}

.context-body h3:first-child { margin-top: 0; }

.context-body p { margin: 0 0 0.6rem; }
.context-body p:last-child { margin-bottom: 0; }

/* ── Footer ── */
.page-footer {
  margin-top: 5rem;
  padding-top: 1.5rem;
  border-top: 1px solid #2a2a2a;
  font-size: 0.72rem;
  color: #444;
  letter-spacing: 0.05em;
}

/* ms-pages content stays hidden — these divs exist in some chapter HTML but are unused */
.ms-pages { display: none; }

/* ── Info-box (bilgi kutucuğu) — reusable across chapters ── */
.ib-trigger {
  display: flex; align-items: center; gap: 1rem;
  margin: 2rem 0; padding: 0.9rem 1.2rem;
  border: 1px solid var(--surface-border); cursor: pointer;
  transition: border-color 0.2s, background 0.15s;
  user-select: none;
  touch-action: manipulation; /* prevents iOS double-tap zoom */
}
.ib-trigger:hover { border-color: color-mix(in srgb, currentColor 25%, transparent); background: var(--hover-bg); }
.ib-trigger__icon { font-size: 1.5rem; flex-shrink: 0; line-height: 1; display: flex; align-items: center; }
.ib-trigger__text { font-size: 0.82rem; color: inherit; opacity: 0.55; letter-spacing: 0.03em; }
.ib-trigger:hover .ib-trigger__text { opacity: 0.85; }

/* iOS Safari fix: flex centering must be in .open, not in the display:none rule */
.ib-overlay {
  display: none;
  position: fixed;
  top: 0; left: 0; right: 0; bottom: 0;
  background: rgba(0,0,0,0.88);
  z-index: 1000;
  padding: 1.5rem;
}
.ib-overlay.open {
  display: -webkit-box;
  display: -webkit-flex;
  display: flex;
  -webkit-box-align: center;
  -webkit-align-items: center;
  align-items: center;
  -webkit-box-pack: center;
  -webkit-justify-content: center;
  justify-content: center;
}

.ib-card {
  background: var(--surface); border: 1px solid var(--surface-border);
  max-width: 560px; width: 100%; max-height: 90vh;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch; /* iOS momentum scrolling */
  overscroll-behavior: contain;      /* prevent page scroll bleed */
  padding: 2rem; position: relative;
  animation: ib-in 0.22s ease;
}
@keyframes ib-in {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}
.ib-card__close {
  position: absolute; top: 1rem; right: 1rem;
  background: none; border: none; color: inherit; opacity: 0.4;
  font-size: 1rem; cursor: pointer; padding: 0.2rem 0.5rem;
  transition: opacity 0.15s;
}
.ib-card__close:hover { opacity: 0.75; }
.ib-card__head {
  display: flex; align-items: center; gap: 1rem;
  margin-bottom: 1.2rem; padding-bottom: 1.2rem;
  border-bottom: 1px solid var(--surface-border);
}
.ib-card__head-icon { font-size: 2rem; line-height: 1; }
.ib-card__head h3 { margin: 0; font-size: 0.95rem; font-weight: 600; color: inherit; opacity: 0.9; }
.ib-card__intro { font-size: 0.86rem; color: inherit; opacity: 0.7; line-height: 1.65; margin: 0 0 1.4rem; }
.ib-entries { display: flex; flex-direction: column; gap: 1.1rem; }
.ib-entry { border-left: 2px solid var(--surface-border); padding-left: 1rem; }
.ib-entry__tag {
  font-size: 0.68rem; letter-spacing: 0.22em; text-transform: uppercase;
  color: inherit; opacity: 0.45; margin-bottom: 0.35rem;
}
.ib-entry p { margin: 0; font-size: 0.85rem; color: inherit; opacity: 0.62; line-height: 1.62; }


/* ══════════════════════════════════════════════════════════════════
   Gallery (grid reader) mode  —  galeri.html + gallery.js
   A justified, fixed-height / variable-width grid of each chapter's
   artworks, with a within-chapter slider on click. Reuses the fullscreen
   overlay + theme panel from artworks.js.
   ══════════════════════════════════════════════════════════════════ */

/* Top-nav button on the chapter index that jumps to gallery mode */
.nav-gallery {
  font-size: 0.82rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #888 !important;
  border: 1px solid #2a2a2a;
  border-radius: 999px;
  padding: 0.4rem 0.9rem;
  transition: color 0.15s, border-color 0.15s, background 0.15s;
}
.nav-gallery:hover { color: #f0f0f0 !important; border-color: #555; background: var(--hover-bg); }
/* CSS-drawn 2×2 grid glyph (reliable across fonts, inherits text colour) */
.nav-gallery::before {
  content: "";
  display: inline-block;
  width: 10px;
  height: 10px;
  margin-right: 0.55em;
  vertical-align: -1px;
  background:
    linear-gradient(currentColor, currentColor) 0 0 / 3.5px 3.5px no-repeat,
    linear-gradient(currentColor, currentColor) 100% 0 / 3.5px 3.5px no-repeat,
    linear-gradient(currentColor, currentColor) 0 100% / 3.5px 3.5px no-repeat,
    linear-gradient(currentColor, currentColor) 100% 100% / 3.5px 3.5px no-repeat;
}

/* Decluttered gallery nav: just a back link with a minimalist arrow */
.nav--back-only { justify-content: flex-start; }
.nav-back {
  display: inline-flex;
  align-items: center;
  gap: 0.55em;
}
.nav-back__icon {
  width: 17px;
  height: 17px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform 0.2s ease;
}
.nav-back:hover .nav-back__icon { transform: translateX(-3px); }

/* Page shell — wider than the reading column */
.gallery-page {
  max-width: 1600px;
  margin: 0 auto;
  padding: 2.5rem 2rem 8rem;
}
.gallery-loading {
  color: #666;
  text-align: center;
  padding: 4rem 1rem;
  font-size: 0.9rem;
}

/* Per-chapter header */
.gallery-chapter { margin-bottom: 3.5rem; }
.gallery-chapter__header {
  padding-bottom: 0.8rem;
  margin-bottom: 1.1rem;
  border-bottom: 1px solid var(--surface-border);
}
.gallery-chapter__num {
  font-size: 0.62rem;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: #555;
  margin-bottom: 0.4rem;
}
.gallery-chapter__title {
  display: inline-block;
  font-size: clamp(1.3rem, 3vw, 2rem);
  font-weight: 700;
  color: #f0f0f0;
  letter-spacing: -0.01em;
  line-height: 1.1;
  transition: color 0.15s;
}
.gallery-chapter__title:hover { color: var(--soy-green); }
.gallery-chapter__desc {
  font-size: 0.9rem;
  color: #666;
  line-height: 1.55;
  margin-top: 0.35rem;
  max-width: 640px;
}

/* Justified grid — gallery.js sets each tile's px width/height */
.gallery-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.gallery-tile {
  position: relative;
  overflow: hidden;
  background-color: var(--surface, #0f0f0f);
  /* Blurred LQIP data-URI is set inline; scaled up it reads as a soft placeholder */
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  border-radius: 2px;
  cursor: zoom-in;
  /* Fallback height before JS justification runs (aspect-ratio keeps shape) */
  height: 240px;
  aspect-ratio: var(--ratio, 1);
}
.gallery-tile img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  opacity: 0;
  transition: opacity 0.5s ease, transform 0.35s ease, filter 0.2s ease;
  filter: brightness(0.94);
}
.gallery-tile img.is-loaded { opacity: 1; }
.gallery-tile:hover img { transform: scale(1.04); filter: brightness(1.05); }
.gallery-tile:focus-visible { outline: 2px solid var(--soy-green); outline-offset: 2px; }

/* Within-chapter slider (sits below the artworks.js fullscreen overlay, z 900) */
.gallery-slider {
  position: fixed;
  inset: 0;
  z-index: 850;
  background: rgba(8, 8, 8, 0.97);
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s;
}
.gallery-slider.show { opacity: 1; pointer-events: auto; }

/* The slider's content is a real .art-carousel (gallery.js builds it, artworks.js's
   initCarousel wires it). That component is written for the page flow — it claims a
   whole viewport of vertical space and breaks out of the reading column by centring
   itself on a 50% margin. Inside a fixed overlay it simply fills the box instead.
   Everything else — track, slides, dots, the ‹ › in the side margins, and their
   removal under 600px — is inherited unchanged, which is the point. */
.art-carousel--overlay {
  --carousel-h: calc(100svh - 7rem);
  min-height: 0;
  height: 100%;
  width: 100%;
  margin: 0;
  transform: none;
  padding: 3.2rem 0 1.4rem;   /* clears the ✕ above and the dots below */
  box-sizing: border-box;
}

.gallery-slider__close {
  position: fixed;
  top: calc(1.2rem + var(--sa-top)); right: calc(1.5rem + var(--sa-right));
  width: 2.4rem; height: 2.4rem;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0, 0, 0, 0.55);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 50%;
  color: #ccc; font-size: 1.4rem; line-height: 1; cursor: pointer; padding: 0;
  -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
  transition: color 0.15s, background 0.15s;
  z-index: 860;   /* above the full-height nav buttons so its corner isn't stolen */
}
.gallery-slider__close:hover { color: #fff; background: rgba(0, 0, 0, 0.75); }

@media (max-width: 600px) {
  .gallery-page { padding: 1.5rem 1rem 6rem; }
  /* --art-w: 100% comes from the base .art-carousel phone rule; only the chrome
     the overlay adds needs trimming. The ‹ › are already hidden there. */
  .art-carousel--overlay { --carousel-h: calc(100svh - 6rem); padding: 2.8rem 0 1.2rem; }
}

/* Theme tweaks — keep tiles readable on light themes */
body.theme-paper .gallery-tile,
body.theme-paper .gallery-chapter__desc { color: #888; }
body.theme-paper .gallery-chapter__title { color: #111; }
