/*
Theme Name: Webstore
Theme URI: https://example.com/webstore-theme
Author: Webstore
Description: A block theme built to pair with the Webstore plugin. Generic by design — it assumes nothing about what is being sold, and gives the plugin the two things a plugin cannot reach: the site header and footer, and site-wide typography. Installing it is optional; not installing it costs polish, never function.
Requires at least: 6.4
Tested up to: 6.7
Requires PHP: 8.1
Version: 1.0.3
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: webstore-theme
Tags: e-commerce, block-patterns, full-site-editing, one-column, custom-colors
*/

/*
 * Almost nothing lives here.
 *
 * A block theme's styling belongs in `theme.json`, and this theme's *shop*
 * styling belongs in the plugin — which ships its own tokens and stylesheet and
 * works with any theme. Duplicating either here would create a second source of
 * truth for how a product card looks, and the two would drift the first time
 * somebody changed one.
 *
 * What is left is the handful of rules that only make sense when theme and
 * plugin are installed together: the header's cart count, the dark scheme, and
 * the print stylesheet for picking lists (§14.5).
 *
 * **On the two font families.** Headings used to be set in the Display family,
 * which is a Georgia serif - and a serif heading over a sans paragraph gave the
 * whole site the air of a newspaper rather than a shop. Headings and the site
 * title now follow Body, and carry their weight and line height instead. The
 * serif family is still declared, so a shop that wants it can pick it in
 * Appearance, Editor, Styles, Typography without editing a file.
 *
 * Neither family loads a font. Both are stacks of what an operating system
 * already has, because a theme that fetches a webfont makes every page wait on
 * somebody else's server and hands a third party a log of who visited the shop.
 *
 * **On the radius values in `theme.json`'s `settings.custom`.** They mirror the
 * plugin's own tokens by name and value, so a shop styled in the Customizer and
 * a page styled in the site editor cannot disagree. The plugin stays the source
 * of truth: it emits the same names inline on store routes, and those override
 * these.
 *
 * That note used to live in `theme.json` itself, as a `"comment"` key beside
 * the radius values — which is why it is here now. Every key under
 * `settings.custom` is compiled into a CSS custom property, so the sentence
 * became a declaration, and the apostrophe in "plugin's" opened a CSS string
 * that never closed. The browser swallowed the rest of the stylesheet: one rule
 * survived out of a hundred and twenty-three, and the theme rendered in Times
 * New Roman with default blue links and no page padding, on every site using
 * it. JSON has no comments, and `settings.custom` is not a substitute.
 */

/* ------------------------------------------------------------- Dark scheme */

/*
 * theme.json has no scheme dimension.
 *
 * Its palette is one set of colours, and `styles.color` binds the page
 * background and text to them — so on its own this theme is light at midnight.
 * With the plugin active that produced a genuinely broken page: the shop's own
 * content followed the plugin's dark tokens while the header, footer and page
 * background stayed white. The site editor still edits one palette; these rules
 * only restate it for dark, by the same slugs.
 *
 * The guard order matches the plugin's `tokens.css` exactly, and for the same
 * reasons:
 *
 * - `prefers-color-scheme` is the visitor's own preference, and is what "auto"
 *   means. `:not([data-theme="light"])` lets a shop pinned to light stay light
 *   even for a visitor whose OS is dark.
 * - `[data-theme="dark"]` wins outright, because a shop that pinned dark meant
 *   it. The plugin writes that attribute onto `<html>` on store routes when the
 *   shop has chosen a scheme; off a store route there is no attribute and
 *   following the visitor is the right answer.
 *
 * Values are the plugin's own dark defaults, so the two halves of the page
 * cannot disagree about what "surface" is.
 */
@media (prefers-color-scheme: dark) {
	:root:not([data-theme="light"]) {
		--wp--preset--color--base: #131417;
		--wp--preset--color--surface: #1c1e22;
		--wp--preset--color--contrast: #f2f3f5;
		--wp--preset--color--muted: #a2a7b0;
		--wp--preset--color--border: #2c2f35;
		--wp--preset--color--accent: #f2f3f5;
		--wp--preset--color--accent-ink: #16171a;
		--wp--preset--color--sale: #e5534b;
	}
}

:root[data-theme="dark"] {
	--wp--preset--color--base: #131417;
	--wp--preset--color--surface: #1c1e22;
	--wp--preset--color--contrast: #f2f3f5;
	--wp--preset--color--muted: #a2a7b0;
	--wp--preset--color--border: #2c2f35;
	--wp--preset--color--accent: #f2f3f5;
	--wp--preset--color--accent-ink: #16171a;
	--wp--preset--color--sale: #e5534b;
}

/*
 * theme.json states the button hover as a literal `#333333`, which is a dark
 * grey under a light accent and invisible under a dark one. Stated here as a
 * relationship instead, so it follows whichever accent is in force.
 */
:root .wp-element-button:hover,
:root .wp-block-button__link:hover {
	background-color: color-mix(in srgb, var(--wp--preset--color--accent) 82%, var(--wp--preset--color--base));
}

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

/*
 * The row inside the header, not the header itself.
 *
 * The `<header>` used to carry `display: flex` from here while its block markup
 * said `constrained` — so WordPress capped each child at the 42rem reading
 * measure and the CSS then spread them across a container that was not that
 * wide. The header sat at one width, the shop at another and the footer at a
 * third, on the same page. The arrangement is stated once now, in the block
 * layout, and this file only handles the spacing.
 */
.ws-theme-header__row {
	gap: var(--webstore-space-4, 1rem);
}

.ws-theme-header__brand {
	font-family: var(--webstore-font-display, inherit);
	font-size: var(--webstore-scale-xl, 1.375rem);
	font-weight: var(--webstore-weight-heading, 600);
	text-decoration: none;
}

.ws-theme-header__actions {
	align-items: center;
	display: flex;
	gap: var(--webstore-space-4, 1rem);
}

.ws-theme-header__cart {
	align-items: center;
	display: inline-flex;
	gap: var(--webstore-space-2, 0.5rem);
	text-decoration: none;
}

/*
 * The count is filled in by the plugin's own script, which fetches it rather
 * than rendering it server-side — a header is exactly the fragment a page cache
 * keeps, and a cached basket count is wrong for everybody but the first
 * visitor.
 */
.ws-theme-header__count {
	background: var(--webstore-color-accent, var(--wp--preset--color--accent));
	border-radius: 999px;
	color: var(--webstore-color-accent-ink, var(--wp--preset--color--accent-ink));
	font-size: var(--webstore-scale-xs, 0.75rem);
	line-height: 1;
	min-width: 1.25rem;
	padding: 3px 6px;
	text-align: center;
}

.ws-theme-header__count[hidden] {
	display: none;
}

/* A slim sticky bar on store routes only, so a long grid keeps the basket. */
body.webstore-store .ws-theme-header {
	background: var(--webstore-color-bg, var(--wp--preset--color--base));
	position: sticky;
	top: 0;
	z-index: 20;
}

/* ------------------------------------------------------------------ Footer */

.ws-theme-footer__marks {
	color: var(--webstore-color-ink-muted, var(--wp--preset--color--muted));
	display: flex;
	flex-wrap: wrap;
	gap: var(--webstore-space-3, 0.75rem);
	font-size: var(--webstore-scale-sm, 0.875rem);
	list-style: none;
	margin: 0;
	padding: 0;
}

/* ------------------------------------------------------------------- Print */

/*
 * Picking lists, collection lists and receipts (§14.5, §8.6). No PDF library:
 * a print stylesheet gives a shop a usable picking list from the page it is
 * already looking at, and every browser can already do it.
 */
@media print {
	.ws-theme-header,
	.ws-theme-footer,
	.ws-drawer,
	.ws-toast,
	.ws-quickview,
	.ws-announcement,
	.ws-filters,
	.wp-block-navigation,
	.ws-button {
		display: none !important;
	}

	body {
		background: #fff;
		color: #000;
		font-size: 12pt;
	}

	/* Links print their destination, or a receipt loses every reference. */
	a[href^="http"]::after {
		content: " (" attr(href) ")";
		font-size: 10pt;
		word-break: break-all;
	}

	.ws-order__lines,
	.ws-cart__lines {
		page-break-inside: avoid;
	}

	table {
		border-collapse: collapse;
		width: 100%;
	}

	th,
	td {
		border-bottom: 1px solid #ccc;
		padding: 6pt 0;
		text-align: left;
	}
}

/* -------------------------------------------------------------- Shop bands */

/*
 * These style the blocks this theme adds, not the plugin's own markup. The
 * plugin ships a complete stylesheet for cards, the basket and the checkout,
 * and it works with any theme - restyling it from here would create a second
 * opinion about what a product card looks like.
 */

.ws-theme-hero {
	background: var(--webstore-color-surface, var(--wp--preset--color--surface));
	border-radius: var(--webstore-radius-lg, 16px);
	padding: var(--webstore-space-12, 3rem) var(--webstore-space-6, 1.5rem);
	text-align: center;
}

.ws-theme-hero__title {
	font-family: var(--webstore-font-display, inherit);
	font-size: var(--webstore-scale-3xl, 2.5rem);
	line-height: 1.15;
	margin: 0 0 var(--webstore-space-3, 0.75rem);
}

.ws-theme-hero__text {
	color: var(--webstore-color-ink-muted, var(--wp--preset--color--muted));
	margin: 0 auto var(--webstore-space-6, 1.5rem);
	max-width: 34rem;
}

.ws-theme-collections {
	display: grid;
	gap: var(--webstore-grid-gap, 1.5rem);
	grid-template-columns: repeat(auto-fill, minmax(var(--webstore-grid-min, 240px), 1fr));
}

.ws-theme-collection {
	border-radius: var(--webstore-radius-md, 8px);
	display: block;
	overflow: hidden;
	position: relative;
	text-decoration: none;
}

.ws-theme-collection__image {
	aspect-ratio: var(--webstore-card-ratio, 1 / 1);
	display: block;
	height: auto;
	object-fit: var(--webstore-image-fit, cover);
	width: 100%;
}

/*
 * The name sits over the image on a gradient rather than under it. A caption
 * below the image makes a row of collections read as a list of files; over it,
 * with the photograph doing the work, it reads as a shop.
 */
.ws-theme-collection__name {
	background: linear-gradient(transparent, rgba(0, 0, 0, 0.55));
	bottom: 0;
	color: #fff;
	display: block;
	font-family: var(--webstore-font-display, inherit);
	font-size: var(--webstore-scale-lg, 1.125rem);
	font-weight: var(--webstore-weight-heading, 600);
	left: 0;
	padding: var(--webstore-space-8, 2rem) var(--webstore-space-4, 1rem) var(--webstore-space-3, 0.75rem);
	position: absolute;
	right: 0;
}

/* A collection with no hero image still needs to be readable. */
.ws-theme-collection:not(:has(.ws-theme-collection__image)) .ws-theme-collection__name {
	background: var(--webstore-color-surface, var(--wp--preset--color--surface));
	color: var(--webstore-color-ink, var(--wp--preset--color--contrast));
	position: static;
	padding: var(--webstore-space-6, 1.5rem) var(--webstore-space-4, 1rem);
	text-align: center;
}

.ws-theme-empty {
	color: var(--webstore-color-ink-muted, var(--wp--preset--color--muted));
	padding: var(--webstore-space-10, 2.5rem) 0;
	text-align: center;
}
