/**
 * Pure camera math over the continuous page stack. Doc space is pt
 * (pages stacked vertically per `page_layout()`); the camera maps a
 * doc point `p` to viewport CSS px as `scroll + p * zoom`. Everything
 * here is side-effect-free so the invariants (zoom-to-anchor, fit,
 * clamps, current-page) are unit-testable without a canvas.
 */
import type { SessionPagesLayout } from "./session.js";
export interface Camera {
    /** CSS px per pt. */
    zoom: number;
    /** Doc origin in viewport CSS px. */
    x: number;
    y: number;
}
export interface Viewport {
    /** CSS px. */
    width: number;
    height: number;
}
export interface ZoomLimits {
    min: number;
    max: number;
}
/** Default page-fit margin — matches the wasm fit-page present. */
export declare const FIT_MARGIN = 0.95;
export declare function clampZoom(zoom: number, limits: ZoomLimits): number;
/** Total doc-space extents of the continuous stack (pt). */
export declare function contentExtent(layout: SessionPagesLayout): {
    width: number;
    height: number;
};
/**
 * Zoom about an anchor point (viewport CSS px): the doc point under
 * the anchor stays under it. With no anchor, zoom about the viewport
 * centre.
 */
export declare function zoomAt(camera: Camera, nextZoom: number, limits: ZoomLimits, viewport: Viewport, anchor?: {
    x: number;
    y: number;
}): Camera;
/**
 * Keep content on screen: per axis, content smaller than the viewport
 * centres; larger content clamps so no blank gap opens at either edge.
 */
export declare function clampScroll(camera: Camera, layout: SessionPagesLayout, viewport: Viewport): Camera;
/**
 * Fit a page: `"page"` fits both dimensions, `"width"` fits the page
 * width (top-aligned to the page). Returns the camera centred on the
 * page in continuous coordinates; single-page mode passes a layout
 * containing just that page at `yPt: 0`.
 */
export declare function fitPage(layout: SessionPagesLayout, pageIndex: number, mode: "page" | "width", viewport: Viewport, limits: ZoomLimits): Camera;
/**
 * The page whose band contains the viewport-centre line (continuous
 * mode). Falls back to the nearest band when the centre sits in a gap.
 */
export declare function currentPageAt(camera: Camera, layout: SessionPagesLayout, viewport: Viewport): number;
/** Scroll that brings `pageIndex`'s top into view (continuous mode). */
export declare function scrollToPage(camera: Camera, layout: SessionPagesLayout, pageIndex: number, viewport: Viewport): Camera;
