/* Pryanic's own layer, on top of uikit's theme variables.
   Every colour is a --mass-* token, so a theme switch restyles the whole site
   without touching this file.

   uikit's theme.css ends with a slice of Tailwind's Preflight, including:

       h1, h2, h3, h4, h5, h6 { font-size: inherit; font-weight: inherit; }
       h1, h2, h3, h4, h5, h6, p, figure, blockquote, dl, dd { margin: 0; }

   So every heading here must state its size, weight AND margin explicitly.
   Leaving any of them out is why headings render as plain body text. */

:root {
	/* One column for the whole site, set by the one thing with a right answer:
	   the reading measure of an article body. Lists, admin and the footer line
	   up with the prose instead of framing it, and the page is the measure plus
	   its own gutters so the text keeps exactly the width it had. The editor
	   opts out below — two panes side by side want the screen. */
	--pry-measure: 46rem;
	--pry-gutter: 24px;
	--pry-page: calc(var(--pry-measure) + var(--pry-gutter) * 2);
	/* One editor pane, sized so the prose inside it is exactly --pry-measure —
	   the preview then breaks its lines where the published page will, which is
	   the only reason to keep a preview at all. The addition is the pane's own
	   frame (14px padding and a 1px border each side) plus the 4px the preview
	   keeps clear for its scrollbar. Two of these need about 1600px of window;
	   under that both panes shrink together, so the preview stays narrower than
	   the article rather than wrong on one side only. */
	--pry-pane: calc(var(--pry-measure) + 34px);
	--pry-radius: 10px;
	--pry-radius-sm: 7px;
	--pry-border: 1px solid var(--mass-border);
}

body {
	margin: 0;
	color: var(--mass-text);
	font: 16px/1.65 ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
	-webkit-font-smoothing: antialiased;
}

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

a:hover {
	text-decoration: underline;
}

::selection {
	background: var(--mass-accent-soft);
}

/* ── Shell ─────────────────────────────────────────────────────────────── */

.pry-shell {
	display: flex;
	flex-direction: column;
	min-height: 100dvh;
}

.pry-wrap {
	width: 100%;
	max-width: var(--pry-page);
	margin-inline: auto;
	padding-inline: var(--pry-gutter);
}

/* main and its wrap are flex columns so a page that wants the leftover height
   can ask for it with flex: 1. For every other page this changes nothing —
   block children stack the same either way — but without the chain a full-height
   editor has no container height to resolve against. */
.pry-main {
	flex: 1;
	min-height: 0;
	display: flex;
	flex-direction: column;
	padding-block: 40px 72px;
}

.pry-main > .pry-wrap {
	flex: 1;
	min-height: 0;
	display: flex;
	flex-direction: column;
}

/* ── Header ────────────────────────────────────────────────────────────── */

.pry-header {
	position: sticky;
	top: 0;
	z-index: 10;
	/* A list is something you scan, so the way home follows you down it. */
	border-bottom: var(--pry-border);
	background: color-mix(in srgb, var(--mass-bg-base) 88%, transparent);
	backdrop-filter: blur(8px);
}

/* An article is something you read, and a bar tracking the top of the text for
   twenty screens is in the way. Unscripted it scrolls off with everything else,
   and the reader gets it back at the top of the page. */
.pry-loose {
	position: static;
}

/* Scripted, it does better than either: pinned everywhere, and out of the way
   going down. header.js adds this class, so the rules above stay what a page
   with no JavaScript gets. */
.pry-header-auto {
	position: sticky;
	top: 0;
	transition: transform 0.22s ease;
	will-change: transform;
}

.pry-header-auto.pry-header-away {
	transform: translateY(-100%);
}

/* A control inside it took focus from the keyboard, and a tab stop off screen is
   not usable at all. :focus-visible rather than :focus-within, because a pointer
   focuses what it clicks: the theme swatches prevent their own navigation, so a
   click left focus sitting in the bar and this rule pinned it open for the rest
   of the visit. */
.pry-header-auto:has(:focus-visible) {
	transform: none;
}

@media (prefers-reduced-motion: reduce) {
	.pry-header-auto {
		transition: none;
	}
}

/* Three columns so the title is centred on the page, not in the space the other
   two leave. Both edges are placed by line number: a site with no title leaves
   the middle empty rather than pulling the controls inward. */
.pry-header-inner {
	display: grid;
	grid-template-columns: 1fr auto 1fr;
	align-items: center;
	gap: 24px;
	min-height: 76px;
}

.pry-header-right {
	grid-column: 3;
	justify-self: end;
	display: flex;
	align-items: center;
	gap: 16px;
}

/* The site name, which is a reader's whole header: they have one page, so there
   is no nav — this is the way home from an article. MASS's brand mark: the
   monospace stack at 800 with wide tracking and a halo in the theme accent. Its
   two display faces cover digits only, so a title of letters falls through to
   exactly this stack — no font to ship. */
.pry-brand {
	grid-column: 2;
	justify-self: center;
	display: inline-block;
	color: var(--mass-text);
	font: 800 30px/1.1 ui-monospace, "JetBrains Mono", Menlo, Consolas, monospace;
	letter-spacing: 0.12em;
	/* Tracking is added after the last letter too; pull it back so the centring
	   is optical rather than arithmetic. */
	margin-right: -0.12em;
	text-shadow: 0 0 18px var(--mass-accent-soft), 0 0 42px var(--mass-accent-soft);
	white-space: nowrap;
	/* A glitch, not an animation: still for seven seconds in eight, then two
	   frames of skew. Keyframes rather than a script, so it runs with JS off
	   and costs nothing to maintain. */
	animation: pry-glitch 8s infinite;
}

.pry-brand:hover {
	color: var(--mass-accent);
	text-decoration: none;
}

@keyframes pry-glitch {
	0%, 74.9% {
		opacity: 1;
		transform: none;
		text-shadow: none;
	}
	75% {
		opacity: 0.72;
		transform: skewX(-5deg) translateX(-1px);
		text-shadow: 1px 0 0 var(--mass-accent-soft), -1px 0 0 var(--mass-accent-soft);
	}
	76.2% {
		opacity: 1;
		transform: none;
		text-shadow: none;
	}
	77% {
		opacity: 0.82;
		transform: skewX(3deg) translateX(1px);
	}
	78%, 100% {
		opacity: 1;
		transform: none;
		text-shadow: none;
	}
}

/* A flicker is exactly what this setting is for. Below the rule it overrides,
   since both name .pry-brand and the later one wins. */
@media (prefers-reduced-motion: reduce) {
	.pry-brand {
		animation: none;
	}
}

/* Nav at the left edge, theme picker pushed to the right by the margin below.
   Admin only. */
.pry-nav {
	display: flex;
	align-items: center;
	gap: 20px;
	font-size: 14.5px;
}

.pry-nav a {
	color: var(--mass-text-muted);
	padding-block: 4px;
	border-bottom: 2px solid transparent;
}

.pry-nav a:hover {
	color: var(--mass-text);
	text-decoration: none;
}

.pry-nav a[aria-current="page"] {
	color: var(--mass-text);
	border-bottom-color: var(--mass-accent);
}

/* Theme picker: plain links, so it works with JS off. */

.pry-themes {
	display: flex;
	gap: 7px;
	align-items: center;
}

.pry-swatch {
	width: 18px;
	height: 18px;
	border-radius: 50%;
	background: var(--sw);
	border: var(--pry-border);
	display: block;
}

.pry-swatch:hover {
	border-color: var(--mass-text-muted);
}

.pry-swatch[aria-current="true"] {
	outline: 2px solid var(--mass-accent);
	outline-offset: 2px;
}

/* ── Buttons ───────────────────────────────────────────────────────────── */

.pry-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 6px;
	padding: 8px 16px;
	border-radius: var(--pry-radius-sm);
	border: 1px solid transparent;
	font-size: 14.5px;
	font-weight: 600;
	line-height: 1.2;
	cursor: pointer;
	background: none;
	color: var(--mass-text);
	white-space: nowrap;
}

.pry-btn:hover {
	text-decoration: none;
}

.pry-btn-sm {
	padding: 5px 11px;
	font-size: 13.5px;
}

/* A button that is only its mark. Square, so three of them beside the theme
   picker still fit inside half the header's leftover width — which is what keeps
   the brand between them optically centred rather than shoved left. */
.pry-btn-icon {
	padding: 0;
	width: 32px;
	height: 32px;
	flex: none;
}

/* Where the author is. The same fill the selected tag chip uses, so "this one is
   on" looks the same wherever it appears. */
.pry-btn-icon[aria-current] {
	background: var(--mass-accent);
	border-color: var(--mass-accent);
	color: var(--mass-bg-base);
	box-shadow: var(--mass-glow-primary, none);
}

.pry-btn-icon[aria-current]:hover {
	background: var(--mass-accent);
	color: var(--mass-bg-base);
}

/* The label follows the theme's own fill ink, not white: a theme whose fill is
   the light source (Carbon's accent is #daf0fd) puts dark ink on it. */
/* These are plain <a>/<button>, not sl-button, so uikit's component rules never
   reach them — the glow hook has to be repeated here. Themes that set no halo
   fall back to none. */
.pry-btn-primary {
	background: var(--mass-accent-fill);
	color: var(--mass-fill-text);
	box-shadow: var(--mass-glow-primary, none);
}

.pry-btn-primary:hover {
	background: color-mix(in srgb, var(--mass-accent-fill) 86%, #000);
}

.pry-btn-ghost {
	border-color: var(--mass-border);
	color: var(--mass-text-muted);
}

.pry-btn-ghost:hover {
	border-color: var(--mass-accent);
	color: var(--mass-text);
	background: var(--mass-bg-hover);
}

/* The same frame every other button has: a destructive action is still an
   action, and a borderless one reads as a link beside two buttons — which on the
   confirm page left Cancel looking like the button and Delete like the caption.
   The ink carries the warning at rest; the red frame arrives on hover, where the
   pointer already is. */
.pry-btn-danger {
	border-color: var(--mass-border);
	color: var(--mass-danger);
}

.pry-btn-danger:hover {
	border-color: var(--mass-danger);
	background: var(--mass-danger-soft);
}

.pry-inline-form {
	display: inline-flex;
}

/* ── Page headings ─────────────────────────────────────────────────────── */

/* Present to a screen reader, absent to everything else. Not display:none and
   not visibility:hidden — both take the element out of the accessibility tree
   too, which is the opposite of the point. */
.pry-offscreen {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	border: 0;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

.pry-title {
	font-size: 30px;
	font-weight: 700;
	line-height: 1.2;
	letter-spacing: -0.025em;
	margin: 0 0 20px;
	color: var(--mass-text);
}

.pry-lede {
	color: var(--mass-text-muted);
	font-size: 15px;
	margin: -12px 0 22px;
}

/* ── Post list ─────────────────────────────────────────────────────────── */

.pry-list {
	display: flex;
	flex-direction: column;
	gap: 12px;
	list-style: none;
	margin: 0;
	padding: 0;
}

/* The feed stacks the first page, every page loaded after it, and the button —
   at the same gap the cards inside a page use, so a page boundary is invisible. */
.pry-feed {
	display: flex;
	flex-direction: column;
	gap: 12px;
}

.pry-more {
	display: flex;
	justify-content: center;
	padding-block: 8px;
}

/* The button ends the list, so the space under it should read as the gap the
   list left above it — not that gap plus the page's own bottom padding, which
   put it three times closer to the last card than to the footer. Only when
   there is a button: a page that ends in an article still wants the room. */
.pry-main:has(.pry-more:not(:empty)) {
	padding-bottom: 24px;
}

/* Both stay in the document when there is nothing to show, because the server
   patches them by id and an id it cannot find is a patch that lands nowhere.
   Empty, they must not take a row of the feed's gap. */
#post-more:empty,
.pry-more:empty {
	display: none;
}

.pry-card {
	position: relative;
	background: var(--mass-bg-panel);
	border: var(--pry-border);
	border-radius: var(--pry-radius);
	padding: 20px 22px;
	transition: border-color 0.15s ease, transform 0.15s ease;
}

.pry-card:hover {
	border-color: color-mix(in srgb, var(--mass-accent) 55%, transparent);
	transform: translateY(-1px);
}

.pry-card-title {
	font-size: 20px;
	font-weight: 650;
	line-height: 1.3;
	letter-spacing: -0.015em;
	margin: 0 0 8px;
}

.pry-card-title a {
	color: var(--mass-text);
}

/* The whole card opens the post, empty space included, without a second link or
   a click handler: the title's own anchor grows an overlay over the card. One
   link in the accessibility tree, one tab stop, and the href still shows in the
   status bar. The cost is that text inside the card can no longer be selected by
   dragging — the overlay swallows it. */
.pry-card-title a::after {
	content: "";
	position: absolute;
	inset: 0;
	border-radius: inherit;
}

/* Tags sit inside the card and must stay reachable, so lift them out from under
   the overlay. */
/* In a card the tags are a label on the date line, not a control — quieter and
   smaller than the filter chips above, which are. z-index lifts them out of the
   title's click overlay so they stay clickable. */
.pry-card .pry-tag,
.pry-article-header .pry-tag {
	position: relative;
	z-index: 1;
	padding: 1px 8px;
	font-size: 11.5px;
	background: transparent;
	border-color: var(--mass-border);
	color: var(--mass-text-faint);
}

.pry-card .pry-tag:hover,
.pry-article-header .pry-tag:hover {
	border-color: var(--mass-accent);
	color: var(--mass-accent);
}

/* Highlight the title from anywhere on the card, so it is obvious what the click
   is going to open. */
.pry-card:hover .pry-card-title a,
.pry-card-title a:hover {
	color: var(--mass-accent);
	text-decoration: none;
}

/* The overlay is invisible, so focus has to be drawn on the card it covers. */
.pry-card:has(.pry-card-title a:focus-visible) {
	outline: 2px solid var(--mass-accent);
	outline-offset: 2px;
}

.pry-card-title a:focus-visible {
	outline: none;
}

.pry-card-summary {
	margin: 10px 0 0;
	color: var(--mass-text-muted);
	font-size: 14.5px;
	line-height: 1.6;
	/* Summaries are one flattened paragraph; cap them so cards stay even. */
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

.pry-meta {
	display: flex;
	align-items: center;
	gap: 10px;
	flex-wrap: wrap;
	color: var(--mass-text-faint);
	font-size: 13px;
}

.pry-meta .pry-sep {
	opacity: 0.5;
}

/* A date reads short and hovers long: the full instant with its zone lives in
   data-full and is drawn here, so it takes the theme like everything else.
   Dotted underline because nothing else on the site says "there is more here"
   without also saying "this is a link". */
.pry-time {
	position: relative;
	text-decoration: underline dotted currentColor;
	text-underline-offset: 3px;
	text-decoration-thickness: 1px;
	opacity: 0.85;
}

/* Only where a pointer can hover. A touch device has no hover to end, so the
   bubble would open on a tap and stay. */
@media (hover: hover) {
	.pry-time::after {
		content: attr(data-full);
		position: absolute;
		/* Left-aligned rather than centred: every meta line starts at the page's
		   left edge, which is the one side the bubble cannot be clipped against. */
		left: 0;
		/* Below, not above. Above the date on an article is the title, and a
		   bubble across a 42px headline reads as a rendering fault; below is the
		   gap before the rule. Everywhere else it lands on body text, where a
		   floating bubble is what a reader expects. */
		top: calc(100% + 7px);
		z-index: 3;
		padding: 5px 9px;
		border: var(--pry-border);
		border-radius: var(--pry-radius-sm);
		background: var(--mass-bg-panel);
		/* It floats over content, so it needs to look like it does. */
		box-shadow: 0 4px 14px rgb(0 0 0 / 0.28);
		color: var(--mass-text);
		font-size: 12.5px;
		line-height: 1.3;
		white-space: nowrap;
		/* Not display:none — a hidden box cannot be transitioned, and this one
		   should fade rather than blink. pointer-events keeps it from eating the
		   hover that summoned it. */
		opacity: 0;
		visibility: hidden;
		pointer-events: none;
		transition: opacity 120ms ease, visibility 120ms;
	}

	.pry-time:hover::after {
		opacity: 1;
		visibility: visible;
	}
}

/* ── Tags ──────────────────────────────────────────────────────────────── */

.pry-tags {
	display: flex;
	gap: 6px;
	flex-wrap: wrap;
	list-style: none;
	margin: 0;
	padding: 0;
}

.pry-tag {
	display: inline-flex;
	align-items: center;
	gap: 5px;
	padding: 2px 10px;
	border-radius: 999px;
	background: var(--mass-badge-bg);
	color: var(--mass-badge-text);
	font-size: 12.5px;
	border: 1px solid transparent;
}

.pry-tag:hover {
	border-color: var(--mass-accent);
	color: var(--mass-accent);
	text-decoration: none;
}

.pry-tag-count {
	color: var(--mass-text-faint);
	font-variant-numeric: tabular-nums;
}

/* The tag filter on the index. Bigger than the tags in a post's meta line,
   because here they are the control rather than a label. */
.pry-filter {
	display: flex;
	gap: 7px;
	flex-wrap: wrap;
	margin: 0 0 22px;
}

.pry-filter .pry-tag {
	font-size: 13.5px;
	padding: 4px 13px;
}

.pry-filter .pry-tag[aria-current] {
	background: var(--mass-accent);
	color: var(--mass-bg-base);
	box-shadow: var(--mass-glow-primary, none);
}

.pry-filter .pry-tag[aria-current] .pry-tag-count {
	color: inherit;
	opacity: 0.75;
}

/* The long tail, behind the platform's own disclosure — no script, and it keeps
   its state while the page is open.
   order sends the toggle to the end of the row: the tail chips come after it in
   the markup, but "Less" belongs after the thing it closes. */
.pry-filter-more {
	order: 1;
}

.pry-filter-more > summary {
	display: inline-flex;
	align-items: center;
	padding: 4px 13px;
	border-radius: 999px;
	border: 1px dashed var(--mass-border);
	color: var(--mass-text-faint);
	font-size: 13.5px;
	cursor: pointer;
	list-style: none;
}

/* Safari draws its own triangle through ::-webkit-details-marker, which
   list-style alone does not remove. */
.pry-filter-more > summary::-webkit-details-marker {
	display: none;
}

.pry-filter-more > summary:hover {
	border-color: var(--mass-accent);
	color: var(--mass-accent);
}

.pry-filter-more > summary:focus-visible {
	outline: 2px solid var(--mass-accent);
	outline-offset: 2px;
}

/* The tail's wrapper dissolves when the disclosure is open, so its chips become
   flex items of the filter row and carry on from the head's last one instead of
   starting a line of their own. */
.pry-filter-rest {
	display: none;
}

.pry-filter-more[open] ~ .pry-filter-rest {
	display: contents;
}

/* Both labels ship; exactly one is shown. */
.pry-filter-more > summary .pry-more-close,
.pry-filter-more[open] > summary .pry-more-open {
	display: none;
}

.pry-filter-more[open] > summary .pry-more-close {
	display: inline;
}

/* ── Article ───────────────────────────────────────────────────────────── */

.pry-article-header {
	margin-bottom: 32px;
	padding-bottom: 24px;
	border-bottom: var(--pry-border);
}

.pry-article-title {
	font-size: clamp(30px, 4.4vw, 42px);
	font-weight: 750;
	line-height: 1.12;
	letter-spacing: -0.03em;
	margin: 0 0 14px;
	color: var(--mass-text);
}

/* Prose. Every heading restates size + weight + margin, because the preflight
   above zeroes all three. */

.pry-prose {
	font-size: 17px;
	line-height: 1.72;
	color: var(--mass-text);
}

.pry-prose h1,
.pry-prose h2,
.pry-prose h3,
.pry-prose h4,
.pry-prose h5,
.pry-prose h6 {
	color: var(--mass-text);
	letter-spacing: -0.02em;
	line-height: 1.25;
	font-weight: 700;
	margin: 2em 0 0.6em;
}

.pry-prose > :first-child {
	margin-top: 0;
}

.pry-prose h1 { font-size: 28px; }
.pry-prose h2 { font-size: 24px; }
.pry-prose h3 { font-size: 20px; }
.pry-prose h4 { font-size: 17.5px; }
.pry-prose h5,
.pry-prose h6 { font-size: 16px; }

.pry-prose p {
	margin: 0 0 1.15em;
}

.pry-prose ul,
.pry-prose ol {
	margin: 0 0 1.15em;
	padding-left: 1.4em;
}

.pry-prose li {
	margin-bottom: 0.35em;
}

.pry-prose li::marker {
	color: var(--mass-text-faint);
}

.pry-prose strong {
	font-weight: 680;
	color: var(--mass-text);
}

.pry-prose img {
	max-width: 100%;
	height: auto;
	border-radius: var(--pry-radius);
	display: block;
	margin-block: 1.5em;
}

.pry-prose blockquote {
	margin: 1.5em 0;
	padding: 2px 0 2px 18px;
	border-left: 3px solid var(--mass-accent);
	color: var(--mass-text-muted);
	font-style: italic;
}

.pry-prose blockquote p:last-child {
	margin-bottom: 0;
}

.pry-prose hr {
	border: 0;
	border-top: var(--pry-border);
	margin-block: 2.5em;
}

.pry-prose a {
	text-decoration: underline;
	text-decoration-color: color-mix(in srgb, var(--mass-accent) 40%, transparent);
	text-underline-offset: 3px;
}

/* Code */

.pry-prose code {
	font-family: ui-monospace, "JetBrains Mono", SFMono-Regular, Menlo, Consolas, monospace;
	font-size: 0.88em;
	background: var(--mass-bg-active);
	padding: 0.15em 0.4em;
	border-radius: 5px;
}

.pry-prose pre {
	background: var(--mass-bg-panel);
	border: var(--pry-border);
	border-radius: var(--pry-radius);
	padding: 16px 18px;
	overflow-x: auto;
	margin: 0 0 1.4em;
	font-family: ui-monospace, "JetBrains Mono", SFMono-Regular, Menlo, Consolas, monospace;
	font-size: 13.5px;
	line-height: 1.7;
}

.pry-prose pre code {
	background: none;
	padding: 0;
	font-size: inherit;
	line-height: inherit;
}

/* The copy button and the block it belongs to. The wrapper carries the bottom
   margin the <pre> used to, because the <pre> is now inside it — and the button
   anchors to the wrapper rather than the <pre>, which scrolls horizontally and
   would carry it off the edge. Both are built by copy.js; without the script
   neither exists and the block is exactly what it was. */
.pry-code {
	position: relative;
	margin: 0 0 1.4em;
}

.pry-code pre {
	margin: 0;
}

.pry-copy {
	position: absolute;
	top: 8px;
	right: 8px;
	display: inline-flex;
	align-items: center;
	/* Square around a 14px glyph, and it grows on its own for the one state that
	   needs words. */
	padding: 5px;
	border: var(--pry-border);
	border-radius: var(--pry-radius-sm);
	background: var(--mass-bg-base);
	color: var(--mass-text-muted);
	font-size: 11.5px;
	font-family: inherit;
	line-height: 1.6;
	cursor: pointer;
	/* Out of the way until wanted, and never hidden from a keyboard: opacity
	   rather than display, so the button stays focusable and in the tab order. */
	opacity: 0;
	transition: opacity 120ms ease, color 120ms ease, border-color 120ms ease;
}

/* :focus, not :focus-visible, for the reveal: focus-visible is withheld from
   focus the browser judges non-keyboard, which would leave the button invisible
   while it holds focus. The outline below stays on focus-visible, where it
   belongs. */
.pry-code:hover .pry-copy,
.pry-copy:focus {
	opacity: 1;
}

/* A pointer is what the hover reveal assumes. On touch there is none, so the
   button simply stays. */
@media (hover: none) {
	.pry-copy {
		opacity: 1;
	}
}

.pry-copy:hover {
	color: var(--mass-accent);
	border-color: var(--mass-accent);
}

.pry-copy:focus-visible {
	outline: 2px solid var(--mass-accent);
	outline-offset: 2px;
}

.pry-copy[data-state="done"] {
	color: var(--mass-success);
	border-color: color-mix(in srgb, var(--mass-success) 45%, transparent);
}

.pry-copy[data-state="failed"] {
	color: var(--mass-warning);
	border-color: color-mix(in srgb, var(--mass-warning) 45%, transparent);
	/* The fallback is the one state that speaks in words. */
	padding: 3px 9px;
}

/* flex, not inline-flex: an inline-level box sits on a baseline and would give
   the button a descender's worth of padding under the glyph. */
.pry-copy-mark {
	display: flex;
}

/* Tables */

.pry-prose .pry-table-scroll,
.pry-prose table {
	margin: 0 0 1.4em;
}

.pry-prose table {
	width: 100%;
	border-collapse: collapse;
	font-size: 15px;
	border: var(--pry-border);
	border-radius: var(--pry-radius);
	overflow: hidden;
}

.pry-prose th,
.pry-prose td {
	border-bottom: var(--pry-border);
	padding: 9px 14px;
	text-align: left;
}

.pry-prose tr:last-child td {
	border-bottom: 0;
}

.pry-prose th {
	background: var(--mass-bg-panel);
	font-weight: 650;
	color: var(--mass-text);
}

/* Task lists */

.pry-prose input[type="checkbox"] {
	accent-color: var(--mass-accent);
	margin-right: 6px;
	vertical-align: -1px;
}

/* Footnotes */

.pry-prose .footnotes {
	margin-top: 3em;
	padding-top: 1.5em;
	border-top: var(--pry-border);
	font-size: 14.5px;
	color: var(--mass-text-muted);
}

.pry-prose .footnotes hr {
	display: none;
}

/* ── Search ────────────────────────────────────────────────────────────── */

/* No reading-measure cap here: the form is a control, not prose, and it sits
   directly above the result cards. Anything narrower than they are reads as a
   misalignment rather than as a deliberate column. */
.pry-search-form {
	display: flex;
	gap: 10px;
	margin-bottom: 16px;
}

.pry-search-form .pry-input {
	flex: 1;
	padding: 10px 13px;
	font-size: 15px;
}

/* WebKit paints its own clear button on type="search"; it sits on the site's
   border colour and reads as a rendering fault. */
.pry-search-form .pry-input::-webkit-search-cancel-button {
	appearance: none;
}

.pry-snippet {
	color: var(--mass-text-muted);
	font-size: 14.5px;
	line-height: 1.6;
	margin: 10px 0 0;
}

.pry-snippet mark {
	background: var(--mass-accent-soft);
	color: var(--mass-accent);
	border-radius: 3px;
	padding: 0 3px;
	font-weight: 600;
}

/* ── Admin ─────────────────────────────────────────────────────────────── */

.pry-row-actions {
	display: flex;
	gap: 6px;
	align-items: center;
}

/* Metrics */

.pry-metrics {
	margin-bottom: 34px;
}

.pry-metrics-title {
	margin: 0 0 12px;
	font-size: 17px;
	font-weight: 650;
	color: var(--mass-text);
}

.pry-table {
	width: 100%;
	border-collapse: collapse;
	font-size: 15px;
	border: var(--pry-border);
	border-radius: var(--pry-radius);
	overflow: hidden;
}

.pry-table th,
.pry-table td {
	border-bottom: var(--pry-border);
	padding: 9px 14px;
	text-align: left;
}

.pry-table tr:last-child td {
	border-bottom: 0;
}

.pry-table th {
	background: var(--mass-bg-panel);
	font-weight: 650;
	color: var(--mass-text);
}

/* Counts are read down the column, so the digits line up: tabular figures and a
   width that holds the widest number this site will ever show. */
.pry-num {
	text-align: right;
	font-variant-numeric: tabular-nums;
	white-space: nowrap;
	width: 8ch;
}

/* The author's buttons. They sit in the header because they belong to no single
   post — everything that does is managed from the post itself. */
.pry-header-actions {
	display: flex;
	gap: 8px;
	align-items: center;
}

/* The controls for one post, on the post. Separated from the article by a rule
   rather than a panel: it is chrome the author sees and the reader never does,
   and boxing it would put a second frame inside the page's own header. */
.pry-post-actions {
	display: flex;
	gap: 6px;
	align-items: center;
	flex-wrap: wrap;
	margin-top: 16px;
	padding-top: 14px;
	border-top: var(--pry-border);
}

.pry-post-actions .pry-status {
	margin: 0 auto 0 0;
}

/* The Draft badge, on a card and in a post's own header. Warning colours, not
   the green badge pair: this is now the only state that is ever badged, and it
   means "not live yet" — green read as the opposite. */
.pry-state {
	font-size: 11px;
	font-weight: 650;
	text-transform: uppercase;
	letter-spacing: 0.07em;
	padding: 3px 9px;
	border-radius: 999px;
	background: var(--mass-warning-soft);
	color: var(--mass-warning);
}

/* A card's whole surface is a link to the post; the badge must not swallow the
   click, and the action bar's buttons must stay clickable. */
.pry-card .pry-state,
.pry-post-actions {
	position: relative;
	z-index: 1;
}

/* Confirming a deletion: the two choices, side by side. */
.pry-confirm-actions {
	display: flex;
	gap: 8px;
	align-items: center;
	margin-top: 20px;
}

/* ── Editor ────────────────────────────────────────────────────────────── */

/* The editor is the only page that wants the window rather than the page
   measure. A reading column is right for prose and wrong for a writing surface:
   at 60rem the two panes are too narrow to hold a line of Markdown and its
   rendering side by side, and the box ends halfway down a tall screen with
   nothing under it. Widened and stretched to whatever the viewport has left. */
/* A definite height, not min-height: a 1fr grid row in a container whose height
   is only bounded below resolves to max-content, so the panes grew to fit the
   text and pushed the footer off the bottom. Pinning the shell to the viewport
   makes the remainder a real number the panes can divide and scroll inside. */
.pry-shell:has(.pry-editor-page) {
	height: 100dvh;
}

.pry-main:has(.pry-editor-page) {
	padding-block: 24px 28px;
}

/* The editor's own column widens. The header and footer do not.

   They used to, on the reasoning that chrome stopping short of the content it
   sits above reads as a broken grid — true when the brand was left-aligned and
   had a content edge to line up with. It is centred now, and both bars put their
   controls at the edges of their column: widening those columns flung the
   author's marks and the sign-out button out to the window edges on the way into
   the editor and back again on the way out. Chrome that moves when the page
   changes is worse than chrome that is narrower than the page. */
.pry-shell:has(.pry-editor-page) .pry-main > .pry-wrap {
	max-width: calc(var(--pry-pane) * 2 + 14px + var(--pry-gutter) * 2);
}

/* Rows: the title bar, then the form. Inside the form: the metadata strip, then
   the panes take everything left. The minmax(0, 1fr) at each level is what lets
   the bottom row shrink to the viewport instead of being pushed past it by the
   textarea's content height. */
.pry-editor-page {
	flex: 1;
	min-height: 0;
	display: grid;
	grid-template-rows: auto minmax(0, 1fr);
	gap: 14px;
}

.pry-editor {
	min-height: 0;
	display: grid;
	grid-template-rows: auto minmax(20rem, 1fr);
	gap: 14px;
}

.pry-editor-bar {
	display: flex;
	align-items: center;
	gap: 16px;
	flex-wrap: wrap;
}

/* The title is the page's heading, so it is styled as one and only reveals its
   underline as a field. Nothing labels it: a lone large field at the top of an
   editor is unambiguous, and the label would cost a row. */
.pry-editor-title {
	flex: 1 1 16rem;
	min-width: 0;
	background: transparent;
	color: var(--mass-text);
	border: 0;
	border-bottom: var(--pry-border);
	border-radius: 0;
	padding: 5px 2px 8px;
	font: inherit;
	font-size: 26px;
	font-weight: 700;
	letter-spacing: -0.02em;
}

.pry-editor-title::placeholder {
	color: var(--mass-text-faint);
	font-weight: 600;
}

.pry-editor-title:focus {
	outline: none;
	border-bottom-color: var(--mass-accent);
}

.pry-editor-bar-actions {
	display: flex;
	align-items: center;
	gap: 8px;
	flex-shrink: 0;
}

/* Summary takes the room, because it is the one field holding a sentence; tags
   and the link-preview picker hold a few words and a filename. */
.pry-editor-meta {
	display: grid;
	grid-template-columns: minmax(9rem, 1fr) minmax(15rem, 2fr);
	gap: 14px;
	align-items: end;
}

.pry-field {
	display: flex;
	flex-direction: column;
	gap: 5px;
	min-width: 0;
}

.pry-field-label {
	font-size: 11px;
	font-weight: 650;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	color: var(--mass-text-faint);
}

.pry-input {
	width: 100%;
	background: var(--mass-bg-panel);
	color: var(--mass-text);
	border: var(--pry-border);
	border-radius: var(--pry-radius-sm);
	padding: 8px 11px;
	font: inherit;
	font-size: 14px;
}

.pry-input::placeholder {
	color: var(--mass-text-faint);
}

.pry-input:focus,
.pry-source:focus {
	outline: none;
	border-color: var(--mass-accent);
	box-shadow: 0 0 0 3px var(--mass-accent-soft);
}

/* The preview gets --pry-pane and the source takes what is left.

   Two full panes need about 1600px of window, which most screens do not have, so
   one of them has to absorb the shortfall. It is the source: that pane holds
   Markdown in a monospace face and its width means nothing, while the preview's
   width is the whole point — a preview at some other measure breaks its lines
   somewhere the published page will not. Past 1600px the wrap's own cap stops
   the source growing, so the two end up equal. */
.pry-editor-panes {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, var(--pry-pane));
	gap: 14px;
	min-height: 0;
}

.pry-pane {
	display: flex;
	flex-direction: column;
	min-width: 0;
	min-height: 0;
	background: var(--mass-bg-panel);
	border: var(--pry-border);
	border-radius: var(--pry-radius);
	padding: 12px 14px 14px;
}

.pry-pane-head {
	display: flex;
	align-items: center;
	gap: 10px;
	margin-bottom: 10px;
	flex-shrink: 0;
}

/* The title takes the slack, so every control after it groups at the right edge
   rather than spreading evenly across the head. */
.pry-pane-title {
	margin: 0;
	margin-right: auto;
	font-size: 11px;
	font-weight: 650;
	text-transform: uppercase;
	letter-spacing: 0.09em;
	color: var(--mass-text-faint);
}

/* The pane head's trailing controls: the Images link, and the Insert image
   button the upload script adds beside it. Both read as chrome, not as actions
   competing with Save. */
.pry-pane-link {
	background: none;
	border: 0;
	padding: 0;
	font: inherit;
	font-size: 11px;
	font-weight: 650;
	text-transform: uppercase;
	letter-spacing: 0.09em;
	color: var(--mass-text-faint);
	cursor: pointer;
}

.pry-pane-link:hover {
	color: var(--mass-accent);
	text-decoration: none;
}

/* Only while a file is over the textarea. */
.pry-source.pry-dropping {
	border-color: var(--mass-accent);
	box-shadow: 0 0 0 3px var(--mass-accent-soft);
}

/* Both panes fill their column and scroll inside it, so the two stay the same
   height whatever either one contains — a short preview beside a long source no
   longer reads as a broken box. */
.pry-source {
	flex: 1;
	min-height: 0;
	width: 100%;
	resize: none;
	display: block;
	background: var(--mass-bg-base);
	color: var(--mass-text);
	border: var(--pry-border);
	border-radius: var(--pry-radius-sm);
	padding: 12px 14px;
	font-family: ui-monospace, "JetBrains Mono", SFMono-Regular, Menlo, Consolas, monospace;
	font-size: 13.5px;
	line-height: 1.7;
	tab-size: 4;
}

/* No font-size of its own. It carried 15.5px against the article's 17px, which
   put the preview's line breaks in different places from the published page's
   whatever the pane was wide — the one thing a preview must not do. */
.pry-preview-body {
	flex: 1;
	min-height: 0;
	overflow-y: auto;
	padding-right: 4px;
}

/* The preview pane is server-rendered; this only marks a render in flight. */
.pry-busy {
	opacity: 0.5;
	transition: opacity 0.12s ease;
}

.pry-status {
	font-size: 13px;
	color: var(--mass-text-muted);
	white-space: nowrap;
}

/* Below the split, panes stack and size to content: two half-height boxes on a
   phone are worse than one of each you can scroll past.

   77rem, not the 62rem it was: the preview holds its measure and the source
   takes the rest, so the narrower the window the narrower the source, and by
   1100px it was a 208px column to write Markdown in. This is the width where the
   source still gets 400px. Under it, one truthful preview stacked under a usable
   editor beats two panes that are each wrong. */
@media (max-width: 77rem) {
	/* Release the viewport pin: stacked panes size to content and the page
	   scrolls, so a fixed height would clip the second one. */
	.pry-shell:has(.pry-editor-page) {
		height: auto;
		min-height: 100dvh;
	}

	.pry-editor-page,
	.pry-editor {
		grid-template-rows: auto auto;
	}

	.pry-editor-meta {
		grid-template-columns: 1fr;
	}

	/* Stacked, but still capped and centred: the preview keeps the article's
	   measure here too, which is the only width at which it tells the truth. */
	.pry-editor-panes {
		grid-template-columns: minmax(0, var(--pry-pane));
		justify-content: center;
	}

	.pry-editor-bar-actions {
		width: 100%;
		justify-content: flex-end;
	}

	.pry-source {
		min-height: 20rem;
	}

	.pry-preview-body {
		min-height: 10rem;
		overflow-y: visible;
	}
}

.pry-status[data-variant="error"] {
	color: var(--mass-danger);
}

.pry-status[data-variant="success"] {
	color: var(--mass-success);
}

/* Login */

.pry-login {
	max-width: 21rem;
	margin: 8vh auto 0;
	display: flex;
	flex-direction: column;
	gap: 16px;
	background: var(--mass-bg-panel);
	border: var(--pry-border);
	border-radius: var(--pry-radius);
	padding: 28px;
}

.pry-login .pry-input {
	padding: 10px 13px;
	font-size: 15px;
}

.pry-login .pry-title {
	margin-bottom: 0;
	font-size: 22px;
}

/* ── Images ────────────────────────────────────────────────────────────── */

.pry-upload-form {
	display: flex;
	gap: 10px;
	align-items: center;
	flex-wrap: wrap;
	margin-bottom: 12px;
}

.pry-upload-form .pry-input {
	width: auto;
	flex: 1;
	min-width: 14rem;
	padding: 6px 8px;
}

/* The browser's own file button is the only unthemed control on the site; this
   is the one selector that reaches it. */
.pry-upload-form .pry-input::file-selector-button {
	margin-right: 10px;
	background: var(--mass-bg-base);
	color: var(--mass-text);
	border: var(--pry-border);
	border-radius: var(--pry-radius-sm);
	padding: 5px 12px;
	font: inherit;
	font-size: 13px;
	font-weight: 600;
	cursor: pointer;
}

.pry-upload-form .pry-input::file-selector-button:hover {
	border-color: var(--mass-accent);
	color: var(--mass-accent);
}

.pry-upload-list {
	display: flex;
	flex-direction: column;
	gap: 8px;
	list-style: none;
	margin: 0;
	padding: 0;
}

.pry-upload {
	display: flex;
	align-items: center;
	gap: 14px;
	flex-wrap: wrap;
	background: var(--mass-bg-panel);
	border: var(--pry-border);
	border-radius: var(--pry-radius);
	padding: 12px 16px;
}

/* A fixed box with a checkered backdrop: a transparent PNG on a panel-coloured
   card otherwise looks like a broken image. */
.pry-upload-thumb {
	flex-shrink: 0;
	width: 72px;
	height: 72px;
	display: grid;
	place-items: center;
	overflow: hidden;
	border-radius: var(--pry-radius-sm);
	border: var(--pry-border);
	background-color: var(--mass-bg-base);
	background-image:
		linear-gradient(45deg, var(--mass-border) 25%, transparent 25%),
		linear-gradient(-45deg, var(--mass-border) 25%, transparent 25%),
		linear-gradient(45deg, transparent 75%, var(--mass-border) 75%),
		linear-gradient(-45deg, transparent 75%, var(--mass-border) 75%);
	background-size: 12px 12px;
	background-position: 0 0, 0 6px, 6px -6px, -6px 0;
}

.pry-upload-thumb img {
	max-width: 100%;
	max-height: 100%;
	object-fit: contain;
}

.pry-upload-main {
	flex: 1;
	min-width: 0;
	display: flex;
	flex-direction: column;
	gap: 6px;
}

.pry-upload-name {
	margin: 0;
	font-weight: 620;
	font-size: 15px;
	color: var(--mass-text);
	overflow-wrap: anywhere;
}

/* user-select: all makes one click take the whole snippet, which is what a copy
   button would be for — and this needs no script. */
.pry-upload-snippet {
	user-select: all;
	display: inline-block;
	max-width: 100%;
	overflow-wrap: anywhere;
	background: var(--mass-bg-base);
	border: var(--pry-border);
	border-radius: var(--pry-radius-sm);
	padding: 5px 9px;
	font-family: ui-monospace, "JetBrains Mono", SFMono-Regular, Menlo, Consolas, monospace;
	font-size: 12.5px;
	color: var(--mass-text-muted);
}

.pry-upload-preview {
	max-width: 100%;
	max-height: 40vh;
	border-radius: var(--pry-radius);
	border: var(--pry-border);
}

/* ── Misc ──────────────────────────────────────────────────────────────── */

.pry-empty {
	color: var(--mass-text-faint);
	text-align: center;
	padding: 56px 16px;
	border: 1px dashed var(--mass-border);
	border-radius: var(--pry-radius);
	font-size: 15px;
}

.pry-error {
	text-align: center;
	padding: 8vh 0;
}

.pry-error-detail {
	margin: -4px 0 24px;
	color: var(--mass-text-faint);
	font-size: 15px;
}

.pry-error-code {
	font-size: 64px;
	font-weight: 750;
	letter-spacing: -0.03em;
	line-height: 1;
	margin: 0 0 12px;
	color: var(--mass-text-faint);
}

/* ── Footer ────────────────────────────────────────────────────────────── */

.pry-footer {
	border-top: var(--pry-border);
	color: var(--mass-text-faint);
	font-size: 13.5px;
	padding-block: 20px;
}

/* Grid, not flex: the credit sits in the middle column, so it is centred on the
   page rather than in whatever space the other two leave. The 1fr columns are
   what makes those two symmetric — space-between would push the middle right,
   because the owner and their links are wider than the auth button. */
.pry-footer-inner {
	display: grid;
	grid-template-columns: 1fr auto 1fr;
	align-items: center;
	gap: 16px;
}

.pry-footer-inner > :last-child {
	justify-self: end;
}

/* The credit, centred on the footer row. Quieter than everything beside it — it
   names the tool, and the reader came for the posts. */
.pry-colophon {
	color: var(--mass-text-faint);
	font-size: 12.5px;
}

/* Links elsewhere are marked by the accent colour, which is too loud for a
   credit. Muted instead — but then it needs an underline, or the only thing
   saying "link" is gone and it reads as the sentence it sits in. */
.pry-colophon a {
	color: inherit;
	text-decoration: underline;
	text-decoration-color: color-mix(in srgb, currentColor 50%, transparent);
	text-underline-offset: 2px;
}

.pry-colophon a:hover {
	color: var(--mass-accent);
	text-decoration-color: currentColor;
}

/* The owner's name and their links are one group, so the auth control keeps the
   far edge to itself however many links there are. */
.pry-footer-owner {
	display: flex;
	align-items: center;
	gap: 14px;
	flex-wrap: wrap;
}

.pry-social {
	display: flex;
	align-items: center;
	gap: 12px;
	list-style: none;
	margin: 0;
	padding: 0;
}

/* flex, not inline-flex: an inline-level box sits on a baseline, so the list item
   grew a descender's worth of space under the mark and the mark rode 3px above
   the name beside it. Block-level, and the item is exactly the icon. */
.pry-social-link {
	display: flex;
	color: var(--mass-text-faint);
	border-radius: var(--pry-radius-sm);
}

.pry-social-link:hover {
	color: var(--mass-accent);
	text-decoration: none;
}

.pry-social-link:focus-visible {
	outline: 2px solid var(--mass-accent);
	outline-offset: 3px;
}

@media (max-width: 40rem) {
	/* Nav and picker still fit one row without the brand mark; only the
	   breathing room needs to come down. */
	.pry-wrap {
		padding-inline: 16px;
	}

	/* A long title plus the picker doesn't fit a phone at 30px, so the title
	   comes down with the header whose height it sets. */
	.pry-header-inner {
		gap: 12px;
		min-height: 62px;
	}

	.pry-brand {
		font-size: 22px;
	}

	/* Signed in there are three buttons and the picker beside a centred brand,
	   which is more than a phone is wide — so that row splits in two. A reader
	   has only the picker there and keeps the single row. */
	.pry-header-inner:has(.pry-header-actions) {
		grid-template-columns: 1fr;
		justify-items: center;
		padding-block: 10px;
		min-height: 0;
	}

	/* Both children name a column of the three-column layout, which this one no
	   longer has — left alone they would be placed into implicit columns beside
	   it rather than stacked in it. */
	.pry-header-inner:has(.pry-header-actions) .pry-brand,
	.pry-header-inner:has(.pry-header-actions) .pry-header-right {
		grid-column: 1;
		justify-self: center;
		flex-wrap: wrap;
		justify-content: center;
	}

	.pry-nav {
		gap: 14px;
		font-size: 14px;
	}

	.pry-main {
		padding-block: 28px 48px;
	}

	/* Three columns can't hold their content this narrow — the owner's links
	   and the credit would both wrap mid-group. Stack instead, all left. */
	.pry-footer-inner {
		grid-template-columns: 1fr;
		gap: 12px;
	}

	.pry-footer-inner > :last-child {
		justify-self: start;
	}
}

html.sl-theme-dark {
/* Background */ .chroma-bg { color: #f8f8f2; background-color: #282a36; }
/* PreWrapper */ .chroma-chroma { color: #f8f8f2; background-color: #282a36; }
/* LineTableTD */ .chroma-chroma .chroma-lntd { vertical-align: top; padding: 0; margin: 0; border: 0; }
/* LineTable */ .chroma-chroma .chroma-lntable { border-spacing: 0; padding: 0; margin: 0; border: 0; }
/* LineHighlight */ .chroma-chroma .chroma-hl { background-color: #3d3f4a }
/* LineNumbersTable */ .chroma-chroma .chroma-lnt { white-space: pre; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #7f7f7f }
/* LineNumbers */ .chroma-chroma .chroma-ln { white-space: pre; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #7f7f7f }
/* Line */ .chroma-chroma .chroma-line { display: flex; }
/* Keyword */ .chroma-chroma .chroma-k { color: #ff79c6 }
/* KeywordConstant */ .chroma-chroma .chroma-kc { color: #ff79c6 }
/* KeywordDeclaration */ .chroma-chroma .chroma-kd { color: #8be9fd; font-style: italic }
/* KeywordNamespace */ .chroma-chroma .chroma-kn { color: #ff79c6 }
/* KeywordPseudo */ .chroma-chroma .chroma-kp { color: #ff79c6 }
/* KeywordReserved */ .chroma-chroma .chroma-kr { color: #ff79c6 }
/* KeywordType */ .chroma-chroma .chroma-kt { color: #8be9fd }
/* NameAttribute */ .chroma-chroma .chroma-na { color: #50fa7b }
/* NameBuiltin */ .chroma-chroma .chroma-nb { color: #8be9fd; font-style: italic }
/* NameClass */ .chroma-chroma .chroma-nc { color: #50fa7b }
/* NameFunction */ .chroma-chroma .chroma-nf { color: #50fa7b }
/* NameLabel */ .chroma-chroma .chroma-nl { color: #8be9fd; font-style: italic }
/* NameTag */ .chroma-chroma .chroma-nt { color: #ff79c6 }
/* NameVariable */ .chroma-chroma .chroma-nv { color: #8be9fd; font-style: italic }
/* NameVariableClass */ .chroma-chroma .chroma-vc { color: #8be9fd; font-style: italic }
/* NameVariableGlobal */ .chroma-chroma .chroma-vg { color: #8be9fd; font-style: italic }
/* NameVariableInstance */ .chroma-chroma .chroma-vi { color: #8be9fd; font-style: italic }
/* LiteralString */ .chroma-chroma .chroma-s { color: #f1fa8c }
/* LiteralStringAffix */ .chroma-chroma .chroma-sa { color: #f1fa8c }
/* LiteralStringBacktick */ .chroma-chroma .chroma-sb { color: #f1fa8c }
/* LiteralStringChar */ .chroma-chroma .chroma-sc { color: #f1fa8c }
/* LiteralStringDelimiter */ .chroma-chroma .chroma-dl { color: #f1fa8c }
/* LiteralStringDoc */ .chroma-chroma .chroma-sd { color: #f1fa8c }
/* LiteralStringDouble */ .chroma-chroma .chroma-s2 { color: #f1fa8c }
/* LiteralStringEscape */ .chroma-chroma .chroma-se { color: #f1fa8c }
/* LiteralStringHeredoc */ .chroma-chroma .chroma-sh { color: #f1fa8c }
/* LiteralStringInterpol */ .chroma-chroma .chroma-si { color: #f1fa8c }
/* LiteralStringOther */ .chroma-chroma .chroma-sx { color: #f1fa8c }
/* LiteralStringRegex */ .chroma-chroma .chroma-sr { color: #f1fa8c }
/* LiteralStringSingle */ .chroma-chroma .chroma-s1 { color: #f1fa8c }
/* LiteralStringSymbol */ .chroma-chroma .chroma-ss { color: #f1fa8c }
/* LiteralNumber */ .chroma-chroma .chroma-m { color: #bd93f9 }
/* LiteralNumberBin */ .chroma-chroma .chroma-mb { color: #bd93f9 }
/* LiteralNumberFloat */ .chroma-chroma .chroma-mf { color: #bd93f9 }
/* LiteralNumberHex */ .chroma-chroma .chroma-mh { color: #bd93f9 }
/* LiteralNumberInteger */ .chroma-chroma .chroma-mi { color: #bd93f9 }
/* LiteralNumberIntegerLong */ .chroma-chroma .chroma-il { color: #bd93f9 }
/* LiteralNumberOct */ .chroma-chroma .chroma-mo { color: #bd93f9 }
/* Operator */ .chroma-chroma .chroma-o { color: #ff79c6 }
/* OperatorWord */ .chroma-chroma .chroma-ow { color: #ff79c6 }
/* Comment */ .chroma-chroma .chroma-c { color: #6272a4 }
/* CommentHashbang */ .chroma-chroma .chroma-ch { color: #6272a4 }
/* CommentMultiline */ .chroma-chroma .chroma-cm { color: #6272a4 }
/* CommentSingle */ .chroma-chroma .chroma-c1 { color: #6272a4 }
/* CommentSpecial */ .chroma-chroma .chroma-cs { color: #6272a4 }
/* CommentPreproc */ .chroma-chroma .chroma-cp { color: #ff79c6 }
/* CommentPreprocFile */ .chroma-chroma .chroma-cpf { color: #ff79c6 }
/* GenericDeleted */ .chroma-chroma .chroma-gd { color: #ff5555 }
/* GenericEmph */ .chroma-chroma .chroma-ge { text-decoration: underline }
/* GenericHeading */ .chroma-chroma .chroma-gh { font-weight: bold }
/* GenericInserted */ .chroma-chroma .chroma-gi { color: #50fa7b; font-weight: bold }
/* GenericOutput */ .chroma-chroma .chroma-go { color: #44475a }
/* GenericSubheading */ .chroma-chroma .chroma-gu { font-weight: bold }
/* GenericUnderline */ .chroma-chroma .chroma-gl { text-decoration: underline }

.chroma-chroma { background: transparent; }

}
html.sl-theme-light {
/* Background */ .chroma-bg { background-color: #f8f8f8; }
/* PreWrapper */ .chroma-chroma { background-color: #f8f8f8; }
/* Other */ .chroma-chroma .chroma-x { color: #000000 }
/* Error */ .chroma-chroma .chroma-err { color: #a40000 }
/* LineTableTD */ .chroma-chroma .chroma-lntd { vertical-align: top; padding: 0; margin: 0; border: 0; }
/* LineTable */ .chroma-chroma .chroma-lntable { border-spacing: 0; padding: 0; margin: 0; border: 0; }
/* LineHighlight */ .chroma-chroma .chroma-hl { background-color: #dfdfdf }
/* LineNumbersTable */ .chroma-chroma .chroma-lnt { white-space: pre; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #7f7f7f }
/* LineNumbers */ .chroma-chroma .chroma-ln { white-space: pre; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #7f7f7f }
/* Line */ .chroma-chroma .chroma-line { display: flex; }
/* Keyword */ .chroma-chroma .chroma-k { color: #204a87; font-weight: bold }
/* KeywordConstant */ .chroma-chroma .chroma-kc { color: #204a87; font-weight: bold }
/* KeywordDeclaration */ .chroma-chroma .chroma-kd { color: #204a87; font-weight: bold }
/* KeywordNamespace */ .chroma-chroma .chroma-kn { color: #204a87; font-weight: bold }
/* KeywordPseudo */ .chroma-chroma .chroma-kp { color: #204a87; font-weight: bold }
/* KeywordReserved */ .chroma-chroma .chroma-kr { color: #204a87; font-weight: bold }
/* KeywordType */ .chroma-chroma .chroma-kt { color: #204a87; font-weight: bold }
/* Name */ .chroma-chroma .chroma-n { color: #000000 }
/* NameAttribute */ .chroma-chroma .chroma-na { color: #c4a000 }
/* NameBuiltin */ .chroma-chroma .chroma-nb { color: #204a87 }
/* NameBuiltinPseudo */ .chroma-chroma .chroma-bp { color: #3465a4 }
/* NameClass */ .chroma-chroma .chroma-nc { color: #000000 }
/* NameConstant */ .chroma-chroma .chroma-no { color: #000000 }
/* NameDecorator */ .chroma-chroma .chroma-nd { color: #5c35cc; font-weight: bold }
/* NameEntity */ .chroma-chroma .chroma-ni { color: #ce5c00 }
/* NameException */ .chroma-chroma .chroma-ne { color: #cc0000; font-weight: bold }
/* NameFunction */ .chroma-chroma .chroma-nf { color: #000000 }
/* NameFunctionMagic */ .chroma-chroma .chroma-fm { color: #000000 }
/* NameLabel */ .chroma-chroma .chroma-nl { color: #f57900 }
/* NameNamespace */ .chroma-chroma .chroma-nn { color: #000000 }
/* NameOther */ .chroma-chroma .chroma-nx { color: #000000 }
/* NameProperty */ .chroma-chroma .chroma-py { color: #000000 }
/* NameTag */ .chroma-chroma .chroma-nt { color: #204a87; font-weight: bold }
/* NameVariable */ .chroma-chroma .chroma-nv { color: #000000 }
/* NameVariableClass */ .chroma-chroma .chroma-vc { color: #000000 }
/* NameVariableGlobal */ .chroma-chroma .chroma-vg { color: #000000 }
/* NameVariableInstance */ .chroma-chroma .chroma-vi { color: #000000 }
/* NameVariableMagic */ .chroma-chroma .chroma-vm { color: #000000 }
/* Literal */ .chroma-chroma .chroma-l { color: #000000 }
/* LiteralDate */ .chroma-chroma .chroma-ld { color: #000000 }
/* LiteralString */ .chroma-chroma .chroma-s { color: #4e9a06 }
/* LiteralStringAffix */ .chroma-chroma .chroma-sa { color: #4e9a06 }
/* LiteralStringBacktick */ .chroma-chroma .chroma-sb { color: #4e9a06 }
/* LiteralStringChar */ .chroma-chroma .chroma-sc { color: #4e9a06 }
/* LiteralStringDelimiter */ .chroma-chroma .chroma-dl { color: #4e9a06 }
/* LiteralStringDoc */ .chroma-chroma .chroma-sd { color: #8f5902; font-style: italic }
/* LiteralStringDouble */ .chroma-chroma .chroma-s2 { color: #4e9a06 }
/* LiteralStringEscape */ .chroma-chroma .chroma-se { color: #4e9a06 }
/* LiteralStringHeredoc */ .chroma-chroma .chroma-sh { color: #4e9a06 }
/* LiteralStringInterpol */ .chroma-chroma .chroma-si { color: #4e9a06 }
/* LiteralStringOther */ .chroma-chroma .chroma-sx { color: #4e9a06 }
/* LiteralStringRegex */ .chroma-chroma .chroma-sr { color: #4e9a06 }
/* LiteralStringSingle */ .chroma-chroma .chroma-s1 { color: #4e9a06 }
/* LiteralStringSymbol */ .chroma-chroma .chroma-ss { color: #4e9a06 }
/* LiteralNumber */ .chroma-chroma .chroma-m { color: #0000cf; font-weight: bold }
/* LiteralNumberBin */ .chroma-chroma .chroma-mb { color: #0000cf; font-weight: bold }
/* LiteralNumberFloat */ .chroma-chroma .chroma-mf { color: #0000cf; font-weight: bold }
/* LiteralNumberHex */ .chroma-chroma .chroma-mh { color: #0000cf; font-weight: bold }
/* LiteralNumberInteger */ .chroma-chroma .chroma-mi { color: #0000cf; font-weight: bold }
/* LiteralNumberIntegerLong */ .chroma-chroma .chroma-il { color: #0000cf; font-weight: bold }
/* LiteralNumberOct */ .chroma-chroma .chroma-mo { color: #0000cf; font-weight: bold }
/* Operator */ .chroma-chroma .chroma-o { color: #ce5c00; font-weight: bold }
/* OperatorWord */ .chroma-chroma .chroma-ow { color: #204a87; font-weight: bold }
/* Punctuation */ .chroma-chroma .chroma-p { color: #000000; font-weight: bold }
/* Comment */ .chroma-chroma .chroma-c { color: #8f5902; font-style: italic }
/* CommentHashbang */ .chroma-chroma .chroma-ch { color: #8f5902; font-style: italic }
/* CommentMultiline */ .chroma-chroma .chroma-cm { color: #8f5902; font-style: italic }
/* CommentSingle */ .chroma-chroma .chroma-c1 { color: #8f5902; font-style: italic }
/* CommentSpecial */ .chroma-chroma .chroma-cs { color: #8f5902; font-style: italic }
/* CommentPreproc */ .chroma-chroma .chroma-cp { color: #8f5902; font-style: italic }
/* CommentPreprocFile */ .chroma-chroma .chroma-cpf { color: #8f5902; font-style: italic }
/* Generic */ .chroma-chroma .chroma-g { color: #000000 }
/* GenericDeleted */ .chroma-chroma .chroma-gd { color: #a40000 }
/* GenericEmph */ .chroma-chroma .chroma-ge { color: #000000; font-style: italic }
/* GenericError */ .chroma-chroma .chroma-gr { color: #ef2929 }
/* GenericHeading */ .chroma-chroma .chroma-gh { color: #000080; font-weight: bold }
/* GenericInserted */ .chroma-chroma .chroma-gi { color: #00a000 }
/* GenericOutput */ .chroma-chroma .chroma-go { color: #000000; font-style: italic }
/* GenericPrompt */ .chroma-chroma .chroma-gp { color: #8f5902 }
/* GenericStrong */ .chroma-chroma .chroma-gs { color: #000000; font-weight: bold }
/* GenericSubheading */ .chroma-chroma .chroma-gu { color: #800080; font-weight: bold }
/* GenericTraceback */ .chroma-chroma .chroma-gt { color: #a40000; font-weight: bold }
/* GenericUnderline */ .chroma-chroma .chroma-gl { color: #000000; text-decoration: underline }
/* TextWhitespace */ .chroma-chroma .chroma-w { color: #f8f8f8; text-decoration: underline }

.chroma-chroma { background: transparent; }

}
