feat: build MapSift Overpass data explorer

This commit is contained in:
zv
2026-06-23 18:56:59 +02:00
commit b1e1df7e1d
23 changed files with 2909 additions and 0 deletions

369
src/styles.css Normal file
View File

@@ -0,0 +1,369 @@
:root {
font-family:
Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
sans-serif;
color: #17211c;
background: #eef1ed;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
min-width: 320px;
}
button,
input,
select {
font: inherit;
}
button {
border: 1px solid #b8c2b5;
border-radius: 6px;
background: #ffffff;
color: #17211c;
cursor: pointer;
min-height: 38px;
padding: 0.55rem 0.8rem;
}
button:hover:not(:disabled) {
border-color: #5d7f86;
background: #f4f8f7;
}
button:disabled {
cursor: not-allowed;
opacity: 0.55;
}
input,
select {
width: 100%;
border: 1px solid #b8c2b5;
border-radius: 6px;
background: #ffffff;
color: #17211c;
min-height: 38px;
padding: 0.5rem 0.65rem;
}
label,
legend {
color: #394840;
font-size: 0.84rem;
font-weight: 650;
}
a {
color: #0b6977;
}
.app-shell {
display: grid;
grid-template-columns: minmax(320px, 390px) minmax(0, 1fr);
min-height: 100vh;
}
.control-panel {
display: flex;
flex-direction: column;
gap: 1rem;
border-right: 1px solid #cdd5c9;
background: #fafbf8;
padding: 1rem;
overflow-y: auto;
}
.brand-header h1 {
margin: 0;
color: #17211c;
font-size: 1.65rem;
line-height: 1.1;
}
.brand-header p {
margin: 0.25rem 0 0;
color: #66726a;
font-size: 0.92rem;
line-height: 1.4;
}
.control-group {
display: flex;
flex-direction: column;
gap: 0.42rem;
margin: 0;
min-width: 0;
border: 0;
padding: 0;
}
.custom-fields {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0.75rem;
}
.segmented-control {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0.5rem;
}
.segmented-control label {
display: flex;
align-items: center;
gap: 0.45rem;
border: 1px solid #b8c2b5;
border-radius: 6px;
background: #ffffff;
min-height: 38px;
padding: 0.45rem 0.55rem;
font-weight: 560;
}
.segmented-control input {
width: auto;
min-height: auto;
}
.viewport-note {
margin: -0.25rem 0 0;
color: #66726a;
font-size: 0.86rem;
line-height: 1.4;
}
.button-row,
.query-actions {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.primary-button {
border-color: #226a5d;
background: #226a5d;
color: #ffffff;
font-weight: 700;
}
.primary-button:hover:not(:disabled) {
border-color: #174d44;
background: #174d44;
}
.query-panel,
.results-panel {
display: flex;
flex-direction: column;
min-height: 0;
}
.panel-heading {
display: flex;
align-items: center;
justify-content: space-between;
gap: 0.75rem;
margin-bottom: 0.55rem;
}
.panel-heading h2 {
margin: 0;
font-size: 1rem;
line-height: 1.2;
}
.panel-heading span {
color: #66726a;
font-weight: 700;
}
.query-preview {
overflow: auto;
max-height: 260px;
margin: 0;
border: 1px solid #cbd6cf;
border-radius: 6px;
background: #16201d;
color: #eaf4ef;
padding: 0.75rem;
font-family: "SFMono-Regular", Consolas, "Liberation Mono", monospace;
font-size: 0.78rem;
line-height: 1.5;
white-space: pre-wrap;
word-break: break-word;
}
.message {
margin: 0;
border-left: 3px solid #2e7a70;
background: #e8f3ef;
color: #29433b;
padding: 0.65rem 0.75rem;
font-size: 0.9rem;
line-height: 1.4;
}
.error-message {
border-left-color: #a13f30;
background: #f9e9e5;
color: #6d2d23;
}
.workspace {
display: grid;
grid-template-rows: minmax(420px, 1fr) minmax(180px, 34vh);
min-width: 0;
min-height: 100vh;
}
.map-region {
min-width: 0;
min-height: 420px;
}
.map-view {
width: 100%;
height: 100%;
}
.result-marker {
display: grid;
place-items: center;
border: 2px solid #ffffff;
border-radius: 50%;
background: #0b6977;
box-shadow: 0 2px 10px rgb(0 0 0 / 25%);
}
.result-marker span {
display: block;
width: 7px;
height: 7px;
border-radius: 50%;
background: #ffffff;
}
.result-marker-selected {
background: #c84830;
box-shadow: 0 0 0 4px rgb(200 72 48 / 20%);
}
.results-panel {
border-top: 1px solid #cdd5c9;
background: #f7f8f5;
padding: 0.9rem 1rem 1rem;
overflow: hidden;
}
.results-list {
display: grid;
gap: 0.55rem;
overflow: auto;
margin: 0;
padding: 0;
list-style: none;
}
.results-list li {
display: grid;
gap: 0.35rem;
border: 1px solid #d7ded5;
border-radius: 8px;
background: #ffffff;
padding: 0.5rem;
}
.result-row {
display: grid;
gap: 0.25rem;
width: 100%;
border: 0;
background: transparent;
padding: 0.25rem;
text-align: left;
}
.result-row:hover:not(:disabled),
.result-row-selected {
background: #eef6f4;
}
.result-title {
color: #17211c;
font-weight: 750;
}
.result-meta,
.tag-list {
color: #66726a;
font-size: 0.82rem;
line-height: 1.35;
}
.osm-link {
justify-self: start;
padding: 0 0.25rem 0.2rem;
font-size: 0.82rem;
font-weight: 650;
}
.empty-state {
display: grid;
place-items: center;
min-height: 120px;
border: 1px dashed #b8c2b5;
border-radius: 8px;
color: #66726a;
padding: 1rem;
text-align: center;
line-height: 1.45;
}
@media (max-width: 900px) {
.app-shell {
grid-template-columns: 1fr;
}
.control-panel {
border-right: 0;
border-bottom: 1px solid #cdd5c9;
}
.workspace {
grid-template-rows: 62vh minmax(260px, auto);
min-height: auto;
}
}
@media (max-width: 560px) {
.control-panel,
.results-panel {
padding: 0.8rem;
}
.custom-fields,
.segmented-control {
grid-template-columns: 1fr;
}
.query-actions,
.button-row {
flex-direction: column;
}
.button-row button,
.query-actions button {
width: 100%;
}
}