SpawnProtectionEffect.cs
using Sandbox;
using System;

/// <summary>A local, pulsing glow driven by the player's replicated spawn protection timer.</summary>
public sealed class SpawnProtectionEffect : Component
{
	[RequireComponent] private Player Player { get; set; }
	[RequireComponent] private HealthComponent Health { get; set; }

	private GameObject _effectObject;
	private HighlightOutline _outline;

	protected override void OnUpdate()
	{
		// The local player has a hidden body and sees protection on their health bar.
		if ( !Health.IsInvulnerable || !Player.Avatar.IsValid() || (!IsProxy && !Player.IsBot) )
		{
			DestroyEffect();
			return;
		}

		if ( !_effectObject.IsValid() )
		{
			_effectObject = new GameObject( GameObject, false, "Spawn Protection Glow" )
			{
				NetworkMode = NetworkMode.Never
			};
			_outline = _effectObject.AddComponent<HighlightOutline>();
			_outline.OverrideTargets = true;
			_outline.ObscuredColor = Color.Transparent;
			_outline.InsideObscuredColor = Color.Transparent;
			_effectObject.Enabled = true;
		}

		// Refresh while active so clothing that finishes loading after spawn also glows.
		_outline.Targets = Player.Avatar.Components.GetAll<ModelRenderer>( FindMode.EverythingInSelfAndDescendants )
			.Cast<Renderer>().ToList();

		var pulse = 0.5f + 0.5f * MathF.Sin( Health.SpawnProtectionRemaining * MathF.PI * 4f );
		var fade = Math.Clamp( Health.SpawnProtectionRemaining / 0.5f, 0f, 1f );
		_outline.Color = new Color( 0.15f, 0.85f, 1f, (0.65f + pulse * 0.3f) * fade );
		_outline.InsideColor = new Color( 0.15f, 0.85f, 1f, (0.08f + pulse * 0.08f) * fade );
		_outline.Width = 0.25f + pulse * 0.15f;
	}

	protected override void OnDisabled() => DestroyEffect();
	protected override void OnDestroy() => DestroyEffect();

	private void DestroyEffect()
	{
		if ( _effectObject.IsValid() )
			_effectObject.Destroy();

		_effectObject = null;
		_outline = null;
	}
}