/* davidbogle.com - styles added after the 2022 port
 *
 * Deliberately separate from main.css. That file is a frozen record of the
 * 2022 theme, verified against its original SCSS by scripts/verify-css-port.mjs;
 * adding new rules there would make every addition read as unexplained drift.
 * New work goes here instead.
 *
 * Same vocabulary as the inherited theme: Rasa, #ff9a60 accent, grey scale
 * running #202020 / #404040 / #767676 / #a0a0a0 / #dfdfdf.
 *
 * THE GREYS, since there are two and the difference matters:
 *
 *   #767676  Secondary TEXT - the lead-in under a heading, nav links, dates,
 *            the empty state. Anything a reader actually reads. 4.54:1 on
 *            white, so it clears WCAG AA for normal text.
 *   #a0a0a0  The quiet tier - feed line, wall-label keys, post-list dates.
 *            2.62:1, which is below AA, and acceptable only because every one
 *            of these is ALSO marked as secondary by size, case or position.
 *            Lightness is decoration there, never the sole signal. Do not
 *            promote prose into it.
 *
 * The theme arrived with #808080 (3.95:1) in the first role. It failed AA by a
 * margin invisible to the eye and obvious to a contrast checker; #767676 is a
 * shade darker and fixes it. `.date-post` is overridden below rather than
 * edited in main.css, which stays frozen.
 */

/* --- Page frame ---------------------------------------------------------- */
/* The theme indents the page twice as far on the left as on the right:
 * `padding: 0 1em 0 2em` on .page-content and .header, doubling to 2em/4em
 * above 768px. On the 2022 blog the text column never reached the right edge,
 * so the imbalance never showed. This site fills the width on a phone, where
 * 33px of left margin against 17px of right is the first thing you notice.
 *
 * Only padding-right is set, so the left indent - which everything on the site
 * is aligned to, including the masthead - stays exactly where it was. Written
 * here rather than in main.css, which stays a frozen record of the 2022 theme;
 * see scripts/verify-css-port.mjs. */

.page-content,
.header {
	padding-right: 2em;
}

@media (min-width: 768px) {
	.page-content,
	.header {
		padding-right: 4em;
	}
}

/* --- Site navigation ---------------------------------------------------- */

.navigation {
	margin-top: 0.5em;
}

.navigation a {
	color: #767676;
}

.navigation a.is-current {
	color: #202020;
}

/* --- Post meta ---------------------------------------------------------- */

/* The date under a title. main.css sets it to #808080; this brings it onto the
 * same secondary grey as everything else, which matters most on a painting
 * page, where the date sits directly above the description and any mismatch
 * between two near-identical greys reads as a mistake rather than a system. */
.date-post {
	color: #767676;
}

/* Post tags used to sit here, under the date, in their own smaller style.
 * They now sit at the foot of the post and reuse `.tag-cloud` below - the same
 * rule /words/ uses - so the two treatments cannot drift apart. */

/* --- Post footer, and the slot comments would occupy -------------------- */

.post-footer {
	margin-top: 3em;
	padding-top: 1em;
	border-top: 1px solid #dfdfdf;
	color: #767676;
	font-size: 0.9em;
}

/* --- Listings ----------------------------------------------------------- */

/* The lead-in line that sits under a heading, before the real content: the
 * standfirst on /words/ and a painting's description. One rule for both, so
 * the two cannot drift into looking like different kinds of thing.
 *
 * Grey rather than italic, and that is a constraint rather than a preference:
 * every Rasa face in this theme is font-style: normal. `italic` would get a
 * browser-synthesized oblique - the upright face mechanically sheared, keeping
 * upright letterforms and distorting the strokes, which shows badly at weight
 * 300. Real italics would mean sourcing and shipping an italic file. */
.listing-intro,
.painting-description {
	color: #767676;
	margin-bottom: 1.5em;
}

/* One rule, two places: the tag block at the foot of a post and the wall label
 * at the foot of a painting. Both are "a quiet block, set off by a rule, after
 * the main content", and stating that as one rule rather than two sets of
 * matching numbers is what stops the two from drifting apart later. */
.tag-cloud,
.painting-label {
	margin-top: 2em;
	padding-top: 1em;
	border-top: 1px solid #dfdfdf;
	font-size: 0.9em;
}

.tag-cloud a ~ a {
	margin-left: 0.7em;
}

/* --- Feed --------------------------------------------------------------- */

.feed-link {
	margin-top: 2em;
	font-size: 0.85em;
	color: #a0a0a0;
}

/* --- Empty states ------------------------------------------------------- */

/* No italic, for the reason given at .listing-intro: none of the Rasa faces
 * here has one, so `font-style: italic` renders as a synthesized shear. Italic
 * is the convention for an empty state, but a convincing-looking convention
 * drawn badly is worse than the grey doing the job on its own. */
.empty {
	color: #767676;
}

/* --- Drafts ------------------------------------------------------------- */
/* Development-only; drafts are never written in a production build. */

.draft-banner {
	margin-bottom: 1.5em;
	padding: 0.5em 0.8em;
	border-left: 2px solid #ff9a60;
	background: #f6f0ea;
	color: #404040;
	font-size: 0.85em;
}

/* --- Images ------------------------------------------------------------- */
/* The ported theme sets `img { max-width: calc(100% - 3em) }`, which suits an
 * image sitting inside running text but leaves gallery work inset by 56px
 * against a 700px measure. Paintings should occupy the full measure. Overridden
 * here rather than edited in main.css, which stays a frozen record of the 2022
 * theme - see scripts/verify-css-port.mjs. */

.gallery-image,
.painting-images img {
	max-width: 100%;
}

/* --- Gallery ------------------------------------------------------------ */
/* The homepage. Deliberately plain: the paintings supply all the colour, so
 * the grid itself stays out of the way. */

.gallery {
	list-style: none;
	/* Top margin matches what every other page gets from its <h1>, so the
	 * gallery starts at the same height as "Words" or "About" rather than
	 * jumping up against the nav. The homepage is the one page with no heading
	 * of its own, so the zero from this list reset had nothing above it to
	 * supply the space.
	 *
	 * 2.4em, not a measured pixel value: main.css sets `h1..h6 { margin: 1em 0
	 * 0.3em }` at `h1 { font-size: 2.4em }`, and 1em of a 2.4em heading is
	 * 2.4em of body text. Same arithmetic the theme does, written the same way.
	 * The other three sides stay zeroed - that part is the list reset. */
	margin: 2.4em 0 0 0;
	padding: 0;
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
	gap: 2em 1.5em;
}

.gallery-item {
	margin: 0;
	padding: 0;
}

.gallery-item a {
	display: block;
	color: #404040;
}

/* The link underline animation from the theme is for running text; on a
 * picture it just draws a line under the image. */
.gallery-item a:before {
	display: none;
}

.gallery-image {
	display: block;
	width: 100%;
	height: auto;
	background: #e4e4e4;
}

.gallery-caption {
	display: block;
	margin-top: 0.5em;
	font-size: 0.9em;
}

.home-heading {
	margin-top: 2.5em;
}

/* --- A single painting --------------------------------------------------- */

/* The wall label. `.painting-label` shares its rule and spacing with
 * `.tag-cloud` above; what follows is only the two-column part.
 *
 * This replaces `.painting-details`, a single grey line of dot-separated spans
 * that rode under the date. Two problems, and spacing only fixed the first:
 * it crowded the date, and it was unlabelled - so `status: available` reached
 * the page as the bare word "available". */
.painting-label {
	display: grid;
	grid-template-columns: max-content 1fr;
	gap: 0.5em 1.5em;
	color: #404040;
	/* The key and its value are different sizes - 15.1px against 18.9px - and
	 * grid's default (stretch) starts each cell's text at the top of its own
	 * box. The smaller font's baseline then lands 2px high, which reads as a
	 * label that is very slightly floating. Aligning on the baseline is what
	 * makes a pair sit on one line rather than merely near one. */
	align-items: baseline;
}

.painting-label dt {
	color: #a0a0a0;
	font-size: 0.8em;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}

.painting-label dd {
	margin: 0;
}

/* Status is the one field that is a state rather than a description, and the
 * only one a visitor might act on, so it carries the theme's accent.
 *
 * As a dot, not as text colour: #ff9a60 on white measures about 2.2:1, well
 * under the 4.5:1 needed for small text. A coloured marker beside dark text
 * gets the emphasis without making the word itself hard to read. */
.painting-status:before {
	content: "";
	display: inline-block;
	width: 0.5em;
	height: 0.5em;
	margin-right: 0.5em;
	border-radius: 50%;
	background: #ff9a60;
}

/* .painting-description is styled with .listing-intro above - same role, one
 * rule. Nothing painting-specific left to say here. */

/* Images in justified rows: every image in a row is the SAME HEIGHT, and its
 * width follows the photo's own proportions. A tall portrait sits narrow beside
 * a wide landscape, both uncropped, and the row's bottom edge is straight.
 *
 * This replaced an equal-column grid, which had the failure the other way
 * round: forcing every photo to one width made a portrait tower over the
 * landscape next to it, and left the row bottoms ragged. Cropping to a common
 * ratio with object-fit would tidy both, and is not on the table - this is a
 * page for looking at the work, and trimming the work to square up a grid gets
 * the priority backwards.
 *
 * How it works, since it is not obvious from the numbers:
 *
 *   flex-basis  = ratio x --row-height   gives every image the width it would
 *                                        need to stand --row-height tall, so
 *                                        items that fit on one line already
 *                                        share a height.
 *   flex-grow   = ratio x 1000           distributes the leftover space in the
 *                                        same proportion, so they still share
 *                                        a height once stretched to the full
 *                                        measure.
 *
 * --row-height is NOMINAL. It decides only how many images land on a line;
 * flex-grow then stretches them to fill the measure, and that is what sets the
 * height you actually see. So a smaller nominal does not mean smaller images -
 * it means more of them per row.
 *
 * It is 19rem for slack, and the first version got this wrong in a way worth
 * recording. At 28rem two portraits needed 692px against a 700px measure - a
 * fit with 8px to spare, which held only at the widest layout. The ported
 * theme drops `.wrapper` to near-full-width below 800px, and on a window even
 * slightly narrower than that the pair no longer fit, so every image fell to
 * its own row: a layout asked to be horizontal, rendering vertical. 19rem
 * keeps two per row down to about a 500px measure while still refusing a third
 * at 700px.
 *
 * --row-height-max caps how tall a row may get, and handles the opposite
 * failure. A row holding a single image (its neighbour would not fit) has
 * flex-grow stretch that one image across the whole measure - a lone portrait
 * measured 933px beside rows of 448px, the towering-image problem arriving
 * from the other direction. The cap engages only on those rows, leaving a
 * little space at the right-hand end, which is the right trade against one
 * image at twice the scale of its siblings. */
.painting-images {
	/* The space before the images belongs HERE, not on the element above.
	 * What precedes this block varies - the description, body prose, or
	 * nothing at all when both are empty - so a margin-bottom on any one of
	 * them is a rule that only sometimes applies. */
	margin-top: 2em;
	--row-height: 19rem;
	--row-height-max: 30rem;
	display: flex;
	flex-wrap: wrap;
	gap: 1.5em;
}

.painting-images figure {
	margin: 0;
	min-width: 0;
	flex-grow: calc(var(--ratio) * 1000);
	flex-basis: calc(var(--ratio) * var(--row-height));
	max-width: calc(var(--ratio) * var(--row-height-max));
}

/* A painting photographed once is the hero of its own page, so it takes the
 * full measure instead of being capped like one image among several. Without
 * this, the cap above would shrink the five single-photo paintings on this
 * site back to roughly two thirds of the measure. */
.painting-images.is-single figure {
	flex-basis: 100%;
	/* Held at the reading measure rather than the full 1180px. A lone portrait
	 * spanning the wide layout would stand over 1500px tall - taller than the
	 * window it is being viewed in. */
	max-width: 700px;
}

/* There used to be a `:after { flex-grow: 1000000 }` here to stop the last row
 * stretching. It was the wrong tool: it absorbed ALL the slack on that row, so
 * a trailing image sat at exactly --row-height while full rows had grown well
 * past it - 304px against 404px, the last row visibly the runt. --row-height-max
 * already bounds that case, and bounds it the same way for every row, so the
 * spacer was a second mechanism solving a solved problem, less well. */

/* Without this the anchor stays inline and carries a line-height descender,
 * which shows up as a few stray pixels under every image. */
.painting-images figure a {
	display: block;
}

.painting-images img {
	display: block;
	width: 100%;
	height: auto;
	background: #e4e4e4;
}

.painting-images a:before {
	display: none;
}

.painting-back {
	margin-top: 2.5em;
	font-size: 0.9em;
}

/* --- Wide pages ---------------------------------------------------------- */
/* The gallery homepage opts out of the 700px reading measure via `wide: true`
 * in its front matter. Paintings at ~336px inside a measure chosen for reading
 * are cramped; text is not, so running content inside a wide page is pulled
 * back to 700px rather than the container being widened for everything.
 *
 * NOTE: two grid rules exist. `.gallery` above sets the 220px track for any
 * non-wide page; `.is-wide .gallery` below overrides it to 260px, and that is
 * the one the homepage actually uses. Read them together before changing
 * either - the first review of this code cited the 220px rule for a page
 * governed by the 260px one.
 *
 * This block used to carry a warning that index.njk's `sizes` hint and its
 * eager-loading "first row" both tracked the column count here, and had to be
 * changed together. That coupling is gone: eager loading is now first-tile-only
 * (correct at every width, since `auto-fill` makes the real row size vary), and
 * the `sizes` hint is deliberately approximate. The old comment had already
 * drifted out of date on its first outing, which is the argument against
 * documenting a derived pixel value in the first place. */

.page-content.is-wide {
	max-width: 1180px;
}

.is-wide > .wrapper > *:not(.gallery):not(.painting) {
	max-width: 700px;
}

/* A painting page is wide for the same reason the homepage is, but the
 * exemption has to be written at two levels: the wrapper's only child here is
 * the <article>, so capping direct children would cap everything inside it.
 * The article runs full width; its children go back to the reading measure,
 * except the image block. */
.is-wide .painting > *:not(.painting-images) {
	max-width: 700px;
}

.is-wide .gallery {
	grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
}
