/*
 * Content typography.
 *
 * Everything readable on the page is driven by the tokens on .content, so the
 * ink hierarchy and the rhythm can be retuned in one place. Sizes are in rem
 * (not px) so the reader's own browser font-size setting is respected.
 */

body {
	-webkit-font-smoothing: antialiased;
	font-family: Segoe UI, Segoe UI Variable Text, -apple-system, BlinkMacSystemFont, Helvetica Neue, Helvetica, Arial, sans-serif;
	font-weight: 400;
	font-size: 1rem;
}

.content {
	/*
	 * Document-like measure. The .content wrapper spans the whole column, while
	 * the flow elements inside it are capped and centered, so a block can opt
	 * into a different width by setting --measure on itself (it inherits to its
	 * children):
	 *
	 *   <div class="wide">   ... wide tables, diagrams, side-by-side code ...
	 *   <div class="narrow"> ... short, laconic content ...
	 *   <div class="normal"> ... back to the default measure ...
	 *
	 * The wider measure is deliberate: the columns flanking the article already
	 * frame it, so a long line reads as a document page rather than a stray band.
	 */
	--measure: 52rem;

	/* Ink hierarchy: headings darkest, body a step back, asides quieter still */
	--content-ink: #22262b;
	--content-ink-strong: #101317;
	--content-ink-muted: #6b7280;
	--content-rule: rgba(0, 0, 0, 0.11);
	--content-surface: rgba(0, 0, 0, 0.045);
	--content-link: #0a58ca;

	/* Vertical rhythm */
	--content-leading: 1.65;
	--content-gap: 1.15em;

	max-width: none;
	color: var(--content-ink);
	line-height: var(--content-leading);
}

.content :where(h1, h2, h3, h4, h5, h6, p, ul, ol, dl, blockquote, pre, table, figure, img, hr) {
	max-width: var(--measure);
	margin-inline: auto;
}

.content .normal { --measure: 52rem; }
.content .wide   { --measure: 76rem; }
.content .narrow { --measure: 36rem; }

.content .normal,
.content .wide,
.content .narrow {
	max-width: var(--measure);
	margin-inline: auto;
}

/*
 * Headings.
 *
 * Space above a heading is much larger than the space below it, so the heading
 * binds to the text it introduces instead of floating between two sections.
 * Large sizes take a lighter weight and negative tracking, small sizes take a
 * heavier weight — the optical correction that keeps the scale even.
 */
.content :where(h1, h2, h3, h4, h5, h6) {
	color: var(--content-ink-strong);
	text-wrap: balance;
	margin-block-end: 0.5em;
}

.content h1 {
	font-size: clamp(1.875rem, 1.6rem + 1.4vw, 2.375rem);
	font-weight: 300;
	line-height: 1.15;
	letter-spacing: -0.021em;
	margin-block-start: 0;
}

.content h2 {
	font-size: clamp(1.375rem, 1.25rem + 0.6vw, 1.625rem);
	font-weight: 500;
	line-height: 1.22;
	letter-spacing: -0.014em;
	margin-block-start: 1.2em;
}

.content h3 {
	font-size: 1.25rem;
	font-weight: 600;
	line-height: 1.3;
	letter-spacing: -0.008em;
	margin-block-start: 2.2em;
}

.content h4 {
	font-size: 1.0625rem;
	font-weight: 600;
	line-height: 1.35;
	margin-block-start: 2em;
}

/*
 * h5 is used in the articles as a small run-in label ("SOLUTION:", "Scaling:"),
 * so it is set as one: small, tracked out, quieter than the body it labels.
 */
.content h5,
.content h6 {
	font-size: 0.8125rem;
	font-weight: 600;
	line-height: 1.4;
	letter-spacing: 0.07em;
	text-transform: uppercase;
	color: var(--content-ink-muted);
	margin-block-start: 2.4em;
	margin-block-end: 0.65em;
}

/* A heading opening a block, or stacked under another heading, drops its lead-in */
.content :where(h1, h2, h3, h4, h5, h6):first-child {
	margin-block-start: 0;
}

/* :is(), not :where() — this must outrank the per-level .content h2/h3/... rules */
.content :is(h1, h2, h3, h4, h5, h6) + :is(h1, h2, h3, h4, h5, h6) {
	margin-block-start: 0.9em;
}

/* Body text */
.content p {
	line-height: var(--content-leading);
	margin-block: 0 var(--content-gap);
	text-wrap: pretty;
}

.content :where(strong, b) {
	font-weight: 600;
	color: var(--content-ink-strong);
}

.content a {
	color: var(--content-link);
	text-decoration-line: underline;
	text-decoration-thickness: 0.06em;
	text-underline-offset: 0.18em;
	text-decoration-color: color-mix(in srgb, currentColor 35%, transparent);
	transition: text-decoration-color 0.12s ease-in-out;
}

.content a:hover,
.content a:focus-visible {
	text-decoration-color: currentColor;
}

/* Lists: markers sit inside the measure, items breathe */
.content :where(ul, ol) {
	line-height: var(--content-leading);
	margin-block: 0 var(--content-gap);
	padding-inline-start: 1.5em;
}

.content :where(ul, ol) li + li {
	margin-block-start: 0.4em;
}

.content :where(ul, ol) li::marker {
	color: var(--content-ink-muted);
}

.content :where(ul, ol) :where(ul, ol) {
	margin-block: 0.4em 0;
}

/* Quotes: a rule instead of a box, so the page stays quiet */
.content blockquote {
	margin-block: 1.8em;
	padding-inline-start: 1.25rem;
	border-inline-start: 2px solid var(--content-rule);
	color: var(--content-ink-muted);
}

.content blockquote > :last-child {
	margin-block-end: 0;
}

/* Code */
.content :where(code, .code, .code-inline) {
	font-family: ui-monospace, SFMono-Regular, Cascadia Mono, Consolas, Liberation Mono, monospace;
	font-size: 0.875em;
	background-color: var(--content-surface);
	border: 1px solid var(--content-rule);
	border-radius: 4px;
	padding: 0.12em 0.36em;
	overflow-wrap: break-word;
}

.content pre {
	font-family: ui-monospace, SFMono-Regular, Cascadia Mono, Consolas, Liberation Mono, monospace;
	font-size: 0.875rem;
	line-height: 1.55;
	background-color: var(--content-surface);
	border: 1px solid var(--content-rule);
	border-radius: 8px;
	padding: 1rem 1.15rem;
	margin-block: 1.6em;
	overflow-x: auto;
}

/* A code element inside a pre is already framed by it */
.content pre :where(code, .code, .code-inline) {
	background: none;
	border: 0;
	padding: 0;
	font-size: inherit;
	white-space: pre;
}

/* Tables */
.content table {
	width: 100%;
	border-collapse: collapse;
	font-size: 0.9375rem;
	line-height: 1.5;
	margin-block: 1.8em;
}

.content :where(th, td) {
	padding: 0.55rem 0.75rem;
	text-align: start;
	vertical-align: top;
	border-block-end: 1px solid var(--content-rule);
}

.content th {
	font-weight: 600;
	color: var(--content-ink-strong);
}

/* Figures and images */
.content :where(img, figure) {
	display: block;
	height: auto;
	margin-block: 1.8em;
}

.content img {
	max-inline-size: 100%;
	border-radius: 8px;
}

.content figcaption {
	font-size: 0.875rem;
	color: var(--content-ink-muted);
	margin-block-start: 0.6em;
}

/* The figure already spaces itself, so its image does not add a second margin */
.content figure img {
	margin-block: 0;
}

/*
 * Dev blog.
 *
 * The feed is the section title and intro, then one <article class="post"> per
 * post: an h2.post-title linking to the post, the .post-meta line (author with
 * avatar, date, the post's language), then the post itself. A post opened on its
 * own page keeps its h1, with the same .post-meta line under it.
 */
/* The feed's header is a label for the feed, not a page title: the posts are the content */
.content .blog-header h1 {
	font-size: 1.375rem;
	font-weight: 500;
	margin-block-end: 0.15em;
}

.content .blog-header p {
	font-size: 0.875rem;
	color: var(--content-ink-muted);
	margin-block-end: 0;
}

.content .post {
	border-block-start: 1px solid var(--content-rule);
	margin-block-start: 3em;
	padding-block-start: 2.4em;
}

/* Right under the header the first post needs only its rule, not the full gap */
.content .blog-header + .post {
	margin-block-start: 1.2em;
	padding-block-start: 1.6em;
}

.content .post-title {
	margin-block-start: 0;
}

.content .post-title a {
	color: inherit;
	text-decoration: none;
}

.content .post-title a:hover {
	color: var(--content-link);
}

.content .post-meta {
	font-size: 0.875rem;
	color: var(--content-ink-muted);
	margin-block-end: 1.6em;
	display: flex;
	align-items: center;
	gap: 0.4em;
}

/* The author's face, round and small, so the line still reads as metadata */
.content .post-meta .post-avatar {
	inline-size: 2rem;
	block-size: 2rem;
	border-radius: 50%;
	object-fit: cover;
	margin: 0;
}

.content .post-meta span {
	color: var(--content-ink);
}

.content .post-more {
	margin-block-start: 3em;
	text-align: center;
}

/* Section break */
.content hr {
	border: 0;
	border-block-start: 1px solid var(--content-rule);
	opacity: 1;
	margin-block: 3em;
}

/*
 * Hierarchy trees.
 *
 * A structure diagram written as a plain nested list, so an article can show an
 * enterprise breakdown without any markup beyond <ul>/<li>. The connectors are
 * drawn in CSS: every child row gets an elbow, and the vertical stem stops at
 * the last child of its level.
 *
 *   <ul class="tree">
 *       <li><svg class="kraft-icon"><use href="#icon-Rabbit"></use></svg>Holding <span>Enterprise</span>
 *           <ul>
 *               <li><svg class="kraft-icon"><use href="#icon-Planet"></use></svg>Oak School <span>Legal Entity</span>
 *                   <ul>
 *                       <li><svg class="kraft-icon"><use href="#icon-Banknote"></use></svg>City Bank <span>Bank Account</span></li>
 *                   </ul>
 *               </li>
 *           </ul>
 *       </li>
 *   </ul>
 *
 * Both extras on a row are optional: the <svg> names a mark from the icon
 * sprite (see KraftIcons.jsx for the names), and the <span> holds the node kind,
 * set as a quiet chip after the name. Nest as deep as needed — the connectors
 * are level-agnostic.
 */
.content .tree {
	/* Indent per level, and where the elbow meets the row */
	--tree-indent: 1.15rem;
	--tree-arm: 0.7rem;
	--tree-stem: 0.85em;

	font-size: 0.9375rem;
	line-height: 1.5;
	margin-block: 1.8em;
}

.content .tree,
.content .tree ul {
	list-style: none;
	padding-inline-start: 0;
}

.content .tree li {
	position: relative;
	margin-block: 0;
}

.content .tree li + li {
	margin-block-start: 0.2em;
}

/* Children hang under the parent name, offset by one indent */
.content .tree ul {
	margin-block: 0.2em 0;
	padding-inline-start: var(--tree-indent);
}

.content .tree ul > li {
	padding-inline-start: calc(var(--tree-arm) + 0.45rem);
}

/* Vertical stem: full height of the row, clipped to the elbow on the last child */
.content .tree ul > li::before {
	content: '';
	position: absolute;
	inset-block: 0 0;
	inset-inline-start: 0;
	border-inline-start: 1px solid var(--content-rule);
}

.content .tree ul > li:last-child::before {
	inset-block-end: auto;
	block-size: var(--tree-stem);
}

/* Horizontal arm reaching from the stem to the row */
.content .tree ul > li::after {
	content: '';
	position: absolute;
	inset-block-start: var(--tree-stem);
	inset-inline-start: 0;
	inline-size: var(--tree-arm);
	border-block-start: 1px solid var(--content-rule);
}

/* The root node carries the whole diagram, so it is the one row set in strong ink */
.content .tree > li {
	color: var(--content-ink-strong);
	font-weight: 600;
}

.content .tree > li ul {
	color: var(--content-ink);
	font-weight: 400;
}

/*
 * Node marks. The article references the shared icon sprite by name
 * (<svg class="kraft-icon"><use href="#icon-Planet"></use></svg>), so a row
 * shows what kind of node it is before the name is read.
 *
 * Each kind carries its own hue, and the mark is matched on the symbol it
 * references — the article names the icon, the stylesheet colours it, so a row
 * never has to spell out its kind twice. Hues are muted enough that a deep tree
 * still reads as text with marks, not as a chart.
 */
.content .tree {
	--tree-mark-enterprise: #7c3aed;
	--tree-mark-entity: #2563eb;
	--tree-mark-bank: #0f9b6c;
	--tree-mark-cash: #d1477a;
	--tree-mark-account: #0e8ba8;
	--tree-mark-workgroup: #c2760c;
	--tree-mark-warehouse: #6b7280;
}

.content .tree .kraft-icon {
	inline-size: 1.15em;
	block-size: 1.15em;
	margin-inline-end: 0.45em;
	vertical-align: -0.24em;
	color: var(--content-ink-muted);
	stroke-width: 1.6;
}

.content .tree .kraft-icon:has(use[href='#icon-Rabbit'])    { color: var(--tree-mark-enterprise); }
.content .tree .kraft-icon:has(use[href='#icon-Planet'])    { color: var(--tree-mark-entity); }
.content .tree .kraft-icon:has(use[href='#icon-Banknote'])  { color: var(--tree-mark-bank); }
.content .tree .kraft-icon:has(use[href='#icon-PiggyBank']) { color: var(--tree-mark-cash); }
.content .tree .kraft-icon:has(use[href='#icon-Account'])   { color: var(--tree-mark-account); }
.content .tree .kraft-icon:has(use[href='#icon-Coins'])     { color: var(--tree-mark-account); }
.content .tree .kraft-icon:has(use[href='#icon-Workgroup']) { color: var(--tree-mark-workgroup); }
.content .tree .kraft-icon:has(use[href='#icon-Warehouse']) { color: var(--tree-mark-warehouse); }
.content .tree .kraft-icon:has(use[href='#icon-Box'])       { color: var(--tree-mark-warehouse); }
.content .tree .kraft-icon:has(use[href='#icon-Boxes'])     { color: var(--tree-mark-warehouse); }
.content .tree .kraft-icon:has(use[href='#icon-Package'])   { color: var(--tree-mark-warehouse); }

/* Dark theme: the same hues lifted, so they hold against the dark ground */
[data-bs-theme='dark'] .content .tree {
	--tree-mark-enterprise: #b39cf7;
	--tree-mark-entity: #7fb0ff;
	--tree-mark-bank: #4fd1a5;
	--tree-mark-cash: #f490b4;
	--tree-mark-account: #5cc8e0;
	--tree-mark-workgroup: #eab04a;
	--tree-mark-warehouse: #a5adba;
}

/* Node kind: a quiet chip, so the names stay the thing being read */
.content .tree li > span {
	display: inline-block;
	margin-inline-start: 0.45em;
	padding: 0.05em 0.45em;
	border: 1px solid var(--content-rule);
	border-radius: 999px;
	background-color: var(--content-surface);
	color: var(--content-ink-muted);
	font-size: 0.8125em;
	font-weight: 400;
	white-space: nowrap;
	vertical-align: baseline;
}

/*
 * Form mockups.
 *
 * A screenshot of an application form written as plain markup, so an article
 * can show what a card looks like without shipping an image or a live form.
 * Nothing here is a real control — every field is a <span> — so the block is
 * inert, copy-pastable and translatable like the rest of the prose.
 *
 *   <div class="form-mock">
 *       <div class="form-mock-row">
 *           <span>Template</span>
 *           <span class="text">legal.entity.mx</span>
 *       </div>
 *
 *       <div class="form-mock-band">General information</div>
 *
 *       <div class="form-mock-row">
 *           <span>Internal name</span>
 *           <span>Restaurants - La Polar</span>
 *       </div>
 *       <div class="form-mock-row">
 *           <span>Tax regime</span>
 *           <span class="select"><i>*</i>601 - General corporate</span>
 *           <span class="add"></span>
 *       </div>
 *       <div class="form-mock-row">
 *           <span>Note</span>
 *           <span></span>
 *       </div>
 *   </div>
 *
 * The rules of the block, in full:
 *
 *   - the first <span> of a row is its label, every later one is a value;
 *   - a value is drawn as a filled field by default, `.text` makes it plain
 *     text (a read-only line, no field behind it), `.select` adds the drop-down
 *     chevron, `.add` draws the small "add another" tile;
 *   - an empty <span> is an empty field — that is how a blank row is written;
 *   - several values stack in the field column and the label centers against
 *     the stack, which is how a repeatable field (many tax regimes) is shown;
 *   - `<i>` inside a value is the accent mark that fronts a chosen entry;
 *   - `.form-mock-band` is a section caption spanning the whole card;
 *   - the card draws its own panel: a hairline frame, lifted off the page, so
 *     it can be dropped into the prose as is;
 *   - `.form-mock` sits inside the article measure, so put it in a `.narrow`
 *     wrapper for a compact card or `.wide` for a full-width one.
 *
 * Rows carry a stub at the end standing in for the row's command button; the
 * plain-text rows drop it, since there is nothing to command.
 */
.content .form-mock {
	--form-mock-label: 11rem;
	--form-mock-gap: 0.5rem;
	--form-mock-stub: 2rem;
	--form-mock-accent: var(--content-link);
	--form-mock-field-bg: var(--content-surface);

	/* The panel the card sits on: lifted off the page, framed by a hairline */
	--form-mock-panel-bg: #fff;
	--form-mock-panel-shadow: 0 1px 2px rgba(0, 0, 0, 0.05), 0 8px 20px rgba(0, 0, 0, 0.05);

	/* The card is the query container, so a row folds on the card's own width */
	container: form-mock / inline-size;

	max-width: var(--measure);
	margin-block: 1.8em;
	margin-inline: auto;
	padding: 1.35rem 1.5rem 1.5rem;
	border: 1px solid var(--content-rule);
	border-radius: 10px;
	background-color: var(--form-mock-panel-bg);
	box-shadow: var(--form-mock-panel-shadow);
	font-size: 0.875rem;
	line-height: 1.5;
}

/* Dark theme: the panel lifts by lightening, and the drop shadow goes away */
[data-bs-theme='dark'] .content .form-mock {
	--form-mock-panel-bg: rgba(255, 255, 255, 0.04);
	--form-mock-panel-shadow: none;
}

/* The panel's own padding closes the card, so the last row drops its gap */
.content .form-mock > :last-child {
	margin-block-end: 0;
}

.content .form-mock-row {
	display: grid;
	grid-template-columns: var(--form-mock-label) minmax(0, 1fr) var(--form-mock-stub);
	align-items: center;
	gap: var(--form-mock-gap);
	margin-block-end: var(--form-mock-gap);
}

/* Label: quiet, top-aligned against a stack of values so it reads as its title */
.content .form-mock-row > span:first-child {
	grid-column: 1;
	grid-row: 1 / -1;
	align-self: center;
	color: var(--content-ink-muted);
	text-wrap: pretty;
}

/* Every later span is a value, and they stack down the field column */
.content .form-mock-row > span ~ span {
	grid-column: 2;
	min-height: 2rem;
	padding: 0.35rem 0.6rem;
	border: 1px solid transparent;
	border-radius: 3px;
	background-color: var(--form-mock-field-bg);
	color: var(--content-ink);
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/* The row's command stub: a fixed cell against the first field of the row */
.content .form-mock-row::after {
	content: '';
	grid-column: 3;
	grid-row: 1;
	height: 2rem;
	border-radius: 3px;
	background-color: var(--form-mock-field-bg);
}

/* A read-only line: the value is the text itself, so no field and no stub */
.content .form-mock-row > .text {
	padding-inline: 0;
	background: none;
	color: var(--content-ink-strong);
}

.content .form-mock-row:has(> .text)::after {
	visibility: hidden;
}

/* A chosen entry is fronted by its mark */
.content .form-mock-row > span ~ span > i {
	color: var(--form-mock-accent);
	font-style: normal;
	margin-inline-end: 0.5em;
}

/* Drop-down: the chevron is drawn here, so the markup stays free of SVG */
.content .form-mock-row > .select {
	/*
	 * Left as a block, not a flex row: the value then ellipsizes at the content
	 * edge and the chevron keeps the end padding to itself.
	 */
	position: relative;
	padding-inline-end: 1.9rem;
}

.content .form-mock-row > .select::after {
	content: '';
	position: absolute;
	inset-inline-end: 0.7rem;

	/*
	 * Centred on the field, not left at its static position: the mark is a
	 * square turned 45deg, so it is pulled back by half its own height and
	 * then a hair more — the V is bottom-heavy, so its optical centre sits
	 * above its geometric one.
	 */
	inset-block-start: 50%;
	transform: translateY(calc(-50% - 0.06em)) rotate(45deg);

	width: 0.42em;
	height: 0.42em;
	border-inline-end: 1.5px solid var(--content-ink-muted);
	border-block-end: 1.5px solid var(--content-ink-muted);
}

/* "Add another value": a tile, not a field, so it is sized to its mark */
.content .form-mock-row > .add {
	justify-self: start;
	width: 2.5rem;
	padding: 0;
	background: none;
	position: relative;
}

.content .form-mock-row > .add::before,
.content .form-mock-row > .add::after {
	content: '';
	position: absolute;
	inset-inline-start: 50%;
	inset-block-start: 50%;
	width: 0.85rem;
	height: 1.5px;
	background-color: var(--content-ink-muted);
	transform: translate(-50%, -50%);
}

.content .form-mock-row > .add::after {
	transform: translate(-50%, -50%) rotate(90deg);
}

/*
 * Section caption: centered over a rule that runs the width of the card, which
 * is how the application groups a card into its sections.
 */
.content .form-mock-band {
	display: flex;
	align-items: center;
	gap: 0.9rem;
	margin-block: 1.4em 0.9em;
	color: var(--form-mock-accent);
	font-size: 0.8125rem;
	text-align: center;
}

.content .form-mock-band::before,
.content .form-mock-band::after {
	content: '';
	flex: 1;
	border-block-start: 1px solid var(--content-rule);
}

/*
 * Cards side by side.
 *
 * Two forms next to each other is how an article shows the same concept under
 * two different templates — the fields differ, the card does not. The set is a
 * grid that reflows to one column when the article gets narrow, so put it in a
 * `.wide` wrapper when the two cards should have room:
 *
 *   <div class="form-mock-set wide">
 *       <div class="form-mock"> ... </div>
 *       <div class="form-mock"> ... </div>
 *   </div>
 *
 * A card in a set takes a tighter label column, since it now has half the width.
 */
.content .form-mock-set {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
	gap: 1.5rem 2.5rem;
	max-width: var(--measure);
	margin-block: 1.8em;
	margin-inline: auto;
}

.content .form-mock-set .form-mock {
	--form-mock-label: 7.5rem;
	--form-mock-stub: 1.25rem;

	/*
	 * width, not the grid item's default stretch: the card is its own query
	 * container, and a size-contained item does not stretch to its track — it
	 * shrinks to min-content instead, which folds the whole card to a sliver.
	 */
	width: 100%;
	max-width: none;
	margin-block: 0;
	font-size: 0.8125rem;
}

/*
 * Narrow card: the label moves above its field rather than squeezing it. This
 * is measured on the card, not the window, so a card in a two-column set folds
 * on its own width.
 */
@container form-mock (max-width: 17rem) {
	.content .form-mock-row {
		grid-template-columns: minmax(0, 1fr) var(--form-mock-stub);
	}

	.content .form-mock-row > span:first-child {
		grid-column: 1 / -1;
		grid-row: auto;
	}

	.content .form-mock-row > span ~ span {
		grid-column: 1;
	}

	.content .form-mock-row::after {
		grid-row: 2;
	}
}

/*
 * Flow diagrams.
 *
 * A sequence of stages written as a plain list, so an article can show a
 * lifecycle as boxes and lines without shipping an image.
 *
 *   <ol class="flow">
 *       <li>New</li>
 *       <li>Editing</li>
 *       <li class="is-optional">Special</li>
 *       <li class="is-optional">Verification/Approval</li>
 *       <li class="flow-fork">
 *           <ol>
 *               <li class="is-positive">Done</li>
 *               <li class="is-negative">Cancelled</li>
 *           </ol>
 *       </li>
 *   </ol>
 *
 * A plain <li> is a required stage, joined to the next by a plain line (no
 * arrowhead — the reading order is always left to right, top to bottom, so
 * the line alone is enough). `is-optional` marks a stage that only exists in
 * some variants of the flow, drawn dashed and quieter. `is-positive` /
 * `is-negative` tone a stage as a good/bad outcome. `flow-fork` draws no box
 * of its own — its nested <ol> is simply a boxed line down the side (the
 * list's own left border) with one short line reaching from it into each
 * outcome.
 *
 * The same markup, as `<ul class="flow flow-key">` with plain text instead
 * of further stages, makes a legend explaining the tones (see operations.html).
 */
.content .flow {
	--flow-gap: 2rem;

	display: flex;
	flex-wrap: wrap;
	align-items: center;
	list-style: none;
	margin-block: 1.8em;
	padding-inline-start: 0;
	font-size: 0.9375rem;
}

/* Override the prose list rule (li + li gets top margin for a vertical list)
   — a row has no "next line" to space out, and the stray margin was throwing
   off align-items: center for every pill after the first */
.content .flow > li {
	margin-block-start: 0;
}

.content .flow > li,
.content .flow-fork li {
	position: relative;
	padding: 0.5em 1.1em;
	border: 1px solid var(--content-rule);
	border-radius: 999px;
	background-color: var(--content-surface);
	color: var(--content-ink-strong);
	white-space: nowrap;
}

/* The fork draws no box of its own — it is just the line to its outcomes */
.content .flow > li.flow-fork {
	padding: 0;
	border: 0;
	background: none;
}

.content .flow > li.is-optional {
	border-style: dashed;
	color: var(--content-ink-muted);
	background: none;
}

.content .flow li.is-positive {
	border-color: color-mix(in srgb, #0f9b6c 45%, var(--content-rule));
	color: #0f9b6c;
}

.content .flow li.is-negative {
	border-color: color-mix(in srgb, #b3435c 45%, var(--content-rule));
	color: #b3435c;
}

/* Line to the next stage */
.content .flow > li:not(:last-child) {
	margin-inline-end: var(--flow-gap);
}

.content .flow > li:not(:last-child)::after {
	content: '';
	position: absolute;
	inset-inline-start: 100%;
	inset-block-start: 50%;
	inline-size: var(--flow-gap);
	border-block-start: 1px solid var(--content-rule);
}

/* Key variant: the same boxes explaining their own tones, without the lines */
.content .flow.flow-key > li:not(:last-child) {
	margin-inline-end: 1.25rem;
}

.content .flow.flow-key > li:not(:last-child)::after {
	content: none;
}

/* Fork: the nested list's own left border is the shared line to both outcomes */
.content .flow-fork > ol {
	list-style: none;
	margin: 0;
	padding-inline-start: 1.1rem;
	border-inline-start: 1px solid var(--content-rule);
}

.content .flow-fork li + li {
	margin-block-start: 0.4em;
}

.content .flow-fork li::before {
	content: '';
	position: absolute;
	inset-inline-start: -1.1rem;
	inset-block-start: 50%;
	inline-size: 1.1rem;
	border-block-start: 1px solid var(--content-rule);
}

[data-bs-theme='dark'] .content .flow li.is-positive {
	color: #4fd1a5;
	border-color: color-mix(in srgb, #4fd1a5 45%, var(--content-rule));
}

[data-bs-theme='dark'] .content .flow li.is-negative {
	color: #e8899e;
	border-color: color-mix(in srgb, #e8899e 45%, var(--content-rule));
}

/*
 * Concept map (section index pages).
 *
 * `.concept-sentence` is a lead paragraph whose key nouns are links set as
 * coloured chips; `.topic-cards` is an <ol> of linked cards, one per concept.
 * Both are toned by the same `is-<concept>` classes, so a chip in the sentence
 * and its card below share a colour and read as one thing:
 *
 *   <a class="concept-chip is-agent" href="..."><svg class="kraft-icon">...</svg>an agent</a>
 *
 *   <ol class="topic-cards">
 *       <li class="is-agent"><a href="...">
 *           <svg class="kraft-icon">...</svg>
 *           <strong>Agents</strong>
 *           <span>One-line description.</span>
 *       </a></li>
 *   </ol>
 *
 * `.concept-aside` is a quiet, italic one-liner for a remark under the lead.
 */
.content {
	--concept-enterprise: #7c3aed;
	--concept-agent: #2563eb;
	--concept-item: #c2760c;
	--concept-operation: #0f9b6c;
	--concept-document: #d1477a;
}

[data-bs-theme='dark'] .content {
	--concept-enterprise: #b39cf7;
	--concept-agent: #7fb0ff;
	--concept-item: #eab04a;
	--concept-operation: #4fd1a5;
	--concept-document: #f490b4;
}

.content .is-enterprise { --concept: var(--concept-enterprise); }
.content .is-agent      { --concept: var(--concept-agent); }
.content .is-item       { --concept: var(--concept-item); }
.content .is-operation  { --concept: var(--concept-operation); }
.content .is-document   { --concept: var(--concept-document); }

.content .concept-sentence {
	margin-block: 1.6em;
	padding: 1.1em 1.4em;
	border-inline-start: 3px solid var(--content-rule);
	border-radius: 0 0.5rem 0.5rem 0;
	background-color: var(--content-surface);
	font-size: 1.1875rem;
	line-height: 2.1;
	color: var(--content-ink-strong);
}

.content .concept-chip {
	display: inline-flex;
	align-items: center;
	gap: 0.35em;
	padding: 0.05em 0.6em 0.05em 0.45em;
	border: 1px solid color-mix(in srgb, var(--concept) 40%, transparent);
	border-radius: 999px;
	background-color: color-mix(in srgb, var(--concept) 10%, transparent);
	color: var(--concept);
	font-weight: 600;
	line-height: 1.5;
	white-space: nowrap;
	text-decoration: none;
	transition: background-color 0.12s ease-in-out;
}

.content .concept-chip:hover,
.content .concept-chip:focus-visible {
	background-color: color-mix(in srgb, var(--concept) 20%, transparent);
}

.content .concept-chip .kraft-icon {
	inline-size: 1.05em;
	block-size: 1.05em;
}

.content .concept-aside {
	color: var(--content-ink-muted);
	font-style: italic;
}

.content .topic-cards {
	/* Neutral by default; an `is-<concept>` class on the <li> tones a card */
	--concept: var(--content-ink-muted);

	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));
	gap: 0.6rem;
	padding: 0;
	list-style: none;
}

/* Override the prose list rule: a grid cell has no "next line" to space out */
.content .topic-cards > li {
	margin: 0;
}

/* Icon on the left spanning both lines; title above, subtitle below */
.content .topic-cards a {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr);
	grid-template-rows: auto auto;
	column-gap: 0.85rem;
	align-items: start;
	height: 100%;
	padding: 0.75rem 0.9rem;
	background-color: var(--content-surface);
	color: var(--content-ink-muted);
	font-size: 0.875rem;
	line-height: 1.45;
	text-decoration: none;
	transition: background-color 0.12s ease-in-out;
}

/* A step past --content-surface, so it darkens on light and lifts on dark */
.content .topic-cards a:hover,
.content .topic-cards a:focus-visible {
	background-color: color-mix(in srgb, var(--content-ink-strong) 9%, transparent);
}

.content .topic-cards .kraft-icon,
.content .topic-cards a:not(:has(> .kraft-icon))::before {
	grid-row: 1 / span 2;
	inline-size: 2.25rem;
	block-size: 2.25rem;
	color: var(--concept);
}

/* A raster icon (<img class="kraft-icon">) sheds the article image spacing */
.content .topic-cards img.kraft-icon {
	inline-size: auto;
	block-size: auto;
	margin: 0.2rem 0 0;
	border-radius: 0;
}

/*
 * A card written without an icon gets a neutral page mark in its place, so the
 * titles in a list stay aligned whether or not every topic has its own icon.
 */
.content .topic-cards a:not(:has(> .kraft-icon))::before {
	content: '';
	background-color: var(--content-ink-muted);
	opacity: 0.6;
	-webkit-mask: var(--topic-card-placeholder) center / contain no-repeat;
	mask: var(--topic-card-placeholder) center / contain no-repeat;
	--topic-card-placeholder: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14 2.75H7A2.25 2.25 0 0 0 4.75 5v14A2.25 2.25 0 0 0 7 21.25h10A2.25 2.25 0 0 0 19.25 19V8L14 2.75Z'/%3E%3Cpath d='M13.75 3v3.5c0 .97.78 1.75 1.75 1.75H19M8.5 12.75h7M8.5 16.25h4.5'/%3E%3C/svg%3E");
}

.content .topic-cards strong {
	font-size: 0.9375rem;
	line-height: 1.4;
}

[data-bs-theme='dark'] .content {
	--content-ink: rgba(255, 255, 255, 0.82);
	--content-ink-strong: rgba(255, 255, 255, 0.95);
	--content-ink-muted: rgba(255, 255, 255, 0.55);
	--content-rule: rgba(255, 255, 255, 0.14);
	--content-surface: rgba(255, 255, 255, 0.06);
	--content-link: #6ea8fe;
}

/* Docs three-column layout: both side columns stick while the content scrolls */
.docs-sidebar > .position-sticky,
.docs-sidebar .position-sticky {
	top: 1rem;
	max-height: calc(100vh - 2rem);
	overflow-y: auto;
}

/*
 * Navigation tree (docs sidebar).
 *
 * Rows are transparent at rest, tinted on hover and tinted harder when
 * selected. A row runs flush to the left edge of the column and is rounded on
 * the right, so it reads as a pill growing out of the page edge.
 * Tints are plain black/white alphas, so they sit on any sidebar background.
 */
/* The rows reach the column edge themselves, so the column drops its padding */
.docs-sidebar:has(.docs-nav) {
	padding-inline-start: 0;
}

.docs-nav {
	--docs-nav-radius: 1.5rem;
	--docs-nav-indent: 0.85rem;
	--docs-nav-caret: 0.85rem;
	--docs-nav-bleed: calc(var(--bs-gutter-x, 1.5rem) * 0.5);

	--docs-nav-hover-bg: rgba(0, 0, 0, 0.05);
	--docs-nav-active-bg: rgba(0, 0, 0, 0.11);
	--docs-nav-color: rgba(0, 0, 0, 0.72);
	--docs-nav-hover-color: rgba(0, 0, 0, 0.92);
	--docs-nav-active-color: var(--bs-primary, #0d6efd);

	margin-inline-end: 0.5rem;
}

.docs-nav .nav {
	--bs-nav-link-padding-y: 0.3rem;
	--bs-nav-link-padding-x: 0.75rem;
	gap: 1px;
}

.docs-nav .nav-link {
	display: block;
	background-color: transparent;
	border-radius: 0 var(--docs-nav-radius) var(--docs-nav-radius) 0;
	color: var(--docs-nav-color);
	font-size: 0.9375rem;
	line-height: 1.3;
	padding-inline-start: calc(var(--bs-nav-link-padding-x) + var(--docs-nav-bleed));
	transition: background-color 0.12s ease-in-out, color 0.12s ease-in-out;
}

.docs-nav .nav-link:hover,
.docs-nav .nav-link:focus-visible {
	background-color: var(--docs-nav-hover-bg);
	color: var(--docs-nav-hover-color);
}

.docs-nav .nav-link:focus-visible {
	outline: 2px solid rgba(0, 0, 0, 0.35);
	outline-offset: -2px;
}

/* Selected row: called out by color, not weight, so rows never reflow */
.docs-nav .nav-link.is-active,
.docs-nav .nav-link.is-active:hover {
	background-color: var(--docs-nav-active-bg);
	color: var(--docs-nav-active-color);
}

/*
 * Section rows: the label is a link to the category index, the caret beside it
 * only opens the group. The caret sits on top of the link's left padding, so
 * the tinted pill still runs flush to the column edge and the whole row stays
 * clickable.
 */
.docs-nav .docs-nav-row {
	position: relative;
}

/* Sections reserve the caret's width, whether or not they have one, so every
 * section label starts on the same line */
.docs-nav .docs-nav-section > .docs-nav-row > .nav-link {
	padding-inline-start: calc(var(--bs-nav-link-padding-x) + var(--docs-nav-bleed) + var(--docs-nav-caret));
}

.docs-nav .docs-nav-caret {
	position: absolute;
	inset-block: 0;
	inset-inline-start: var(--docs-nav-bleed);
	z-index: 1;
	display: flex;
	align-items: center;
	justify-content: center;
	width: calc(var(--bs-nav-link-padding-x) + var(--docs-nav-caret));
	padding: 0;
	border: 0;
	border-radius: 0.375rem;
	background-color: transparent;
	color: var(--docs-nav-color);
	opacity: 0.6;
}

.docs-nav .docs-nav-caret:hover,
.docs-nav .docs-nav-caret:focus-visible {
	opacity: 1;
}

.docs-nav .docs-nav-caret:focus-visible {
	outline: 2px solid rgba(0, 0, 0, 0.35);
	outline-offset: -2px;
}

.docs-nav .docs-nav-caret svg {
	transition: transform 0.15s ease-in-out;
}

.docs-nav .docs-nav-caret.is-open svg {
	transform: rotate(90deg);
}

/* Child rows indent by padding, so the tint still reaches the column edge */
.docs-nav .docs-nav-items {
	margin-bottom: 0.35rem;
}

.docs-nav .docs-nav-items .nav-link {
	padding-inline-start: calc(var(--bs-nav-link-padding-x) + var(--docs-nav-bleed) + var(--docs-nav-caret) + var(--docs-nav-indent));
}

[data-bs-theme='dark'] .docs-nav {
	--docs-nav-hover-bg: rgba(255, 255, 255, 0.07);
	--docs-nav-active-bg: rgba(255, 255, 255, 0.14);
	--docs-nav-color: rgba(255, 255, 255, 0.72);
	--docs-nav-hover-color: rgba(255, 255, 255, 0.95);
	--docs-nav-active-color: #6ea8fe;
}

/*
 * Breadcrumbs.
 *
 * The trail sits above the article and is centered on the same --measure, so
 * its first crumb lines up with the left edge of the body text instead of the
 * column. Ink is a step quieter than the prose; the current page is the only
 * crumb that keeps the body ink.
 *
 * The trail also owns the lead-in space above the page title: the h1 opens its
 * own .content block, so the :first-child reset zeroes its top margin and this
 * margin-bottom is the whole gap between the trail and the title.
 */
.docs-breadcrumb-bar {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	max-width: var(--measure);
	margin-inline: auto;
	margin-bottom: 1.5rem;
}

.docs-breadcrumb {
	flex: 1;
	min-width: 0;
	margin: 0;
	font-size: 0.875rem;
	--bs-breadcrumb-divider-color: var(--content-ink-muted);
	--bs-breadcrumb-item-active-color: var(--content-ink);

	/* Undo the prose list treatment: no marker indent, no stacking gap */
	padding-inline-start: 0;
	align-items: center;
}

.docs-breadcrumb a {
	color: var(--content-ink-muted);
	text-decoration: none;
}

.docs-breadcrumb a:hover,
.docs-breadcrumb a:focus-visible {
	color: var(--content-link);
	text-decoration: underline;
}

.docs-breadcrumb li + li {
	margin-block-start: 0;
}

/* Phones: opens the navigation tree under the breadcrumb row */
.docs-nav-toggle {
	display: inline-flex;
	flex: none;
	align-items: center;
	justify-content: center;
	width: 2rem;
	height: 2rem;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: transparent;
	color: var(--content-ink);
}

.docs-nav-toggle:hover,
.docs-nav-toggle:focus-visible,
.docs-nav-toggle[aria-expanded='true'] {
	background-color: var(--content-surface);
}

.docs-nav-drawer {
	max-width: var(--measure);
	margin: -0.75rem auto 1.5rem;
	padding-block: 0.5rem;
	border-bottom: 1px solid var(--content-rule);
}

/* Inside the article column the tree flows with the page instead of sticking */
.docs-nav-drawer .position-sticky {
	position: static !important;
}

/*
 * Page outline (right docs column).
 *
 * The headings of the article being read, so a long page can be scanned and
 * jumped through. Quieter than the navigation tree on the left: no pills, just
 * a hairline down the side, with the section being read marked on it.
 */
.content :where(h2, h3) {
	/* A heading jumped to from the outline lands with a little air above it */
	scroll-margin-top: 1.5rem;
}

.docs-outline {
	--docs-outline-color: rgba(0, 0, 0, 0.6);
	--docs-outline-hover-color: rgba(0, 0, 0, 0.92);
	--docs-outline-active-color: var(--bs-primary, #0d6efd);
	--docs-outline-rule: rgba(0, 0, 0, 0.11);

	font-size: 0.875rem;
	line-height: 1.35;
}

.docs-outline-title {
	margin-block-end: 0.6rem;
	font-size: 0.75rem;
	font-weight: 600;
	letter-spacing: 0.07em;
	text-transform: uppercase;
	color: var(--docs-outline-color);
}

.docs-outline ul {
	list-style: none;
	margin: 0;
	padding: 0;
	border-inline-start: 1px solid var(--docs-outline-rule);
}

.docs-outline a {
	display: block;
	/* Pulled over the rule, so the active marker replaces it rather than doubling it */
	margin-inline-start: -1px;
	padding: 0.25rem 0 0.25rem 0.85rem;
	border-inline-start: 2px solid transparent;
	color: var(--docs-outline-color);
	text-decoration: none;
	transition: color 0.12s ease-in-out, border-color 0.12s ease-in-out;
}

.docs-outline .docs-outline-level-3 a {
	padding-inline-start: 1.65rem;
	font-size: 0.8125rem;
}

.docs-outline a:hover,
.docs-outline a:focus-visible {
	color: var(--docs-outline-hover-color);
}

.docs-outline a.is-active {
	color: var(--docs-outline-active-color);
	border-inline-start-color: var(--docs-outline-active-color);
}

[data-bs-theme='dark'] .docs-outline {
	--docs-outline-color: rgba(255, 255, 255, 0.6);
	--docs-outline-hover-color: rgba(255, 255, 255, 0.95);
	--docs-outline-active-color: #6ea8fe;
	--docs-outline-rule: rgba(255, 255, 255, 0.14);
}
