/*
	Boat Weather Dashboard — dashboard.css

	Day theme:
		near-white paper, near-black ink, built for direct sunlight.

	Dark theme:
		reduced luminance with neutral map.

	Night theme:
		black paper, desaturated amber-red ink, preserves night vision.

	Radar:
		the geographic base is deliberately subdued.
		Radar imagery remains geographically fixed and is never cropped.
		The map slot's height is set by dashboard.js from the map bounds.
*/


:root
{
	--paper: #f7f6f2;
	--ink: #16181c;
	--dim: #70747c;
	--line: #d9d7d0;
	--warn: #b33a1e;

	--map-water: #dfe8ec;
}


body.dark
{
	--paper: #16181c;
	--ink: #e8e6df;
	--dim: #8a8f98;
	--line: #2b2e34;
	--warn: #ff7a55;

	--map-water: #22282d;
}


body.night
{
	--paper: #000000;
	--ink: #d24a32;
	--dim: #7a3524;
	--line: #351a12;
	--warn: #ff6a45;

	--map-water: #090000;
}


*
{
	box-sizing: border-box;
	margin: 0;
	padding: 0;

	-webkit-user-select: none;
	user-select: none;
}


html,
body
{
	height: 100%;
}


body
{
	background: var( --paper );
	color: var( --ink );

	font-family: -apple-system, system-ui, sans-serif;
	font-variant-numeric: tabular-nums;

	display: flex;
	flex-direction: column;

	padding:
		env( safe-area-inset-top )
		env( safe-area-inset-right )
		env( safe-area-inset-bottom )
		env( safe-area-inset-left );

	transition:
		background 0.6s,
		color 0.6s;
}


/* ------------------------------------------------------------- top bar */


#top_bar
{
	display: flex;
	align-items: baseline;

	gap: 1rem;

	padding: 0.6rem 1.2rem 0.4rem;

	font-size: 0.95rem;
	color: var( --dim );
}


#alert_dot
{
	color: var( --warn );
	font-size: 1.2rem;
}


#data_age
{
	margin-left: auto;
}


#data_age.stale
{
	color: var( --warn );
	font-weight: 600;
}


#theme_select
{
	background: var( --paper );

	border: 1px solid var( --line );
	border-radius: 0.5rem;

	color: var( --dim );

	font: inherit;

	padding: 0.15rem 0.5rem;
}


/* ----------------------------------------------------------- tile grid */


#tile_grid
{
	flex: 1;

	display: grid;

	gap: 2px;

	background: var( --line );

	grid-template-columns:
		minmax( 0, 2fr )
		minmax( 14rem, 1fr );

	grid-template-rows:
		repeat( 4, minmax( 0, 1fr ) )
		auto;

	grid-auto-flow: row;

	min-height: 0;
}


.tile
{
	background: var( --paper );

	position: relative;

	display: flex;
	flex-direction: column;

	align-items: center;
	justify-content: center;

	gap: 0.3rem;

	padding: 1rem;

	overflow: hidden;

	min-width: 0;
	min-height: 0;

	transition: background 0.6s;
}


.tile.hero
{
	grid-column: 1;
	grid-row: 1 / span 4;
}


.tile h2
{
	font-size: 0.9rem;
	font-weight: 600;

	text-transform: uppercase;
	letter-spacing: 0.12em;

	color: var( --dim );

	margin-bottom: 2px;
}


/* ------------------------------------------------------------ readings */


.reading .value
{
	font-size: 3.4rem;
	font-weight: 700;

	line-height: 1;
}


.tile.hero .reading .value
{
	font-size: 6.5rem;
}


.reading .unit
{
	font-size: 1.3rem;

	color: var( --dim );

	margin-left: 0.3rem;
}


.reading .forecast
{
	font-size: 1.4rem;

	color: var( --dim );

	margin-left: 0.5rem;
}


.tile.hero .reading .forecast
{
	font-size: 2.2rem;
}


.detail
{
	color: var( --dim );

	font-size: 1rem;
}


.trend
{
	font-size: 1.15rem;

	color: var( --dim );
}


.tile.hero .trend
{
	font-size: 1.6rem;

	color: var( --ink );
}


.value.dimmed,
.reading .value.dimmed
{
	opacity: 0.35;
}


/* ------------------------------------------------------------- compass */


#compass
{
	display: none;

	width: min( 42vh, 34vw );

	aspect-ratio: 1;

	padding-bottom: 3px;
}


.tile.hero #compass
{
	display: block;
}


.cardinal
{
	font-size: 15px;
	font-weight: 600;

	fill: currentColor;

	text-anchor: middle;
	dominant-baseline: middle;

	opacity: 0.7;
}


#wind_arrow
{
	transition: transform 1s ease;
}


#wind_compass_point
{
	font-size: 1.6rem;
	font-weight: 600;

	margin-right: 0.4rem;
}


.tile.hero #wind_compass_point
{
	font-size: 2.4rem;
}


/* --------------------------------------------------------------- radar */


.radar-tile
{
	padding: 0.65rem;

	gap: 0.45rem;

	align-items: stretch;
	justify-content: flex-start;
}


/*
	In landscape the hero column is taller than the map needs,
	so centre the heading + map + timeline stack vertically.
*/

.radar-tile.hero
{
	justify-content: center;
}


.radar-heading
{
	width: 100%;

	display: flex;

	align-items: baseline;
	justify-content: space-between;

	gap: 1rem;

	padding: 0 0.25rem;
}


.radar-heading h2
{
	margin: 0;
}


#radar_status
{
	font-size: 0.8rem;

	color: var( --dim );

	white-space: nowrap;
}


/* ---------------------------------------------------------- weather map */


/*
	Height is written by fit_weather_map() so that the slot always
	matches the Web Mercator aspect ratio of the map bounds.
*/

#weather_map_slot
{
	flex: none;

	width: 100%;
}


#weather_map
{
	position: relative;

	overflow: hidden;

	background: var( --map-water );

	border: 1px solid var( --line );
}


/*
	Every geographic layer occupies exactly the same rectangle.

	The radar images are generated for these map bounds, so nothing
	here should independently crop, zoom or preserve image aspect ratio.
*/


#map_base,
#radar_frames,
#lightning_canvas
{
	position: absolute;

	inset: 0;

	width: 100%;
	height: 100%;
}


/* ------------------------------------------------------------ basemap */


#map_base
{
	overflow: hidden;

	z-index: 1;

	/*
		The OSM map becomes a quiet geographic reference rather than
		the dominant visual element.
	*/

	filter:
		grayscale( 1 )
		saturate( 0 )
		contrast( 0.58 )
		brightness( 1.17 );

	opacity: 0.54;
}


.map-tile
{
	position: absolute;

	max-width: none;

	pointer-events: none;

	/*
		The JS calculates exact tile dimensions and positions.
		Do not use object-fit or CSS transforms here.
	*/
}


/* -------------------------------------------------------------- radar */


#radar_frames
{
	z-index: 2;

	pointer-events: none;
}


.radar-frame
{
	position: absolute;

	inset: 0;

	display: block;

	width: 100%;
	height: 100%;

	object-fit: fill;

	opacity: 0;

	filter:
		saturate( 1.5 )
		contrast( 1.2 );

	pointer-events: none;

	transition: opacity 0.12s linear;
}


.radar-frame.active
{
	opacity: 1;
}


/* ---------------------------------------------------------- lightning */


#lightning_canvas
{
	z-index: 3;

	pointer-events: none;
}


/* -------------------------------------------------------- attribution */


.map-attribution
{
	position: absolute;

	left: 0.25rem;
	bottom: 0.2rem;

	z-index: 5;

	font-size: 0.62rem;
	line-height: 1;

	color: rgba( 0, 0, 0, 0.52 );

	background: rgba( 255, 255, 255, 0.7 );

	padding: 0.18rem 0.26rem;
}


/* --------------------------------------------------------- dark map */


body.dark #weather_map
{
	background: #171d20;
}


body.dark #map_base
{
	filter:
		grayscale( 1 )
		saturate( 0 )
		brightness( 0.48 )
		contrast( 0.65 );

	opacity: 0.5;
}


body.dark .radar-frame
{
	filter:
		saturate( 1.6 )
		contrast( 1.25 )
		brightness( 1.05 );
}


body.dark .map-attribution
{
	color: rgba( 255, 255, 255, 0.46 );

	background: rgba( 0, 0, 0, 0.6 );
}


/* -------------------------------------------------------- night map */


body.night #weather_map
{
	background: #050000;
}


body.night #map_base
{
	filter:
		grayscale( 1 )
		sepia( 1 )
		saturate( 5 )
		hue-rotate( 320deg )
		brightness( 0.3 )
		contrast( 0.85 );

	opacity: 0.4;
}


body.night .radar-frame
{
	filter:
		grayscale( 1 )
		sepia( 1 )
		saturate( 6 )
		hue-rotate( 320deg )
		brightness( 0.68 )
		contrast( 1.35 );
}


body.night .map-attribution
{
	color: var( --dim );

	background: rgba( 0, 0, 0, 0.72 );
}


/* ------------------------------------------------------ radar timeline */


#radar_timeline
{
	flex: 0 0 auto;

	width: 100%;

	display: flex;

	justify-content: space-between;

	gap: 0.25rem;
}


.radar-time-button
{
	flex: 1;

	border: 0;
	border-top: 3px solid var( --line );

	background: transparent;

	color: var( --dim );

	font: inherit;
	font-size: 0.78rem;

	padding: 0.28rem 0 0;

	cursor: pointer;
}


.radar-time-button.active
{
	border-top-color: var( --ink );

	color: var( --ink );

	font-weight: 650;
}


body.night .radar-time-button.active
{
	border-top-color: var( --warn );

	color: var( --warn );
}


/* ------------------------------------------------------- radar summary */


.radar-summary
{
	flex: 0 0 auto;

	width: 100%;

	display: flex;

	justify-content: space-between;

	gap: 0.7rem;

	font-size: 0.9rem;

	color: var( --dim );

	white-space: nowrap;
}


/* ------------------------------------------------------ compact radar */


.radar-tile:not(.hero) .radar-heading
{
	position: absolute;

	top: 0.75rem;
	left: 0.8rem;
	right: 2.8rem;

	z-index: 6;

	width: auto;

	text-shadow:
		0 1px 2px var( --paper );
}


.radar-tile:not(.hero) #radar_status,
.radar-tile:not(.hero) #radar_timeline,
.radar-tile:not(.hero) #radar_rain,
.radar-tile:not(.hero) #lightning_count,
.radar-tile:not(.hero) .map-attribution
{
	display: none;
}


/*
	Compact mode: the slot fills the tile and fit_weather_map()
	sizes the map to fit inside it, centred, geography intact.
*/

.radar-tile:not(.hero) #weather_map_slot
{
	position: absolute;

	inset: 0;

	width: auto;
	height: auto;

	display: flex;
	align-items: center;
	justify-content: center;
}


.radar-tile:not(.hero) #weather_map
{
	border: 0;
}


.radar-tile:not(.hero) .radar-summary
{
	position: absolute;

	left: 0.8rem;
	bottom: 0.65rem;

	z-index: 6;

	width: auto;

	color: var( --ink );

	font-weight: 650;

	text-shadow:
		0 1px 2px var( --paper );
}


/* ------------------------------------------------------------- promote */


.promote
{
	position: absolute;

	top: 0.5rem;
	right: 0.6rem;

	z-index: 10;

	background: none;

	border: none;

	color: var( --dim );

	font-size: 1.5rem;

	padding: 0.4rem;

	cursor: pointer;
}


.tile.hero .promote
{
	display: none;
}


/* ------------------------------------------------------------- sun bar */


#sun_bar
{
	grid-column: 1 / -1;

	background: var( --paper );

	display: flex;

	justify-content: space-between;

	padding: 0.8rem 1.4rem;

	font-size: 1.25rem;

	transition: background 0.6s;
}


#sun_secondary
{
	color: var( --dim );
}


/* -------------------------------------------------------------- portrait */


@media ( orientation: portrait )
{
	#tile_grid
	{
		grid-template-columns:
			1fr
			1fr;

		grid-template-rows:
			minmax( 0, 5fr )
			minmax( 0, 2.5fr )
			minmax( 0, 2.5fr )
			auto;
	}


	/*
		When the radar is the hero, its row shrinks to the 2:1 map
		and the four small tiles share whatever is left.
	*/

	#tile_grid:has( .radar-tile.hero )
	{
		grid-template-rows:
			auto
			minmax( 0, 1fr )
			minmax( 0, 1fr )
			auto;
	}


	.tile.hero
	{
		grid-column: 1 / -1;
		grid-row: 1;
	}


	#compass
	{
		width: min( 30vh, 50vw );
	}
}


/* --------------------------------------------------------- small screens */


@media ( max-width: 700px )
{
	.reading .value
	{
		font-size: 2.5rem;
	}


	.tile.hero .reading .value
	{
		font-size: 5rem;
	}


	.radar-summary
	{
		font-size: 0.78rem;
	}
}


/* ---------------------------------------------------- reduced motion */


@media ( prefers-reduced-motion: reduce )
{
	body,
	.tile,
	#sun_bar,
	#wind_arrow,
	.radar-frame
	{
		transition: none;
	}
}
