
:root {
	--gutter: 1rem;

	/* Default vertical breathing room for modules. Fluid — scales with viewport height.
	   Individual modules can override via `padding-block: X` as needed. */
	--module-block-padding: clamp(40px, 8vh, 120px);
}

body {
	display: flex;
	flex-direction: column;
	min-height: 100vh; 
	/* be at least a full viewport height */
	/* consider 100svh and 100dvh too */
}

main {
	flex-grow: 1;
	/* fill up available space which happens push the footer down to the bottom */

	/* padding-top: 1rem;  */
	/* breathing room below sticky header - this shouldn' be needed... */
}

inner-column {
	display: block;
	/*	width: 98%; maybe? */
	width: 100%; /* it might not seem nessesary if you have the content */

	/* max-width: 1200px; *//* could be a variable in settings */ */
	margin-inline: auto; /* horizontally center this by default */

	/* container-type: inline-size; - fights with sub grid (see "Why subgrid
	   and container queries don't share this grid" below) */
}

/* Account for sticky header on page sections */
.page-section {
	scroll-margin-top: 4rem;
}

:root {
	--layout: 1fr 1fr 1fr;

	@media (width >= 700px) {
		--layout: 1fr 1fr 1fr 1fr 1fr 1fr;
	}

	@media (width >= 1000px) {
		--layout:
			1fr
			clamp(50px, 6vw, 100px)
			repeat(12, clamp(40px, 5vw, 80px))
			clamp(50px, 6vw, 100px)
			1fr;
	}
}


.page-content {
	/* border: 3px solid red; */

	/* Grow to fill remaining viewport height (body is flex-column, min-height: 100vh).
	   Keeps the footer pinned to the bottom on short pages instead of floating up. */
	flex: 1;

	/* $todo: breathing room between the last module and the site-footer.
	   Tricky because emphasis scopes use flush-edge backgrounds — a margin
	   on the last module breaks the flush, a padding on .page-content paints
	   a page-bg stripe that may fight the last module's color. Options to try
	   when the need is real: (a) padding-block-end on .page-content (simplest,
	   watch backgrounds), (b) a targeted rule on .page-section:last-child
	   (doesn't solve featured/full bleed), (c) a deliberate "closing spacer"
	   module that carries its own emphasis. Leave it until a concrete page
	   forces the decision. */

	display: grid;
	grid-template-columns: var(--layout);
	column-gap: var(--gutter);
	align-items: start;   /* items align to top of their row track */
	align-content: start; /* row tracks pack at top; leftover vertical space stays empty (flex:1 still pins the footer) */

	padding-bottom: 50px;
}


/*
	Layout participants and how they relate.

	<article> — semantic landmark wrapper for content pages (workshop,
	resource, etc.). Kept as a real block (NOT display: contents — that
	strips the landmark from the accessibility tree and breaks position).
	Inside .page-content, it spans the full grid and exposes subgrid so its
	child .page-sections lay out as if they were direct grid items of
	.page-content.

	.page-section — its own grid using the shared --layout token. Doesn't
	inherit via subgrid, so it stands alone and can be nested anywhere.

	page-module — block by default. It's a grid ITEM of its section, placed
	via grid-column. Modules that need internal column-aware layout (e.g.
	text/figure with featured prominence) opt into subgrid on themselves —
	see page-module.css. This keeps the default safe: drop a module in
	anywhere and it works, no surprises.

	inner-column — block by default. Modules that need it as a grid for
	internal placement declare so locally.
*/

/*
	Why subgrid and container queries don't share this grid (2026-09-18).

	The original intent: one grid at the top, inherited by subgrid at every
	level, with inner-column as the size container so a module could lay
	itself out from the width it was actually given (normal vs featured vs
	full — different widths at the same viewport, which @media can't see).

	That can't be built. It's a catch-22 on one node:
	- container-type makes an element an independent formatting context
	  (CSS Conditional 5).
	- a grid container forced into an independent formatting context is
	  not a subgrid — grid-template-columns computes to none (CSS Grid 2).
	So the element you measure can't also pass the tracks down. It fails
	silently: children collapse into one implicit column. No wrapper fixes
	it — the container has to be an ancestor of whatever asks, so it always
	sits between the grid and the asker.

	The rule that falls out: each branch has one switch point. Above it,
	real shared tracks (subgrid) and nothing is measurable. Below it,
	measurable (@container) and the real grid is gone.

	What we do instead, on purpose:
	- .page-section redeclares var(--layout) rather than subgridding. The
	  middle columns are viewport-sized, so the copy lines up exactly.
	- A module that needs tracks inside opts into subgrid locally, and
	  sizes itself with @media + [data-prominence] — never @container.
	- container-type goes on leaves only: things placed on the grid that
	  pass no tracks along (code-study is the example). Their children can
	  query them; an element can never query itself.
	- An @container with no container ancestor does NOT fall back to the
	  viewport. It just never applies.

	Revisit only if CSS gains a way to measure a node while it keeps
	passing tracks through.
*/
.page-content > article {
	display: grid;
	grid-column: 1 / -1;
	grid-template-columns: subgrid;
}

/* Per-page decorative row-spanners (temp proof blocks for now).
   The narrow-width grid is 3 tracks — these placements target the wider
   grid, so hide below 1000px to avoid wrapping weirdness. */
.row-span-proof {
	@media (width < 1000px) {
		display: none;
	}
}


.page-section {
	grid-column: 1 / -1;

	display: grid;
	grid-template-columns: var(--layout);
	column-gap: var(--gutter);
}

page-module {
	grid-column: 1 / -1;
}

@media (width >= 1000px) {
	page-module {
		grid-column: 3 / -3;   /* reading band by default */
	}
}

ul[role='list'],
ol[role='list'] {
	list-style: none;
	margin: 0;
	padding: 0;
}
