/**
 * Theme Name:        Shinosaur
 * Theme URI:         https://www.shinosaur.com/
 * Author:            Shinosaur
 * Author URI:        https://www.shinosaur.com/
 * Description:       Custom block theme for Shinosaur — eco-conscious cleaning services across Delaware. Built for WCAG 2.2 AA and Core Web Vitals; all design tokens live in theme.json.
 * Requires at least: 6.7
 * Tested up to:      7.0
 * Requires PHP:      8.1
 * Version:           1.0.0
 * License:           GNU General Public License v2 or later
 * License URI:       https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain:       shinosaur
 * Tags:              block-theme, full-site-editing, accessibility-ready, custom-colors, custom-menu
 *
 * @package Shinosaur
 */

/*
 * This file is intentionally small. Design tokens are defined in theme.json and
 * emitted by WordPress as CSS custom properties; per-template styling lives in
 * assets/css/ and is enqueued conditionally (see inc/enqueue.php).
 *
 * What belongs here: global rules that must apply to every page regardless of
 * template — focus indicators, the skip link, motion preferences, and reflow
 * safety. Nothing else.
 */

/* -------------------------------------------------------------------------
 * 1. Base
 * ---------------------------------------------------------------------- */

/*
 * Border-box sizing.
 *
 * The design comp opens with `* { box-sizing: border-box }` and every measurement
 * in it assumes that. WordPress applies border-box to most core blocks but not
 * universally, so without this any element combining `width: 100%` with
 * horizontal padding overflows its container by exactly that padding — which is
 * how the trust strip ended up 52px wider than the viewport.
 *
 * Declared with the inherit pattern so a component can opt a subtree into
 * content-box if it ever genuinely needs to.
 */
html {
	box-sizing: border-box;
}

*,
*::before,
*::after {
	box-sizing: inherit;
}

/*
 * Smooth scrolling is opt-out for users who ask for reduced motion. Declaring it
 * inside the media query (rather than overriding later) means we never emit the
 * property at all for those users.
 */
@media (prefers-reduced-motion: no-preference) {
	html {
		scroll-behavior: smooth;
	}
}

/*
 * WordPress emits `:where(.wp-site-blocks) > * { margin-block-start: <blockGap> }`,
 * which puts 34px between the utility bar, the header and <main>. The comp has
 * the three flush against each other.
 */
.wp-site-blocks > * {
	margin-block-start: 0;
}

body {
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	/*
	 * Belt-and-braces against WCAG 1.4.10 (Reflow). Long unbroken strings — URLs
	 * in editor-authored copy, for instance — must not force a horizontal
	 * scrollbar at 320px.
	 */
	overflow-wrap: break-word;
}

/*
 * WCAG 1.4.12 (Text Spacing): headings set in Archivo at negative tracking can
 * collide when a user applies a spacing override. Allow the cascade to win.
 */
:where(h1, h2, h3, h4, h5, h6) {
	text-wrap: balance;
}

:where(p, li) {
	text-wrap: pretty;
}

/* Media never overflows its container, and always reserves its own space. */
:where(img, svg, video, canvas, iframe) {
	max-width: 100%;
	height: auto;
}

/* Form controls inherit typography rather than falling back to the UA font. */
:where(input, select, textarea, button) {
	font: inherit;
	color: inherit;
}

::selection {
	background: var(--wp--preset--color--gold);
	color: var(--wp--preset--color--plum);
}

/* -------------------------------------------------------------------------
 * 2. Focus indicators — WCAG 2.4.7, 2.4.11, 2.4.13
 * ---------------------------------------------------------------------- */

/*
 * The design comp removed focus outlines on every form control (`outline: none`)
 * and replaced them with a border-colour change measuring roughly 1.3:1. That
 * fails 2.4.7 and 2.4.13, so we restore a real indicator globally.
 *
 * `:focus-visible` (not `:focus`) keeps the ring off mouse clicks while
 * guaranteeing it for keyboard users. The offset ensures the ring is legible
 * against both the control and the surface behind it, satisfying the 3:1
 * contrast requirement of 2.4.11 (Focus Appearance) on either side.
 */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
	outline: var(--wp--custom--focus--width) solid var(--wp--custom--focus--color);
	outline-offset: var(--wp--custom--focus--offset);
	border-radius: var(--wp--custom--radius--sm);
}

/*
 * On plum and teal surfaces the standard teal ring drops below 3:1. Any section
 * carrying `.is-inverse` swaps to gold, which measures 13.36:1 on plum.
 */
.is-inverse :where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
	outline-color: var(--wp--custom--focus--color-inverse);
}

/*
 * Remove the UA focus ring only where we have already supplied a stronger one.
 * Never a bare `outline: none`.
 */
:where(a, button, input, select, textarea, summary, [tabindex]):focus:not(:focus-visible) {
	outline: none;
}

/* -------------------------------------------------------------------------
 * 3. Skip link — WCAG 2.4.1
 * ---------------------------------------------------------------------- */

.shinosaur-skip-link {
	position: absolute;
	top: 0;
	left: 0;
	z-index: 1000;
	padding: 1rem 1.5rem;
	background: var(--wp--preset--color--plum);
	color: var(--wp--preset--color--white);
	font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 800;
	text-decoration: none;
	border-radius: 0 0 var(--wp--custom--radius--md) 0;
	/*
	 * Translated out of view rather than hidden, so it remains focusable and is
	 * announced in the correct DOM order.
	 */
	transform: translateY(-100%);
}

.shinosaur-skip-link:focus {
	transform: translateY(0);
}

@media (prefers-reduced-motion: no-preference) {
	.shinosaur-skip-link {
		transition: transform 120ms ease-out;
	}
}

/*
 * `#main` receives focus programmatically when the skip link is followed. It
 * must not show a persistent ring, but must still be reachable.
 */
:where(#main):focus {
	outline: none;
}

/* -------------------------------------------------------------------------
 * 4. Screen-reader utilities
 * ---------------------------------------------------------------------- */

.screen-reader-text {
	position: absolute !important;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

.screen-reader-text:focus {
	position: static !important;
	width: auto;
	height: auto;
	margin: 0;
	overflow: visible;
	clip-path: none;
	white-space: normal;
}

/* -------------------------------------------------------------------------
 * 5. Target size — WCAG 2.5.8 (Level AA, 24x24 minimum)
 * ---------------------------------------------------------------------- */

/*
 * Applies to controls that would otherwise be sized purely by their glyph —
 * icon buttons, chip links, pagination. Inline links inside a paragraph are
 * exempt under the standard, hence `:not(p a)`.
 */
:where(button, [role="button"], input[type="submit"], input[type="button"]),
:where(a):not(p a):not(li a) {
	min-block-size: 24px;
	min-inline-size: 24px;
}

/* -------------------------------------------------------------------------
 * 6. Motion — WCAG 2.2.2, 2.3.3
 * ---------------------------------------------------------------------- */

/*
 * The comp carries roughly ten infinite decorative animations (drifting orbs,
 * Ken Burns, pulsing map dots, twinkles). They are ambient rather than
 * informational, so the correct behaviour for a reduced-motion request is to
 * stop them outright — not to shorten them.
 *
 * `scroll-behavior: auto !important` is required because the smooth-scroll rule
 * above is scoped to `no-preference`, but WordPress core and plugins may set it
 * unconditionally elsewhere.
 */
@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;
	}

	/*
	 * Reveal-on-scroll must never leave content invisible when its animation is
	 * suppressed. See assets/js/reveal.js — the JS is a no-op under reduced
	 * motion, and this guarantees the CSS agrees.
	 */
	[data-reveal] {
		opacity: 1 !important;
		transform: none !important;
	}
}

/*
 * Progressive-enhancement guard: if scripting is unavailable the reveal
 * animation never runs, so its initial hidden state must not apply.
 */
@media (scripting: none) {
	[data-reveal] {
		opacity: 1 !important;
		transform: none !important;
	}
}

/* -------------------------------------------------------------------------
 * 7. Print
 * ---------------------------------------------------------------------- */

@media print {
	.shinosaur-skip-link,
	[data-print="hide"] {
		display: none !important;
	}

	body {
		background: #fff;
		color: #000;
	}
}
