/**
 * HypeMillDoc — layout, header, sidebar, ToC, dark/light mode.
 * Content typography (headings/lists/tables/code/etc.) lives in blocks.css.
 */

:root {
	--hmd-font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
	--hmd-font-bengali: 'Noto Sans Bengali', 'Inter', sans-serif;

	--hmd-bg: #ffffff;
	--hmd-bg-subtle: #f7f7f9;
	--hmd-bg-sidebar: #fafafa;
	--hmd-text: #1f2328;
	--hmd-text-muted: #66707a;
	--hmd-border: #e4e4e8;
	--hmd-accent: #4f46e5;
	--hmd-accent-soft: #eef1ff;
	--hmd-header-bg: #ffffff;
	--hmd-code-bg: #f4f4f7;
	--hmd-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);

	--hmd-header-height: 64px;
	--hmd-sidebar-width: 260px;
	--hmd-toc-width: 240px;

	--hmd-scrollbar-thumb: #c7c9d1;
	--hmd-scrollbar-thumb-hover: #a9acb6;
	--hmd-scrollbar-track: transparent;
}

[data-hmd-theme="dark"] {
	--hmd-bg: #14151a;
	--hmd-bg-subtle: #1b1c22;
	--hmd-bg-sidebar: #17181d;
	--hmd-text: #e7e8ea;
	--hmd-text-muted: #9a9fa6;
	--hmd-border: #2a2b32;
	--hmd-accent: #818cf8;
	--hmd-accent-soft: #21223a;
	--hmd-header-bg: #17181d;
	--hmd-code-bg: #1e1f26;
	--hmd-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);

	--hmd-scrollbar-thumb: #3a3c46;
	--hmd-scrollbar-thumb-hover: #4c4f5c;
	--hmd-scrollbar-track: transparent;
}

/* ------------------------------ Scrollbars ------------------------------ *
 * The ::-webkit-scrollbar pseudo-elements apply to EVERY scrollable
 * element on the page (the ::-webkit-scrollbar selector itself isn't
 * scoped to :root/body) — so this one rule set covers the main page,
 * the sidebar, the ToC, the search-results dropdown, and code blocks
 * alike, with no need for a separate class on each. Firefox only
 * supports the coarser scrollbar-width/scrollbar-color pair (no
 * separate track/thumb-hover styling), set on <html> so it inherits
 * everywhere Firefox is concerned. */
html {
	scrollbar-width: thin;
	scrollbar-color: var(--hmd-scrollbar-thumb) var(--hmd-scrollbar-track);
}

::-webkit-scrollbar {
	width: 10px;
	height: 10px;
}

::-webkit-scrollbar-track {
	background: var(--hmd-scrollbar-track);
}

::-webkit-scrollbar-thumb {
	background-color: var(--hmd-scrollbar-thumb);
	border-radius: 8px;
	border: 2px solid var(--hmd-bg);
	background-clip: padding-box;
}

::-webkit-scrollbar-thumb:hover {
	background-color: var(--hmd-scrollbar-thumb-hover);
}

::-webkit-scrollbar-corner {
	background: transparent;
}

* {
	box-sizing: border-box;
}

html,
body {
	margin: 0;
	padding: 0;
}

body {
	font-family: var(--hmd-font-sans);
	background: var(--hmd-bg);
	color: var(--hmd-text);
	font-size: 16px;
	line-height: 1.65;
	transition: background-color 0.15s ease, color 0.15s ease;
}

:lang(bn),
[lang="bn"] {
	font-family: var(--hmd-font-bengali);
}

a {
	color: var(--hmd-accent);
	text-decoration: none;
}

a:hover {
	text-decoration: underline;
}

img {
	max-width: 100%;
	height: auto;
}

/* ------------------------------- Header ------------------------------- */

.hmd-header {
	position: sticky;
	top: 0;
	z-index: 50;
	background: var(--hmd-header-bg);
	border-bottom: 1px solid var(--hmd-border);
	height: var(--hmd-header-height);
}

.hmd-header__inner {
	max-width: 1400px;
	margin: 0 auto;
	height: 100%;
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding: 0 24px;
	gap: 20px;
}

/* The four auth pages (login/register/forgot-password/reset-password)
   get a bare header — see header.php's $hmd_is_auth_page docblock — so
   the only thing left in .hmd-header__inner is the brand/logo. Centering
   it here (rather than leaving the default space-between, which would
   just pin a lone item to the left) is what actually needs the modifier
   class; everything else about .hmd-header--auth's header looks and
   behaves the same as the normal one. */
.hmd-header__inner--auth {
	justify-content: center;
}

.hmd-header__brand img {
	max-height: 36px;
	max-width: 100px;
	display: block;
}

.hmd-header__site-name {
	font-size: 18px;
	font-weight: 700;
	color: var(--hmd-text);
}

.hmd-header__right {
	display: flex;
	align-items: center;
	gap: 16px;
	flex: 1;
	justify-content: flex-end;
}

.hmd-header__nav {
	display: flex;
}

.hmd-header__menu {
	list-style: none;
	display: flex;
	gap: 20px;
	margin: 0;
	padding: 0;
}

.hmd-header__menu a {
	color: var(--hmd-text);
	font-size: 14px;
	font-weight: 500;
}

.hmd-header__menu a:hover {
	color: var(--hmd-accent);
	text-decoration: none;
}

/* Lives at the top of the left sidebar (above the category tree) so
   search is the first thing available while browsing docs, rather
   than competing for space in the top header. */
.hmd-sidebar__search {
	position: relative;
	width: 100%;
	margin-bottom: 20px;
}

.hmd-sidebar__search input {
	width: 100%;
	padding: 8px 12px;
	border: 1px solid var(--hmd-border);
	border-radius: 8px;
	background: var(--hmd-bg-subtle);
	color: var(--hmd-text);
	font-size: 14px;
	font-family: inherit;
}

.hmd-sidebar__search-results {
	position: absolute;
	top: calc(100% + 6px);
	left: 0;
	right: 0;
	background: var(--hmd-bg);
	border: 1px solid var(--hmd-border);
	border-radius: 8px;
	box-shadow: var(--hmd-shadow);
	max-height: 320px;
	overflow-y: auto;
	z-index: 60;
}

.hmd-search-result,
.hmd-search-empty {
	display: block;
	padding: 10px 14px;
	font-size: 14px;
	color: var(--hmd-text);
	border-bottom: 1px solid var(--hmd-border);
}

.hmd-search-result:hover {
	background: var(--hmd-accent-soft);
	text-decoration: none;
}

.hmd-search-empty {
	color: var(--hmd-text-muted);
	font-style: italic;
}

/* A real button, not a plain text link: filled with the accent color
   so "Log in" reads as the header's one clear call to action. "Log
   out" (shown instead, in the same header slot, once signed in) uses
   a quieter outline style — still a proper button, just visually
   secondary since it's a less-frequent action than logging in. */
.hmd-header__auth-link {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	font-size: 14px;
	font-weight: 600;
	white-space: nowrap;
	padding: 8px 18px;
	border-radius: 8px;
	border: 1px solid var(--hmd-accent);
	background: var(--hmd-accent);
	color: #ffffff;
	transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.hmd-header__auth-link:hover {
	filter: brightness(0.92);
	color: #ffffff;
	text-decoration: none;
}

.hmd-header__auth-link--logout {
	background: transparent;
	border-color: var(--hmd-border);
	color: var(--hmd-text);
}

.hmd-header__auth-link--logout:hover {
	background: var(--hmd-accent-soft);
	border-color: var(--hmd-accent);
	color: var(--hmd-accent);
	opacity: 1;
}

/* ---------------------------- Theme switch ---------------------------- *
 * A scaled-down, self-contained take on a sun<->moon sliding toggle
 * (checkbox + label, no JS needed for the animation itself — app.js
 * only keeps it in sync with the stored preference). */

.hmd-theme-switch {
	position: relative;
	display: inline-flex;
	cursor: pointer;
	flex-shrink: 0;
}

.hmd-theme-switch input {
	position: absolute;
	opacity: 0;
	width: 1px;
	height: 1px;
}

.hmd-theme-switch__track {
	position: relative;
	width: 56px;
	height: 28px;
	border-radius: 999px;
	background: linear-gradient(to bottom, #7ec8ec, #b3e0f2);
	border: 1px solid rgba(0, 0, 0, 0.08);
	overflow: hidden;
	transition: background 0.4s ease;
}

.hmd-theme-switch input:checked + .hmd-theme-switch__track {
	background: linear-gradient(to bottom, #10121f, #1e2140);
}

/* The track's own default border (rgba(0,0,0,0.08), set above) is
   basically invisible once the header itself goes dark -- a near-black
   border on a near-black track/header just disappears, so the switch
   was blending into the background with no visible edge. A light,
   low-opacity border here gives it a visible outline specifically in
   dark mode, without needing to touch the light-mode look at all. */
[data-hmd-theme="dark"] .hmd-theme-switch__track {
	border-color: rgba(255, 255, 255, 0.25);
}

.hmd-theme-switch input:focus-visible + .hmd-theme-switch__track {
	outline: 2px solid var(--hmd-accent);
	outline-offset: 2px;
}

.hmd-theme-switch__stars {
	position: absolute;
	inset: 0;
	opacity: 0;
	transition: opacity 0.4s ease;
}

.hmd-theme-switch input:checked + .hmd-theme-switch__track .hmd-theme-switch__stars {
	opacity: 1;
}

.hmd-theme-switch__stars span {
	position: absolute;
	width: 3px;
	height: 3px;
	border-radius: 50%;
	background: #fff;
	box-shadow: 0 0 3px #fff;
}
.hmd-theme-switch__stars span:nth-child(1) { top: 6px; left: 10px; }
.hmd-theme-switch__stars span:nth-child(2) { top: 16px; left: 6px; width: 2px; height: 2px; }
.hmd-theme-switch__stars span:nth-child(3) { top: 9px; left: 18px; width: 2px; height: 2px; }
.hmd-theme-switch__stars span:nth-child(4) { top: 19px; left: 16px; }

.hmd-theme-switch__thumb {
	position: absolute;
	top: 3px;
	left: 3px;
	width: 20px;
	height: 20px;
	border-radius: 50%;
	background: #ffd166;
	display: flex;
	align-items: center;
	justify-content: center;
	color: #fff8e1;
	transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1), background 0.4s ease, color 0.4s ease;
	box-shadow: 0 0 8px rgba(255, 209, 102, 0.7);
}

.hmd-theme-switch input:checked + .hmd-theme-switch__track .hmd-theme-switch__thumb {
	transform: translateX(28px);
	background: #e8e8f0;
	color: #9a9fc9;
	box-shadow: 0 0 6px rgba(232, 232, 240, 0.6);
}

.hmd-theme-switch__sun-rays {
	width: 14px;
	height: 14px;
	transition: opacity 0.3s ease, transform 0.4s ease;
}

.hmd-theme-switch input:checked + .hmd-theme-switch__track .hmd-theme-switch__sun-rays {
	opacity: 0;
	transform: rotate(90deg) scale(0.5);
}

.hmd-theme-switch__crater {
	position: absolute;
	border-radius: 50%;
	background: rgba(0, 0, 0, 0.12);
	opacity: 0;
	transition: opacity 0.3s ease 0.1s;
}
.hmd-theme-switch__crater--1 { width: 5px; height: 5px; top: 4px; left: 5px; }
.hmd-theme-switch__crater--2 { width: 3px; height: 3px; top: 11px; left: 11px; }

.hmd-theme-switch input:checked + .hmd-theme-switch__track .hmd-theme-switch__crater {
	opacity: 1;
}

.hmd-theme-switch:active .hmd-theme-switch__thumb {
	transform: scale(0.88);
}
.hmd-theme-switch input:checked:active + .hmd-theme-switch__track .hmd-theme-switch__thumb {
	transform: translateX(28px) scale(0.88);
}

/* Mobile-only group: the theme switch + hamburger, pinned together at
   the right edge of row 1 — hidden by default so the theme switch
   doesn't duplicate the desktop copy in .hmd-header__right; see the
   max-width media query below for where it actually becomes visible. */
.hmd-header__mobile-controls {
	display: none;
	align-items: center;
	gap: 14px;
}

/* Row 1's hamburger (opens the right-hand nav offcanvas) and row 3's
   bar icon (opens the left-hand categories offcanvas) share this same
   plain icon-button look. Both are mobile-only — see the max-width
   media query below, which is also where .hmd-header__menu-toggle
   and .hmd-header__sidebar-toggle actually get display: flex. */
.hmd-header__menu-toggle,
.hmd-header__sidebar-toggle {
	display: none;
	align-items: center;
	justify-content: center;
	background: none;
	border: 1px solid var(--hmd-border);
	border-radius: 8px;
	color: var(--hmd-text);
	width: 38px;
	height: 38px;
	flex-shrink: 0;
	cursor: pointer;
	padding: 0;
}

.hmd-header__menu-toggle {
	flex-direction: column;
	gap: 4px;
	border: none;
	width: auto;
	height: auto;
	padding: 8px;
}

.hmd-header__menu-toggle span {
	width: 22px;
	height: 2px;
	background: var(--hmd-text);
	display: block;
}

.hmd-header__sidebar-toggle svg {
	width: 20px;
	height: 20px;
}

/* ------------------------- Mobile header rows -------------------------- *
 * Hidden entirely on desktop (see the max-width: 960px media query,
 * which is the ONLY place these get display: flex) -- row 2 (log
 * in/out + theme switch) and row 3 (search + categories toggle) stack
 * underneath row 1 (logo + nav-offcanvas hamburger, which is just
 * .hmd-header__inner reused as-is). */

.hmd-header__mobile-row {
	display: none;
	align-items: center;
	gap: 12px;
	padding: 10px 16px;
	border-top: 1px solid var(--hmd-border);
}

.hmd-header__mobile-row--utils {
	justify-content: space-between;
}

.hmd-header__mobile-row--search {
	justify-content: stretch;
}

.hmd-header__mobile-row--search .hmd-sidebar__search {
	flex: 1;
	margin-bottom: 0;
}

/* ---------------------- Right-hand nav offcanvas ------------------------ *
 * Fixed, full-screen container; the dark overlay and the sliding panel
 * are both children so one .is-open toggle on the container drives
 * both at once via descendant selectors. Desktop never sees this at
 * all in practice (nothing opens it there), but it's kept
 * pointer-events: none while closed as a defensive measure regardless
 * of viewport width. */

.hmd-nav-offcanvas {
	position: fixed;
	inset: 0;
	z-index: 80;
	pointer-events: none;
}

.hmd-nav-offcanvas__overlay {
	position: absolute;
	inset: 0;
	background: rgba(0, 0, 0, 0.45);
	opacity: 0;
	transition: opacity 0.2s ease;
}

.hmd-nav-offcanvas__panel {
	position: absolute;
	top: 0;
	right: 0;
	bottom: 0;
	width: 280px;
	max-width: 82vw;
	background: var(--hmd-bg);
	box-shadow: var(--hmd-shadow);
	padding: 20px 16px;
	transform: translateX(100%);
	transition: transform 0.2s ease;
	overflow-y: auto;
}

.hmd-nav-offcanvas.is-open {
	pointer-events: auto;
}

.hmd-nav-offcanvas.is-open .hmd-nav-offcanvas__overlay {
	opacity: 1;
}

.hmd-nav-offcanvas.is-open .hmd-nav-offcanvas__panel {
	transform: translateX(0);
}

.hmd-nav-offcanvas__close {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 34px;
	height: 34px;
	margin-left: auto;
	margin-bottom: 12px;
	background: none;
	border: 1px solid var(--hmd-border);
	border-radius: 8px;
	color: var(--hmd-text);
	cursor: pointer;
}

.hmd-nav-offcanvas__close svg {
	width: 18px;
	height: 18px;
}

.hmd-nav-offcanvas__nav .hmd-header__menu {
	flex-direction: column;
	gap: 4px;
}

.hmd-nav-offcanvas__nav .hmd-header__menu a {
	display: block;
	padding: 10px 8px;
	border-radius: 6px;
}

.hmd-nav-offcanvas__nav .hmd-header__menu a:hover {
	background: var(--hmd-accent-soft);
}

/* Log in/out, now living inside the nav drawer instead of its own
   mobile header row — separated from the menu links with a divider
   and stretched to the full width of the panel so it reads as a
   distinct action, not just another link. */
.hmd-nav-offcanvas__auth {
	margin-top: 16px;
	padding-top: 16px;
	border-top: 1px solid var(--hmd-border);
}

.hmd-nav-offcanvas__auth .hmd-header__auth-link {
	display: flex;
	width: 100%;
}

/* -------------------------------- Shell -------------------------------- */

.hmd-shell {
	display: flex;
	align-items: flex-start;
	max-width: 1400px;
	margin: 0 auto;
}

.hmd-sidebar {
	width: var(--hmd-sidebar-width);
	flex-shrink: 0;
	position: sticky;
	top: var(--hmd-header-height);
	height: calc(100vh - var(--hmd-header-height));
	overflow-y: auto;
	border-right: 1px solid var(--hmd-border);
	padding: 24px 16px;
}

/* Mobile-only close (×) button inside the categories drawer — see the
   max-width media query for where it actually becomes visible. On
   desktop the sidebar is a normal static column, so it's never shown.
   There's deliberately no dark overlay/backdrop behind the drawer: it
   isn't modal, so the page stays visible and scrollable while it's
   open (tap the × or a category link to close it instead). */
.hmd-sidebar__close {
	display: none;
	align-items: center;
	justify-content: center;
	width: 34px;
	height: 34px;
	margin-left: auto;
	margin-bottom: 12px;
	background: none;
	border: 1px solid var(--hmd-border);
	border-radius: 8px;
	color: var(--hmd-text);
	cursor: pointer;
}

.hmd-sidebar__close svg {
	width: 18px;
	height: 18px;
}

.hmd-sidebar-category {
	margin-bottom: 6px;
}

/* Accordion toggle — a real <button> for keyboard/screen-reader
   accessibility, styled to look like the plain label it replaces. */
.hmd-sidebar-category__label {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 8px;
	width: 100%;
	background: none;
	border: none;
	font: inherit;
	font-size: 12px;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.05em;
	color: var(--hmd-text-muted);
	padding: 8px 10px;
	margin: 0;
	cursor: pointer;
	border-radius: 6px;
	text-align: left;
}

.hmd-sidebar-category__label:hover {
	background: var(--hmd-accent-soft);
	color: var(--hmd-accent);
}

.hmd-sidebar-category__chevron {
	/* The inline <svg> has no width/height attribute (only a viewBox),
	   so without an explicit size here the browser falls back to its
	   default intrinsic SVG size (300x150) and a flex item with no
	   basis stretches to fit — the chevron was rendering many times
	   larger than the sidebar itself, overlapping the category label.
	   Fixing the box size (matching the 12x8 viewBox's aspect ratio)
	   keeps it a small, well-behaved icon. */
	width: 10px;
	height: 7px;
	flex: 0 0 auto;
	transition: transform 0.15s ease;
	color: var(--hmd-text-muted);
}

.hmd-sidebar-category.is-open > .hmd-sidebar-category__label .hmd-sidebar-category__chevron {
	transform: rotate(180deg);
}

/* Collapsible panel, animated with CSS Grid's "0fr <-> 1fr" trick
   instead of a JS-measured max-height. The old approach (app.js
   reading scrollHeight and setting it as an inline max-height) broke
   for nested categories: a parent's max-height was frozen to whatever
   its content measured BEFORE any child was ever expanded, so
   expanding a child later had nowhere to grow into and got silently
   clipped — and worse, confirmed live via getAnimations() that the
   max-height transition itself could get stuck mid-animation
   (playState "running", currentTime frozen at 0), which per spec
   means the transition's OWN animated value overrides literally any
   author-set value on that property, inline !important included, for
   as long as it's stuck. A grid row track doesn't have either problem:
   0fr/1fr always represents "give this row none/all of the leftover
   space its content wants", recalculated by the browser's own layout
   on every frame — there's no fixed pixel number to go stale, and
   nothing for any JS to measure or get wrong, at any nesting depth. */
.hmd-sidebar-category__panel {
	display: grid;
	grid-template-rows: 0fr;
	transition: grid-template-rows 0.2s ease;
}

.hmd-sidebar-category.is-open > .hmd-sidebar-category__panel {
	grid-template-rows: 1fr;
}

/* The single grid item the trick needs: min-height: 0 lets it actually
   shrink to nothing when its row is 0fr (grid items default to
   min-height: auto, which would otherwise refuse to collapse below
   its own content's natural height), and overflow: hidden clips that
   content while collapsed/mid-transition. */
.hmd-sidebar-category__panel-inner {
	min-height: 0;
	overflow: hidden;
}

.hmd-sidebar-category__docs {
	list-style: none;
	margin: 0;
	padding: 0;
}

.hmd-sidebar-category__docs a {
	display: block;
	padding: 7px 10px;
	border-radius: 6px;
	font-size: 14px;
	color: var(--hmd-text);
}

.hmd-sidebar-category__docs a:hover {
	background: var(--hmd-accent-soft);
	text-decoration: none;
}

.hmd-sidebar-category__docs a.is-current {
	background: var(--hmd-accent);
	color: #fff;
	font-weight: 600;
}

.hmd-sidebar-category__children {
	margin-left: 12px;
	border-left: 1px solid var(--hmd-border);
	padding-left: 6px;
}

.hmd-sidebar__empty {
	color: var(--hmd-text-muted);
	font-size: 14px;
	padding: 0 10px;
}

.hmd-main {
	flex: 1;
	min-width: 0;
	display: flex;
	align-items: flex-start;
	gap: 32px;
	padding: 32px;
	transition: opacity 0.15s ease;
}

/* Applied a beat after a SPA-style navigation starts (see app.js —
   deliberately delayed so a fast/cached load never flickers this).
   Without any of this the page just looked frozen while the next doc
   was being fetched, which read as the click "not working". */
.hmd-main.is-loading {
	opacity: 0.55;
	pointer-events: none;
}

/* A slim indeterminate progress bar pinned to the very top of the
   viewport — the same visual language browsers themselves use for
   page loads, so a SPA-style navigation still gives that familiar
   "something is happening" cue instead of feeling stuck. */
.hmd-nav-progress {
	position: fixed;
	top: 0;
	left: 0;
	width: 100%;
	height: 3px;
	z-index: 10000;
	background: transparent;
	pointer-events: none;
	opacity: 0;
}

.hmd-nav-progress::before {
	content: '';
	display: block;
	height: 100%;
	width: 30%;
	background: var(--hmd-accent, #4f46e5);
	border-radius: 0 2px 2px 0;
	transform: translateX(-100%);
}

.hmd-nav-progress.is-active {
	opacity: 1;
	transition: opacity 0.1s ease;
}

.hmd-nav-progress.is-active::before {
	animation: hmd-nav-progress-slide 1.1s ease-in-out infinite;
}

.hmd-nav-progress.is-done {
	opacity: 0;
	transition: opacity 0.25s ease 0.05s;
}

.hmd-nav-progress.is-done::before {
	animation: none;
	width: 100%;
	transform: translateX(0);
	transition: width 0.2s ease, transform 0.2s ease;
}

@keyframes hmd-nav-progress-slide {
	0% {
		transform: translateX(-100%);
	}
	50% {
		transform: translateX(150%);
	}
	100% {
		transform: translateX(320%);
	}
}

@media (prefers-reduced-motion: reduce) {
	.hmd-main {
		transition: none;
	}
	.hmd-nav-progress.is-active::before {
		animation: none;
		width: 100%;
	}
}

.hmd-page {
	max-width: 1000px;
	margin: 0 auto;
	padding: 40px 24px;
}

/* --------------------------- Empty doc list ---------------------------- */

.hmd-empty-doc-list {
	max-width: 420px;
	margin: 48px auto;
	text-align: center;
}

.hmd-empty-doc-list__icon {
	width: 40px;
	height: 40px;
	color: var(--hmd-text-muted);
	margin-bottom: 16px;
}

.hmd-empty-doc-list__title {
	font-size: 18px;
	font-weight: 700;
	color: var(--hmd-text);
	margin: 0 0 8px;
}

.hmd-empty-doc-list__text {
	font-size: 14px;
	color: var(--hmd-text-muted);
	margin: 0;
	line-height: 1.6;
}

/* --------------------- Empty state (no header/footer) ------------------ */

/*
 * Used when a visitor has literally nothing accessible to see on the
 * homepage, the all-docs archive, or a category page — no nav/search/
 * footer, no sidebar, just a small logo + log in/out bar plus the
 * empty-state note, vertically AND horizontally centered in whatever
 * viewport height that bar leaves behind.
 *
 * .hmd-empty-state-body is a full-height flex column (min-height:
 * 100vh, not height, so content taller than the viewport on very small
 * screens still isn't clipped) with exactly two children: the bar
 * (natural height) and .hmd-empty-fullpage (flex: 1). That's what lets
 * the note center itself in the REMAINING space below the bar rather
 * than in the full 100vh — centering on 100vh directly, with the bar
 * also present, would have pushed the total page taller than one
 * screen and left an awkward extra scroll for no reason.
 */
.hmd-empty-state-body {
	display: flex;
	flex-direction: column;
	min-height: 100vh;
}

.hmd-empty-fullpage__header {
	position: static;
	flex: none;
}

/* Same desktop look as .hmd-header__right, but intentionally never
   hidden by the (max-width: 960px) rule that hides .hmd-header__right
   on mobile — see the docblock in inc/template-functions.php's
   hypemilldoc_render_empty_state_page() for why: this bar IS the only
   header on this page at any width, so the toggle + log in/out link
   have to stay visible on mobile too, not just desktop. */
.hmd-empty-fullpage__header-right {
	display: flex;
	align-items: center;
	gap: 16px;
}

.hmd-empty-fullpage {
	flex: 1;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 24px;
	box-sizing: border-box;
	background: var(--hmd-bg);
}

.hmd-empty-fullpage .hmd-empty-doc-list {
	margin: 0;
}

/* -------------------------------- 404 --------------------------------- */

.hmd-404 {
	max-width: 480px;
	margin: 60px auto;
	text-align: center;
}

.hmd-404__code {
	font-size: 72px;
	font-weight: 800;
	line-height: 1;
	margin: 0 0 8px;
	color: var(--hmd-accent);
}

.hmd-404__title {
	font-size: 24px;
	font-weight: 700;
	margin: 0 0 12px;
	color: var(--hmd-text);
}

.hmd-404__text {
	font-size: 15px;
	color: var(--hmd-text-muted);
	margin: 0 0 28px;
	line-height: 1.6;
}

.hmd-404__search {
	max-width: 360px;
	margin: 0 auto 24px;
}

.hmd-404__search .hmd-sidebar__search {
	margin-bottom: 0;
}

.hmd-404__home {
	display: inline-flex;
	align-items: center;
	font-size: 14px;
	font-weight: 600;
	color: var(--hmd-accent);
}

/* -------------------------------- Doc -------------------------------- */

.hmd-doc {
	flex: 1;
	min-width: 0;
	max-width: 760px;
}

/* Category/search/all-docs listing pages have no ToC sibling — let the
   content column breathe a little wider and stay centered instead of
   hugging the left edge with dead space on the right. */
.hmd-main > .hmd-doc:only-child {
	max-width: 900px;
	margin: 0 auto;
}

/* Breadcrumb (left) and the Copy-as-Markdown toolbar (right) now share
   one row above the title — see hypemilldoc_render_doc_article(). */
.hmd-doc__meta-row {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	margin-bottom: 14px;
}

.hmd-doc__breadcrumb {
	font-size: 13px;
	color: var(--hmd-text-muted);
}

.hmd-doc__breadcrumb a {
	color: var(--hmd-text-muted);
}

.hmd-doc__header {
	display: flex;
	align-items: center;
	gap: 12px;
	margin-bottom: 16px;
}

.hmd-doc__title {
	font-size: 32px;
	font-weight: 800;
	margin: 0;
	line-height: 1.25;
}

.hmd-doc__toolbar {
	display: flex;
	justify-content: flex-end;
	flex-shrink: 0;
}

.hmd-copy-md {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	background: var(--hmd-bg-subtle);
	border: 1px solid var(--hmd-border);
	color: var(--hmd-text);
	font-size: 13px;
	font-weight: 500;
	padding: 7px 14px;
	border-radius: 8px;
	cursor: pointer;
}

.hmd-copy-md__icon {
	width: 15px;
	height: 15px;
	flex-shrink: 0;
}

.hmd-copy-md:hover {
	background: var(--hmd-accent-soft);
	border-color: var(--hmd-accent);
	color: var(--hmd-accent);
}

/* -------------------------------- ToC -------------------------------- */

.hmd-toc-wrap {
	width: var(--hmd-toc-width);
	flex-shrink: 0;
	position: sticky;
	top: calc(var(--hmd-header-height) + 32px);
	/* Long docs can have more headings than fit in one screen. Without
	   its own height limit + scroll, a sticky element just keeps
	   growing downward past the viewport — the "active" heading link
	   can end up rendered below the fold with nothing to scroll it
	   into view except scrolling the whole page (which doesn't move a
	   sticky element). Giving the ToC its own scroll area keeps every
	   item, including the active one, reachable. */
	max-height: calc(100vh - var(--hmd-header-height) - 64px);
	overflow-y: auto;
}

.hmd-toc__label {
	font-size: 12px;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.05em;
	color: var(--hmd-text-muted);
	margin-bottom: 10px;
}

/* The ToC is now a genuine nested tree — hypemilldoc_build_toc_tree()
   wraps each heading's children in their own <ul class="hmd-toc__list">
   nested inside the parent <li>. Indentation therefore comes from real
   ancestor/descendant nesting (one padding-left step per <ul> level),
   not from a flat per-heading-level lookup table like before — a
   heading's visual depth now always matches how deep it's actually
   nested under its parents, however many or few levels that is. */
.hmd-toc__list {
	list-style: none;
	margin: 0;
	padding: 0;
}

.hmd-toc__list--root {
	border-left: 2px solid var(--hmd-border);
}

.hmd-toc__item .hmd-toc__list {
	padding-left: 14px;
}

.hmd-toc__item a {
	display: block;
	padding: 5px 0 5px 14px;
	font-size: 13px;
	color: var(--hmd-text-muted);
	border-left: 2px solid transparent;
	margin-left: -2px;
}

/* Direct-child combinator ("> a"), not a plain descendant selector —
   a heading's own level class must only style ITS OWN link, never a
   nested child's link that happens to live inside the same <li>. H1
   and H2 get a visual weight bump so a doc that genuinely uses both as
   real top-level/second-level sections (e.g. the API doc) can actually
   tell them apart, instead of both looking identical as before. */
.hmd-toc__item--h1 > a {
	font-weight: 600;
	color: var(--hmd-text);
}

.hmd-toc__item--h2 > a {
	font-weight: 500;
}

.hmd-toc__item a:hover,
.hmd-toc__item a.is-active {
	color: var(--hmd-accent);
	border-left-color: var(--hmd-accent);
	text-decoration: none;
}

/* ------------------------------- Landing ------------------------------- */

.hmd-landing {
	max-width: 1000px;
	margin: 0 auto;
	padding: 60px 24px;
}

.hmd-landing__hero {
	text-align: center;
	margin-bottom: 48px;
}

.hmd-landing__hero h1 {
	font-size: 40px;
	margin-bottom: 8px;
}

.hmd-landing__hero p {
	color: var(--hmd-text-muted);
	font-size: 18px;
	margin-bottom: 24px;
}

.hmd-landing__search {
	display: flex;
	justify-content: center;
	gap: 8px;
}

.hmd-landing__search input {
	width: 360px;
	max-width: 100%;
	padding: 12px 16px;
	border-radius: 8px;
	border: 1px solid var(--hmd-border);
	font-size: 15px;
}

.hmd-landing__search button {
	padding: 12px 20px;
	border-radius: 8px;
	border: none;
	background: var(--hmd-accent);
	color: #fff;
	font-weight: 600;
	cursor: pointer;
}

.hmd-landing__categories {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
	gap: 20px;
}

.hmd-landing__category-card {
	display: block;
	padding: 20px;
	border: 1px solid var(--hmd-border);
	border-radius: 12px;
	background: var(--hmd-bg-subtle);
	color: var(--hmd-text);
}

.hmd-landing__category-card:hover {
	border-color: var(--hmd-accent);
	text-decoration: none;
}

.hmd-landing__category-card h2 {
	font-size: 17px;
	margin: 0 0 6px;
}

.hmd-landing__category-card p {
	font-size: 14px;
	color: var(--hmd-text-muted);
	margin: 0;
}

/* ------------------------------ Doc listing ------------------------------ */

.hmd-doc-list__intro {
	color: var(--hmd-text-muted);
	margin-bottom: 24px;
}

.hmd-doc-list {
	display: flex;
	flex-direction: column;
	gap: 12px;
}

.hmd-doc-list__item {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	padding: 16px 20px;
	border: 1px solid var(--hmd-border);
	border-radius: 10px;
	background: var(--hmd-bg-subtle);
	color: var(--hmd-text);
}

.hmd-doc-list__item:hover {
	border-color: var(--hmd-accent);
	text-decoration: none;
}

.hmd-doc-list__item-main h3 {
	margin: 0 0 4px;
	font-size: 16px;
}

.hmd-doc-list__item-main p {
	margin: 0;
	font-size: 14px;
	color: var(--hmd-text-muted);
}

.hmd-pagination {
	display: flex;
	gap: 6px;
	margin-top: 24px;
}

.hmd-pagination a,
.hmd-pagination span {
	display: inline-block;
	padding: 6px 12px;
	border: 1px solid var(--hmd-border);
	border-radius: 6px;
	font-size: 14px;
	color: var(--hmd-text);
}

.hmd-pagination .current {
	background: var(--hmd-accent);
	border-color: var(--hmd-accent);
	color: #fff;
}

/* ------------------------------- Auth pages ------------------------------- */

.hmd-auth {
	display: flex;
	justify-content: center;
	padding: 60px 20px;
}

.hmd-auth-card {
	width: 100%;
	max-width: 400px;
	background: var(--hmd-bg-subtle);
	border: 1px solid var(--hmd-border);
	border-radius: 14px;
	padding: 36px 32px;
}

.hmd-auth-card__title {
	font-size: 24px;
	font-weight: 800;
	margin: 0 0 6px;
	text-align: center;
}

.hmd-auth-card__subtitle {
	color: var(--hmd-text-muted);
	text-align: center;
	margin: 0 0 24px;
	font-size: 14px;
}

.hmd-auth-notice {
	padding: 10px 14px;
	border-radius: 8px;
	font-size: 13px;
	margin-bottom: 20px;
}

.hmd-auth-notice--error {
	background: #fdecec;
	color: #c0392b;
}

.hmd-auth-notice--success {
	background: #e7f7ec;
	color: #147a3d;
}

.hmd-auth-form {
	display: flex;
	flex-direction: column;
	gap: 16px;
}

.hmd-auth-field {
	display: flex;
	flex-direction: column;
	gap: 6px;
	font-size: 13px;
	font-weight: 600;
	color: var(--hmd-text);
}

.hmd-auth-field input {
	padding: 10px 12px;
	border-radius: 8px;
	border: 1px solid var(--hmd-border);
	background: var(--hmd-bg);
	color: var(--hmd-text);
	font-size: 14px;
	font-family: inherit;
	font-weight: 400;
}

.hmd-auth-field input:focus {
	outline: none;
	border-color: var(--hmd-accent);
	box-shadow: 0 0 0 3px var(--hmd-accent-soft);
}

.hmd-auth-checkbox {
	display: flex;
	align-items: center;
	gap: 8px;
	font-size: 13px;
	color: var(--hmd-text-muted);
}

.hmd-auth-submit {
	background: var(--hmd-accent);
	color: #fff;
	border: none;
	border-radius: 8px;
	padding: 11px 16px;
	font-size: 14px;
	font-weight: 600;
	cursor: pointer;
	margin-top: 4px;
}

.hmd-auth-submit:hover {
	opacity: 0.92;
}

.hmd-auth-links {
	text-align: center;
	margin-top: 22px;
	font-size: 13px;
}

.hmd-auth-links a {
	color: var(--hmd-text-muted);
}

.hmd-auth-links__sep {
	margin: 0 6px;
	color: var(--hmd-border);
}

/* -------------------------------- Footer -------------------------------- */

.hmd-footer {
	border-top: 1px solid var(--hmd-border);
	padding: 24px;
	text-align: center;
	color: var(--hmd-text-muted);
	font-size: 13px;
}

/* Desktop-only: logo stays left, nav is lifted out of the normal flex
   flow with position: absolute and centered against .hmd-header__inner
   (its nearest positioned ancestor), and the utility group (theme
   switch + log in/out button) stays right via .hmd-header__inner's
   own space-between layout. Below 961px this whole rule is skipped
   entirely -- .hmd-header__nav and #hmd-header-right both go
   display: none instead (see the max-width media query), replaced by
   the dedicated mobile rows + offcanvas panels. */
@media (min-width: 961px) {
	.hmd-header__inner {
		position: relative;
	}

	.hmd-header__nav {
		position: absolute;
		left: 50%;
		top: 50%;
		transform: translate(-50%, -50%);
	}
}

/* ------------------------------ Responsive ------------------------------ */

@media (max-width: 1200px) {
	.hmd-toc-wrap {
		display: none;
	}
}

@media (max-width: 960px) {
	/* The desktop-only nav + utility group are replaced wholesale by
	   the mobile rows and the two offcanvas panels below -- nothing
	   about them (including the old dropdown-panel behaviour) is
	   reused at this width. */
	.hmd-header__nav,
	.hmd-header__right {
		display: none;
	}

	.hmd-header__menu-toggle,
	.hmd-header__sidebar-toggle {
		display: flex;
	}

	.hmd-header__mobile-controls {
		display: flex;
	}

	.hmd-header__mobile-row {
		display: flex;
	}

	/* The sidebar's OWN search form (desktop) is hidden on mobile --
	   search now lives in row 3 of the mobile header instead (see
	   .hmd-header__mobile-row--search in header.php), since the
	   sidebar itself becomes a categories-only offcanvas drawer. */
	.hmd-sidebar > .hmd-sidebar__search {
		display: none;
	}

	.hmd-sidebar__close {
		display: flex;
	}

	/* --hmd-header-height (64px) is a single-row measurement — no
	   longer accurate once the mobile header grows to 3 stacked rows,
	   so .hmd-header can't keep a fixed height at this width. Letting
	   it size to its actual (auto) content height means anything that
	   positioned itself "just below the header" using that variable
	   would now sit at the wrong offset — rather than trying to keep a
	   second, mobile-specific height variable in sync, both offcanvas
	   drawers (nav and categories) simply cover the FULL viewport
	   (top: 0) instead of starting below the header. That's a standard
	   pattern for mobile drawers anyway, and sidesteps the measurement
	   problem entirely. */
	.hmd-header {
		height: auto;
		/* On mobile the FULL 3-row header no longer sticks — only the
		   search row (row 3) does, right below. Keeping the whole
		   header pinned ate too much vertical space on small screens
		   and pinned rows (logo, login/theme toggle) nobody needed
		   while scrolling a doc. */
		position: static;
	}

	.hmd-header__inner {
		height: auto;
		padding: 12px 16px;
	}

	.hmd-header__mobile-row--search {
		position: sticky;
		top: 0;
		z-index: 50;
		background: var(--hmd-header-bg);
	}

	.hmd-shell {
		position: relative;
	}

	.hmd-sidebar {
		position: fixed;
		top: 0;
		left: 0;
		bottom: 0;
		/* The base (desktop) rule above sets an explicit
		   height: calc(100vh - var(--hmd-header-height)) — for an
		   absolutely/fixed-positioned box, once top/height/bottom are
		   ALL specified, height wins and bottom is ignored, so without
		   this override the drawer was stuck at that shorter desktop
		   height instead of actually reaching bottom: 0. That's exactly
		   what showed up as empty space below the drawer once its
		   (too-short) box ended partway down the screen. height: 100vh
		   makes top/height agree instead of fighting bottom. */
		height: 100vh;
		/* Mobile-only: the base rule no longer sets a background (removed
		   so the DESKTOP static column blends into the page), but this
		   drawer overlays real page content when open, so it still needs
		   to be opaque here. */
		background: var(--hmd-bg-sidebar);
		/* Above the sticky search row (z-index: 50, see
		   .hmd-header__mobile-row--search) -- otherwise the open drawer
		   was rendering BEHIND that sticky bar instead of over it. */
		z-index: 60;
		transform: translateX(-100%);
		transition: transform 0.2s ease;
		box-shadow: var(--hmd-shadow);
	}

	.hmd-sidebar.is-open {
		transform: translateX(0);
	}

	.hmd-main {
		padding: 20px;
	}

	.hmd-doc__title {
		font-size: 24px;
	}

	/* Copy as Markdown is a desktop/copy-paste convenience — dropped on
	   mobile rather than squeezed next to the breadcrumb. */
	.hmd-doc__toolbar {
		display: none;
	}
}

/* Locks background scrolling while either offcanvas panel (nav or
   categories) is open, applied/removed by app.js. */
body.hmd-no-scroll {
	overflow: hidden;
}

/* -------------------------- Image lightbox -------------------------- */
/* Built once and reused by assets/js/lightbox-init.js for every image
   inside a doc's content. z-index 20000 clears the top-of-page nav
   progress bar (10000, see .hmd-nav-progress above) and everything
   else on the page — this is the topmost thing that can ever be on
   screen. Background scroll is locked the same way the offcanvas
   panels already do it (body.hmd-no-scroll), applied/removed by the
   script itself. */
.hmd-lightbox {
	display: none;
	position: fixed;
	inset: 0;
	z-index: 20000;
	background: rgba( 10, 10, 14, 0.92 );
	align-items: center;
	justify-content: center;
	padding: 56px 72px;
}

.hmd-lightbox.is-open {
	display: flex;
}

html.hmd-lightbox-open {
	overflow: hidden;
}

.hmd-lightbox__figure {
	margin: 0;
	max-width: 100%;
	max-height: 100%;
	display: flex;
	flex-direction: column;
	align-items: center;
}

.hmd-lightbox__img {
	display: block;
	max-width: 100%;
	max-height: calc( 100vh - 160px );
	border-radius: 6px;
	box-shadow: 0 12px 40px rgba( 0, 0, 0, 0.5 );
}

/* Holds a cloned <svg> when the lightbox is showing a Mermaid diagram
   instead of an <img> — lightbox-init.js toggles which of the two is
   visible per item. A diagram can be much wider than tall (a long
   flowchart) or the reverse, so this scrolls in both directions at
   the diagram's own natural size rather than distorting it to fit;
   the near-full-viewport overlay is already a big jump up from the
   inline card, which is the "zoom" a reader actually wants here — a
   flowchart's node text doesn't get any more readable by stretching
   the SVG beyond its own rendered proportions. */
.hmd-lightbox__svg-host {
	/* "width", not just "max-width" — found live: as a flex child of
	   .hmd-lightbox__figure (align-items: center, not stretch), a plain
	   max-width left this div free to shrink-to-fit its own content
	   instead of actually taking that width, and Mermaid's SVG (which
	   itself has width="100%" plus an inline max-width from its ORIGINAL
	   small inline-card rendering) had nothing real to fill — so
	   "zooming" a diagram rendered it at basically the same small size
	   as inline, just sitting inside a bigger dark overlay. A real
	   width here is what the SVG's own width:100% actually resolves
	   against. */
	width: min( 92vw, 1100px );
	max-height: calc( 100vh - 160px );
	position: relative;
	/* Back to a plain scrolling box — this is the default, on-open
	   presentation the reader should always land on, matching how it
	   looked before pinch/drag-pan was ever added. Zoom is now driven
	   ONLY by the +/−/1:1 buttons (see lightbox-init.js), which just
	   scale the SVG in place; overflow: auto is what makes anything
	   that ends up taller/wider than the host once scaled up still
	   reachable, via the browser's own scrollbars, instead of needing
	   a custom pan gesture to get there.
	   Background/padding/shadow now live here unconditionally (used to
	   only apply while actively panning, which meant the default,
	   just-opened view had NO background at all behind a diagram — the
	   dark overlay showed straight through, and a dark-theme diagram
	   with light text and no background of its own was unreadable
	   against it). Matches .hmd-mermaid's own background (see
	   blocks.css) rather than a hardcoded white/black, so it's
	   consistent with the inline card either way. */
	overflow: auto;
	background: var( --hmd-code-bg, #f4f4f7 );
	border-radius: 8px;
	padding: 20px;
	box-shadow: 0 12px 40px rgba( 0, 0, 0, 0.5 );
}

.hmd-lightbox__svg-host svg {
	display: block;
	/* Zoom is a real WIDTH change (see setSvgZoom() in lightbox-init.js),
	   not a CSS transform: scale() — found live, a transform only
	   changes how something is PAINTED, never the layout size the
	   browser uses to compute this host's own scrollWidth/scrollHeight.
	   A scaled-up diagram rendered visually bigger but the overflow:auto
	   box's actual scrollable area never grew to match, so panning to
	   the parts that now stuck out past the visible edge was flat-out
	   impossible — there was nowhere for the scrollbar to go. Resizing
	   the SVG for real (height: auto lets it keep its own aspect ratio)
	   is what an enlarged photo in a normal image lightbox does too,
	   and it's what actually gives the scrollbars something bigger to
	   scroll. A short transition so the +/−/1:1 buttons ease into their
	   new size instead of jumping instantly. */
	height: auto;
	transition: width 0.15s ease;
}

.hmd-lightbox__zoom-controls {
	position: absolute;
	bottom: 18px;
	right: 18px;
	display: flex;
	gap: 6px;
}

.hmd-lightbox__zoom-btn {
	width: 36px;
	height: 36px;
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: 8px;
	background: rgba( 255, 255, 255, 0.08 );
	border: 1px solid rgba( 255, 255, 255, 0.16 );
	color: #fff;
	font-size: 15px;
	font-family: var( --hmd-font-sans, sans-serif );
	cursor: pointer;
	padding: 0;
	transition: background 0.15s ease;
}

.hmd-lightbox__zoom-btn:hover {
	background: rgba( 255, 255, 255, 0.18 );
}

.hmd-lightbox__zoom-reset {
	font-size: 11px;
	font-weight: 600;
}

@media ( max-width: 640px ) {
	.hmd-lightbox__zoom-controls {
		bottom: 12px;
		right: 12px;
	}
}

.hmd-lightbox__caption {
	margin-top: 14px;
	color: rgba( 255, 255, 255, 0.75 );
	font-size: 13px;
	text-align: center;
	max-width: 70ch;
}

.hmd-lightbox__count {
	position: absolute;
	bottom: 18px;
	left: 0;
	right: 0;
	text-align: center;
	color: rgba( 255, 255, 255, 0.55 );
	font-size: 12px;
}

.hmd-lightbox__close,
.hmd-lightbox__nav {
	position: absolute;
	display: flex;
	align-items: center;
	justify-content: center;
	background: rgba( 255, 255, 255, 0.08 );
	border: 1px solid rgba( 255, 255, 255, 0.16 );
	color: #fff;
	border-radius: 999px;
	cursor: pointer;
	padding: 0;
	transition: background 0.15s ease;
}

.hmd-lightbox__close:hover,
.hmd-lightbox__nav:hover {
	background: rgba( 255, 255, 255, 0.18 );
}

.hmd-lightbox__close {
	top: 18px;
	right: 18px;
	width: 40px;
	height: 40px;
}

.hmd-lightbox__close svg {
	width: 18px;
	height: 18px;
}

.hmd-lightbox__nav {
	top: 50%;
	width: 48px;
	height: 48px;
	transform: translateY( -50% );
}

.hmd-lightbox__nav svg {
	width: 20px;
	height: 20px;
}

.hmd-lightbox__nav--prev {
	left: 18px;
}

.hmd-lightbox__nav--next {
	right: 18px;
}

@media ( max-width: 640px ) {
	.hmd-lightbox {
		padding: 88px 16px 40px;
	}

	.hmd-lightbox__nav {
		width: 40px;
		height: 40px;
	}

	.hmd-lightbox__close {
		top: 12px;
		right: 12px;
	}

	.hmd-lightbox__nav--prev {
		left: 8px;
	}

	.hmd-lightbox__nav--next {
		right: 8px;
	}
}
