/* Codex Publicus page viewer. Every color, font and size reads a --cpv-* custom
   property with a system-color or neutral fallback, so the component works
   unthemed and a host themes it from its own stylesheet. */

.cpv {
  display: block;
  color: var(--cpv-text, CanvasText);
  background: var(--cpv-surface, Canvas);
  font-family: var(--cpv-font-ui, system-ui, sans-serif);
}

.cpv__chrome {
  display: flex;
  flex-direction: column;
  gap: var(--cpv-space, 0.5rem);
  padding-block-end: var(--cpv-space, 0.5rem);
}

.cpv__toolbar,
.cpv__selbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--cpv-space, 0.5rem);
}

/* The selection toolbar keeps its space while idle: if it pushed the pages
   down when it appeared, the text under a pointer drag would move mid-drag.
   Idle, it is invisible and out of the tab order and the accessibility tree. */
.cpv__selbar:not([data-active="true"]) {
  visibility: hidden;
}

.cpv__notice[hidden],
.cpv-page__read[hidden] {
  display: none;
}

.cpv__button {
  font: inherit;
  color: var(--cpv-text, CanvasText);
  background: transparent;
  border: 1px solid var(--cpv-text-muted, color-mix(in srgb, CanvasText 70%, Canvas));
  border-radius: var(--cpv-radius, 4px);
  padding: 0.25em 0.6em;
  cursor: pointer;
  text-decoration: none;
}

.cpv__button:hover {
  border-color: var(--cpv-accent, LinkText);
  color: var(--cpv-accent, LinkText);
}

.cpv__button:disabled,
.cpv__button[aria-disabled="true"] {
  cursor: not-allowed;
  color: var(--cpv-text-muted, color-mix(in srgb, CanvasText 70%, Canvas));
  border-style: dashed;
}

.cpv__button[aria-pressed="true"] {
  border-color: var(--cpv-accent, LinkText);
  color: var(--cpv-accent, LinkText);
}

.cpv :focus-visible {
  outline: 3px solid var(--cpv-focus, Highlight);
  outline-offset: 2px;
}

/* The field takes the viewer's own colors, so a host's dark tokens reach it
   instead of the user agent's light field. */
.cpv__pageno-input {
  font: inherit;
  font-family: var(--cpv-font-mono, ui-monospace, monospace);
  inline-size: 4.5ch;
  color: var(--cpv-text, CanvasText);
  background: var(--cpv-surface, Canvas);
  border: 1px solid var(--cpv-text-muted, color-mix(in srgb, CanvasText 70%, Canvas));
  border-radius: var(--cpv-radius, 4px);
  padding: 0.15em 0.3em;
}

.cpv__zoom,
.cpv-page__number {
  font-family: var(--cpv-font-mono, ui-monospace, monospace);
  color: var(--cpv-text-muted, color-mix(in srgb, CanvasText 70%, Canvas));
}

.cpv__notice {
  margin: 0;
  color: var(--cpv-text, CanvasText);
  border-inline-start: 4px solid var(--cpv-accent, LinkText);
  padding-inline-start: var(--cpv-space, 0.5rem);
}

.cpv-visually-hidden {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* The pages scroll inside their own container, in both directions, so the
   chrome above never scrolls sideways at high zoom (WCAG 1.4.10). */
.cpv__pages {
  position: relative;
  block-size: var(--cpv-height, 80vh);
  overflow: auto;
  display: grid;
  gap: calc(var(--cpv-space, 0.5rem) * 3);
  justify-items: safe center;
  align-content: start;
  padding: var(--cpv-space, 0.5rem);
}

.cpv-page {
  display: grid;
  gap: calc(var(--cpv-space, 0.5rem) / 2);
  inline-size: 100%;
  justify-items: safe center;
}

.cpv--zoom-fit .cpv-page__frame,
.cpv--zoom-fit .cpv-page__sheet {
  inline-size: 100%;
}

/* Surface and overlays share one grid area; the overlay SVG sizes the cell
   from its viewBox (and its width attribute at a fixed zoom), and the surface
   fills it without contributing a size of its own. The frame stacks the
   annotation layer over the sheet the same way: beside the role="img" sheet,
   not inside it, because the children of an image are presentational and
   its links would be unreachable. */
.cpv-page__frame,
.cpv-page__sheet {
  display: grid;
}

.cpv-page__sheet {
  box-shadow: var(--cpv-page-shadow, none);
  background: var(--cpv-page-paper, white);
}

.cpv-page__frame > *,
.cpv-page__sheet > * {
  grid-area: 1 / 1;
}

.cpv-page__surface {
  contain: size;
  inline-size: 100%;
  block-size: 100%;
  filter: var(--cpv-page-filter, none);
}

.cpv-page__overlay {
  display: block;
  block-size: auto;
  max-inline-size: none;
  mix-blend-mode: multiply;
  cursor: text;
  user-select: text;
}

.cpv--zoom-fit .cpv-page__overlay {
  inline-size: 100%;
}

/* Positioned above the overlay: the overlay's blend mode makes it a stacking
   context, which would otherwise paint over the links and take their clicks. */
.cpv-page__annotations {
  position: relative;
  z-index: 1;
  contain: size;
  inline-size: 100%;
  block-size: 100%;
  pointer-events: none;
}

.cpv-page__annotations .cpv-hl {
  pointer-events: auto;
  cursor: pointer;
}

/* Highlights never take the pointer or the selection; only word text does. */
.cpv-layer-hl {
  pointer-events: none;
  user-select: none;
}

.cpv-layer-text text {
  fill: transparent;
  white-space: pre;
}

.cpv-layer-text text::selection {
  fill: transparent;
  background: transparent;
}

.cpv-hl {
  stroke: none;
}

.cpv-hl--passage {
  fill: var(--cpv-hl-passage, color-mix(in srgb, Mark 35%, transparent));
  stroke: var(--cpv-hl-passage-edge, CanvasText);
  stroke-width: 1px;
  vector-effect: non-scaling-stroke;
}

.cpv-hl--selection {
  fill: var(--cpv-hl-selection, color-mix(in srgb, Highlight 30%, transparent));
}

.cpv-hl--focus {
  fill: var(--cpv-hl-focus, color-mix(in srgb, var(--cpv-accent, LinkText) 25%, transparent));
  stroke: var(--cpv-accent, LinkText);
  stroke-width: 2px;
  vector-effect: non-scaling-stroke;
}

[class*="cpv-hl--annotation-"] {
  fill: color-mix(in srgb, var(--cpv-accent, LinkText) 15%, transparent);
  stroke: var(--cpv-accent, LinkText);
  stroke-width: 1px;
  stroke-dasharray: 3 2;
  vector-effect: non-scaling-stroke;
}

.cpv-annotation:focus-visible .cpv-hl {
  stroke: var(--cpv-focus, Highlight);
  stroke-width: 3px;
  stroke-dasharray: none;
}

.cpv-page__meta {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--cpv-space, 0.5rem);
  justify-content: center;
}

.cpv-page__read,
.cpv-fallback a {
  color: var(--cpv-accent, LinkText);
}

@media (forced-colors: active) {
  .cpv-hl--passage,
  .cpv-hl--focus,
  .cpv-hl--selection {
    fill: Highlight;
    fill-opacity: 0.35;
    stroke: CanvasText;
    stroke-width: 2px;
  }

  .cpv-page__overlay {
    mix-blend-mode: normal;
  }
}
