/* ==========================================================================
   Design system — document layout only.

   This file adds no colours, sizes or spacing of its own. Every value here
   is a token from ../css/styles.css, so this page cannot drift away from
   the site it documents.
   ========================================================================== */

/* Three values here are documentation rather than design: the colour that
   marks a "do not", and the two that build the card in the don't column.
   None of them appears on the site, so none is a system token. Each has a
   dark counterpart holding the same contrast against its paper. */
:root {
	--warn: #8b4a2b;        /* 6.8:1 */
	--demo-card: #fafafa;
	--demo-shadow: rgba(0, 0, 0, 0.06);
}

@media (prefers-color-scheme: dark) {
	:root {
		--warn: #d38f6a;    /* 6.7:1 */
		--demo-card: #1f1f1f;
		--demo-shadow: rgba(0, 0, 0, 0.5);
	}
}

/* Contents. Sticky beside the sections, and it says which one you are in.
   Built from the sections themselves, so adding one adds its entry. */
.layout {
	display: flex;
	align-items: flex-start;
	gap: var(--s8);
	padding-top: var(--s8);
}

.layout .doc {
	flex: 1 1 auto;
	min-width: 0;
}

.toc {
	position: sticky;
	top: var(--s5);
	flex: none;
	width: 240px;
}

.toc__list {
	display: flex;
	flex-direction: column;
}

/* The heading only acts as a menu on a phone. */
.section__heading .chevron {
	display: none;
}

/* While the menu is open the heading is the menu's bar, so it says so. Both
   words occupy the same box and only their opacity differs — the bar does
   not resize, and nothing moves. */
.section__title {
	position: relative;
	min-width: 0;
}

.section__name {
	transition: opacity var(--t-open) ease-out;
}

.section__menu {
	position: absolute;
	inset: 0;
	opacity: 0;
	/* It lies over the name, so without this a copied heading reads ColourMenu. */
	user-select: none;
	transition: opacity var(--t-close) ease-in;
}

body.menu-open .section__heading.is-current .section__name {
	opacity: 0;
	transition: opacity var(--t-close) ease-in;
}

body.menu-open .section__heading.is-current .section__menu {
	opacity: 1;
	transition: opacity var(--t-open) ease-out;
}

.toc__item {
	display: flex;
	align-items: center;
	gap: var(--s3);
	padding: var(--s2) 0;
	color: var(--ink-muted);
}

/* A tick rather than a number: the section order carries no meaning, so
   numbering it would be decoration. Grey to ink, one ramp step longer. */
.toc__tick {
	flex: none;
	width: var(--s4);
	height: var(--rule-w);
	background: var(--grey);
	transition: width var(--t-confirm) ease, background-color var(--t-confirm) ease;
}

@media (hover: hover) {
	.toc__item:hover {
		color: var(--ink-strong);
	}

	.toc__item:hover .toc__tick {
		background: var(--ink-strong);
	}
}

.toc__item.is-current {
	color: var(--ink);
	font-weight: 500;
}

.toc__item.is-current .toc__tick {
	width: var(--s5);
	background: var(--ink);
}

@media (max-width: 1100px) {
	.layout {
		flex-direction: column;
		gap: 0;
	}

	/* One heading is the menu: the one for the section you are in, which is
	   the one at the top of the window. The others stay plain headings. */
	.section__heading.is-current {
		cursor: pointer;
	}

	.section__heading.is-current .chevron {
		display: block;
	}

	body.menu-open .section__heading .chevron {
		transform: rotate(180deg);
		color: var(--ink-strong);
	}

	/* The menu covers the page rather than hanging off it. Half-covered, the
	   page behind stays scrollable, and scrolling it moves the section you are
	   about to choose from. Covering also settles the transition: nothing in
	   the panel belongs to the heading and nothing unfolds out of it, so it
	   fades in where the drawer on the portfolio grows.

	   Its own scroll container, so a long list still reaches its end on a
	   short screen, and contain keeps that scroll from chaining to the page. */
	.toc {
		position: fixed;
		inset: 0;
		z-index: 3;
		width: auto;
		background: var(--paper);
		overflow-y: auto;
		overscroll-behavior: contain;
		opacity: 0;
		visibility: hidden;
		transition:
			opacity var(--t-close) ease-in,
			visibility 0s linear var(--t-close);
	}

	body.menu-open .toc {
		opacity: 1;
		visibility: visible;
		transition: opacity var(--t-open) ease-out;
	}

	/* And the page behind holds still. Covering it is not enough on its own:
	   a list that happens to fit has nothing of its own to scroll, so the drag
	   would pass straight through to the page. */
	body.menu-open {
		overflow: hidden;
	}

	/* The heading stays above the panel: it is the bar, not something covered. */
	body.menu-open .section__heading.is-current {
		z-index: 4;
	}

	/* --menu-top is the heading's own bottom edge, set as the menu opens. */
	.toc__list {
		padding: calc(var(--menu-top, 0px) + var(--s2)) var(--page-x) var(--s5);
	}
}

.doc {
	display: flex;
	flex-direction: column;
	gap: var(--s8);
	padding-bottom: var(--s8);
}

/* Sections reuse the site's sticky-row idiom, so scrolling the reference
   feels the same as scrolling the portfolio. */
.section {
	position: relative;
	border-top: var(--rule-w) solid var(--rule);
	/* Landing on a section brings the gap above it along, so the heading
	   arrives with room over it rather than jammed against the window edge.
	   The same step the sections are spaced by — one gap, stated once. */
	scroll-margin-top: var(--s8);
}


/* The heading holds one height whatever size its type is. A sticky element
   keeps its box in flow, so a changing height would pull the page up and
   down under it — and it has to stay a child of .section, because a sticky
   element only travels as far as its containing block. */

.section__heading {
	position: sticky;
	top: 0;
	z-index: 2;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--s4);
	height: calc(34px * 1.25 + var(--s4));
	background: var(--paper);
	font-size: 34px;
	font-weight: 300;
	line-height: 1.25;
	letter-spacing: -0.01em;
	transition:
		font-size var(--t-confirm) ease,
		font-weight var(--t-confirm) ease,
		letter-spacing var(--t-confirm) ease,
		line-height var(--t-confirm) ease;
}

/* Pinned to the top it steps back down to Strong, so a heading you have
   already read stops competing with the section under it. */
.section__heading.is-stuck {
	font-size: 16px;
	font-weight: 500;
	letter-spacing: 0;
}

/* Narrow enough and a long name wraps, so there the bar takes its height from
   its own name instead of holding one height for every section — a fixed
   height would drop the second line onto the section beneath it.

   Which means it cannot shrink as it pins either: the box would collapse
   under the text and pull the page up. So on a phone the heading stays at
   display size, and little is lost — the shrink made room beside a contents
   rail that a phone does not have. */
@media (max-width: 1100px) {
	.section__heading,
	.section__heading.is-stuck {
		height: auto;
		padding: var(--s2) 0;
		font-size: 34px;
		font-weight: 300;
		letter-spacing: -0.01em;
	}
}

.section__body {
	display: flex;
	flex-direction: column;
	gap: var(--s7);
	padding: var(--s5) 0 var(--s8);
}

.lede {
	max-width: var(--measure);
	display: flex;
	flex-direction: column;
	gap: var(--s4);
}

/* A row of specification: label, value, explanation. */
.spec {
	display: grid;
	grid-template-columns: 200px 220px minmax(0, 1fr);
	gap: var(--s5);
	align-items: baseline;
	padding: var(--s4) 0;
	border-top: var(--rule-w) solid var(--rule);
}

.spec:last-child {
	border-bottom: var(--rule-w) solid var(--rule);
}

.spec > :first-child {
	font-weight: 500;
}

.spec__value {
	color: var(--ink-strong);
	font-variant-numeric: tabular-nums;
}

.spec__note {
	color: var(--ink);
}

/* A specimen sits on its own line, with its explanation beneath it. */
.spec__stack {
	display: flex;
	flex-direction: column;
	gap: var(--s2);
	align-items: flex-start;
}

@media (max-width: 800px) {
	.spec {
		grid-template-columns: minmax(0, 1fr);
		gap: var(--s1);
	}
}

/* The colour table carries both schemes at once: a swatch each in front, then
   a column per scheme. Nothing here is a second palette — it is one row per
   token, read across. */
.swatches .spec {
	grid-template-columns: 60px 130px 170px 170px minmax(0, 1fr);
	gap: var(--s4);
	/* a swatch is a block, not a line of text — centre it against the row */
	align-items: center;
}

.swatch-pair {
	display: flex;
	gap: var(--s1);
}

/* The scheme you are in is inked; the one you are not recedes. Weight and
   grey, as everywhere else — there is no marker and no second colour. */
.scheme {
	color: var(--ink-muted);
	font-variant-numeric: tabular-nums;
}

.scheme[data-current] {
	color: var(--ink);
}

.scheme[data-fails] {
	color: var(--warn);
}

/* On a phone the swatch keeps its column and everything else stacks beside
   it. Left to wrap on its own the five cells reflow into three rows, which
   puts the note under the swatch in a 56px column, one word per line. */
@media (max-width: 800px) {
	.swatches .spec {
		grid-template-columns: 60px minmax(0, 1fr);
		align-items: start;
		gap: var(--s1) 0;
	}

	.swatches .spec > :first-child {
		grid-row: 1 / span 4;
	}

	.swatches .spec > :not(:first-child) {
		grid-column: 2;
	}
}

.swatch {
	display: block;
	width: 25px;
	height: 25px;
	border: var(--rule-w) solid var(--rule);
}

[data-scheme][data-current] {
	color: var(--ink);
	font-weight: 500;
}

/* Two- and three-up blocks for principles, rules and states. */
.grid-2,
.grid-3,
.grid-4 {
	display: grid;
	gap: var(--s5) var(--s7);
}

.grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

@media (max-width: 1100px) {
	.grid-3,
	.grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 800px) {
	.grid-2,
	.grid-3,
	.grid-4 { grid-template-columns: minmax(0, 1fr); }
}

.block {
	display: flex;
	flex-direction: column;
	gap: var(--s2);
}

.block__title {
	font-weight: 500;
}

.block__body {
	color: var(--ink);
}

/* A numbered principle, with the test that lets you fail it. */
.principle {
	display: grid;
	grid-template-columns: 50px 260px minmax(0, 1fr);
	gap: var(--s6);
	padding: var(--s5) 0;
	border-top: var(--rule-w) solid var(--rule);
}

.principle:last-child {
	border-bottom: var(--rule-w) solid var(--rule);
}

.principle__no { color: var(--ink-muted); }
.principle__name { font-weight: 500; }

.principle__body {
	display: flex;
	flex-direction: column;
	gap: var(--s2);
	max-width: var(--measure);
}

.test { color: var(--ink-muted); }
.test b { color: var(--ink-strong); }

@media (max-width: 1100px) {
	.principle {
		grid-template-columns: 50px minmax(0, 1fr);
		gap: var(--s4);
	}
	.principle__body { grid-column: 2; }
}

/* Bulleted rule lists, using a rule-coloured dash rather than a bullet. */
.rules {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: var(--s4) var(--s7);
	padding: var(--s4) 0;
	border-top: var(--rule-w) solid var(--rule);
	border-bottom: var(--rule-w) solid var(--rule);
}

@media (max-width: 800px) {
	.rules { grid-template-columns: minmax(0, 1fr); }
}

.rule-item {
	display: flex;
	gap: var(--s3);
	align-items: baseline;
}

.rule-item::before {
	content: "";
	flex: none;
	width: var(--s2);
	height: var(--rule-w);
	background: var(--grey);
	transform: translateY(-0.35em);
}

/* Specimens are exhibits, not working furniture: the real components are
   sticky and stack above the page, which would let them ride over the
   section heading. Pin them down and take the interaction off. */
.specimen {
	padding-bottom: 0;
}

.specimen .item__heading {
	position: static;
	z-index: auto;
}

.specimen .row {
	cursor: default;
}

.specimen .row[data-state="hover"] {
	background: var(--hover);
}

.specimen .chevron[data-state="open"] {
	transform: rotate(180deg);
	color: var(--ink-strong);
}

/* Layout specimens. The bands below are real bands — only their page rhythm
   is suppressed, so seven shapes fit on one screen instead of seven. */
.shapes .band {
	padding-block: 0;
	border-top: 0;
}

.slot {
	padding: var(--s5) var(--s3);
	background: var(--fill);
	color: var(--ink-muted);
	text-align: center;
}

.case {
	display: flex;
	flex-direction: column;
	gap: var(--s3);
	padding: var(--s5) 0;
	border-top: var(--rule-w) solid var(--rule);
}

.case:last-child {
	border-bottom: var(--rule-w) solid var(--rule);
}

.case__head {
	display: flex;
	gap: var(--s3);
}

.case__note {
	max-width: var(--measure);
}

/* The grid drawn as itself. Its columns are set from a real band at load, so
   there is no second twelve to keep in step. Below the collapse there is one
   column and nothing to draw. */
.ruler {
	display: grid;
	gap: var(--gutter);
}

.ruler > * {
	height: var(--s5);
	background: var(--fill);
}

@media (max-width: 1100px) {
	.ruler {
		display: none;
	}
}

/* Specimen shelves. */
.shelf {
	display: flex;
	flex-wrap: wrap;
	gap: var(--s5);
	align-items: center;
}

.icon-set {
	display: flex;
	flex-wrap: wrap;
	gap: var(--s7);
}

.icon-cell {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--s2);
}

.icon {
	width: 20px;
	height: 20px;
	color: var(--ink-strong);
}

.icon-cell span { color: var(--ink-muted); }

/* Do / don't pairs. */
.pair {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: var(--s7);
	padding: var(--s5) 0;
	border-top: var(--rule-w) solid var(--rule);
}

.pair:last-child { border-bottom: var(--rule-w) solid var(--rule); }

@media (max-width: 800px) {
	.pair { grid-template-columns: minmax(0, 1fr); gap: var(--s5); }
}

.pair__side {
	display: flex;
	flex-direction: column;
	gap: var(--s3);
}

.pair__label { font-weight: 500; }
.pair__label--dont { color: var(--warn); }
.pair__note { color: var(--ink-muted); }

/* The space ramp. Its columns live here rather than on the element, so the
   single-column rule above can still take over on a phone. */
@media (min-width: 801px) {
	.ramp .spec {
		grid-template-columns: 90px 150px minmax(0, 1fr);
	}
}

.ramp-bar {
	display: block;
	height: var(--s2);
	background: var(--ink-strong);
}

/* Deliberately wrong specimens, for the don't column only. */
.demo-card {
	padding: var(--s3) var(--s4);
	background: var(--demo-card);
	border: var(--rule-w) solid var(--fill);
	border-radius: 8px;
	box-shadow: 0 1px 3px var(--demo-shadow);
}

.demo-faint { color: var(--grey); }

.storyboard {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: var(--s6);
}

@media (max-width: 1100px) {
	.storyboard { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.frame {
	display: flex;
	flex-direction: column;
	gap: var(--s3);
}

.frame__box {
	height: 150px;
	overflow: clip;
	border-top: var(--rule-w) solid var(--rule);
	border-bottom: var(--rule-w) solid var(--rule);
	padding: var(--s3) 0;
}

.frame__fill {
	width: 100%;
	background: var(--fill);
}
