:host {
	display: block;
	width: var(--size, 320px);
	max-width: 100%;
	/* Default ring thickness (fraction of the radius), used only when there's
	   no channel and the disc renders as a ring. */
	--ring-thickness: 0.35;

	/* Render every slotted point (a <color-swatch>, or a <color-scale>'s swatches)
	   as a compact dot with a hover/focus tooltip. Both properties inherit down to
	   the slotted elements, which style themselves accordingly — hue-wheel only
	   positions them (see ::slotted below and hue-wheel-global.css). */
	--swatch-style: dot;
	--details-style: compact;
}

#wheel {
	position: relative;
	aspect-ratio: 1;
	container-type: inline-size;
	border-radius: 50%;
	cursor: crosshair;
	/* Suppress pan/zoom so dragging on touch doesn't scroll the page. */
	touch-action: none;
	-webkit-user-select: none;
	user-select: none;
}

:host([readonly]) #wheel {
	cursor: default;
}

#disc {
	position: absolute;
	inset: 0;
	border-radius: 50%;
	/* The wheel is the only intended pointer target; let events fall through the
	   disc (and its layers) to #wheel. */
	pointer-events: none;
}

/* Ring mode: punch a circular hole so only an annulus of hue shows. */
:host(:state(ring)) #disc {
	--_inner: calc((1 - var(--ring-thickness)) * 50cqi);
	mask: radial-gradient(circle, transparent 0 var(--_inner), #000 var(--_inner));
}

.layer {
	position: absolute;
	/* Outer edge maps to this layer's channel value: fraction 1 → full size,
	   fraction 0 → a point at the centre. */
	inset: calc((1 - var(--fraction)) * 50%);
	border-radius: 50%;
}

/* Polar placement, shared by the marker and slotted points. --hue (angle) +
   --channel (raw value) come from JS. The point sits at angle --hue, --_r out from
   the centre: go to the angle, move out, rotate back so it stays upright — no trig.
   `translate` (applied before `transform` per spec order) centres the box on the
   wheel centre first; `transform` then walks it out to the polar point. */
#marker,
::slotted(color-swatch) {
	position: absolute;
	top: 50%;
	left: 50%;
	margin: 0;
	--_channel-progress: clamp(
		0,
		(var(--channel) - var(--channel-min)) / (var(--channel-max) - var(--channel-min)),
		1
	);
	--_r: calc(var(--_channel-progress) * 50cqi);
	translate: -50% -50%;
	transform: rotate(calc(-1 * var(--hue))) translateX(var(--_r)) rotate(var(--hue));
}

/* The built-in marker: the current colour as a <color-swatch> dot (dot mode comes
   from the inherited --swatch-style), distinguished from plotted points by the dot
   knobs, which reproduce the prominent white ring. To customise it (incl. adding a
   tooltip), slot your own <color-swatch slot="marker"> instead. A slotted marker
   stacks above the points like this one does. */
#marker,
::slotted([slot="marker"]) {
	z-index: 2;
}

/* No colour selected → no marker. A bare `hidden` can't hide a <color-swatch> (its
   own :host sets `display`), so hide it explicitly; otherwise it parks at the centre
   and jumps to the first click. */
#marker[hidden],
::slotted([slot="marker"][hidden]) {
	display: none;
}

#marker {
	--dot-size: 1em;
	--dot-border: 2px solid white;
	--dot-shadow: 0 0 0 1px rgb(0 0 0 / 0.4), 0 1px 2px rgb(0 0 0 / 0.4);

	/* No tooltip by default — the dot just marks the current colour. */
	&::part(details) {
		display: none;
	}
}

/* Plotted points: a directly-slotted <color-swatch> is positioned by its own
   hue/channel (set by JS) — the same polar placement as the marker (see above).
   ::slotted() reaches a slotted swatch from here; a <color-scale>'s inner swatches
   are ::part()s and can't be reached through ::slotted(), so those are placed in
   hue-wheel-global.css. */

:host(:not([readonly])) {
	#marker {
		cursor: grab;

		&:active {
			cursor: grabbing;
		}
	}
}

/* No channel → marker and points ride the middle of the ring. */
:host(:state(ring)) :is(#marker, ::slotted(color-swatch)) {
	--_r: calc((1 - var(--ring-thickness) / 2) * 50cqi);
}

#marker:focus-visible,
::slotted([slot="marker"]:focus-visible) {
	outline: 2px solid Highlight;
	outline-offset: 2px;
}

slot {
	display: block;
}
