/*
 * Shared responsive layer — US-002.
 *
 * Loaded LAST on every page (inc/responsive-media.php enqueues it at priority
 * 50, after every feature stylesheet), so it is the one place that guarantees
 * the same behaviour for every page's sections, cards and media:
 *
 *   1. nothing can overflow a 320px viewport sideways;
 *   2. every collection grid is one column on a phone, two from 600px and the
 *      designed column count from 1024px;
 *   3. media (images, video, iframes, tables, long URLs) stays inside its own
 *      container instead of widening the page;
 *   4. anything a finger has to hit is at least 44px, and nothing is reachable
 *      by hover alone.
 *
 * Every value comes from the design tokens in assets/css/design-tokens.css.
 *
 * Grid rules repeat their class (".card-grid.card-grid") on purpose: a feature
 * stylesheet may be printed after this file when a page enqueues it late, and
 * the doubled class keeps the shared column stages winning without !important.
 *
 * Shared classes a template can opt into (also used by the rules below, so a
 * page template that does not exist yet has them ready):
 *   .rwd-grid           one column, two from 600px, --rwd-cols from 1024px
 *   .rwd-table-scroll   wrapper that scrolls a wide table inside itself
 *   .rwd-embed          16/9 (or --rwd-ratio) responsive iframe/video holder
 *   .rwd-break          wraps long words and URLs instead of widening the page
 *   .rwd-stack-cta      CTA row: full-width buttons on a phone, inline above
 */

/* ==========================================================================
   1. Overflow safety — nothing may exceed the viewport at 320px
   ========================================================================== */

/*
 * Only `body` carries overflow-x (as it already did in style.css). Making
 * `html` non-visible too would propagate html's value to the viewport instead
 * and turn `body` into a real scroll container, against which every
 * `position: sticky` descendant — the privacy page's table of contents, the
 * enquiry form's heading — would stop sticking.
 */
html,
body {
	max-width: 100%;
}

body {
	overflow-x: hidden;
}

/*
 * A grid or flex item defaults to min-width:auto, so one long word or a wide
 * image inside a card stretches the whole track and pushes the page sideways.
 * Zeroing it on the theme's own layout items is what actually prevents the
 * horizontal scrollbar at 320px.
 *
 * .service-section__body appears here for that guard ONLY: its column stages
 * stay with assets/css/services.css, which shows it two-up between 680px and
 * 899px because from 900px it moves into the narrow column of that page's
 * asymmetric split.
 */
.rwd-grid > *,
.card-grid > *,
.article-grid > *,
.about-team__list > *,
.about-team__item,
.about-offices__list > *,
.about-how__list > *,
.home-explore__list > *,
.privacy-cards > *,
.work-cases__list > *,
.work-case__parts > *,
.case-study__fields > *,
.service-section__body > *,
.site-footer__grid > * {
	min-width: 0;
}

/* The page gutter is the only horizontal padding; no element may opt out. */
.container {
	max-width: min(var(--container-max), 100%);
}

/*
 * A hero or band that paints a full-bleed background uses 100% of the
 * containing block — never 100vw, which is wider than the viewport whenever a
 * scrollbar is present and is a classic source of sideways scroll.
 */
.home-hero,
.work-hero,
.about-hero,
.services-hero,
.blog-hero,
.careers-hero,
.contact-hero,
.privacy-hero,
.imprint-hero,
.article__hero,
.case-study__hero {
	max-width: 100%;
	overflow-x: hidden;
}

/* ==========================================================================
   2. Media — responsive by default, inside its own box
   ========================================================================== */

img,
video,
svg,
canvas,
audio,
iframe,
embed,
object {
	max-width: 100%;
}

img,
video,
canvas {
	height: auto;
}

/*
 * A cropped photo keeps its box: these containers set the aspect ratio (or
 * fill a hero band), and the image covers it without distorting.
 */
.team-card__photo,
.article-card__image,
.work-hero__image,
.home-hero__image,
.home-hero__video,
.service-card__image {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/*
 * The hero band stacks its still image under the video: the image is what a
 * phone (and a visitor with JavaScript off) sees, the video covers it once
 * assets/js/hero-media.js attaches its source above the breakpoint.
 */
.home-hero__media > .home-hero__image,
.home-hero__media > .home-hero__video {
	position: absolute;
	inset: 0;
}

/*
 * Reduced motion hides the video (style.css), which leaves the still image.
 * The decorative background behind it points at the small variant first, so a
 * phone never fetches the desktop file for it either.
 */
@media (prefers-reduced-motion: reduce) {
	.home-hero__media--has-poster {
		background-image: url("../videos/hero-800.jpg");
		background-image: image-set(
			url("../videos/hero-800.jpg") 1x,
			url("../videos/hero.jpg") 2x
		);
	}
}

/* These carry their own aspect-ratio, so their height stays automatic. */
.service-section__image,
.about-story__image,
.article__image {
	display: block;
	width: 100%;
	object-fit: cover;
}

/*
 * Embeds (oEmbed, YouTube, maps) scale with the column instead of keeping the
 * provider's fixed pixel width.
 */
.rwd-embed,
.wp-block-embed__wrapper,
.entry-content .wp-block-embed,
.article__content .wp-block-embed {
	position: relative;
	width: 100%;
	max-width: 100%;
}

.rwd-embed {
	aspect-ratio: var(--rwd-ratio, 16 / 9);
}

/*
 * Every embed scales with its column. No ratio is imposed here: a map, an
 * audio player, a post embed or a form is not 16:9, and forcing that on it
 * would clip its content.
 */
.entry-content iframe,
.article__content iframe,
.entry-content video,
.article__content video,
.wp-block-embed iframe {
	display: block;
	width: 100%;
	max-width: 100%;
	border: 0;
}

/*
 * The ratio is applied only where it is known: the shared .rwd-embed wrapper,
 * a self-hosted video block, and the wp-embed-aspect-* class WordPress adds to
 * a video provider's embed.
 */
.rwd-embed > iframe,
.rwd-embed > video,
.wp-block-video video,
.wp-embed-aspect-16-9 iframe,
.wp-embed-aspect-21-9 iframe,
.wp-embed-aspect-18-9 iframe,
.wp-embed-aspect-4-3 iframe,
.wp-embed-aspect-1-1 iframe,
.wp-embed-aspect-9-16 iframe,
.wp-embed-aspect-2-3 iframe {
	height: auto;
}

.rwd-embed > iframe,
.rwd-embed > video {
	width: 100%;
	height: 100%;
	aspect-ratio: auto;
}

.wp-block-video video,
.wp-embed-aspect-16-9 iframe {
	aspect-ratio: var(--rwd-ratio, 16 / 9);
}

.wp-embed-aspect-21-9 iframe { aspect-ratio: 21 / 9; }
.wp-embed-aspect-18-9 iframe { aspect-ratio: 18 / 9; }
.wp-embed-aspect-4-3 iframe { aspect-ratio: 4 / 3; }
.wp-embed-aspect-1-1 iframe { aspect-ratio: 1 / 1; }
.wp-embed-aspect-9-16 iframe { aspect-ratio: 9 / 16; }
.wp-embed-aspect-2-3 iframe { aspect-ratio: 2 / 3; }

/* An audio player keeps its own height. */
.entry-content audio,
.article__content audio {
	width: 100%;
	height: auto;
}

/* ==========================================================================
   3. Tables and long words — scroll or wrap, never widen the page
   ========================================================================== */

.rwd-table-scroll,
.entry-content .wp-block-table,
.article__content .wp-block-table {
	display: block;
	width: 100%;
	max-width: 100%;
	overflow-x: auto;
	-webkit-overflow-scrolling: touch;
	overscroll-behavior-x: contain;
}

.entry-content table,
.article__content table,
.rwd-table-scroll > table {
	display: block;
	width: 100%;
	max-width: 100%;
	overflow-x: auto;
	border-collapse: collapse;
	font-size: var(--text-sm);
}

/* Inside a scrolling wrapper the table itself may keep its natural width. */
.rwd-table-scroll > table,
.entry-content .wp-block-table > table,
.article__content .wp-block-table > table {
	display: table;
	width: max-content;
	min-width: 100%;
	overflow: visible;
}

.entry-content th,
.entry-content td,
.article__content th,
.article__content td {
	padding: var(--space-2) var(--space-3);
	border: 1px solid var(--color-border);
	text-align: left;
	vertical-align: top;
}

/*
 * A long word, an e-mail address or an unbroken URL in editor content breaks
 * mid-word rather than pushing the column out. `anywhere` (not break-word)
 * because only it also shrinks the element's min-content width, which is what
 * a grid track measures.
 */
.rwd-break,
.entry-content,
.article__content,
.privacy-section__body,
.imprint-list,
.office-card__value,
.work-case__summary,
.site-footer__text {
	overflow-wrap: anywhere;
	word-break: break-word;
}

.entry-content a,
.article__content a,
.imprint-list a,
.site-footer a {
	overflow-wrap: anywhere;
}

.entry-content pre,
.article__content pre {
	max-width: 100%;
	overflow-x: auto;
	white-space: pre;
}

/* ==========================================================================
   4. Column stages — 1 / 2 (>=600px) / designed count (>=1024px)
   ========================================================================== */

.rwd-grid,
.card-grid.card-grid,
.article-grid.article-grid,
.about-team__list.about-team__list,
.about-offices__list.about-offices__list,
.about-how__list.about-how__list,
.home-explore__list.home-explore__list,
.privacy-cards.privacy-cards,
.work-case__parts.work-case__parts,
.case-study__fields.case-study__fields {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
}

/* The shared class brings its own rhythm; the feature grids keep theirs. */
.rwd-grid {
	gap: var(--space-6);
}

@media (min-width: 600px) {
	.rwd-grid,
	.card-grid.card-grid,
	.article-grid.article-grid,
	.about-team__list.about-team__list,
	.about-offices__list.about-offices__list,
	.about-how__list.about-how__list,
	.home-explore__list.home-explore__list,
	.privacy-cards.privacy-cards,
	.work-case__parts.work-case__parts,
	.case-study__fields.case-study__fields {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (min-width: 1024px) {
	/* The designed desktop column count of each collection. */
	.rwd-grid {
		grid-template-columns: repeat(var(--rwd-cols, 3), minmax(0, 1fr));
	}

	.card-grid.card-grid,
	.article-grid.article-grid,
	.about-team__list.about-team__list,
	.home-explore__list.home-explore__list,
	.work-case__parts.work-case__parts,
	.case-study__fields.case-study__fields {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}

	.about-how__list.about-how__list {
		grid-template-columns: repeat(4, minmax(0, 1fr));
	}

	.about-offices__list.about-offices__list,
	.privacy-cards.privacy-cards {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (min-width: 1280px) {
	.about-team__list.about-team__list {
		grid-template-columns: repeat(4, minmax(0, 1fr));
	}
}

/* Case studies stay one full-width editorial block per row at every width. */
.work-cases__list.work-cases__list {
	grid-template-columns: minmax(0, 1fr);
}

/* ==========================================================================
   5. Hero and call-to-action buttons on a phone
   ========================================================================== */

/*
 * Below the tablet breakpoint a CTA spans the column, so it is impossible to
 * miss with a thumb; from 600px the buttons sit inline again.
 */
@media (max-width: 599px) {
	.rwd-stack-cta,
	.home-hero__actions,
	.home-cta__actions,
	.work-cta__actions,
	.careers-cta__actions,
	.careers-hero__actions,
	.services-cta__actions,
	.service-section__actions,
	.about-hero__actions,
	.article__cta-actions,
	.blog-empty__actions,
	.work-cases__empty .work-case__more {
		display: flex;
		flex-direction: column;
		align-items: stretch;
		gap: var(--space-3);
	}

	.rwd-stack-cta > .btn,
	.home-hero__actions .btn,
	.home-cta__actions .btn,
	.work-cta__actions .btn,
	.careers-cta__actions .btn,
	.careers-hero__actions .btn,
	.services-cta__actions .btn,
	.service-section__actions .btn,
	.about-hero__actions .btn,
	.article__cta-actions .btn,
	.blog-empty__actions .btn {
		width: 100%;
		justify-content: center;
		text-align: center;
	}
}

/*
 * Tap targets (WCAG 2.5.5): every button and standalone control is at least
 * 44x44px. inline-flex, because min-height does nothing on an inline box.
 */
.btn,
button,
input[type="submit"],
input[type="button"],
.site-nav-toggle,
.site-nav__list a,
.wpcf7-submit,
.cookie-banner__button,
.pagination a,
.pagination span,
.page-numbers {
	min-height: var(--tap-target);
}

.btn,
.site-nav__list a,
.pagination a,
.page-numbers {
	display: inline-flex;
	align-items: center;
	justify-content: center;
}

button,
input[type="submit"],
input[type="button"],
.wpcf7-submit {
	min-width: var(--tap-target);
}

/* Form fields are comfortable to hit and never trigger the iOS zoom-on-focus
   that a sub-16px field size causes. */
input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]),
select,
textarea {
	max-width: 100%;
	min-height: var(--tap-target);
	font-size: max(16px, var(--text-base));
}

textarea {
	min-height: calc(var(--tap-target) * 3);
}

/* ==========================================================================
   6. No hover-only interaction
   ========================================================================== */

/*
 * Cards lift on hover for a mouse. On a touch screen there is no hover, so the
 * same affordance is bound to focus — and nothing is ever *revealed* by hover
 * alone: these rules only restate decoration.
 */
.team-card:focus-within,
.article-card:focus-within,
.explore-card:focus-within,
.service-card:focus-within,
.post-card:focus-within,
.work-case:focus-within,
.office-card:focus-within {
	box-shadow: var(--shadow-lg);
}

@media (hover: none) {
	/* Touch: no transform that only a mouse could trigger, and no sticky
	   hover state left behind after a tap. */
	.team-card:hover,
	.article-card:hover,
	.explore-card:hover,
	.service-card:hover,
	.post-card:hover,
	.work-case:hover,
	.btn:hover {
		transform: none;
	}

	.btn:active {
		transform: translateY(1px);
	}
}

a:focus-visible,
button:focus-visible,
[tabindex]:focus-visible {
	outline: 3px solid var(--color-accent-600);
	outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
	.btn:active,
	.team-card:hover,
	.article-card:hover,
	.explore-card:hover,
	.service-card:hover,
	.post-card:hover,
	.work-case:hover {
		transform: none;
	}
}
