/* Vome — brand-landing hero board.
 *
 * The animated SVG that opens vome.io.  Same family as the
 * /how-it-works exhibits (glowing wires, marching packets, a "brain"
 * chip that shows who is actually running Home Assistant) but styled
 * to be looked at rather than operated: softer, bigger, ambient, and
 * driven by three square tabs across its head instead of a switch
 * panel.  The tabs are also the carousel's position indicator.
 *
 * The whole board is a state machine expressed in CSS.  The <svg>
 * carries exactly one of ``mode-hosted`` / ``mode-linked`` /
 * ``mode-standby`` (plus ``is-failed`` during the handover demo);
 * every rule below keys off that, so static/js/vome_hero.js only ever
 * swaps a class name and a caption.
 *
 * Theme tokens come from vomehome.css.
 */

/* ── Stage ─────────────────────────────────────────────────────── */
.vh-stage {
	max-width: 1000px;
	margin: 1.75rem auto 0;
}

.vh-board {
	position: relative;
	overflow: hidden;
	border: 1px solid var(--border);
	border-radius: 22px;
	padding: 0.5rem 0.75rem 0.25rem;
	background:
		radial-gradient(620px 300px at 22% 12%, rgba(255, 152, 0, 0.07), transparent 62%),
		radial-gradient(700px 340px at 82% 78%, rgba(16, 185, 129, 0.08), transparent 60%),
		#0a0c11;
	box-shadow: 0 24px 60px -30px rgba(0, 0, 0, 0.9);
}

/* A very slow aurora drifting behind the diagram — the "arty" layer.
 * Pointer-events off so the touchable SVG bits stay touchable. */
.vh-board::before {
	content: "";
	position: absolute;
	inset: -30%;
	pointer-events: none;
	background:
		radial-gradient(closest-side, rgba(255, 152, 0, 0.16), transparent 70%) 18% 30% / 55% 62% no-repeat,
		radial-gradient(closest-side, rgba(16, 185, 129, 0.17), transparent 70%) 78% 66% / 60% 66% no-repeat;
	filter: blur(28px);
	opacity: 0.55;
	animation: vhAurora 26s ease-in-out infinite alternate;
}
@keyframes vhAurora {
	from { transform: translate3d(-2.5%, -1.5%, 0) scale(1); }
	to   { transform: translate3d(3%, 2.5%, 0) scale(1.09); }
}

.vh-svg {
	position: relative;
	display: block;
	width: 100%;
	height: auto;
}

/* ── Static furniture ──────────────────────────────────────────── */
.vh-shadow { fill: rgba(0, 0, 0, 0.5); filter: blur(9px); }
.vh-aura { opacity: 0.75; }

.vh-house {
	fill: rgba(16, 18, 24, 0.72);
	stroke: var(--border-light);
	stroke-width: 1.6;
	stroke-linejoin: round;
}
.vh-hex {
	fill: rgba(11, 20, 20, 0.78);
	stroke: rgba(16, 185, 129, 0.42);
	stroke-width: 1.8;
	stroke-linejoin: round;
}

.vh-node rect { fill: var(--bg-tertiary); stroke: var(--border-light); stroke-width: 1.4; }
.vh-node .vh-screen { fill: #0a0c11; stroke: rgba(255, 152, 0, 0.3); }

.vh-label { fill: var(--text-primary); font-size: 13.5px; font-weight: 650; }
.vh-sub { fill: var(--text-muted); font-size: 11px; }
.vh-place {
	fill: var(--text-muted);
	font-size: 11.5px;
	font-weight: 700;
	letter-spacing: 0.13em;
	text-transform: uppercase;
}
.vh-mark {
	fill: rgba(16, 185, 129, 0.75);
	font-size: 10.5px;
	font-weight: 700;
	letter-spacing: 0.14em;
	text-transform: uppercase;
}

/* Bulb — the one thing on the board everybody recognises. */
.vh-cord { fill: none; stroke: var(--border-light); stroke-width: 1.4; }
.vh-bulb-glass { fill: rgba(255, 183, 77, 0.16); stroke: rgba(255, 183, 77, 0.75); stroke-width: 1.6; }
.vh-bulb-filament { fill: none; stroke: var(--secondary); stroke-width: 1.8; stroke-linecap: round; }
.vh-bulb-base { fill: var(--bg-tertiary); stroke: var(--border-light); stroke-width: 1.2; }
.vh-bulb-halo {
	fill: var(--secondary);
	opacity: 0.13;
	transform-box: fill-box;
	transform-origin: center;
	animation: vhBreathe 4.5s ease-in-out infinite;
}
@keyframes vhBreathe {
	0%, 100% { transform: scale(0.9); opacity: 0.1; }
	50%      { transform: scale(1.25); opacity: 0.22; }
}

/* ── Wires: a faint rail plus a marching dash for live traffic ─── */
.vh-rail {
	fill: none;
	stroke: var(--border-light);
	stroke-width: 1.6;
	opacity: 0.65;
}
.vh-flow {
	fill: none;
	stroke: var(--primary);
	stroke-width: 2.6;
	stroke-linecap: round;
	stroke-dasharray: 2 20;
	opacity: 0;
	filter: url(#vh-glow);
	transition: opacity 0.5s ease;
	animation: vhMarch 1.9s linear infinite;
}
.vh-flow.vh-flow-lan { stroke: var(--accent-bright); }
/* The agent's wire is the same relay as everything else, drawn in the
   assistant's colour so the board says "and this too" rather than
   "and this, somehow differently". */
.vh-flow.vh-flow-agent {
	stroke: var(--secondary, #f59e0b);
	stroke-dasharray: 3 14;
	animation-duration: 1.5s;
}
.vh-flow.vh-flow-backup {
	stroke: var(--accent);
	stroke-dasharray: 9 16;
	stroke-width: 2.2;
	animation-duration: 3.4s;
}
@keyframes vhMarch {
	from { stroke-dashoffset: 44; }
	to   { stroke-dashoffset: 0; }
}

/* ── Brain chip: who is actually running Home Assistant ────────── */
.vh-brain { opacity: 0; transition: opacity 0.45s ease; }
.vh-brain rect { fill: var(--accent); stroke: none; }
.vh-brain text {
	fill: #05231a;
	font-size: 9.5px;
	font-weight: 800;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}
/* The halo starts on the node's own outline and ripples outward, so it
   never sweeps across the label inside. */
.vh-halo {
	fill: none;
	stroke: var(--accent);
	stroke-width: 1.5;
	transform-box: fill-box;
	transform-origin: center;
	animation: vhPulse 2.8s ease-out infinite;
}
@keyframes vhPulse {
	0%   { transform: scale(1); opacity: 0.4; }
	100% { transform: scale(1.45); opacity: 0; }
}

/* ── Swappable interiors ───────────────────────────────────────── */
.vh-swap { opacity: 0; transition: opacity 0.45s ease; pointer-events: none; }
.vh-swap.is-on { opacity: 1; pointer-events: auto; }

.vh-chip rect { fill: rgba(16, 185, 129, 0.12); stroke: rgba(16, 185, 129, 0.5); stroke-width: 1.3; }
.vh-chip text { fill: var(--text-primary); font-size: 12px; font-weight: 600; }
.vh-chip.is-ghost rect { fill: none; stroke: var(--border-light); stroke-dasharray: 4 4; }
.vh-chip.is-ghost text { fill: var(--text-muted); }

.vh-door { fill: rgba(255, 152, 0, 0.09); stroke: rgba(255, 152, 0, 0.55); stroke-width: 1.6; }
.vh-door-knob { fill: var(--secondary); }
.vh-vault rect { fill: var(--bg-tertiary); stroke: var(--border-light); stroke-width: 1.4; }
.vh-vault .vh-dial { fill: none; stroke: var(--text-muted); stroke-width: 1.6; }

/* Small pills that annotate a wire or a box.  The opaque fill is doing
   work: a tag sitting on the long wire masks the rail behind it, so it
   reads as a label *on* the connection rather than a floating caption. */
.vh-tag rect {
	fill: #0a0c11;
	stroke: var(--border-light);
	stroke-width: 1.1;
}
.vh-tag text {
	fill: var(--text-secondary);
	font-size: 10px;
	font-weight: 600;
	letter-spacing: 0.03em;
}
/* Dashed and dimmed = "you might not need this one".  The Pi bridge and
   the tunnel home are both genuinely optional when we host — plenty of
   homes are all cloud/Wi-Fi devices — and the board would be lying if
   it drew them the same weight as the parts that are always there. */
.vh-tag.vh-optional rect { stroke: var(--border-light); stroke-dasharray: 4 3; }
.vh-tag.vh-optional text { fill: var(--text-muted); }
/* …and the box the optional tag belongs to loses its solid outline too. */
.mode-hosted #vh-pi-node > rect { stroke-dasharray: 5 4; }
/* Once the standby has taken over there are no backups running to it. */
.is-failed #vh-wire-standby { opacity: 0; }

.vh-wordmark {
	fill: var(--accent-bright);
	font-size: 11px;
	font-weight: 800;
	letter-spacing: 0.22em;
}

/* Anything that dies during the handover demo. */
.vh-dieable { transition: opacity 0.6s ease, filter 0.6s ease; }
.is-failed .vh-dieable { opacity: 0.22; filter: saturate(0); }

/* ── The agent ─────────────────────────────────────────────────── */
/* A chip with a face: it reaches the same door the phone does, so it is
   drawn to the same weight and sits on the same rail. */
.vh-agent rect { fill: rgba(245, 158, 11, 0.10); stroke: var(--secondary, #f59e0b); }
.vh-agent-eye { fill: var(--secondary, #f59e0b); stroke: none; }
.vh-agent-mouth,
.vh-agent-pin {
	fill: none;
	stroke: var(--secondary, #f59e0b);
	stroke-width: 2;
	stroke-linecap: round;
}
.vh-agent-eye { animation: vhBlink 5.5s ease-in-out infinite; }
@keyframes vhBlink {
	0%, 92%, 100% { transform: scaleY(1); }
	95%           { transform: scaleY(0.12); }
}
.vh-agent-eye {
	transform-box: fill-box;
	transform-origin: center;
}

/* ── Moving packets (static/js/exhibits/flow_animator.js) ───────── */
/* The dashed wires say a route exists; the dots say something is going
   along it right now.  Same animator the /how-it-works exhibits use, so
   the two boards move in the same language. */
.flow-dot {
	pointer-events: none;
	filter: url(#vh-glow);
}
.flow-dot.tone-ok { fill: var(--primary); }
.flow-dot.tone-agent { fill: var(--secondary, #f59e0b); }
.flow-dot.tone-lan { fill: var(--accent-bright); }

/* ── Which flows are live in which mode ────────────────────────── */
.mode-hosted #vh-f-home,
.mode-hosted #vh-f-you,
.mode-hosted #vh-f-agent,
.mode-hosted #vh-f-lan { opacity: 1; }

.mode-linked #vh-f-home,
.mode-linked #vh-f-you,
.mode-linked #vh-f-agent,
.mode-linked #vh-f-lan { opacity: 1; }
/* Linked mode is a visitor arriving: traffic runs hub → home. */
.mode-linked #vh-f-home { animation-direction: reverse; }

.mode-standby #vh-f-backup,
.mode-standby #vh-f-agent,
.mode-standby #vh-f-lan { opacity: 1; }
.mode-standby.is-failed #vh-f-backup { opacity: 0; }
.mode-standby.is-failed #vh-f-home,
.mode-standby.is-failed #vh-f-you { opacity: 1; }
.mode-standby.is-failed #vh-f-lan { opacity: 0; }
/* After a takeover the standby is driving the house, not reporting to
   it — so the traffic on that wire turns around. */
.mode-standby.is-failed #vh-f-home { animation-direction: reverse; }

/* ── Where the brain sits ──────────────────────────────────────── */
.mode-hosted #vh-brain-hub { opacity: 1; }
.mode-linked #vh-brain-pi { opacity: 1; }
.mode-standby #vh-brain-pi { opacity: 1; }
.mode-standby.is-failed #vh-brain-pi { opacity: 0; }
.mode-standby.is-failed #vh-brain-hub { opacity: 1; }

/* ── Tabs across the head of the board ─────────────────────────── */
/* Square on purpose — they read as three panels of one instrument,
   not as browser tabs.  Equal columns so they span the full width. */
.vh-tabs {
	position: relative;
	z-index: 2;
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
	margin: -0.5rem -0.75rem 0;
	border-bottom: 1px solid var(--border);
}
.vh-tab {
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 0.15rem;
	min-height: 3.6rem;
	padding: 0.65rem 0.9rem;
	border: none;
	border-right: 1px solid var(--border);
	background: rgba(255, 255, 255, 0.012);
	color: var(--text-muted);
	text-align: center;
	cursor: pointer;
	transition: background 0.2s ease, color 0.2s ease;
}
.vh-tab:last-child { border-right: none; }
.vh-tab:hover { background: rgba(255, 255, 255, 0.045); color: var(--text-secondary); }

.vh-tab-lead {
	font-size: 0.95rem;
	font-weight: 700;
	line-height: 1.2;
	color: inherit;
}
.vh-tab-sub {
	font-size: 0.78rem;
	font-weight: 500;
	line-height: 1.25;
	color: var(--text-muted);
	opacity: 0.85;
}

.vh-tab[aria-selected="true"] {
	background: rgba(255, 152, 0, 0.07);
	color: var(--text-primary);
}
.vh-tab[aria-selected="true"] .vh-tab-sub { color: var(--secondary); opacity: 1; }
/* The lit edge is the only "tab" cue — no shoulders, no notch. */
.vh-tab[aria-selected="true"]::after {
	content: "";
	position: absolute;
	left: 0;
	right: 0;
	bottom: -1px;
	height: 2px;
	background: linear-gradient(90deg, var(--primary), var(--secondary));
}

/* ── Carousel controls, on the glass ───────────────────────────── */
.vh-arrow {
	position: absolute;
	top: 34%;
	z-index: 2;
	width: 2.6rem;
	height: 2.6rem;
	display: flex;
	align-items: center;
	justify-content: center;
	border: 1px solid var(--border-light);
	border-radius: 50%;
	background: rgba(10, 12, 17, 0.72);
	backdrop-filter: blur(6px);
	color: var(--text-secondary);
	font-size: 1.15rem;
	cursor: pointer;
	transition: var(--transition);
}
.vh-arrow:hover {
	border-color: var(--primary);
	color: var(--primary);
	background: rgba(10, 12, 17, 0.92);
}
.vh-arrow-prev { left: 0.75rem; }
.vh-arrow-next { right: 0.75rem; }

/* The readout panel sits across the foot of the board so the controls
   read as part of the exhibit rather than a toolbar beneath it. */
.vh-panel {
	position: relative;
	z-index: 1;
	margin: -0.25rem 0.25rem 0.25rem;
	padding: 1.1rem 1.35rem 1.25rem;
	border-top: 1px solid var(--border);
	background: linear-gradient(180deg, rgba(10, 12, 17, 0), rgba(10, 12, 17, 0.55) 40%);
	text-align: center;
}

.vh-caption {
	max-width: 620px;
	margin: 0 auto;
	min-height: 3.4rem;
	color: var(--text-secondary);
	font-size: 0.98rem;
	line-height: 1.55;
}
.vh-caption strong { color: var(--text-primary); font-weight: 650; }

.vh-cta-row {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: 0.6rem 1.1rem;
	margin-top: 0.9rem;
}
.vh-cta { padding: 0.62rem 1.35rem; }
.vh-cta-alt {
	color: var(--text-secondary);
	text-decoration: none;
	font-size: 0.92rem;
	font-weight: 650;
}
.vh-cta-alt:hover { color: var(--primary); }
.vh-poke {
	background: none;
	border: none;
	padding: 0;
	color: var(--primary);
	font-size: 0.92rem;
	font-weight: 650;
	cursor: pointer;
	white-space: nowrap;
	border-bottom: 1px dashed rgba(255, 152, 0, 0.5);
}
.vh-poke:hover { color: var(--secondary); }
.vh-poke[hidden] { display: none; }

/* ── Small screens: the board stays legible, the arrows tuck in ── */
@media (max-width: 640px) {
	.vh-board { border-radius: 16px; padding: 0.35rem; }
	.vh-arrow { width: 2.1rem; height: 2.1rem; font-size: 0.95rem; top: 30%; }
	.vh-arrow-prev { left: 0.3rem; }
	.vh-arrow-next { right: 0.3rem; }
	.vh-panel { padding: 0.9rem 0.75rem 1rem; }
	.vh-caption { font-size: 0.9rem; min-height: 4.6rem; }
	/* Three tabs across a phone leaves no room for the sub-line; the
	   lead alone still says which mode you are on. */
	.vh-tabs { margin: -0.35rem -0.35rem 0; }
	.vh-tab { min-height: 2.9rem; padding: 0.5rem 0.35rem; }
	.vh-tab-lead { font-size: 0.78rem; }
	.vh-tab-sub { display: none; }
}

/* ── Reduced motion: keep the picture, drop the movement ───────── */
@media (prefers-reduced-motion: reduce) {
	.vh-board::before { animation: none; }
	.vh-flow {
		animation: none;
		stroke-dasharray: none;
		stroke-width: 2;
		opacity: 0;
	}
	/* A ripple frozen mid-flight is just a hard ring across the board —
	   the chip already says who is in charge, so drop it entirely. */
	.vh-halo { display: none; }
	.vh-bulb-halo { animation: none; opacity: 0.16; }
	.vh-agent-eye { animation: none; }
	/* The animator draws no dots under reduced motion; this is belt and
	   braces for anything already on the board when the setting flips. */
	.flow-dot { display: none; }
}
