/*
Theme Name: Madrona
Theme URI: https://github.com/JamieHunter/jme-photo-wordpress
Author: Jamie Hunter
Author URI: https://jmephotollc.com/
Description: Block theme for Madrona — a monthly cover magazine of editorial portraiture, photographed by J.Me Photo LLC. Dark by default, cover-led, built around a 4:5 cover plate.
Requires at least: 6.6
Tested up to: 7.1
Requires PHP: 8.0
Version: 0.3.7
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: madrona
Tags: block-theme, full-site-editing, magazine, photography, one-column, accessibility-ready
*/

/*
 * Block themes take their styling from theme.json.
 * Only rules that genuinely cannot be expressed as a token belong here.
 *
 * The palette was sampled from the November 2025 / December 2025 / January 2026
 * covers, not chosen. See docs/madrona/design-system.md for the measurements.
 */

/* ---------------------------------------------------------------
   The masthead.

   MADRONA is set edge to edge on the covers, and the width of the
   word is what makes it read as a masthead rather than a heading.
   theme.json has no viewport-relative font size, so the clamp lives
   in settings.custom and is applied here.

   letter-spacing is negative and scales with the size: at 12rem a
   fixed tracking that looks right at 3rem opens the word up and it
   stops being a lockup.
   --------------------------------------------------------------- */
.madrona-masthead,
.madrona-masthead .wp-block-site-title,
.madrona-masthead .wp-block-site-title a {
	font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--custom--type--masthead);
	font-weight: 700;
	line-height: 0.86;
	letter-spacing: -0.022em;
	text-transform: uppercase;
	text-decoration: none;
	text-wrap: nowrap;
	margin: 0;
}

/* ---------------------------------------------------------------
   Cover lines.

   The italic Didone caps in gold — "THE LATE SET", "THE TELL",
   "THE STILL POINT". A heading block style, so it is pickable in
   the editor instead of a hand-typed class.

   `cover-line` IS THE COVER-LINE COLOR AND NOTHING ELSE. Never a
   button, never a link, never a border. It survives as a signal
   only because it appears once or twice per view; the moment it
   becomes a UI color the palette collapses into "black and gold".

   Gold on the dark issues, teal on the light one. The December
   cover proves the ROLE travels while the hue does not, which is
   exactly what a role-named slug is for.
   --------------------------------------------------------------- */
.is-style-cover-line {
	font-family: var(--wp--preset--font-family--display);
	font-style: italic;
	font-weight: 500;
	text-transform: uppercase;
	letter-spacing: 0.01em;
	line-height: 1.02;
	color: var(--wp--preset--color--cover-line);
	margin-bottom: 0.15em;
}

/* The subject's name sits directly under its cover line, roman and
   larger — the pairing is the whole cover-line device. */
.is-style-cover-subject {
	font-family: var(--wp--preset--font-family--display);
	font-style: normal;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.005em;
	line-height: 1;
	margin-top: 0;
}

/* ---------------------------------------------------------------
   Labels — the letterspaced small caps voice.

   "PHOTOGRAPHED BY", "JANUARY 2026 - NO. 04", credits, folios.
   Mono rather than a Didone small cap: at 11px a hairline serif is
   a legibility problem, and tabular figures are what an issue
   number and a date actually want.
   --------------------------------------------------------------- */
.is-style-label {
	font-family: var(--wp--preset--font-family--label);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 500;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	line-height: 1.5;
	font-variant-numeric: tabular-nums;
	color: var(--wp--preset--color--muted);
	margin-bottom: 0;
}

/* ---------------------------------------------------------------
   The cover plate.

   Every cover is 4:5. That is not a crop preference — it is the
   proportion the covers were composed in, and a grid of covers
   that are not all the same shape stops reading as a newsstand.

   Applied as a block style so an editor picks it, and set on the
   wrapper as well as the img: inside a query loop the featured
   image block sizes the figure, and a ratio on the img alone
   leaves the figure the wrong height and the grid rows ragged.
   --------------------------------------------------------------- */
.is-style-cover-plate,
.is-style-cover-plate img {
	aspect-ratio: var(--wp--custom--cover--ratio);
	width: 100%;
	object-fit: cover;
	border-radius: 0;
}

/* A hairline, the width of a print rebate, in whichever color
   `muted` currently is. */
.is-style-cover-plate {
	box-shadow: 0 0 0 1px color-mix(in srgb, var(--wp--preset--color--muted) 38%, transparent);
}

/* Covers lift on hover in a grid — the only motion in the theme. */
@media (prefers-reduced-motion: no-preference) {
	.wp-block-post-template .is-style-cover-plate {
		transition: transform 220ms ease, box-shadow 220ms ease;
	}
	.wp-block-post-template li:hover .is-style-cover-plate {
		transform: translateY(-4px);
		box-shadow: 0 0 0 1px color-mix(in srgb, var(--wp--preset--color--muted) 70%, transparent),
		            0 18px 40px rgba(0, 0, 0, 0.55);
	}
}

/* ---------------------------------------------------------------
   Prints do not have rounded corners.

   theme.json sets radius 0 on images; this catches the plugin and
   embed cases that set their own.
   --------------------------------------------------------------- */
.wp-block-image img,
.wp-block-post-featured-image img,
.wp-block-cover {
	border-radius: 0;
}

/* ---------------------------------------------------------------
   Links on the two grounds.

   theme.json defines ONE global link color and has no conditional,
   so the second ground has to be named here. The palette is split
   by ground on purpose, and the measurements are why:

     muted           #B5A278   7.9:1 on canvas   2.1:1 on inverse
     inverse-accent  #264F53   2.2:1 on canvas   7.6:1 on inverse

   Neither works on both grounds. Rather than hunt for one color
   that does - and get a compromise - the slug carries the
   constraint: anything prefixed `inverse-` is for the light ground
   only, everything else for the dark one.

   The global link color is `ink`, because `ink` is the primary text
   color on whichever ground is current. That is also why the Light
   issue variation needs no style override at all.

   Any future light surface that is not .has-inverse-background-color
   belongs in the selector list below.
   --------------------------------------------------------------- */
.has-inverse-background-color :where(a:not(.wp-element-button)) {
	color: var(--wp--preset--color--inverse-accent);
}
.has-inverse-background-color :where(a:not(.wp-element-button)):hover {
	color: var(--wp--preset--color--canvas);
}

/* The focus ring is the one place `cover-line` may act as UI. A
   rare, high-attention color is exactly what a focus ring wants,
   and a ring is never persistent - it appears for one control at a
   time, which is the same discipline as one cover line per cover.
   This is the ONLY exception. */
:where(a, button, input, select, textarea, .wp-element-button):focus-visible {
	outline: 2px solid var(--wp--preset--color--cover-line);
	outline-offset: 3px;
}

/* ---------------------------------------------------------------
   Reading measure.

   Long-form runs at contentSize (44rem). Standfirst — the deck
   under a headline — runs at large size and needs a shorter
   measure or it reads as body copy set too big.
   --------------------------------------------------------------- */
.is-style-standfirst {
	max-width: 34rem;
	/* A constrained layout gives every child a narrower-than-container
	   treatment of `margin-left: auto; margin-right: auto`, so a standfirst
	   with its own max-width centers itself and drifts out of alignment with
	   the label and heading above it.

	   The standfirst must start where its SIBLINGS start, which is the left
	   edge of the content column - not the left edge of the container. Those
	   are the same place only while the container is no wider than
	   contentSize. Pin it to the container edge and any full-bleed parent
	   throws the standfirst out to the viewport edge on its own, while the
	   label and heading above it stay in the column. That is what single.html
	   does: the opening lockup sits inside an alignfull cover.

	   So offset by half the difference, clamped at zero. Inside a column or a
	   contentSize-wide group the difference is negative, max() returns 0, and
	   this is exactly the old `margin-inline: 0 auto` - which is why
	   page-issue and archive-intro are unaffected.

	   !important is not laziness here: core's layout rule carries !important
	   itself, so no amount of specificity wins. This is the one place in the
	   theme that needs it, and it is why - the sister theme's trick of
	   stacking :not() selectors only works against core's :where() rules,
	   which this is not. */
	margin-inline: max(
		0px,
		(100% - var(--wp--style--global--content-size)) / 2
	) auto !important;
	font-size: var(--wp--preset--font-size--large);
	line-height: 1.42;
	color: var(--wp--preset--color--ink);
}

/* Drop the orphan gap above the first and below the last child of a
   painted group — a section that starts with a paragraph should not
   have a blank band above it. */
.wp-block-group.has-background > *:first-child { margin-block-start: 0; }
.wp-block-group.has-background > *:last-child  { margin-block-end: 0; }

/* ---------------------------------------------------------------
   Header navigation.

   Item spacing has to be set on the container, not the block: core
   gives the container `gap: inherit`, and the responsive-overlay
   wrappers in between are not flex, so an inherited gap resolves to
   `normal`. Learned on the sister theme; same fix applies here.
   --------------------------------------------------------------- */
header .wp-block-navigation .wp-block-navigation__container {
	gap: clamp(1rem, 1.6vw, 1.5rem);
}

.wp-block-navigation .wp-block-navigation-item__content {
	font-family: var(--wp--preset--font-family--label);
	font-size: var(--wp--preset--font-size--x-small);
	letter-spacing: 0.12em;
	text-transform: uppercase;
	text-decoration: none;
}

.wp-block-navigation .wp-block-navigation-item__content:hover,
.wp-block-navigation .wp-block-navigation-item__content:focus-visible {
	text-decoration: underline;
	text-underline-offset: 0.35em;
}

footer .wp-block-navigation .wp-block-navigation__container {
	gap: 0.35rem;
}


/* ---------------------------------------------------------------
   Pop-over ("peek") cards.

   Ported from the sister theme on 6 September 2026 so the covers on
   the front page can be previewed without leaving it. The script in
   assets/js/peek.js is generic - it activates only on images the
   editor opted in with a block style, and every word the card shows
   comes from that block's own fields. These rules only style the
   overlay.

   Two styles, two behaviours:

     is-style-peek       (core/image) - click pins a card. For a
                         standalone image that is not itself a link.
     is-style-peek-link  (core/image and core/post-featured-image) -
                         hover previews, click follows the link. For a
                         cover that already goes somewhere; pinning a
                         card in front of a link would be in the way.
   --------------------------------------------------------------- */

.wp-block-image.is-style-peek { cursor: zoom-in; }

/*
 * "Preview on hover" post cards. The card is a link, so the cursor stays
 * a pointer - it must not promise a zoom it does not give.
 */
.wp-block-post-featured-image.is-style-peek-link,
.wp-block-image.is-style-peek-link { cursor: pointer; }

/*
 * The caption belongs to the pop-over card, not the page — but this file
 * is also handed to the editor by add_editor_style(), and a caption that
 * is display:none there cannot be seen or edited. Hide it on the front
 * end only; in the editor show it, marked as what it is.
 */
.wp-block-image.is-style-peek > figcaption { display: none; }

.editor-styles-wrapper .wp-block-image.is-style-peek > figcaption {
	display: block;
	padding-left: 8px;
	border-left: 2px solid var(--wp--preset--color--muted);
	opacity: 0.8;
}

.editor-styles-wrapper .wp-block-image.is-style-peek > figcaption::before {
	content: "Pop-over card \2014 title: Settings \203A Advanced";
	display: block;
	font-size: 0.65em;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	color: var(--wp--preset--color--muted);
}

/* The hidden attribute must win over our display rules. */
.madrona-peek-overlay[hidden],
.madrona-peek-pop[hidden] { display: none !important; }

/* Hover popover: anchored over the image, no backdrop. */
.madrona-peek-pop {
	position: fixed;
	z-index: 9999;
	margin: 0;
	display: flex;
	flex-direction: column;
	background: var(--wp--preset--color--surface);
	border: 1px solid var(--wp--preset--color--muted);
	box-shadow: 0 10px 34px rgba(0, 0, 0, 0.28);
	padding: 8px;
	cursor: zoom-in;
}

.madrona-peek-pop > img {
	display: block;
	width: 100%;
	height: auto;
}

.madrona-peek-overlay {
	position: fixed;
	inset: 0;
	z-index: 9999;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 24px;
	background: color-mix(in srgb, var(--wp--preset--color--ink) 62%, transparent);
	backdrop-filter: blur(2px);
}

.madrona-peek-card {
	position: relative;
	margin: 0;
	max-width: min(92vw, 720px);
	max-height: 92vh;
	display: flex;
	flex-direction: column;
	background: var(--wp--preset--color--surface);
	border: 1px solid var(--wp--preset--color--muted);
	box-shadow: 0 18px 50px rgba(0, 0, 0, 0.35);
	padding: 10px;
}

.madrona-peek-card > img {
	display: block;
	width: auto;
	height: auto;
	max-width: 100%;
	max-height: calc(92vh - 110px);
	object-fit: contain;
	margin: 0 auto;
}

.madrona-peek-close {
	position: absolute;
	top: -14px;
	right: -14px;
	width: 32px;
	height: 32px;
	border-radius: 50%;
	border: 1px solid var(--wp--preset--color--muted);
	background: var(--wp--preset--color--surface);
	color: var(--wp--preset--color--ink);
	font-size: 20px;
	line-height: 1;
	cursor: pointer;
}

.madrona-peek-meta {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 4px 16px;
	padding: 10px 4px 2px;
	font-size: 0.85rem;
	color: var(--wp--preset--color--muted);
}

