/*
Theme Name: Shakes
Theme URI:
Author: Rob Anderson
Description: Blank starter theme for Shakes project. Designed for custom Gutenberg blocks.
Version: 1.0.0
Text Domain: shakes
*/

/* Clip any accidental horizontal overflow (e.g. 100vw break-outs, wide SVGs)
   without disabling position: sticky inside the page. */
html {
	overflow-x: clip;
}

/* Fixed overlay header. At the top it is transparent; after the page begins
   scrolling it adopts the same 76%-opaque dark glass treatment and 18px blur
   used by the Resolut reference header. Plain CSS keeps the JS-only state
   independent of Tailwind's content scanner. */
.site-header {
	position: fixed;
	background-color: transparent;
	-webkit-backdrop-filter: blur(0) saturate(1);
	backdrop-filter: blur(0) saturate(1);
	transition: background-color 0.3s, backdrop-filter 0.3s, -webkit-backdrop-filter 0.3s, box-shadow 0.3s;
	border-bottom: 1px solid transparent;
}

/* !important: Tailwind's utilities (bg-transparent etc.) are compiled inside
   @layer utilities, which can out-prioritize normal specificity from this
   unlayered stylesheet — same reason editor-overrides.css uses !important. */
.site-header.is-scrolled {
	background-color: rgba(7, 8, 11, 0.76) !important;
	-webkit-backdrop-filter: blur(18px) saturate(1.35);
	backdrop-filter: blur(18px) saturate(1.35);
	box-shadow: 0 12px 30px rgba(0, 0, 0, 0.18);
}

/* The page visible beside the mobile off-canvas menu uses the same dark glass
   as the scrolled header, keeping both navigation states visually consistent. */
#site-navigation-overlay {
	background-color: rgba(7, 8, 11, 0.76);
	-webkit-backdrop-filter: blur(18px) saturate(1.35);
	backdrop-filter: blur(18px) saturate(1.35);
}

/* One lockup, always. The header used to stack the full lockup and the icon-only
   mark absolutely on top of each other and crossfade between them on scroll; that
   is gone, so the absolute positioning and the fixed 224x45 footprint that existed
   to stop the nav shifting mid-fade go with it. The image sizes itself now.

   `.site-logo-mark` and the `.is-scrolled` rules are deliberately deleted rather
   than left dormant — .is-scrolled is still set on the header for other things, so
   a dormant rule here would come back to life the moment someone re-added the
   element. */
.site-logo {
	position: relative;
	display: block;
}

/* Native desktop select menus otherwise render the form's inherited white
   text on the browser's default white option background until hover. */
.shakes-contact-department option {
	background-color: #1E1E1E;
	color: #FFFFFF;
}

/* The image itself carries h-[42px] md:h-[45px], so the wrapper no longer needs a
   matching height — it did only while the images were absolutely positioned out of
   flow and the wrapper had to reserve their space. */

/* Off-canvas mobile nav links: wp_nav_menu's default walker only lets us set
   a class on the <ul> (menu_class), not on each <a> — so these rows are
   plain CSS rather than Tailwind utilities, matching the .site-header
   pattern above. The current-page accent border lives on the full-bleed <li>
   (edge to edge, per Figma); the row divider lives on the <a> and is inset
   by the same left/right margin the link text/icon are padded by, so it
   stops short of the screen edges instead of spanning full width. The
   right margin (24px) is intentionally narrower than the left (32px) so the
   nav-arrow icons land at the same inset as the close (X) button. */
.shakes-nav-menu-mobile > li {
	width: 100%;
	border-left: 2px solid transparent;
}

.shakes-nav-menu-mobile > li.current-menu-item,
.shakes-nav-menu-mobile > li.current_page_item {
	border-left-color: #8D1D1C;
}

/* The Duct Run "Play" trigger sits outside the generated menu markup (it's a
   <button>, since it opens a dialog rather than navigating) but shares the row
   treatment so it reads as one more item in the list. Temporary, alongside the
   rest of the Play modal harness. */
.shakes-nav-menu-mobile > li > a,
.shakes-duct-play-mobile {
	display: flex;
	align-items: center;
	justify-content: space-between;
	margin: 0 24px 0 32px;
	padding: 16px 0;
	border-bottom: 2px solid #1E1E1E;
	color: #FFFFFF;
	font-family: "Chakra Petch", sans-serif;
	font-weight: 600;
	font-size: 24px;
	line-height: 32px;
	letter-spacing: 2.4px;
	text-transform: uppercase;
	text-decoration: none;
}

/* A <button> brings its own UA borders and centred label, so restate what the
   <a> rule takes for granted. Width comes from the parent nav's flex-col
   stretch — form controls size to their content even at width:auto. The extra
   2px of left margin stands in for the transparent accent border on the <li>
   the generated rows sit inside, so this row's text and divider line up with
   theirs to the pixel. */
.shakes-duct-play-mobile {
	margin-left: 34px;
	border-left: 0;
	border-right: 0;
	border-top: 0;
	text-align: left;
}


/* ---- Duct Run launcher ----------------------------------------------------
   The nav trigger is set in the game's own 5x7 face with the joystick beside
   it, so the entry point looks like the thing it opens rather than one more
   nav word. The face is declared here rather than in duct-run.css because that
   stylesheet is only fetched when the modal first opens — by which point the
   header has long since rendered. */
@font-face {
	font-family: ShakesPixel;
	src: url(assets/fonts/shakes-pixel.ttf) format("truetype");
	font-display: swap;
}

.shakes-duct-play {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	font-family: ShakesPixel, ui-monospace, monospace;
	/* One pixel per unit at 8px, so only multiples of 8 land on whole pixels. */
	font-size: 16px;
	line-height: 1;
	letter-spacing: 1px;
	-webkit-font-smoothing: none;
}

.shakes-duct-play .joystick {
	width: 26px;
	height: 26px;
	flex: 0 0 auto;
	display: block;
	image-rendering: pixelated;
}

/* Desktop uses the game itself as the launcher: a reduced yellow handheld
   console with its cyan duct route still legible at navigation size. */
.shakes-duct-play-desktop {
	width: 44px;
	height: 44px;
	padding: 2px;
	border: 0;
}

.shakes-duct-play-desktop .duct-run-console-icon {
	display: block;
	width: 40px;
	height: 40px;
	transform-origin: 50% 65%;
}

@keyframes shakes-console-bounce {
	0%, 100% { transform: translateY(0) rotate(0deg); }
	28% { transform: translateY(-7px) rotate(-4deg); }
	48% { transform: translateY(0) rotate(2deg); }
	68% { transform: translateY(-3px) rotate(-2deg); }
	84% { transform: translateY(0) rotate(1deg); }
}

.shakes-duct-play-desktop:hover .duct-run-console-icon {
	animation: shakes-console-bounce 520ms cubic-bezier(0.34, 1.56, 0.64, 1);
}

@media (prefers-reduced-motion: reduce) {
	.shakes-duct-play-desktop:hover .duct-run-console-icon {
		animation: none;
	}
}

.shakes-duct-play-desktop:focus-visible {
	outline: 2px solid #8d1d1c;
	outline-offset: 3px;
}

/* In the off-canvas panel the row is taller and left-aligned, so the icon sits
   with the text rather than centring the pair. The label matches the other
   items in that list rather than setting its own size. */
.shakes-duct-play-mobile {
	justify-content: space-between;
	font-size: 16px;
}

.shakes-duct-play-mobile .duct-run-console-icon {
	width: 32px;
	height: 32px;
	flex: 0 0 auto;
	display: block;
}

/* ---- Duct Run modal shell -------------------------------------------------
   The open/close transition is written here rather than as Tailwind utilities
   toggled from JS: those class names only ever appear inside a JavaScript
   string, and Tailwind's content glob doesn't scan assets/js — so any new state
   would compile to nothing. This also lives in style.css rather than
   duct-run.css because duct-run.css is fetched on first open, which is the very
   moment the opening transition runs. */
#duct-run-modal {
	align-items: center;
	padding: 12px;
	background-color: rgba(7, 8, 11, 0.76) !important;
	-webkit-backdrop-filter: blur(18px) saturate(1.35);
	backdrop-filter: blur(18px) saturate(1.35);
	transition: opacity 600ms cubic-bezier(0.22, 1, 0.36, 1);
}

/* Rises from the bottom on every size, not just phones — it is the same object
   arriving the same way, and the scale-and-fade it replaced read as a web modal
   rather than as a machine being pulled up in front of you. */
#duct-run-panel {
	/* The 6x6 game uses a deliberate landscape cabinet on desktop: a readable
	   fitting/action service bay beside the native 504px board, plus framing. */
	max-width: 900px;
	opacity: 0;
	transform: translateY(100%);
	transition: opacity 600ms ease, transform 650ms cubic-bezier(0.22, 1, 0.36, 1);
}

#duct-run-panel.is-open {
	opacity: 1;
	transform: none;
}

/* On a phone it is a sheet: it comes up from the bottom edge and stays there,
   which is where a thumb already is. Full width, and the bottom corners square
   because there is nothing below them to round against. */
@media (max-width: 639px) {
	#duct-run-modal {
		align-items: flex-end;
		padding: 0;
	}

	#duct-run-panel { max-width: none; }

	#duct-run-modal .shakes-duct {
		border-radius: 16px 16px 0 0;
		border-bottom: 0;
	}
}

@media (prefers-reduced-motion: reduce) {
	#duct-run-modal,
	#duct-run-panel { transition: none; }
}


/* ================= footer slogan =================
   Real text where the footer logo used to carry baked letterforms, framed by the two
   red corner brackets the artwork had. Each bracket is an L of two borders on a
   pseudo-element — which is all they ever were — so they now grow and shrink with the
   text instead of being fixed at whatever size the SVG was drawn at.

   Diagonally opposed, top-left and bottom-right, matching the original. Not a full
   border: the point of a bracket is that it implies the frame rather than drawing it.

   Italic and letter-spaced to match the artwork it replaces. The face is the theme's
   only one (Chakra Petch), which is what the lettering was set in. */
.site-slogan {
	position: relative;
	margin: 0;
	/* The padding IS the gap between the text and its brackets — there is no other
	   spacing between them — so it sets how tight the framing reads and, at the same
	   time, how much width the text gets. Tight: 8px and 10px. Narrowing it only ever
	   gives the text MORE room, so the three-line wrap this needs is safe (it needs at
	   least 260px of content and now has 280px). Going the other way is what breaks
	   it: at 18px inside a 260px box the content was 224px and the line wrapped to
	   five. */
	padding: 8px 10px;
	/* Sized to HUG the text, not to fill the column. The brackets sit on this box's
	   corners, so a 300px box beside a 203px line put them 40px out and reading as
	   unrelated to the words. 232px is the longest rendered line plus the padding plus
	   9px of slack — enough that a slightly different font rendering on the server
	   cannot tip the wrap to four lines, and close enough that the brackets read as
	   framing the text.

	   Measured, not guessed, and it is TIED TO THE EXACT STRING. This has already been
	   re-measured once, when the slogan changed and changed back: at 232px the current
	   wording wraps to five lines, and the shorter one it briefly held wrapped to two
	   at 300px. 284px is the current line's widest rendered row (256px) plus the
	   padding plus 8px of slack. If the wording changes again, re-measure. */
	max-width: 284px;
	text-align: center;
	font-style: italic;
	font-weight: 500;
	/* 13px, up from 12. It reads small beside the mark at 12, and the mark itself
	   came down 25% in the same pass — this keeps the block from looking like a
	   caption under a logo rather than part of one lockup. */
	font-size: 13px;
	line-height: 1.7;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: #585858;
}

.site-slogan::before,
.site-slogan::after {
	content: "";
	position: absolute;
	width: 14px;
	height: 14px;
	border: 2px solid #8D1D1C;
}

.site-slogan::before {
	top: 0;
	left: 0;
	border-right: 0;
	border-bottom: 0;
}

.site-slogan::after {
	right: 0;
	bottom: 0;
	border-left: 0;
	border-top: 0;
}
