Modular-Staging
accius 1 day ago
parent bb16dff928
commit 01aa159a01

@ -572,439 +572,6 @@ const App = () => {
<span>35</span>
</div>
</div>
) : config.layout === 'tablet' ? (
/* TABLET LAYOUT - Optimized for 7-10" widescreen displays (16:9) */
<div style={{
width: '100vw',
height: '100vh',
display: 'flex',
flexDirection: 'column',
background: 'var(--bg-primary)',
fontFamily: 'JetBrains Mono, monospace',
overflow: 'hidden'
}}>
{/* COMPACT TOP BAR */}
<div style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
background: 'var(--bg-panel)',
borderBottom: '1px solid var(--border-color)',
padding: '4px 12px',
height: '44px',
flexShrink: 0,
gap: '8px'
}}>
{/* Callsign */}
<span
style={{
fontSize: '20px',
fontWeight: '900',
color: 'var(--accent-amber)',
fontFamily: 'Orbitron, monospace',
cursor: 'pointer',
whiteSpace: 'nowrap'
}}
onClick={() => setShowSettings(true)}
title="Settings"
>
{config.callsign}
</span>
{/* UTC */}
<div style={{ display: 'flex', alignItems: 'center', gap: '4px', whiteSpace: 'nowrap' }}>
<span style={{ fontSize: '11px', color: 'var(--text-muted)' }}>UTC</span>
<span style={{ fontSize: '18px', fontWeight: '700', color: 'var(--accent-cyan)' }}>{utcTime}</span>
</div>
{/* Local */}
<div
style={{ display: 'flex', alignItems: 'center', gap: '4px', cursor: 'pointer', whiteSpace: 'nowrap' }}
onClick={handleTimeFormatToggle}
title={`Click for ${use12Hour ? '24h' : '12h'} format`}
>
<span style={{ fontSize: '11px', color: 'var(--text-muted)' }}>LOC</span>
<span style={{ fontSize: '18px', fontWeight: '700', color: 'var(--accent-amber)' }}>{localTime}</span>
</div>
{/* Solar Quick Stats */}
<div style={{ display: 'flex', gap: '8px', fontSize: '12px', whiteSpace: 'nowrap' }}>
<span>
<span style={{ color: 'var(--text-muted)' }}>SFI </span>
<span style={{ color: 'var(--accent-amber)', fontWeight: '700' }}>{solarIndices?.data?.sfi?.current || spaceWeather?.data?.solarFlux || '--'}</span>
</span>
<span>
<span style={{ color: 'var(--text-muted)' }}>K </span>
<span style={{ color: parseInt(solarIndices?.data?.kp?.current ?? spaceWeather?.data?.kIndex) >= 4 ? 'var(--accent-red)' : 'var(--accent-green)', fontWeight: '700' }}>
{solarIndices?.data?.kp?.current ?? spaceWeather?.data?.kIndex ?? '--'}
</span>
</span>
<span>
<span style={{ color: 'var(--text-muted)' }}>SSN </span>
<span style={{ color: 'var(--accent-cyan)', fontWeight: '700' }}>{solarIndices?.data?.ssn?.current || '--'}</span>
</span>
</div>
{/* Controls */}
<div style={{ display: 'flex', gap: '4px' }}>
<button
onClick={() => setShowSettings(true)}
style={{
background: 'var(--bg-tertiary)',
border: '1px solid var(--border-color)',
padding: '4px 8px',
borderRadius: '4px',
color: 'var(--text-secondary)',
fontSize: '12px',
cursor: 'pointer'
}}
></button>
<button
onClick={handleFullscreenToggle}
style={{
background: 'var(--bg-tertiary)',
border: '1px solid var(--border-color)',
padding: '4px 8px',
borderRadius: '4px',
color: 'var(--text-secondary)',
fontSize: '12px',
cursor: 'pointer'
}}
>{isFullscreen ? '⛶' : '⛶'}</button>
</div>
</div>
{/* MAIN AREA: Map + Data Sidebar */}
<div style={{ flex: 1, display: 'flex', overflow: 'hidden' }}>
{/* MAP */}
<div style={{ flex: 1, position: 'relative' }}>
<WorldMap
deLocation={config.location}
dxLocation={dxLocation}
onDXChange={handleDXChange}
potaSpots={potaSpots.data}
mySpots={mySpots.data}
dxPaths={dxPaths.data}
dxFilters={dxFilters}
satellites={satellites.data}
pskReporterSpots={filteredPskSpots}
showDXPaths={mapLayers.showDXPaths}
showDXLabels={mapLayers.showDXLabels}
onToggleDXLabels={toggleDXLabels}
showPOTA={mapLayers.showPOTA}
showSatellites={mapLayers.showSatellites}
showPSKReporter={mapLayers.showPSKReporter}
wsjtxSpots={wsjtxMapSpots}
showWSJTX={mapLayers.showWSJTX}
onToggleSatellites={toggleSatellites}
hoveredSpot={hoveredSpot}
/>
</div>
{/* DATA SIDEBAR */}
<div style={{
width: '220px',
flexShrink: 0,
display: 'flex',
flexDirection: 'column',
borderLeft: '1px solid var(--border-color)',
background: 'var(--bg-secondary)',
overflow: 'hidden'
}}>
{/* Band Conditions Grid */}
<div style={{ padding: '6px', borderBottom: '1px solid var(--border-color)' }}>
<div style={{ fontSize: '10px', color: 'var(--accent-amber)', fontWeight: '700', marginBottom: '4px', textTransform: 'uppercase', letterSpacing: '0.5px' }}>Band Conditions</div>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: '3px' }}>
{(bandConditions?.data || []).slice(0, 13).map((band, idx) => {
const colors = {
GOOD: { bg: 'rgba(0,255,136,0.2)', color: '#00ff88', border: 'rgba(0,255,136,0.4)' },
FAIR: { bg: 'rgba(255,180,50,0.2)', color: '#ffb432', border: 'rgba(255,180,50,0.4)' },
POOR: { bg: 'rgba(255,68,102,0.2)', color: '#ff4466', border: 'rgba(255,68,102,0.4)' }
};
const s = colors[band.condition] || colors.FAIR;
return (
<div key={idx} style={{
background: s.bg,
border: `1px solid ${s.border}`,
borderRadius: '3px',
padding: '3px 1px',
textAlign: 'center'
}}>
<div style={{ fontFamily: 'Orbitron, monospace', fontSize: '11px', fontWeight: '700', color: s.color }}>{band.band}</div>
<div style={{ fontSize: '8px', fontWeight: '600', color: s.color, opacity: 0.8 }}>{band.condition}</div>
</div>
);
})}
</div>
{/* MUF/LUF */}
{propagation.data && (
<div style={{ display: 'flex', gap: '8px', marginTop: '4px', fontSize: '10px', justifyContent: 'center' }}>
<span><span style={{ color: 'var(--text-muted)' }}>MUF </span><span style={{ color: '#ff8800', fontWeight: '600' }}>{propagation.data.muf || '?'}</span></span>
<span><span style={{ color: 'var(--text-muted)' }}>LUF </span><span style={{ color: '#00aaff', fontWeight: '600' }}>{propagation.data.luf || '?'}</span></span>
</div>
)}
</div>
{/* Compact DX Cluster */}
<div style={{ flex: 1, overflow: 'hidden', display: 'flex', flexDirection: 'column' }}>
<div style={{ padding: '4px 6px', borderBottom: '1px solid var(--border-color)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<span style={{ fontSize: '10px', color: 'var(--accent-red)', fontWeight: '700', textTransform: 'uppercase' }}>DX Cluster</span>
<span style={{ fontSize: '9px', color: 'var(--text-muted)' }}>{dxCluster.data?.length || 0} spots</span>
</div>
<div style={{ flex: 1, overflowY: 'auto', fontSize: '11px' }}>
{dxCluster.data?.slice(0, 30).map((spot, i) => (
<div
key={i}
style={{
padding: '2px 6px',
display: 'grid',
gridTemplateColumns: '55px 1fr 30px',
gap: '3px',
borderBottom: '1px solid rgba(255,255,255,0.04)',
cursor: 'pointer',
background: hoveredSpot?.call === spot.call ? 'var(--bg-tertiary)' : 'transparent',
fontSize: '10px'
}}
onMouseEnter={() => setHoveredSpot(spot)}
onMouseLeave={() => setHoveredSpot(null)}
>
<span style={{ color: '#ffff00' }}>{parseFloat(spot.freq).toFixed(1)}</span>
<span style={{ color: 'var(--accent-cyan)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{spot.call}</span>
<span style={{ color: 'var(--text-muted)', textAlign: 'right' }}>{spot.time || '--'}</span>
</div>
))}
</div>
</div>
</div>
</div>
</div>
) : config.layout === 'compact' ? (
/* COMPACT LAYOUT - Optimized for 4:3 screens and data-first display */
<div style={{
width: '100vw',
height: '100vh',
display: 'flex',
flexDirection: 'column',
background: 'var(--bg-primary)',
fontFamily: 'JetBrains Mono, monospace',
overflow: 'hidden'
}}>
{/* TOP: Callsign + Times + Solar */}
<div style={{
background: 'var(--bg-panel)',
borderBottom: '1px solid var(--border-color)',
padding: '8px 12px',
flexShrink: 0
}}>
{/* Row 1: Callsign + Times */}
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: '4px' }}>
<span
style={{
fontSize: '26px',
fontWeight: '900',
color: 'var(--accent-amber)',
fontFamily: 'Orbitron, monospace',
cursor: 'pointer'
}}
onClick={() => setShowSettings(true)}
title="Settings"
>
{config.callsign}
</span>
<div style={{ display: 'flex', gap: '16px', alignItems: 'center' }}>
<div style={{ textAlign: 'center' }}>
<div style={{ fontSize: '9px', color: 'var(--text-muted)', textTransform: 'uppercase' }}>UTC</div>
<div style={{ fontSize: '22px', fontWeight: '700', color: 'var(--accent-cyan)', lineHeight: 1 }}>{utcTime}</div>
<div style={{ fontSize: '10px', color: 'var(--text-muted)' }}>{utcDate}</div>
</div>
<div
style={{ textAlign: 'center', cursor: 'pointer' }}
onClick={handleTimeFormatToggle}
title={`Click for ${use12Hour ? '24h' : '12h'}`}
>
<div style={{ fontSize: '9px', color: 'var(--text-muted)', textTransform: 'uppercase' }}>Local</div>
<div style={{ fontSize: '22px', fontWeight: '700', color: 'var(--accent-amber)', lineHeight: 1 }}>{localTime}</div>
<div style={{ fontSize: '10px', color: 'var(--text-muted)' }}>{localDate}</div>
</div>
</div>
<div style={{ display: 'flex', gap: '4px' }}>
<button
onClick={() => setShowSettings(true)}
style={{
background: 'var(--bg-tertiary)',
border: '1px solid var(--border-color)',
padding: '4px 8px',
borderRadius: '4px',
color: 'var(--text-secondary)',
fontSize: '12px',
cursor: 'pointer'
}}
></button>
<button
onClick={handleFullscreenToggle}
style={{
background: 'var(--bg-tertiary)',
border: '1px solid var(--border-color)',
padding: '4px 8px',
borderRadius: '4px',
color: 'var(--text-secondary)',
fontSize: '12px',
cursor: 'pointer'
}}
></button>
</div>
</div>
{/* Row 2: Solar indices inline */}
<div style={{ display: 'flex', gap: '12px', fontSize: '12px', justifyContent: 'center' }}>
<span>
<span style={{ color: 'var(--text-muted)' }}>SFI </span>
<span style={{ color: 'var(--accent-amber)', fontWeight: '700' }}>{solarIndices?.data?.sfi?.current || spaceWeather?.data?.solarFlux || '--'}</span>
</span>
<span>
<span style={{ color: 'var(--text-muted)' }}>K </span>
<span style={{ color: parseInt(solarIndices?.data?.kp?.current ?? spaceWeather?.data?.kIndex) >= 4 ? 'var(--accent-red)' : 'var(--accent-green)', fontWeight: '700' }}>
{solarIndices?.data?.kp?.current ?? spaceWeather?.data?.kIndex ?? '--'}
</span>
</span>
<span>
<span style={{ color: 'var(--text-muted)' }}>SSN </span>
<span style={{ color: 'var(--accent-cyan)', fontWeight: '700' }}>{solarIndices?.data?.ssn?.current || '--'}</span>
</span>
{propagation.data && (
<>
<span>
<span style={{ color: 'var(--text-muted)' }}>MUF </span>
<span style={{ color: '#ff8800', fontWeight: '600' }}>{propagation.data.muf || '?'} MHz</span>
</span>
<span>
<span style={{ color: 'var(--text-muted)' }}>LUF </span>
<span style={{ color: '#00aaff', fontWeight: '600' }}>{propagation.data.luf || '?'} MHz</span>
</span>
</>
)}
{localWeather?.data && (
<span>
<span style={{ marginRight: '2px' }}>{localWeather.data.icon}</span>
<span style={{ color: 'var(--accent-cyan)', fontWeight: '600' }}>{localWeather.data.temp}°{localWeather.data.tempUnit || tempUnit}</span>
</span>
)}
</div>
</div>
{/* BAND CONDITIONS - Full Width */}
<div style={{
padding: '6px 12px',
borderBottom: '1px solid var(--border-color)',
background: 'var(--bg-secondary)',
flexShrink: 0
}}>
<div style={{ display: 'flex', justifyContent: 'center', gap: '4px', flexWrap: 'wrap' }}>
{(bandConditions?.data || []).slice(0, 13).map((band, idx) => {
const colors = {
GOOD: { bg: 'rgba(0,255,136,0.2)', color: '#00ff88', border: 'rgba(0,255,136,0.4)' },
FAIR: { bg: 'rgba(255,180,50,0.2)', color: '#ffb432', border: 'rgba(255,180,50,0.4)' },
POOR: { bg: 'rgba(255,68,102,0.2)', color: '#ff4466', border: 'rgba(255,68,102,0.4)' }
};
const s = colors[band.condition] || colors.FAIR;
return (
<div key={idx} style={{
background: s.bg,
border: `1px solid ${s.border}`,
borderRadius: '4px',
padding: '4px 8px',
textAlign: 'center',
minWidth: '52px'
}}>
<div style={{ fontFamily: 'Orbitron, monospace', fontSize: '13px', fontWeight: '700', color: s.color }}>{band.band}</div>
<div style={{ fontSize: '9px', fontWeight: '600', color: s.color, opacity: 0.8 }}>{band.condition}</div>
</div>
);
})}
</div>
</div>
{/* MAIN: Map + DX Cluster side by side */}
<div style={{ flex: 1, display: 'flex', overflow: 'hidden' }}>
{/* Map */}
<div style={{ flex: 1, position: 'relative' }}>
<WorldMap
deLocation={config.location}
dxLocation={dxLocation}
onDXChange={handleDXChange}
potaSpots={potaSpots.data}
mySpots={mySpots.data}
dxPaths={dxPaths.data}
dxFilters={dxFilters}
satellites={satellites.data}
pskReporterSpots={filteredPskSpots}
showDXPaths={mapLayers.showDXPaths}
showDXLabels={mapLayers.showDXLabels}
onToggleDXLabels={toggleDXLabels}
showPOTA={mapLayers.showPOTA}
showSatellites={mapLayers.showSatellites}
showPSKReporter={mapLayers.showPSKReporter}
wsjtxSpots={wsjtxMapSpots}
showWSJTX={mapLayers.showWSJTX}
onToggleSatellites={toggleSatellites}
hoveredSpot={hoveredSpot}
/>
<div style={{
position: 'absolute',
bottom: '6px',
left: '50%',
transform: 'translateX(-50%)',
fontSize: '11px',
color: 'var(--text-muted)',
background: 'rgba(0,0,0,0.7)',
padding: '2px 8px',
borderRadius: '4px'
}}>
{deGrid} {dxGrid} Click map to set DX
</div>
</div>
{/* Compact DX Cluster */}
<div style={{
width: '200px',
flexShrink: 0,
borderLeft: '1px solid var(--border-color)',
background: 'var(--bg-secondary)',
display: 'flex',
flexDirection: 'column',
overflow: 'hidden'
}}>
<div style={{ padding: '4px 6px', borderBottom: '1px solid var(--border-color)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<span style={{ fontSize: '10px', color: 'var(--accent-red)', fontWeight: '700', textTransform: 'uppercase' }}>DX Cluster</span>
<span style={{ fontSize: '9px', color: 'var(--text-muted)' }}>{dxCluster.data?.length || 0}</span>
</div>
<div style={{ flex: 1, overflowY: 'auto' }}>
{dxCluster.data?.slice(0, 40).map((spot, i) => (
<div
key={i}
style={{
padding: '2px 6px',
display: 'grid',
gridTemplateColumns: '50px 1fr 28px',
gap: '3px',
borderBottom: '1px solid rgba(255,255,255,0.04)',
cursor: 'pointer',
background: hoveredSpot?.call === spot.call ? 'var(--bg-tertiary)' : 'transparent',
fontSize: '10px'
}}
onMouseEnter={() => setHoveredSpot(spot)}
onMouseLeave={() => setHoveredSpot(null)}
>
<span style={{ color: '#ffff00' }}>{parseFloat(spot.freq).toFixed(1)}</span>
<span style={{ color: 'var(--accent-cyan)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{spot.call}</span>
<span style={{ color: 'var(--text-muted)', textAlign: 'right' }}>{spot.time || '--'}</span>
</div>
))}
</div>
</div>
</div>
</div>
) : (
/* MODERN LAYOUT */
<div style={{

@ -176,9 +176,7 @@ export const SettingsPanel = ({ isOpen, onClose, config, onSave }) => {
const layoutDescriptions = {
modern: t('station.settings.layout.modern.describe'),
classic: t('station.settings.layout.classic.describe'),
tablet: t('station.settings.layout.tablet.describe'),
compact: t('station.settings.layout.compact.describe')
classic: t('station.settings.layout.classic.describe')
};
return (
@ -463,7 +461,7 @@ export const SettingsPanel = ({ isOpen, onClose, config, onSave }) => {
{t('station.settings.layout')}
</label>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: '8px' }}>
{['modern', 'classic', 'tablet', 'compact'].map((l) => (
{['modern', 'classic'].map((l) => (
<button
key={l}
onClick={() => setLayout(l)}
@ -478,7 +476,7 @@ export const SettingsPanel = ({ isOpen, onClose, config, onSave }) => {
fontWeight: layout === l ? '600' : '400'
}}
>
{l === 'modern' ? '🖥️' : l === 'classic' ? '📺' : l === 'tablet' ? '📱' : '📊'} {t('station.settings.layout.' + l)}
{l === 'modern' ? '🖥️' : '📺'} {t('station.settings.layout.' + l)}
</button>
))}
</div>

@ -53,9 +53,5 @@
"plugins.layers.earthquakes.description": "Live-USGS-Erdbebendaten (M2,5+ der letzten 24 Stunden)",
"plugins.layers.wxradar.name": "Wetterradar",
"plugins.layers.wxradar.description": "NEXRAD-Wetterradar-Überlagerung für Nordamerika",
"plugins.layers.wxradar.attribution": "Wetterdaten © Iowa State University Mesonet",
"station.settings.layout.tablet": "Tablet",
"station.settings.layout.tablet.describe": "→ Optimized for 7-10\" widescreen displays (16:9)",
"station.settings.layout.compact": "Compact",
"station.settings.layout.compact.describe": "→ Data-first layout for 4:3 and smaller screens"
"plugins.layers.wxradar.attribution": "Wetterdaten © Iowa State University Mesonet"
}

@ -28,10 +28,6 @@
"station.settings.layout.classic.describe": "→ Original HamClock-style layout",
"station.settings.layout.modern": "Modern",
"station.settings.layout.modern.describe": "→ Modern responsive grid layout",
"station.settings.layout.tablet": "Tablet",
"station.settings.layout.tablet.describe": "→ Optimized for 7-10\" widescreen displays (16:9)",
"station.settings.layout.compact": "Compact",
"station.settings.layout.compact.describe": "→ Data-first layout for 4:3 and smaller screens",
"station.settings.latitude": "Latitude",
"station.settings.locator": "Grid Square (or enter Lat/Lon below)",
"station.settings.longitude": "Longitude",

@ -54,9 +54,5 @@
"plugins.layers.earthquakes.description": "Datos sísmicos en vivo del USGS (M2.5+ de las últimas 24 horas)",
"plugins.layers.wxradar.name": "Radar meteorológico",
"plugins.layers.wxradar.description": "Superposición del radar meteorológico NEXRAD para Norteamérica",
"plugins.layers.wxradar.attribution": "Datos meteorológicos © Iowa State University Mesonet",
"station.settings.layout.tablet": "Tablet",
"station.settings.layout.tablet.describe": "→ Optimized for 7-10\" widescreen displays (16:9)",
"station.settings.layout.compact": "Compact",
"station.settings.layout.compact.describe": "→ Data-first layout for 4:3 and smaller screens"
"plugins.layers.wxradar.attribution": "Datos meteorológicos © Iowa State University Mesonet"
}

@ -53,9 +53,5 @@
"plugins.layers.earthquakes.description": "Données sismiques USGS en direct (M2,5+ sur les dernières 24 heures)",
"plugins.layers.wxradar.name": "Radar météo",
"plugins.layers.wxradar.description": "Surcouche du radar météo NEXRAD pour lAmérique du Nord",
"plugins.layers.wxradar.attribution": "Données météo © Iowa State University Mesonet",
"station.settings.layout.tablet": "Tablet",
"station.settings.layout.tablet.describe": "→ Optimized for 7-10\" widescreen displays (16:9)",
"station.settings.layout.compact": "Compact",
"station.settings.layout.compact.describe": "→ Data-first layout for 4:3 and smaller screens"
"plugins.layers.wxradar.attribution": "Données météo © Iowa State University Mesonet"
}

@ -53,9 +53,5 @@
"plugins.layers.earthquakes.description": "Dati sismici USGS in tempo reale (M2,5+ delle ultime 24 ore)",
"plugins.layers.wxradar.name": "Radar meteorologico",
"plugins.layers.wxradar.description": "Sovrapposizione del radar meteorologico NEXRAD per il Nord America",
"plugins.layers.wxradar.attribution": "Dati meteo © Iowa State University Mesonet",
"station.settings.layout.tablet": "Tablet",
"station.settings.layout.tablet.describe": "→ Optimized for 7-10\" widescreen displays (16:9)",
"station.settings.layout.compact": "Compact",
"station.settings.layout.compact.describe": "→ Data-first layout for 4:3 and smaller screens"
"plugins.layers.wxradar.attribution": "Dati meteo © Iowa State University Mesonet"
}

@ -53,9 +53,5 @@
"plugins.layers.earthquakes.description": "USGSのリアルタイム地震データ過去24時間のM2.5以上)",
"plugins.layers.wxradar.name": "気象レーダー",
"plugins.layers.wxradar.description": "北米向けNEXRAD気象レーダーのオーバーレイ",
"plugins.layers.wxradar.attribution": "気象データ © Iowa State University Mesonet",
"station.settings.layout.tablet": "Tablet",
"station.settings.layout.tablet.describe": "→ Optimized for 7-10\" widescreen displays (16:9)",
"station.settings.layout.compact": "Compact",
"station.settings.layout.compact.describe": "→ Data-first layout for 4:3 and smaller screens"
"plugins.layers.wxradar.attribution": "気象データ © Iowa State University Mesonet"
}

@ -53,9 +53,5 @@
"plugins.layers.earthquakes.description": "USGS 실시간 지진 데이터 (지난 24시간 동안 일어난 규모 M2.5 이상의 지진)",
"plugins.layers.wxradar.name": "기상 레이더",
"plugins.layers.wxradar.description": "북아메리카 지역 NEXRAD 기상 레이더 오버레이",
"plugins.layers.wxradar.attribution": "기상 데이터 © Iowa State University Mesonet",
"station.settings.layout.tablet": "Tablet",
"station.settings.layout.tablet.describe": "→ Optimized for 7-10\" widescreen displays (16:9)",
"station.settings.layout.compact": "Compact",
"station.settings.layout.compact.describe": "→ Data-first layout for 4:3 and smaller screens"
"plugins.layers.wxradar.attribution": "기상 데이터 © Iowa State University Mesonet"
}

@ -53,9 +53,5 @@
"plugins.layers.earthquakes.description": "Live USGS-aardbevingsgegevens (M2,5+ van de afgelopen 24 uur)",
"plugins.layers.wxradar.name": "Weerradar",
"plugins.layers.wxradar.description": "NEXRAD-weerradaroverlay voor Noord-Amerika",
"plugins.layers.wxradar.attribution": "Weergegevens © Iowa State University Mesonet",
"station.settings.layout.tablet": "Tablet",
"station.settings.layout.tablet.describe": "→ Optimized for 7-10\" widescreen displays (16:9)",
"station.settings.layout.compact": "Compact",
"station.settings.layout.compact.describe": "→ Data-first layout for 4:3 and smaller screens"
"plugins.layers.wxradar.attribution": "Weergegevens © Iowa State University Mesonet"
}

@ -53,9 +53,5 @@
"plugins.layers.earthquakes.description": "Dados sísmicos do USGS ao vivo (M2,5+ das últimas 24 horas)",
"plugins.layers.wxradar.name": "Radar meteorológico",
"plugins.layers.wxradar.description": "Sobreposição do radar meteorológico NEXRAD para a América do Norte",
"plugins.layers.wxradar.attribution": "Dados meteorológicos © Iowa State University Mesonet",
"station.settings.layout.tablet": "Tablet",
"station.settings.layout.tablet.describe": "→ Optimized for 7-10\" widescreen displays (16:9)",
"station.settings.layout.compact": "Compact",
"station.settings.layout.compact.describe": "→ Data-first layout for 4:3 and smaller screens"
"plugins.layers.wxradar.attribution": "Dados meteorológicos © Iowa State University Mesonet"
}

@ -905,105 +905,3 @@ body::before {
position: relative;
z-index: 10000 !important;
}
/* ============================================
RESPONSIVE: Phone & Small Screen Overrides
============================================ */
/* Tablets and small screens (under 1024px) */
@media (max-width: 1024px) {
.panel {
padding: 6px !important;
border-radius: 4px !important;
}
.panel-header {
font-size: 11px !important;
padding: 4px 6px !important;
}
}
/* Phone landscape and small tablets (under 768px) */
@media (max-width: 768px) {
/* Force single-column on modern layout */
.ohc-mobile-stack {
display: flex !important;
flex-direction: column !important;
grid-template-columns: unset !important;
}
.panel {
padding: 4px !important;
margin-bottom: 2px !important;
border-radius: 3px !important;
}
.panel-header {
font-size: 10px !important;
padding: 3px 6px !important;
}
/* Prevent horizontal overflow */
body {
overflow-x: hidden;
}
}
/* Phone portrait (under 480px) */
@media (max-width: 480px) {
/* Extra compact for phones */
.panel {
padding: 3px !important;
font-size: 11px !important;
}
.panel-header {
font-size: 9px !important;
}
/* Reduce font sizes globally for very small screens */
body {
font-size: 12px;
}
}
/* Short screens (Pi 7" touchscreen at 480px height) */
@media (max-height: 520px) {
.panel {
padding: 3px !important;
}
.panel-header {
padding: 2px 4px !important;
font-size: 10px !important;
}
}
/* Touch device improvements */
@media (pointer: coarse) {
/* Larger tap targets for touchscreens */
button {
min-height: 36px;
min-width: 36px;
}
/* Prevent text selection on tap */
.panel-header {
user-select: none;
-webkit-user-select: none;
}
/* Scrollbar styling for touch */
::-webkit-scrollbar {
width: 4px;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.15);
border-radius: 2px;
}
}

Loading…
Cancel
Save

Powered by TurnKey Linux.