/*
 * seventhree — supplementary styles
 *
 * theme.json owns the design tokens (colour, type scale, spacing, layout).
 * This file only handles what theme.json cannot express: the /// motif,
 * interaction states, and the two bespoke list layouts.
 */

/* ---------------------------------------------------------------------------
   1. Foundations
   ------------------------------------------------------------------------ */

html {
	-webkit-text-size-adjust: 100%;
}

body {
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	text-rendering: optimizeLegibility;
}

::selection {
	background: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--base);
}

/* A single visible focus treatment for every interactive element. Orange is
   otherwise reserved for the logo, so it reads unmistakably as "you are here". */
:where(a, button, input, textarea, select, summary, [tabindex]):focus-visible {
	outline: 2px solid var(--wp--preset--color--accent);
	outline-offset: 3px;
}

/* Core injects the skip link; restyle it to match the brand. */
.skip-link:focus {
	background: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--base);
	font-family: var(--wp--preset--font-family--mono);
}

@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
		scroll-behavior: auto !important;
	}
}

/* ---------------------------------------------------------------------------
   2. The /// motif
   ------------------------------------------------------------------------ */

/* Header nav items, echoing "/// HOME" from the original site. */
.st-header .wp-block-navigation-item__content::before {
	content: "/// ";
	color: var(--wp--preset--color--contrast);
	transition: color 0.18s ease;
}

.st-header .wp-block-navigation-item__content:hover::before,
.st-header .wp-block-navigation-item__content:focus::before,
.st-header .current-menu-item .wp-block-navigation-item__content::before {
	color: var(--wp--preset--color--accent);
}

/* The current page keeps its slashes orange but the label stays white, so the
   marker reads as position rather than as a hover state that got stuck. */
.st-header .current-menu-item .wp-block-navigation-item__content {
	color: var(--wp--preset--color--contrast);
}

/* Utility: an eyebrow label above a section, e.g. "/// SERVICES". Apply the
   class to any heading or paragraph via the block editor's Advanced panel. */
.st-eyebrow {
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--small);
	letter-spacing: 0.18em;
	text-transform: uppercase;
}

.st-eyebrow::before {
	content: "/// ";
	color: var(--wp--preset--color--accent);
}

/* Page titles carry the motif too, so a bare page like Contact still reads as
   part of the set rather than as a stray heading. */
.st-page-title::before {
	color: var(--wp--preset--color--accent);
	content: "/// ";
}

/* Half the default post-title size — 1–1.75rem against 2–3.5rem.
 *
 * Scoped to page titles rather than set on core/post-title, so case study
 * headlines keep their full weight. The h1 in the selector is doing real work:
 * WordPress emits block styles as :root :where(.wp-block-post-title), and a
 * bare class would tie on specificity and be settled by source order. Adding
 * the element name wins outright, whichever stylesheet loads first.
 */
h1.st-page-title {
	font-size: clamp(1rem, 0.66rem + 1.45vw, 1.75rem);
}

/* Decorative slash rule, used in place of a plain separator. */
.st-rule {
	border: 0;
	color: var(--wp--preset--color--hairline);
	font-size: var(--wp--preset--font-size--small);
	letter-spacing: 0.4em;
	line-height: 1;
	overflow: hidden;
	white-space: nowrap;
	-webkit-user-select: none;
	user-select: none;
}

.st-rule::before {
	content: "////////////////////////////////////////////////////////////////////////////////////////////////";
}

/* ---------------------------------------------------------------------------
   3. Header
   ------------------------------------------------------------------------ */

/* Header type is 1.5x its original size at desktop — 13px to 19.5px — but
 * scales rather than sitting fixed. Fixed, the logo and four nav items would
 * wrap on a laptop; instead they ease back down and reach the original size
 * around 700px, just before the mobile overlay takes over.
 */
.st-header {
	font-size: clamp(0.8125rem, 0.41rem + 0.93vw, 1.21875rem);
	letter-spacing: 0.14em;
	text-transform: uppercase;
}

/* Sized here rather than through the block's width attribute, which emits an
   inline style on the <img> and would beat any responsive rule. */
.st-header .wp-block-site-logo {
	width: max(140px, min(252px, 20vw));
}

.st-header .wp-block-site-logo img {
	display: block;
	height: auto;
	width: 100%;
}

.st-header .wp-block-navigation {
	font-size: inherit;
	letter-spacing: inherit;
}

/* The front page shows the logo full size in the hero immediately below, so the
 * header copy is redundant there and only there.
 *
 * Hidden with CSS rather than given its own header template part: a second part
 * would create a second navigation menu, and the two would drift apart the first
 * time a nav item changed. One header, one menu, one line of CSS.
 */
body.home .st-header .wp-block-site-logo {
	display: none;
}

/* With the logo gone the flex row has a single child, and space-between would
   park the nav on the left. */
body.home .st-header .wp-block-group.alignwide {
	justify-content: flex-end;
}

/* Below 600px the nav collapses to core's overlay. Make the toggle match. */
.st-header .wp-block-navigation__responsive-container-open,
.st-header .wp-block-navigation__responsive-container-close {
	color: var(--wp--preset--color--contrast);
}

/* The mobile menu overlay.
 *
 * Core paints it white and blacks the text whenever the navigation block has no
 * colour of its own:
 *   .wp-block-navigation:not(.has-background)
 *     .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay)
 *     { background-color: #fff }
 *
 * That scores (0,5,0). The block now declares overlayBackgroundColor and
 * overlayTextColor, which is the supported way to answer it — but those rules
 * are load-bearing enough on a black site to be worth stating outright rather
 * than depending on attribute plumbing alone.
 */
.st-header .wp-block-navigation__responsive-container.is-menu-open {
	background-color: var(--wp--preset--color--base) !important;
	color: var(--wp--preset--color--contrast) !important;
	padding-top: var(--wp--preset--spacing--50);
}

/* Core forces `color: inherit !important` onto the items inside an open
   overlay, so the links have to be told again here. */
.st-header .wp-block-navigation__responsive-container.is-menu-open a,
.st-header .wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation-item__content {
	color: var(--wp--preset--color--contrast) !important;
}

.st-header .wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation-item__content {
	font-size: var(--wp--preset--font-size--large);
}

/* ---------------------------------------------------------------------------
   4. Hero
   ------------------------------------------------------------------------ */

/* The hero logo is sized entirely here rather than via the block's width
   attribute — that attribute emits an inline style on the <img>, which would
   win over any responsive rule and pin the logo to a fixed pixel width. */
.st-hero .wp-block-site-logo {
	margin-inline: auto;
	max-width: 820px;
	width: 100%;
}

.st-hero .wp-block-site-logo img {
	display: block;
	height: auto;
	width: 100%;
}

/* The tagline sets on one line, sized to the width of its container.
 *
 * Courier is monospaced, so the line width is exactly predictable: 46
 * characters at 0.6em advance, less 0.02em of letter-spacing each, is 26.68em.
 * Dividing the container by that gives 3.74cqw as the largest size that still
 * fits; 3.6cqw leaves a small safety margin for font fallback differences.
 *
 * cqw rather than vw is what makes the editor match the published page. vw
 * measures the browser window, but the Site Editor renders the page inside a
 * narrower canvas — so a vw-sized headline looks correct in one and overflows
 * in the other. cqw measures this element's own container, which is the same
 * box in both.
 */
.st-hero {
	container-type: inline-size;
}

.st-hero__tagline {
	font-size: 3.6cqw;
	margin-inline: auto;
	max-width: none;
	white-space: nowrap;
}

/* One line stops being legible on a narrow phone — 46 monospaced characters
   across 375px works out at under 12px. Below this width it wraps instead. */
@media (max-width: 480px) {
	.st-hero__tagline {
		font-size: var(--wp--preset--font-size--x-large);
		max-width: 22ch;
		text-wrap: balance;
		white-space: normal;
	}
}

/* ---------------------------------------------------------------------------
   5. Slideshow
   ------------------------------------------------------------------------ */

/* A core Gallery block carrying the st-slides class.
 *
 * Slides share a single grid cell and crossfade between them. Everything is
 * gated on .st-js, so a visitor without JavaScript gets the plain gallery —
 * the same images, all at once instead of in sequence.
 *
 * Stacking is keyed to .st-js rather than to the .is-slideshow class the script
 * adds, so it applies at first paint. Waiting for the script is what made the
 * slides appear side by side for a moment and then snap into position.
 */
.st-js .st-slides {
	display: grid;
	gap: 0;
	/* An explicit column is what makes slides fill the width. Left to the
	   implicit `auto` track, the column sizes itself from content whose own
	   width is a percentage of that column — circular, and browsers settle it
	   by shrinking the slide while the gallery stays full width. */
	grid-template-columns: minmax(0, 1fr);
	position: relative;
}

.st-js .st-slides > figure.wp-block-image {
	/* These photographs run from 1.6:1 to 1.9:1, so natural heights would make
	   the section jump taller and shorter as it cycles. A fixed ratio also gives
	   the box a height before the images download, so the intersection observer
	   cannot see a zero-height element and pause the slideshow on load. */
	aspect-ratio: var(--st-slide-ratio, 16 / 9);
	display: block;
	grid-column: 1;
	grid-row: 1;
	opacity: 0;
	transition: opacity 0.9s ease;
}

/* Before the script marks a slide active, show the first one. This also covers
   a gallery holding a single image, which the script leaves alone entirely. */
.st-js .st-slides:not(.is-slideshow) > figure.wp-block-image:first-child {
	opacity: 1;
}

.st-js .st-slides.is-slideshow > figure.wp-block-image.is-active {
	opacity: 1;
}

/* Inactive slides are transparent but still laid out, so without this they
   would sit on top of the active one and swallow its clicks. */
.st-js .st-slides.is-slideshow > figure.wp-block-image:not(.is-active) {
	pointer-events: none;
}

/* Slide width is the one place `!important` earns its keep here.
 *
 * Core ships a width rule for gallery children at every column count —
 * columns-1 through columns-8, plus columns-default, plus special cases for
 * galleries holding exactly one or two images. Each is written as
 * `figure.wp-block-image:not(#individual-image)`, where no element with that id
 * exists anywhere; it is there purely to borrow an ID's specificity so gallery
 * widths survive contact with theme styles. They score from (1,4,1) to (1,6,1),
 * and the applicable one changes with the number of slides in the gallery.
 *
 * Out-specifying a moving target across eleven rules means writing something
 * unreadable that still breaks the day a slide is added or removed. Declaring
 * the intent once is honest and stable. The scope is a single element inside
 * one component, so nothing downstream needs to override it.
 *
 * `margin` and `max-width` sit outside the important declaration deliberately —
 * they only need to beat the (1,3,1) base rule, and anything given ID-level
 * specificity here would also outrank the `.is-active` rule that reveals the
 * slide. That is exactly how an earlier version rendered a correctly sized
 * black box with every slide invisible.
 */
html.st-js .st-slides > figure.wp-block-image:not(#individual-image) {
	margin: 0;
	max-width: none;
	width: 100% !important;
}

.st-js .st-slides > figure.wp-block-image img {
	display: block;
	height: 100%;
	object-fit: cover;
	width: 100%;
}

.st-slides__controls {
	align-items: center;
	background: rgb(0 0 0 / 70%);
	bottom: 0;
	display: flex;
	gap: 0.5rem;
	padding: 0.6rem 0.75rem;
	position: absolute;
	right: 0;
	z-index: 2;
}

.st-slides__dot {
	background: var(--wp--preset--color--muted);
	border: 0;
	cursor: pointer;
	height: 3px;
	padding: 0;
	transition: background-color 0.18s ease;
	width: 22px;
}

.st-slides__dot:hover,
.st-slides__dot[aria-current="true"] {
	background: var(--wp--preset--color--accent);
}

.st-slides__toggle {
	background: none;
	border: 0;
	cursor: pointer;
	height: 14px;
	margin-left: 0.35rem;
	padding: 0;
	position: relative;
	width: 12px;
}

/* Pause and play are drawn in CSS rather than set as glyphs — Courier has no
   dependable character for either, and the browser would substitute a face at
   odds with everything around it. */
.st-slides__toggle::before,
.st-slides__toggle::after {
	background: var(--wp--preset--color--contrast);
	content: "";
	inset-block: 0;
	position: absolute;
	transition: background-color 0.18s ease;
	width: 4px;
}

.st-slides__toggle::before { left: 0; }
.st-slides__toggle::after { right: 0; }

.st-slides__toggle:hover::before,
.st-slides__toggle:hover::after {
	background: var(--wp--preset--color--accent);
}

/* Paused: the two bars become a single play triangle. */
.is-paused .st-slides__toggle::before {
	background: transparent;
	border-bottom: 7px solid transparent;
	border-left: 11px solid var(--wp--preset--color--contrast);
	border-top: 7px solid transparent;
	inset-block: 0;
	width: 0;
}

.is-paused .st-slides__toggle:hover::before {
	border-left-color: var(--wp--preset--color--accent);
}

.is-paused .st-slides__toggle::after {
	display: none;
}

/* ---------------------------------------------------------------------------
   6. Services list
   ------------------------------------------------------------------------ */

.st-services {
	border-top: 1px solid var(--wp--preset--color--hairline);
}

.st-service {
	border-bottom: 1px solid var(--wp--preset--color--hairline);
	display: grid;
	gap: 0 var(--wp--preset--spacing--30);
	grid-template-columns: 4ch 1fr;
	padding-block: var(--wp--preset--spacing--30);
}

.st-service__index {
	color: var(--wp--preset--color--accent);
	font-size: var(--wp--preset--font-size--small);
	grid-column: 1;
	grid-row: 1;
	letter-spacing: 0.08em;
	margin: 0;
	padding-top: 0.45em;
}

.st-service__title {
	grid-column: 2;
	grid-row: 1;
	margin: 0;
}

.st-service__body {
	color: var(--wp--preset--color--muted);
	grid-column: 2;
	margin: 0.6em 0 0;
	max-width: 58ch;
}

@media (max-width: 600px) {
	.st-service {
		grid-template-columns: 1fr;
	}

	.st-service__body {
		grid-column: 1;
	}
}

/* ---------------------------------------------------------------------------
   7. Portfolio
   ------------------------------------------------------------------------ */

/* Portfolio grid ----------------------------------------------------------
   Two large image cards per row, each one a single link through to the case
   study. The image carries the project; the text sits on top of it. */

.st-work-grid {
	display: grid;
	gap: var(--wp--preset--spacing--30);
	grid-template-columns: repeat(2, minmax(0, 1fr));
	list-style: none;
	margin: 0;
	padding: 0;
}

.st-work-grid > li {
	margin: 0;
}

/* Laid out as a grid rather than with absolute positioning.
 *
 * The click target is a pseudo-element stretched from the title's link, and an
 * absolutely positioned element is measured against its nearest positioned
 * ancestor. With the caption absolutely positioned, that ancestor was the
 * caption itself — so the "whole card" hit area only ever covered the text
 * strip along the bottom. In grid the caption stays in normal flow, leaving
 * .st-card as the containing block and the stretch covering the whole tile.
 */
.st-card {
	aspect-ratio: 3 / 2;
	/* Visible when a project has no image yet, so the card still has presence
	   instead of collapsing to its text. */
	background-color: #0b0b0b;
	border: 1px solid var(--wp--preset--color--hairline);
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	grid-template-rows: 1fr auto;
	overflow: hidden;
	position: relative;
	transition: border-color 0.18s ease;
}

.st-card:hover,
.st-card:focus-within {
	border-color: var(--wp--preset--color--accent);
}

/* Spans both rows so the image fills the tile behind the caption. */
.st-card__media {
	grid-column: 1;
	grid-row: 1 / -1;
	margin: 0;
	overflow: hidden;
}

.st-card__media img {
	height: 100%;
	object-fit: cover;
	width: 100%;
}

/* A gradient rather than a flat dim: the top of the image stays fully visible
   and only the area behind the text is darkened, so legibility never costs the
   photograph. */
.st-card__body {
	align-self: end;
	background: linear-gradient(
		to top,
		rgb(0 0 0 / 92%) 0%,
		rgb(0 0 0 / 75%) 45%,
		rgb(0 0 0 / 0%) 100%
	);
	grid-column: 1;
	grid-row: 2;
	padding: var(--wp--preset--spacing--40) var(--wp--preset--spacing--30)
		var(--wp--preset--spacing--30);
	/* Above the image, which spans this row too. */
	z-index: 1;
}

.st-card .st-card__meta {
	align-items: baseline;
	color: var(--wp--preset--color--muted);
	display: flex;
	flex-wrap: wrap;
	font-size: var(--wp--preset--font-size--small);
	gap: 0 0.6em;
	letter-spacing: 0.14em;
	margin: 0 0 0.5em;
	text-transform: uppercase;
}

/* Divides discipline from date. Sits on the second child rather than between
   fixed elements, so a project with no discipline assigned shows the date alone
   without a stray leading slash. */
.st-card .st-card__meta > * + *::before {
	color: var(--wp--preset--color--hairline);
	content: "/ ";
}

/* The taxonomy terms render as links, but the whole card is already one link;
   letting them capture clicks would give the tile two destinations. */
.st-card__meta a {
	color: inherit;
	pointer-events: none;
}

.st-card__title {
	font-size: clamp(1.125rem, 0.95rem + 0.9vw, 1.625rem);
	letter-spacing: -0.01em;
	margin: 0;
}

.st-card__title a {
	color: var(--wp--preset--color--contrast);
	transition: color 0.18s ease;
}

/* One link per card, stretched over the whole tile. The image and the terms are
   deliberately not links, so the card is a single tab stop rather than three.
   z-index 2 puts the hit area above the caption's own stacking. */
.st-card__title a::after {
	content: "";
	inset: 0;
	position: absolute;
	z-index: 2;
}

.st-card:hover .st-card__title a,
.st-card__title a:focus-visible {
	color: var(--wp--preset--color--accent);
}

.st-card__excerpt {
	color: var(--wp--preset--color--muted);
	display: -webkit-box;
	font-size: var(--wp--preset--font-size--small);
	-webkit-line-clamp: 2;
	line-clamp: 2;
	-webkit-box-orient: vertical;
	margin: 0.6em 0 0;
	overflow: hidden;
}

.st-card__excerpt p {
	margin: 0;
}

.st-card__excerpt .wp-block-post-excerpt__more-text {
	display: none;
}

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

	.st-card {
		aspect-ratio: 4 / 3;
	}
}

/* Row list ----------------------------------------------------------------
   Still used by the blog index and search results. The portfolio moved to the
   card grid above. */
/* The list bleeds out by the amount each row is padded, so the hover highlight
   has breathing room around the text while the text itself stays aligned with
   the headings above it — and every rule, top and bottom, lines up. */
.st-work-list {
	border-top: 1px solid var(--wp--preset--color--hairline);
	list-style: none;
	margin: 0 calc(var(--wp--preset--spacing--20) * -1);
	padding: 0;
}

.st-work-list li {
	margin: 0;
}

.st-work-row {
	align-items: baseline;
	border-bottom: 1px solid var(--wp--preset--color--hairline);
	column-gap: var(--wp--preset--spacing--30);
	display: grid;
	grid-template-columns: 132px 1fr auto 2ch;
	padding: var(--wp--preset--spacing--20);
	position: relative;
	scroll-margin-top: var(--wp--preset--spacing--20);
	transition: background-color 0.18s ease;
}

/* The thumbnail column is a fixed width rather than auto, so every title starts
   on the same vertical line whether or not that project has an image yet. */
.st-work-row__thumb {
	grid-column: 1;
	grid-row: 1;
	margin: 0;
}

.st-work-row__thumb img {
	aspect-ratio: 3 / 2;
	display: block;
	object-fit: cover;
	width: 100%;
}

/* The row marker is generated rather than authored, so editors never have to
   maintain a decorative block alongside the real content. */
/* Hover changes colour only — no padding shift, so the row cannot appear to
   twitch as the pointer crosses it. */
.st-work-row:hover,
.st-work-row:focus-within {
	background-color: #0b0b0b;
}

.st-work-row__title {
	font-size: var(--wp--preset--font-size--large);
	grid-column: 2;
	grid-row: 1;
	letter-spacing: -0.01em;
	margin: 0;
}

/* Stretch the title link across the whole row so the entire strip is clickable,
   while the link text itself remains the accessible name. */
.st-work-row__title a::after {
	content: "";
	inset: 0;
	position: absolute;
}

.st-work-row__meta {
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--small);
	grid-column: 3;
	grid-row: 1;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	white-space: nowrap;
}

.st-work-row__meta a {
	color: inherit;
	position: relative;
	z-index: 1;
}

.st-work-row__excerpt {
	color: var(--wp--preset--color--muted);
	grid-column: 2;
	margin: 0.5em 0 0;
	max-width: 60ch;
}

.st-work-row__excerpt p {
	margin: 0;
}

/* Core renders a read-more link inside the excerpt block; it duplicates the
   title link on an already-clickable row, so it is suppressed. */
.st-work-row__excerpt .wp-block-post-excerpt__more-text {
	display: none;
}

/* Accordion ---------------------------------------------------------------
   The portfolio index collapses each case study behind its title. Panels are
   hidden by the .st-js class rather than by the script itself, so they are
   never briefly visible on load. Without JavaScript .st-js is absent, every
   panel stays open, and the page reads as one long document. */

.st-work-row__toggle {
	background: none;
	border: 0;
	color: inherit;
	cursor: pointer;
	font: inherit;
	letter-spacing: inherit;
	padding: 0;
	text-align: left;
	width: 100%;
}

/* Stretches the hit area over the whole row without swallowing the meta link. */
.st-work-row__toggle::after {
	content: "";
	inset: 0;
	position: absolute;
}

.st-work-row__chev {
	color: var(--wp--preset--color--muted);
	grid-column: 4;
	grid-row: 1;
	text-align: right;
	transition: color 0.18s ease;
	-webkit-user-select: none;
	user-select: none;
}

.st-work-row:hover .st-work-row__chev,
.st-work-row.is-open .st-work-row__chev {
	color: var(--wp--preset--color--accent);
}

.st-work-row__panel {
	grid-column: 2 / -1;
	padding-block: var(--wp--preset--spacing--30) var(--wp--preset--spacing--20);
}

.st-js .st-work-row__panel {
	display: none;
}

.st-js .st-work-row.is-open .st-work-row__panel {
	display: block;
}

/* An open row stays lifted, so the reader can see which one they are inside. */
.st-work-row.is-open {
	background-color: #0b0b0b;
}

.st-work-row__permalink {
	color: var(--wp--preset--color--muted);
	display: inline-block;
	font-size: var(--wp--preset--font-size--small);
	letter-spacing: 0.12em;
	margin-top: var(--wp--preset--spacing--30);
	position: relative;
	text-transform: uppercase;
	z-index: 1;
}

.st-work-row__permalink::before {
	content: "/// ";
}

@media (max-width: 700px) {
	.st-work-row {
		grid-template-columns: 84px 1fr 2ch;
	}

	.st-work-row__title {
		grid-column: 2;
	}

	.st-work-row__meta {
		grid-column: 2;
		grid-row: 2;
		margin-top: 0.4em;
	}

	.st-work-row__chev {
		grid-column: 3;
	}

	/* Below this width the panel reclaims the thumbnail column too, otherwise
	   the case study text is squeezed into well under half the screen. */
	.st-work-row__excerpt,
	.st-work-row__panel {
		grid-column: 1 / -1;
	}

	.st-work-row__excerpt {
		margin-top: 0.6em;
	}
}

/* Single case study ------------------------------------------------------- */

/* A back link at the top, where someone who arrived from the grid will look for
   it, plus the button still at the foot for anyone who read to the end. The
   arrow points the way out rather than the /// used elsewhere, which marks a
   heading rather than a direction. */
.st-backlink {
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--small);
	letter-spacing: 0.14em;
	margin: 0;
	text-transform: uppercase;
}

.st-backlink a {
	color: inherit;
	transition: color 0.18s ease;
}

.st-backlink a::before {
	content: "← ";
	font-family: system-ui, "Segoe UI Symbol", sans-serif;
}

.st-backlink a:hover,
.st-backlink a:focus-visible {
	color: var(--wp--preset--color--accent);
}

.st-case-study__meta {
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--small);
	letter-spacing: 0.14em;
	text-transform: uppercase;
}

/* Body copy and images share one measure.
   There is deliberately no reading-measure cap here. Capping the text narrower
   than the images left the paragraphs centred inside a wider column, which read
   as a mistake rather than as typography. Width now comes entirely from the
   block layout's content size, so prose and galleries line up on both edges. */

.st-case-study__body h2 {
	margin-top: var(--wp--preset--spacing--50);
}

.st-case-study__body h3 {
	margin-top: var(--wp--preset--spacing--40);
}

/* Prose links -------------------------------------------------------------
   Orange-on-hover alone meant a link was invisible until the pointer found it,
   which is no use to anyone reading rather than hunting. A permanent underline
   carries the "this is a link" signal; the arrow adds "and it leaves the site".
   Buttons and the read-more link are excluded — they already read as
   actionable, and an underline fights their border. */

:where(.wp-block-post-content, .st-case-study__body)
	a:not(.wp-element-button):not(.wp-block-read-more) {
	text-decoration: underline;
	text-decoration-color: var(--wp--preset--color--contrast);
	text-decoration-thickness: 1px;
	text-underline-offset: 0.22em;
	transition: color 0.18s ease, text-decoration-color 0.18s ease;
}

:where(.wp-block-post-content, .st-case-study__body)
	a:not(.wp-element-button):not(.wp-block-read-more):hover,
:where(.wp-block-post-content, .st-case-study__body)
	a:not(.wp-element-button):not(.wp-block-read-more):focus-visible {
	color: var(--wp--preset--color--accent);
	text-decoration-color: var(--wp--preset--color--accent);
}

/* Courier New carries no north-east arrow, so the glyph is drawn from the
   system UI font instead of being silently substituted by the browser. */
:where(.wp-block-post-content, .st-case-study__body)
	a[target="_blank"]:not(.wp-element-button)::after {
	content: "↗";
	display: inline-block;
	font-family: system-ui, "Segoe UI Symbol", "Apple Color Emoji", sans-serif;
	font-size: 0.8em;
	margin-left: 0.2em;
	text-decoration: none;
	-webkit-user-select: none;
	user-select: none;
	vertical-align: baseline;
}

/* ---------------------------------------------------------------------------
   8. Contact form
   ------------------------------------------------------------------------ */

.st-form {
	max-width: 640px;
}

.st-form__form {
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--30);
}

.st-form__row {
	display: flex;
	flex-direction: column;
	gap: 0.5rem;
}

.st-form__label {
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--small);
	letter-spacing: 0.14em;
	text-transform: uppercase;
}

/* Inputs are ruled underneath rather than boxed — a full border on black reads
   as a heavy rectangle, and the underline matches the hairlines used elsewhere. */
.st-form__input {
	background: transparent;
	border: 0;
	border-bottom: 1px solid var(--wp--preset--color--hairline);
	border-radius: 0;
	color: var(--wp--preset--color--contrast);
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--medium);
	padding: 0.6em 0;
	transition: border-color 0.18s ease;
	width: 100%;
}

.st-form__input:hover {
	border-bottom-color: var(--wp--preset--color--muted);
}

.st-form__input:focus {
	border-bottom-color: var(--wp--preset--color--accent);
	outline: none;
}

/* The underline already signals focus, so the global focus ring would be a
   second, redundant marker around a field that is not a button. */
.st-form__input:focus-visible {
	outline: none;
}

.st-form__textarea {
	line-height: 1.65;
	resize: vertical;
}

.st-form__submit {
	align-self: flex-start;
	background: transparent;
	border: 1px solid var(--wp--preset--color--contrast);
	border-radius: 0;
	color: var(--wp--preset--color--contrast);
	cursor: pointer;
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--medium);
	letter-spacing: 0.08em;
	padding: 0.9em 1.8em;
	text-transform: uppercase;
	transition: background-color 0.18s ease, border-color 0.18s ease, color 0.18s ease;
}

.st-form__submit:hover,
.st-form__submit:focus-visible {
	background: var(--wp--preset--color--accent);
	border-color: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--base);
}

/* Off-screen rather than display:none — some bots skip hidden fields, but a
   positioned one still looks fillable to them. */
.st-form__trap {
	height: 1px;
	left: -9999px;
	overflow: hidden;
	position: absolute;
	width: 1px;
}

.st-form__notice {
	border-left: 2px solid var(--wp--preset--color--muted);
	margin-bottom: var(--wp--preset--spacing--30);
	padding: 0.75em 0 0.75em var(--wp--preset--spacing--20);
}

.st-form__notice.is-ok {
	border-left-color: var(--wp--preset--color--accent);
}

.st-form__notice.is-error {
	border-left-color: var(--wp--preset--color--contrast);
	color: var(--wp--preset--color--contrast);
}

/* Chrome and Safari repaint autofilled fields with their own pale background,
   which on a black form renders white text on near-white. */
.st-form__input:-webkit-autofill,
.st-form__input:-webkit-autofill:hover,
.st-form__input:-webkit-autofill:focus {
	-webkit-text-fill-color: var(--wp--preset--color--contrast);
	box-shadow: 0 0 0 1000px var(--wp--preset--color--base) inset;
	caret-color: var(--wp--preset--color--contrast);
}

/* ---------------------------------------------------------------------------
   9. Footer
   ------------------------------------------------------------------------ */

.st-footer {
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--small);
	letter-spacing: 0.1em;
}

.st-footer a {
	color: var(--wp--preset--color--muted);
}

.st-footer a:hover,
.st-footer a:focus {
	color: var(--wp--preset--color--accent);
}

/* ---------------------------------------------------------------------------
  10. Editor parity
   ------------------------------------------------------------------------ */

/* The Site Editor canvas does not inherit the black body background from
   theme.json in every context; force it so what Andy edits looks like what
   ships. */
.editor-styles-wrapper {
	background-color: var(--wp--preset--color--base);
}

/* Slideshows are deliberately NOT stacked in the editor — piling the slides on
 * top of each other would make them impossible to select, reorder or delete.
 * They stay side by side so they can be worked on, and this label explains why
 * the editor and the published page differ, which is otherwise a mystery worth
 * an afternoon.
 */
.editor-styles-wrapper .st-slides {
	outline: 1px dashed var(--wp--preset--color--hairline);
	outline-offset: 8px;
	position: relative;
}

.editor-styles-wrapper .st-slides::before {
	color: var(--wp--preset--color--muted);
	content: "/// SLIDESHOW — these stack and crossfade on the published page. Change the pause between slides by adding a class like st-slides-8s under Advanced (default 5s).";
	display: block;
	flex-basis: 100%;
	font-family: var(--wp--preset--font-family--mono);
	font-size: 0.75rem;
	letter-spacing: 0.1em;
	margin-bottom: 0.75rem;
	text-transform: uppercase;
}
