(attempt to) render onscreen elements at print size
Hunter
Monday, July 27th, 2026 at 11:26 PM
50
51 const isUsingSafari = isSafari();
52
53 +const isUsingWindows = navigator.userAgent.includes('Windows');
54 +
55 // Parse URL parameters for custom cell size
56 function parseCellSizeFromURL() {
57 const urlParams = new URLSearchParams(window.location.search);
84 // Initialize cell size from URL
85 CELL_SIZE_MM = parseCellSizeFromURL();
86
87 +const PANEL_PPI = {
88 + 1920: 141, // 15.6" 1080p laptop
89 + 2560: 109, // 27" 1440p
90 + 2736: 267, // 12.3" 3:2 tablet
91 + 2880: 267, // 13" 3:2 tablet
92 + 3840: 163 // 27" 4K
93 +};
94 +
95 +function estimateWindowsPPI() {
96 + const pixelRatio = window.devicePixelRatio;
97 + if (pixelRatio === 1) return null;
98 +
99 + const nativeWidth = screen.width * pixelRatio;
100 + if (nativeWidth >= 3800 && pixelRatio >= 2) return null;
101 +
102 + const panel = Object.keys(PANEL_PPI).find(width => Math.abs(width - nativeWidth) <= width * 0.02);
103 +
104 + return panel ? PANEL_PPI[panel] / pixelRatio : null;
105 +}
106 +
107 +function estimateScreenPPI() {
108 + const logicalWidth = screen.width;
109 + const pixelRatio = window.devicePixelRatio;
110 +
111 + if (isUsingWindows) {
112 + const windowsPPI = estimateWindowsPPI();
113 + if (windowsPPI) return windowsPPI;
114 + }
115 +
116 + if (logicalWidth >= 3840) return 163; // 27" 4K, OS scaling off
117 + if (logicalWidth >= 2048) return 109; // 27" 5K retina or 1440p
118 + if (logicalWidth >= 1800) return 92.6; // 23.8" 1080p and friends
119 +
120 + return pixelRatio > 1 ? 127.7 : 92.6; // retina laptop (2560px / 227ppi), else standard density
121 +}
122 +
123 +// Life-size page width; CSS clamps this to the viewport so it never overflows horizontally
124 +function applyPageWidth() {
125 + const pageWidth = (LETTER_WIDTH_MM / 25.4) * estimateScreenPPI();
126 + document.documentElement.style.setProperty('--page-width', `${pageWidth}px`);
127 + updateGridLineWidth();
128 +}
129 +
130 +const baselinePixelRatio = window.devicePixelRatio;
131 +
132 +function updateGridLineWidth() {
133 + const zoom = window.devicePixelRatio / baselinePixelRatio;
134 + document.documentElement.style.setProperty('--line-width', `${Math.min(1, 1 / zoom)}px`);
135 +}
136 +
137 +applyPageWidth();
138 +
139 // Calculate grid dimensions based on cell size
140 const gridDimensions = calculateGridDimensions(CELL_SIZE_MM);
141 GRID_COLS = gridDimensions.cols;
1163
1164 // Update all image positions when window resizes (for responsive scaling)
1165 window.addEventListener('resize', () => {
1166 + applyPageWidth(); // display or zoom may have changed
1167 images.forEach(img => {
1168 updateImagePosition(img);
1169 });
123 display: flex;
124 justify-content: center;
125 align-items: flex-start;
126 + align-items: safe center;
127 min-height: 100vh;
128 padding: 20px;
129 }
130
131 .page {
- /* Scale down on narrow screens, but never larger than 8.5in */
- max-width: min(8.5in, calc(100vw - 40px));
- width: 100%;
- /* Maintain 8.5:11 aspect ratio (11/8.5 = 1.294117647) */
132 + width: min(100%, var(--page-width, 8.5in));
133 aspect-ratio: 8.5 / 11;
134 background: var(--page);
135 position: relative;
157 width: 100%;
158 height: 100%;
159 box-sizing: border-box;
- border-top: 1px dashed var(--grid-line);
- border-left: 1px dashed var(--grid-line);
160 + border-top: var(--line-width, 1px) dashed var(--grid-line);
161 + border-left: var(--line-width, 1px) dashed var(--grid-line);
162 margin: 0;
163 padding: 0;
164 display: block;
166
167 /* Add right border to rightmost column */
168 .grid-cell.right-edge {
- border-right: 1px dashed var(--grid-line);
- width: calc(100% + 1px);
169 + border-right: var(--line-width, 1px) dashed var(--grid-line);
170 + width: calc(100% + var(--line-width, 1px));
171 }
172
173 /* Add bottom border to bottom row */
174 .grid-cell.bottom-edge {
- border-bottom: 1px dashed var(--grid-line);
- height: calc(100% + 1px);
175 + border-bottom: var(--line-width, 1px) dashed var(--grid-line);
176 + height: calc(100% + var(--line-width, 1px));
177 }
178
179 /* Solid grid lines for cell sizes <= 3.56mm (screen preview only) */
200 }
201
202 .page {
- max-width: 100vw;
203 box-shadow: none;
204 }
205
213 .grid-cell.right-edge {
214 border-right-style: solid;
215 border-right-color: var(--grid-line-light);
- width: calc(100% + 1px);
216 + width: calc(100% + var(--line-width, 1px));
217 }
218
219 .grid-cell.bottom-edge {
220 border-bottom-style: solid;
221 border-bottom-color: var(--grid-line-light);
- height: calc(100% + 1px);
222 + height: calc(100% + var(--line-width, 1px));
223 }
224 }
225