/* viewer.css - the desk (scroll container), the column of pages and each page's layers.
   Owns #desk, #pages, .page and .page-* (docs/ARCHITECTURE.md section 3).

   Stacking inside a page: .page-space (transformed, so its own stacking context) holds the
   canvas and the five layers, painted in DOM order. The search, object and tool layers get
   no z-index on purpose: a z-index would make them isolated groups and objects with
   mix-blend-mode: multiply (highlights, marker ink, and the tool-layer's own live drag
   previews of both) could no longer blend with the PDF canvas underneath. The form layer
   gets z-index: 0, which keeps the same DOM-order painting but contains its children's own
   z-indexes (it has no blended content of its own). */

/* ------------------------------------------------------------------ app chrome
   The bars and panels around the desk are never text to select: a native select-all that
   still reaches them (context menu > Select all, or Ctrl+A with a dialog open) would
   highlight - and Ctrl+C copy - the file name, mode buttons, zoom and status text along with
   the document. Ctrl+A in View mode itself is handled by viewer.js (selects the page's text).
   Editable fields inside keep their own text selection (Safari needs it stated). */

#topbar,
#toolstrip,
#left-panel,
#right-panel,
#statusbar {
    -webkit-user-select: none;
    user-select: none;
}

:is(#topbar, #toolstrip, #left-panel, #right-panel, #statusbar) :is(input, textarea, [contenteditable]:not([contenteditable="false"])) {
    -webkit-user-select: text;
    user-select: text;
}

/* ------------------------------------------------------------------ desk */

#desk {
    position: relative;
    min-width: 0;
    min-height: 0;
    overflow: auto;
    overscroll-behavior: contain;
    overflow-anchor: none;             /* viewer.js keeps the view steady itself */
    scrollbar-gutter: stable;          /* fit-width must not oscillate with the scrollbar */
    touch-action: pan-x pan-y;         /* native one-finger scroll; pinch is ours */
    -webkit-tap-highlight-color: transparent;
    background-color: var(--desk);
    background-image: radial-gradient(circle, var(--desk-dot) 1px, transparent 1.5px);
    background-size: 20px 20px;
    background-attachment: local;      /* the dot grid scrolls with the pages */
}

#desk:focus {
    outline: none;
}

/* The column of pages. `max-content` + `min-width: 100%` lets a page wider than the desk
   widen the column (horizontal scroll) instead of being clipped on the left. */
#pages {
    position: relative;
    box-sizing: border-box;
    width: max-content;
    min-width: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 24px;
    padding: 32px 40px 64px;
}

#desk[data-empty] #pages::before {
    content: "This document has no pages. Add pages in Pages mode.";
    margin-top: 12vh;
    font: var(--fs-m) / 1.4 var(--font-ui);
    color: var(--text-3);
}

@media (max-width: 640px) {
    #pages {
        padding: 16px 12px 48px;
    }
}

/* ------------------------------------------------------------------ page */

.page {
    position: relative;
    flex: none;
    background: var(--paper);
    border-radius: 2px;
    box-shadow: var(--shadow-page);
}

.page-space {
    position: absolute;
    left: 0;
    top: 0;
    transform-origin: 0 0;
}

/* The pdf.js bitmap: sized in points inside .page-space and counter-rotated by viewer.js,
   so it always covers the page box exactly while its pixels stay in rotation R. */
.page-canvas {
    position: absolute;
    left: 0;
    top: 0;
    display: block;
    transform-origin: 0 0;
    pointer-events: none;
    -webkit-user-select: none;
    user-select: none;
}

.page-space > .layer {
    position: absolute;
    inset: 0;
    pointer-events: none;
}

/* Objects, search hits and form inputs never show outside the sheet. `clip` rather than
   `hidden`: it cannot be scrolled when a focused input sits near an edge. */
.page-space > .search-layer,
.page-space > .object-layer,
.page-space > .form-layer {
    overflow: clip;
}

.page-space > .form-layer {
    z-index: 0;
}

/* Text selection is live only in View mode with the Select text tool. */
#desk[data-text-select] .text-layer,
body[data-mode="view"][data-tool="text-select"] .text-layer {
    pointer-events: auto;
}

.page-number {
    position: absolute;
    left: 0;
    right: 0;
    top: calc(100% + 4px);
    font: 500 var(--fs-xs) / 14px var(--font-mono);
    font-variant-numeric: tabular-nums;
    text-align: center;
    color: var(--text-3);
    pointer-events: none;
    -webkit-user-select: none;
    user-select: none;
}

.page.current > .page-number {
    color: var(--ink);
    font-weight: 600;
}

/* Shown on a page whose content pdf.js could not draw. A themed chip, because the sheet
   itself stays white in dark mode. */
.page-error {
    position: absolute;
    left: 50%;
    top: 50%;
    box-sizing: border-box;
    width: min(80%, 280px);
    padding: 10px 14px;
    transform: translate(-50%, -50%);
    font: var(--fs-s) / 1.45 var(--font-ui);
    text-align: center;
    color: var(--text-2);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    box-shadow: var(--shadow-1);
    pointer-events: none;
}

/* ------------------------------------------------------------------ pdf.js text layer
   Adapted from pdf.js 6.3.289 web/text_layer_builder.css (.textLayer -> .text-layer).
   TextLayer is built at scale 1, rotation 0 inside .page-space (1 unit = 1pt), so the
   scale variables it reads are all 1; zoom and rotation come from the parent transform.
   TextLayer sets per span: left/top (%), --font-height, font-family, --scale-x, --rotate;
   on the container: --min-font-size, width/height (overridden here: inset 0 is exact). */

.text-layer {
    position: absolute;
    inset: 0;
    width: auto !important;
    height: auto !important;
    overflow: clip;
    opacity: 1;
    line-height: 1;
    text-align: initial;
    -webkit-text-size-adjust: none;
    -moz-text-size-adjust: none;
    text-size-adjust: none;
    forced-color-adjust: none;
    transform-origin: 0 0;
    caret-color: CanvasText;
    z-index: 0;
    -webkit-user-select: text;
    user-select: text;

    --scale-factor: 1;
    --user-unit: 1;
    --total-scale-factor: calc(var(--scale-factor) * var(--user-unit));
    --scale-round-x: 1px;
    --scale-round-y: 1px;
    --min-font-size: 1;
    --text-scale-factor: calc(var(--total-scale-factor) * var(--min-font-size));
    --min-font-size-inv: calc(1 / var(--min-font-size));
}

.text-layer :is(span, br) {
    position: absolute;
    color: transparent;
    white-space: pre;
    cursor: text;
    transform-origin: 0% 0%;
}

.text-layer > :not(.markedContent),
.text-layer .markedContent span:not(.markedContent) {
    z-index: 1;
    --font-height: 0;
    font-size: calc(var(--text-scale-factor) * var(--font-height));
    --scale-x: 1;
    --rotate: 0deg;
    transform: rotate(var(--rotate)) scaleX(var(--scale-x)) scale(var(--min-font-size-inv));
}

.text-layer span.markedContent {
    top: 0;
    height: 0;
}

.text-layer span[role="img"] {
    -webkit-user-select: none;
    user-select: none;
    cursor: default;
}

.text-layer ::selection {
    background: var(--select-soft);
    background: color-mix(in srgb, var(--select) 30%, transparent);
}

/* Chrome paints a selection box for line breaks; hide it (pdf.js issue 13840). */
.text-layer br::selection {
    background: transparent;
}

.text-layer .endOfContent {
    display: block;
    position: absolute;
    inset: 100% 0 0;
    z-index: 0;
    cursor: default;
    -webkit-user-select: none;
    user-select: none;
}

.text-layer.selecting .endOfContent {
    top: 0;
}
