/* ==========================================================
   ws-toc.css
   Jump menu for long documents. Loads only where [ws_toc] is.
   Owns own prefix. Only main.css brand tokens shared.
   ========================================================== */

/* === Geometry ===
   Reading column is 800. Rail plus gap decides the breakpoint
   at the bottom of this file. Change one, recheck the other. */
:root {
	--wstoc-rail: 200px;
	--wstoc-gap: 32px;
	--wstoc-bar-h: 52px;
	--wstoc-bleed: 24px;
	--wstoc-shadow: 0 6px 24px rgba(82, 88, 91, 0.12);
}

/* Light grey cast vanishes on charcoal. Dark needs its own. */
[data-theme="dark"] {
	--wstoc-shadow: 0 6px 24px rgba(0, 0, 0, 0.35);
}

/* Anchor landing clearance. Bar covers the heading without it. */
.ws-page__content h2[id],
.ws-page__content h3[id] {
	scroll-margin-top: calc(var(--wstoc-bar-h) + 24px);
}

/* === Shell ===
   One list, two layouts. Not a <details>: that element parks its
   contents in a UA shadow slot that author CSS cannot force open, so
   the rail had no way to show the list. Button plus nav, toggled by
   class, works at both sizes.

   Base state assumes no JS: list open, toggle hidden. The theme adds
   .js to <html> before paint, so nothing flashes. */
.wstoc {
	margin: 32px calc(var(--wstoc-bleed) * -1) 40px;
	background: var(--ws-bg);
	border-top: 1px solid var(--ws-border);
	border-bottom: 1px solid var(--ws-border);
}

/* Pinning an always-open list would bury the page under it. */
.js .wstoc {
	position: sticky;
	top: 0;
	z-index: 40;
	box-shadow: var(--wstoc-shadow);
}

/* === Toggle. The pinned bar. === */
.wstoc__summary { display: none; }

.js .wstoc__summary {
	position: relative;
	display: flex;
	align-items: center;
	gap: 12px;
	width: 100%;
	height: var(--wstoc-bar-h);
	padding: 0 var(--wstoc-bleed);
	margin: 0;
	font: inherit;
	text-align: left;
	color: inherit;
	background: none;
	border: 0;
	border-radius: 0;
	cursor: pointer;
	-webkit-user-select: none;
	user-select: none;
}

.wstoc__summary:focus-visible {
	outline: 2px solid var(--ws-accent);
	outline-offset: -2px;
}

/* Static half. Says what the control is before anything moves. */
.wstoc__kicker {
	flex: 0 0 auto;
	font-family: var(--ws-font);
	font-size: 0.64rem;
	font-weight: 900;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--ws-muted);
}

/* Live half. JS writes the section name. No JS leaves it empty and
   the bar is hidden anyway. */
.wstoc__here {
	flex: 1 1 auto;
	min-width: 0;
	font-family: var(--ws-font);
	font-size: 0.95rem;
	font-weight: 700;
	color: var(--ws-heading);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

.wstoc__chev {
	flex: 0 0 auto;
	width: 18px;
	height: 18px;
	color: var(--ws-muted);
	transition: transform 0.24s var(--ws-ease);
}
.wstoc.is-open .wstoc__chev { transform: rotate(180deg); }

/* Read progress. Sits on the bottom rule so it reads as part of the
   edge, not a second widget bolted to the bar. */
.wstoc__progress {
	position: absolute;
	left: 0;
	bottom: -1px;
	height: 2px;
	width: 0;
	background: var(--ws-accent);
	pointer-events: none;
}

/* === Panel === */
.js .wstoc__panel { display: none; }
.js .wstoc.is-open .wstoc__panel { display: block; }

.wstoc__panel {
	max-height: min(60vh, 420px);
	overflow-y: auto;
	overscroll-behavior: contain;
	padding: 4px var(--wstoc-bleed) 16px;
	border-top: 1px solid var(--ws-border);
}

.wstoc__list {
	list-style: none;
	margin: 0;
	padding: 0;
}
.wstoc__list--sub { padding-left: 14px; }
.wstoc__list li { margin: 0; }

/* SPECIFICITY: main.css hangs a lime underline on every content
   link at (0,2,2). Three classes here clear it. background-size
   is held at zero through hover, which is where the base rule
   would otherwise grow the fill. */
.ws-page__content .wstoc .wstoc__link {
	display: block;
	padding: 9px 0 9px 14px;
	margin-left: -1px;
	font-family: var(--ws-font);
	font-size: 0.95rem;
	font-weight: 700;
	line-height: 1.35;
	color: var(--ws-muted);
	text-decoration: none;
	background-size: 0 0;
	border-left: 2px solid var(--ws-border);
	transition: color 0.2s var(--ws-ease), border-color 0.2s var(--ws-ease);
}

.ws-page__content .wstoc .wstoc__link--sub {
	font-weight: 400;
	font-size: 0.88rem;
}

@media (hover: hover) {
	.ws-page__content .wstoc .wstoc__link:hover {
		color: var(--ws-heading);
		background-size: 0 0;
		border-left-color: var(--ws-grey);
	}
}

.ws-page__content .wstoc .wstoc__link:focus-visible {
	outline: 2px solid var(--ws-accent);
	outline-offset: -2px;
}

/* Set by scroll spy. No JS means no mark, which is the correct
   degradation: a plain list of anchors that all still work. */
.ws-page__content .wstoc .wstoc__link.is-current {
	color: var(--ws-heading);
	border-left-color: var(--ws-accent);
}

.wstoc__railhead { display: none; }

/* === Rail layout ===
   800 column plus 32 gap plus 200 rail needs 1264 of content.
   1320 leaves a margin either side, so that is the switch. Below
   it the bar is the layout, not a fallback. */
@media (min-width: 1320px) {

	.wstoc,
	.js .wstoc {
		position: fixed;
		top: 128px;
		left: calc(50% - 400px - var(--wstoc-gap) - var(--wstoc-rail));
		width: var(--wstoc-rail);
		max-height: calc(100vh - 200px);
		margin: 0;
		padding: 0;
		background: none;
		border: 0;
		box-shadow: none;
		overflow-y: auto;
	}

	.wstoc__summary,
	.js .wstoc__summary { display: none; }

	/* No toggle at this size, so the list is simply always shown. */
	.js .wstoc__panel,
	.js .wstoc.is-open .wstoc__panel,
	.wstoc__panel {
		display: block;
		max-height: none;
		overflow: visible;
		padding: 0;
		border-top: 0;
	}

	.wstoc__railhead {
		display: block;
		font-family: var(--ws-font);
		font-size: 0.64rem;
		font-weight: 900;
		letter-spacing: 0.14em;
		text-transform: uppercase;
		color: var(--ws-muted);
		margin: 0 0 12px;
	}

	.ws-page__content .wstoc .wstoc__link {
		padding-top: 7px;
		padding-bottom: 7px;
	}
}

@media (prefers-reduced-motion: reduce) {
	.wstoc__chev,
	.ws-page__content .wstoc .wstoc__link { transition: none; }
}
