diff --git a/public/css/arf.css b/public/css/arf.css
index 3e4e894..2c52415 100644
--- a/public/css/arf.css
+++ b/public/css/arf.css
@@ -70,6 +70,8 @@ body {
color: var(--color-text-primary);
font-size: var(--font-size-base);
font-family: var(--font-family);
+ margin: 0;
+ overflow: hidden;
}
noscript p {
@@ -94,7 +96,8 @@ noscript p {
svg {
display: block;
width: 100%;
- height: auto;
+ /* Fill remaining viewport height below header + search bar */
+ height: calc(100vh - 120px);
cursor: grab;
}
@@ -109,7 +112,6 @@ svg:active {
position: relative;
font-size: var(--font-size-xl);
font-weight: bold;
- top: 20px;
text-align: center;
color: var(--color-header);
padding: var(--space-2) var(--space-4);
@@ -393,10 +395,6 @@ a {
padding: var(--space-2) var(--space-3);
}
- #header hr {
- display: none;
- }
-
#header-actions {
right: var(--space-3);
}
@@ -417,7 +415,7 @@ a {
/* Maximize SVG tree viewport */
svg {
- min-height: 60vh;
+ height: calc(100vh - 80px);
}
/* Floating notes button (mobile only) */
diff --git a/public/index.html b/public/index.html
index 4abff3c..9fc8790 100644
--- a/public/index.html
+++ b/public/index.html
@@ -31,7 +31,6 @@
-
diff --git a/public/js/arf.js b/public/js/arf.js
index 7bbe86a..5919e9e 100644
--- a/public/js/arf.js
+++ b/public/js/arf.js
@@ -84,38 +84,36 @@ d3.json("arf.json").then(function(json) {
root.children.forEach(collapse);
- // On mobile, stretch the viewBox to match the actual rendered aspect ratio
- // so the zoom-to-fill calculation uses the real visible area, not the
- // fixed 1280x800 letterboxed region.
- if (window.innerWidth <= 768) {
- var rect = svgEl.node().getBoundingClientRect();
- if (rect.width && rect.height) {
- svgH = Math.round(svgW * (rect.height / rect.width));
- svgEl.attr("viewBox", "0 0 " + svgW + " " + svgH);
- }
-
- // Run tree layout to get final node positions, then compute zoom from data.
- tree(root);
- root.descendants().forEach(function(d) { d.y = d.depth * 180; });
- var visibleNodes = root.descendants();
- var minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;
- visibleNodes.forEach(function(d) {
- if (d.x < minX) minX = d.x;
- if (d.x > maxX) maxX = d.x;
- if (d.y < minY) minY = d.y;
- if (d.y > maxY) maxY = d.y;
- });
- var pad = 40;
- var bw = (maxY - minY) || 1;
- var bh = (maxX - minX) || 1;
- var k = Math.min((svgW - pad * 2) / bw, (svgH - pad * 2) / bh, 3);
- var cx = (minY + maxY) / 2;
- var cy = (minX + maxX) / 2;
- var tx = svgW / 2 - margin[3] - cx * k;
- var ty = svgH / 2 - margin[0] - cy * k;
- svgEl.call(zoom.transform, d3.zoomIdentity.translate(tx, ty).scale(k));
+ // Stretch the viewBox to match the actual rendered aspect ratio so the
+ // zoom-to-fill calculation uses the real visible area, not the fixed
+ // 1280x800 letterboxed region.
+ var rect = svgEl.node().getBoundingClientRect();
+ if (rect.width && rect.height) {
+ svgH = Math.round(svgW * (rect.height / rect.width));
+ svgEl.attr("viewBox", "0 0 " + svgW + " " + svgH);
}
+ // Run tree layout to get final node positions, then compute zoom from data.
+ tree(root);
+ root.descendants().forEach(function(d) { d.y = d.depth * 180; });
+ var visibleNodes = root.descendants();
+ var minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;
+ visibleNodes.forEach(function(d) {
+ if (d.x < minX) minX = d.x;
+ if (d.x > maxX) maxX = d.x;
+ if (d.y < minY) minY = d.y;
+ if (d.y > maxY) maxY = d.y;
+ });
+ var pad = 40;
+ var bw = (maxY - minY) || 1;
+ var bh = (maxX - minX) || 1;
+ var k = Math.min((svgW - pad * 2) / bw, (svgH - pad * 2) / bh, 3);
+ var cx = (minY + maxY) / 2;
+ var cy = (minX + maxX) / 2;
+ var tx = svgW / 2 - margin[3] - cx * k;
+ var ty = svgH / 2 - margin[0] - cy * k;
+ svgEl.call(zoom.transform, d3.zoomIdentity.translate(tx, ty).scale(k));
+
update(root);
initSearch();
});