mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-12 14:22:21 +00:00
619 lines
13 KiB
CSS
619 lines
13 KiB
CSS
/* ── Street Level panel ─────────────────────────────────────────
|
||
The rail owns position and width (layers.css). */
|
||
#street-level-panel {
|
||
--sl-green: #05cb63;
|
||
/* KartaView's purple for lines; a lighter one where it is text (WCAG AA). */
|
||
--sl-kartaview: #635bff;
|
||
--sl-kartaview-text: #8f8aff;
|
||
/* Panoramax's orange; the darker one sits behind white text. */
|
||
--sl-panoramax: #ff6f00;
|
||
--sl-panoramax-fill: #b84e00;
|
||
--sl-text: 0.6rem;
|
||
}
|
||
|
||
#street-level-panel .panel-glow {
|
||
position: absolute;
|
||
inset: -18px;
|
||
background: radial-gradient(
|
||
ellipse at center,
|
||
rgba(5, 203, 99, 0.16) 0%,
|
||
transparent 65%
|
||
);
|
||
filter: blur(16px);
|
||
opacity: 0.25;
|
||
pointer-events: none;
|
||
}
|
||
|
||
.street-level-panel-inner {
|
||
position: relative;
|
||
background: var(--glass-bg);
|
||
border: 1px solid var(--glass-border);
|
||
border-radius: var(--panel-radius);
|
||
padding: 14px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8px;
|
||
backdrop-filter: blur(24px) saturate(1.4);
|
||
-webkit-backdrop-filter: blur(24px) saturate(1.4);
|
||
box-shadow:
|
||
0 8px 32px rgba(0, 0, 0, 0.5),
|
||
0 0 0 1px rgba(255, 255, 255, 0.03) inset,
|
||
0 1px 0 rgba(255, 255, 255, 0.06) inset;
|
||
scrollbar-width: thin;
|
||
scrollbar-color: rgba(0, 212, 255, 0.46) rgba(255, 255, 255, 0.06);
|
||
}
|
||
|
||
/* Class-qualified, not id-qualified, so a theme's header rule still wins. */
|
||
.street-level-panel-inner > .panel-header {
|
||
gap: 8px;
|
||
}
|
||
|
||
.sl-status {
|
||
background: transparent;
|
||
font: inherit;
|
||
font-family: var(--font-mono);
|
||
font-size: var(--sl-text);
|
||
letter-spacing: 0.1em;
|
||
padding: 2px 7px;
|
||
border-radius: 999px;
|
||
border: 1px solid var(--glass-border-hover);
|
||
color: var(--text-secondary);
|
||
white-space: nowrap;
|
||
cursor: pointer;
|
||
transition:
|
||
border-color var(--transition-fast),
|
||
color var(--transition-fast);
|
||
}
|
||
|
||
.sl-status:hover,
|
||
.sl-status:focus-visible {
|
||
color: var(--text-primary);
|
||
border-color: var(--accent);
|
||
outline: none;
|
||
}
|
||
|
||
.sl-status.is-on {
|
||
color: var(--sl-green);
|
||
border-color: rgba(5, 203, 99, 0.55);
|
||
}
|
||
|
||
.sl-status.is-busy {
|
||
color: var(--accent);
|
||
border-color: rgba(0, 212, 255, 0.55);
|
||
}
|
||
|
||
.sl-status.is-warn {
|
||
color: #ffb300;
|
||
border-color: rgba(255, 179, 0, 0.55);
|
||
}
|
||
|
||
/* Collapsed strips hide the body entirely: nothing to paint or tab into. */
|
||
#street-level-panel.collapsed .sl-body,
|
||
#street-level-panel.collapsed .sl-status {
|
||
display: none;
|
||
}
|
||
|
||
.sl-body,
|
||
.sl-controls {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8px;
|
||
}
|
||
|
||
.sl-body {
|
||
min-height: 0;
|
||
}
|
||
|
||
.sl-controls {
|
||
min-width: 0;
|
||
margin: 0;
|
||
padding: 0;
|
||
border: 0;
|
||
}
|
||
|
||
.sl-controls:disabled {
|
||
opacity: 0.45;
|
||
pointer-events: none;
|
||
}
|
||
|
||
/* ── Providers ───────────────────────────────────────────────────────────── */
|
||
.sl-providers {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
flex-wrap: wrap;
|
||
}
|
||
|
||
.sl-chips {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 4px;
|
||
}
|
||
|
||
/* `--chip-color` comes from the provider. */
|
||
.sl-chips .data-toggle-chip {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 5px;
|
||
}
|
||
|
||
.sl-chips .data-toggle-chip::before {
|
||
content: '';
|
||
width: 7px;
|
||
height: 7px;
|
||
border-radius: 50%;
|
||
background: var(--chip-color, currentColor);
|
||
opacity: 0.45;
|
||
flex: none;
|
||
}
|
||
|
||
.sl-chips .data-toggle-chip.active {
|
||
color: var(--chip-color, var(--accent));
|
||
border-color: var(--chip-color, var(--accent));
|
||
background: color-mix(
|
||
in srgb,
|
||
var(--chip-color, var(--accent)) 14%,
|
||
transparent
|
||
);
|
||
}
|
||
|
||
/* #635bff text on its own tint is 3.7:1 at this size; the lighter one is ~6:1. */
|
||
.sl-chips .data-toggle-chip.active[data-chip-id='kartaview'] {
|
||
color: var(--sl-kartaview-text);
|
||
}
|
||
|
||
.sl-chips .data-toggle-chip.active::before {
|
||
opacity: 1;
|
||
}
|
||
|
||
.sl-chips .data-toggle-chip.chip-error {
|
||
color: #ffb300;
|
||
border-color: rgba(255, 179, 0, 0.55);
|
||
}
|
||
|
||
/* The coverage hint and OPEN STREET VIEW share a line; the hint wraps. */
|
||
.sl-meta-row {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
}
|
||
|
||
.sl-meta-row .sl-meta {
|
||
flex: 1 1 auto;
|
||
min-width: 0;
|
||
}
|
||
|
||
/* Scoped to outrank .scene-btn's flex: 1, which squeezed the button to its
|
||
min-width beside a long coverage line and clipped its one-line label. */
|
||
.sl-meta-row .sl-nearest-btn {
|
||
flex: 0 0 auto;
|
||
}
|
||
|
||
.sl-nearest-btn[hidden] {
|
||
display: none;
|
||
}
|
||
|
||
/* When the hint and the button do not both fit, the button takes its own line. */
|
||
html:not([lang='en']) .sl-meta-row {
|
||
flex-wrap: wrap;
|
||
}
|
||
|
||
html:not([lang='en']) .sl-meta-row .sl-meta {
|
||
flex: 1 1 14em;
|
||
}
|
||
|
||
html:not([lang='en']) .sl-meta-row .sl-nearest-btn {
|
||
flex: 1 0 auto;
|
||
}
|
||
|
||
/* ── Errors ──────────────────────────────────────────────────────────────── */
|
||
.sl-error {
|
||
font-family: var(--font-sans);
|
||
font-size: 0.72rem;
|
||
line-height: 1.4;
|
||
color: #ff8a80;
|
||
}
|
||
|
||
/* ── Filters ──────────────────────────────────────────────────── */
|
||
.sl-filters {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
flex-wrap: wrap;
|
||
}
|
||
|
||
.sl-seg[hidden],
|
||
.sl-controls[hidden],
|
||
.sl-filters[hidden],
|
||
.sl-since[hidden] {
|
||
display: none;
|
||
}
|
||
|
||
.sl-since {
|
||
display: grid;
|
||
grid-template-columns: auto 1fr;
|
||
align-items: center;
|
||
gap: 4px 10px;
|
||
}
|
||
|
||
.sl-range {
|
||
width: 100%;
|
||
min-width: 0;
|
||
margin: 0;
|
||
accent-color: var(--sl-green);
|
||
cursor: pointer;
|
||
}
|
||
|
||
.sl-range:focus-visible {
|
||
outline: 1px solid var(--accent);
|
||
outline-offset: 3px;
|
||
}
|
||
|
||
/* The value and its note share a line: ANY DATE (by upload date). */
|
||
.sl-since-value {
|
||
grid-column: 2;
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
align-items: baseline;
|
||
gap: 0 6px;
|
||
min-width: 0;
|
||
}
|
||
|
||
.sl-since-note {
|
||
font-family: var(--font-mono);
|
||
font-size: 0.5rem;
|
||
letter-spacing: 0.08em;
|
||
color: var(--text-secondary);
|
||
}
|
||
|
||
.sl-since-note[hidden] {
|
||
display: none;
|
||
}
|
||
|
||
.sl-since-label {
|
||
font-family: var(--font-mono);
|
||
font-size: var(--sl-text);
|
||
letter-spacing: 0.08em;
|
||
color: var(--text-primary);
|
||
}
|
||
|
||
/* ── Embedded viewer ─────────────────────────────────────────────────────── */
|
||
.sl-viewer-wrap {
|
||
position: relative;
|
||
container-type: inline-size;
|
||
display: flex;
|
||
flex-direction: column;
|
||
flex: 0 0 auto;
|
||
border-radius: 12px;
|
||
overflow: hidden;
|
||
border: 1px solid var(--glass-border-hover);
|
||
background: #000;
|
||
}
|
||
|
||
.sl-viewer-wrap[hidden] {
|
||
display: none;
|
||
}
|
||
|
||
/* Nothing sits over the image, so the provider's own controls stay clear. */
|
||
.sl-viewer-stage {
|
||
position: relative;
|
||
display: flex;
|
||
flex-direction: column;
|
||
flex: 0 0 auto;
|
||
}
|
||
|
||
.sl-viewer {
|
||
width: 100%;
|
||
aspect-ratio: 16 / 10;
|
||
min-height: 180px;
|
||
}
|
||
|
||
.sl-viewer-placeholder {
|
||
position: absolute;
|
||
inset: 0;
|
||
display: grid;
|
||
place-items: center;
|
||
z-index: 3;
|
||
background: rgba(0, 0, 0, 0.35);
|
||
}
|
||
|
||
.sl-viewer-placeholder[hidden] {
|
||
display: none;
|
||
}
|
||
|
||
.sl-viewer-placeholder::after {
|
||
content: '';
|
||
width: 28px;
|
||
height: 28px;
|
||
border-radius: 50%;
|
||
border: 2px solid rgba(255, 255, 255, 0.2);
|
||
border-top-color: var(--sl-green);
|
||
animation: sl-spin 0.9s linear infinite;
|
||
}
|
||
|
||
@keyframes sl-spin {
|
||
to {
|
||
transform: rotate(360deg);
|
||
}
|
||
}
|
||
|
||
.sl-viewer-bar {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
gap: 6px;
|
||
padding: 5px 6px;
|
||
background: rgba(10, 10, 15, 0.85);
|
||
border-bottom: 1px solid var(--glass-border);
|
||
}
|
||
|
||
.sl-viewer-tools {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
min-width: 0;
|
||
flex-wrap: wrap;
|
||
}
|
||
|
||
.sl-viewer-tools .scene-btn {
|
||
padding: 4px 8px;
|
||
font-size: var(--sl-text);
|
||
background: rgba(10, 10, 15, 0.75);
|
||
flex: none;
|
||
min-width: 0;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
}
|
||
|
||
.sl-viewer-tools .scene-btn[hidden] {
|
||
display: none;
|
||
}
|
||
|
||
.sl-viewer-tools .sl-seg {
|
||
background: rgba(10, 10, 15, 0.75);
|
||
}
|
||
|
||
@container (max-width: 380px) {
|
||
.sl-viewer-tools .sl-btn-text {
|
||
display: none;
|
||
}
|
||
}
|
||
|
||
.sl-viewer-x {
|
||
flex: none;
|
||
width: 26px;
|
||
height: 26px;
|
||
border-radius: 50%;
|
||
border: 1px solid rgba(255, 255, 255, 0.25);
|
||
background: rgba(10, 10, 15, 0.8);
|
||
color: var(--text-primary);
|
||
font-family: var(--font-mono);
|
||
font-size: 1.1rem;
|
||
line-height: 1;
|
||
cursor: pointer;
|
||
display: grid;
|
||
place-items: center;
|
||
transition: all var(--transition-fast);
|
||
}
|
||
|
||
.sl-viewer-x:hover {
|
||
color: #0a0a0f;
|
||
background: #fff;
|
||
border-color: #fff;
|
||
}
|
||
|
||
.sl-image-meta {
|
||
flex: 0 0 auto;
|
||
padding: 6px 10px;
|
||
font-family: var(--font-mono);
|
||
font-size: var(--sl-text);
|
||
letter-spacing: 0.06em;
|
||
color: var(--text-secondary);
|
||
background: rgba(0, 0, 0, 0.7);
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
gap: 2px 10px;
|
||
min-height: 26px;
|
||
}
|
||
|
||
.sl-image-by {
|
||
color: var(--text-primary);
|
||
overflow-wrap: anywhere;
|
||
min-width: 0;
|
||
}
|
||
|
||
.sl-image-by:empty {
|
||
display: none;
|
||
}
|
||
|
||
.sl-image-right {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
margin-left: auto;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.sl-image-link {
|
||
color: var(--sl-green);
|
||
text-decoration: none;
|
||
letter-spacing: 0.1em;
|
||
}
|
||
|
||
.sl-image-link[hidden] {
|
||
display: none;
|
||
}
|
||
|
||
.sl-image-link:hover {
|
||
text-decoration: underline;
|
||
}
|
||
|
||
.sl-meta {
|
||
font-family: var(--font-mono);
|
||
font-size: var(--sl-text);
|
||
letter-spacing: 0.06em;
|
||
color: var(--text-secondary);
|
||
}
|
||
|
||
.sl-meta:empty {
|
||
display: none;
|
||
}
|
||
|
||
/* ── Full screen (EXPAND) ────────────────────────────────────────────────── */
|
||
/* The browser lifts the viewer into the top layer; the photo takes the rest.
|
||
iPhone Safari has no element fullscreen, so there the viewer is a popover
|
||
sized to the viewport instead. */
|
||
.sl-viewer-wrap:fullscreen {
|
||
border: 0;
|
||
border-radius: 0;
|
||
}
|
||
|
||
.sl-viewer-wrap:popover-open {
|
||
position: fixed;
|
||
inset: 0;
|
||
width: 100vw;
|
||
height: 100dvh;
|
||
max-width: none;
|
||
max-height: none;
|
||
margin: 0;
|
||
padding: 0;
|
||
border: 0;
|
||
border-radius: 0;
|
||
}
|
||
|
||
.sl-viewer-wrap:is(:fullscreen, :popover-open) .sl-viewer-stage,
|
||
.sl-viewer-wrap:is(:fullscreen, :popover-open) .sl-viewer {
|
||
flex: 1 1 auto;
|
||
height: auto;
|
||
min-height: 0;
|
||
aspect-ratio: auto;
|
||
}
|
||
|
||
/* ── Photo viewer (KartaView, Panoramax) ─────────────────────────────────── */
|
||
.sl-photo-viewer {
|
||
/* The lit source's colour: a focus ring, and behind the white ‹ › glyphs. */
|
||
--sl-photo-ring: var(--sl-kartaview-text);
|
||
--sl-photo-fill: color-mix(in srgb, var(--sl-kartaview) 85%, transparent);
|
||
position: absolute;
|
||
inset: 0;
|
||
background: #000;
|
||
outline: none;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.sl-photo-viewer:focus-visible {
|
||
outline: none;
|
||
}
|
||
|
||
/* The photo and canvas fill the viewer and would cover a ring drawn on it:
|
||
draw the ring on a layer above them (clicks pass through). */
|
||
.sl-photo-viewer:focus-visible::after {
|
||
content: '';
|
||
position: absolute;
|
||
inset: 0;
|
||
z-index: 3;
|
||
border: 2px solid var(--sl-photo-ring);
|
||
pointer-events: none;
|
||
}
|
||
|
||
/* White on #ff6f00 is 2.8:1; on the darker orange behind ‹ › it is 5.1:1. */
|
||
.sl-photo-viewer[data-provider='panoramax'] {
|
||
--sl-photo-ring: var(--sl-panoramax);
|
||
--sl-photo-fill: var(--sl-panoramax-fill);
|
||
}
|
||
|
||
.sl-photo-flat,
|
||
.sl-photo-pano {
|
||
position: absolute;
|
||
inset: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
user-select: none;
|
||
}
|
||
|
||
.sl-photo-flat {
|
||
object-fit: contain;
|
||
}
|
||
|
||
.sl-photo-pano {
|
||
cursor: grab;
|
||
touch-action: none;
|
||
}
|
||
|
||
.sl-photo-pano.sl-photo-dragging {
|
||
cursor: grabbing;
|
||
}
|
||
|
||
.sl-photo-flat[hidden],
|
||
.sl-photo-pano[hidden] {
|
||
display: none;
|
||
}
|
||
|
||
.sl-photo-step {
|
||
position: absolute;
|
||
top: 50%;
|
||
z-index: 2;
|
||
width: 34px;
|
||
height: 44px;
|
||
margin-top: -22px;
|
||
border: 1px solid rgba(255, 255, 255, 0.18);
|
||
border-radius: 8px;
|
||
background: rgba(10, 10, 15, 0.62);
|
||
color: #fff;
|
||
font-size: 1.5rem;
|
||
line-height: 1;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.sl-photo-step-prev {
|
||
left: 6px;
|
||
}
|
||
|
||
.sl-photo-step-next {
|
||
right: 6px;
|
||
}
|
||
|
||
.sl-photo-step:hover:not(:disabled),
|
||
.sl-photo-step:focus-visible {
|
||
background: var(--sl-photo-fill);
|
||
outline: none;
|
||
}
|
||
|
||
.sl-photo-step:disabled {
|
||
opacity: 0.3;
|
||
cursor: default;
|
||
}
|
||
|
||
/* Nothing to step through until a photo shows. */
|
||
.sl-photo-viewer:not([data-kind='flat']):not([data-kind='pano'])
|
||
.sl-photo-step {
|
||
display: none;
|
||
}
|
||
|
||
/* ── Short viewports ─────────────────────────────────────────────────────── */
|
||
@media (max-height: 640px) {
|
||
.street-level-panel-inner {
|
||
padding: 10px;
|
||
gap: 6px;
|
||
}
|
||
|
||
.sl-viewer {
|
||
min-height: 150px;
|
||
}
|
||
}
|
||
|
||
/* ── Phones ──────────────────────────────────────────────────────────────── */
|
||
/* The phone rail spans 50vh + 8px to 2vh + 7.5rem from the bottom
|
||
(responsive.css). Size the photo to that band, less ~150px of panel chrome,
|
||
so it shows without scrolling. */
|
||
@media (max-width: 720px) {
|
||
.sl-viewer {
|
||
aspect-ratio: auto;
|
||
height: clamp(110px, calc(48vh - 8px - 7.5rem - 150px), 320px);
|
||
min-height: 0;
|
||
}
|
||
}
|