/**
 * Single project
 *
 * The fixed top of a project page — see single-project.php and the two parts in
 * template-parts/. Not a block stylesheet: there is no block.json to declare
 * it, so inc/enqueue.php loads it on `is_singular( 'project' )` only.
 *
 * @package Norwegian_Flagstone
 */

.nf-project__gallery {

	/* Gutter between the pictures, matching the Projects block's card grid. */
	--nf-project-gap: clamp(1rem, 2.5vw, 1.5rem);
}

/* Header -------------------------------------------------------------------- */

/*
 * The way back to the listing, above the title. The stack's gap is built for
 * the space between a title and a paragraph, which under a one-line link reads
 * as a gap with nothing in it — so the link pulls its own bottom margin in and
 * sits with the title it belongs to.
 *
 * Flex rather than inline, so the arrow and the words stay on one line and the
 * gap between them is a gap and not a space character that can wrap.
 *
 * The underline is on the label inside and not on the link, which is what keeps
 * there being one of them. A flex container paints its own text decoration and
 * its blockified items paint the inherited one again at their own position, so
 * an underlined flex link draws two lines a couple of pixels apart. Moving the
 * decoration inside also keeps it off the arrow, which is a glyph and not a
 * word — and a descendant cannot opt out of an ancestor's decoration, so this
 * is the only place the choice can be made.
 *
 * The offset is left alone because text-underline-offset inherits, so the label
 * already has the 0.2em the `a` rule in base.css sets. The thickness is
 * repeated because text-decoration-thickness does *not* inherit: without it the
 * label falls back to `auto`, which the browser scales with the font — and at
 * this size that came out thinner than every other link on the page.
 */
.nf-project__back {
	align-items: center;
	color: var(--nf-color-text-muted);
	display: inline-flex;
	font-size: var(--nf-fs-small);
	gap: var(--nf-space-2xs);
	line-height: var(--nf-lh-body);
	margin-block-end: calc(var(--nf-space-m) * -0.5);
	text-decoration: none;
}

.nf-project__back-label {
	text-decoration: underline;
	text-decoration-thickness: 1px;
}

.nf-project__back:hover,
.nf-project__back:focus {
	color: var(--nf-color-link-hover);
}

/*
 * The arrow leans back on hover — a couple of pixels, which is enough to say
 * the link goes somewhere without becoming an animation.
 */
.nf-project__back-icon {
	transition: transform var(--nf-duration-fast) var(--nf-ease);
}

.nf-project__back:hover .nf-project__back-icon {
	transform: translateX(-0.125rem);
}

@media (prefers-reduced-motion: reduce) {

	.nf-project__back-icon {
		transition: none;
	}
}

/*
 * Looser than body copy: this is a single centred paragraph with nothing
 * around it, and at the reading measure a tight leading makes it read as a
 * caption rather than as the project's description.
 */
.nf-project__intro {
	line-height: var(--nf-lh-loose);
}

/* Meta ---------------------------------------------------------------------- */

/*
 * The same labelled facts as the meta line under a card in the Projects block,
 * so the two read as one vocabulary — and, as there, even columns whatever the
 * count, so Material / Surface / Style space themselves across the measure
 * instead of bunching in the middle.
 *
 * `auto-fit` rather than the card's `grid-auto-flow: column`, because this row
 * has to survive a phone: four descriptors would each get 80px of a 320px
 * screen in fixed columns, where here they wrap to two rows of two.
 */
.nf-project__meta {
	display: grid;
	gap: var(--nf-space-m) var(--nf-space-s);
	grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
	margin: 0;
	padding-block-start: var(--nf-space-2xs);

	/*
	 * .nf-stack--center centres its children, so without this the grid takes
	 * its own content width and the even columns quietly collapse.
	 */
	width: 100%;
}

.nf-project__meta-item {
	display: flex;
	flex-direction: column;
	gap: 0.125rem;
	min-width: 0;
}

.nf-project__meta-label {
	color: var(--nf-color-text-muted);
	font-size: var(--nf-fs-small);
	line-height: var(--nf-lh-body);
}

.nf-project__meta-value {
	color: var(--nf-color-text);
	font-size: var(--nf-fs-small);
	font-weight: var(--nf-font-weight-medium);
	line-height: var(--nf-lh-body);
	margin: 0;
}

/* Gallery ------------------------------------------------------------------- */

/*
 * Justified rows. Each row is a flex line whose items grow in proportion to
 * their own aspect ratio, and that one detail is what the whole layout turns
 * on: give every item `flex-grow: <its ratio>` against a zero basis and the
 * widths come out proportional to the ratios — which means every item in the
 * row resolves to the *same height*, and the row fills its width exactly,
 * whatever the gap happens to be.
 *
 * So the arithmetic in inc/image-rows.php only has to choose where the rows
 * break. It never needs the container's pixel width, and it does not need the
 * gap to be exact — the browser settles both, where they are actually known.
 */

.nf-project__grid {
	display: flex;
	flex-direction: column;
	gap: var(--nf-project-gap);
	list-style: none;
	margin: 0;
	padding: 0;
}

.nf-project__row {
	display: flex;
	gap: var(--nf-project-gap);

	/* base.css spaces stacked list items; the gap owns that here. */
	margin: 0;
}

.nf-project__cell {
	/*
	 * `--nf-project-ratio` is written per image by PHP. The fallback is only
	 * for an attachment whose dimensions could not be read.
	 */
	flex: var(--nf-project-ratio, 1.5) 1 0;
	margin: 0;

	/*
	 * A caption's longest word would otherwise put a floor under the cell's
	 * width and push the row out of true, so this has to be zero.
	 */
	min-inline-size: 0;
}

/*
 * The frame owns the shape, not the image. An image-optimisation plugin
 * (Imagify, ShortPixel, EWWW) rewrites <img> into <picture><source><img> and
 * moves the class onto the wrapper — so a ratio set on `.nf-project__image`
 * ends up on a box that is no longer the image, which leaves the photographs at
 * their own proportions. Same fix, and the same reasoning, as the Projects,
 * Card slider and Image Slider blocks.
 *
 * It is a link to the original file, so it is also the click target and carries
 * the affordance for one.
 */
.nf-project__frame {
	aspect-ratio: var(--nf-project-ratio, 1.5);
	border-radius: var(--nf-radius-l);
	cursor: zoom-in;
	display: block;
	overflow: hidden;
	position: relative;
}

.nf-project__frame:focus-visible {
	outline: 2px solid var(--nf-gull);
	outline-offset: 3px;
}

/*
 * Named rather than `> *`: the link also contains the screen-reader label, and
 * stretching that to fill the frame would put a 100%-tall clipped span over the
 * photograph. The three selectors cover the image, the <picture> that may have
 * replaced it, and the image inside that.
 */
.nf-project__frame > img,
.nf-project__frame > picture,
.nf-project__frame picture img {
	block-size: 100%;
	display: block;
	inline-size: 100%;

	/*
	 * There is nothing to crop — the frame's ratio *is* the image's ratio — but
	 * the ratio is rounded to four places on the way through PHP, so `cover`
	 * absorbs the sub-pixel rather than letting a hairline of background show.
	 */
	object-fit: cover;
	transition: transform var(--nf-duration-slow) var(--nf-ease);
}

.nf-project__caption {
	color: var(--nf-color-text-muted);
	font-size: var(--nf-fs-small);
	margin-top: var(--nf-space-2xs);
}

/* Responsive ---------------------------------------------------------------- */

/*
 * Every width breakpoint lives here, at the foot of the file, and not beside
 * the component it adjusts. A media query carries no specificity of its own, so
 * one written above a base rule loses to it on source order — which reads as
 * the query simply not working. Same arrangement, and the same reason, as
 * planner.css.
 */

/*
 * One image per row on a phone. A justified row of three would be 83px tall at
 * 390px wide — a strip, not a photograph — so below the breakpoint the rows
 * stack and every image takes its own natural height.
 *
 * `flex` has to be reset, not just the direction: in a column the grow factor
 * would distribute *height* in proportion to each ratio, which is the opposite
 * of what the ratio means here and would fight the frame's aspect-ratio.
 */
@media (max-width: 47.9375em) {

	.nf-project__row {
		flex-direction: column;
	}

	.nf-project__cell {
		flex: 0 0 auto;
	}
}

/*
 * Hover zoom. Gated on `no-preference` and on a real pointer, the way the Image
 * Slider does it: base.css already strips the easing under reduced motion, and
 * this keeps the scale from applying at all. `any-hover` rather than `hover`
 * because a laptop with a touchscreen has both, and the mouse should still get
 * the effect.
 */
@media (prefers-reduced-motion: no-preference) and (any-hover: hover) {

	.nf-project__frame:hover > img,
	.nf-project__frame:hover > picture,
	.nf-project__frame:hover picture img {
		transform: scale(1.03);
	}
}
