/**
 * FreshBrand Editorial — Progressive table of contents
 * =============================================================================
 * A reading rail built by `assets/js/toc.js` from whatever LuckyWP already
 * printed inside `.article-content`. Nothing here styles LuckyWP's own inline
 * box: that keeps its border, its toggle and its smooth scroll exactly as the
 * plugin ships them, and stays the whole feature when JavaScript is off, below
 * the desktop width, and in print — where it already is the collapsible
 * "contents" control those cases need.
 *
 * ONE SIGNAL PER STATE. The rail's job is "where am I?", not "here is the
 * outline again", so it spends emphasis carefully:
 *
 *   section, idle      muted, medium
 *   section, current   ink, semibold          <- the only weight change
 *   sub-heading        muted, one step down   <- only shown while its section is
 *   sub-heading, here  accent                 <- the only colour in the rail
 *
 * There are no rules, no tree lines and no boxes. Hierarchy comes from the
 * index column, the indent and that one weight step; an earlier version drew a
 * hairline beside every level and the rail started competing with the article
 * for the reader's attention.
 *
 * The rail lives at the end of `<body>`, so `position: fixed` cannot be
 * captured by a transformed ancestor inside the article, and every token below
 * resolves against `html:root` / `body.qodef-skin--dark` — dark mode needs no
 * rules of its own.
 *
 * Geometry comes from the article's real measured geometry, not from a
 * hardcoded column: `--fb-toc-left` and `--fb-toc-width` are written by the
 * script on load and on resize.
 *
 * @package FreshBrand_Editorial
 */

.fb-toc-rail {
	position: fixed;
	top: var(--fb-toc-top);
	left: var(--fb-toc-left, 0px);
	z-index: 90; /* Under einar's sticky header, which sits at 100. */

	display: flex;
	flex-direction: column;
	gap: 2rem;

	width: var(--fb-toc-width, 24rem);
	max-height: calc(100vh - var(--fb-toc-top) - 6rem);
	overflow-x: hidden;
	overflow-y: auto;
	overscroll-behavior: contain;

	/* 6rem clears einar's 60px sticky header with room to breathe; the admin
	   bar pushes everything down by its own 32px. */
	--fb-toc-top: 10rem;

	/* The index column, and the gap after it. The sub-headings indent by the
	   sum of the two so they align under the section's label, not its number. */
	--fb-toc-index: 2.2rem;
	--fb-toc-gap: 1.2rem;

	opacity: 0;
	visibility: hidden;
	transform: translateY(0.8rem);
	transition:
		opacity 0.4s var(--ease-smooth),
		transform 0.4s var(--ease-smooth),
		visibility 0.4s;

	scrollbar-width: thin;
	scrollbar-color: var(--bd-color) transparent;
}

.admin-bar .fb-toc-rail {
	--fb-toc-top: 13.2rem;
}

.fb-toc-rail.is-visible {
	opacity: 1;
	visibility: visible;
	transform: none;
}

.fb-toc-rail::-webkit-scrollbar {
	width: 2px;
}

.fb-toc-rail::-webkit-scrollbar-thumb {
	background-color: var(--bd-color);
}

/* --- Title ---------------------------------------------------------------
   An eyebrow, not a heading: the rail is furniture, the article is the page.
   No letter-spacing — FreshBrand tightens type and never opens it out, so
   labels take their identity from case, weight and colour. */

.fb-toc-rail__title {
	margin: 0;
	font-family: var(--font-body);
	font-size: 1.15rem;
	font-weight: 600;
	line-height: 1.4;
	letter-spacing: normal;
	text-transform: uppercase;
	color: var(--text-light);
}

/* --- Sections ------------------------------------------------------------ */

/* Two classes, not one. einar resets lists with `ol:not(.wp-block)` — and
   `:not()` carries the specificity of its argument, so that rule weighs (0,1,1)
   and beat a single-class reset here. Its `margin-bottom: 1.5em` survived on the
   sub-list and held the folded-away wrapper open at 26px, which read as a gap
   under every closed section. */
.fb-toc-rail .fb-toc-rail__list,
.fb-toc-rail .fb-toc-rail__sub,
.fb-toc-rail .fb-toc-rail__section,
.fb-toc-rail .fb-toc-rail__item {
	margin: 0;
	padding: 0;
	list-style: none;
}

.fb-toc-rail .fb-toc-rail__section + .fb-toc-rail__section {
	margin-top: 1.4rem;
}

.fb-toc-rail__link {
	display: flex;
	font-family: var(--font-body);
	line-height: 1.45;
	letter-spacing: normal;
	color: var(--text-light);
	text-decoration: none;
	transition: color 0.3s var(--ease-smooth);
}

.fb-toc-rail__link:hover,
.fb-toc-rail__link:focus-visible {
	color: var(--qode-main-color);
	text-decoration: none;
}

.fb-toc-rail__link--section {
	gap: var(--fb-toc-gap);
	font-size: 1.35rem;
	font-weight: 500;
}

/* The section being read. Weight and ink carry it on their own — it never also
   takes the accent, which belongs to the exact sub-heading below. */
.fb-toc-rail__link--section.is-current {
	color: var(--qode-main-color);
	font-weight: 600;
}

.fb-toc-rail__number {
	flex: 0 0 var(--fb-toc-index);
	font-variant-numeric: tabular-nums;
	font-weight: 400;
	color: var(--text-light);
}

/* Two lines is the honest limit for a Vietnamese heading in a 22rem column;
   the full text stays available as the link's title attribute. */
.fb-toc-rail__label {
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	line-clamp: 2;
	overflow: hidden;
}

/* --- Sub-headings, revealed with their section ---------------------------
   `grid-template-rows: 0fr -> 1fr` is the only way to transition to a height
   the content decides, and it needs a wrapper with exactly one track to grow.
   The list inside clips, so the first item's own padding folds away with it. */

.fb-toc-rail__reveal {
	display: grid;
	grid-template-rows: 0fr;
	transition: grid-template-rows 0.35s var(--ease-smooth);
}

.fb-toc-rail__reveal.is-open {
	grid-template-rows: 1fr;
}

.fb-toc-rail .fb-toc-rail__sub {
	min-height: 0;
	overflow: hidden;
}

.fb-toc-rail__link--sub {
	padding: 0.45rem 0 0.45rem calc(var(--fb-toc-index) + var(--fb-toc-gap));
	font-size: 1.25rem;
	font-weight: 400;
}

.fb-toc-rail__sub > .fb-toc-rail__item:first-child .fb-toc-rail__link--sub {
	padding-top: 0.9rem;
}

/* The one place the rail uses colour: the sub-heading actually on screen. */
.fb-toc-rail__link--sub.is-active {
	color: var(--primary);
	font-weight: 500;
}

/* --- Boundaries ----------------------------------------------------------
   A 720px measure plus a 220px rail plus 64px of air first fits at about
   1360px. Below that the inline table of contents — which is already a
   collapsible box above the article — is the only one. The script measures the
   same thing at runtime and agrees; both are stated so neither can quietly
   drift alone. */

@media (max-width: 84.99em) {
	.fb-toc-rail {
		display: none;
	}
}

@media (prefers-reduced-motion: reduce) {
	.fb-toc-rail,
	.fb-toc-rail__link,
	.fb-toc-rail__reveal {
		transition: none;
		transform: none;
	}
}

@media print {
	.fb-toc-rail {
		display: none;
	}
}
