/*
 * responsive.css — adaptive layer for the Artology theme.
 *
 * Loaded AFTER style.css (enqueued in header.php), so rules here win the
 * cascade. All responsive / mobile work lives in this file; style.css — the
 * original fixed-980 desktop design — stays untouched.
 *
 * Plan: docs/plans/responsive-adaptation-plan.md
 *   Block 1  viewport meta + fluid wrapper/columns; widen on large screens.
 *   Block 2  phone breakpoint (single column) + hamburger menu.
 *   Block 3  full-bleed container (Tilda prep).
 *   Block 4  gallery (jqzoom / jScrollPane / slider).
 *   Block 5  sliders / slideshow page.
 *   Block 6  contact form.
 *   Block 7  home intro fade (CSS reveal of #introHome).
 *
 * Breakpoints (starting set, tuned with Playwright):
 *   >=1281  wrapper capped at 1280px (large desktop, margins trimmed)
 *   901-1280 fluid wrapper (94vw), proportional columns
 *   <=900   single column + hamburger menu
 *   <=560   phone tuning (spacing, typography, tap targets)
 *
 * Colors and overall concept are NOT changed here. c.
 */

/* ==========================================================================
   Block 1 — fluid base layout + large-screen widen
   Replaces the fixed 980px structure with a fluid grid. Percentages are taken
   against the original 980px context so the layout reproduces the desktop
   design around a ~1000-1080px viewport, widens up to a 1280px cap on large
   screens, and shrinks down on smaller ones. box-sizing:border-box is applied
   only to the fluidised structural elements (not globally), so their existing
   px paddings are absorbed into the percentage widths. c.
   ========================================================================== */

/* Sticky-footer wrapper: fluid, capped at 1280 (was width:980px).
   margin/min-height kept from style.css. c. */
#wrapper {
	width: 95%;
	max-width: 1280px;
	box-sizing: border-box;
}

/* Footer bar matches the wrapper so it aligns with the body column (was 980px). */
#footer #container {
	width: 95%;
	max-width: 1280px;
	box-sizing: border-box;
}

/* Two-column pages: content 670 + 6 pad = 676/980 = 69%; sidebar 260 + 20 pad =
   280/980 = 28.57%; the ~2.43% remainder is the float gap (~24px at 980). c. */
.mainContent {
	width: 69%;
	box-sizing: border-box;
}

#sidebar {
	width: 28.57%;
	box-sizing: border-box;
}

/* One-column pages (gallery / article / artists / contact): full wrapper width
   (was 980px). Inner fixed-px modules (slider, .foto/.text) are handled in their
   own blocks (4-6). c. */
.mainContentBig {
	width: 100%;
	box-sizing: border-box;
}

/* Home banner (slideshow): stretch to the full column width (was fixed 980x450).
   Pulled forward from Block 5 on request. Source images are 1980x900, so the
   stretch up to the 1280 wrapper costs no quality. aspect-ratio keeps the design
   proportion and gives the relative box a height for its absolutely-positioned
   images (myslideshow.js only toggles display/opacity, not size). c. */
.fadein {
	width: 100%;
	height: auto;
	aspect-ratio: 980 / 450;
}

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

/* ==========================================================================
   Block 2a — phone breakpoint: single column + flexible logo
   At <=900 the two-column layout collapses to one (content first, sidebar
   full-width below it), content media is constrained to its column, and the
   fixed-width logo is allowed to shrink on very narrow screens. The footer
   stacking (2b) and hamburger menu (2c) are handled in their own steps. c.
   ========================================================================== */

@media screen and (max-width: 900px) {

	/* Two columns -> single column. .mainContent (float:left) and #sidebar
	   (float:right, margin-top:104px desktop offset) both go full width and
	   stop floating, so they stack in source order: content, then sidebar.
	   Sidebar drops its 104px offset and aligns its left edge with the 6px
	   left padding of .mainContent. c. */
	.mainContent {
		width: 100%;
		float: none;
	}

	#sidebar {
		width: 100%;
		float: none;
		margin-top: 0;
		padding-left: 6px;
	}

	/* Content media never overflows the now full-width column. The home banner
	   (.fadein img) keeps its own object-fit rule — higher specificity. c. */
	.mainContent img,
	.mainContentBig img,
	#sidebar img {
		max-width: 100%;
		height: auto;
	}

	/* WordPress wraps captioned images in .wp-caption with an inline fixed
	   width (image width + 10px) — that overflowed the narrow column. max-width
	   caps the inline width; border-box keeps any padding inside the cap. c. */
	.wp-caption {
		max-width: 100%;
		box-sizing: border-box;
	}

	/* Pagination (.wp-pagenavi) overran the narrow column: WP outputs the links
	   with NO whitespace between them, so the inline row had no wrap opportunity
	   and text-align:center spilled it past both edges. Flex-wrap breaks between
	   items regardless of whitespace; nowrap keeps each label atomic; gap takes
	   over spacing so the original per-item margins don't double up. c. */
	.wp-pagenavi {
		display: flex;
		flex-wrap: wrap;
		justify-content: center;
		align-items: center;
		gap: 6px;
	}
	.wp-pagenavi a,
	.wp-pagenavi span {
		white-space: nowrap;
		margin: 0;
	}

	/* Logo: the fixed 329x100 background image becomes fluid below its native
	   width (max-width caps it at 329 so it is never upscaled / blurred).
	   background-size:contain keeps the whole mark visible; aspect-ratio gives
	   the now-auto height a box to match. c. */
	#logo {
		width: 100%;
		max-width: 329px;
		height: auto;
		aspect-ratio: 329 / 100;
		background-size: contain;
	}
}

/* ==========================================================================
   Block 2b — footer progressive wrap (phone)
   Desktop (>=901) keeps the original float row untouched. At <=900 the footer
   sheds items by available space, one at a time: the logo stays anchored left,
   the email stays beside it while it fits, and the copyright sits flush right
   and drops onto its own centered line when it no longer fits; below that the
   email also drops to a centered line.

   Mechanism: logo + email are grouped in .footLeft. #container is a centered
   flex-wrap row; .footLeft carries margin-right:auto, which (a) on the full row
   pushes copyright flush right with no gap — so there is no jump at the 900/901
   boundary — and (b) when copyright wraps, justify-content:center centers it on
   its own line while .footLeft stays left. .footLeft is display:contents on
   desktop so the original float row is untouched.

   The sticky-footer mechanism (html/body height:100%, #wrapper margin-bottom
   -4em, .push 4em spacer, #footer height:4em) reserves only 4em — too little
   once the footer wraps — so release it here and let it flow. c.
   ========================================================================== */

/* Wrapper is transparent on desktop: logo/email behave as direct #container
   children and the original float layout is unchanged. c. */
.footLeft {
	display: contents;
}

@media screen and (max-width: 900px) {

	/* Release the sticky footer (a wrapped footer is taller than its 4em pull). */
	#wrapper {
		margin-bottom: 0;
	}
	.push {
		display: none;
	}
	#footer {
		height: auto;
	}

	/* Centered flex-wrap row. justify-content centers any item that wraps onto
	   its own line; align-items:center balances the differing box heights. c. */
	#footer #container {
		display: flex;
		flex-wrap: wrap;
		justify-content: center;
		align-items: center;
		gap: 6px 24px;
	}

	/* Logo + email group: a real flex box here (overrides display:contents),
	   left-anchored. margin-right:auto pushes copyright flush right while it
	   shares the row, and keeps the group left once copyright wraps. flex-wrap
	   lets the email drop under the logo on very narrow screens. c. */
	.footLeft {
		display: flex;
		flex-wrap: wrap;
		align-items: center;
		gap: 6px 24px;
		margin-right: auto;
	}

	/* Empty dead div; #container already carries the top border. c. */
	#border {
		display: none;
	}

	.footBox {
		float: none;
		height: auto;
	}

	/* Logo anchors left (first item in .footLeft). Keep its 177x63 box. */
	#smallLogo {
		height: 63px;
		margin: 0;
	}

	/* Email sits beside the logo; min-height keeps the 56px-tall icon unclipped. */
	#femail {
		margin: 0;
		min-height: 56px;
	}

	/* Copyright: flush right while it fits (pushed by .footLeft's auto margin),
	   centered by justify-content when it wraps onto its own line. c. */
	#copyright {
		float: none;
		margin: 0;
	}
}

/* At <=365 the email no longer fits beside the logo and wraps to its own line
   inside .footLeft; center it there (auto margins on the now-alone flex item).
   365 is the measured wrap point — at 366+ the email stays inline beside the
   logo, so the centering only ever applies once it has actually dropped. c. */
@media screen and (max-width: 365px) {
	#femail {
		margin-left: auto;
		margin-right: auto;
	}
}

/* ==========================================================================
   Block 2c — hamburger menu (phone)
   At <=900 the menu becomes a full-width vertical list. menu-toggle.js adds
   .menu-collapsible (and toggles .menu-open) so JS users get a hamburger button
   that collapses the list; without JS the list stays visible as a plain
   vertical menu. The desktop menu (>=901) is untouched. Palette unchanged —
   bars/separators reuse existing theme grays. c.
   ========================================================================== */

/* Toggle button hidden by default: desktop (>=901) and the no-JS fallback never
   show it. It is revealed only at <=900 once JS marks the menu collapsible. c. */
.menu-toggle {
	display: none;
}

@media screen and (max-width: 900px) {

	/* Menu becomes a full-width block; items stack as full-width rows with
	   comfortable tap targets (the desktop 70px-top tall-buttons are dropped).
	   This vertical form is also the no-JS fallback. c. */
	#menu {
		float: none;
		width: 100%;
		padding: 8px 0 0;
	}
	#menu ul li {
		display: block;
		margin: 0;
		border-bottom: 1px solid #f0f0f0;
	}
	#menu a {
		float: none;
		padding: 14px 15px;   /* >=44px tap target (was 70px 15px 3px tall-button) */
	}

	/* JS-enhanced: reveal the toggle (right-aligned block via auto left margin)
	   and collapse the list until opened. */
	#menu.menu-collapsible .menu-toggle {
		display: block;
		position: relative;
		width: 44px;
		height: 44px;
		margin-left: auto;
		border: 0;
		background: transparent;
		cursor: pointer;
	}
	#menu.menu-collapsible ul {
		display: none;
	}
	#menu.menu-collapsible.menu-open ul {
		display: block;
	}

	/* Hamburger icon: three bars (the span + its two pseudo-elements) in the
	   existing menu gray. c. */
	.menu-toggle-bar {
		position: absolute;
		top: 50%;
		left: 9px;
		width: 26px;
		height: 3px;
		background: #989898;
		transform: translateY(-50%);
		transition: background 0.2s ease;
	}
	.menu-toggle-bar::before,
	.menu-toggle-bar::after {
		content: "";
		position: absolute;
		left: 0;
		width: 26px;
		height: 3px;
		background: #989898;
		transition: transform 0.2s ease, top 0.2s ease;
	}
	.menu-toggle-bar::before {
		top: -8px;
	}
	.menu-toggle-bar::after {
		top: 8px;
	}

	/* Open state: middle bar fades, outer bars cross into an X. c. */
	#menu.menu-open .menu-toggle-bar {
		background: transparent;
	}
	#menu.menu-open .menu-toggle-bar::before {
		top: 0;
		transform: rotate(45deg);
	}
	#menu.menu-open .menu-toggle-bar::after {
		top: 0;
		transform: rotate(-45deg);
	}
}

/* ==========================================================================
   Block 3 — full-bleed utility + Tilda host (integration prep)
   Goal: let a page render Tilda-style markup край-в-край inside the normal site
   chrome (header above, footer below) without touching the existing layout.

   .full-bleed pulls a block out of the centered #wrapper column (max 1280) to
   the full viewport width. The host template (tilda-fullwidth.php) puts the
   content in such a block so Tilda's own blocks lay out as designed:
   .t-cover / .t-container_100 span the window, .t-container self-centers.
   body{overflow-x:hidden} (style.css:39) absorbs the 100vw-vs-scrollbar
   rounding, so no horizontal scrollbar appears.

   Nothing existing carries these classes -> zero visual change to current
   pages. Tilda CSS/JS, the two-jQuery conflict (js-notes §6) and wpautop
   handling for raw pasted markup are the integration stage, not here. c.
   ========================================================================== */
.full-bleed {
	width: 100vw;
	margin-inline: calc(50% - 50vw);
}

/* Tilda host: clears the floated header above it so the content starts below
   the menu/logo row. Pairs with .full-bleed on the same element. c. */
.tilda-host {
	clear: both;
}

/* ==========================================================================
   Block 4 — gallery (art_gallery.php): native scroll-snap slider
   Replaces the easySlider1.7 engine (which froze #slider/ul to 980px at init
   and never recomputed on resize) with a CSS scroll-snap track, and the
   per-pane jScrollPane custom scrollbars with native overflow. The dot
   controls (ol#controls) are rebuilt by scripts/gallery-slider.js with the
   same markup, so the existing dot styling and #controlsN deep-links keep
   working. jqzoom hover-zoom is handled separately (Block 4b). c.
   ========================================================================== */

/* Frame: was fixed 980x450; fluid, original proportions. The 1px border and
   40px margin-top from style.css are kept; border-box keeps the border inside
   the 100% width. c. */
#sliderFrame {
	width: 100%;
	height: auto;
	aspect-ratio: 980 / 450;
	box-sizing: border-box;
}

/* Scroll-snap track (was a JS-driven easySlider). Scrollbar hidden; swipe on
   touch, dot controls on desktop. c. */
#slider {
	width: 100%;
	height: 100%;
	overflow-x: auto;
	overflow-y: hidden;
	scroll-snap-type: x mandatory;
	-webkit-overflow-scrolling: touch;
	scrollbar-width: none;            /* Firefox */
}
#slider::-webkit-scrollbar {           /* WebKit/Blink */
	display: none;
}
#slider ul {
	display: flex;
	width: 100%;
	height: 100%;
	margin: 0;
	padding: 0;
}

/* Each slide spans the track; was fixed 980. c. */
#slider li {
	flex: 0 0 100%;
	width: auto;
	height: 100%;
	overflow: hidden;
	scroll-snap-align: start;
	box-sizing: border-box;
}

/* Inner two-column layout: float -> flex, fixed px -> fluid %. c. */
.innerFrameScroll {
	display: flex;
	gap: 10px;
	height: 100%;
	margin-top: 0;
	box-sizing: border-box;
}
.photoScroll {
	float: none;
	width: auto;
	height: auto;
	flex: 1 1 62%;          /* 600/980 */
	min-width: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	box-sizing: border-box;
}
.photoScroll a.jQZoom {
	display: inline-flex;
	max-width: 100%;
	max-height: 100%;
}
.photoScroll img {
	max-width: 100%;
	max-height: 100%;
	width: auto;
	height: auto;
	object-fit: contain;
}
.textFrame {
	float: none;
	width: auto;
	height: 100%;
	flex: 1 1 32%;          /* 320/980 */
	min-width: 0;
	margin-top: 0;
	box-sizing: border-box;
}
/* Native vertical scroll for long text (was jScrollPane). c. */
.textScroll {
	height: 100%;
	overflow-y: auto;
}

/* Artwork meta under the title: a flowing label/value table.
   Every gallery template emits the same flat run of
   <span class="phTech">label</span><span class="phInfo">value</span> pairs.
   style.css laid them out with float + fixed px widths (115/180) tuned for the
   old fixed 320px column, so they misaligned / wrapped badly at any other
   width — narrow AND wide. CSS grid turns the same markup into a 2-column
   table (labels / values) that stays aligned and flows at every width, across
   all gallery templates at once (.paraInfo, .paraInfo.shortMe,
   .paraInfoConsult). c. */
.paraInfo,
.paraInfoConsult {
	display: grid;
	/* 1fr spacers on the outside centre the content-sized label/value columns,
	   so short values don't strand the visible text to the left (which a single
	   flexible value column did). The title spans all four tracks and wraps into
	   the flexible spacers, so long titles still break across lines instead of
	   stretching the data columns one-line wide (verified on /books/zusman/
	   slide 17). Labels -> col 2, values -> col 3. c. */
	grid-template-columns: 1fr max-content max-content 1fr;
	column-gap: 12px;
}
/* Title spans both columns; keep a reduced reserved height so it doesn't slip
   into the table (was 200/155px). c. */
.paraInfo h2,
.paraInfoConsult h2,
.shortMe h2 {
	grid-column: 1 / -1;
	height: 130px;
	align-self: start;
}
/* Cells: were float + fixed width/height. min-height/line-height give the rows
   air so they don't slip together. c. */
.paraInfo span.phTech,
.paraInfo span.phInfo,
.paraInfoConsult span.phTech,
.paraInfoConsult span.phInfo {
	float: none;
	width: auto;
	height: auto;
	min-height: 30px;
	line-height: 30px;
}
.paraInfo span.phTech,
.paraInfoConsult span.phTech {
	grid-column: 2;
	text-align: right;
}
.paraInfo span.phInfo,
.paraInfoConsult span.phInfo {
	grid-column: 3;
}

@media screen and (max-width: 900px) {
	/* Stack photo over text; each slide grows to its content height. The track
	   still swipes horizontally between artworks; its height is fitted to the
	   active slide by gallery-slider.js (flex-start avoids stretching every
	   slide to the tallest one). c. */
	#sliderFrame {
		aspect-ratio: auto;
		height: auto;
	}
	#slider ul {
		align-items: flex-start;
	}
	#slider li {
		height: auto;
	}
	.innerFrameScroll {
		flex-direction: column;
		height: auto;
		/* Inset the content from the #sliderFrame border so neither the image nor
		   the text butts against it on small screens. c. */
		padding: 10px 16px;
		box-sizing: border-box;
	}
	.photoScroll,
	.textFrame {
		flex: 0 0 auto;
		width: 100%;
		height: auto;
		/* Drop the desktop asymmetric paddings (photoScroll padding-left:10,
		   textFrame padding-right:10) so the image centres and the text sits
		   evenly; the inset above is provided by .innerFrameScroll. c. */
		padding-left: 0;
		padding-right: 0;
	}
	.photoScroll img {
		max-height: none;
	}
	.textScroll {
		height: auto;
		overflow-y: visible;
	}
}

/* Block 4e - gallery slider prev/next chevrons -------------------------------
   easySlider shipped no arrows; gallery-slider.js now adds prev/next <button>s
   that page the scroll-snap track. Minimal side chevrons (same glyphs as the
   lightbox) pinned to the frame's left/right edges, but with NO backing: grey,
   coral on hover. They auto-hide like the lightbox (the script toggles
   .slide-nav-hidden on #sliderFrame) and the script sets their top inline so
   they centre on the photo, not the whole slide (matters on <=900, where the
   text stacks below the photo). c. */
#sliderFrame {
	position: relative;   /* anchor for the absolutely-positioned chevrons. c. */
}
.slideNav {
	position: absolute;
	top: 50%;             /* static fallback; the script overrides top inline to the photo centre. c. */
	transform: translateY(-50%);
	z-index: 5;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 48px;
	height: 72px;
	padding: 0;
	border: 0;
	background: none;     /* no backdrop, unlike the lightbox chevrons. c. */
	color: #999;
	cursor: pointer;
	font-size: 0;         /* drop the button's own text box; the glyph is on ::before. c. */
	line-height: 1;
	transition: opacity 0.55s ease, color 0.2s ease;
}
.slidePrev {
	left: 0;
}
.slideNext {
	right: 0;
}
.slideNav::before {
	font-size: 30px;
	line-height: 1;
}
.slidePrev::before {
	content: '\276E';     /* same chevron glyphs as the lightbox. c. */
}
.slideNext::before {
	content: '\276F';
}
.slideNav:hover {
	color: #f67474;
}
.slideNav:focus-visible {
	outline: 2px solid #f67474;
	outline-offset: -2px;
	color: #f67474;
}
/* Faded out at the track ends (disabled) and while auto-hidden. Both drop
   pointer-events so a click at the photo edge falls through to the photo and
   opens the Shutter lightbox instead of paging. c. */
.slideNav[disabled],
#sliderFrame.slide-nav-hidden .slideNav {
	opacity: 0;
	pointer-events: none;
}

/* Block 4c - bookCovers montage hotspots ------------------------------------
   First slide of the books gallery is one montage of six covers, click-mapped
   with a fixed-pixel <map> whose coords don't scale with the responsive image
   (below ~1020px it renders under 600px and 5/6 hotspots hit the wrong book).
   gallery-bookCovers.php now overlays % anchors on the image; this positions them. c. */
.coverMap {
	position: relative;
	display: inline-block;   /* hugs the image box so the % anchors map onto it. c. */
	max-width: 100%;
}
.coverMap img {
	display: block;          /* drop inline baseline gap so the box == the image. c. */
}
.coverArea {
	position: absolute;
	display: block;
}

/* Block 4 lightbox - Shutter prev/next + counter ----------------------------
   Shutter's built-in lightbox nav is enabled by the shutterset_* class now on
   the gallery photo anchors (nggallery/*.php), which makes Shutter group the
   photos into a set. By default prev/next are tiny "<<" / ">>" text links in a
   bar under the image; restyle them into minimal side chevrons with a faint dark
   backing, vertically centred on the screen edges. The counter stays a quiet grey
   under the image. shutter.css loads after this file, so each rule is scoped
   `body #shDisplay ...` to win specificity without !important. Arrow keys navigate
   the set for free. c. */
body #shDisplay div#shPrev a,
body #shDisplay div#shNext a {
	position: fixed;
	top: 50%;
	transform: translateY(-50%);
	z-index: 10003;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 56px;
	height: 84px;
	margin: 0;
	font-size: 0;
	letter-spacing: 0;
	text-decoration: none;
	color: rgba(255, 255, 255, 0.85);
	background: rgba(0, 0, 0, 0.28);
}
body #shDisplay div#shPrev a { left: 0; border-radius: 0 6px 6px 0; }
body #shDisplay div#shNext a { right: 0; border-radius: 6px 0 0 6px; }
body #shDisplay div#shPrev a::before { content: '\276E'; font-size: 34px; line-height: 1; }
body #shDisplay div#shNext a::before { content: '\276F'; font-size: 34px; line-height: 1; }
body #shDisplay div#shTitle a:hover {
	color: #f67474;
	background: rgba(0, 0, 0, 0.40);
}
body #shDisplay div#shPrev a:focus-visible,
body #shDisplay div#shNext a:focus-visible {
	outline: 2px solid #f67474;
	outline-offset: -2px;
}
body #shDisplay div#shCount {
	color: #999;
	margin-top: 8px;
	font-size: 12px;
}

/* Auto-hide: controls fade out a moment after each image (lightbox-autohide.js
   toggles .sh-controls-hidden on #shDisplay). No pointer-events:none - the hit
   zones stay live while invisible, so an edge tap/click still pages. c. */
body #shDisplay div#shPrev a,
body #shDisplay div#shNext a,
body #shDisplay div#shCount {
	transition: opacity 0.55s ease;
}
body #shDisplay.sh-controls-hidden div#shPrev a,
body #shDisplay.sh-controls-hidden div#shNext a,
body #shDisplay.sh-controls-hidden div#shCount {
	opacity: 0;
}

/* Loading indicator: lightbox-autohide.js clears Shutter's inline pageHeight/2
   offset and sets a plain label; this centres it on the viewport and makes it
   small/grey instead of big bold crimson. c. */
body #shShutter #shWaitBar {
	position: fixed;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	width: auto;
	height: auto;
	margin: 0;
	font: 400 14px/1.4 'Helvetica Neue', Arial, sans-serif;
	letter-spacing: normal;
	color: #999;
}

/* ==========================================================================
   Block 5 — home template (art_page.php): intro text under the banner
   The banner (.fadein slideshow) was already fluidised in Block 1. The only
   remaining piece is #introHome: style.css gives it a 170px top gap under the
   banner, an awkward empty band on narrow screens, so trim it at <=900. Keep a
   small left inset: the banner has a ragged/torn edge and the inset lines the
   intro up under it (that's why it isn't zeroed) - scaled from the desktop 10px
   down to 5px on narrow. The intro reveal (a jQuery fade in the old myslideshow.js)
   is now a CSS transition; scripts/intro-reveal.js only toggles the classes - see
   Block 7. c.
   ========================================================================== */
@media screen and (max-width: 900px) {
	#introHome {
		margin-top: 120px;
		margin-left: 5px;
	}
}

/* ==========================================================================
   Block 6 — contact template (contact-form.php): form + content blocks
   The page is one column in source order, but everything is pinned to desktop
   pixel widths/floats: the form (div.box 615px, inputs 200px, textarea 350px,
   labels a 100px right-aligned column, button/status indented 120px) and the
   blocks after it (#bioText 560px, #contactImage img / #contactDetails /
   #bookLinks floated). At <=900 that forces ~250px of horizontal scroll. Make
   the form fluid with stacked labels and drop the floats so everything falls
   into one column. Markup, validation (scripts/contact-form.js) and mail() are
   untouched - CSS only. c.
   ========================================================================== */
@media screen and (max-width: 900px) {
	/* Form: fluid box, full-width fields (border-box keeps the 2px border + inner
	   padding inside 100%), labels stacked above their field. c. */
	div.box {
		width: auto;
		float: none;
	}
	div.box .input_text,
	div.box .message {
		width: 100%;
		box-sizing: border-box;
		display: block;
	}
	div.box label span {
		float: none;
		width: auto;
		text-align: left;
		padding: 0 0 4px 0;
	}
	div.box label span.error {
		float: none;
		width: auto;
		padding: 4px 0;
	}
	/* Button + status lose the 120px column indent. c. */
	div.box button.button {
		margin-left: 0;
	}
	#msgStatus {
		width: auto;
		margin-left: 0;
	}
	/* Blocks under the form stack into one column (were floated / fixed-width).
	   #contactImage img keeps the Block 2a max-width:100%. c. */
	#contactFormWrap,
	#contactDetails,
	#bookLinks,
	#bioText {
		float: none;
	}
	#bioText {
		width: auto;
	}
	#contactImage img {
		float: none;
	}
}

/* ==========================================================================
   Block 7 — home intro fade-in (art_page.php). Replaces the jQuery .animate
   reveal from the old myslideshow.js. scripts/intro-reveal.js adds .intro-fade
   on load (so the text stays visible with JS off) and .intro-shown on reveal.
   The transition sits on the revealed state, so the initial hide is instant (no
   fade-out flash) and only the reveal animates - matching the old 1.5s fade-in.
   Applies at all widths (not just <=900). c.
   ========================================================================== */
.fade.intro-fade { opacity: 0; }
.fade.intro-fade.intro-shown { opacity: 1; transition: opacity 1.5s ease; }

/* ==========================================================================
   Post date badge - year line under the day number (feed / search / archive).
   Added together with the new .year in the .the_date block; lives here to keep
   the original style.css untouched. Year sits tucked under the big day number
   (negative top margin); month (#d3cece) and year (#b8b7b7) sit a step darker
   than the big day number, which keeps its original light grey. c.
   ========================================================================== */
.the_date .year {
	font-family: georgia, serif;
	color: #b8b7b7;
	font-size: 15px;
	line-height: 1;
	margin: -12px 0 0 0;
}

.the_date .month { color: #d3cece; }  /* override style.css light grey; a touch lighter than the year. c. */
