From 14a514e3e4dea12821b0334c0a4ada22dea9fc87 Mon Sep 17 00:00:00 2001 From: kritzl Date: Thu, 6 Jun 2024 11:27:16 +0200 Subject: [PATCH] some major improvements - filter by station type - sort by distance (WIP) - detect old data structure and clear localStorage if not compatible - add substitue coordinates for stations without valid osm node - improve responsive styles --- elevators.js | 377 ++++++++++++++++++++++++++++++++++++++++---------- index.html | 37 ++++- style.css | 209 +++++++++++++++++++++++----- style.css.map | 2 +- style.scss | 229 +++++++++++++++++++++++++++--- 5 files changed, 726 insertions(+), 128 deletions(-) diff --git a/elevators.js b/elevators.js index f302008..5f4fc3b 100644 --- a/elevators.js +++ b/elevators.js @@ -3,8 +3,64 @@ const internalData = { stations: [], }; let geolocationPermission = false; -let geolocation = [null, null]; +let geolocation = null; const openStations = new Set(); +let sortByDistance = false; + +const substituteCoordinates = [ + { + name: 'Borgweg (Stadtpark)', + coordinates: [53.5907696, 10.0147719], + }, + { + name: 'Emilienstraße', + coordinates: [53.5716862, 9.9525424], + }, + { + name: 'Garstedt', + coordinates: [53.6844739, 9.9860415], + }, + { + name: 'Hagenbecks Tierpark', + coordinates: [53.5925874, 9.9440359], + }, + { + name: 'Hauptbahnhof Nord', + coordinates: [53.5541197, 10.0061270], + }, + { + name: 'Hoheneichen', + coordinates: [53.6355141, 10.0677176], + }, + { + name: 'Kornweg (Klein Borstel)', + coordinates: [53.6324430, 10.0541722], + }, + { + name: 'Lauenbrück', + coordinates: [53.1971209, 9.5640765], + }, + { + name: 'Lutterothstraße', + coordinates: [53.5819938, 9.9476215], + }, + { + name: 'Meckelfeld', + coordinates: [53.4248897, 10.0291223], + }, + { + name: 'Sengelmannstraße (City Nord)', + coordinates: [53.6093953, 10.0220004], + }, + { + name: 'St.Pauli', + coordinates: [53.5507957, 9.9700752], + }, + { + name: 'Winsen(Luhe)', + coordinates: [53.3534304, 10.2086841], + }, +] Object.defineProperty(String.prototype, 'capitalize', { @@ -15,12 +71,17 @@ Object.defineProperty(String.prototype, 'capitalize', { }); async function loadElevators() { - const res = await fetch('https://www.hvv.de/elevators', {referrer: ""}); + document.querySelector('#errorMessage').classList.add('hidden'); + const res = await fetch('https://www.hvv.de/elevators', { + referrer: "", + }).catch(e => { + document.querySelector('#errorMessage').classList.remove('hidden'); + }); const data = await res.json(); const stations = data['stations']; - stations.sort(sortStations) + stations.sort(sortStations); internalData.lastUpdate = new Date(data['lastUpdate']); let stationIndex = 0; @@ -102,7 +163,10 @@ async function loadElevators() { } } - localStorage.setItem("internal_data", JSON.stringify(internalData)); + localStorage.setItem("internal_data", JSON.stringify({ + api: 'v1', + ...internalData + })); } const dateTimeStyle = new Intl.DateTimeFormat('de-DE', { @@ -119,12 +183,55 @@ async function loadOsmData() { } } - const osmData = await fetch(`https://overpass-api.de/api/interpreter?data=[out:json];node(id:${nodeIdList.join(',')});out%20body;`, {}); - const osmJson = await osmData.json(); + const osmResponse = await fetch(`https://overpass-api.de/api/interpreter?data=[out:json];node(id:${nodeIdList.join(',')});out%20body;`, {}); + const osmJson = await osmResponse.json(); if (!osmJson.hasOwnProperty('elements')) return; - localStorage.setItem("osm_data", JSON.stringify(osmJson)); + const osmNodes = {}; + for await (const node of osmJson.elements) { + if (node.hasOwnProperty('tags')) { + const tags = node['tags']; + if (tags['highway'] === 'elevator') { + osmNodes[node['id']] = node; + } else { + console.warn(`OSM Node is not an elevator. (NodeID: ${node['id']})`); + } + } else { + console.warn(`OSM Node has no Tags. (NodeID: ${node['id']})`); + } + } + + //update coordinates in stations + for (const stationIndex in internalData.stations) { + const station = internalData.stations[stationIndex]; + for (const elevator of station.elevators) { + const node = osmNodes[elevator.osmNodeId] + if (node) { + internalData.stations[stationIndex]['coordinates'] = [ + node['lat'], + node['lon'], + ] + } + } + + if (!internalData.stations[stationIndex].hasOwnProperty('coordinates')) { + const substitute = substituteCoordinates.filter(subs => subs.name === internalData.stations[stationIndex].name) + if (substitute.length) { + internalData.stations[stationIndex]['coordinates'] = substitute[0].coordinates; + } + } + } + + localStorage.setItem("osm_data", JSON.stringify({ + api: 'v1', + lastUpdate: new Date(), + nodes: osmNodes + })); + localStorage.setItem("internal_data", JSON.stringify({ + api: 'v1', + ...internalData + })); } function distance([lat1, lon1], [lat2, lon2]) { @@ -145,9 +252,12 @@ function distance([lat1, lon1], [lat2, lon2]) { function registerGeolocationWatcher() { navigator.geolocation.watchPosition((pos) => { - geolocation = [pos.coords.latitude, pos.coords.longitude] + if (geolocation === null) { + geolocation = [pos.coords.latitude, pos.coords.longitude]; + renderData(geolocation); + } }, (e) => { - console.log(e) + console.warn(e) }, { enableHighAccuracy: true, timeout: 5000, @@ -177,8 +287,6 @@ function allowGeolocation() { checkGeolocationPermission() -document.querySelector('#stationsNearMe').addEventListener('click', allowGeolocation) - function sortStations(stationA, stationB) { const nameA = stationA.mainSubStation.stationName.toUpperCase(); // ignore upper and lowercase const nameB = stationB.mainSubStation.stationName.toUpperCase(); // ignore upper and lowercase @@ -193,6 +301,20 @@ function sortStations(stationA, stationB) { return 0; } +function sortStationsByDistance(stationA, stationB) { + const distanceA = stationA.distance; // ignore upper and lowercase + const distanceB = stationB.distance; // ignore upper and lowercase + if (distanceA < distanceB) { + return -1; + } + if (distanceA > distanceB) { + return 1; + } + + // names must be equal + return 0; +} + function getType(line) { const type = line.replace(/[^A-z]/g, ""); switch (type) { @@ -218,7 +340,7 @@ function getTypes(lines) { return types; } -function renderData() { +function renderData(location = null) { const ls = JSON.parse(localStorage.getItem("internal_data")); if (!ls) return; internalData.lastUpdate = ls['lastUpdate']; @@ -230,6 +352,18 @@ function renderData() { return; } + if ( + location !== null + && ( + location.length !== 2 + || typeof location[0] !== 'number' + || typeof location[1] !== 'number' + ) + ) { + console.error('No valid location provided') + return; + } + document.querySelector('#updateInfo').classList.remove('hidden'); document.querySelector('#loadElevators').classList.remove('hidden'); document.querySelector('#filters').classList.remove('hidden'); @@ -241,18 +375,57 @@ function renderData() { //clear list before update listContainer.innerHTML = ''; - const stations = internalData['stations']; + let stations = [...internalData['stations']]; for (const stationIndex in stations) { const station = stations[stationIndex]; + station.id = stationIndex; + + if (location !== null) { + if (station.hasOwnProperty('coordinates')) { + station.distance = distance(location, station.coordinates); + } else { + console.log('station has no position:', station.name); + } + } + } + + stations = stations.sort(sortStationsByDistance); + + for (const stationIndex in stations) { + const station = stations[stationIndex]; + + if (location !== null) { + if (station.hasOwnProperty('coordinates')) { + station.distance = distance(location, station.coordinates); + } else { + console.log('station has no position:', station.name); + } + } let elevatorsTemplate = ''; let previewTemplate = ''; for (const elevator of station.elevators) { - let linesTemplate = '
Linien: '; - for (const line of elevator.lines) { - linesTemplate += `${line.line}`; + const stateTemplate = ` + `; + + let linesTemplate = ''; + linesTemplate = `
${stateTemplate}`; + if (elevator.lines.length) { + linesTemplate = `
${stateTemplate}`; + linesTemplate += `
Linien: `; + for (const line of elevator.lines) { + linesTemplate += `${line.line}`; + } + linesTemplate += '
'; } linesTemplate += '
'; @@ -264,41 +437,32 @@ function renderData() { let osmTemplate = ''; if (osmData) { - const nodes = osmData.elements.filter(node => node.id === elevator.osmNodeId) - if (nodes.length) { - const nodeInfo = nodes[0]; - if (nodeInfo.hasOwnProperty('tags')) { - const tags = nodeInfo['tags']; - if (tags['highway'] === 'elevator') { - osmTemplate = '
'; - osmTemplate += `
-
Link zur Karte
-
- - Auf Karte anzeigen - -
-
`; - if (tags.hasOwnProperty('description')) { - osmTemplate += `
Beschreibung
${tags['description']}
`; - } - if (tags.hasOwnProperty('level')) { - osmTemplate += `
Ebenen
${tags['level'].split(';').sort().join(', ')}
`; - } - if (tags.hasOwnProperty('wheelchair')) { - osmTemplate += `
Rollstühle
${tags['wheelchair'] === 'yes' ? 'Ja' : 'Nein'}
`; - } - if (tags.hasOwnProperty('bicycle')) { - osmTemplate += `
Fahrräder
${tags['bicycle'] === 'yes' ? 'Ja' : 'Nein'}
`; - } + const node = osmData.nodes[elevator.osmNodeId] + if (node) { - osmTemplate += '
'; - } else { - console.warn(`OSM Node is not an elevator. At:\t${station.name}\t${elevator.label} (NodeID: ${elevator.osmNodeId})`); - } - } else { - console.warn(`OSM Node has no Tags. At:\t${station.name}\t${elevator.label} (NodeID: ${elevator.osmNodeId})`); + osmTemplate = '
'; + osmTemplate += `
+
Link zur Karte
+
+ + Auf Karte anzeigen + +
+
`; + if (node.tags.hasOwnProperty('description')) { + osmTemplate += `
Beschreibung
${node.tags['description']}
`; } + if (node.tags.hasOwnProperty('level')) { + osmTemplate += `
Ebenen
${node.tags['level'].split(';').sort().join(', ')}
`; + } + if (node.tags.hasOwnProperty('wheelchair')) { + osmTemplate += `
Rollstühle
${node.tags['wheelchair'] === 'yes' ? 'Ja' : 'Nein'}
`; + } + if (node.tags.hasOwnProperty('bicycle')) { + osmTemplate += `
Fahrräder
${node.tags['bicycle'] === 'yes' ? 'Ja' : 'Nein'}
`; + } + + osmTemplate += '
'; } else { console.warn(`OSM Node not found (deleted). At:\t${station.name}\t${elevator.label} (NodeID: ${elevator.osmNodeId})`); } @@ -310,19 +474,10 @@ function renderData() { previewTemplate += `` - elevatorsTemplate += `
  • - - + ${stateTemplate}
    - ${elevator.lines.length ? `${linesTemplate}` : ''} + ${linesTemplate} ${elevator.instCause !== '' ? `
    ${elevator.instCause}
    ` : ''} ${elevator.levels.length ? levelsTemplate : elevator.description}
    @@ -365,11 +520,14 @@ function renderData() {
  • `; } - const template = `
  • + const template = `
  • +
    ${station.types.sort().map(t => `${t}`).join('')}
    + ${typeof station.distance !== 'undefined' ? `
    ${Math.round(station.distance / 100) / 10}
    km
    ` : ''} +

    ${station.name}

    -
    +
    Aufzüge anzeigen -
    @@ -393,7 +551,7 @@ ${station.state.unavailable ? `Bei ${station.state.unavailable} ${station.state. //immediate invocation (function () { - listContainer.querySelectorAll(`#station_${stationIndex} .loadOSM`).forEach(e => { + listContainer.querySelectorAll(`#station_${station.id} .loadOSM`).forEach(e => { e.addEventListener('click', (ev) => { ev.target.querySelector('.spinner').classList.remove('hidden'); loadOsmData().then(() => { @@ -416,6 +574,8 @@ ${station.state.unavailable ? `Bei ${station.state.unavailable} ${station.state. } }); }) + + filterData(); } document.querySelector('#loadElevators') @@ -424,7 +584,6 @@ document.querySelector('#loadElevators') loadElevators().then(() => { e.target.querySelector('.spinner').classList.add('hidden'); renderData(); - filterData(); }); }) @@ -434,19 +593,65 @@ document.querySelector('#initialLoad') loadElevators().then(() => { e.target.classList.add('hidden'); renderData(); - filterData(); }); }) -renderData(); +document.querySelector('#loadOsm') + .addEventListener('click', (e) => { + e.target.querySelector('.spinner').classList.remove('hidden'); + loadOsmData().then(() => { + e.target.querySelector('.spinner').classList.add('hidden'); + renderData(); + closeDialog('#dialog_osm'); + }); + }) + +document.querySelector('#stationsNearMe') + .addEventListener('click', async (e) => { + e.target.querySelector('.spinner').classList.remove('hidden'); + if (!sortByDistance) { + if (JSON.parse(localStorage.getItem("osm_data")) === null) { + openDialog('#dialog_osm'); + } else { + if (geolocationPermission !== 'granted') { + allowGeolocation(); + } else { + // If geolocation is already set. + // If not the location watcher will re-render our data. + if (geolocation !== null) { + renderData(geolocation) + } + sortByDistance = e.target.ariaPressed = true; + } + } + } else { + sortByDistance = e.target.ariaPressed = false; + + renderData(); + } + e.target.querySelector('.spinner').classList.add('hidden'); + }) function filterData() { const searchString = document.querySelector('#searchStation').value; + const typeU = document.querySelector('button.typeChip[data-type="U"]'); + const typeS = document.querySelector('button.typeChip[data-type="S"]'); + const typeA = document.querySelector('button.typeChip[data-type="A"]'); + const typeR = document.querySelector('button.typeChip[data-type="R"]'); + const activeTypes = []; + if(typeU.ariaPressed === 'true') activeTypes.push('U'); + if(typeS.ariaPressed === 'true') activeTypes.push('S'); + if(typeA.ariaPressed === 'true') activeTypes.push('A'); + if(typeR.ariaPressed === 'true') activeTypes.push('R'); if (internalData) { for (const stationIndex in internalData.stations) { - const matches = internalData.stations[stationIndex].name.toLowerCase().search(searchString.toLowerCase()) >= 0; - document.querySelector(`#station_${stationIndex}`).classList.toggle('hidden', !matches); + const matchesSearch = internalData.stations[stationIndex].name.toLowerCase().search(searchString.toLowerCase()) >= 0; + let matchesType = false; + internalData.stations[stationIndex].types.forEach(type => { + if(activeTypes.includes(type)) matchesType = true; + }) + document.querySelector(`#station_${stationIndex}`).classList.toggle('hidden', !(matchesSearch && matchesType)); } } } @@ -455,4 +660,36 @@ document.querySelector('#searchStation').addEventListener('input', (e) => { filterData(); }) -filterData() \ No newline at end of file +document.querySelectorAll('button.typeChip').forEach(e => { + e.addEventListener('click', (event) => { + e.ariaPressed = e.ariaPressed === 'true' ? 'false' : 'true'; + filterData(); + }) +}) + +function openDialog(selector) { + document.querySelector('body').classList.add('has-dialog') + document.querySelector('#dialog_layer').classList.add('active') + document.querySelector(selector).classList.remove('hidden') +} + +function closeDialog(selector) { + document.querySelector('body').classList.remove('has-dialog') + document.querySelector('#dialog_layer').classList.remove('active') + document.querySelector(selector).classList.add('hidden') +} + +// data api version check +const check_internal = JSON.parse(localStorage.getItem("internal_data")); +const check_osm = JSON.parse(localStorage.getItem("osm_data")); +if (check_internal === null || check_internal.hasOwnProperty('api') && check_internal.api === 'v1') { + if (check_osm === null || check_osm.hasOwnProperty('api') && check_osm.api === 'v1') { + renderData(); + } else { + console.log('osm_data: version mismatch') + localStorage.removeItem('osm_data'); + } +} else { + console.log('internal_data: version mismatch') + localStorage.removeItem('internal_data'); +} diff --git a/index.html b/index.html index 9770960..58e4796 100644 --- a/index.html +++ b/index.html @@ -37,10 +37,17 @@ + +
    + + +
    + +
    \ No newline at end of file diff --git a/style.css b/style.css index 35e2dc8..94a7483 100644 --- a/style.css +++ b/style.css @@ -10,6 +10,18 @@ --color-gray-800: hsl(12, 6%, 15%); --color-gray-900: hsl(24, 10%, 10%); --color-gray-950: hsl(20, 14%, 4%); + --color-red: #971616; + --color-orange: #cc6300; + --color-green: #19942e; + --bg-type-u: #006ab3; + --bg-type-s: #1a962b; + --bg-type-a: #f39100; + --bg-type-r: #000000; + --bg-type-u-disabled: #c3cfd7; + --bg-type-s-disabled: #c6d4c8; + --bg-type-a-disabled: #dfd8cf; + --bg-type-r-disabled: #b3b3b3; + --color-type-disabled: var(--color-gray-400); --bg: var(--color-gray-50); --text: var(--color-gray-950); --text-secondary: var(--color-gray-700); @@ -52,23 +64,64 @@ --station-border: var(--color-gray-600); --station-border-hover: var(--color-gray-400); --elevator-bg: var(--color-gray-900); + --bg-type-u-disabled: #627f93; + --bg-type-s-disabled: #688b6d; + --bg-type-a-disabled: #aa987f; + --bg-type-r-disabled: #333333; + --color-type-disabled: var(--color-gray-200); } } +body.has-dialog { + overflow: hidden; +} + +.dialogs { + display: none; + position: fixed; + overflow-y: auto; + max-width: 100vw; + padding: 1em; + top: 0; + right: 0; + bottom: 0; + left: 0; + background: rgba(0, 0, 0, 0.3); +} +.dialogs.active { + display: block; +} + +[role=dialog] { + box-sizing: border-box; + max-width: 800px; + margin: 0 auto; + padding: 15px; + border-radius: 1rem; + background-color: var(--background); + color: var(--color); + position: relative; +} +[role=dialog] button.close-modal { + position: absolute; + top: 0; + right: 0; +} + .hidden { display: none !important; } .text-red { - color: #971616; + color: var(--color-red); } .text-orange { - color: #cc6300; + color: var(--color-orange); } .text-green { - color: #19942e; + color: var(--color-green); } body { @@ -125,6 +178,8 @@ main { } footer { + display: flex; + justify-content: center; margin: 1em auto; max-width: 960px; } @@ -147,6 +202,9 @@ button:hover { background-color: var(--station-bg-hover); border-color: var(--station-border-hover); } +button[aria-pressed=true] { + background-color: var(--nav-bg-visited); +} button.size-s { font-size: 0.8rem; padding: var(--space-s) var(--space-m); @@ -168,12 +226,23 @@ div#updateInfo { div#filters { display: flex; + flex-wrap: wrap; gap: var(--space-m); - justify-items: stretch; + justify-content: stretch; } div#filters button, div#filters input { font-size: 1.5rem; } +div#filters > * { + width: 100%; + justify-content: center; + text-align: center; +} +@media screen and (min-width: 576px) { + div#filters > * { + width: auto; + } +} button#initialLoad { font-size: 1.5rem; @@ -183,6 +252,14 @@ button.loadOSM { width: fit-content; } +div#errorMessage { + border: solid 2px var(--color-red); + border-radius: var(--item-radius); + padding: var(--space-xl) var(--space-xl); + margin-top: var(--space-l); + font-size: 1.5rem; +} + ul#stationList { padding: 0; list-style: none; @@ -202,9 +279,20 @@ ul#stationList > li.station > div.stationSummary { display: flex; gap: var(--space-m); } -ul#stationList > li.station > div.stationSummary div.typeList { +ul#stationList > li.station > div.stationSummary div.symbol { + position: relative; +} +ul#stationList > li.station > div.stationSummary div.symbol div.typeList { flex-shrink: 0; } +ul#stationList > li.station > div.stationSummary div.symbol div.distance { + position: absolute; + width: 100%; + bottom: -2lh; + text-align: center; + color: var(--text-secondary); + font-size: 0.9em; +} ul#stationList > li.station > div.stationSummary div.stationTitle { align-self: stretch; flex-grow: 1; @@ -286,19 +374,26 @@ ul#stationList > li.station > details > ul > li.elevator { display: flex; align-items: start; flex-wrap: nowrap; - padding: var(--space-m); gap: var(--space-m); position: relative; - margin: 0 1rem 1rem; - padding-right: var(--space-2xl); + margin: 0 var(--space-s) var(--space-s); + padding: var(--space-s); } @media screen and (min-width: 576px) { ul#stationList > li.station > details > ul > li.elevator { margin: 0 var(--space-2xl) 1rem; + padding: var(--space-m); + padding-right: var(--space-2xl); } } -ul#stationList > li.station > details > ul > li.elevator > span { +ul#stationList > li.station > details > ul > li.elevator > .stateIcon { flex-shrink: 0; + display: none; +} +@media screen and (min-width: 576px) { + ul#stationList > li.station > details > ul > li.elevator > .stateIcon { + display: inline; + } } ul#stationList > li.station > details > ul > li.elevator:not(:first-child):before { content: ""; @@ -326,11 +421,25 @@ ul#stationList > li.station > details > ul > li.elevator > div.elevatorData .ele font-weight: bold; grid-column: 1/-1; } -ul#stationList > li.station > details > ul > li.elevator > div.elevatorData .lineList { +ul#stationList > li.station > details > ul > li.elevator > div.elevatorData div.firstRow { + grid-column: 1/-1; + display: flex; + gap: var(--space-m); +} +@media screen and (min-width: 576px) { + ul#stationList > li.station > details > ul > li.elevator > div.elevatorData div.firstRow.hiddenOnDesktop { + display: none; + } +} +@media screen and (min-width: 576px) { + ul#stationList > li.station > details > ul > li.elevator > div.elevatorData div.firstRow .stateIcon { + display: none; + } +} +ul#stationList > li.station > details > ul > li.elevator > div.elevatorData div.firstRow .lineList { display: flex; gap: var(--space-m); align-items: center; - grid-column: 1/-1; min-height: var(--space-2xl); } ul#stationList > li.station > details > ul > li.elevator > div.elevatorData hr { @@ -350,6 +459,7 @@ ul#stationList > li.station > details > ul > li.elevator > div.elevatorData .osm ul#stationList > li.station > details > ul > li.elevator > div.elevatorData .osm .osmHeading { display: flex; align-items: center; + flex-wrap: wrap; gap: var(--space-l); margin-bottom: var(--space-l); } @@ -414,7 +524,7 @@ ul#stationList > li.station > details > ul > li.elevator > div.elevatorData dl d font-weight: bold; min-width: 15ch; } -@media (max-width: 576px) { +@media (max-width: 400px) { ul#stationList > li.station > details > ul > li.elevator > div.elevatorData dl div dt { width: 100%; } @@ -430,66 +540,101 @@ ul#stationList > li.station > details > ul > li.elevator > div.elevatorData dl d } } -span.lineChip, span.typeChip { +span.lineChip, span.typeChip, button.typeChip { font-weight: bold; font-size: 0.8em; text-align: center; box-sizing: border-box; } -span.lineChip[data-type=U], span.typeChip[data-type=U] { - background-color: #006ab3; +span.lineChip[data-type=U], span.typeChip[data-type=U], button.typeChip[data-type=U] { + background-color: var(--bg-type-u); color: #ffffff; } -span.lineChip[data-type=U][data-line=U1], span.typeChip[data-type=U][data-line=U1] { +span.lineChip[data-type=U][data-line=U1], span.typeChip[data-type=U][data-line=U1], button.typeChip[data-type=U][data-line=U1] { background-color: #006ab3; } -span.lineChip[data-type=U][data-line=U2], span.typeChip[data-type=U][data-line=U2] { +span.lineChip[data-type=U][data-line=U2], span.typeChip[data-type=U][data-line=U2], button.typeChip[data-type=U][data-line=U2] { background-color: #e2001a; } -span.lineChip[data-type=U][data-line=U3], span.typeChip[data-type=U][data-line=U3] { +span.lineChip[data-type=U][data-line=U3], span.typeChip[data-type=U][data-line=U3], button.typeChip[data-type=U][data-line=U3] { background-color: #ffdd00; color: #000000; } -span.lineChip[data-type=U][data-line=U4], span.typeChip[data-type=U][data-line=U4] { +span.lineChip[data-type=U][data-line=U4], span.typeChip[data-type=U][data-line=U4], button.typeChip[data-type=U][data-line=U4] { background-color: #0098a1; } -span.lineChip[data-type=S], span.typeChip[data-type=S] { - background-color: #1a962b; +span.lineChip[data-type=S], span.typeChip[data-type=S], button.typeChip[data-type=S] { + background-color: var(--bg-type-s); color: #ffffff; } -span.lineChip[data-type=S][data-line=S1], span.typeChip[data-type=S][data-line=S1] { +span.lineChip[data-type=S][data-line=S1], span.typeChip[data-type=S][data-line=S1], button.typeChip[data-type=S][data-line=S1] { background-color: #1a962b; } -span.lineChip[data-type=S][data-line=S2], span.typeChip[data-type=S][data-line=S2] { +span.lineChip[data-type=S][data-line=S2], span.typeChip[data-type=S][data-line=S2], button.typeChip[data-type=S][data-line=S2] { background-color: #b51143; } -span.lineChip[data-type=S][data-line=S3], span.typeChip[data-type=S][data-line=S3] { +span.lineChip[data-type=S][data-line=S3], span.typeChip[data-type=S][data-line=S3], button.typeChip[data-type=S][data-line=S3] { background-color: #622181; } -span.lineChip[data-type=S][data-line=S4], span.typeChip[data-type=S][data-line=S4] { +span.lineChip[data-type=S][data-line=S4], span.typeChip[data-type=S][data-line=S4], button.typeChip[data-type=S][data-line=S4] { background-color: #be148e; } -span.lineChip[data-type=S][data-line=S5], span.typeChip[data-type=S][data-line=S5] { +span.lineChip[data-type=S][data-line=S5], span.typeChip[data-type=S][data-line=S5], button.typeChip[data-type=S][data-line=S5] { background-color: #0089bb; } -span.lineChip[data-type=S][data-line=S6], span.typeChip[data-type=S][data-line=S6] { +span.lineChip[data-type=S][data-line=S6], span.typeChip[data-type=S][data-line=S6], button.typeChip[data-type=S][data-line=S6] { background-color: #d3da00; color: #000000; } -span.lineChip[data-type=A], span.typeChip[data-type=A] { - background-color: #f39100; +span.lineChip[data-type=A], span.typeChip[data-type=A], button.typeChip[data-type=A] { + background-color: var(--bg-type-a); color: #ffffff; } -span.lineChip[data-type=R], span.typeChip[data-type=R] { - background-color: #000000; +span.lineChip[data-type=R], span.typeChip[data-type=R], button.typeChip[data-type=R] { + background-color: var(--bg-type-r); color: #ffffff; } @media (prefers-color-scheme: dark) { - span.lineChip[data-type=R], span.typeChip[data-type=R] { + span.lineChip[data-type=R], span.typeChip[data-type=R], button.typeChip[data-type=R] { border: solid 2px #ffffff; } } +div#typeFilter { + display: flex; + flex-grow: 1; + flex-wrap: nowrap; + flex-shrink: 0; + min-height: var(--space-2xl); + gap: var(--space-m); +} +div#typeFilter button.typeChip { + padding: 0; + height: 100%; + aspect-ratio: 1/1; + justify-content: center; + align-items: center; +} +div#typeFilter button.typeChip[data-type=U], div#typeFilter button.typeChip[data-type=S], div#typeFilter button.typeChip[data-type=A], div#typeFilter button.typeChip[data-type=R] { + border: solid 2px var(--station-border); +} +div#typeFilter button.typeChip[data-type=U][aria-pressed=false], div#typeFilter button.typeChip[data-type=S][aria-pressed=false], div#typeFilter button.typeChip[data-type=A][aria-pressed=false], div#typeFilter button.typeChip[data-type=R][aria-pressed=false] { + background-color: var(--color-gray-500); + color: var(--color-type-disabled); +} +div#typeFilter button.typeChip[data-type=U][aria-pressed=false][data-type=U], div#typeFilter button.typeChip[data-type=S][aria-pressed=false][data-type=U], div#typeFilter button.typeChip[data-type=A][aria-pressed=false][data-type=U], div#typeFilter button.typeChip[data-type=R][aria-pressed=false][data-type=U] { + background-color: var(--bg-type-u-disabled); +} +div#typeFilter button.typeChip[data-type=U][aria-pressed=false][data-type=S], div#typeFilter button.typeChip[data-type=S][aria-pressed=false][data-type=S], div#typeFilter button.typeChip[data-type=A][aria-pressed=false][data-type=S], div#typeFilter button.typeChip[data-type=R][aria-pressed=false][data-type=S] { + background-color: var(--bg-type-s-disabled); +} +div#typeFilter button.typeChip[data-type=U][aria-pressed=false][data-type=A], div#typeFilter button.typeChip[data-type=S][aria-pressed=false][data-type=A], div#typeFilter button.typeChip[data-type=A][aria-pressed=false][data-type=A], div#typeFilter button.typeChip[data-type=R][aria-pressed=false][data-type=A] { + background-color: var(--bg-type-a-disabled); +} +div#typeFilter button.typeChip[data-type=U][aria-pressed=false][data-type=R], div#typeFilter button.typeChip[data-type=S][aria-pressed=false][data-type=R], div#typeFilter button.typeChip[data-type=A][aria-pressed=false][data-type=R], div#typeFilter button.typeChip[data-type=R][aria-pressed=false][data-type=R] { + background-color: var(--bg-type-r-disabled); +} + span.lineChip { padding: 0.3em 0.6em; min-width: 4ch; diff --git a/style.css.map b/style.css.map index cd7fca4..0ae8de6 100644 --- a/style.css.map +++ b/style.css.map @@ -1 +1 @@ -{"version":3,"sourceRoot":"","sources":["style.scss"],"names":[],"mappings":"AAGA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAGA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAmBA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAzBA;EA/BF;IAgCI;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;;;AAcJ;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EAGA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;AAEA;EACE;EACA;;AAGF;EACE;;;AAKF;EACE;EACA;EACA;EACA;EACA;EACA;;AAGE;EACE;EACA;EACA;EAEA;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;;AAOV;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;;AAGF;EACE;EACA;;;AAIJ;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;;AAEA;EACE;;;AAIJ;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAEA;EACE;;AAIF;EACE;EACA;EAEA;EACA;EACA;;AAEA;EACE;EACA;EACA;EAEA;;AAEA;EAPF;IAQI;;;AAIJ;EACE;EAEA;EACA;EACA;EACA;;AAEA;EARF;IASI;IACA;IACA;;;AAMR;EACE;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EA1BF;IA2BI;;;AAIJ;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EAEA;EAKA;;AAJA;EATF;IAUI;;;AAMF;EACE;;AAIF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EAEA;;AACA;EARF;IASI;;;AAGF;EACE;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;;AAEA;EACE;;AAQA;EACE;;AAMR;EACE;EACA;EACA;EAEA;EACA;;AAEA;EACE;EAEA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAIA;EACE;;AAKF;EACE;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAKN;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EARF;IASI;;;AAIJ;EACE;EACA;EAEA;;AAEA;EANF;IAOI;;;;AAYpB;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;EACA;;AAGF;EACE;;AAIJ;EACE;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;EACA;;AAIJ;EACE;EACA;;AAGF;EACE;EACA;;AAEA;EAJF;IAKI;;;;AAKN;EACE;EACA;;AAEA;EACE;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EAEE;EAMA;EACA;EACA;EACA;EACA;EACA;EACA;;AAVA;EACE;;AAWF;EAIE;EACA;;;AAMJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAIJ;EACE;IACE","file":"style.css"} \ No newline at end of file +{"version":3,"sourceRoot":"","sources":["style.scss"],"names":[],"mappings":"AAMA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;EAOA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EA0BA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAhCA;EAjDF;IAkDI;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IAEA;IACA;IACA;IACA;IACA;;;;AAgBF;EACE;;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;;AAKJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGE;EACE;EACA;EACA;;;AAKN;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EAGA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;AAEA;EACE;EACA;;AAGF;EACE;;;AAKF;EACE;EACA;EACA;EACA;EACA;EACA;;AAGE;EACE;EACA;EACA;EAEA;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;;AAOV;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;;AAGF;EACE;EACA;;AAGF;EACE;;AAGF;EACE;EACA;;;AAIJ;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA;EACA;;AACA;EAJF;IAKI;;;;AAKN;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;;AAWA;EACE;EACA;;AAEA;EACE;;AAEA;EACE;;AAGF;EACE;EACA;EACA;EAEA;EACA;EACA;;AAKJ;EACE;EACA;EAEA;EACA;EACA;;AAEA;EACE;EACA;EACA;EAEA;;AAEA;EAPF;IAQI;;;AAIJ;EACE;EAEA;EACA;EACA;EACA;;AAEA;EARF;IASI;IACA;IACA;;;AAMR;EACE;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EA1BF;IA2BI;;;AAIJ;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EAEA;EACA;;AACA;EATF;IAUI;IACA;IACA;;;AAIF;EACE;EACA;;AACA;EAHF;IAII;;;AAKJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EAEA;;AACA;EARF;IASI;;;AAGF;EACE;EACA;;AAGF;EACE;EACA;EACA;;AAGE;EADF;IAEI;;;AAKF;EADF;IAEI;;;AAKJ;EACE;EACA;EACA;EACA;;AAKJ;EACE;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAOA;EACE;;AAMR;EACE;EACA;EACA;EAEA;EACA;;AAEA;EACE;EAEA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAIA;EACE;;AAKF;EACE;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAKN;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EARF;IASI;;;AAIJ;EACE;EACA;EAEA;;AAEA;EANF;IAOI;;;;AAYpB;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;EACA;;AAGF;EACE;;AAIJ;EACE;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;EACA;;AAIJ;EACE;EACA;;AAGF;EACE;EACA;;AAEA;EAJF;IAKI;;;;AAMN;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;;AACA;EACE;;AACA;EACE;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;;AAQV;EACE;EACA;;AAEA;EACE;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EAEE;EAMA;EACA;EACA;EACA;EACA;EACA;EACA;;AAVA;EACE;;AAWF;EAIE;EACA;;;AAMJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAIJ;EACE;IACE","file":"style.css"} \ No newline at end of file diff --git a/style.scss b/style.scss index a57dd41..52ae926 100644 --- a/style.scss +++ b/style.scss @@ -1,4 +1,7 @@ +@use 'sass:color'; + $mobileBreakpoint: 576px; +$smallBreakpoint: 400px; $mediumBreakpoint: 800px; :root { @@ -14,6 +17,24 @@ $mediumBreakpoint: 800px; --color-gray-900: hsl(24, 10%, 10%); --color-gray-950: hsl(20, 14%, 4%); + --color-red: #971616; + --color-orange: #cc6300; + --color-green: #19942e; + + + $colorTypeU: #006ab3; + $colorTypeS: #1a962b; + $colorTypeA: #f39100; + $colorTypeR: #000000; + --bg-type-u: #{$colorTypeU}; + --bg-type-s: #{$colorTypeS}; + --bg-type-a: #{$colorTypeA}; + --bg-type-r: #{$colorTypeR}; + --bg-type-u-disabled: #{scale-color($colorTypeU, $saturation: -80%, $lightness: +70%)}; + --bg-type-s-disabled: #{scale-color($colorTypeS, $saturation: -80%, $lightness: +70%)}; + --bg-type-a-disabled: #{scale-color($colorTypeA, $saturation: -80%, $lightness: +70%)}; + --bg-type-r-disabled: #{scale-color($colorTypeR, $saturation: -80%, $lightness: +70%)}; + --color-type-disabled: var(--color-gray-400); --bg: var(--color-gray-50); --text: var(--color-gray-950); @@ -47,6 +68,13 @@ $mediumBreakpoint: 800px; --station-border: var(--color-gray-600); --station-border-hover: var(--color-gray-400); --elevator-bg: var(--color-gray-900); + + --bg-type-u-disabled: #{scale-color($colorTypeU, $saturation: -80%, $lightness: +20%)}; + --bg-type-s-disabled: #{scale-color($colorTypeS, $saturation: -80%, $lightness: +20%)}; + --bg-type-a-disabled: #{scale-color($colorTypeA, $saturation: -80%, $lightness: +20%)}; + --bg-type-r-disabled: #{scale-color($colorTypeR, $saturation: -80%, $lightness: +20%)}; + --color-type-disabled: var(--color-gray-200); + } --elevator-list-gap: 3rem; @@ -60,20 +88,63 @@ $mediumBreakpoint: 800px; --space-2xl: 3rem; } +body { + &.has-dialog { + overflow: hidden; + } +} + +.dialogs { + display: none; + position: fixed; + overflow-y: auto; + max-width: 100vw; + padding: 1em; + top: 0; + right: 0; + bottom: 0; + left: 0; + background: rgb(0 0 0 / 30%); + + &.active { + display: block; + } +} + + +[role="dialog"] { + box-sizing: border-box; + max-width: 800px; + margin: 0 auto; + padding: 15px; + border-radius: 1rem; + background-color: var(--background); + color: var(--color); + position: relative; + + button { + &.close-modal { + position: absolute; + top: 0; + right: 0; + } + } +} + .hidden { display: none !important; } .text-red { - color: #971616; + color: var(--color-red); } .text-orange { - color: #cc6300; + color: var(--color-orange); } .text-green { - color: #19942e; + color: var(--color-green); } body { @@ -142,6 +213,8 @@ main { } footer { + display: flex; + justify-content: center; margin: 1em auto; max-width: 960px; } @@ -165,6 +238,10 @@ button { border-color: var(--station-border-hover); } + &[aria-pressed='true'] { + background-color: var(--nav-bg-visited); + } + &.size-s { font-size: 0.8rem; padding: var(--space-s) var(--space-m); @@ -189,12 +266,22 @@ div#updateInfo { div#filters { display: flex; + flex-wrap: wrap; gap: var(--space-m); - justify-items: stretch; + justify-content: stretch; button, input { font-size: 1.5rem; } + + > * { + width: 100%; + justify-content: center; + text-align: center; + @media screen and (min-width: $mobileBreakpoint) { + width: auto; + } + } } button#initialLoad { @@ -205,6 +292,14 @@ button.loadOSM { width: fit-content; } +div#errorMessage { + border: solid 2px var(--color-red); + border-radius: var(--item-radius); + padding: var(--space-xl) var(--space-xl); + margin-top: var(--space-l); + font-size: 1.5rem; +} + ul#stationList { padding: 0; list-style: none; @@ -220,12 +315,35 @@ ul#stationList { position: relative; padding: var(--space-m); + //div.distance { + // display: flex; + // justify-content: center; + // font-size: 0.8rem; + // color: var(--text-secondary); + // position: absolute; + // width: 100%; + //} + > div.stationSummary { display: flex; gap: var(--space-m); - div.typeList { - flex-shrink: 0; + div.symbol { + position: relative; + + div.typeList { + flex-shrink: 0; + } + + div.distance { + position: absolute; + width: 100%; + bottom: -2lh; + + text-align: center; + color: var(--text-secondary); + font-size: 0.9em; + } } @@ -318,20 +436,24 @@ ul#stationList { display: flex; align-items: start; flex-wrap: nowrap; - padding: var(--space-m); gap: var(--space-m); position: relative; - margin: 0 1rem 1rem; + margin: 0 var(--space-s) var(--space-s); + padding: var(--space-s); @media screen and (min-width: $mobileBreakpoint) { margin: 0 var(--space-2xl) 1rem; + padding: var(--space-m); + padding-right: var(--space-2xl); } - padding-right: var(--space-2xl); - // elevator icon - > span { + > .stateIcon { flex-shrink: 0; + display: none; + @media screen and (min-width: $mobileBreakpoint) { + display: inline; + } } // divider between elevators @@ -362,14 +484,33 @@ ul#stationList { grid-column: 1 / -1; } - .lineList { + div.firstRow { + grid-column: 1 / -1; display: flex; gap: var(--space-m); - align-items: center; - grid-column: 1 / -1; - min-height: var(--space-2xl); + + &.hiddenOnDesktop { + @media screen and (min-width: $mobileBreakpoint) { + display: none; + } + } + + .stateIcon { + @media screen and (min-width: $mobileBreakpoint) { + display: none; + } + } + + + .lineList { + display: flex; + gap: var(--space-m); + align-items: center; + min-height: var(--space-2xl); + } } + hr { grid-column: 1 / -1; width: 100%; @@ -385,9 +526,10 @@ ul#stationList { border-radius: var(--item-radius); padding: var(--space-l); - .osmHeading{ + .osmHeading { display: flex; align-items: center; + flex-wrap: wrap; gap: var(--space-l); margin-bottom: var(--space-l); @@ -397,7 +539,6 @@ ul#stationList { } - dl { div { dt { @@ -474,7 +615,7 @@ ul#stationList { font-weight: bold; min-width: 15ch; - @media (max-width: $mobileBreakpoint) { + @media (max-width: $smallBreakpoint) { width: 100%; } } @@ -498,14 +639,14 @@ ul#stationList { } } -span.lineChip, span.typeChip { +span.lineChip, span.typeChip, button.typeChip { font-weight: bold; font-size: 0.8em; text-align: center; box-sizing: border-box; &[data-type="U"] { - background-color: #006ab3; + background-color: var(--bg-type-u); color: #ffffff; &[data-line="U1"] { @@ -527,7 +668,7 @@ span.lineChip, span.typeChip { } &[data-type="S"] { - background-color: #1a962b; + background-color: var(--bg-type-s); color: #ffffff; &[data-line="S1"] { @@ -557,12 +698,12 @@ span.lineChip, span.typeChip { } &[data-type="A"] { - background-color: #f39100; + background-color: var(--bg-type-a); color: #ffffff; } &[data-type="R"] { - background-color: #000000; + background-color: var(--bg-type-r); color: #ffffff; @media (prefers-color-scheme: dark) { @@ -571,6 +712,48 @@ span.lineChip, span.typeChip { } } + +div#typeFilter{ + display: flex; + flex-grow: 1; + flex-wrap: nowrap; + flex-shrink: 0; + min-height: var(--space-2xl); + gap: var(--space-m); + + button.typeChip { + padding: 0; + height: 100%; + aspect-ratio: 1/1; + justify-content: center; + align-items: center; + &[data-type="U"], &[data-type="S"], &[data-type="A"], &[data-type="R"] { + border: solid 2px var(--station-border); + &[aria-pressed="false"] { + background-color: var(--color-gray-500); + color: var(--color-type-disabled); + + &[data-type="U"] { + background-color: var(--bg-type-u-disabled); + } + + &[data-type="S"] { + background-color: var(--bg-type-s-disabled); + } + + &[data-type="A"] { + background-color: var(--bg-type-a-disabled); + } + + &[data-type="R"] { + background-color: var(--bg-type-r-disabled); + } + } + } + } +} + + span.lineChip { padding: 0.3em 0.6em; min-width: 4ch;