/*
	CalebFrames — custom layer on top of Strata (HTML5 UP).
	Adds: dark/light theming, scroll-reveal animations, theme toggle button,
	gallery grid, and small polish. Template's compiled main.css is untouched.
*/

/* ===========================================================
   1. THEME — dark is the default. Light is applied only when
   html[data-theme="light"] is set. This keeps the original
   template look intact for light mode and layers dark on top.
   =========================================================== */

html[data-theme="dark"] body {
	background: #14181d;
}

/* Body / form text */
html[data-theme="dark"] body,
html[data-theme="dark"] input,
html[data-theme="dark"] select,
html[data-theme="dark"] textarea {
	color: #b7c0cc;
}

/* Headings & emphasis */
html[data-theme="dark"] h1,
html[data-theme="dark"] h2,
html[data-theme="dark"] h3,
html[data-theme="dark"] h4,
html[data-theme="dark"] h5,
html[data-theme="dark"] h6,
html[data-theme="dark"] strong,
html[data-theme="dark"] b,
html[data-theme="dark"] #header h1,
html[data-theme="dark"] #header strong {
	color: #f2f5f8;
}

/* Section dividers, rules, boxes */
html[data-theme="dark"] #main > section {
	border-top-color: rgba(255, 255, 255, 0.09);
}
html[data-theme="dark"] hr {
	border-bottom-color: rgba(255, 255, 255, 0.12);
}
html[data-theme="dark"] .box {
	border-color: rgba(255, 255, 255, 0.12);
}

/* Buttons */
html[data-theme="dark"] input[type="submit"],
html[data-theme="dark"] input[type="reset"],
html[data-theme="dark"] input[type="button"],
html[data-theme="dark"] .button {
	border-color: rgba(255, 255, 255, 0.18);
	color: #e8edf2 !important;
}
html[data-theme="dark"] input[type="submit"]:hover,
html[data-theme="dark"] input[type="reset"]:hover,
html[data-theme="dark"] input[type="button"]:hover,
html[data-theme="dark"] .button:hover {
	border-color: #49bf9d;
	color: #49bf9d !important;
}

/* Form fields */
html[data-theme="dark"] input[type="text"],
html[data-theme="dark"] input[type="email"],
html[data-theme="dark"] input[type="password"],
html[data-theme="dark"] select,
html[data-theme="dark"] textarea {
	background: rgba(255, 255, 255, 0.04);
	border-color: rgba(255, 255, 255, 0.14);
}
html[data-theme="dark"] input[type="text"]:focus,
html[data-theme="dark"] input[type="email"]:focus,
html[data-theme="dark"] select:focus,
html[data-theme="dark"] textarea:focus {
	border-color: #49bf9d;
	box-shadow: 0 0 0 1px #49bf9d;
}
html[data-theme="dark"] ::placeholder {
	color: #7f8b98;
	opacity: 1;
}
html[data-theme="dark"] select option {
	background: #1c2127;
	color: #d7dde4;
}

/* Poptrox lightbox popup */
html[data-theme="dark"] .poptrox-popup,
html[data-theme="dark"] .poptrox-popup .caption {
	background: #1c2127;
	color: #d7dde4;
}

/* ===========================================================
   2. THEME TOGGLE BUTTON
   =========================================================== */
.theme-toggle {
	position: absolute;
	top: 1.25rem;
	right: 1.25rem;
	z-index: 11000;
	width: 2.9rem;
	height: 2.9rem;
	border-radius: 50%;
	border: solid 2px rgba(160, 160, 160, 0.4);
	background: rgba(255, 255, 255, 0.85);
	color: #49bf9d;
	cursor: pointer;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 0;
	backdrop-filter: blur(6px);
	transition: border-color 0.2s ease, background 0.2s ease, box-shadow 0.2s ease, color 0.2s ease;
	-webkit-backdrop-filter: blur(6px);
}
.theme-toggle:hover {
	border-color: #49bf9d;
	color: #3aa88a;
	box-shadow: 0 0 0 3px rgba(73, 191, 157, 0.18);
}
.theme-toggle svg {
	width: 1.3rem;
	height: 1.3rem;
	display: block;
}
html[data-theme="dark"] .theme-toggle {
	background: rgba(28, 33, 39, 0.8);
	border-color: rgba(255, 255, 255, 0.2);
}
/* Show sun in dark mode (click to go light), moon in light mode. */
.theme-toggle .icon-sun { display: none; }
.theme-toggle .icon-moon { display: block; }
html[data-theme="dark"] .theme-toggle .icon-sun { display: block; }
html[data-theme="dark"] .theme-toggle .icon-moon { display: none; }

/* ===========================================================
   3. SCROLL-REVEAL ANIMATIONS
   Hidden state only applies when JS is active (html.js-reveal),
   so content is never stuck invisible if JS fails.
   =========================================================== */
html.js-reveal .reveal {
	opacity: 0;
	transform: translateY(28px);
	transition: opacity 1s cubic-bezier(0.4, 0, 0.2, 1),
	            transform 1s cubic-bezier(0.4, 0, 0.2, 1);
	will-change: opacity, transform;
}
html.js-reveal .reveal.is-visible {
	opacity: 1;
	transform: none;
}
/* Stagger children (e.g. gallery tiles) via inline --reveal-delay. */
html.js-reveal .reveal[style*="--reveal-delay"] {
	transition-delay: var(--reveal-delay);
}

@media (prefers-reduced-motion: reduce) {
	html.js-reveal .reveal {
		opacity: 1 !important;
		transform: none !important;
		transition: none !important;
	}
	.theme-toggle { transition: none; }
}

/* ===========================================================
   4. GALLERY GRID (placeholder-ready)
   =========================================================== */
/* Fluid column count driven by a minimum tile width — no fixed
   breakpoints to keep in sync. auto-fit collapses unused tracks so a
   single item (e.g. one video) fills the row instead of being squeezed
   into a narrow column beside empty space. */
.gallery-grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(255px, 1fr));
	gap: 1.25em;
	margin: 0 0 2em 0;
}

.gallery-grid .work-item { margin: 0; }
/* Cap how wide a tile can grow, but only when it's alone in the grid
   (nothing else to share the row with) — otherwise it stretches to
   fill the entire container, ending up bigger than its own lightbox.
   With 2+ items this must NOT apply: capping every tile while their
   grid tracks (1fr) keep growing past that cap leaves a gap after each
   capped tile instead of letting them grow to fill the row — visible
   as growing gaps between photos, and an uneven-looking right margin
   on the last column, at wide viewports. */
.gallery-grid:not(:has(.work-item + .work-item)) .work-item {
	max-width: 400px;
}
.gallery-grid .work-item .thumb {
	display: block;
	border-radius: 0.35em;
	overflow: hidden;
	aspect-ratio: 4 / 3;
	border-bottom: none;
}
/* Video thumbnails are 16:9 — match the tile to that ratio so nothing
   gets cropped (cutting off thumbnail text) or letterboxed. */
.gallery-grid .work-item.video-tile .thumb {
	aspect-ratio: 16 / 9;
	/* Photo thumbs pick up a 24px bottom margin from Strata's own
	   ".work-item .image" rule (they carry the "image" class); video
	   thumbs don't use that class (it'd also bring a "View" hover
	   overlay that clashes with the custom play button), so match the
	   spacing by hand instead. */
	margin-bottom: 1.5em;
}
.gallery-grid .work-item .thumb img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}
/* Strata's "View" hover state stacks its noise-texture overlay twice at
   full opacity to darken the image for text legibility — looks quite
   grainy. A single layer at a lower opacity still darkens enough to
   keep "View" readable, without the harsh texture. */
.gallery-grid .work-item .image.thumb:hover:before {
	background: url("images/overlay.png");
	opacity: 0.65;
}
.gallery-grid .work-item h3 {
	font-size: 0.9em;
	margin: 0.75em 0 0 0;
	letter-spacing: 0.1em;
	text-transform: uppercase;
}

/* Empty placeholder tile (no real photo yet) */
.gallery-grid .placeholder-tile {
	display: flex;
	align-items: center;
	justify-content: center;
	text-align: center;
	aspect-ratio: 4 / 3;
	border-radius: 0.35em;
	border: dashed 2px rgba(130, 130, 130, 0.4);
	color: #9aa2ab;
	font-size: 0.8em;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	padding: 1em;
}

/* Video tile play badge */
.gallery-grid .video-item { position: relative; }
.gallery-grid .video-item::after {
	content: "";
	position: absolute;
	top: 50%;
	left: 50%;
	width: 4rem;
	height: 4rem;
	transform: translate(-50%, -50%);
	border-radius: 50%;
	background: rgba(0, 0, 0, 0.6);
	border: solid 3px rgba(255, 255, 255, 0.95);
	box-shadow: 0 2px 12px rgba(0, 0, 0, 0.4);
	z-index: 2;
	pointer-events: none;
	transition: background 0.25s ease;
}
.gallery-grid .video-item::before {
	content: "";
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-35%, -50%);
	border-style: solid;
	border-width: 0.6rem 0 0.6rem 1rem;
	border-color: transparent transparent transparent #fff;
	z-index: 3;
	pointer-events: none;
}
.gallery-grid .video-item:hover::after { background: #49bf9d; }

/* ===========================================================
   5. GALLERY PAGE LAYOUT (make it consistent with the site)
   =========================================================== */
.gallery-page #gallery-wrapper {
	width: 100%;
	max-width: min(90%, 2000px);
	margin: 0 auto;
	padding: 2.5em 2em 3em 2em;
}

/* Sticky footer: keeps the footer pinned to the bottom of the viewport
   on short-content pages instead of floating right after the grid with
   a big empty gap below it. */
html, body {
	height: 100%;
}
.gallery-page {
	display: flex;
	flex-direction: column;
	min-height: 100vh;
}
.gallery-page #gallery-wrapper {
	flex: 1;
}
.gallery-topbar {
	width: 100%;
	max-width: min(90%, 2000px);
	margin: 0 auto;
	padding: 1.5em 2em;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 0.75em 1em;
	border-bottom: solid 1px rgba(130, 130, 130, 0.25);
}
.gallery-topbar .brand {
	font-weight: 700;
	letter-spacing: 0.15em;
	text-transform: uppercase;
	font-size: 1.05em;
	color: #787878;
	white-space: nowrap;
}
html[data-theme="dark"] .gallery-topbar .brand { color: #f2f5f8; }
html[data-theme="dark"] .gallery-topbar { border-bottom-color: rgba(255, 255, 255, 0.1); }

/* Button + toggle live together in normal flex flow (not the toggle's
   usual fixed positioning) so their gap is always automatic and they
   can never overlap, at any screen width — no breakpoint guesswork. */
.gallery-topbar-actions {
	display: flex;
	align-items: center;
	gap: 0.75em;
	flex-shrink: 0;
}
.gallery-topbar-actions .theme-toggle {
	position: static;
	top: auto;
	right: auto;
}

/* Small screens: stack "Caleb Frames" above the Back/toggle group and
   center both instead of the default left-brand/right-actions row,
   which gets cramped once things wrap. */
@media (max-width: 600px) {
	.gallery-topbar {
		flex-direction: column;
		justify-content: center;
	}
}

/* Gallery footer: reuse the header sidebar's photo + overlay so it feels unified.
   Paths are relative to THIS stylesheet (assets/css/), matching main.css. */
.gallery-page #footer {
	margin-top: 3em;
	/* Strata only gives #footer padding inside a couple of specific
	   breakpoints, because it normally expects the footer to sit inside
	   the already-padded #header sidebar. This page has no sidebar, so
	   the footer needs its own padding at every width, not just some —
	   set unconditionally here rather than relying on those breakpoints. */
	padding: 3em 2em;
	background-color: #1f1815;
	background-image: url("images/overlay.png"), url("../../images/bg.jpg");
	background-position: top left, center bottom;
	background-repeat: repeat, no-repeat;
	background-size: auto, cover;
	background-attachment: scroll, scroll;
	border-top: solid 1px rgba(255, 255, 255, 0.08);
}
/* On the home page, this content is centered by sitting inside the
   #header sidebar. The gallery page's footer stands alone with no such
   container, so it needs its own centering — otherwise everything just
   hugs the left edge of the full-width bar. */
.gallery-page #footer .inner {
	/* No padding here — #footer itself already carries Strata's own
	   padding (main.css). Adding more here was stacking on top of it,
	   making the gallery footer taller (and a differently-cropped
	   background photo) than the home page's footer. */
	max-width: min(90%, 2000px);
	margin: 0 auto;
	text-align: center;
}
.gallery-page #footer .icons {
	display: flex;
	justify-content: center;
	/* Strata gives .icons a top margin and .copyright a bottom margin
	   (both expected to add spacing against neighboring content). Here
	   they're the first/last things in the footer, so those margins
	   just add lopsided extra space beyond the footer's own symmetric
	   padding — zero both out below and let the padding alone govern
	   top/bottom spacing. */
	margin-top: 0;
}
.gallery-page #footer .copyright {
	margin-bottom: 0;
}

/* ===========================================================
   6. CONTACT FORM STATUS MESSAGE
   =========================================================== */
/* Match the button's spacing above (from the message box) and below
   (to the status message) so the whole form has consistent rhythm.
   margin-bottom: 0 also prevents this row's margin from collapsing
   with .form-status's margin-top (would win out over ours since
   collapsed sibling margins take the larger value, not the sum). */
#contact-form ul.actions {
	margin-top: 20px;
	margin-bottom: 0;
}
/* Strata's own grid gutter system spaces wrapped rows (Name/Email row
   to Message box) at 1.25em (~27px) by default — override to 20px so
   every gap in the form matches the same rhythm. The negative margin
   on the row and the positive padding on its children have to change
   together (that's how the template's gutter trick works: the margin
   cancels the first row's padding, so only gaps *between* rows show). */
#contact-form .row.gtr-50.gtr-uniform {
	margin-top: -20px;
}
#contact-form .row.gtr-50.gtr-uniform > * {
	padding-top: 20px;
}
.form-status {
	margin: 0;
	font-size: 0.9em;
}
.form-status:empty { margin: 0; }
.form-status.is-success,
.form-status.is-error {
	display: flex;
	align-items: center;
	gap: 0.6em;
	margin-top: 20px; /* matches the row gap between the message box and Send button */
	padding: 0.85em 1.1em;
	border-radius: 0.5em;
	border: solid 1px;
	animation: form-status-in 0.25s ease;
}
.form-status.is-success::before,
.form-status.is-error::before {
	flex-shrink: 0;
	width: 1.3em;
	height: 1.3em;
	border-radius: 50%;
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 0.8em;
	font-weight: 700;
	line-height: 1;
}
.form-status.is-success {
	color: #2f9973;
	background: rgba(73, 191, 157, 0.1);
	border-color: rgba(73, 191, 157, 0.35);
}
.form-status.is-success::before {
	content: "\2713";
	background: #49bf9d;
	color: #fff;
}
.form-status.is-error {
	color: #c9504f;
	background: rgba(228, 107, 107, 0.1);
	border-color: rgba(228, 107, 107, 0.35);
}
.form-status.is-error::before {
	content: "!";
	background: #e46b6b;
	color: #fff;
}
html[data-theme="dark"] .form-status.is-success { color: #7fe0bf; }
html[data-theme="dark"] .form-status.is-error { color: #f0a3a3; }

@keyframes form-status-in {
	from { opacity: 0; transform: translateY(-4px); }
	to { opacity: 1; transform: translateY(0); }
}

/* ===========================================================
   7. LIGHTBOX ICONS — real inline <svg> elements (injected by
   custom.js / video-lightbox.js), not CSS background-images.
   A background-image SVG sized in fractional em units can render
   with sub-pixel blur/ghosting on some browsers' rasterizers
   (varies by OS/zoom) — an actual DOM <svg> avoids that entirely,
   same as the theme-toggle icons which never had this problem.
   =========================================================== */
.poptrox-popup .closer {
	display: flex;
	align-items: center;
	justify-content: center;
	top: 10px;
	right: 10px;
	width: 2.15em;
	height: 2.15em;
	line-height: normal;
	border-radius: 50%;
	border: solid 2px rgba(255, 255, 255, 0.6);
	background: rgba(0, 0, 0, 0.25);
}
.poptrox-popup .closer:before { content: none; }
.poptrox-popup .closer svg {
	width: 16px;
	height: 16px;
	display: block;
	color: #fff;
	pointer-events: none;
	shape-rendering: geometricPrecision;
}

.poptrox-popup .nav-next:before,
.poptrox-popup .nav-previous:before { content: none; }
.poptrox-popup .nav-next,
.poptrox-popup .nav-previous {
	display: flex;
	align-items: center;
}
.poptrox-popup .nav-next { justify-content: flex-end; }
.poptrox-popup .nav-previous { justify-content: flex-start; }
.poptrox-popup .nav-next svg,
.poptrox-popup .nav-previous svg {
	width: 20px;
	height: 20px;
	margin: 0 0.4em;
	display: block;
	color: #fff;
	pointer-events: none;
	shape-rendering: geometricPrecision;
}

/* Video lightbox close button (assets/js/video-lightbox.js) — same
   circular-badge treatment as the photo lightbox, positioned flush
   against the video box's own corner (not the full-screen overlay). */
.video-lightbox-close {
	-webkit-appearance: none;
	appearance: none;
	box-sizing: border-box;
	/* Fixed to the viewport's top-right corner (same slot as the theme
	   toggle, which it sits above while the video is open) — clear of
	   the video frame entirely, so it never collides with YouTube's own
	   player controls. */
	position: fixed;
	top: 1.25rem;
	right: 1.25rem;
	margin: 0;
	padding: 0;
	width: 2.9rem;
	height: 2.9rem;
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: 50%;
	border: solid 2px rgba(255, 255, 255, 0.6);
	background: rgba(0, 0, 0, 0.45);
	cursor: pointer;
	z-index: 2;
	opacity: 0.9;
	transition: opacity 0.2s ease, border-color 0.2s ease;
	/* Neutralize Firefox/Chrome default button active/focus treatment
	   (inset shadow, shifted padding) so the icon never appears to move. */
	outline: none;
	-moz-user-select: none;
}
.video-lightbox-close::-moz-focus-inner {
	border: 0;
	padding: 0;
}
.video-lightbox-close:active {
	transform: none;
}
.video-lightbox-close svg {
	width: 16px;
	height: 16px;
	display: block;
	color: #fff;
	pointer-events: none;
	shape-rendering: geometricPrecision;
}
.video-lightbox-close:hover {
	opacity: 1;
	border-color: #49bf9d;
}
.video-lightbox-close:focus-visible {
	border-color: #49bf9d;
}

/* ===========================================================
   8. GALLERY FILTER TABS (All / Photos / Videos)
   =========================================================== */
.gallery-filter-bar {
	display: flex;
	gap: 0.6em;
	margin: 0 0 2em 0;
	flex-wrap: wrap;
}
.gallery-filter-bar button {
	appearance: none;
	-webkit-appearance: none;
	background: transparent;
	border: solid 2px rgba(130, 130, 130, 0.35);
	border-radius: 999px;
	color: #787878;
	cursor: pointer;
	font-size: 0.8em;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	padding: 0.55em 1.3em;
	transition: color 0.2s ease, border-color 0.2s ease, background 0.2s ease;
}
.gallery-filter-bar button:hover {
	color: #49bf9d;
	border-color: #49bf9d;
}
.gallery-filter-bar button.active {
	background: #49bf9d;
	border-color: #49bf9d;
	color: #0d1a15;
}
html[data-theme="dark"] .gallery-filter-bar button {
	color: #b7c0cc;
	border-color: rgba(255, 255, 255, 0.2);
}
html[data-theme="dark"] .gallery-filter-bar button.active {
	color: #0d1a15;
}

/* ===========================================================
   9. PHOTO GRID
   Previously used CSS multi-column "masonry" so mixed-aspect-ratio
   photos could keep their natural shape. That technique doesn't
   reliably fill the row once item count doesn't line up with the
   column-width's computed column count — with e.g. 4 photos, the
   browser could still reserve 6 column tracks, leaving the last two
   empty and the row visibly not full width. CSS Grid's auto-fit
   doesn't have that failure mode (same mechanism already used for the
   video grid, including correctly handling a single lone item), so
   the photo grid now uses it too — trading true masonry staggering
   for tiles that reliably fill every row, at any item count. Tiles
   crop to the shared 4:3 aspect ratio (.gallery-grid .work-item .thumb).
   =========================================================== */
.gallery-grid.masonry {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(255px, 1fr));
	gap: 1.25em;
}

/* ===========================================================
   10. HOME PAGE FOOTER ON MOBILE
   Below 736px, main.css detaches the footer from the sidebar and
   gives it standalone padding (2.25em 1.5em) — noticeably shorter and
   less evenly spaced (its icons/copyright margins are asymmetric) than
   the gallery page's standalone footer. Match that here so the two
   pages' footers feel consistent on mobile. Only `#footer` (not
   `.gallery-page #footer`) so this doesn't affect the gallery page,
   which already governs itself with a more specific selector, or the
   home page on desktop, where the footer sits inside the sidebar.
   =========================================================== */
@media (max-width: 736px) {
	#footer {
		padding: 3em 2em;
	}
	#footer .icons {
		margin-top: 0;
	}
	#footer .copyright {
		margin-bottom: 0;
	}
}
