Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions build/pages/index.en.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
<meta name="twitter:card" content="summary_large_image">
<link rel="stylesheet" href="fonts.css?v=20260821">
<link rel="stylesheet" href="tokens.css?v=20260822">
<link rel="stylesheet" href="style.css?v=20260822c">
<link rel="stylesheet" href="style.css?v=20260822d">
<script src="i18n.js?v=20260821"></script>
<script src="i18n-data.js?v=20260821"></script>
<script src="i18n-map.js?v=20260822"></script>
Expand Down Expand Up @@ -442,6 +442,6 @@ <h2 id="introTitle">Follow the water. Protect its pathways.</h2>

<script src="fmt.js?v=20260822"></script>
<script src="gschg31.js?v=20260821"></script>
<script src="app.js?v=20260822b"></script>
<script src="app.js?v=20260822c"></script>
</body>
</html>
6 changes: 6 additions & 0 deletions scripts/verify-site.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@ for (const [label, pattern] of [
['independently scrolling evidence', /#workspace #legend\s*\{[^}]*flex:\s*1 1 auto;[^}]*overflow-y:\s*auto/s],
['stacked portrait workspace', /@media \(max-width:\s*900px\) and \(orientation:\s*portrait\)[\s\S]*?#workspace\s*\{[^}]*height:\s*var\(--workspace-h\)[\s\S]*?#map, #flow\s*\{[^}]*width:\s*100vw;[^}]*height:\s*calc\(100dvh - var\(--workspace-h\)\)/s],
['compact short-landscape rail', /@media \(max-height:\s*560px\) and \(orientation:\s*landscape\)[\s\S]*?#workspace #modes\s*\{[^}]*overflow-x:\s*auto/s],
['discoverable narrow layer rail', /#workspace #modeRail\.canScrollForward \.modeRailCue-end\s*\{\s*opacity:\s*1/s],
['useful smallest-phone evidence height', /@media \(max-width:\s*480px\) and \(max-height:\s*650px\) and \(orientation:\s*portrait\)\s*\{[\s\S]*?--workspace-h:\s*62dvh/s],
['sidebar project brief', /#workspace #intro\s*\{[^}]*position:\s*absolute;[^}]*inset:\s*0;[^}]*height:\s*100%/s],
['sidebar map readout', /#workspace #tooltip\s*\{[^}]*position:\s*static;[^}]*border-bottom:/s],
['high-contrast control boundary token', /--control-border:\s*#[0-9a-f]{6}/i],
Expand All @@ -183,6 +185,10 @@ if (!/window\.visualViewport\?\.addEventListener\(['"]resize['"]/.test(appSource
if (!/modeNav\.addEventListener\(['"]wheel['"]/.test(appSource)) {
fail(join(site, 'app.js'), 'intermediate mode rail has no practical mouse-wheel navigation');
}
if (!/modeNav\.addEventListener\(['"]scroll['"],\s*syncCues/.test(appSource) ||
!/classList\.toggle\(['"]canScrollForward['"]/.test(appSource)) {
fail(join(site, 'app.js'), 'narrow mode rail does not disclose additional layers');
}
if (!/workspace\.append\(el\)/.test(appSource) || !/dialog\.show\(\)/.test(appSource) || /dialog\.showModal\(\)/.test(appSource)) {
fail(join(site, 'app.js'), 'project brief must occupy the evidence workspace without covering the map');
}
Expand Down
27 changes: 27 additions & 0 deletions site/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,23 @@ for (const id of ['titlebar', 'modes', 'mapControls', 'tooltip', 'legend', 'ribb
const publicationCredits = document.getElementById('credits');
if (publicationCredits) document.getElementById('legendBody')?.append(publicationCredits);

// On narrow screens the layers form a real horizontal rail. Give that rail a
// stable shell so its two quiet edge cues can stay fixed while the buttons move
// beneath them. The cues are visual only: touch, trackpad, wheel and keyboard
// navigation keep operating on the native scroll container.
const layerModes = document.getElementById('modes');
const modeRail = document.createElement('div');
modeRail.id = 'modeRail';
layerModes.before(modeRail);
modeRail.append(layerModes);
for (const [side, arrow] of [['start', '\u2039'], ['end', '\u203a']]) {
const cue = document.createElement('span');
cue.className = `modeRailCue modeRailCue-${side}`;
cue.setAttribute('aria-hidden', 'true');
cue.textContent = arrow;
modeRail.append(cue);
}

const ENDPOINT = 'https://lindas.admin.ch/query';

/* ---- the palette -----------------------------------------------------------
Expand Down Expand Up @@ -2063,13 +2080,23 @@ for (const b of document.querySelectorAll('#modes button')) {
(function practicalModeRail() {
const modeNav = document.getElementById('modes');
if (!modeNav) return;
const rail = document.getElementById('modeRail');
const syncCues = () => {
const max = Math.max(0, modeNav.scrollWidth - modeNav.clientWidth);
rail?.classList.toggle('canScrollBack', max > 4 && modeNav.scrollLeft > 6);
rail?.classList.toggle('canScrollForward', max > 4 && modeNav.scrollLeft < max - 6);
};
modeNav.addEventListener('wheel', event => {
const max = modeNav.scrollWidth - modeNav.clientWidth;
if (max <= 2 || Math.abs(event.deltaX) >= Math.abs(event.deltaY)) return;
const before = modeNav.scrollLeft;
modeNav.scrollLeft = Math.max(0, Math.min(max, before + event.deltaY));
if (modeNav.scrollLeft !== before) event.preventDefault();
}, { passive: false });
modeNav.addEventListener('scroll', syncCues, { passive: true });
window.addEventListener('resize', syncCues, { passive: true });
if ('ResizeObserver' in window) new ResizeObserver(syncCues).observe(modeNav);
requestAnimationFrame(syncCues);
})();

// ---- accessible data view --------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion site/data/provenance.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions site/de/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
<meta name="twitter:card" content="summary_large_image">
<link rel="stylesheet" href="../fonts.css?v=20260821">
<link rel="stylesheet" href="../tokens.css?v=20260822">
<link rel="stylesheet" href="../style.css?v=20260822c">
<link rel="stylesheet" href="../style.css?v=20260822d">
<script src="../i18n.js?v=20260821"></script>
<script src="../i18n-data.js?v=20260821"></script>
<script src="../i18n-map.js?v=20260822"></script>
Expand Down Expand Up @@ -393,6 +393,6 @@ <h2 id="introTitle">Dem Wasser folgen. Seine Wege schützen.</h2>

<script src="../fmt.js?v=20260822"></script>
<script src="../gschg31.js?v=20260821"></script>
<script src="../app.js?v=20260822b"></script>
<script src="../app.js?v=20260822c"></script>
</body>
</html>
4 changes: 2 additions & 2 deletions site/en/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
<meta name="twitter:card" content="summary_large_image">
<link rel="stylesheet" href="../fonts.css?v=20260821">
<link rel="stylesheet" href="../tokens.css?v=20260822">
<link rel="stylesheet" href="../style.css?v=20260822c">
<link rel="stylesheet" href="../style.css?v=20260822d">
<script src="../i18n.js?v=20260821"></script>
<script src="../i18n-data.js?v=20260821"></script>
<script src="../i18n-map.js?v=20260822"></script>
Expand Down Expand Up @@ -442,6 +442,6 @@ <h2 id="introTitle">Follow the water. Protect its pathways.</h2>

<script src="../fmt.js?v=20260822"></script>
<script src="../gschg31.js?v=20260821"></script>
<script src="../app.js?v=20260822b"></script>
<script src="../app.js?v=20260822c"></script>
</body>
</html>
4 changes: 2 additions & 2 deletions site/fr/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
<meta name="twitter:card" content="summary_large_image">
<link rel="stylesheet" href="../fonts.css?v=20260821">
<link rel="stylesheet" href="../tokens.css?v=20260822">
<link rel="stylesheet" href="../style.css?v=20260822c">
<link rel="stylesheet" href="../style.css?v=20260822d">
<script src="../i18n.js?v=20260821"></script>
<script src="../i18n-data.js?v=20260821"></script>
<script src="../i18n-map.js?v=20260822"></script>
Expand Down Expand Up @@ -393,6 +393,6 @@ <h2 id="introTitle">Suivre l’eau. Protéger ses voies.</h2>

<script src="../fmt.js?v=20260822"></script>
<script src="../gschg31.js?v=20260821"></script>
<script src="../app.js?v=20260822b"></script>
<script src="../app.js?v=20260822c"></script>
</body>
</html>
4 changes: 2 additions & 2 deletions site/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
<meta name="twitter:card" content="summary_large_image">
<link rel="stylesheet" href="fonts.css?v=20260821">
<link rel="stylesheet" href="tokens.css?v=20260822">
<link rel="stylesheet" href="style.css?v=20260822c">
<link rel="stylesheet" href="style.css?v=20260822d">
<script src="i18n.js?v=20260821"></script>
<script src="i18n-data.js?v=20260821"></script>
<script src="i18n-map.js?v=20260822"></script>
Expand Down Expand Up @@ -393,6 +393,6 @@ <h2 id="introTitle">Dem Wasser folgen. Seine Wege schützen.</h2>

<script src="fmt.js?v=20260822"></script>
<script src="gschg31.js?v=20260821"></script>
<script src="app.js?v=20260822b"></script>
<script src="app.js?v=20260822c"></script>
</body>
</html>
4 changes: 2 additions & 2 deletions site/it/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
<meta name="twitter:card" content="summary_large_image">
<link rel="stylesheet" href="../fonts.css?v=20260821">
<link rel="stylesheet" href="../tokens.css?v=20260822">
<link rel="stylesheet" href="../style.css?v=20260822c">
<link rel="stylesheet" href="../style.css?v=20260822d">
<script src="../i18n.js?v=20260821"></script>
<script src="../i18n-data.js?v=20260821"></script>
<script src="../i18n-map.js?v=20260822"></script>
Expand Down Expand Up @@ -393,6 +393,6 @@ <h2 id="introTitle">Seguire l’acqua. Proteggere i suoi percorsi.</h2>

<script src="../fmt.js?v=20260822"></script>
<script src="../gschg31.js?v=20260821"></script>
<script src="../app.js?v=20260822b"></script>
<script src="../app.js?v=20260822c"></script>
</body>
</html>
4 changes: 2 additions & 2 deletions site/rm/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
<meta name="twitter:card" content="summary_large_image">
<link rel="stylesheet" href="../fonts.css?v=20260821">
<link rel="stylesheet" href="../tokens.css?v=20260822">
<link rel="stylesheet" href="../style.css?v=20260822c">
<link rel="stylesheet" href="../style.css?v=20260822d">
<script src="../i18n.js?v=20260821"></script>
<script src="../i18n-data.js?v=20260821"></script>
<script src="../i18n-map.js?v=20260822"></script>
Expand Down Expand Up @@ -393,6 +393,6 @@ <h2 id="introTitle">Suandar l’aua. Proteger sias vias.</h2>

<script src="../fmt.js?v=20260822"></script>
<script src="../gschg31.js?v=20260821"></script>
<script src="../app.js?v=20260822b"></script>
<script src="../app.js?v=20260822c"></script>
</body>
</html>
33 changes: 32 additions & 1 deletion site/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -1051,6 +1051,24 @@ body.hasRibbon #credits { display: none; }
#workspace #siteNav { margin-top: 9px; padding-top: 8px; }
#workspace #introOpen { margin-left: -7px; }
#workspace #evidence { display: none; }
#workspace #modeRail { display: contents; }
#workspace .modeRailCue {
position: absolute; z-index: 2; top: 0; bottom: 1px;
display: none; place-items: center; width: 34px;
color: var(--ink); font-size: 23px; line-height: 1;
opacity: 0; pointer-events: none;
transition: opacity 140ms ease;
}
#workspace .modeRailCue-start {
left: 0; justify-items: start; padding-left: 6px;
background: linear-gradient(90deg, var(--surface-1) 36%, transparent);
}
#workspace .modeRailCue-end {
right: 0; justify-items: end; padding-right: 6px;
background: linear-gradient(270deg, var(--surface-1) 36%, transparent);
}
#workspace #modeRail.canScrollBack .modeRailCue-start,
#workspace #modeRail.canScrollForward .modeRailCue-end { opacity: 1; }
@media (min-width: 1100px) and (min-height: 860px) {
#workspace #evidence { display: block; }
}
Expand Down Expand Up @@ -1213,6 +1231,10 @@ body.hasRibbon #workspace #credits { display: block; }
}
#workspace #titlebar .themeBtn { width: 40px; height: 40px; }

#workspace #modeRail {
position: relative; display: block; flex: none; min-width: 0;
}
#workspace .modeRailCue { display: grid; }
#workspace #modes {
display: flex; flex-direction: row; gap: 2px; padding: 4px 8px;
overflow-x: auto; overflow-y: hidden; overscroll-behavior-x: contain;
Expand Down Expand Up @@ -1245,7 +1267,12 @@ body.hasRibbon #workspace #credits { display: block; }
#workspace .introLangs [lang] { min-width: 40px; min-height: 44px; }
}
@media (max-width: 480px) and (max-height: 650px) and (orientation: portrait) {
:root { --workspace-h: 58dvh; }
:root { --workspace-h: 62dvh; }
#workspace #titlebar { padding-top: 6px; padding-bottom: 4px; }
#workspace #titlebar .stamp {
font-size: 9.5px; line-height: 1.25; letter-spacing: -.01em;
}
#workspace #siteNav { margin-top: 2px; padding-top: 2px; }
}

/* Short landscape screens keep real columns but compact the index into one
Expand All @@ -1261,6 +1288,10 @@ body.hasRibbon #workspace #credits { display: block; }
#workspace #titlebar .stamp { display: block; margin-top: 2px; font-size: 10.5px; }
#workspace #siteNav { flex-wrap: nowrap; margin-top: 4px; padding-top: 3px; }
#workspace #titlebar .langs { margin-left: auto; }
#workspace #modeRail {
position: relative; display: block; flex: none; min-width: 0;
}
#workspace .modeRailCue { display: grid; }
#workspace #modes {
display: flex; flex-direction: row; gap: 2px; padding: 4px 7px;
overflow-x: auto; overflow-y: hidden; touch-action: pan-x;
Expand Down