.reading-mode-open {
  overflow: hidden;
}

.reading-mode-open .app-frame {
  visibility: hidden;
}

.reading-view {
  --reader-bg: #17191d;
  --reader-page: #f4f0e6;
  --reader-ink: #27241f;
  --reader-muted: #827d73;
  --reader-accent: #8a6245;
  --reader-font: "Noto Serif KR", Georgia, serif;
  --reader-font-size: 18px;
  --reader-font-weight: 400;
  --reader-leading: 1.85;
  --reader-paragraph-gap: 1em;
  --reader-column-width: 620px;
  --reader-column-height: 680px;
  --reader-column-gap: 152px;
  --reader-column-stride: 772px;
  --reader-page-padding: 68px;
  position: fixed;
  z-index: 220;
  inset: 0;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  overflow: hidden;
  background: var(--reader-bg);
  color: var(--reader-ink);
  color-scheme: light dark;
  font-family: "Noto Sans KR", system-ui, sans-serif;
  isolation: isolate;
}

.reading-view[hidden] {
  display: none;
}

.reading-view button,
.reading-view input,
.reading-view select {
  font: inherit;
}

.reader-topbar {
  position: relative;
  z-index: 8;
  display: grid;
  grid-template-columns: auto minmax(150px, 1fr) auto;
  align-items: center;
  gap: 18px;
  min-height: 58px;
  padding: 8px clamp(14px, 2.4vw, 34px);
  border-bottom: 1px solid color-mix(in srgb, var(--reader-page) 16%, transparent);
  background: color-mix(in srgb, var(--reader-bg) 92%, #000 8%);
  color: color-mix(in srgb, var(--reader-page) 88%, transparent);
}

.reader-topbar button,
.reader-panel button,
.reader-empty button {
  border: 0;
  background: transparent;
  color: inherit;
  cursor: pointer;
}

/* Return is navigation, not a title — it sits a step below the heading in weight
   and only comes forward on hover. The arrow carries the meaning, so the word can
   stay quiet. */
.reader-close {
  display: inline-flex;
  align-items: baseline;
  gap: 9px;
  min-height: 34px;
  padding: 0;
  color: color-mix(in srgb, var(--reader-page) 42%, transparent);
  font-size: 9px;
  letter-spacing: .16em;
  text-transform: uppercase;
  transition: color 120ms ease;
}

.reader-close:hover,
.reader-close:focus-visible {
  color: color-mix(in srgb, var(--reader-page) 88%, transparent);
}

.reader-close span:first-child {
  font-size: 13px;
  letter-spacing: 0;
}

/* One line, read left to right: character — list. Hierarchy comes from tracking
   and colour rather than from stacking, which made two short words occupy two
   lines and read as neither a title nor a subtitle. */
.reader-heading {
  display: flex;
  min-width: 0;
  align-items: baseline;
  justify-content: center;
  gap: 20px;
}

.reader-heading small {
  flex: 0 1 auto;
  overflow: hidden;
  color: color-mix(in srgb, var(--reader-page) 44%, transparent);
  font-size: 9px;
  letter-spacing: .22em;
  text-overflow: ellipsis;
  text-transform: uppercase;
  white-space: nowrap;
}

.reader-heading small:empty {
  display: none;
}

/* The list name is the subject of the screen, so it gets the size and the full
   contrast — the character name beside it is the context. */
.reader-heading strong {
  flex: 0 1 auto;
  overflow: hidden;
  min-width: 0;
  color: color-mix(in srgb, var(--reader-page) 94%, transparent);
  font-family: var(--reader-font);
  font-size: 15px;
  font-weight: 500;
  letter-spacing: .01em;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.reader-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 5px;
}

.reader-actions button,
.reader-mode-button {
  min-height: 32px;
  padding: 0 9px;
  border: 1px solid transparent;
  border-radius: 4px;
  color: color-mix(in srgb, var(--reader-page) 58%, transparent);
  font-size: 9px;
  letter-spacing: .08em;
  text-transform: uppercase;
}

.reader-actions button:hover,
.reader-actions button[aria-pressed="true"],
.reader-mode-button[aria-pressed="true"] {
  border-color: color-mix(in srgb, var(--reader-page) 24%, transparent);
  color: var(--reader-page);
}

.reader-main {
  position: relative;
  min-width: 0;
  min-height: 0;
}

.reader-empty {
  display: grid;
  place-items: center;
  min-height: 100%;
  padding: 32px;
  color: color-mix(in srgb, var(--reader-page) 70%, transparent);
  text-align: center;
}

.reader-empty > div {
  max-width: 440px;
}

.reader-empty p {
  margin: 12px 0 24px;
  color: color-mix(in srgb, var(--reader-page) 46%, transparent);
  font-size: 12px;
  line-height: 1.8;
}

.reader-empty button,
.reader-primary {
  min-height: 36px;
  padding: 0 15px !important;
  border-radius: 4px !important;
  background: var(--reader-accent) !important;
  color: #fff !important;
  font-size: 10px !important;
  font-weight: 600 !important;
  letter-spacing: .08em;
  text-transform: uppercase;
}

.reader-scroll-view {
  position: absolute;
  inset: 0;
  overflow: auto;
  overscroll-behavior: contain;
  scrollbar-color: color-mix(in srgb, var(--reader-page) 24%, transparent) transparent;
}

.reader-scroll-content {
  box-sizing: border-box;
  width: min(calc(100% - 36px), var(--reader-scroll-width, 780px));
  min-height: 100%;
  margin: 0 auto;
  padding: clamp(44px, 7vw, 96px) clamp(20px, 5vw, 70px) 18vh;
  background: var(--reader-page);
  box-shadow: 0 0 80px rgba(0, 0, 0, .24);
}

.reader-page-view {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: 48px minmax(0, 1fr) 48px;
  grid-template-rows: minmax(0, 1fr) auto;
  align-items: center;
  gap: clamp(6px, 1vw, 16px);
  padding: clamp(10px, 2vw, 24px);
  overflow: hidden;
}

.reader-page-view[hidden],
.reader-scroll-view[hidden] {
  display: none;
}

.reader-page-nav {
  display: grid;
  place-items: center;
  width: 42px;
  aspect-ratio: 1;
  padding: 0 !important;
  border: 1px solid color-mix(in srgb, var(--reader-page) 18%, transparent) !important;
  border-radius: 50%;
  background: transparent !important;
  color: color-mix(in srgb, var(--reader-page) 66%, transparent) !important;
  font-size: 20px !important;
}

.reader-page-nav:disabled {
  opacity: .18;
  cursor: default;
}

.reader-page-stage {
  position: relative;
  display: grid;
  place-items: center;
  min-width: 0;
  min-height: 0;
  width: 100%;
  height: 100%;
  perspective: 1600px;
}

.reader-page-viewport {
  position: relative;
  box-sizing: border-box;
  width: var(--reader-viewport-width, 760px);
  height: var(--reader-viewport-height, 820px);
  max-width: 100%;
  max-height: 100%;
  overflow: hidden;
  border-radius: 3px;
  background-color: var(--reader-page);
  background-image: none;
  box-shadow: 0 28px 90px rgba(0, 0, 0, .34), inset 0 0 0 1px rgba(70, 54, 34, .1);
  contain: layout style;
  transform-style: preserve-3d;
}

.reader-page-viewport.is-spread {
  background-image: none;
  box-shadow: 0 28px 90px rgba(0, 0, 0, .34), inset 0 0 0 1px rgba(70, 54, 34, .1);
}

.reader-turn-sheet {
  position: absolute;
  z-index: 7;
  top: 0;
  bottom: 0;
  display: none;
  width: 100%;
  pointer-events: none;
  transform-style: preserve-3d;
  contain: strict;
}

.reader-page-viewport.is-spread .reader-turn-sheet {
  width: calc((100% - 20px) / 2);
}

.reader-turn-face {
  position: absolute;
  inset: 0;
  display: block;
  overflow: hidden;
  border-radius: inherit;
  background-color: var(--reader-page);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

.reader-turn-front {
  background-image:
    radial-gradient(ellipse 22% 110% at 100% 50%, rgba(255, 255, 255, .34), transparent 62%),
    linear-gradient(90deg, transparent 58%, rgba(46, 37, 29, .05) 78%, rgba(46, 37, 29, .2));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--reader-ink) 8%, transparent), -7px 5px 20px rgba(0, 0, 0, .13);
}

.reader-turn-back {
  background-image:
    radial-gradient(ellipse 22% 110% at 0 50%, rgba(255, 255, 255, .28), transparent 64%),
    linear-gradient(270deg, transparent 54%, rgba(46, 37, 29, .08) 78%, rgba(46, 37, 29, .22));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--reader-ink) 8%, transparent), 8px 5px 24px rgba(0, 0, 0, .16);
  transform: rotateY(180deg);
}

.reader-turn-sheet::after {
  content: "";
  position: absolute;
  inset: 0;
  opacity: 0;
  background: linear-gradient(90deg, rgba(255, 255, 255, .2), transparent 32%, rgba(0, 0, 0, .18) 93%);
  transform: translateZ(1px);
}

/* The falloff is baked into the gradient rather than applied with
   filter: blur(). This element animates opacity + translateX for 480ms, and a
   blurred layer has to be re-blurred on every one of those frames. Runs the
   full height so the ends clip against the viewport instead of showing the
   hard edge the blur used to soften. */
.reader-turn-cast {
  position: absolute;
  z-index: 6;
  top: 0;
  bottom: 0;
  display: block;
  width: 18%;
  opacity: 0;
  pointer-events: none;
  background: linear-gradient(90deg,
    rgba(0, 0, 0, 0),
    rgba(0, 0, 0, .08) 24%,
    rgba(0, 0, 0, .24) 50%,
    rgba(0, 0, 0, .08) 76%,
    rgba(0, 0, 0, 0));
}

.reader-page-viewport.is-turning-forward .reader-turn-sheet {
  right: 0;
  display: block;
  transform-origin: left center;
  will-change: transform;
  animation: readerSheetForward 480ms cubic-bezier(.2, .68, .18, 1) both;
}

.reader-page-viewport.is-turning-back .reader-turn-sheet {
  left: 0;
  display: block;
  transform-origin: right center;
  will-change: transform;
  animation: readerSheetBack 480ms cubic-bezier(.2, .68, .18, 1) both;
}

.reader-page-viewport.is-turning-forward .reader-turn-sheet::after,
.reader-page-viewport.is-turning-back .reader-turn-sheet::after {
  animation: readerSheetLight 480ms ease-in-out both;
}

.reader-page-viewport.is-turning-forward .reader-turn-cast {
  left: 44%;
  animation: readerCastForward 480ms ease-in-out both;
}

.reader-page-viewport.is-turning-back .reader-turn-cast {
  right: 44%;
  animation: readerCastBack 480ms ease-in-out both;
}

@keyframes readerSheetForward {
  0% { transform: translate3d(0, 0, 0) rotateY(0deg) skewY(0deg); }
  40% { transform: translate3d(-1.2%, 0, 16px) rotateY(-72deg) skewY(-.55deg); }
  52% { transform: translate3d(-1.8%, 0, 20px) rotateY(-101deg) skewY(.45deg); }
  100% { transform: translate3d(-2.4%, 0, 0) rotateY(-180deg) skewY(0deg); }
}

@keyframes readerSheetBack {
  0% { transform: translate3d(0, 0, 0) rotateY(0deg) skewY(0deg); }
  40% { transform: translate3d(1.2%, 0, 16px) rotateY(72deg) skewY(.55deg); }
  52% { transform: translate3d(1.8%, 0, 20px) rotateY(101deg) skewY(-.45deg); }
  100% { transform: translate3d(2.4%, 0, 0) rotateY(180deg) skewY(0deg); }
}

@keyframes readerSheetLight {
  0%, 100% { opacity: 0; }
  22% { opacity: .32; }
  48% { opacity: .8; }
  76% { opacity: .26; }
}

@keyframes readerCastForward {
  0%, 100% { opacity: 0; transform: translateX(32%); }
  45% { opacity: .62; transform: translateX(-8%); }
  58% { opacity: .3; transform: translateX(-32%); }
}

@keyframes readerCastBack {
  0%, 100% { opacity: 0; transform: translateX(-32%); }
  45% { opacity: .62; transform: translateX(8%); }
  58% { opacity: .3; transform: translateX(32%); }
}

.reader-page-flow {
  position: absolute;
  z-index: 1;
  top: var(--reader-page-padding);
  left: var(--reader-page-padding);
  width: var(--reader-column-width);
  height: var(--reader-column-height);
  column-width: var(--reader-column-width);
  column-gap: var(--reader-column-gap);
  column-fill: auto;
  overflow: visible;
  /* 2D on purpose. This element is as wide as the whole document (a 68-page list
     runs past 50,000px), and translate3d pins that entire span into a GPU layer,
     which is why turns get slower the further in you are. The offset is never
     transitioned — position changes are instant and the turn sheet covers them —
     so there is nothing here that needs a compositor layer of its own. */
  transform: translate(var(--reader-page-offset, 0px), 0);
}

.reader-page-viewport.is-turning-forward .reader-page-flow,
.reader-page-viewport.is-turning-back .reader-page-flow {
  animation: readerFlowExchange 480ms ease-in-out both;
}

/* The flat dip is where the page content is swapped. Widened to 46–54% so
   setTimeout jitter can't land the swap on a visible frame. Do not remove this
   animation for performance — the turn sheet covers only one leaf, so this dip is
   the only thing hiding the swap on the other half in 2-page view. */
@keyframes readerFlowExchange {
  0%, 32% { opacity: 1; }
  46%, 54% { opacity: .04; }
  68%, 100% { opacity: 1; }
}

/* Folio: the page's own number, printed in the bottom margin of each sheet.
   In 2-page view each half carries its own; in 1-page view the left one is
   centred across the whole sheet and the right is dropped. */
.reader-folio {
  position: absolute;
  z-index: 8;
  right: 0;
  bottom: 9px;
  left: 0;
  color: color-mix(in srgb, var(--reader-ink) 34%, transparent);
  font-family: var(--reader-font);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  letter-spacing: .18em;
  text-align: center;
  pointer-events: none;
}

/* ─────────────────────────────────────────────────────────────────
   Log blocks, rebound to paper.

   The blocks aren't styled by the character themes — logpaste.js injects its own
   CSS (see its ~line 1260) and reads colour from --panel / --theme-panel /
   --lp-*. Those resolve to the app's dark chrome, which is inherited straight
   into the reader: a black card whose text reading.css then forces to dark ink,
   so the block goes invisible.

   Rebinding the tokens here fixes every block at once, and keeps working for
   blocks added later — far better than chasing 367 rules across themes.
   ───────────────────────────────────────────────────────────────── */
.reading-view {
  /* App chrome tokens the block CSS falls back to */
  --panel: var(--reader-page);
  --theme-panel: var(--reader-page);
  --ink: var(--reader-ink);
  --theme-ink: var(--reader-ink);
  --muted: var(--reader-muted);
  --theme-muted: var(--reader-muted);
  --line: color-mix(in srgb, var(--reader-ink) 16%, transparent);
  --theme-line: color-mix(in srgb, var(--reader-ink) 16%, transparent);

  /* logpaste's own tokens */
  --lp-line: color-mix(in srgb, var(--reader-ink) 16%, transparent);
  --lp-muted: var(--reader-muted);
  --lp-accent: var(--reader-accent);
  --lp-context-paper: transparent;

  /* Type follows the reader's own settings, so a block reads as the same
     document as the prose around it rather than as a pasted-in panel. */
  --lp-body-font: var(--reader-font);
  --lp-dialogue-font: var(--reader-font);
  --lp-speaker-font: var(--reader-font);
  --lp-size: var(--reader-font-size);
  --lp-leading: var(--reader-leading);
  --lp-paragraph-gap: var(--reader-paragraph-gap);
}

/* Swiss editorial: a section is set off by a hairline above and below, not by a
   filled card. This is also what removes the "only this block has a background"
   inconsistency — every section now sits on the same paper. */
/* logpaste declares --lp-context-paper on the section itself, which beats an
   inherited value, so the token is re-declared here as well as on the root. */
.reading-view .log-context-section {
  --lp-context-paper: transparent;
  border: 0;
  border-top: 1px solid color-mix(in srgb, var(--reader-ink) 20%, transparent);
  border-bottom: 1px solid color-mix(in srgb, var(--reader-ink) 12%, transparent);
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  padding-inline: 0;
}

/* Avatar and node portraits filled themselves from --theme-panel. */
.reading-view :is(.log-map-node-portrait, .log-character-portrait, .log-character-image) {
  background: transparent;
}

/* Section label — the SETTINGS / ILLUSTRATION micro-caps. */
.reading-view .log-context-label {
  color: var(--reader-muted);
  font-family: var(--reader-font);
  letter-spacing: .2em;
}

/* Cards inside the blocks (character info, relationship nodes) lose their fills
   for the same reason. */
.reading-view :is(.log-character-card, .log-character-feature, .log-character-info,
.log-character-group, .log-relationship-viewport, .log-map-person-inspector,
.log-bgm-card, .log-character-stage) {
  border-color: color-mix(in srgb, var(--reader-ink) 14%, transparent);
  background: transparent;
  box-shadow: none;
}

.reader-folio-right {
  display: none;
}

.reader-page-viewport.is-spread .reader-folio {
  right: auto;
  width: calc((100% - 20px) / 2);
}

.reader-page-viewport.is-spread .reader-folio-right {
  display: block;
  right: 0;
  left: auto;
}

/* Overall position, on the desk rather than on the paper — so it reads against
   --reader-bg and uses the page colour for contrast, like the nav arrows. */
.reader-page-progress {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  gap: clamp(8px, 1.4vw, 16px);
  margin-top: clamp(4px, .8vw, 10px);
  padding: 0 clamp(2px, 1vw, 12px);
}

.reader-page-status {
  color: color-mix(in srgb, var(--reader-page) 60%, transparent);
  font-size: 10px;
  font-variant-numeric: tabular-nums;
  letter-spacing: .12em;
  white-space: nowrap;
  pointer-events: none;
}

.reader-progress-rail {
  position: relative;
  flex: 1;
  min-width: 40px;
  height: 2px;
  border-radius: 2px;
  background: color-mix(in srgb, var(--reader-page) 15%, transparent);
}

/* A native range laid over the rail, invisible but full size: dragging, clicking
   and arrow keys all come for free, and the visible bar stays ours to style.
   The hit area is padded out to a comfortable height without thickening the rule. */
.reader-progress-seek {
  position: absolute;
  top: 50%;
  left: 0;
  width: 100%;
  height: 22px;
  margin: 0;
  padding: 0;
  transform: translateY(-50%);
  opacity: 0;
  cursor: ew-resize;
  -webkit-appearance: none;
  appearance: none;
  background: transparent;
}

.reader-progress-seek::-webkit-slider-thumb {
  width: 22px;
  height: 22px;
  -webkit-appearance: none;
  appearance: none;
}

.reader-progress-seek::-moz-range-thumb {
  width: 22px;
  height: 22px;
  border: 0;
}

.reader-progress-seek:focus-visible {
  outline: 1px solid color-mix(in srgb, var(--reader-page) 50%, transparent);
  outline-offset: 4px;
}

/* Thickens under the pointer so the thin rule still reads as draggable. */
.reader-page-progress:hover .reader-progress-rail,
.reader-progress-rail:has(.reader-progress-seek:focus-visible) {
  height: 4px;
}

.reader-progress-rail {
  transition: height 120ms ease;
}

.reader-progress-fill {
  display: block;
  width: var(--reader-progress, 0%);
  height: 100%;
  border-radius: inherit;
  background: color-mix(in srgb, var(--reader-accent) 76%, var(--reader-page));
  transition: width 260ms cubic-bezier(.22, .75, .28, 1);
}

.reader-progress-percent {
  min-width: 3.2em;
  color: color-mix(in srgb, var(--reader-page) 42%, transparent);
  font-size: 10px;
  font-variant-numeric: tabular-nums;
  letter-spacing: .12em;
  text-align: right;
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .reader-progress-fill {
    transition: none;
  }
}

.reader-entry {
  box-sizing: border-box;
  color: var(--reader-ink);
  font-family: var(--reader-font);
  font-size: var(--reader-font-size);
  font-weight: var(--reader-font-weight);
  line-height: var(--reader-leading);
  overflow-wrap: anywhere;
  word-break: keep-all;
}

.reader-entry + .reader-entry {
  margin-top: clamp(42px, 7vw, 76px);
  padding-top: clamp(28px, 5vw, 48px);
  border-top: 1px solid color-mix(in srgb, var(--reader-ink) 13%, transparent);
}

.reader-entry-head {
  break-after: avoid;
  margin-bottom: clamp(24px, 4vw, 38px);
}

.reader-source {
  margin: 0 0 9px;
  color: var(--reader-muted);
  font-family: "Noto Sans KR", system-ui, sans-serif;
  font-size: .68em;
  font-weight: 500;
  letter-spacing: .15em;
  line-height: 1.4;
  opacity: .68;
  text-transform: uppercase;
}

.reader-entry-head h2 {
  margin: 0;
  color: var(--reader-ink);
  font-family: var(--reader-font);
  font-size: clamp(1.45em, 3vw, 2.2em);
  font-weight: 600;
  line-height: 1.24;
  letter-spacing: -.035em;
}

.reader-entry-date {
  display: block;
  margin-top: 8px;
  color: var(--reader-muted);
  font-family: "Noto Sans KR", system-ui, sans-serif;
  font-size: .66em;
  letter-spacing: .08em;
}

.reader-entry-body {
  color: var(--reader-ink);
  font: inherit;
  line-height: inherit;
}

/* Read mode owns its palette. Source HTML may contain inline colors or
   theme-specific text tokens, but every visible glyph is normalized to the
   reader's text/muted controls without altering the stored original HTML. */
.reading-view .reader-entry .reader-entry-body,
.reading-view .reader-entry .reader-entry-body * {
  color: var(--reader-ink) !important;
  -webkit-text-fill-color: var(--reader-ink) !important;
}

.reading-view .reader-entry .reader-entry-body :where(
  small,
  time,
  figcaption,
  .muted,
  .text-muted,
  .eyebrow,
  .reader-source,
  .reader-entry-date,
  [class*="meta"],
  [class*="caption"],
  [class*="kicker"],
  [class*="date"]
) {
  color: var(--reader-muted) !important;
  -webkit-text-fill-color: var(--reader-muted) !important;
}

.reading-view .reader-entry .reader-entry-body svg text {
  fill: var(--reader-ink) !important;
}

.reader-entry-body > p + p {
  margin-top: var(--reader-paragraph-gap);
}

/* An image can't be split, so it has to fit a column outright — otherwise it is
   pushed whole to the next column and leaves the rest of the current one blank.
   Clamping to the column height guarantees it always fits. */
.reader-gallery-image {
  display: block;
  width: 100%;
  max-height: min(62vh, 660px, var(--reader-column-height, 660px));
  margin: 0 0 clamp(26px, 4vw, 42px);
  object-fit: contain;
  break-inside: avoid;
}

.reader-expanded-tabs {
  display: grid;
  gap: var(--reader-paragraph-gap);
  margin: 20px 0;
}

.reader-expanded-tab {
  min-width: 0;
}

.reading-view.reader-unify-font .reader-entry,
.reading-view.reader-unify-font .reader-entry *:not(.ic-c):not(.ic-o) {
  font-family: var(--reader-font) !important;
}

/* Only genuinely atomic boxes refuse to split. A block that is taller than the
   space left in a column gets pushed whole to the next one, and in 2-page view
   that shows up as a sheet with content on one half and a gap on the other —
   so anything that can grow into a long passage has to stay breakable. */
.reader-page-flow :is(img, figure, table, .media-block, .log-relationship-viewport, .log-map-person-inspector) {
  break-inside: avoid;
  max-width: 100%;
}

.reader-page-flow :is(blockquote, details, .ps-chat, .ps-letter, .ps-emphasis, .media-gallery, .log-context-section),
.reader-page-flow .reader-expanded-tab {
  break-inside: auto;
  max-width: 100%;
}

.reader-page-flow img,
.reader-scroll-content img {
  max-width: 100%;
}

/* In page mode an inline illustration is unbreakable, so one taller than the
   space left in a column is pushed whole to the next one and leaves a gap —
   the same half-empty sheet the gallery images caused. Capping at the column
   height means an illustration always fits wherever it lands. */
.reader-page-flow img {
  max-height: min(72vh, var(--reader-column-height, 660px));
}

.reader-page-flow :is(.media-gallery, .media-carousel, .media-compare, .media-swap),
.reader-scroll-content :is(.media-gallery, .media-carousel, .media-compare, .media-swap) {
  max-width: 100%;
}

.reader-page-flow .log-transcript,
.reader-scroll-content .log-transcript {
  width: 100%;
  max-width: 100%;
  min-width: 0;
}

.reader-panel-shade {
  position: fixed;
  z-index: 7;
  inset: 0;
  background: rgba(0, 0, 0, .44);
  opacity: 0;
  transition: opacity 180ms ease;
}

.reader-panel-shade.is-open {
  opacity: 1;
}

.reader-panel {
  position: fixed;
  z-index: 15;
  top: 0;
  right: 0;
  bottom: 0;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  width: min(440px, 94vw);
  background: #20242a;
  color: #eef0f2;
  box-shadow: -28px 0 70px rgba(0, 0, 0, .32);
  transform: translateX(100%);
  transition: transform 210ms cubic-bezier(.22, .75, .28, 1);
}

.reader-panel[data-reader-panel-view="sources"] {
  width: min(560px, 96vw);
}

.reader-panel.is-open {
  transform: translateX(0);
}

.reader-panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  min-height: 58px;
  padding: 10px 18px;
  border-bottom: 1px solid rgba(255, 255, 255, .11);
}

.reader-panel-head h3 {
  margin: 0;
  font-size: 14px;
  font-weight: 600;
}

.reader-panel-head button {
  color: rgba(255, 255, 255, .62);
  font-size: 10px;
  letter-spacing: .08em;
  text-transform: uppercase;
}

.reader-panel-body {
  overflow: auto;
  padding: 18px;
}

.reader-panel-section + .reader-panel-section {
  margin-top: 24px;
  padding-top: 20px;
  border-top: 1px solid rgba(255, 255, 255, .1);
}

.reader-panel-section > h4,
.reader-source-group > h4 {
  margin: 0 0 12px;
  color: rgba(255, 255, 255, .5);
  font-size: 9px;
  font-weight: 500;
  letter-spacing: .13em;
  text-transform: uppercase;
}

.reader-create-row,
.reader-settings-row,
.reader-rename-row,
.reader-bookmark-add {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 8px;
  align-items: center;
}

/* Fields are ruled, not boxed: a single baseline under the value, which keeps
   every control sitting on one grid line instead of each floating in its own
   rounded rectangle. */
.reader-panel input[type="text"],
.reader-panel input[type="search"],
.reader-panel select,
.reader-panel input[type="number"] {
  box-sizing: border-box;
  width: 100%;
  min-height: 32px;
  padding: 6px 0;
  border: 0;
  border-bottom: 1px solid rgba(255, 255, 255, .2);
  border-radius: 0;
  background: transparent;
  color: #fff;
  font-size: 12px;
  transition: border-color 120ms ease;
}

.reader-panel select {
  padding-right: 18px;
}

.reader-panel input[type="text"]:focus,
.reader-panel input[type="search"]:focus,
.reader-panel select:focus,
.reader-panel input[type="number"]:focus {
  border-bottom-color: #fff;
  outline: 0;
}

.reader-panel input[type="range"] {
  width: 100%;
  accent-color: var(--reader-accent);
}

/* The swatch is the control — no frame needed around a colour. */
.reader-panel input[type="color"] {
  width: 34px;
  height: 18px;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  cursor: pointer;
}

.reader-panel input[type="color"]::-webkit-color-swatch-wrapper {
  padding: 0;
}

.reader-panel input[type="color"]::-webkit-color-swatch {
  border: 1px solid rgba(255, 255, 255, .22);
}

/* Label left, control right, both locked to the same column across every row —
   the alignment is what makes a settings list read as a grid. */
.reader-setting {
  display: grid;
  grid-template-columns: 5.6em minmax(0, 1fr) 3.4em;
  gap: 12px;
  align-items: center;
  padding: 7px 0;
}

.reader-setting > span {
  color: rgba(255, 255, 255, .58);
  font-size: 9px;
  letter-spacing: .13em;
  text-transform: uppercase;
}

.reader-setting > output {
  color: rgba(255, 255, 255, .82);
  font-size: 10px;
  font-variant-numeric: tabular-nums;
  letter-spacing: .06em;
  text-align: right;
}

.reader-setting > output:empty {
  display: none;
}

.reader-setting-check {
  display: grid;
  grid-template-columns: 5.6em minmax(0, 1fr);
  gap: 12px;
  align-items: center;
  padding: 7px 0;
}

.reader-setting-check > span {
  color: rgba(255, 255, 255, .58);
  font-size: 9px;
  letter-spacing: .13em;
  text-transform: uppercase;
}

.reader-setting-check input[type="checkbox"] {
  justify-self: start;
  width: 13px;
  height: 13px;
  accent-color: var(--reader-accent);
}

.reader-list-card,
.reader-order-row,
.reader-bookmark-row,
.reader-source-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 10px;
  align-items: center;
  padding: 11px 0;
  border-bottom: 1px solid rgba(255, 255, 255, .08);
}

.reader-list-card strong,
.reader-order-row strong,
.reader-bookmark-row strong,
.reader-source-row strong {
  display: block;
  overflow: hidden;
  font-size: 12px;
  font-weight: 500;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.reader-list-card small,
.reader-order-row small,
.reader-bookmark-row small,
.reader-source-row small {
  display: block;
  margin-top: 3px;
  color: rgba(255, 255, 255, .43);
  font-size: 9px;
}

.reader-row-actions {
  display: flex;
  gap: 4px;
}

/* Swiss editorial: a word is already a control, so it doesn't need a box drawn
   round it. Type carries the affordance — micro-caps, wide tracking, a rule that
   appears on hover — and dropping the borders lets the rows align to one grid
   instead of to a row of chips. */
.reader-row-actions button,
.reader-create-row button,
.reader-rename-row button,
.reader-bookmark-add button,
.reader-panel-toolbar button,
.reader-source-actions button {
  min-height: 26px;
  padding: 0;
  border: 0;
  border-bottom: 1px solid transparent;
  border-radius: 0;
  color: rgba(255, 255, 255, .62);
  font-size: 9px;
  letter-spacing: .14em;
  text-transform: uppercase;
  transition: color 120ms ease, border-color 120ms ease;
}

.reader-row-actions button:hover:not(:disabled),
.reader-create-row button:hover,
.reader-rename-row button:hover,
.reader-bookmark-add button:hover,
.reader-panel-toolbar button:hover,
.reader-source-actions button:hover {
  border-bottom-color: currentColor;
  color: #fff;
}

.reader-row-actions button:focus-visible,
.reader-panel-toolbar button:focus-visible,
.reader-source-actions button:focus-visible {
  outline: 1px solid rgba(255, 255, 255, .5);
  outline-offset: 3px;
}

/* The arrows are glyphs, not words — tracking would push them off centre. */
.reader-row-actions button {
  min-width: 16px;
  font-size: 11px;
  letter-spacing: 0;
}

.reader-row-actions {
  gap: 14px;
}

.reader-row-actions button:disabled {
  opacity: .2;
}

/* The title is the control that opens the article. */
.reader-order-jump {
  display: block;
  overflow: hidden;
  width: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  color: inherit;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0;
  text-align: left;
  text-overflow: ellipsis;
  text-transform: none;
  white-space: nowrap;
}

.reader-order-jump:hover,
.reader-order-jump:focus-visible {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

.reader-panel-toolbar,
.reader-source-actions,
/* Quick themes read as a row of words separated by space, not as chips. */
.reader-preset-row {
  display: flex;
  flex-wrap: wrap;
  gap: 18px;
  margin-bottom: 14px;
}

.reader-preset-row button {
  padding: 0;
  border: 0;
  border-bottom: 1px solid transparent;
  border-radius: 0;
  background: transparent;
  color: rgba(255, 255, 255, .62);
  font-size: 9px;
  letter-spacing: .14em;
  text-transform: uppercase;
  transition: color 120ms ease, border-color 120ms ease;
}

.reader-preset-row button:hover {
  border-bottom-color: currentColor;
  color: #fff;
}

.reader-source-console {
  position: sticky;
  z-index: 3;
  top: -18px;
  margin: -18px -18px 18px;
  padding: 16px 18px 14px;
  border-bottom: 1px solid rgba(255, 255, 255, .11);
  background: #20242a;
  box-shadow: 0 14px 24px rgba(10, 12, 15, .18);
}

.reader-source-search {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 12px;
  align-items: center;
}

.reader-source-search > span {
  color: rgba(255, 255, 255, .54);
  font-size: 9px;
  letter-spacing: .08em;
}

.reader-source-console-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 10px;
}

.reader-source-hide {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  color: rgba(255, 255, 255, .57);
  font-size: 9px;
}

.reader-source-hide input {
  margin: 0;
  accent-color: var(--reader-accent);
}

.reader-source-count {
  color: rgba(255, 255, 255, .44);
  font-size: 9px;
  white-space: nowrap;
}

.reader-source-actions {
  margin: 12px 0 0;
}

.reader-source-actions .reader-source-apply {
  border-color: color-mix(in srgb, var(--reader-accent) 70%, rgba(255, 255, 255, .2));
  background: color-mix(in srgb, var(--reader-accent) 28%, transparent);
  color: #fff;
}

.reader-source-actions .reader-source-apply:disabled {
  border-color: rgba(255, 255, 255, .09);
  background: rgba(255, 255, 255, .025);
  color: rgba(255, 255, 255, .3);
}

.reader-source-groups {
  display: grid;
  gap: 10px;
}

.reader-source-group {
  overflow: clip;
  border: 1px solid rgba(255, 255, 255, .09);
  border-radius: 5px;
  background: rgba(255, 255, 255, .018);
}

.reader-source-group > summary {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 12px;
  align-items: center;
  min-height: 52px;
  padding: 9px 12px;
  cursor: pointer;
  list-style: none;
}

.reader-source-group > summary::-webkit-details-marker {
  display: none;
}

.reader-source-group > summary strong,
.reader-source-group > summary small {
  display: block;
}

.reader-source-group > summary strong {
  color: rgba(255, 255, 255, .78);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
}

.reader-source-group > summary small {
  margin-top: 3px;
  color: rgba(255, 255, 255, .37);
  font-size: 9px;
}

.reader-source-chevron {
  color: rgba(255, 255, 255, .42);
  font-size: 15px;
  transition: transform 160ms ease;
}

.reader-source-group[open] .reader-source-chevron {
  transform: rotate(180deg);
}

.reader-source-group-tools {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 7px 10px;
  border-top: 1px solid rgba(255, 255, 255, .07);
  border-bottom: 1px solid rgba(255, 255, 255, .07);
  background: rgba(0, 0, 0, .09);
}

.reader-source-group-tools > span {
  margin-right: auto;
  color: rgba(255, 255, 255, .37);
  font-size: 9px;
}

.reader-source-group-tools button {
  min-height: 26px;
  padding: 0 7px;
  border: 1px solid rgba(255, 255, 255, .1);
  border-radius: 3px;
  color: rgba(255, 255, 255, .59);
  font-size: 8px;
}

.reader-source-list {
  padding: 4px 8px 7px;
}

.reader-source-row {
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: 10px;
  min-height: 48px;
  padding: 7px 8px;
  border: 1px solid transparent;
  border-radius: 4px;
  cursor: pointer;
  content-visibility: auto;
  contain-intrinsic-size: 48px;
  transition: border-color 120ms ease, background 120ms ease;
}

.reader-source-row:hover {
  background: rgba(255, 255, 255, .035);
}

.reader-source-row.is-selected {
  border-color: color-mix(in srgb, var(--reader-accent) 58%, transparent);
  background: color-mix(in srgb, var(--reader-accent) 12%, transparent);
}

.reader-source-row[hidden] {
  display: none;
}

.reader-source-row input {
  margin: 0;
  accent-color: var(--reader-accent);
}

.reader-source-row.is-added {
  opacity: .5;
}

.reader-source-copy {
  min-width: 0;
}

.reader-source-added {
  padding: 3px 5px;
  border: 1px solid rgba(255, 255, 255, .11);
  border-radius: 99px;
  color: rgba(255, 255, 255, .45);
  font-size: 8px;
}

.reader-setting {
  display: grid;
  grid-template-columns: 104px minmax(0, 1fr) auto;
  gap: 10px;
  align-items: center;
  min-height: 42px;
  border-bottom: 1px solid rgba(255, 255, 255, .07);
}

.reader-setting > span {
  color: rgba(255, 255, 255, .62);
  font-size: 10px;
}

.reader-setting output {
  min-width: 42px;
  color: rgba(255, 255, 255, .5);
  font-size: 9px;
  text-align: right;
}

.reader-setting-check {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: 40px;
  border-bottom: 1px solid rgba(255, 255, 255, .07);
  color: rgba(255, 255, 255, .68);
  font-size: 10px;
}

.reader-setting-check input {
  accent-color: var(--reader-accent);
}

.reader-color-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px 14px;
}

.reader-color-grid label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  color: rgba(255, 255, 255, .62);
  font-size: 10px;
}

.reader-contrast-note {
  margin: 12px 0 0;
  color: #e6b871;
  font-size: 9px;
  line-height: 1.6;
}

.reader-panel-empty {
  margin: 12px 0;
  color: rgba(255, 255, 255, .42);
  font-size: 11px;
  line-height: 1.7;
}

@media (max-width: 900px) {
  .reader-topbar {
    grid-template-columns: auto minmax(100px, 1fr) auto;
    gap: 8px;
  }

  .reader-actions [data-reader-layout],
  .reader-actions [data-reader-animation] {
    display: none;
  }

  .reader-page-view {
    grid-template-columns: 36px minmax(0, 1fr) 36px;
    gap: 4px;
    padding: 8px;
  }

  .reader-page-nav {
    width: 32px;
  }
}

@media (max-width: 620px) {
  .reader-topbar {
    min-height: 52px;
    padding-inline: 10px;
  }

  .reader-close span:last-child,
  .reader-actions [data-reader-panel="bookmarks"] {
    display: none;
  }

  .reader-actions button {
    padding-inline: 6px;
  }

  .reader-heading strong {
    font-size: 12px;
  }

  .reader-page-view {
    grid-template-columns: minmax(0, 1fr);
  }

  .reader-page-nav {
    position: absolute;
    z-index: 7;
    top: 50%;
    background: color-mix(in srgb, var(--reader-bg) 82%, transparent) !important;
    transform: translateY(-50%);
  }

  .reader-page-nav[data-reader-prev] { left: 7px; }
  .reader-page-nav[data-reader-next] { right: 7px; }

  .reader-scroll-content {
    width: 100%;
    padding: 38px 22px 18vh;
  }

  .reader-color-grid {
    grid-template-columns: 1fr;
  }

  .reader-source-console-row {
    align-items: flex-start;
    flex-direction: column;
    gap: 7px;
  }

  .reader-source-count {
    white-space: normal;
  }

  .reader-source-group-tools {
    flex-wrap: wrap;
  }

  .reader-source-group-tools > span {
    width: 100%;
  }
}

@media (prefers-reduced-motion: reduce) {
  .reader-panel,
  .reader-panel-shade {
    transition: none;
  }

  .reader-turn-sheet,
  .reader-turn-sheet::after,
  .reader-turn-cast {
    animation: none !important;
    display: none !important;
  }
}
