Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/arverma/Bihar-Police-Notebook/llms.txt

Use this file to discover all available pages before exploring further.

Bihar Police Notebook displays A4 pages at their true print dimensions in the DOM, then applies a CSS transform: scale() to shrink or grow them visually to fit the available window width. The scale is purely cosmetic — all layout measurements, overflow detection, and print geometry operate on the original unscaled dimensions. The scaling system is implemented in editor/js/page-scale.js and editor/css/page-preview.css.

DOM Hierarchy

The scale mechanism operates on three nested elements:
#editorStage  (.editor-stage)
└── .editor-scale
    └── .editor-letter  /  .editor-diary  (Letter or Diary wrapper)
        ├── .letter-page  (× N)
        └── .diary-page   (× N)
The CSS transform is applied to .editor-scale. Inner page elements always render at their true A4 pixel dimensions; only the containing scale element is transformed.

Why a separate .editor-scale wrapper?

Applying transform directly to .editor-stage would interfere with scroll geometry. The intermediate .editor-scale wrapper gives the scale system a clean target that does not affect the scroll container or the layout of sibling elements.

Scale Logic

initPageScale() in page-scale.js sets up the scale controller and returns a handle used by main.js.

Fit-to-Width Calculation

On every refresh() call the controller:
  1. Reads the available width of .editor-stage (the scroll port).
  2. Reads the natural rendered width of the .editor-scale element (the A4 content width plus margins).
  3. Computes scale = stageWidth / contentWidth, clamped to a sensible range.
  4. Sets transform: scale(scale) and transform-origin: top center on .editor-scale.

Negative-Margin Collapse

A naive scale implementation would leave a gap equal to (1 - scale) * contentHeight below the scaled content — the DOM still reserves space for the unscaled dimensions. page-preview.css uses a negative bottom margin technique to collapse this surplus:
.editor-scale {
  transform-origin: top center;
  /* Negative margin equals the visual height reduction */
  margin-bottom: calc((var(--scale, 1) - 1) * 100%);
}
This approach is chosen over height: 0 clipping or absolute positioning because it allows multi-page diary layouts to flow naturally — no page is cut off mid-scroll.
The negative margin is recalculated after every refresh() call so it stays accurate as the user resizes the window or adds diary pages.

Behaviour by Device Class

The page is automatically scaled to fill the available width. There is no manual zoom UI — fit-to-width is always maintained. refresh() is called on:
  • Window resize (via ResizeObserver on .editor-stage)
  • Template switch (switchTemplate)
  • Document load (loadDocumentState)
  • New document creation (startNewDocument)
  • onPageFocus callback (when the diary adds a page)
The scale factor is exposed via pageScale.getScale() so the transliteration suggestion popup (showSuggestions) can offset its coordinates correctly.

API

initPageScale()

import { initPageScale } from './page-scale.js';

const pageScale = initPageScale();
Initialises the scale controller. Attaches a ResizeObserver to .editor-stage and calls refresh() on the first available animation frame. Returns a controller object. Returned controller:
refresh()
() => void
Recomputes and applies the fit-to-width scale immediately. Call this after any layout change that affects the page content area (template switch, page add/delete, document load).
getScale()
() => number
Returns the current numeric scale factor (e.g. 0.72 for 72 % scale). Used by the transliteration popup to convert element-relative coordinates to viewport coordinates.

CSS Files

FileScope
page-preview.css.editor-scale transform and negative-margin rules, @media print reset, Fit chip styles, mobile pinch-zoom touch-action rules
page-scale.jsRuntime scale computation, ResizeObserver wiring, pinch/double-tap event handlers
When adding new page types or changing the A4 page width constants in paged-sheet.js or diary-sheet.js, always call pageScale.refresh() afterwards so the scale controller picks up the new natural content width.
Do not apply overflow: hidden to .editor-scale — this would clip multi-page diary content at the scaled boundary. The negative-margin technique depends on the content overflowing visually while the parent scrolls to the correct height.

Build docs developers (and LLMs) love