<!--
  Dashboard daemon panel. Renders detailed runtime info for the Docker engine
  and the configured proxy provider (NPM or Traefik). Subscribes to the
  shared health store so there is no extra network traffic beyond the
  single /api/health poll already running for the sidebar chips.

  Aesthetic: control-room / forge — two terminal-styled panels side by side,
  with key/value rows, a container-state bar graph, and registration marks
  that reveal on hover. Dimensions are generous but everything is rendered
  in mono to reinforce the "instrumentation" feel.
-->
<script lang="ts">
	import { health, refreshHealth } from '$lib/stores/health';
	import { IconRefresh, IconContainer, IconServer, IconShield, IconWifi } from '$lib/components/icons';
	import { t } from '$lib/i18n';

	const docker = $derived($health.docker);
	const proxy = $derived($health.proxy);
	const checked = $derived($health.checked);

	const dockerConnected = $derived(docker?.connected ?? false);
	const proxyConnected = $derived(proxy?.connected ?? false);
	const proxyProvider = $derived(proxy?.provider ?? 'none');

	const totalContainers = $derived(
		(docker?.running ?? 0) + (docker?.paused ?? 0) + (docker?.stopped ?? 0)
	);

	const runningPct = $derived(
		totalContainers > 0 ? ((docker?.running ?? 0) / totalContainers) * 100 : 0
	);
	const pausedPct = $derived(
		totalContainers > 0 ? ((docker?.paused ?? 0) / totalContainers) * 100 : 0
	);
	const stoppedPct = $derived(
		totalContainers > 0 ? ((docker?.stopped ?? 0) / totalContainers) * 100 : 0
	);

	import { formatBytes as formatBytesShared } from '$lib/format/bytes';

	function formatBytes(n: number | undefined): string {
		if (!n || n <= 0) return '—';
		return formatBytesShared(n);
	}

	function formatMs(n: number | undefined): string {
		if (typeof n !== 'number') return '—';
		return `${n} ms`;
	}

	let refreshing = $state(false);
	async function onRefresh(): Promise<void> {
		if (refreshing) return;
		refreshing = true;
		try {
			await refreshHealth();
		} finally {
			refreshing = false;
		}
	}
</script>

<section class="daemons">
	<header class="daemons-head">
		<div>
			<span class="eyebrow">SYSTEMS // DAEMONS</span>
			<h2 class="daemons-title">{$t('daemons.title')}<span class="accent">.</span></h2>
		</div>
		<button class="refresh-btn" type="button" onclick={onRefresh} disabled={refreshing} title={$t('daemons.refresh')}>
			<span class:spin={refreshing} class="refresh-icon"><IconRefresh size={14} /></span>
			<span>{refreshing ? $t('daemons.refreshing') : $t('daemons.refresh')}</span>
		</button>
	</header>

	<div class="daemons-grid">
		<!-- ═══════════ DOCKER PANEL ═══════════ -->
		<article class="panel" class:panel-down={checked && !dockerConnected}>
			<div class="panel-head">
				<div class="panel-title">
					<IconContainer size={15} />
					<span>{$t('daemons.docker')}</span>
				</div>
				<span class="status-pill" class:live={dockerConnected} class:down={!dockerConnected}>
					<span class="status-dot"></span>
					{dockerConnected ? $t('daemons.online') : $t('daemons.offline')}
				</span>
			</div>

			{#if !checked}
				<div class="panel-skeleton">
					<div class="skel-bar"></div>
					<div class="skel-bar skel-bar-narrow"></div>
					<div class="skel-bar"></div>
				</div>
			{:else if !dockerConnected}
				<div class="panel-error">
					<code>{docker?.error ?? $t('daemons.dockerNotReachable')}</code>
					<p>{$t('daemons.dockerHint')}</p>
				</div>
			{:else}
				<!-- Container state breakdown — stacked bar -->
				<div class="state-block">
					<div class="state-head">
						<span class="state-caption">{$t('daemons.containers')}</span>
						<span class="state-total">{totalContainers}</span>
					</div>
					{#if totalContainers > 0}
						<div class="state-bar" aria-hidden="true">
							<span class="seg seg-run" style="width: {runningPct}%"></span>
							<span class="seg seg-pause" style="width: {pausedPct}%"></span>
							<span class="seg seg-stop" style="width: {stoppedPct}%"></span>
						</div>
					{:else}
						<div class="state-bar empty" aria-hidden="true"></div>
					{/if}
					<div class="state-legend">
						<span class="leg"><i class="ld ld-run"></i>{$t('daemons.running')} <b>{docker?.running ?? 0}</b></span>
						<span class="leg"><i class="ld ld-pause"></i>{$t('daemons.paused')} <b>{docker?.paused ?? 0}</b></span>
						<span class="leg"><i class="ld ld-stop"></i>{$t('daemons.stopped')} <b>{docker?.stopped ?? 0}</b></span>
					</div>
				</div>

				<!-- Key/value grid -->
				<dl class="kv">
					<div>
						<dt>{$t('daemons.version')}</dt>
						<dd>{docker?.version ?? '—'}</dd>
					</div>
					<div>
						<dt>{$t('daemons.apiVersion')}</dt>
						<dd>{docker?.api_version ?? '—'}</dd>
					</div>
					<div>
						<dt>{$t('daemons.platform')}</dt>
						<dd>{docker?.os ?? '—'}{docker?.arch ? ` · ${docker.arch}` : ''}</dd>
					</div>
					<div>
						<dt>{$t('daemons.kernel')}</dt>
						<dd class="truncate" title={docker?.kernel ?? ''}>{docker?.kernel ?? '—'}</dd>
					</div>
					<div>
						<dt>{$t('daemons.cpu')}</dt>
						<dd>{docker?.ncpu ? `${docker.ncpu} cores` : '—'}</dd>
					</div>
					<div>
						<dt>{$t('daemons.memory')}</dt>
						<dd>{formatBytes(docker?.memory_total)}</dd>
					</div>
					<div>
						<dt>{$t('daemons.storage')}</dt>
						<dd>{docker?.storage_driver ?? '—'}</dd>
					</div>
					<div>
						<dt>{$t('daemons.images')}</dt>
						<dd>{docker?.images ?? 0}</dd>
					</div>
					<div>
						<dt>{$t('daemons.latency')}</dt>
						<dd>{formatMs(docker?.latency_ms)}</dd>
					</div>
					<div class="kv-wide">
						<dt>{$t('daemons.rootDir')}</dt>
						<dd class="truncate" title={docker?.root_dir ?? ''}>{docker?.root_dir ?? '—'}</dd>
					</div>
				</dl>
			{/if}
		</article>

		<!-- ═══════════ PROXY PANEL ═══════════ -->
		<article class="panel" class:panel-down={checked && !proxyConnected && proxyProvider !== 'none'}>
			<div class="panel-head">
				<div class="panel-title">
					{#if proxyProvider === 'npm'}
						<IconShield size={15} />
					{:else}
						<IconWifi size={15} />
					{/if}
					<span>
						{proxyProvider === 'npm'
							? $t('daemons.npm')
							: proxyProvider === 'traefik'
							? $t('daemons.traefik')
							: $t('daemons.proxy')}
					</span>
				</div>
				{#if proxyProvider === 'none' || !proxy}
					<span class="status-pill idle">
						<span class="status-dot"></span>
						{$t('daemons.notConfigured')}
					</span>
				{:else}
					<span class="status-pill" class:live={proxyConnected} class:down={!proxyConnected}>
						<span class="status-dot"></span>
						{proxyConnected ? $t('daemons.online') : $t('daemons.offline')}
					</span>
				{/if}
			</div>

			{#if !checked}
				<div class="panel-skeleton">
					<div class="skel-bar"></div>
					<div class="skel-bar skel-bar-narrow"></div>
					<div class="skel-bar"></div>
				</div>
			{:else if proxyProvider === 'none' || !proxy}
				<div class="panel-empty">
					<IconServer size={20} />
					<p>{$t('daemons.noProxyDesc')}</p>
					<a href="/settings" class="inline-link">{$t('daemons.configureProxy')} →</a>
				</div>
			{:else if !proxyConnected}
				<div class="panel-error">
					<code>{proxy.error ?? $t('daemons.notReachable', { provider: proxyProvider.toUpperCase() })}</code>
					<p>{$t('daemons.proxyHint')}</p>
					{#if proxy.url}
						<p class="url"><span class="kdim">URL</span> <code>{proxy.url}</code></p>
					{/if}
				</div>
			{:else}
				{#if proxyProvider === 'npm'}
					{@const total = proxy.proxy_hosts ?? 0}
					{@const managed = proxy.proxy_hosts_managed ?? 0}
					{@const external = Math.max(0, total - managed)}
					{@const managedPct = total > 0 ? (managed / total) * 100 : 0}

					<!-- NPM stat tiles -->
					<div class="proxy-stats">
						<a href="/proxies" class="pstat pstat-wide">
							<span class="pstat-label">{$t('daemons.proxyHosts')}</span>
							<div class="pstat-split">
								<span class="pstat-value">{total}</span>
								<span class="pstat-sep">·</span>
								<span class="pstat-sub">
									<span class="pstat-chip managed">
										<i class="pstat-dot managed"></i>
										{managed} <em>{$t('daemons.managed')}</em>
									</span>
									<span class="pstat-chip external">
										<i class="pstat-dot external"></i>
										{external} <em>{$t('daemons.external')}</em>
									</span>
								</span>
							</div>
							{#if total > 0}
								<div class="pstat-meter" aria-hidden="true">
									<span class="meter-fill" style="width: {managedPct}%"></span>
								</div>
							{/if}
						</a>
						<a href="/settings/npm" class="pstat">
							<span class="pstat-label">{$t('daemons.accessLists')}</span>
							<span class="pstat-value">{proxy.access_lists ?? 0}</span>
						</a>
						<a href="/settings/npm" class="pstat">
							<span class="pstat-label">{$t('daemons.certificates')}</span>
							<span class="pstat-value">{proxy.certificates ?? 0}</span>
						</a>
					</div>
				{/if}

				<dl class="kv">
					<div>
						<dt>{$t('daemons.provider')}</dt>
						<dd class="mono">{proxyProvider.toUpperCase()}</dd>
					</div>
					<div>
						<dt>{$t('daemons.latency')}</dt>
						<dd>{formatMs(proxy.latency_ms)}</dd>
					</div>
					<div class="kv-wide">
						<dt>{$t('daemons.endpoint')}</dt>
						<dd class="truncate" title={proxy.url ?? ''}>{proxy.url ?? '—'}</dd>
					</div>
				</dl>
			{/if}
		</article>
	</div>
</section>

<style>
	.daemons {
		position: relative;
	}

	/* ── Header ─────────────────────────────────────────────── */
	.daemons-head {
		display: flex;
		align-items: flex-end;
		justify-content: space-between;
		gap: 1rem;
		margin-bottom: 0.85rem;
	}
	.eyebrow {
		display: block;
		font-family: var(--forge-mono);
		font-size: 0.62rem;
		letter-spacing: 0.22em;
		text-transform: uppercase;
		color: var(--text-tertiary);
		margin-bottom: 0.2rem;
	}
	.daemons-title {
		font-family: var(--font-family-sans);
		font-size: 1.35rem;
		font-weight: 600;
		line-height: 1.2;
		letter-spacing: -0.01em;
		color: var(--text-primary);
		margin: 0;
	}
	.daemons-title .accent {
		color: var(--forge-accent);
		font-weight: 700;
	}
	.refresh-btn {
		display: inline-flex;
		align-items: center;
		gap: 0.4rem;
		padding: 0.38rem 0.7rem;
		background: var(--surface-card);
		border: 1px solid var(--border-primary);
		border-radius: 8px;
		font-family: var(--forge-mono);
		font-size: 0.62rem;
		font-weight: 600;
		letter-spacing: 0.14em;
		text-transform: uppercase;
		color: var(--text-secondary);
		cursor: pointer;
		transition: all 150ms ease;
	}
	.refresh-btn:hover:not(:disabled) {
		color: var(--text-primary);
		border-color: var(--color-brand-400);
		background: var(--surface-card-hover);
	}
	.refresh-btn:disabled { opacity: 0.55; cursor: wait; }
	.refresh-icon { display: inline-flex; }
	.refresh-icon.spin :global(svg) { animation: daemon-spin 0.9s linear infinite; }

	@keyframes daemon-spin { to { transform: rotate(360deg); } }

	/* ── Grid ───────────────────────────────────────────────── */
	.daemons-grid {
		display: grid;
		grid-template-columns: 1fr;
		gap: 0.75rem;
	}
	@media (min-width: 900px) {
		.daemons-grid { grid-template-columns: 1.15fr 1fr; }
	}

	/* ── Panel base ─────────────────────────────────────────── */
	.panel {
		position: relative;
		background: var(--surface-card);
		border: 1px solid var(--border-primary);
		border-radius: 14px;
		padding: 1rem 1.1rem 1.1rem;
		overflow: hidden;
	}
	.panel::before {
		/* Registration mark: top-left corner tick */
		content: '';
		position: absolute;
		top: 0; left: 0;
		width: 14px; height: 14px;
		border-top: 2px solid var(--color-brand-500);
		border-left: 2px solid var(--color-brand-500);
		border-top-left-radius: 14px;
		opacity: 0;
		transition: opacity 200ms ease;
	}
	.panel:hover::before { opacity: 1; }
	.panel::after {
		/* Subtle orange wash top */
		content: '';
		position: absolute;
		inset: 0 0 auto 0;
		height: 2px;
		background: linear-gradient(90deg, var(--color-brand-500), transparent 70%);
		opacity: 0;
		transition: opacity 250ms ease;
	}
	.panel:hover::after { opacity: 0.55; }
	.panel-down {
		border-color: color-mix(in srgb, var(--color-danger) 45%, transparent);
		background: color-mix(in srgb, var(--color-danger) 3%, var(--surface-card));
	}

	.panel-head {
		display: flex;
		align-items: center;
		justify-content: space-between;
		gap: 0.5rem;
		margin-bottom: 0.85rem;
		padding-bottom: 0.75rem;
		border-bottom: 1px dashed var(--border-secondary);
	}
	.panel-title {
		display: inline-flex;
		align-items: center;
		gap: 0.5rem;
		font-family: var(--forge-mono);
		font-size: 0.72rem;
		font-weight: 700;
		letter-spacing: 0.16em;
		text-transform: uppercase;
		color: var(--text-primary);
	}
	.panel-title :global(svg) { color: var(--color-brand-600); }

	.status-pill {
		display: inline-flex;
		align-items: center;
		gap: 0.4rem;
		padding: 0.22rem 0.55rem;
		border-radius: 999px;
		font-family: var(--forge-mono);
		font-size: 0.58rem;
		font-weight: 700;
		letter-spacing: 0.16em;
		text-transform: uppercase;
		background: var(--surface-card-hover);
		border: 1px solid var(--border-primary);
		color: var(--text-tertiary);
	}
	.status-pill .status-dot {
		width: 6px; height: 6px;
		border-radius: 50%;
		background: var(--text-tertiary);
	}
	.status-pill.live {
		color: var(--color-success-dark);
		background: color-mix(in srgb, var(--color-success) 9%, transparent);
		border-color: color-mix(in srgb, var(--color-success) 35%, transparent);
	}
	.status-pill.live .status-dot {
		background: var(--color-success);
		animation: daemon-pulse 1.8s ease-in-out infinite;
	}
	.status-pill.down {
		color: var(--color-danger-dark);
		background: color-mix(in srgb, var(--color-danger) 10%, transparent);
		border-color: color-mix(in srgb, var(--color-danger) 40%, transparent);
	}
	.status-pill.down .status-dot {
		background: var(--color-danger);
		animation: daemon-blink 0.9s steps(2) infinite;
	}
	.status-pill.idle { opacity: 0.75; }

	:global([data-theme='dark']) .status-pill.live { color: #86efac; }
	:global([data-theme='dark']) .status-pill.down { color: #fca5a5; }

	@keyframes daemon-pulse {
		0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--color-success) 40%, transparent); }
		50%      { box-shadow: 0 0 0 4px color-mix(in srgb, var(--color-success) 0%, transparent); }
	}
	@keyframes daemon-blink {
		0%, 100% { opacity: 1; }
		50%      { opacity: 0.3; }
	}

	/* ── Container state bar ───────────────────────────────── */
	.state-block {
		margin-bottom: 0.95rem;
		padding: 0.75rem 0.85rem;
		background: color-mix(in srgb, var(--color-brand-500) 4%, transparent);
		border: 1px solid color-mix(in srgb, var(--color-brand-500) 18%, transparent);
		border-radius: 10px;
	}
	.state-head {
		display: flex;
		justify-content: space-between;
		align-items: baseline;
		margin-bottom: 0.5rem;
	}
	.state-caption {
		font-family: var(--forge-mono);
		font-size: 0.58rem;
		letter-spacing: 0.2em;
		text-transform: uppercase;
		color: var(--text-tertiary);
	}
	.state-total {
		font-family: var(--font-family-sans);
		font-size: 1.6rem;
		font-weight: 700;
		line-height: 1;
		color: var(--text-primary);
		font-variant-numeric: tabular-nums;
	}
	.state-bar {
		display: flex;
		height: 10px;
		width: 100%;
		border-radius: 6px;
		overflow: hidden;
		background: var(--border-secondary);
	}
	.state-bar.empty {
		background: repeating-linear-gradient(45deg, var(--border-secondary), var(--border-secondary) 4px, transparent 4px, transparent 8px);
		border: 1px dashed var(--border-primary);
	}
	.seg { display: block; height: 100%; transition: width 600ms cubic-bezier(0.2, 0.8, 0.2, 1); }
	.seg-run { background: var(--color-success); }
	.seg-pause { background: var(--color-warning); }
	.seg-stop { background: var(--text-tertiary); }
	.state-legend {
		display: flex;
		flex-wrap: wrap;
		gap: 0.9rem;
		margin-top: 0.55rem;
		font-family: var(--forge-mono);
		font-size: 0.62rem;
		color: var(--text-secondary);
		letter-spacing: 0.04em;
	}
	.state-legend b { color: var(--text-primary); font-weight: 700; font-variant-numeric: tabular-nums; margin-left: 0.25rem; }
	.leg { display: inline-flex; align-items: center; gap: 0.4rem; }
	.ld { display: inline-block; width: 8px; height: 8px; border-radius: 2px; }
	.ld-run { background: var(--color-success); }
	.ld-pause { background: var(--color-warning); }
	.ld-stop { background: var(--text-tertiary); }

	/* ── Key/Value grid ────────────────────────────────────── */
	.kv {
		display: grid;
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 0.45rem 1.1rem;
		margin: 0;
	}
	.kv > div {
		display: flex;
		flex-direction: column;
		gap: 0.1rem;
		min-width: 0;
	}
	.kv-wide { grid-column: 1 / -1; }
	.kv dt {
		font-family: var(--forge-mono);
		font-size: 0.54rem;
		letter-spacing: 0.2em;
		text-transform: uppercase;
		color: var(--text-tertiary);
		margin: 0;
	}
	.kv dd {
		font-family: var(--forge-mono);
		font-size: 0.78rem;
		color: var(--text-primary);
		margin: 0;
		line-height: 1.35;
		font-variant-numeric: tabular-nums;
	}
	.kv dd.mono { letter-spacing: 0.04em; }
	.truncate {
		overflow: hidden;
		text-overflow: ellipsis;
		white-space: nowrap;
	}

	/* ── Proxy stat tiles ─────────────────────────────────── */
	.proxy-stats {
		display: grid;
		grid-template-columns: 1fr 1fr;
		grid-template-areas:
			'wide wide'
			'a b';
		gap: 0.4rem;
		margin-bottom: 0.95rem;
	}
	.pstat-wide { grid-area: wide; }
	.pstat {
		display: flex;
		flex-direction: column;
		gap: 0.2rem;
		padding: 0.6rem 0.7rem;
		background: color-mix(in srgb, var(--color-brand-500) 4%, transparent);
		border: 1px solid color-mix(in srgb, var(--color-brand-500) 16%, transparent);
		border-radius: 10px;
		text-decoration: none;
		color: inherit;
		transition: all 150ms ease;
	}
	.pstat:hover {
		border-color: var(--color-brand-500);
		background: color-mix(in srgb, var(--color-brand-500) 9%, transparent);
		transform: translateY(-1px);
	}
	.pstat-label {
		font-family: var(--forge-mono);
		font-size: 0.52rem;
		letter-spacing: 0.2em;
		text-transform: uppercase;
		color: var(--text-tertiary);
	}
	.pstat-value {
		font-family: var(--font-family-sans);
		font-size: 1.35rem;
		font-weight: 700;
		line-height: 1;
		color: var(--text-primary);
		font-variant-numeric: tabular-nums;
	}

	/* Split-stat layout for proxy hosts (total / managed / external). */
	.pstat-split {
		display: flex;
		align-items: baseline;
		gap: 0.55rem;
		flex-wrap: wrap;
		margin-top: 0.15rem;
	}
	.pstat-split .pstat-value {
		font-size: 1.8rem;
		line-height: 1;
	}
	.pstat-sep {
		color: var(--text-tertiary);
		font-family: var(--forge-mono);
		font-size: 1.2rem;
		line-height: 1;
		opacity: 0.55;
	}
	.pstat-sub {
		display: inline-flex;
		gap: 0.4rem;
		flex-wrap: wrap;
	}
	.pstat-chip {
		display: inline-flex;
		align-items: center;
		gap: 0.35rem;
		padding: 0.12rem 0.45rem 0.12rem 0.35rem;
		border-radius: 999px;
		font-family: var(--forge-mono);
		font-size: 0.66rem;
		font-weight: 700;
		letter-spacing: 0.04em;
		color: var(--text-primary);
		background: var(--surface-card);
		border: 1px solid var(--border-primary);
		font-variant-numeric: tabular-nums;
	}
	.pstat-chip em {
		font-style: normal;
		font-weight: 500;
		font-size: 0.56rem;
		letter-spacing: 0.18em;
		text-transform: uppercase;
		color: var(--text-tertiary);
		margin-left: 0.1rem;
	}
	.pstat-chip.managed {
		border-color: color-mix(in srgb, var(--color-brand-500) 40%, transparent);
		color: var(--color-brand-700);
		background: color-mix(in srgb, var(--color-brand-500) 10%, var(--surface-card));
	}
	.pstat-chip.external {
		border-color: var(--border-primary);
		color: var(--text-secondary);
	}
	:global([data-theme='dark']) .pstat-chip.managed {
		color: #c7d2fe;
		background: color-mix(in srgb, var(--color-brand-500) 18%, transparent);
	}
	.pstat-dot {
		width: 7px; height: 7px; border-radius: 50%;
		display: inline-block;
	}
	.pstat-dot.managed { background: var(--color-brand-500); box-shadow: 0 0 0 2px color-mix(in srgb, var(--color-brand-500) 20%, transparent); }
	.pstat-dot.external { background: var(--text-tertiary); opacity: 0.6; }

	/* Proportion meter under the total. */
	.pstat-meter {
		margin-top: 0.55rem;
		height: 4px;
		border-radius: 999px;
		background: var(--border-secondary);
		overflow: hidden;
	}
	.meter-fill {
		display: block;
		height: 100%;
		background: linear-gradient(90deg, var(--color-brand-500), var(--color-brand-600));
		border-radius: inherit;
		transition: width 600ms cubic-bezier(0.2, 0.8, 0.2, 1);
	}

	/* ── Error / empty states ─────────────────────────────── */
	.panel-error {
		padding: 0.75rem 0.85rem;
		border-radius: 10px;
		background: color-mix(in srgb, var(--color-danger) 8%, transparent);
		border: 1px solid color-mix(in srgb, var(--color-danger) 35%, transparent);
	}
	.panel-error code {
		display: block;
		font-family: var(--forge-mono);
		font-size: 0.7rem;
		line-height: 1.55;
		color: var(--color-danger-dark);
		word-break: break-word;
		margin-bottom: 0.45rem;
	}
	.panel-error p {
		margin: 0;
		font-size: 0.75rem;
		color: var(--text-secondary);
	}
	.panel-error .url {
		margin-top: 0.45rem;
		font-family: var(--forge-mono);
		font-size: 0.7rem;
	}
	.panel-error .url code {
		display: inline;
		color: var(--text-primary);
		background: var(--surface-card-hover);
		padding: 0.08rem 0.35rem;
		border-radius: 4px;
		margin: 0;
	}
	.kdim {
		display: inline-block;
		color: var(--text-tertiary);
		letter-spacing: 0.2em;
		text-transform: uppercase;
		font-size: 0.54rem;
		margin-right: 0.4rem;
	}
	:global([data-theme='dark']) .panel-error code { color: #fca5a5; }

	.panel-empty {
		display: flex;
		flex-direction: column;
		align-items: flex-start;
		gap: 0.5rem;
		padding: 0.9rem 1rem;
		background: var(--surface-card-hover);
		border: 1px dashed var(--border-primary);
		border-radius: 10px;
		color: var(--text-secondary);
	}
	.panel-empty :global(svg) { color: var(--text-tertiary); }
	.panel-empty p { margin: 0; font-size: 0.8rem; }
	.inline-link {
		font-family: var(--forge-mono);
		font-size: 0.66rem;
		font-weight: 600;
		letter-spacing: 0.14em;
		text-transform: uppercase;
		color: var(--color-brand-600);
		text-decoration: none;
	}
	.inline-link:hover { text-decoration: underline; }

	/* ── Skeleton ─────────────────────────────────────────── */
	.panel-skeleton {
		display: flex;
		flex-direction: column;
		gap: 0.55rem;
		padding: 0.4rem 0;
	}
	.skel-bar {
		height: 10px;
		border-radius: 6px;
		background: linear-gradient(90deg, var(--surface-card-hover) 0%, var(--border-secondary) 50%, var(--surface-card-hover) 100%);
		background-size: 200% 100%;
		animation: skel-shift 1.4s ease-in-out infinite;
	}
	.skel-bar-narrow { width: 55%; }
	@keyframes skel-shift {
		0% { background-position: 200% 0; }
		100% { background-position: -200% 0; }
	}
</style>
