/*
Theme Name: Kedyn Sierra Photography
Theme URI: https://kedynsierra.com
Author: Kedyn Sierra
Author URI: https://kedynsierra.com
Description: Built by hand as a passion project — a custom theme made better, piece by piece, to function and support Kedyn Sierra's photography. Showcases his travel and adventure work, including the 21-day EU expedition series, alongside his portfolio, sponsor and featured-brand partnerships, and contact information for bookings and collaborations.
Version: 0.1.0
License: GNU General Public License v2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: kedynsierra-theme
Requires PHP: 7.4
Tested up to: 6.6
*/

/*
 * This theme has a License/License URI header because `theme-check` reports
 * a missing one as an issue, and that run is one of the remaining cutover
 * blockers (CUTOVER-RUNBOOK.md §0), so this is one fewer finding to triage
 * there.
 *
 * Matches the value on photome-child/style.css. GPL v2-or-later is the
 * standard WordPress theme licence and the correct label for theme PHP
 * regardless, since WordPress's own licence propagates to it. No vendor links
 * anywhere.
 */

/*
 * Everything below this block is ported verbatim from
 * wp-content/themes/photome-child/style.css (lines 20-459 of that file, i.e.
 * everything after its own "Add any of your own custom CSS styles below this
 * line" marker) into the standalone kedynsierra theme (Phase 3.2 of
 * PARENT-THEME-FORK-PLAN.md, 2026-08-04). These are the child theme's real,
 * static, hand-authored CSS rules only - not the parent's vendor screen.css/
 * grid.css, and not the Kirki-Customizer-generated dynamic CSS that the parent
 * injects at runtime via its own custom-css.php (that file is being ported
 * separately into templates/custom-css.php per this same phase, unchanged, as
 * its own runtime-generated stylesheet - it is not duplicated here). No rule
 * text was altered; only this citation banner is new. The child theme's own
 * distinct "Theme Name/Template/etc." header block (that file's lines 1-15)
 * is intentionally NOT carried over - this theme already has its own header
 * block above, and this is now a standalone theme with no Template: parent.
 */

/*
 * Mobile nav visibility fix: the parent theme's dynamic custom-css.php
 * unconditionally hides #mobile_nav_icon (no media query) whenever the
 * tg_sidemenu option is off, and it was only visually rescued because
 * grid.css happened to be enqueued afterward and won the !important tie
 * below 960px. Made explicit and deterministic here instead of relying on
 * incidental enqueue order between two parent-theme stylesheets.
 */
@media (min-width: 961px) {
	#mobile_nav_icon {
		display: none !important;
	}
}

@media (max-width: 960px) {
	#mobile_nav_icon {
		display: inline-block !important;
	}
}

/*
 * Nav hover/focus animation. The parent's own hover rule only nudges
 * #666->#444 with no transition on color (only padding animates), and gets
 * fully overridden anyway by the parent's `color:#fff !important` on
 * transparent/hero headers - so hover has never been visible there. An
 * underline driven by currentColor sidesteps color mode entirely, working
 * identically in both the light-on-dark (hero) and dark-on-light (inner
 * page) header states. Selector stacks both IDs to match/exceed the
 * parent's `#menu_wrapper div .nav li > a` specificity.
 */
#menu_wrapper #main_menu.nav > li > a {
	position: relative;
	transition: color 0.25s ease, padding 0.3s;
}
#menu_wrapper #main_menu.nav > li > a::after {
	content: '';
	position: absolute;
	left: 15px;
	right: 15px;
	bottom: 6px;
	height: 1px;
	background: currentColor;
	transform: scaleX(0);
	transition: transform 0.25s ease;
}
#menu_wrapper #main_menu.nav > li > a:hover::after,
#menu_wrapper #main_menu.nav > li > a.hover::after,
#menu_wrapper #main_menu.nav > li.current-menu-item > a::after,
#menu_wrapper #main_menu.nav > li.current-menu-parent > a::after {
	transform: scaleX(1);
}
@media (prefers-reduced-motion: reduce) {
	#menu_wrapper #main_menu.nav > li > a::after {
		transition: none;
	}
}
.mobile_main_nav li a, #sub_menu li a {
	transition: color 0.2s ease;
}
#close_mobile_menu {
	opacity: 0.7;
	transition: opacity 0.2s ease;
}
#close_mobile_menu:hover, #close_mobile_menu:focus-visible {
	opacity: 1;
}

/*
 * Lightbox close button. The vendor Magnific Popup copy was hand-modified to
 * emit an empty <a class="mfp-close"> with no text/glyph - the "x" depended
 * entirely on a FontAwesome :after rule that only covers 2 of the 3 holder
 * types (image/iframe). The video type (.mfp-inline-holder, used by
 * YouTube/Vimeo/self-hosted-video portfolio items) had zero close-button CSS
 * at all, so it was always invisible/unclickable there, not just sometimes.
 * Click-to-close JS already works generically on the .mfp-close class - this
 * is purely a rendering gap. Using a plain Unicode "x" instead of a
 * FontAwesome glyph so it can't silently fail the same way again.
 */
.mfp-image-holder .mfp-close,
.mfp-iframe-holder .mfp-close,
.mfp-inline-holder .mfp-close {
	right: -13px;
	top: -10px;
	width: 40px;
	height: 40px;
	line-height: 40px;
	border-radius: 250px;
	border: 2px solid transparent;
	color: #fff;
	text-align: center;
	cursor: pointer;
	transition: border-color 0.3s ease-out;
}
.mfp-image-holder .mfp-close:hover,
.mfp-iframe-holder .mfp-close:hover,
.mfp-inline-holder .mfp-close:hover {
	border-color: #fff;
}
.mfp-image-holder .mfp-close::after,
.mfp-iframe-holder .mfp-close::after,
.mfp-inline-holder .mfp-close::after {
	content: "\00d7";
	display: block;
	font-family: Arial, Helvetica, sans-serif;
	font-size: 28px;
	line-height: 40px;
}

/* Contact "Send" button contrast: the parent's generic .solidbg rule is
 * white text on gold (1.68:1), well under the 4.5:1 WCAG AA minimum for
 * text. Keeps the existing gold accent, just fixes the text color. */
input[type=submit].solidbg {
	color: #222;
}

/* Visible keyboard focus: buttons and portfolio filter links currently ship
 * outline:none with no replacement, so keyboard users get zero feedback.
 *
 * Two-tone ring instead of one fixed color: several of these focusable
 * elements (nav links, the logo) sit inside a transparent header over
 * whatever hero photo is currently showing - an arbitrary, unpredictable
 * background a single fixed outline color can't be guaranteed to contrast
 * against (FULLSTACK-AUDIT.md §1.7 flagged the prior single #4a90d9 blue as
 * needing exactly this dual-context check, the same category of bug already
 * found and fixed on the logo's own hover color, live, against two header
 * states). A black ring flush against the element plus a white ring just
 * outside it guarantees at least one of the two contrasts with any
 * background - photo, dark header, or light page - without needing to know
 * what that background actually is. box-shadow (0 spread offset, 2px
 * spread) fills the gap outline-offset leaves transparent; outline paints
 * on top of box-shadow per spec, so the two rings sit flush with no seam. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible,
/*
 * [tabindex="0"] added 2026-08-24. The list above covers only natively
 * focusable elements, but this site deliberately makes two kinds of generic
 * element focusable: the twelve gallery carousels (so the engine's
 * arrow-key handler is reachable) and the Leaflet trip map. Those fell back
 * to the browser's default focus ring, which on a dark, grained portfolio
 * page can be almost invisible - exactly the backgrounds this two-tone ring
 * exists to survive.
 */
[tabindex="0"]:focus-visible,
.portfolio_filter_wrapper a:focus-visible {
	outline: 2px solid #fff;
	outline-offset: 2px;
	box-shadow: 0 0 0 2px #000;
}

/* Title-band fade+rise on page load: single-portfolio.php's 9 category
 * pages and front-page.php's #page_caption. Applied via a wrapper div
 * around the include/element rather than targeting template-portfolio-
 * header.php's internal markup directly - that file is parent-theme-only
 * and not present in this child theme to read, so this stays fully
 * decoupled from whatever markup lives inside it. */
.pm-title-reveal {
	animation: pmTitleReveal 0.7s cubic-bezier(0.22, 1, 0.36, 1) both;
}
@keyframes pmTitleReveal {
	from { opacity: 0; transform: translateY(18px); }
	to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
	.pm-title-reveal { animation: none; }
}

/*
 * Ported verbatim from the Customizer's "Additional CSS" field (wp_posts,
 * post_type 'custom_css', post ID 1877, last edited 2025-04-09) - a
 * FULLSTACK-AUDIT.md §7 flagged opportunity ("fold the ~10 lines of DB-only
 * Additional CSS into style.css"). This was live on every page but existed
 * ONLY in the database - invisible to git, to code review, and to anyone
 * reading this theme's tracked files, despite genuinely affecting rendered
 * output (the #logo_wrapper spacing, the hover-zoom on portfolio/one_half
 * images, and the #overlay_background/#fullscreen_share_wrapper hiding rule
 * - the last one already redundant-but-harmless with this theme's own
 * js/remove-overlay-background.js, which removes that element from the DOM
 * entirely). No rules changed from the original - purely a visibility/
 * version-control fix. The Customizer's Additional CSS field still holds
 * this content and needs clearing by whoever has wp-admin access, so there
 * is a single source of truth instead of two copies; it is tracked as a
 * post-cutover step in PRE-DEPLOY-CHECKLIST.md §4.1 rather than left to this
 * comment. The same applies to the `pp_custom_css` option, which - being a
 * plain option rather than one keyed to the active stylesheet - keeps
 * applying after cutover and so is the more durable of the two duplicates.
 */
#logo_wrapper {
	text-align: center;
	padding: 30px 0 0 0;
	/*
	 * !important (CASCADE-BUG-2026-08-03.md): this rule was ported verbatim
	 * from the Customizer's Additional CSS field (see comment above), which
	 * reliably won the cascade only because WordPress prints it via
	 * wp_custom_css_cb at priority 101, after every enqueued stylesheet.
	 *
	 * That field is NOT empty - a production database check found ~897 bytes
	 * still in it, including this rule. An earlier version of this comment
	 * claimed it had been cleared; it never was. What makes that survivable
	 * is that Additional CSS is looked up by `post_name = get_stylesheet()`,
	 * and this post is keyed to `photome-child` - so it stops being read the
	 * moment the site cuts over to `kedynsierra`, which is precisely when
	 * this ported copy has to win on its own. That makes !important more
	 * necessary here, not less: the safety net it replaces disappears at
	 * cutover rather than having already gone.
	 *
	 * Without it the identical-specificity #logo_wrapper rule in the parent's
	 * screen.css wins, since that prints later in <head> than this stylesheet.
	 * An attempt to fix print order with an explicit wp_enqueue_style()
	 * dependency had no effect (see that doc) - Jetpack Boost's CSS handling
	 * is a live suspect, confirmed elsewhere in this project to alter
	 * stylesheet output, and if it reorders or defers stylesheets after
	 * WordPress's own dependency resolution runs, no enqueue-order fix here
	 * could ever be reliable. !important sidesteps the question entirely
	 * rather than betting on a print-order fix that can't be visually
	 * verified from static reading alone.
	 */
	border-bottom: 0 solid #e1e1e1 !important;
}
html[data-style=fullscreen] #logo_wrapper,
.top_bar.hasbg #logo_wrapper {
	border-bottom: 0 solid rgba(256, 256, 256, .3) !important;
}
/*
 * Header/heading overlap on scroll (POST-DEPLOY-BUGS-2026-08-03.md #2,
 * reported twice, root-caused with real measurements in
 * BUGS-2026-08-03-round3.md #2): the parent theme's own custom.js adds a
 * `.scroll` class to `.top_bar` past 200px of scroll (confirmed by reading
 * the parent's real custom.js, `pp_fixed_menu` branch - MISSION-AUDIT.md's
 * sticky-header investigation) and shrinks it from 159px to 46px tall - but
 * never gives it a background for that state. The bar is `position: fixed`
 * with `background: rgba(0,0,0,0)` throughout, so scrolled-past content is
 * plainly visible through it and the page heading sitting just underneath
 * reads as "cut in half," not just close to the bar. Not a spacing bug -
 * spacing-based fixes (padding/scroll-margin-top) would leave the
 * transparency itself unaddressed.
 *
 * Deliberately does NOT touch the at-rest (unscrolled) transparent state -
 * that's a real, separate design choice used on several pages
 * (page_menu_transparent postmeta) and out of scope here. `!important`
 * because this is the same child-vs-parent stylesheet, same structural
 * cascade risk already found and fixed at #logo_wrapper above in this same
 * file (CASCADE-BUG-2026-08-03.md) - no reason to assume a plain rule would
 * reliably win here either. `.header_style_wrapper.scroll` chained
 * alongside `.top_bar.scroll` since two independent live measurements named
 * two different elements for what may be the same node or tightly-coupled
 * wrapper/child pair (one measurement found `.header_style_wrapper` directly
 * via devtools; the parent-JS trace above found `.top_bar` as the class
 * `custom.js` actually toggles) - harmless if one of the two never matches
 * anything, but not confirmed from static reading alone which is real.
 * Color is a plain white guess, not verified against the parent's own
 * "solid header" state elsewhere (screen.css is only reachable via a
 * connected/live browser) - whoever can check that state directly should
 * swap this for the real value if it differs.
 */
.top_bar.scroll,
.header_style_wrapper.scroll {
	background-color: #fff !important;
}

/*
 * THE OTHER HALF OF THE RULE ABOVE (2026-08-24).
 *
 * The comment above ends by saying its white was "a plain white guess, not
 * verified... whoever can check that state directly should swap this for the
 * real value if it differs." Checked it directly, in a real browser, scrolled:
 * the white is fine, but it was only half the job.
 *
 * On the HOMEPAGE the bar renders as `top_bar hasbg` (the transparent-header
 * state, because the nav sits over the hero photograph). screen.css:1380 makes
 * every nav link, icon and contact link in that state `--color-white`, which is
 * correct over a photo. Scrolling past 200px then adds `.scroll` and the rule
 * above paints the bar white - but nothing ever reset the text. Measured live
 * at scrollY 600: link colour rgb(255,255,255) on a painted rgb(255,255,255)
 * bar. That is 1.00:1. The entire navigation and the logo disappear, and the
 * screenshot confirms a blank white strip where the header should be.
 *
 * Only the homepage is affected - every other page renders `top_bar` without
 * `hasbg`, so its nav is already dark.
 *
 * The logo rules below are a NO-OP on this site today, kept for correctness
 * rather than because they fix anything visible. The theme renders two
 * mutually-exclusive logo anchors and `hasbg` shows the light one, so the
 * same white-on-white reasoning would apply - but measuring the live page
 * found `#logo_wrapper` itself computing to `display: none`, independent of
 * scroll state, so no logo renders in this header at all. That is a
 * pre-existing site-wide setting, not part of this bug and not changed here.
 * If the logo is ever switched back on, these rules mean the scrolled state
 * is already correct instead of quietly reintroducing the same defect.
 */
.top_bar.hasbg.scroll #menu_wrapper div .nav > li > a,
.top_bar.hasbg.scroll i,
.top_bar.hasbg.scroll #mobile_nav_icon,
.top_bar.hasbg.scroll .top_contact_info,
.top_bar.hasbg.scroll .top_contact_info a,
.top_bar.hasbg.scroll .top_contact_info a:hover,
.top_bar.hasbg.scroll .top_contact_info a:active {
	/*
	 * #6d6d6d = 5.09:1 on white. The theme's own default for this nav is
	 * #848484, which is only 3.74:1 and fails WCAG AA for 12px text, so the
	 * scrolled state uses a value that actually passes rather than inheriting
	 * a failing one.
	 */
	color: #6d6d6d !important;
}

/* Keep the current-page item distinguishable from its siblings, as it is
   everywhere else on the site. #333 = 12.63:1. */
.top_bar.hasbg.scroll #menu_wrapper div .nav > li.current-menu-item > a,
.top_bar.hasbg.scroll #menu_wrapper div .nav > li.current_page_item > a,
.top_bar.hasbg.scroll #menu_wrapper div .nav > li > a:hover {
	color: #333 !important;
}

/* Swap the light hero logo for the dark one once the bar turns white. */
.top_bar.hasbg.scroll #custom_logo_transparent {
	display: none !important;
}

.top_bar.hasbg.scroll #custom_logo {
	display: inline-block !important;
}

/* The logo underline accent is keyed to the light state by
   css/site-logo.css; return it to the dark value on the white bar. */
.top_bar.hasbg.scroll .logo_wrapper::before {
	--logo-line-color: #1a1a1a;
}
.portfolio_classic_icon_wrapper {
	display: none !important;
}
.one_third {
	overflow: hidden;
}
.one_third .portfolio_img {
	/*
	 * !important, same root cause as #logo_wrapper above
	 * (CASCADE-BUG-2026-08-03.md) - and here the parent's conflicting rule
	 * (.one_third.gallery3.classic a img) is also higher specificity (3
	 * classes + a type selector vs. this rule's 2 classes), not just later
	 * in the document, so raising specificity to match would mean an
	 * escalating war against a vendor stylesheet this project doesn't
	 * control. !important is the stable fix.
	 */
	transition: transform 0.5s ease-out !important;
}
.one_third:hover .portfolio_img {
	/*
	 * Both !important, same reason as the base rule above - the parent's
	 * .one_third.gallery3.classic a:hover img sets transform: scale(1.3) at
	 * even higher specificity (4 classes + 2 type selectors), not just a
	 * conflicting transition. Without this, hovering wouldn't just use the
	 * wrong easing, it would scale to 1.3x instead of the intended 1.09x.
	 * transition needs !important too so this selector's higher specificity
	 * (3 classes vs. the base rule's 2) still resolves correctly against the
	 * base rule now that both are candidates during :hover.
	 */
	transform: scale(1.09) !important;
	transition: transform 0.5s ease-in-out !important;
}
.one_third:not(:hover) .portfolio_img {
	transform: scale(1);
}
.one_half_bg {
	transition: transform 0.5s ease-in-out;
}
.one_half_bg:hover {
	transform: scale(1.03);
}
.one_half_bg:not(:hover) {
	transform: scale(1);
}
/*
 * Real bug: the site logo is sliced by the mobile nav drawer's left edge.
 * This rule used to also blanket-hide #overlay_background alongside
 * #fullscreen_share_wrapper - this docblock's own comment above called that
 * "redundant-but-harmless" with js/remove-overlay-background.js, which
 * deleted #overlay_background from the DOM entirely. Both assumptions
 * turned out wrong once that JS (and a same-purpose WPCode snippet doing
 * the identical DOM removal, found live in wp_posts post 3900 - both
 * migrated from real, separate production customizations aimed at the same
 * dead "share icons" feature) were removed: #overlay_background ALSO has a
 * completely different, still-real job - css/screen.css's
 * `body.js_nav #overlay_background` rule dims the screen behind the mobile
 * nav drawer (which is only 270-360px wide, not full-viewport) whenever it
 * opens. This !important rule kept that dimming permanently suppressed
 * even after both DOM-removal mechanisms were fixed, leaving the
 * header/logo exposed and visually sliced by the drawer's edge.
 * #overlay_background dropped from this selector - confirmed safe (not
 * reintroducing the old share-icon visual) since nothing in this fork can
 * trigger `.share_open`/`.visible` on it anymore (grepped: `#page_share`'s
 * click handler, the only thing that ever did, was never ported - same
 * "confirmed dead, no real trigger left" situation this fork already
 * documented for the mobile submenu drill-down) - only `body.js_nav` can
 * affect it now, exactly the behavior this fix restores.
 * #fullscreen_share_wrapper (a different, separate element, still
 * genuinely dead) stays hidden.
 */
#fullscreen_share_wrapper {
	display: none !important;
	visibility: hidden !important;
	opacity: 0 !important;
}

/*
 * Ported verbatim from the pp_custom_css option (wp_options) - the second DB-only
 * custom-CSS location CONSOLIDATED-AUDIT.md flags alongside the Customizer "Additional
 * CSS" folded in above, ported here separately since it wasn't caught in that same
 * pass. Hides the parent theme's .icon-scroll "scroll down" indicator (screen.css)
 * sitewide. No rule change, purely a visibility/version-control fix - once this ships,
 * clear the pp_custom_css option value in wp-admin so there's one source of truth.
 */
.icon-scroll {
	display: none !important;
}

/*
 * Standard accessible visually-hidden pattern (clip to a 1px box rather than
 * display:none/visibility:hidden, so screen readers still announce the
 * content - display:none removes it from the accessibility tree entirely).
 * First use: the fallback <h1> on pages with the visible title banner turned
 * off (page_show_title postmeta) - see page-contact.php and
 * page-ten-years-later.php. Those pages' only <h1> lived inside the banner
 * markup, so suppressing the banner silently removed the page's sole
 * heading/SEO h1 too (VERIFIED-2026-08-03-mac-round2.md, "5 more pages still
 * have no h1"). No theme-wide .screen-reader-text class already existed to
 * reuse (checked both this theme and the parent).
 */
.pm-visually-hidden {
	position: absolute !important;
	width: 1px !important;
	height: 1px !important;
	padding: 0 !important;
	margin: -1px !important;
	overflow: hidden !important;
	clip: rect(0, 0, 0, 0) !important;
	white-space: nowrap !important;
	border: 0 !important;
}

/*
 * Header + footer social icon hover/focus animation. Both are parent-theme
 * markup (templates/template-socials.php; footer.php's inline .social_wrapper
 * inside .footer_bar_wrapper) with zero transition anywhere in the parent's
 * screen.css - every state change today is an instant opacity snap (footer:
 * .4 -> 1) or, in the header's case, a true no-op (:hover sets opacity:1, but
 * nothing ever dims it below 1 at rest, so there's no visible feedback there
 * at all). Both icon sets are intentionally kept (not consolidated); only
 * their animation needed polish.
 *
 * `#logo_wrapper .social_wrapper ul li a` below is deliberate, not
 * `.above_top_bar .social_wrapper ul li a` (a plausible-looking but wrong
 * guess): the real, currently-live include chain is header.php -> this
 * child theme's own templates/template-topmenu.php (which overrides the
 * parent's copy of the same file - confirmed both exist, child's wins) ->
 * template-socials.php (not overridden by the child, so the parent's copy
 * is what actually renders). .above_top_bar is a separate, sibling block
 * (top contact-info + top nav menu only, and only rendered at all when the
 * tg_topbar Customizer option is set) that fully closes before .top_bar
 * ever opens. template-socials.php's <div class="social_wrapper"> actually
 * renders inside <div id="logo_wrapper">, itself inside .top_bar -
 * confirmed identically in both the parent theme's own
 * templates/template-topmenu.php and this child theme's override. This
 * also matches the parent screen.css's own established
 * `#logo_wrapper .social_wrapper` pattern (screen.css:2970, 3034) - the
 * `.above_top_bar .social_wrapper` rules that pattern doesn't touch are
 * real parent-theme CSS, just unreachable dead weight given how this site's
 * actual templates are wired, not something worth matching. Targeting
 * `.above_top_bar` instead would make the entire header half of this block
 * dead CSS - correct syntax, correct cascade reasoning, matching nothing in
 * the DOM.
 *
 * CSS-only, no template override needed - matches this project's established
 * "enhance via child CSS, don't duplicate a template just to add a class"
 * pattern. The footer selector remains equal-specificity (same compound
 * chain as the parent's own rule), so normal cascade order (child loads
 * after parent) wins there without needing !important; the header selector
 * is ID-anchored, so it wins on specificity alone regardless of cascade
 * order.
 */
.footer_bar_wrapper .social_wrapper ul li a,
#logo_wrapper .social_wrapper ul li a {
	transition: opacity 200ms ease, transform 200ms ease;
}

.footer_bar_wrapper .social_wrapper ul li a:hover,
.footer_bar_wrapper .social_wrapper ul li a:focus-visible,
.footer_bar_wrapper .social_wrapper ul li a:active,
#logo_wrapper .social_wrapper ul li a:hover,
#logo_wrapper .social_wrapper ul li a:focus-visible,
#logo_wrapper .social_wrapper ul li a:active {
	transform: translateY(-2px);
}

/* :focus-visible is deliberate, not just :hover/:active - these are real
 * <a> tags, so keyboard users tabbing through get the same lift feedback
 * mouse/touch users do, same reasoning already applied to the logo hover
 * polish in site-logo.css. */
@media (prefers-reduced-motion: reduce) {
	.footer_bar_wrapper .social_wrapper ul li a,
	#logo_wrapper .social_wrapper ul li a {
		transition: none;
	}
	.footer_bar_wrapper .social_wrapper ul li a:hover,
	.footer_bar_wrapper .social_wrapper ul li a:focus-visible,
	.footer_bar_wrapper .social_wrapper ul li a:active,
	#logo_wrapper .social_wrapper ul li a:hover,
	#logo_wrapper .social_wrapper ul li a:focus-visible,
	#logo_wrapper .social_wrapper ul li a:active {
		transform: none;
	}
}

/*
 * Nav link contrast failure (NEXT-STEPS-2026-08-04.md #1e, group 1): the
 * primary nav's resting-state text color, #848484 against a white nav
 * background, is 3.74:1 - under WCAG AA's 4.5:1 minimum for this text size/
 * weight. Not this project's own CSS at all - it's a Kirki/Customizer value
 * (theme_mods_photome-child -> tg_menu_font_color = #848484), confirmed by
 * walking the real cascade, not just getComputedStyle(). A DB-only value is
 * invisible to git and has already bitten this project once (the Additional
 * CSS field, CASCADE-BUG-2026-08-03.md) - overriding here instead of editing
 * the Customizer field keeps this fix reproducible across environments and
 * visible to code review, matching how custom-content-width and other
 * Kirki-sourced values are already handled elsewhere in this file.
 * !important is necessary, not decorative: Kirki's own rule is high-priority/
 * near-inline, a plain-specificity override would not reliably beat it.
 * #767676 (118,118,118) is the standard "just clears AA" reference gray
 * (4.54:1 on white) - the smallest visible change from today's #848484 that
 * still passes.
 */
#menu_wrapper .nav ul li a,
#menu_wrapper div .nav li > a {
	color: #767676 !important;
}

/*
 * /ten-years-later/ narrative-quote contrast failure (NEXT-STEPS-2026-08-04.md
 * #1e, group 2): the parent theme's sitewide `blockquote { opacity: 0.4; }`
 * (screen.css) dims this page's two pull-quotes to an effective ~#999999
 * against white - under WCAG AA regardless of the blockquote's own inline
 * color (#222222/#000000, genuinely dark - opacity is what fails here, not
 * color, a distinction only axe-core's composited-contrast check caught;
 * plain getComputedStyle(el).color on its own would have wrongly reported a
 * pass). Scoped to a class added directly on content-ten-years-later.php's
 * two <blockquote> elements (the only <blockquote> usage anywhere in either
 * theme - confirmed via grep - so nothing else is affected either way) rather
 * than overriding the parent's bare `blockquote` selector sitewide, which
 * would be an unscoped guess about a rule nothing else currently exercises.
 * 0.7 clears both real constraints on this page with headroom: the 16px
 * spans need opacity >= ~0.54 for 4.5:1, the 26px bold heading needs
 * >= ~0.42 for 3:1.
 */
.ten-years-quote {
	opacity: 0.7;
}

/*
 * Portfolio category filter (js/custom.js's vanilla-JS replacement for the
 * real parent theme's Isotope-based filtering - see that file's own docblock
 * for why Isotope's masonry-positioning code isn't needed here). Items
 * hidden by a category-filter click get this class toggled on instead of an
 * inline style, keeping the "how" (CSS) and "when" (JS) separate. Plain
 * `display: none` is sufficient - #portfolio_filter_wrapper > .element is a
 * plain float/width layout (screen.css/grid.css), so hiding an item lets the
 * remaining ones reflow using the browser's normal float algorithm, no
 * masonry recalculation needed.
 */
.pm-filter-hidden {
	display: none;
}

/*
 * Share-button feedback toast (js/page-share.js, 2026-08-24).
 *
 * The header share icon rendered on every portfolio page but did nothing -
 * the parent theme's click handler was never ported into this fork (the
 * #fullscreen_share_wrapper docblock above documents the same dead feature
 * from the other direction). It now opens the OS share sheet on mobile and
 * copies the URL on desktop; this is the desktop half's confirmation.
 *
 * Anchored to .post_share_wrapper, which screen.css already sets
 * position: relative. Right-aligned rather than centred because the icon
 * sits within ~120px of the viewport's right edge, so a centred toast would
 * overflow the page.
 */
.page-share-toast {
	position: absolute;
	top: calc(100% + 10px);
	right: 0;
	z-index: 200;

	padding: 6px 10px;
	white-space: nowrap;

	font-size: 11px;
	line-height: 1;
	letter-spacing: 0.08em;
	text-transform: uppercase;

	color: #fff;
	background: rgba(28, 25, 23, 0.94);
	border: 1px solid rgba(255, 255, 255, 0.14);

	/*
	 * Hidden by default and never interactive: the element is created once
	 * and reused, so without pointer-events: none an invisible box would sit
	 * over the header swallowing clicks between shares.
	 */
	opacity: 0;
	transform: translateY(-4px);
	pointer-events: none;

	transition: opacity 180ms ease, transform 180ms ease;
}

.page-share-toast.is-visible {
	opacity: 1;
	transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
	.page-share-toast {
		transition: none;
		transform: none;
	}

	.page-share-toast.is-visible {
		transform: none;
	}
}

/*
 * Tap target for the header share button.
 *
 * Measured live at 414x896: the <a> is a 15x19px box - it is just a 18px
 * Font Awesome glyph - which is well under any reasonable touch minimum and
 * was fiddly to hit on a phone even before it did anything.
 *
 * Expanded with a pseudo-element rather than padding so the header's
 * horizontal layout is untouched (padding would shift the logo row). Scoped
 * to coarse pointers because a mouse does not need it, and the expansion is
 * asymmetric - generous vertically, restrained horizontally - so it stops
 * exactly at the 10px margin that separates it from the fullscreen control
 * on fullscreen-style pages rather than overlapping it.
 */
@media (hover: none) and (pointer: coarse) {
	.post_share_wrapper > a {
		position: relative;
	}

	.post_share_wrapper > a::after {
		content: "";
		position: absolute;
		top: -13px;
		bottom: -13px;
		left: -10px;
		right: -10px;
	}

	/*
	 * Same treatment for the mobile menu toggle (2026-08-24). Measured under
	 * real touch emulation at 375x812: the icon is a 25x15px box with no
	 * padding - the PRIMARY navigation control on a phone, well under any
	 * usable touch minimum.
	 *
	 * The expansion is asymmetric on purpose, and the numbers are not
	 * arbitrary. At 375px the share button sits at 289-305 and its own
	 * ::after above already extends its hit area to 315; the toggle starts at
	 * 320. Growing this one leftward by the same 10px would reach 310 and
	 * OVERLAP the share button's hit area, so the wrong control would swallow
	 * taps aimed at the other. Left grows 2px (to 318, clear of 315), right
	 * grows 12px into the 30px of empty margin before the viewport edge.
	 *
	 * Net effect ~39x45 instead of 25x15, with nothing else moved: this is a
	 * pseudo-element, so the header's layout is untouched.
	 */
	#mobile_nav_icon {
		position: relative;
	}

	#mobile_nav_icon::after {
		content: "";
		position: absolute;
		top: -15px;
		bottom: -15px;
		left: -2px;
		right: -12px;
	}
}
