/* ===== ABJ Portfolio — Professional Theme ===== */
/* Smooth, responsive, Apple-inspired UI with fun details */

/* ===== Preloader ===== */
#preloader {
	position: fixed;
	inset: 0;
	z-index: 99999;
	background: #05060a;
	display: flex;
	align-items: center;
	justify-content: center;
	transition: opacity 0.5s ease, visibility 0.5s ease;
}

#preloader.loaded {
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
}

.preloader-inner {
	text-align: center;
}

.preloader-spinner {
	width: 40px;
	height: 40px;
	border: 3px solid rgba(90, 120, 145, 0.15);
	border-top-color: #5a7891;
	border-radius: 50%;
	animation: spin 0.8s linear infinite;
	margin: 0 auto 1.2rem;
}

@keyframes spin {
	to { transform: rotate(360deg); }
}

.preloader-text {
	font-family: "Montserrat", sans-serif;
	font-size: 1.4rem;
	font-weight: 700;
	letter-spacing: 0.15em;
	color: rgba(255, 255, 255, 0.7);
	text-transform: uppercase;
}

/* Reveal-on-load — opacity only, NEVER blocks pointer events.
   Earlier the gate also set `pointer-events: none` which meant a single
   hung fetch could leave the entire page unclickable until the 10-second
   safety net fired. The preloader spinner lives at z-index 99999 and stays
   on top until removed, so visually the gating below is purely cosmetic. */
body:not(.ready) {
	overflow: hidden;
	height: 100vh;
}

body:not(.ready) main,
body:not(.ready) #mainNav {
	opacity: 0;
}

body.ready main,
body.ready #mainNav {
	opacity: 1;
	transition: opacity 0.6s ease 0.15s;
}

/* Hard guarantee: nothing on the page-ready gate can disable input on
   <main> or the navbar. Decorative pseudo-elements that genuinely need
   pointer-events: none keep their own rules — those override this one
   because their selectors are more specific. */
main, #mainNav {
	pointer-events: auto !important;
}

html {
	scroll-behavior: smooth;
}

:root {
	--primary: #5a7891;
	--secondary: #05060a;
	--accent: #7a1a22;
	--dark: #08090d;
	/* Body — Lato for long-form reading. */
	--font-family-sans-serif: "Lato", -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
	/* Display — Inter as the new heading face. Apple/Linear/Stripe
	   vocabulary. Falls back to system display fonts. Old Montserrat var
	   kept available via `--font-family-mono-display` for tracked-caps
	   contrast use (kbd, eyebrows, the press strip). */
	--font-family-heading: "Inter", -apple-system, BlinkMacSystemFont, "SF Pro Display", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
	--font-family-mono-display: "Montserrat", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}

body {
	font-family: var(--font-family-sans-serif);
	background-color: #08090d;
	color: #cfd2d6;
}

a {
	color: var(--primary);
}

a:hover {
	color: #b59760;       /* hover lifts to oxidized brass — readable on dark */
}

h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
	font-family: var(--font-family-heading);
	font-weight: 700;
}

/* ===== Selection Color ===== */
::selection {
	background: var(--primary);
	color: #fff;
}

/* ===== Animations ===== */

@keyframes float {
	0%, 100% { transform: translateY(0); }
	50% { transform: translateY(-12px); }
}

@keyframes glow {
	0%, 100% { box-shadow: 0 0 20px rgba(90, 120, 145, 0.3); }
	50% { box-shadow: 0 0 50px rgba(90, 120, 145, 0.7), 0 0 80px rgba(90, 120, 145, 0.2); }
}

@keyframes shimmer {
	0% { background-position: -200% 0; }
	100% { background-position: 200% 0; }
}

@keyframes orb-float-1 {
	0%, 100% { transform: translate(0, 0) scale(1); }
	33% { transform: translate(80px, -60px) scale(1.1); }
	66% { transform: translate(-40px, 40px) scale(0.9); }
}

@keyframes orb-float-2 {
	0%, 100% { transform: translate(0, 0) scale(1); }
	33% { transform: translate(-60px, 50px) scale(0.9); }
	66% { transform: translate(50px, -80px) scale(1.15); }
}

@keyframes orb-float-3 {
	0%, 100% { transform: translate(0, 0) scale(1); }
	33% { transform: translate(50px, 60px) scale(1.05); }
	66% { transform: translate(-70px, -40px) scale(0.95); }
}

/* ===== Page Sections ===== */

.page-section {
	padding: 4.25rem 0;
	position: relative;
}

@media (min-width: 992px) {
	.page-section {
		padding: 5.25rem 0;
	}
}

.page-section .page-section-heading {
	font-size: 2rem;
	line-height: 2.2rem;
	letter-spacing: 0.06em;
	font-weight: 600;
}

@media (min-width: 992px) {
	.page-section .page-section-heading {
		font-size: 2.6rem;
		line-height: 2.8rem;
	}
}

/* ===== Section Scroll Offsets ===== */

#experience,
#education,
#skills,
#portfolio,
#codeStats,
#beyond {
	scroll-margin-top: 80px;
}

/* ===== Section Backgrounds — aurora gradients ===== */

#education,
#skills,
#portfolio,
#codeStats,
#beyond {
	position: relative;
	overflow: hidden;
}

#education > .container,
#skills > .container,
#portfolio > .container,
#codeStats > .container,
#beyond > .container {
	position: relative;
	z-index: 2;
}

:root {
	--aurora-hue: 0deg;
}

#education::before, #education::after,
#skills::before,
#portfolio::before, #portfolio::after,
#codeStats::before, #codeStats::after,
#beyond::before, #beyond::after {
	content: '';
	position: absolute;
	border-radius: 50%;
	filter: blur(100px) hue-rotate(var(--aurora-hue));
	pointer-events: none;
	transition: filter 0.3s ease;
}

#education {
	background: linear-gradient(160deg, #04050a 0%, #080a12 30%, #091018 60%, #040608 100%);
}
#education::before {
	width: 450px; height: 450px;
	background: radial-gradient(circle, rgba(90, 120, 145, 0.3), rgba(80, 96, 122, 0.15), transparent 70%);
	top: 15%; right: -5%;
	animation: orb-float-2 16s ease-in-out infinite;
	opacity: 0.35;
}
#education::after {
	width: 350px; height: 350px;
	background: radial-gradient(circle, rgba(122, 26, 34, 0.25), transparent 70%);
	bottom: 10%; left: -3%;
	animation: orb-float-1 20s ease-in-out infinite;
	opacity: 0.3;
}

#skills {
	background: linear-gradient(150deg, #070810 0%, #0a0c14 40%, #080a10 70%, #06070d 100%);
}
#skills::before {
	width: 400px; height: 400px;
	background: radial-gradient(circle, rgba(122, 26, 34, 0.3), rgba(90, 120, 145, 0.15), transparent 70%);
	top: 20%; left: -8%;
	animation: orb-float-3 18s ease-in-out infinite;
	opacity: 0.3;
}

#portfolio {
	background: linear-gradient(145deg, #040508 0%, #070912 35%, #06080e 65%, #030406 100%);
}
#portfolio::before {
	width: 500px; height: 500px;
	background: radial-gradient(circle, rgba(90, 120, 145, 0.25), rgba(60, 78, 92, 0.1), transparent 70%);
	top: 5%; left: -6%;
	animation: orb-float-1 15s ease-in-out infinite;
	opacity: 0.35;
}
#portfolio::after {
	width: 400px; height: 400px;
	background: radial-gradient(circle, rgba(154, 122, 62, 0.2), rgba(122, 26, 34, 0.1), transparent 70%);
	bottom: 8%; right: -5%;
	animation: orb-float-2 22s ease-in-out infinite;
	opacity: 0.3;
}

#codeStats {
	background: linear-gradient(160deg, #050608 0%, #080b12 25%, #070910 50%, #06080d 75%, #04060a 100%);
}
#codeStats::before {
	width: 500px; height: 500px;
	background: radial-gradient(circle, rgba(90, 120, 145, 0.3), rgba(110, 140, 168, 0.1), transparent 70%);
	top: 5%; left: -6%;
	animation: orb-float-1 16s ease-in-out infinite;
	opacity: 0.35;
}
#codeStats::after {
	width: 450px; height: 450px;
	background: radial-gradient(circle, rgba(154, 122, 62, 0.2), rgba(122, 26, 34, 0.1), transparent 70%);
	bottom: 8%; right: -5%;
	animation: orb-float-3 21s ease-in-out infinite;
	opacity: 0.3;
}

#beyond {
	background: linear-gradient(155deg, #06070c 0%, #0a0c14 30%, #080910 55%, #050608 100%);
}
#beyond::before {
	width: 500px; height: 500px;
	background: radial-gradient(circle, rgba(122, 26, 34, 0.3), rgba(154, 122, 62, 0.12), transparent 70%);
	top: 8%; left: -5%;
	animation: orb-float-1 17s ease-in-out infinite;
	opacity: 0.35;
}
#beyond::after {
	width: 400px; height: 400px;
	background: radial-gradient(circle, rgba(90, 120, 145, 0.25), rgba(60, 78, 92, 0.1), transparent 70%);
	bottom: 10%; right: -6%;
	animation: orb-float-3 21s ease-in-out infinite;
	opacity: 0.3;
}

/* ===== Dividers ===== */

.divider-custom {
	margin: 1.5rem 0 2.75rem;
	width: 100%;
	display: flex;
	justify-content: center;
	align-items: center;
}

.divider-custom .divider-custom-line {
	width: 100%;
	max-width: 5rem;
	height: 1px;
	background-color: rgba(10, 10, 35, 0.35);
	border-radius: 0;
}

.divider-custom .divider-custom-line:first-child {
	margin-right: 1rem;
}

.divider-custom .divider-custom-line:last-child {
	margin-left: 1rem;
}

.divider-custom .divider-custom-icon {
	color: rgba(10, 10, 35, 0.5);
	font-size: 1.1rem;
}

.divider-custom.divider-light .divider-custom-line {
	background-color: rgba(255, 255, 255, 0.18);
}

.divider-custom.divider-light .divider-custom-icon {
	color: rgba(255, 255, 255, 0.5) !important;
}

/* ===== Bootstrap Color Overrides ===== */

.bg-primary {
	background-color: var(--primary) !important;
}

.bg-secondary {
	background-color: var(--secondary) !important;
}

.text-primary {
	color: var(--primary) !important;
}

a.text-primary:hover,
a.text-primary:focus {
	color: #3d5a72 !important;
}

.text-secondary {
	color: var(--secondary) !important;
}

a.text-secondary:hover,
a.text-secondary:focus {
	color: #cfd2d6 !important;
}

.btn-primary {
	color: #fff;
	background-color: var(--primary);
	border-color: var(--primary);
}

.btn-primary:hover {
	color: #fff;
	background-color: #3d5a72;
	border-color: #3d5a72;
}

.btn-primary:focus,
.btn-primary.focus {
	color: #fff;
	background-color: #3d5a72;
	border-color: #3d5a72;
	box-shadow: 0 0 0 0.2rem rgba(90, 120, 145, 0.5);
}

.btn-primary:not(:disabled):not(.disabled):active,
.btn-primary:not(:disabled):not(.disabled).active,
.show > .btn-primary.dropdown-toggle {
	color: #fff;
	background-color: #3d5a72;
	border-color: #3d5a72;
}

.btn-outline-light {
	color: #f8f9fa;
	border-color: #f8f9fa;
}

.btn-outline-light:hover {
	color: #04060a;
	background-color: #f8f9fa;
	border-color: #f8f9fa;
}

/* ===== Buttons ===== */

.btn-xl {
	padding: 1rem 1.75rem;
	font-size: 1.25rem;
	border-radius: 50px;
}

.btn-social {
	border-radius: 100%;
	display: inline-flex;
	width: 3.25rem;
	height: 3.25rem;
	font-size: 1.25rem;
	justify-content: center;
	align-items: center;
	transition: transform 0.3s ease, box-shadow 0.3s ease;
}

.btn-social:hover {
	transform: translateY(-3px);
	box-shadow: 0 4px 15px rgba(90, 120, 145, 0.4);
}

/* ===== Scroll Progress FAB ===== */

.scroll-fab {
	position: fixed;
	right: 1.2rem;
	bottom: 1.2rem;
	width: 48px;
	height: 48px;
	border-radius: 50%;
	background: rgba(10, 10, 35, 0.6);
	backdrop-filter: saturate(180%) blur(12px);
	-webkit-backdrop-filter: saturate(180%) blur(12px);
	border: 1px solid rgba(255, 255, 255, 0.08);
	box-shadow: 0 4px 20px rgba(0, 0, 0, 0.35);
	color: #fff;
	padding: 0;
	cursor: pointer;
	z-index: 1042;
	opacity: 0;
	transform: translateY(12px) scale(0.9);
	pointer-events: none;
	transition: opacity 0.3s ease, transform 0.3s ease, background 0.3s ease;
}

.scroll-fab.visible {
	opacity: 1;
	transform: translateY(0) scale(1);
	pointer-events: auto;
}

.scroll-fab:hover {
	background: rgba(10, 10, 35, 0.85);
	border-color: rgba(90, 120, 145, 0.5);
}

.scroll-fab-ring {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	transform: rotate(-90deg);
	pointer-events: none;
}

.scroll-fab-track {
	fill: none;
	stroke: rgba(255, 255, 255, 0.08);
	stroke-width: 2.5;
}

.scroll-fab-progress {
	fill: none;
	stroke: var(--primary);
	stroke-width: 2.5;
	stroke-linecap: round;
	stroke-dasharray: 131.95; /* 2 * π * 21 */
	stroke-dashoffset: 131.95;
	transition: stroke-dashoffset 0.15s linear;
}

.scroll-fab-icon {
	position: relative;
	z-index: 1;
	font-size: 0.9rem;
	transition: transform 0.35s cubic-bezier(0.16, 1, 0.3, 1);
	display: inline-block;
}

.scroll-fab.flip .scroll-fab-icon {
	transform: rotate(180deg);
}

/* ===== Navbar ===== */

#mainNav {
	/* iOS notch/Dynamic-Island handling: pull the navbar UP so its top edge
	   sits at the absolute top of the screen (covering the status-bar safe
	   area), then push the inner content back down with padding equal to
	   the safe-area inset. Negative `top` is required because Bootstrap's
	   `.fixed-top` sets `top: 0` which (in `viewport-fit=cover` rendering
	   on iOS) actually positions the navbar at the top of the page area,
	   leaving the safe area exposed above it.

	   Doing both — `top: 0` AND `padding-top: env(safe-area-inset-top)` —
	   is the combination Apple's HIG recommends for fixed headers in
	   web content that opted into edge-to-edge with `viewport-fit=cover`. */
	padding-top: calc(1rem + env(safe-area-inset-top, 0px));
	padding-bottom: 1rem;
	padding-left: env(safe-area-inset-left, 0px);
	padding-right: env(safe-area-inset-right, 0px);
	font-family: var(--font-family-heading);
	font-weight: 700;
	background-color: rgba(10, 10, 35, 0.55);
	backdrop-filter: saturate(180%) blur(20px);
	-webkit-backdrop-filter: saturate(180%) blur(20px);
	box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05), 0 4px 20px rgba(0, 0, 0, 0.25);
	border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}

/* Failsafe — paint a solid bar across the safe-area region above the
   navbar even on browsers/configurations where `padding-top:
   env(safe-area-inset-top)` doesn't visibly extend the navbar's own
   surface (e.g. when scroll has not yet kicked in and the status-bar
   region is still showing the body background through the fixed nav).

   This `::before` pseudo-element lives at the SAME position-fixed layer
   as the navbar, painted directly on top of the safe-area cutout.
   Pointer-events disabled so it never intercepts taps. */
#mainNav::before {
	content: "";
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	height: env(safe-area-inset-top, 0px);
	background-color: rgba(10, 10, 35, 0.95);
	-webkit-backdrop-filter: saturate(180%) blur(20px);
	backdrop-filter: saturate(180%) blur(20px);
	z-index: 1031;       /* one above Bootstrap's .fixed-top (1030) */
	pointer-events: none;
}

/* Belt-and-braces: also paint an opaque safe-area cap at the body level.
   On some iOS versions the navbar's pseudo-element renders below the
   status-bar overlay region; a `body::after` painted at z-index 10001
   (above body::before vignette at 9999, below the lightbox at 100000)
   guarantees the cap shows. Hidden when there's no notch. */
html::after {
	content: "";
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	height: env(safe-area-inset-top, 0px);
	background: #0a0a23;
	z-index: 10001;
	pointer-events: none;
}

#mainNav .navbar-brand {
	color: #fff;
	font-size: 1.4em;
}

#mainNav .navbar-nav {
	margin-top: 1rem;
}

#mainNav .navbar-nav li.nav-item a.nav-link {
	color: rgba(255, 255, 255, 0.7);
	font-size: 0.7rem;
	font-weight: 500;
	letter-spacing: 0.14em;
	padding: 0.5rem 1rem !important;
	transition: color 0.3s ease;
}

#mainNav .navbar-nav li.nav-item a.nav-link:hover {
	color: var(--primary);
}

#mainNav .navbar-nav li.nav-item a.nav-link:active,
#mainNav .navbar-nav li.nav-item a.nav-link:focus {
	color: #fff;
}

#mainNav .navbar-nav li.nav-item a.nav-link.active {
	color: var(--primary);
}

/* Blog link — accented so it reads as a destination, not a section. */
#mainNav .navbar-nav li.nav-item a.nav-link--blog {
	color: var(--primary) !important;
	font-weight: 600;
}

#mainNav .navbar-nav li.nav-item a.nav-link--blog:hover {
	color: #fff !important;
}

#mainNav .navbar-toggler {
	font-size: 80%;
	padding: 0.8rem;
	border-color: rgba(255, 255, 255, 0.3);
}

@media (min-width: 992px) {
	#mainNav {
		padding-top: calc(1.2rem + env(safe-area-inset-top, 0px));
		padding-bottom: 1.2rem;
		transition: padding-top 0.3s, padding-bottom 0.3s;
	}
	#mainNav .navbar-brand {
		font-size: 1.5em;
		transition: font-size 0.3s;
	}
	#mainNav .navbar-nav {
		margin-top: 0;
	}
	#mainNav .navbar-nav > li.nav-item > a.nav-link.active {
		color: var(--primary);
		background: transparent;
	}
	#mainNav .navbar-nav > li.nav-item > a.nav-link.active:active,
	#mainNav .navbar-nav > li.nav-item > a.nav-link.active:focus,
	#mainNav .navbar-nav > li.nav-item > a.nav-link.active:hover {
		color: var(--primary);
		background: transparent;
	}
	#mainNav.navbar-shrink {
		padding-top: calc(0.5rem + env(safe-area-inset-top, 0px));
		padding-bottom: 0.5rem;
	}
	#mainNav.navbar-shrink .navbar-brand {
		font-size: 1.3em;
	}
}

/* ===== Masthead / Hero ===== */

.masthead {
	/* The mobile navbar now reserves space for the iOS status-bar safe area
	   (env(safe-area-inset-top)). Add the same allowance to the hero's top
	   padding so the avatar doesn't tuck under the taller fixed nav. */
	padding-top: calc(4rem + 74px + env(safe-area-inset-top, 0px));
	padding-bottom: 3rem;
	background: linear-gradient(135deg, #05060a 0%, #0a0c14 40%, #080a10 100%);
	position: relative;
}

/* Parallax layer behind hero */
.masthead > .container {
	position: relative;
	z-index: 2;
}

.masthead-content {
	will-change: opacity, transform;
	transform-origin: center top;
}

.masthead::before {
	content: '';
	position: absolute;
	inset: 0;
	background: radial-gradient(circle at 30% 50%, rgba(90, 120, 145, 0.08) 0%, transparent 50%),
	            radial-gradient(circle at 70% 80%, rgba(154, 122, 62, 0.06) 0%, transparent 50%);
	animation: float 8s ease-in-out infinite;
	pointer-events: none;
}

.masthead .masthead-heading {
	font-size: 1.9rem;
	line-height: 2.2rem;
	letter-spacing: 0.08em;
	font-weight: 600;
}

.masthead .masthead-subheading {
	font-size: 1.05rem;
	opacity: 0.82;
	letter-spacing: 0.02em;
}

.hero-rotating {
	min-height: 1.4em;
	line-height: 1.4;
	display: flex;
	align-items: center;
	justify-content: center;
	transition: opacity 0.4s ease;
}

.hero-rotating.fade-out {
	opacity: 0;
}

.masthead .masthead-avatar {
	width: min(250px, 45vw);
	height: min(250px, 45vw);
	border-radius: 50%;
	border: 4px solid rgba(90, 120, 145, 0.5);
	animation: glow 3s ease-in-out infinite;
	object-fit: cover;
	object-position: center 25%;
	transition: transform 0.4s ease;
	flex-shrink: 0;
}

.masthead .masthead-avatar:hover {
	transform: scale(1.04);
}

@media (min-width: 992px) {
	.masthead {
		padding-top: calc(5rem + 80px + env(safe-area-inset-top, 0px));
		padding-bottom: 4rem;
	}
	.masthead .masthead-avatar {
		width: min(350px, 30vh);
		height: min(350px, 30vh);
	}
	.masthead .masthead-heading {
		font-size: 2.7rem;
		line-height: 2.9rem;
	}
	.masthead .masthead-subheading {
		font-size: 1.25rem;
	}
}

/* ===== Experience Section — Aurora Background ===== */

#experience {
	background: linear-gradient(
		170deg,
		#06070b 0%,
		#0a0c12 18%,
		#0c0e14 35%,
		#080a10 60%,
		#040508 100%
	);
	overflow: hidden;
	position: relative;
}

/* Floating aurora orbs behind experience */
#experience::before,
#experience::after {
	content: '';
	position: absolute;
	border-radius: 50%;
	filter: blur(100px) hue-rotate(var(--aurora-hue));
	opacity: 0.35;
	pointer-events: none;
	transition: filter 0.3s ease;
}

#experience::before {
	width: 500px;
	height: 500px;
	background: radial-gradient(circle, rgba(90, 120, 145, 0.5), rgba(122, 26, 34, 0.3), transparent 70%);
	top: 10%;
	left: -5%;
	animation: orb-float-1 14s ease-in-out infinite;
}

#experience::after {
	width: 600px;
	height: 600px;
	background: radial-gradient(circle, rgba(154, 122, 62, 0.35), rgba(90, 120, 145, 0.2), transparent 70%);
	bottom: 5%;
	right: -8%;
	animation: orb-float-2 18s ease-in-out infinite;
}

/* Third orb via the container */
#experience > .container {
	position: relative;
	z-index: 2;
}

#experience .page-section-heading {
	color: #fff !important;
}

#experience .divider-custom .divider-custom-line {
	background-color: rgba(255, 255, 255, 0.4);
}

#experience .divider-custom .divider-custom-icon {
	color: #fff !important;
}

/* Aurora extra orb */
.experience-orb-3 {
	position: absolute;
	width: 350px;
	height: 350px;
	border-radius: 50%;
	background: radial-gradient(circle, rgba(122, 26, 34, 0.28), rgba(90, 120, 145, 0.18), transparent 70%);
	filter: blur(80px);
	opacity: 0.3;
	top: 50%;
	left: 40%;
	animation: orb-float-3 20s ease-in-out infinite;
	pointer-events: none;
}

/* ===== Timeline ===== */

.timeline {
	position: relative;
	padding: 2rem 0;
}

.timeline::before {
	content: '';
	position: absolute;
	left: 50%;
	top: 0;
	bottom: 0;
	width: 3px;
	background: linear-gradient(to bottom, var(--primary), rgba(122, 26, 34, 0.8), var(--accent));
	transform: translateX(-50%);
}

.timeline-item {
	position: relative;
	margin-bottom: 4.5rem;
	width: 50%;
}

.timeline-item:nth-child(odd) {
	padding-right: 3rem;
	text-align: right;
}

.timeline-item:nth-child(even) {
	padding-left: 3rem;
	margin-left: 50%;
}

.timeline-badge {
	position: absolute;
	top: 0;
	width: 50px;
	height: 50px;
	border-radius: 50%;
	background: linear-gradient(135deg, var(--primary), #7a1a22);
	color: #fff;
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 1.2rem;
	z-index: 2;
	box-shadow: 0 0 0 4px #06070b, 0 0 20px rgba(90, 120, 145, 0.4);
}

.timeline-item:nth-child(odd) .timeline-badge {
	right: -25px;
}

.timeline-item:nth-child(even) .timeline-badge {
	left: -25px;
}

.timeline-panel {
	background: rgba(255, 255, 255, 0.06);
	backdrop-filter: blur(12px);
	-webkit-backdrop-filter: blur(12px);
	border: 1px solid rgba(255, 255, 255, 0.1);
	border-radius: 16px;
	padding: 2rem 2rem 1.75rem;
	box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
	transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.4s ease, border-color 0.4s ease;
	text-align: left;
	color: #e0e0e0;
}

.timeline-panel:hover {
	transform: translateY(-6px);
	box-shadow: 0 12px 40px rgba(90, 120, 145, 0.15);
	border-color: rgba(90, 120, 145, 0.3);
}

.timeline-heading {
	margin-bottom: 1.1rem;
}

.timeline-panel h4 {
	font-size: 1.15rem;
	margin-bottom: 0.35rem;
	color: #fff;
	letter-spacing: 0.01em;
}

.timeline-panel .text-muted {
	color: rgba(255, 255, 255, 0.55) !important;
	font-size: 0.88rem;
}

.timeline-panel ul {
	padding-left: 1.2rem;
	margin-top: 0.25rem;
	margin-bottom: 1.1rem;
}

.timeline-panel ul li {
	font-size: 0.92rem;
	margin-bottom: 0.75rem;
	line-height: 1.7;
	color: rgba(255, 255, 255, 0.8);
}

.timeline-panel ul li:last-child {
	margin-bottom: 0;
}

.timeline-panel ul li strong {
	color: #fff;
	font-weight: 600;
}

.timeline-panel small.text-muted {
	color: rgba(255, 255, 255, 0.4) !important;
	font-size: 0.78rem !important;
	letter-spacing: 0.06em;
	display: inline-block;
	padding-top: 0.25rem;
}

/* Timeline highlight chips — opposite side of each panel */
.timeline-highlight {
	position: absolute;
	top: 1.2rem;
}

/* Odd items: panel is left → highlight goes right */
.timeline-item:nth-child(odd) .timeline-highlight {
	left: calc(100% + 3rem);
	text-align: left;
}

/* Even items: panel is right → highlight goes left */
.timeline-item:nth-child(even) .timeline-highlight {
	right: calc(100% + 3rem);
	text-align: right;
}

.highlight-chip {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	padding: 0.5rem 1.1rem;
	border-radius: 50px;
	background: rgba(10, 10, 35, 0.75);
	border: 1px solid rgba(90, 120, 145, 0.45);
	backdrop-filter: blur(12px);
	-webkit-backdrop-filter: blur(12px);
	box-shadow: 0 2px 12px rgba(0, 0, 0, 0.3);
	white-space: nowrap;
	transition: transform 0.3s ease, box-shadow 0.3s ease;
}

.highlight-chip:hover {
	transform: scale(1.05);
	box-shadow: 0 4px 20px rgba(90, 120, 145, 0.3);
	border-color: rgba(90, 120, 145, 0.7);
}

.highlight-chip i,
.highlight-chip svg {
	font-size: 1rem;
	width: 1rem;
	height: 1rem;
	color: #fff;
	fill: #fff;
}

.highlight-chip span {
	font-size: 0.78rem;
	font-weight: 700;
	color: #fff;
	letter-spacing: 0.03em;
}

/* Link variant — chip as anchor */
a.highlight-chip--link,
a.highlight-chip--link:hover,
a.highlight-chip--link:focus {
	text-decoration: none;
	cursor: pointer;
	color: inherit;
}

/* Scroll target offset so card lands below the fixed navbar */
#allstar-card {
	scroll-margin-top: 100px;
}

/* Pulse glow when scrolled to */
#allstar-card.pulse > .portfolio-card--split {
	animation: allstar-pulse 1.6s ease-out;
}

@keyframes allstar-pulse {
	0%   { box-shadow: 0 0 0 0 rgba(90, 120, 145, 0); border-color: rgba(255, 255, 255, 0.08); }
	25%  { box-shadow: 0 0 0 10px rgba(90, 120, 145, 0.25); border-color: rgba(90, 120, 145, 0.7); }
	70%  { box-shadow: 0 0 0 16px rgba(90, 120, 145, 0);   border-color: rgba(90, 120, 145, 0.3); }
	100% { box-shadow: 0 0 0 0 rgba(90, 120, 145, 0);      border-color: rgba(255, 255, 255, 0.08); }
}

@media (max-width: 768px) {
	.timeline::before {
		left: 25px;
	}
	.timeline-item,
	.timeline-item:nth-child(even) {
		width: 100%;
		margin-left: 0;
		padding-left: 4rem;
		padding-right: 0;
		text-align: left;
	}
	.timeline-item:nth-child(odd) {
		padding-right: 0;
		padding-left: 4rem;
		text-align: left;
	}
	.timeline-badge,
	.timeline-item:nth-child(odd) .timeline-badge,
	.timeline-item:nth-child(even) .timeline-badge {
		left: 0;
		right: auto;
	}
	/* On mobile, highlights tuck below the panel */
	.timeline-highlight,
	.timeline-item:nth-child(odd) .timeline-highlight,
	.timeline-item:nth-child(even) .timeline-highlight {
		position: relative;
		top: auto;
		left: auto;
		right: auto;
		margin-top: 0.8rem;
		text-align: left;
	}
}

/* ===== Skills Section ===== */

#skills .page-section-heading {
	color: #fff !important;
}

#skills .divider-custom .divider-custom-line {
	background-color: rgba(255, 255, 255, 0.4);
}

#skills .divider-custom .divider-custom-icon {
	color: #fff !important;
}

/* ===== Skill Badges ===== */

.skill-badge {
	background: rgba(255, 255, 255, 0.05);
	border: 1px solid rgba(255, 255, 255, 0.08);
	border-radius: 16px;
	padding: 2.25rem 1.25rem;
	box-shadow: none;
	transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.4s ease, border-color 0.4s ease;
	font-weight: 500;
	letter-spacing: 0.02em;
	font-size: 0.92rem;
	color: #e0e0e0;
	backdrop-filter: blur(8px);
	-webkit-backdrop-filter: blur(8px);
	line-height: 1.5;
}

.skill-badge:hover {
	transform: translateY(-8px);
	box-shadow: 0 12px 30px rgba(90, 120, 145, 0.15);
	border-color: rgba(90, 120, 145, 0.3);
}

.skill-badge i {
	color: var(--primary);
	margin-bottom: 1rem !important;
	display: inline-block;
}

/* Give the grid itself more vertical air between rows */
.skill-grid > [class*="col-"] {
	margin-bottom: 1.5rem;
}

@media (min-width: 992px) {
	.skill-grid > [class*="col-"] {
		margin-bottom: 2rem;
	}
}

/* ===== Portfolio Cards (What I've Built) ===== */

a.portfolio-card,
a.portfolio-card:hover,
a.portfolio-card:focus {
	text-decoration: none;
	color: inherit;
}

.portfolio-card {
	cursor: pointer;
	background: rgba(255, 255, 255, 0.04);
	border: 1px solid rgba(255, 255, 255, 0.08);
	border-radius: 16px;
	overflow: hidden;
	transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.4s ease, border-color 0.4s ease;
	height: 100%;
	display: flex;
	flex-direction: column;
	max-width: 25rem;
	margin: 0 auto;
}

.portfolio-card:hover {
	transform: translateY(-8px);
	box-shadow: 0 20px 50px rgba(90, 120, 145, 0.2);
	border-color: rgba(90, 120, 145, 0.25);
}

/* Featured variant — subtle accent border + softly glowing top edge so it
   reads as the primary CTA in the Highlights grid. Used for the Blog card. */
.portfolio-card--featured {
	border-color: rgba(90, 120, 145, 0.28);
	background:
		linear-gradient(180deg, rgba(90, 120, 145, 0.09), rgba(90, 120, 145, 0) 40%),
		rgba(255, 255, 255, 0.04);
	box-shadow: 0 0 0 1px rgba(90, 120, 145, 0.06), 0 8px 24px rgba(0, 0, 0, 0.2);
}

.portfolio-card--featured:hover {
	border-color: rgba(90, 120, 145, 0.55);
	box-shadow: 0 0 0 1px rgba(90, 120, 145, 0.18), 0 24px 56px rgba(90, 120, 145, 0.22);
}

/* Blog preview SVG fills its frame edge-to-edge (like the other logo cards
   but as a rectangular preview). Override the default contain + padding. */
.portfolio-card--featured .portfolio-card-img {
	padding: 0;
	background: transparent;
}

.portfolio-card--featured .portfolio-card-img img {
	width: 100%;
	height: 100%;
	max-width: 100%;
	max-height: 100%;
	object-fit: cover;
	object-position: center;
	transform: none;
}

.portfolio-card--featured:hover .portfolio-card-img img {
	transform: scale(1.04);
}

.portfolio-card-badge {
	display: inline-block;
	font-size: 0.65rem;
	font-weight: 600;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--primary);
	padding: 0.2rem 0.6rem;
	margin-bottom: 0.6rem;
	border: 1px solid rgba(90, 120, 145, 0.35);
	border-radius: 999px;
	background: rgba(90, 120, 145, 0.08);
}

.portfolio-card-img {
	position: relative;
	overflow: hidden;
	background: rgba(255, 255, 255, 0.03);
	height: 200px;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 0;
}

.portfolio-card-img img {
	width: 100%;
	height: 100%;
	/* `cover` so every logo fills the frame identically regardless of its
	   own aspect ratio — the alternative (`contain`) leaves varying widths
	   of empty space around tall-thin vs. wide logos. */
	object-fit: cover;
	object-position: center;
	display: block;
	transition: transform 0.5s ease;
}

/* Compact variant — for logos with tight/packed brand art (Codeforces banner,
   StopStalk circular emblem) that look over-zoomed when `cover` fills edge-
   to-edge. Drops back to `contain` with padding so the logo sits at a
   comfortable size with breathing room. */
.portfolio-card-img--compact {
	padding: 1.25rem 1.5rem;
}

.portfolio-card-img--compact img {
	object-fit: contain;
}

.portfolio-card:hover .portfolio-card-img img {
	transform: scale(1.08);
}

/* Portrait-oriented images: use blurred self as backdrop, sharp trophy centered on top */
.portfolio-card-img--portrait {
	background-size: cover;
	background-position: center;
	background-repeat: no-repeat;
	position: relative;
}

.portfolio-card-img--portrait::before {
	content: "";
	position: absolute;
	inset: 0;
	backdrop-filter: blur(20px) saturate(140%);
	-webkit-backdrop-filter: blur(20px) saturate(140%);
	background: rgba(10, 10, 35, 0.45);
}

.portfolio-card-img--portrait img {
	position: relative;
	z-index: 1;
	max-height: 100%;
	width: auto;
	object-fit: contain;
	filter: drop-shadow(0 8px 20px rgba(0, 0, 0, 0.5));
	transform: none;
}

/* Split-action card — image opens lightbox, body links elsewhere */
.portfolio-card--split {
	display: flex;
	flex-direction: column;
	cursor: default;
}

.portfolio-card-img--button {
	border: none;
	padding: 0;
	margin: 0;
	width: 100%;
	cursor: zoom-in;
	font: inherit;
	color: inherit;
}

.portfolio-card-body--link,
.portfolio-card-body--link:hover,
.portfolio-card-body--link:focus,
.portfolio-card-body--link:active {
	color: inherit;
	text-decoration: none;
	transition: background 0.3s ease;
}

.portfolio-card-body--link:hover {
	background: rgba(90, 120, 145, 0.06);
}

.portfolio-card-body--link:hover h5 {
	color: var(--primary);
}

.portfolio-card-body--link h5 {
	transition: color 0.3s ease;
}

.portfolio-card-body--link h5 .fa-external-link-alt {
	opacity: 0;
	transform: translateX(-4px);
	transition: opacity 0.3s ease, transform 0.3s ease;
}

.portfolio-card-body--link:hover h5 .fa-external-link-alt {
	opacity: 1;
	transform: translateX(0);
}

/* Split card lifts as a unit on hover, same motion as every other card in
   the grid. Click targets are still split: image opens the lightbox, body
   links to the Salesforce article — but the whole card responds visually. */
.portfolio-card--split:hover {
	transform: translateY(-8px);
	box-shadow: 0 20px 50px rgba(90, 120, 145, 0.2);
	border-color: rgba(90, 120, 145, 0.25);
}

.portfolio-card-img--button:hover .portfolio-card-overlay {
	opacity: 1;
}

.portfolio-card-img--button:hover img {
	transform: scale(1.06);
}

/* Zoom button — sits on portrait images, opens lightbox */
.portfolio-card-zoom {
	position: absolute;
	top: 10px;
	right: 10px;
	z-index: 3;
	width: 34px;
	height: 34px;
	border-radius: 50%;
	border: 1px solid rgba(255, 255, 255, 0.2);
	background: rgba(10, 10, 35, 0.55);
	backdrop-filter: blur(10px) saturate(160%);
	-webkit-backdrop-filter: blur(10px) saturate(160%);
	color: #fff;
	font-size: 0.8rem;
	cursor: pointer;
	opacity: 0;
	transform: scale(0.85);
	transition: opacity 0.3s ease, transform 0.3s ease, background 0.3s ease, border-color 0.3s ease;
	padding: 0;
	display: flex;
	align-items: center;
	justify-content: center;
}

.portfolio-card:hover .portfolio-card-zoom,
.portfolio-card-img--button:hover .portfolio-card-zoom,
.portfolio-card-img--button:focus-visible .portfolio-card-zoom,
.lifestyle-card:hover .portfolio-card-zoom,
.lifestyle-img:focus-visible .portfolio-card-zoom {
	opacity: 1;
	transform: scale(1);
}

.portfolio-card-img--button:hover .portfolio-card-zoom,
.lifestyle-img:hover .portfolio-card-zoom {
	background: rgba(90, 120, 145, 0.35);
	border-color: rgba(90, 120, 145, 0.7);
}

/* Always-visible on touch devices (no hover) */
@media (hover: none) {
	.portfolio-card-zoom {
		opacity: 1;
		transform: scale(1);
	}
}

/* Generic zoomable <img> — clickable hero/thumbnail images */
.zoomable {
	cursor: zoom-in;
	transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.4s ease;
}

.zoomable:hover {
	transform: scale(1.02);
}

/* Lifestyle card image made into a button */
.zoomable-btn {
	border: 0;
	padding: 0;
	margin: 0;
	background: none;
	cursor: zoom-in;
	width: 100%;
	font: inherit;
	color: inherit;
	display: block;
}

/* WakaTime cards — zoom affordance */
.zoomable-figure {
	position: relative;
	cursor: zoom-in;
}

.wakatime-zoom {
	position: absolute;
	top: 10px;
	right: 10px;
	z-index: 2;
	width: 30px;
	height: 30px;
	border-radius: 50%;
	border: 1px solid rgba(255, 255, 255, 0.15);
	background: rgba(10, 10, 35, 0.6);
	backdrop-filter: blur(10px) saturate(160%);
	-webkit-backdrop-filter: blur(10px) saturate(160%);
	color: rgba(255, 255, 255, 0.8);
	font-size: 0.7rem;
	opacity: 0;
	transform: scale(0.85);
	transition: opacity 0.3s ease, transform 0.3s ease, background 0.3s ease, border-color 0.3s ease, color 0.3s ease;
	display: flex;
	align-items: center;
	justify-content: center;
	pointer-events: none;
}

.zoomable-figure:hover .wakatime-zoom {
	opacity: 1;
	transform: scale(1);
}

.zoomable-figure:hover {
	background: rgba(90, 120, 145, 0.06);
}

@media (hover: none) {
	.wakatime-zoom {
		opacity: 1;
		transform: scale(1);
	}
}

/* ===== Lightbox — fullscreen image viewer ===== */
.lightbox {
	position: fixed;
	inset: 0;
	z-index: 100000;
	background: rgba(5, 5, 15, 0.92);
	backdrop-filter: blur(8px);
	-webkit-backdrop-filter: blur(8px);
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 2rem;
	opacity: 0;
	visibility: hidden;
	transition: opacity 0.3s ease, visibility 0.3s ease;
}

.lightbox.open {
	opacity: 1;
	visibility: visible;
}

.lightbox-img {
	max-width: 92vw;
	max-height: 88vh;
	width: auto;
	height: auto;
	border-radius: 10px;
	box-shadow: 0 30px 80px rgba(0, 0, 0, 0.6);
	transform: scale(0.95);
	transition: transform 0.35s cubic-bezier(0.16, 1, 0.3, 1);
}

.lightbox.open .lightbox-img {
	transform: scale(1);
}

.lightbox-close {
	position: absolute;
	top: 1.2rem;
	right: 1.2rem;
	width: 44px;
	height: 44px;
	border-radius: 50%;
	border: 1px solid rgba(255, 255, 255, 0.15);
	background: rgba(10, 10, 35, 0.6);
	backdrop-filter: blur(12px);
	-webkit-backdrop-filter: blur(12px);
	color: #fff;
	font-size: 1.1rem;
	cursor: pointer;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 0;
	transition: background 0.25s ease, border-color 0.25s ease, transform 0.25s ease;
}

.lightbox-close:hover {
	background: rgba(154, 122, 62, 0.45);
	border-color: rgba(154, 122, 62, 0.7);
	transform: rotate(90deg);
}

body.lightbox-open {
	overflow: hidden;
}

/* ===== Resume Modal — in-page PDF viewer ===== */
.resume-modal {
	position: fixed;
	inset: 0;
	z-index: 100001;
	background: rgba(5, 5, 15, 0.92);
	backdrop-filter: blur(8px);
	-webkit-backdrop-filter: blur(8px);
	display: flex;
	flex-direction: column;
	opacity: 0;
	visibility: hidden;
	transition: opacity 0.3s ease, visibility 0.3s ease;
	padding: 1.2rem;
}

.resume-modal.open {
	opacity: 1;
	visibility: visible;
}

.resume-modal-toolbar {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	padding: 0.6rem 1rem;
	background: rgba(10, 10, 35, 0.7);
	backdrop-filter: blur(14px) saturate(160%);
	-webkit-backdrop-filter: blur(14px) saturate(160%);
	border: 1px solid rgba(255, 255, 255, 0.08);
	border-radius: 10px 10px 0 0;
	border-bottom: 0;
}

.resume-modal-title {
	color: rgba(255, 255, 255, 0.65);
	font-size: 0.8rem;
	font-weight: 500;
	letter-spacing: 0.12em;
	text-transform: uppercase;
}

.resume-modal-actions {
	display: flex;
	align-items: center;
	gap: 0.65rem;
}

.resume-modal-download {
	display: inline-flex;
	align-items: center;
	padding: 0.45rem 1.1rem;
	font-size: 0.78rem;
	font-weight: 500;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: #fff;
	background: rgba(90, 120, 145, 0.18);
	border: 1px solid rgba(90, 120, 145, 0.35);
	border-radius: 50px;
	text-decoration: none;
	transition: background 0.25s ease, border-color 0.25s ease, transform 0.25s ease;
}

.resume-modal-download:hover {
	background: rgba(90, 120, 145, 0.35);
	border-color: rgba(90, 120, 145, 0.75);
	color: #fff;
	text-decoration: none;
	transform: translateY(-1px);
}

.resume-modal-close {
	width: 36px;
	height: 36px;
	border-radius: 50%;
	border: 1px solid rgba(255, 255, 255, 0.15);
	background: rgba(10, 10, 35, 0.6);
	color: #fff;
	font-size: 0.95rem;
	padding: 0;
	cursor: pointer;
	display: flex;
	align-items: center;
	justify-content: center;
	transition: background 0.25s ease, border-color 0.25s ease, transform 0.25s ease;
}

.resume-modal-close:hover {
	background: rgba(154, 122, 62, 0.4);
	border-color: rgba(154, 122, 62, 0.7);
	transform: rotate(90deg);
}

.resume-modal-body {
	flex: 1;
	background: #0a0c14;
	border: 1px solid rgba(255, 255, 255, 0.08);
	border-top: 0;
	border-radius: 0 0 10px 10px;
	overflow: hidden;
	box-shadow: 0 30px 80px rgba(0, 0, 0, 0.6);
}

.resume-modal-body iframe {
	width: 100%;
	height: 100%;
	border: 0;
	display: block;
	background: #0a0c14;
}

body.resume-open {
	overflow: hidden;
}

@media (max-width: 576px) {
	.resume-modal {
		padding: 0.5rem;
	}
	.resume-modal-title {
		font-size: 0.7rem;
		letter-spacing: 0.08em;
	}
	.resume-modal-download {
		padding: 0.4rem 0.8rem;
		font-size: 0.7rem;
	}
}

/* WakaTime variant — match the dark-themed filter used on the small cards.
   CSS filter also inverts the box-shadow (dark → white halo), so strip it here. */
.lightbox-img.lightbox-img--wakatime {
	filter: invert(0.88) hue-rotate(180deg);
	box-shadow: none;
}

.portfolio-card-overlay {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	display: flex;
	align-items: center;
	justify-content: center;
	background: rgba(10, 10, 35, 0.7);
	color: rgba(255, 255, 255, 0.8);
	opacity: 0;
	transition: opacity 0.3s ease;
}

.portfolio-card:hover .portfolio-card-overlay {
	opacity: 1;
}

.portfolio-card-body {
	padding: 1.5rem 1.5rem 1.6rem;
	flex: 1;
	display: flex;
	flex-direction: column;
}

.portfolio-card-body h5 {
	font-size: 1.05rem;
	color: #fff;
	margin-bottom: 0.65rem;
	font-weight: 600;
	letter-spacing: 0.01em;
}

.portfolio-card-body p {
	font-size: 0.88rem;
	color: rgba(255, 255, 255, 0.6);
	line-height: 1.65;
	margin-bottom: 0;
	flex: 1;
}

.portfolio-card-tag {
	display: inline-block;
	font-size: 0.7rem;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.04em;
	color: var(--primary);
	border: 1px solid rgba(90, 120, 145, 0.3);
	border-radius: 4px;
	padding: 0.2rem 0.5rem;
	margin-right: 0.4rem;
	margin-bottom: 0.3rem;
}


/* ===== Resume — view button in hero ===== */

.btn-resume {
	padding: 0.65rem 1.8rem;
	font-size: 0.9rem;
	font-weight: 500;
	border-radius: 50px;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	transition: transform 0.3s ease, box-shadow 0.3s ease, background 0.3s ease;
}

.btn-resume:hover {
	transform: translateY(-2px);
	box-shadow: 0 6px 20px rgba(90, 120, 145, 0.25);
}

/* ===== Footer ===== */

.footer {
	/* `.footer--oneline` overrides padding to a tight 1.4rem; this base rule
	   only supplies the surface color and text color now. */
	padding-top: 1.4rem;
	padding-bottom: 1.4rem;
	background-color: var(--secondary);
	color: #fff;
}

.footer h4 {
	font-size: 0.85rem;
	font-weight: 600;
	letter-spacing: 0.22em;
	color: rgba(255, 255, 255, 0.4);
}

.footer .lead {
	font-size: 1rem;
	color: rgba(255, 255, 255, 0.7);
}

.footer .footer-emails {
	display: flex;
	flex-direction: column;
	gap: 0.65rem;
	align-items: center;
}

.footer a {
	color: var(--primary);
}

.footer a:hover {
	color: #fff;
}

/* ===== Copyright ===== */

.copyright {
	background-color: #000;
	padding-top: 1.5rem !important;
	padding-bottom: 1.5rem !important;
}

.copyright small {
	color: rgba(255, 255, 255, 0.5);
	font-size: 0.78rem;
	letter-spacing: 0.08em;
}

.legacy-link {
	color: rgba(255, 255, 255, 0.4);
	font-size: 0.8rem;
	display: inline-block;
	margin-top: 0.5rem;
	transition: color 0.3s ease;
}

.legacy-link:hover {
	color: var(--primary);
	text-decoration: none;
}

/* ===== Portfolio row — equal height cards ===== */

.portfolio .row {
	display: flex;
	flex-wrap: wrap;
}

.portfolio .row > [class*="col-"] {
	display: flex;
}

/* ===== Education Cards ===== */

.edu-card {
	background: rgba(255, 255, 255, 0.04);
	border: 1px solid rgba(255, 255, 255, 0.08);
	border-radius: 16px;
	overflow: hidden;
	display: flex;
	flex-direction: column;
	transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.4s ease, border-color 0.4s ease;
	position: relative;
}

.edu-card:hover {
	transform: translateY(-6px);
	box-shadow: 0 16px 40px rgba(90, 120, 145, 0.15);
	border-color: rgba(90, 120, 145, 0.25);
}

.edu-card-accent {
	height: 4px;
	background: linear-gradient(90deg, var(--primary), #7a1a22);
}

.edu-card-body {
	padding: 1.1rem 1.3rem 1rem;
	flex: 1;
	display: flex;
	flex-direction: column;
}

.edu-card-icon {
	font-size: 1.5rem;
	color: var(--primary);
	margin-bottom: 0.6rem;
}

.edu-card h5 {
	font-size: 1rem;
	color: #fff;
	margin-bottom: 0.4rem;
	font-weight: 600;
	letter-spacing: 0.01em;
}

.edu-degree {
	font-size: 0.82rem;
	color: rgba(255, 255, 255, 0.7);
	margin-bottom: 0.2rem;
	line-height: 1.4;
}

.edu-minor {
	font-size: 0.82rem;
	color: rgba(255, 255, 255, 0.7);
	margin-bottom: 0.5rem;
	line-height: 1.4;
}

.edu-detail {
	font-size: 0.82rem;
	color: rgba(255, 255, 255, 0.8);
	margin-bottom: 0.3rem;
	line-height: 1.4;
}

.edu-detail strong {
	color: #fff;
	font-weight: 600;
}

.edu-date {
	font-size: 0.72rem;
	color: rgba(255, 255, 255, 0.4);
	margin-bottom: 0.6rem;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}

.edu-extras {
	display: flex;
	flex-wrap: wrap;
	gap: 0.45rem;
	margin-top: auto;
	padding-top: 1.1rem;
}

.edu-extra-tag {
	display: inline-block;
	font-size: 0.68rem;
	font-weight: 500;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	color: rgba(255, 255, 255, 0.55);
	border: 1px solid rgba(255, 255, 255, 0.14);
	border-radius: 50px;
	padding: 0.3rem 0.75rem;
}

.edu-exam-grid {
	display: grid;
	grid-template-columns: 1fr 1fr;
	grid-template-rows: 1fr 1fr;
	gap: 0.75rem;
}

.edu-exam-grid .exam-card {
	height: 100%;
	padding: 1rem 0.75rem;
	justify-content: center;
}

@media (max-width: 575.98px) {
	.edu-exam-grid {
		grid-template-columns: 1fr 1fr;
	}
}

.edu-card--compact .edu-card-body {
	padding: 1rem;
}

.edu-card--compact h5 {
	font-size: 0.9rem;
}

.edu-card--compact .edu-degree {
	font-size: 0.72rem;
}

.edu-card--compact .edu-detail {
	font-size: 0.72rem;
	margin-bottom: 0.2rem;
}

.edu-card--compact .edu-date {
	font-size: 0.65rem;
}

.edu-card--compact .edu-card-icon {
	font-size: 1.2rem;
	margin-bottom: 0.5rem;
}

/* ===== Education row — equal height ===== */

.education-cards .row {
	display: flex;
	flex-wrap: wrap;
}

.education-cards .row > [class*="col-"] {
	display: flex;
}

.education-cards {
	max-width: 920px;
	margin-left: auto;
	margin-right: auto;
}

/* ===== Exam Score Cards ===== */

.exam-card {
	background: linear-gradient(135deg, rgba(90, 120, 145, 0.12), rgba(90, 120, 145, 0.06));
	border: 1px solid rgba(90, 120, 145, 0.25);
	border-radius: 14px;
	padding: 1rem 0.75rem;
	text-align: center;
	backdrop-filter: blur(12px);
	transition: transform 0.3s ease, box-shadow 0.3s ease;
	height: 100%;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 0.25rem;
}

.exam-card:hover {
	transform: translateY(-3px);
	box-shadow: 0 10px 30px rgba(90, 120, 145, 0.15);
	border-color: rgba(90, 120, 145, 0.4);
}

.exam-card-icon {
	width: 32px;
	height: 32px;
	border-radius: 8px;
	background: linear-gradient(135deg, rgba(90, 120, 145, 0.5), rgba(90, 120, 145, 0.3));
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 0.85rem;
	color: #fff;
	margin-bottom: 0.2rem;
}

.exam-card-title {
	font-family: var(--font-family-heading);
	font-size: 0.78rem;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	color: rgba(255, 255, 255, 0.6);
	margin: 0;
}

.exam-card-score {
	font-family: var(--font-family-heading);
	font-size: 1.25rem;
	font-weight: 700;
	color: #fff;
	line-height: 1.2;
}

.exam-card-max {
	font-size: 0.8rem;
	font-weight: 400;
	color: rgba(255, 255, 255, 0.4);
}

.exam-card-detail {
	font-size: 0.7rem;
	color: rgba(255, 255, 255, 0.4);
	letter-spacing: 0.02em;
}

/* ===== TOEFL Card (legacy — kept for potential future use) ===== */

.toefl-card {
	background: linear-gradient(135deg, rgba(20, 22, 30, 0.92), rgba(30, 33, 45, 0.88));
	border: 1px solid rgba(255, 255, 255, 0.08);
	border-radius: 18px;
	padding: 1.8rem 2rem;
	backdrop-filter: blur(12px);
	transition: transform 0.3s ease, box-shadow 0.3s ease;
}

.toefl-card:hover {
	transform: translateY(-3px);
	box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3);
}

.toefl-header {
	display: flex;
	align-items: center;
	gap: 1rem;
	margin-bottom: 1.5rem;
	flex-wrap: wrap;
}

.toefl-logo {
	width: 48px;
	height: 48px;
	border-radius: 12px;
	background: linear-gradient(135deg, #2563eb, #7c3aed);
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 1.3rem;
	color: #fff;
	flex-shrink: 0;
}

.toefl-title-block {
	flex: 1;
	min-width: 140px;
}

.toefl-title {
	font-family: var(--font-family-heading);
	font-size: 1.05rem;
	font-weight: 600;
	color: #fff;
	margin: 0;
}

.toefl-date {
	font-size: 0.78rem;
	color: rgba(255, 255, 255, 0.45);
	margin: 0.15rem 0 0;
}

.toefl-overall {
	text-align: center;
	padding: 0.5rem 1rem;
	border-radius: 12px;
	background: rgba(255, 255, 255, 0.04);
	border: 1px solid rgba(255, 255, 255, 0.08);
}

.toefl-overall-score {
	font-family: var(--font-family-heading);
	font-size: 2rem;
	font-weight: 700;
	color: #fff;
	line-height: 1;
}

.toefl-overall-max {
	font-size: 0.85rem;
	color: rgba(255, 255, 255, 0.45);
	margin-left: 0.15rem;
}

.toefl-cefr {
	display: block;
	font-size: 0.7rem;
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: #7c3aed;
	margin-top: 0.25rem;
}

.toefl-sections {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 0.75rem;
}

.toefl-section {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 0.35rem;
	padding: 1rem 0.5rem;
	border-radius: 12px;
	background: rgba(255, 255, 255, 0.03);
	border: 1px solid rgba(255, 255, 255, 0.06);
	transition: background 0.2s ease;
}

.toefl-section:hover {
	background: rgba(255, 255, 255, 0.06);
}

.toefl-section-icon {
	font-size: 1.1rem;
	color: rgba(255, 255, 255, 0.5);
}

.toefl-section-label {
	font-size: 0.72rem;
	font-weight: 500;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	color: rgba(255, 255, 255, 0.5);
}

.toefl-section-score {
	font-family: var(--font-family-heading);
	font-size: 1.35rem;
	font-weight: 700;
	color: #fff;
}

.toefl-section-score--top {
	color: #34d399;
}

.toefl-section-max {
	font-size: 0.72rem;
	font-weight: 400;
	color: rgba(255, 255, 255, 0.4);
}

@media (max-width: 575.98px) {
	.toefl-sections {
		grid-template-columns: repeat(2, 1fr);
	}
	.toefl-header {
		flex-direction: column;
		align-items: flex-start;
	}
	.toefl-overall {
		align-self: stretch;
		display: flex;
		align-items: baseline;
		gap: 0.5rem;
		justify-content: center;
	}
	.toefl-cefr {
		display: inline;
		margin-top: 0;
		margin-left: 0.5rem;
	}
	.toefl-card {
		padding: 1.2rem 1rem;
	}
}

/* ===== GitHub Section ===== */

/* Stats */
.gh-stat-card {
	padding: 1.2rem 0.5rem;
	border-radius: 12px;
	background: rgba(255, 255, 255, 0.04);
	border: 1px solid rgba(255, 255, 255, 0.06);
	transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.4s ease, border-color 0.4s ease;
}

.gh-stat-card:hover {
	transform: translateY(-4px);
	box-shadow: 0 8px 25px rgba(90, 120, 145, 0.15);
	border-color: rgba(90, 120, 145, 0.25);
}

.gh-stat-number {
	display: block;
	font-family: var(--font-family-heading);
	font-size: 1.8rem;
	font-weight: 700;
	color: #fff;
	line-height: 1.2;
}

/* Inline unit suffix for ratings — "4.35 / 5" reads at a glance which scale
   the average is on. Sits inline with the number, smaller + muted so the
   headline figure still owns the cell. Used on Books (Goodreads, /5),
   Titles (IMDb, /10), Anime + Manga (MAL, /10). */
.gh-stat-unit {
	display: inline;
	font-size: 0.95rem;
	font-weight: 500;
	color: rgba(255, 255, 255, 0.4);
	margin-left: 0.18rem;
	letter-spacing: 0.02em;
}

.gh-stat-label {
	display: block;
	font-size: 0.75rem;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	color: rgba(255, 255, 255, 0.4);
	margin-top: 0.3rem;
}

/* Language / LOC strip — stacked bar of top languages with a legend row. */
.gh-langs {
	max-width: 820px;
	margin: 1rem auto 2rem;
	padding: 1.25rem 1.5rem;
	background: rgba(255, 255, 255, 0.03);
	border: 1px solid rgba(255, 255, 255, 0.07);
	border-radius: 14px;
}

.gh-langs__header {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 1rem;
	margin-bottom: 0.85rem;
	font-family: var(--font-family-heading);
}

.gh-langs__title {
	font-size: 0.72rem;
	font-weight: 500;
	text-transform: uppercase;
	letter-spacing: 0.22em;
	color: rgba(255, 255, 255, 0.4);
}

.gh-langs__summary {
	font-size: 0.8rem;
	color: rgba(255, 255, 255, 0.7);
	font-variant-numeric: tabular-nums;
}

/* Mobile — stack the header vertically so the summary never gets cropped. */
@media (max-width: 640px) {
	.gh-langs__header {
		flex-direction: column;
		align-items: center;
		text-align: center;
		gap: 0.35rem;
	}
	.gh-langs__summary {
		font-size: 0.78rem;
	}
}

.gh-langs__bar {
	display: flex;
	width: 100%;
	height: 10px;
	border-radius: 999px;
	overflow: hidden;
	background: rgba(255, 255, 255, 0.05);
}

.gh-langs__bar-seg {
	height: 100%;
	transition: flex-basis 0.4s ease;
}

.gh-langs__legend {
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;
	gap: 0.4rem 0.9rem;
	margin-top: 0.85rem;
	font-size: 0.68rem;
	color: rgba(255, 255, 255, 0.65);
	font-variant-numeric: tabular-nums;
}

.gh-langs__legend-item {
	display: inline-flex;
	align-items: center;
	gap: 0.3rem;
	letter-spacing: 0.01em;
	white-space: nowrap;
	flex: 0 0 auto;
}

/* Mobile — center-justify the wrapped rows so they look intentional rather
   than orphaned left-aligned. */
@media (max-width: 720px) {
	.gh-langs__legend {
		justify-content: center;
		gap: 0.5rem 0.9rem;
	}
}

.gh-langs__legend-dot {
	width: 8px;
	height: 8px;
	border-radius: 50%;
	display: inline-block;
}

.gh-langs__legend-pct {
	color: rgba(255, 255, 255, 0.45);
	margin-left: 0.15rem;
}

/* Repo cards */
a.gh-repo-card,
a.gh-repo-card:hover,
a.gh-repo-card:focus {
	text-decoration: none;
	color: inherit;
}

.gh-repo-card {
	display: flex;
	flex-direction: column;
	height: 100%;
	background: rgba(255, 255, 255, 0.03);
	border: 1px solid rgba(255, 255, 255, 0.08);
	border-radius: 12px;
	padding: 1.75rem 1.75rem 1.6rem;
	transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.4s ease, border-color 0.4s ease;
	cursor: pointer;
}

.gh-repo-card:hover {
	transform: translateY(-5px);
	box-shadow: 0 12px 35px rgba(90, 120, 145, 0.15);
	border-color: rgba(90, 120, 145, 0.25);
}

.gh-repo-header {
	display: flex;
	align-items: center;
	gap: 0.7rem;
	margin-bottom: 0.9rem;
}

.gh-repo-icon {
	font-size: 1rem;
	color: var(--primary);
}

.gh-repo-name {
	font-family: var(--font-family-heading);
	font-size: 0.95rem;
	font-weight: 600;
	color: var(--primary);
	letter-spacing: 0.01em;
}

.gh-repo-desc {
	font-size: 0.85rem;
	color: rgba(255, 255, 255, 0.55);
	line-height: 1.7;
	flex: 1;
	margin-bottom: 1.2rem;
}

.gh-repo-footer {
	display: flex;
	align-items: center;
	gap: 1.1rem;
	font-size: 0.72rem;
	color: rgba(255, 255, 255, 0.4);
	padding-top: 0.5rem;
	border-top: 1px solid rgba(255, 255, 255, 0.05);
	letter-spacing: 0.04em;
}

.gh-repo-lang {
	display: flex;
	align-items: center;
	gap: 0.35rem;
}

.gh-lang-dot {
	width: 10px;
	height: 10px;
	border-radius: 50%;
	display: inline-block;
}

.gh-repo-stars i {
	margin-right: 0.2rem;
}

/* Equal height repo cards — scoped to repo grid only */
#codeStats .row > [class*="col-lg-4"] {
	display: flex;
}

/* ===== LeetCode Section ===== */

.lc-color-easy { color: #00b8a3 !important; }
.lc-color-medium { color: #ffc01e !important; }
.lc-color-hard { color: #ef4743 !important; }

.lc-bar {
	display: flex;
	height: 10px;
	border-radius: 5px;
	overflow: hidden;
	background: rgba(255, 255, 255, 0.06);
}

.lc-bar-easy { background: #00b8a3; }
.lc-bar-medium { background: #ffc01e; }
.lc-bar-hard { background: #ef4743; }

.lc-bar-labels {
	display: flex;
	justify-content: center;
	gap: 1.5rem;
	margin-top: 0.5rem;
	font-size: 0.78rem;
	color: rgba(255, 255, 255, 0.45);
}

.lc-dot {
	display: inline-block;
	width: 8px;
	height: 8px;
	border-radius: 50%;
	margin-right: 0.3rem;
	vertical-align: middle;
}

.lc-dot-easy { background: #00b8a3; }
.lc-dot-medium { background: #ffc01e; }
.lc-dot-hard { background: #ef4743; }

/* ===== Heatmaps — DOM grid (LeetCode/GitHub modern style) ===== */
/* The wrap is full-width and centred; an inner `.hm-scroll` element handles
   horizontal overflow on small screens (last month no longer clips). */
#lc-heatmap-wrap,
#gh-heatmap-wrap,
.hm-wrap {
	position: relative;
	display: block;
	max-width: 920px;
	margin: 0 auto;
	padding: 1.4rem 1.2rem;
	background: rgba(255, 255, 255, 0.02);
	border: 1px solid rgba(255, 255, 255, 0.06);
	border-radius: 12px;
	overflow: hidden;
}

.hm-scroll {
	overflow-x: auto;
	overflow-y: hidden;
	-webkit-overflow-scrolling: touch;
	scrollbar-width: thin;
	scrollbar-color: rgba(154, 122, 62, 0.35) transparent;
	padding-bottom: 0.4rem;
}
.hm-scroll::-webkit-scrollbar { height: 6px; }
.hm-scroll::-webkit-scrollbar-track { background: transparent; }
.hm-scroll::-webkit-scrollbar-thumb {
	background: rgba(154, 122, 62, 0.35);
	border-radius: 3px;
}

/* The .hm element pins the months row, the day labels, and the cell grid
   into a single composition. Min-width keeps every column reachable
   horizontally even on tiny screens — scroll reveals what doesn't fit. */
.hm {
	min-width: 720px;            /* ~53 cols × 13 px + day-label gutter */
	font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
	font-size: 10px;
	color: rgba(255, 255, 255, 0.55);
	user-select: none;
}

.hm-months {
	display: grid;
	margin-left: 30px;            /* matches .hm-days width — keeps months aligned */
	grid-template-rows: 14px;
	margin-bottom: 4px;
}

.hm-month {
	font-size: 10px;
	color: rgba(255, 255, 255, 0.45);
	text-align: left;
	white-space: nowrap;
	letter-spacing: 0.02em;
}

.hm-body {
	display: grid;
	grid-template-columns: 30px 1fr;
	column-gap: 0;
	align-items: stretch;
}

.hm-days {
	display: grid;
	grid-template-rows: repeat(7, 1fr);
	font-size: 10px;
	color: rgba(255, 255, 255, 0.35);
	text-align: left;
	letter-spacing: 0.02em;
	padding-right: 6px;
	padding-top: 1px;
}
.hm-days span { line-height: 13px; min-height: 13px; }

.hm-grid {
	display: grid;
	grid-auto-flow: column;
	gap: 3px;
	min-width: 0;
}

/* Each day cell — a button so the OS handles touch/click hit-testing for us. */
.hm-cell {
	width: 11px;
	height: 11px;
	border: 0;
	padding: 0;
	border-radius: 2px;
	background: rgba(255, 255, 255, 0.045);
	cursor: pointer;
	transition: outline-color 0.15s ease, transform 0.15s ease;
	outline: 1px solid transparent;
	outline-offset: -1px;
}

.hm-cell:hover,
.hm-cell:focus-visible {
	outline-color: rgba(181, 151, 96, 0.7);
	transform: scale(1.15);
	z-index: 2;
	position: relative;
}

/* Active states for "pinned" tap-target on mobile — slightly elevated. */
.hm-cell:active {
	transform: scale(1.25);
	outline-color: rgba(181, 151, 96, 0.9);
}

/* GitHub level scale (blue progression) */
.hm-l-0 { background: rgba(255, 255, 255, 0.04); }
.hm-l-1 { background: rgba(66, 170, 245, 0.32); }
.hm-l-2 { background: rgba(66, 170, 245, 0.55); }
.hm-l-3 { background: rgba(66, 170, 245, 0.78); }
.hm-l-4 { background: rgba(66, 170, 245, 1.0); }

/* LeetCode level scale (warm orange — matches LC's own colors) */
.hm-lc-0 { background: rgba(255, 255, 255, 0.04); }
.hm-lc-1 { background: rgba(255, 161, 22, 0.32); }
.hm-lc-2 { background: rgba(255, 161, 22, 0.55); }
.hm-lc-3 { background: rgba(255, 161, 22, 0.78); }
.hm-lc-4 { background: rgba(255, 161, 22, 1.0); }

.hm-legend {
	display: flex;
	align-items: center;
	gap: 0.3rem;
	justify-content: flex-end;
	padding: 0.7rem 0 0;
	margin-left: 30px;
	font-size: 10px;
	color: rgba(255, 255, 255, 0.4);
	letter-spacing: 0.04em;
}
.hm-legend .hm-cell {
	width: 10px;
	height: 10px;
	cursor: default;
}
.hm-legend .hm-cell:hover { transform: none; outline-color: transparent; }
.hm-legend-text { padding: 0 0.25rem; }

/* On small screens, give the user a hint that the grid scrolls. */
@media (max-width: 720px) {
	.hm-wrap { padding: 1rem 0.9rem; }
	.hm-grid { gap: 2px; }
	.hm-cell { width: 10px; height: 10px; }
}

/* Streak line under LeetCode heatmap */
.lc-streak-line {
	color: rgba(255, 255, 255, 0.5);
	font-size: 0.8rem;
	letter-spacing: 0.04em;
	margin-bottom: 1.25rem;
	min-height: 1.2em;
}

/* Extra-large bottom margin utility — Bootstrap 4 tops out at mb-5 */
.mb-6 {
	margin-bottom: 4.5rem !important;
}

@media (min-width: 992px) {
	.mb-6 {
		margin-bottom: 6rem !important;
	}
}

.gh-tooltip {
	position: absolute;
	pointer-events: none;
	background: rgba(8, 9, 13, 0.95);
	color: #e6e6e6;
	font-size: 0.72rem;
	font-family: var(--font-family-heading);
	font-weight: 500;
	padding: 0.45rem 0.8rem;
	border-radius: 6px;
	border: 1px solid rgba(154, 122, 62, 0.35);
	white-space: nowrap;
	opacity: 0;
	transform: translateY(2px);
	transition: opacity 0.15s ease, transform 0.15s ease;
	z-index: 1000;
	box-shadow: 0 8px 22px rgba(0, 0, 0, 0.55);
	letter-spacing: 0.02em;
}

.gh-tooltip.visible {
	opacity: 1;
	transform: translateY(0);
}


/* ===== WakaTime Embed Cards ===== */
.wakatime-grid {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 2rem;
	max-width: 960px;
	margin: 2rem auto 1rem;
	padding: 0 0.5rem;
}

.wakatime-card {
	border-radius: 12px;
	overflow: hidden;
	padding: 1.25rem 1.25rem 1rem;
	background: rgba(255, 255, 255, 0.02);
	border: 1px solid rgba(255, 255, 255, 0.06);
	transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.4s ease, border-color 0.4s ease;
}

.wakatime-card:hover {
	transform: translateY(-4px);
	box-shadow: 0 12px 35px rgba(90, 120, 145, 0.12);
	border-color: rgba(90, 120, 145, 0.2);
}

.wakatime-card img {
	width: 100%;
	display: block;
	border-radius: 6px;
	filter: invert(0.88) hue-rotate(180deg);
	/* Reserve space so the card doesn't collapse to zero height while
	   wakatime.com (which is occasionally slow / 502s) hasn't responded.
	   The aspect-ratio matches WakaTime's 4:3 SVG output. */
	aspect-ratio: 4 / 3;
	background: rgba(255, 255, 255, 0.02);
	min-height: 1px;
}

/* Broken/failed image — show a graceful "couldn't load" hint instead of an
   empty card. `:has()` lets us style the parent if the <img> errored out. */
.wakatime-card img.wakatime-img-error {
	min-height: 140px;
	background: rgba(255, 255, 255, 0.03);
}
.wakatime-card.wakatime-card--error::after {
	content: "WakaTime is loading… ↻";
	display: block;
	text-align: center;
	color: rgba(255, 255, 255, 0.45);
	font-size: 0.75rem;
	font-family: var(--font-family-heading);
	letter-spacing: 0.06em;
	margin-top: 0.4rem;
}

@media (min-width: 992px) {
	.wakatime-grid {
		gap: 2.5rem;
		margin-top: 2.5rem;
	}
	.wakatime-card {
		padding: 1.5rem 1.5rem 1.25rem;
	}
}

@media (max-width: 768px) {
	.wakatime-grid {
		grid-template-columns: 1fr;
		max-width: 520px;
		gap: 1.5rem;
	}
}

/* ===== Beyond Code — Bookshelf ===== */

.bookshelf {
	position: relative;
	padding: 1.5rem 0;
}

.bookshelf-scroll {
	display: flex;
	gap: 1.2rem;
	overflow-x: auto;
	overflow-y: hidden;
	padding: 1rem 0.5rem 1.5rem;
	scroll-snap-type: x mandatory;
	-webkit-overflow-scrolling: touch;
	scrollbar-width: thin;
	scrollbar-color: rgba(255,255,255,0.15) transparent;
}

.bookshelf-scroll::-webkit-scrollbar {
	height: 6px;
}

.bookshelf-scroll::-webkit-scrollbar-track {
	background: transparent;
}

.bookshelf-scroll::-webkit-scrollbar-thumb {
	background: rgba(255,255,255,0.15);
	border-radius: 3px;
}

.bookshelf-scroll::-webkit-scrollbar-thumb:hover {
	background: rgba(255,255,255,0.25);
}

.book-card {
	flex-shrink: 0;
	scroll-snap-align: start;
	width: 140px;
	text-align: center;
	transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1);
	cursor: pointer;
	text-decoration: none;
	color: inherit;
}

.book-card:hover {
	transform: translateY(-8px) scale(1.03);
	text-decoration: none;
	color: inherit;
}

.book-cover-wrap {
	position: relative;
	width: 120px;
	height: 180px;
	margin: 0 auto 0.7rem;
	border-radius: 6px;
	overflow: hidden;
	box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4), 0 0 0 1px rgba(255,255,255,0.06);
	background: rgba(255,255,255,0.04);
}

.book-cover-wrap img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	transition: transform 0.5s ease;
}

.book-card:hover .book-cover-wrap img {
	transform: scale(1.06);
}

.book-cover-wrap::after {
	content: '';
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	background: linear-gradient(90deg, rgba(255,255,255,0.08) 0%, transparent 8%, transparent 92%, rgba(0,0,0,0.15) 100%);
	pointer-events: none;
}

.book-title {
	font-size: 0.72rem;
	font-weight: 600;
	color: rgba(255,255,255,0.8);
	line-height: 1.3;
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
	margin-bottom: 0.15rem;
}

.book-author {
	font-size: 0.65rem;
	color: rgba(255,255,255,0.35);
	line-height: 1.2;
	display: -webkit-box;
	-webkit-line-clamp: 1;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

/* Date a book was rated — sits below the author in a brass-tinted micro-line.
   Mirrors `.film-meta`'s placement on the IMDb shelf (year · director). */
.book-date {
	font-size: 0.6rem;
	color: rgba(212, 175, 106, 0.55);
	line-height: 1.2;
	letter-spacing: 0.02em;
	margin-top: 0.18rem;
	font-family: var(--font-family-heading, inherit);
	font-feature-settings: "tnum" 1, "lnum" 1;
}

/* Skeleton loader for books */
.book-skeleton {
	flex-shrink: 0;
	width: 140px;
	text-align: center;
}

.book-skeleton .book-cover-wrap {
	background: linear-gradient(110deg, rgba(255,255,255,0.04) 8%, rgba(255,255,255,0.08) 18%, rgba(255,255,255,0.04) 33%);
	background-size: 200% 100%;
	animation: shimmer 1.5s linear infinite;
}

/* Film-card skeleton — same shimmer device as `.book-skeleton`, sized to
   the 130×195 poster wrap so the layout doesn't shift when real cards
   replace these. Used while data/films.json is being fetched. */
.film-skeleton {
	flex-shrink: 0;
	width: 150px;
	text-align: center;
}
.film-skeleton .film-poster-wrap {
	background: linear-gradient(110deg, rgba(255,255,255,0.04) 8%, rgba(255,255,255,0.08) 18%, rgba(255,255,255,0.04) 33%);
	background-size: 200% 100%;
	animation: shimmer 1.5s linear infinite;
}

/* ===== Beyond Code — Sub-section headings ===== */

.beyond-sub {
	letter-spacing: 0.22em;
	color: rgba(255,255,255,0.45);
	font-size: 0.78rem;
	font-weight: 500;
	margin-top: 1rem;
	margin-bottom: 2.5rem !important;
}

/* ===== Beyond Code — Apple Music Song Embeds ===== */

.apple-music-song {
	width: 100%;
	height: 175px;
	border-radius: 12px;
	overflow: hidden;
	box-shadow: 0 8px 30px rgba(0, 0, 0, 0.3);
}

.song-label {
	font-size: 0.78rem;
	color: rgba(255, 255, 255, 0.35);
	text-align: center;
	margin-top: 0.6rem;
	margin-bottom: 0;
	letter-spacing: 0.02em;
}

/* Genre tags in Beyond section */
#beyond .portfolio-card-tag {
	margin-bottom: 0.4rem;
}

/* ===== Beyond Code — Lifestyle Cards ===== */

.lifestyle-card {
	background: rgba(255, 255, 255, 0.04);
	border: 1px solid rgba(255, 255, 255, 0.08);
	border-radius: 16px;
	overflow: hidden;
	height: 100%;
	transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.4s ease, border-color 0.4s ease;
}

.lifestyle-card:hover {
	transform: translateY(-6px);
	box-shadow: 0 16px 40px rgba(90, 120, 145, 0.15);
	border-color: rgba(90, 120, 145, 0.2);
}

.lifestyle-img {
	position: relative;
	aspect-ratio: 3 / 4;
	overflow: hidden;
	background: rgba(255, 255, 255, 0.02);
	border: 0;
	padding: 0;
	width: 100%;
	display: block;
	cursor: zoom-in;
	font: inherit;
	color: inherit;
}

.lifestyle-img img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center top;
	display: block;
	transition: transform 0.6s ease;
}

.lifestyle-card:hover .lifestyle-img img {
	transform: scale(1.06);
}

.lifestyle-overlay {
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	background: linear-gradient(180deg, transparent 40%, rgba(10, 10, 35, 0.7) 100%);
	opacity: 0;
	transition: opacity 0.4s ease;
}

.lifestyle-overlay i {
	font-size: 2rem;
	color: rgba(255, 255, 255, 0.8);
	filter: drop-shadow(0 2px 8px rgba(0,0,0,0.4));
}

.lifestyle-card:hover .lifestyle-overlay {
	opacity: 1;
}

.lifestyle-body {
	padding: 1.5rem 1.5rem 1.7rem;
}

.lifestyle-body h5 {
	font-size: 1rem;
	color: #fff;
	margin-bottom: 0.6rem;
	font-weight: 600;
	letter-spacing: 0.02em;
}

.lifestyle-body p {
	font-size: 0.88rem;
	color: rgba(255, 255, 255, 0.55);
	line-height: 1.7;
	margin-bottom: 0;
}

.lifestyle-tags {
	display: flex;
	flex-wrap: wrap;
	gap: 0.35rem;
}

/* aspect-ratio: 3/4 scales naturally on all screens — no breakpoint override needed */

/* ===== Beyond Code — YouTube Embeds (compact) ===== */

.beyond-video-wrap {
	position: relative;
	width: 100%;
	padding-bottom: 56.25%;
	border-radius: 12px;
	overflow: hidden;
	box-shadow: 0 8px 30px rgba(0, 0, 0, 0.3);
	background: rgba(255, 255, 255, 0.02);
}

.beyond-video-wrap iframe {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	border: 0;
}

/* ============================================================================
   ===== Midnight Forge — Luxe Polish =========================================
   ============================================================================
   Purely additive layer. Goal: keep every existing section structurally
   intact, but lift the production value with five moves:
     1. Whisper vignette + dim brass scrollbar (page atmosphere)
     2. Editorial monogram + vitals pill above the avatar
     3. Couture stacked-ring avatar shadow + gradient text-fill on hero h1
     4. Footer manifesto in serif italic
     5. Hairline gradient borders ("Linear/Stripe trick") on the existing
        stat cards, repo cards, edu cards, timeline panels, portfolio cards,
        and lifestyle cards — the move that reads "this site has a budget".
   No new sections. No copy invented. Only universal polish.
   ============================================================================ */

:root {
	--mf-bone: #cfd2d6;
	--mf-bone-bright: #ffffff;
	--mf-steel: #5a7891;
	--mf-brass: #9a7a3e;
	--mf-brass-pale: #b59760;
	--mf-display: "Cormorant Garamond", "Times New Roman", Times, serif;
	--mf-filament: rgba(154, 122, 62, 0.55);
}

/* ----- Whisper vignette — corners only, never fights legibility ----------- */
body::before {
	content: '';
	position: fixed;
	inset: 0;
	pointer-events: none;
	z-index: 9999;
	background: radial-gradient(ellipse at center,
		transparent 65%,
		rgba(0, 0, 0, 0.12) 92%,
		rgba(0, 0, 0, 0.22) 100%);
}

/* ----- Dim brass scrollbar ------------------------------------------------- */
* {
	scrollbar-width: thin;
	scrollbar-color: rgba(154, 122, 62, 0.35) transparent;
}
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-thumb {
	background: linear-gradient(180deg, rgba(154, 122, 62, 0.35), rgba(90, 120, 145, 0.25));
	border-radius: 999px;
	border: 2px solid transparent;
	background-clip: content-box;
}
*::-webkit-scrollbar-thumb:hover {
	background: linear-gradient(180deg, rgba(154, 122, 62, 0.55), rgba(90, 120, 145, 0.45));
	background-clip: content-box;
}
*::-webkit-scrollbar-track { background: transparent; }

/* ----- Hero monogram (above avatar) --------------------------------------- */
.hero-monogram {
	display: inline-flex;
	align-items: center;
	gap: 0.9rem;
	margin: 0 auto 1.4rem;
	font-family: var(--font-family-heading);
	letter-spacing: 0.42em;
	font-size: 0.7rem;
	font-weight: 600;
	text-transform: uppercase;
	opacity: 0.92;
}

.hero-monogram-mark {
	background: linear-gradient(180deg, #ffffff 0%, #cfd2d6 60%, #b59760 130%);
	-webkit-background-clip: text;
	background-clip: text;
	-webkit-text-fill-color: transparent;
	color: transparent;
}

.hero-monogram-rule {
	flex: 0 0 56px;
	height: 1px;
	background: linear-gradient(90deg, transparent 0%, var(--mf-filament) 50%, transparent 100%);
}

@media (max-width: 575px) {
	.hero-monogram { font-size: 0.64rem; letter-spacing: 0.34em; gap: 0.55rem; }
	.hero-monogram-rule { flex-basis: 36px; }
}

/* ----- Hero vitals pill --------------------------------------------------- */
.hero-vitals {
	display: inline-flex;
	align-items: center;
	gap: 1.1rem;
	list-style: none;
	margin: 1.4rem auto 0;
	padding: 0.55rem 1.4rem;
	border: 1px solid rgba(154, 122, 62, 0.28);
	border-radius: 999px;
	background: rgba(10, 10, 35, 0.55);
	backdrop-filter: blur(10px) saturate(140%);
	-webkit-backdrop-filter: blur(10px) saturate(140%);
	box-shadow:
		0 8px 28px rgba(0, 0, 0, 0.45),
		inset 0 1px 0 rgba(255, 255, 255, 0.04);
}

.hero-vitals li {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	font-family: var(--font-family-heading);
	font-size: 0.72rem;
	font-weight: 600;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.78);
}

.hero-vitals li i {
	color: var(--mf-brass-pale);
	font-size: 0.78rem;
	filter: drop-shadow(0 0 6px rgba(154, 122, 62, 0.35));
}

.hero-vitals-sep {
	width: 4px;
	height: 4px;
	border-radius: 50%;
	background: rgba(154, 122, 62, 0.55);
	box-shadow: 0 0 5px rgba(154, 122, 62, 0.5);
}

@media (max-width: 480px) {
	.hero-vitals { gap: 0.7rem; padding: 0.5rem 1rem; }
	.hero-vitals li { font-size: 0.62rem; letter-spacing: 0.14em; }
}

/* ----- Hero avatar — couture rings + brass halo --------------------------- */
.masthead-avatar {
	position: relative;
	box-shadow:
		0 0 0 1px rgba(154, 122, 62, 0.45),
		0 0 0 6px rgba(0, 0, 0, 0.6),
		0 0 0 7px rgba(207, 210, 214, 0.12),
		0 0 0 8px rgba(0, 0, 0, 0.5),
		0 0 60px rgba(154, 122, 62, 0.18),
		0 30px 80px rgba(0, 0, 0, 0.6) !important;
	transition: box-shadow 0.6s cubic-bezier(0.16, 1, 0.3, 1), transform 0.6s ease;
}

.masthead-avatar:hover {
	transform: scale(1.02);
	box-shadow:
		0 0 0 1px rgba(181, 151, 96, 0.75),
		0 0 0 6px rgba(0, 0, 0, 0.6),
		0 0 0 7px rgba(207, 210, 214, 0.22),
		0 0 0 8px rgba(0, 0, 0, 0.5),
		0 0 90px rgba(181, 151, 96, 0.28),
		0 36px 100px rgba(0, 0, 0, 0.7) !important;
}

/* ----- Hero h1 gradient fill ---------------------------------------------- */
.masthead-heading {
	background: linear-gradient(180deg, #ffffff 0%, #cfd2d6 70%, #b59760 130%);
	-webkit-background-clip: text;
	background-clip: text;
	-webkit-text-fill-color: transparent;
	color: transparent;
	letter-spacing: 0.04em !important;
	font-weight: 700;
}

/* ----- The Linear/Stripe gradient hairline border, applied to existing
   cards. Each card gets a `::after` overlay (so we don't fight any existing
   `::before` orb pseudo-elements). The mask-composite trick produces a 1 px
   gradient outline without nested elements or layout cost. -------------- */

.gh-stat-card,
.gh-repo-card,
.edu-card,
.timeline-panel,
.lifestyle-card,
a.portfolio-card,
.portfolio-card,
.skill-badge,
.book-card {
	position: relative;
}

.gh-stat-card::after,
.gh-repo-card::after,
.edu-card::after,
.timeline-panel::after,
.lifestyle-card::after,
a.portfolio-card::after,
.skill-badge::after,
.book-card::after {
	content: '';
	position: absolute;
	inset: 0;
	padding: 1px;
	border-radius: inherit;
	background: linear-gradient(135deg,
		rgba(154, 122, 62, 0.5) 0%,
		rgba(154, 122, 62, 0.05) 35%,
		rgba(207, 210, 214, 0.12) 60%,
		rgba(154, 122, 62, 0.5) 100%);
	-webkit-mask:
		linear-gradient(#000 0 0) content-box,
		linear-gradient(#000 0 0);
	-webkit-mask-composite: xor;
	mask-composite: exclude;
	pointer-events: none;
	opacity: 0.7;
	transition: opacity 0.4s ease;
}

/* On hover, the gradient lifts and brightens — the "lit edge" feel. */
.gh-stat-card:hover::after,
.gh-repo-card:hover::after,
.edu-card:hover::after,
.timeline-panel:hover::after,
.lifestyle-card:hover::after,
a.portfolio-card:hover::after,
.skill-badge:hover::after,
.book-card:hover::after {
	opacity: 1;
	background: linear-gradient(135deg,
		rgba(181, 151, 96, 0.85) 0%,
		rgba(154, 122, 62, 0.18) 35%,
		rgba(207, 210, 214, 0.25) 60%,
		rgba(181, 151, 96, 0.85) 100%);
}

/* The portfolio-card--split has a child `.portfolio-card-img` that's
   absolutely positioned; we don't want the gradient overlay reading inside
   the image button. So we drop the rule on that variant. */
.portfolio-card--split::after { display: none; }

/* ----- Tabular numerals on every metric — small detail, reads expensive -- */
.gh-stat-number,
.lc-bar,
.lc-streak-line,
.gh-langs__summary {
	font-variant-numeric: tabular-nums;
	font-feature-settings: "tnum" 1, "lnum" 1;
}

/* Bigger gh-stat numbers + soft gradient fill — quietly more luxurious */
.gh-stat-number {
	background: linear-gradient(180deg, #ffffff 0%, #d8d2c4 70%, #b59760 130%);
	-webkit-background-clip: text;
	background-clip: text;
	-webkit-text-fill-color: transparent;
	color: transparent;
	letter-spacing: 0.02em;
}

/* Keep LeetCode difficulty colors loud — they're semantic, not decorative */
.lc-color-easy,
.lc-color-medium,
.lc-color-hard {
	-webkit-text-fill-color: initial;
	background: none;
}

/* ----- Footer manifesto --------------------------------------------------- */
.forge-manifesto {
	display: inline-flex;
	flex-wrap: wrap;
	justify-content: center;
	align-items: center;
	gap: 0.7rem;
	margin: 0 0 0.7rem;
	font-family: var(--font-family-heading);
	font-size: 0.72rem;
	font-weight: 600;
	letter-spacing: 0.32em;
	text-transform: uppercase;
	color: var(--mf-brass-pale);
	opacity: 0.92;
}

.forge-manifesto > span:not(.forge-manifesto-sep) {
	color: var(--mf-bone-bright);
}

.forge-manifesto-sep {
	color: rgba(154, 122, 62, 0.5);
	font-weight: 400;
	letter-spacing: 0;
}

@media (max-width: 480px) {
	.forge-manifesto { font-size: 0.62rem; letter-spacing: 0.24em; gap: 0.45rem; }
}

/* "Built quietly" suffix in copyright reads as serif italic for that
   editorial-magazine touch. */
.copyright small {
	color: rgba(255, 255, 255, 0.45);
}

/* ----- Navbar — gentle brass on hover only -------------------------------- */
#mainNav .navbar-nav .nav-link:hover,
#mainNav .navbar-brand:hover {
	color: var(--mf-brass-pale) !important;
}

/* ----- Beyond Code — Film shelf (10/10 picks) ---------------------------- */
/* Same horizontal scroll-snap pattern as the bookshelf, but cards are
   fractionally wider and taller because movie posters are 2:3 aspect. */
.filmshelf {
	position: relative;
	padding: 1.2rem 0 0.5rem;
}

.filmshelf-scroll {
	display: flex;
	gap: 1.6rem;
	overflow-x: auto;
	overflow-y: hidden;
	padding: 0.6rem 0.5rem 1.4rem;
	scroll-snap-type: x mandatory;
	-webkit-overflow-scrolling: touch;
	scrollbar-width: thin;
	scrollbar-color: rgba(154, 122, 62, 0.35) transparent;
}

/* When there are only a few cards, centre them on the row instead of
   left-aligning them. `safe center` makes the browser fall back to
   `flex-start` whenever content overflows, so the leftmost card never
   gets clipped behind the scroll origin. */
.filmshelf--centered .filmshelf-scroll {
	justify-content: safe center;
}

/* If the cards overflow on a small viewport, fall back to scroll-flush-left
   (Bootstrap-style) so the user can swipe. */
@media (max-width: 575px) {
	.filmshelf--centered .filmshelf-scroll {
		justify-content: flex-start;
	}
}
.filmshelf-scroll::-webkit-scrollbar { height: 6px; }
.filmshelf-scroll::-webkit-scrollbar-track { background: transparent; }
.filmshelf-scroll::-webkit-scrollbar-thumb {
	background: rgba(154, 122, 62, 0.35);
	border-radius: 3px;
}
.filmshelf-scroll::-webkit-scrollbar-thumb:hover {
	background: rgba(154, 122, 62, 0.55);
}

.film-card {
	flex-shrink: 0;
	scroll-snap-align: start;
	width: 150px;
	text-align: center;
	color: inherit;
	text-decoration: none !important;
	transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}

.film-card:hover {
	transform: translateY(-8px) scale(1.03);
	color: inherit;
}

.film-poster-wrap {
	position: relative;
	width: 130px;
	height: 195px;          /* 2:3 poster aspect */
	margin: 0 auto 0.7rem;
	border-radius: 6px;
	overflow: hidden;
	background: rgba(255,255,255,0.04);
	box-shadow:
		0 4px 20px rgba(0, 0, 0, 0.55),
		0 0 0 1px rgba(154, 122, 62, 0.22);
	transition: box-shadow 0.4s ease;
}

.film-card:hover .film-poster-wrap {
	box-shadow:
		0 14px 32px rgba(0, 0, 0, 0.7),
		0 0 0 1px rgba(181, 151, 96, 0.55);
}

.film-poster-wrap img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	transition: transform 0.55s ease;
}

.film-card:hover .film-poster-wrap img {
	transform: scale(1.05);
}

/* Brass rating badge — sits in the bottom-right of the poster */
.film-rating {
	position: absolute;
	right: 6px;
	bottom: 6px;
	min-width: 22px;
	height: 22px;
	padding: 0 6px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	background: linear-gradient(180deg, rgba(8, 9, 13, 0.9), rgba(8, 9, 13, 0.95));
	border: 1px solid rgba(181, 151, 96, 0.6);
	border-radius: 999px;
	color: #f5e4b5;
	font-family: var(--font-family-heading);
	font-size: 0.66rem;
	font-weight: 700;
	letter-spacing: 0.04em;
	box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
}

/* "10" badge gets a hint more weight to read clearly. */
.film-rating:not(:empty) { line-height: 1; }

.film-title {
	font-size: 0.74rem;
	font-weight: 600;
	color: rgba(255, 255, 255, 0.85);
	line-height: 1.3;
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
	margin-bottom: 0.15rem;
	letter-spacing: 0.01em;
}

.film-meta {
	font-size: 0.66rem;
	color: rgba(255, 255, 255, 0.35);
	line-height: 1.2;
	letter-spacing: 0.02em;
}

/* ----- Footer — one clean three-cell line ------------------------------- */
/* email · © year + name · social icons.
   CSS Grid `1fr auto 1fr` so the centre cell stays optically centred even
   when the email and the social row aren't symmetric in width. Single
   brass hairline at the top is the only chrome. Wraps gracefully on
   narrow viewports. */

footer.footer.footer--oneline {
	position: relative;
	padding: 1.2rem 0 !important;
	border-top: 1px solid rgba(212, 175, 106, 0.14);
}

.footer-line {
	display: grid;
	grid-template-columns: 1fr auto 1fr;
	align-items: center;
	gap: 1rem 1.6rem;
	font-family: var(--font-family-heading);
	font-size: 0.78rem;
	letter-spacing: 0.06em;
	color: rgba(221, 211, 189, 0.55);
}

/* Left cell — email. Pinned to the start. */
.footer-email {
	justify-self: start;
	display: inline-flex;
	align-items: center;
	gap: 0.45rem;
	color: rgba(221, 211, 189, 0.55);
	text-decoration: none !important;
	transition: color 0.2s ease;
	white-space: nowrap;
}
.footer-email i { color: var(--mf-brass-pale, #b59760); font-size: 0.85rem; }
.footer-email:hover { color: var(--mf-brass-pale, #b59760); }

/* Centre cell — copyright + legacy link. Auto-sized so it stays put. */
.footer-copy {
	justify-self: center;
	white-space: nowrap;
}
.footer-copy-mark {
	color: rgba(181, 151, 96, 0.85);
	font-weight: 600;
	margin-left: 0.15rem;
}
.footer-line-sep {
	color: rgba(154, 122, 62, 0.5);
	margin: 0 0.55rem;
}
.footer-legacy {
	color: rgba(221, 211, 189, 0.55);
	text-decoration: none;
	transition: color 0.2s ease;
}
.footer-legacy:hover { color: var(--mf-brass-pale, #b59760); }

/* Right cell — socials. Pinned to the end. */
.footer-socials {
	justify-self: end;
	display: inline-flex;
	align-items: center;
	gap: 0.9rem;
}
.footer-social {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 1.6rem;
	height: 1.6rem;
	font-size: 0.95rem;
	color: rgba(221, 211, 189, 0.55);
	text-decoration: none !important;
	transition: color 0.2s ease, transform 0.2s ease;
}
.footer-social:hover {
	color: var(--mf-brass-pale, #b59760);
	transform: translateY(-1px);
}

/* Below ~820px the three cells stack so the email + the long copyright
   line don't crash into each other. Centred as a column. */
@media (max-width: 820px) {
	.footer-line {
		grid-template-columns: 1fr;
		justify-items: center;
		gap: 0.7rem;
	}
	.footer-email,
	.footer-copy,
	.footer-socials { justify-self: center; }
	.footer-copy { white-space: normal; }
}


/* ============================================================================
   ===== ATELIER — High-budget editorial pass ================================
   ============================================================================
   Sealed additive layer. Goal: take the page from "dark dev portfolio" to
   "T Magazine profile of an engineer". Six moves:

     1. Fine-grain paper noise overlay across the entire page (the trick that
        makes flat dark surfaces feel ink-printed instead of pixel-rendered).
     2. Editorial chapter eyebrows above every section heading via the
        `.chapter-eyebrow` element (Roman numeral in brass-foil + small-caps).
     3. A magazine-style press strip below the hero — small-caps tickerline
        of credentials separated by brass diamonds.
     4. Refined dividers — chunky icon dividers become hairline brass rules
        with a brass-foil glyph.
     5. Editorial pull-quote treatment — italic Cormorant, hanging brass
        quote-mark, hairline rules above and below.
     6. Brass inner-glow on every card-hover (the move that reads "budget").

   No prior layer is removed. Every existing animation, orb, timeline, and
   hover continues to work. Atelier sits on top.
   ========================================================================== */

:root {
	--at-ink:        #07070a;
	--at-vellum:     #ddd3bd;
	--at-brass-1:    #d4af6a;
	--at-brass-2:    #9a7a3e;
	--at-brass-3:    #66491c;
	--at-blood:      #7a1a22;
	--at-paper:      url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='220' height='220'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' seed='7' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.85  0 0 0 0 0.83  0 0 0 0 0.74  0 0 0 0.95 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
}

/* ----- Paper grain — the single biggest "feels printed" move -------------- */
body::after {
	content: '';
	position: fixed;
	inset: 0;
	pointer-events: none;
	z-index: 9998; /* under MF's vignette at 9999 */
	background-image: var(--at-paper);
	background-size: 220px 220px;
	opacity: 0.07;
	mix-blend-mode: overlay;
}

/* ----- Chapter eyebrows --------------------------------------------------- */
.chapter-eyebrow {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 0.9rem;
	margin: 0 auto 1rem;
	max-width: 36rem;
	font-family: var(--font-family-heading);
	font-size: 0.66rem;
	font-weight: 600;
	letter-spacing: 0.42em;
	text-transform: uppercase;
	color: var(--at-brass-1);
}

.chapter-eyebrow::before,
.chapter-eyebrow::after {
	content: '';
	flex: 1;
	height: 1px;
	background: linear-gradient(90deg, transparent 0%, rgba(212, 175, 106, 0.6) 50%, transparent 100%);
	max-width: 6rem;
}

.chapter-eyebrow .chapter-numeral {
	font-family: var(--mf-display, "Cormorant Garamond", serif);
	font-style: italic;
	font-weight: 500;
	font-size: 1.1rem;
	letter-spacing: 0.04em;
	background: linear-gradient(180deg, #f1d99a 0%, #b59760 60%, #66491c 130%);
	-webkit-background-clip: text;
	background-clip: text;
	-webkit-text-fill-color: transparent;
	color: transparent;
}

.chapter-eyebrow .chapter-bullet {
	color: rgba(212, 175, 106, 0.45);
	font-weight: 400;
	letter-spacing: 0;
}

@media (max-width: 575px) {
	.chapter-eyebrow {
		font-size: 0.58rem;
		letter-spacing: 0.32em;
		gap: 0.55rem;
	}
	.chapter-eyebrow::before,
	.chapter-eyebrow::after {
		max-width: 3rem;
	}
	.chapter-eyebrow .chapter-numeral { font-size: 0.95rem; }
}

/* ----- Section headings — brass-foil editorial weight --------------------- */
.page-section .page-section-heading {
	background: linear-gradient(180deg, #ffffff 0%, #ddd3bd 60%, #b59760 135%);
	-webkit-background-clip: text;
	background-clip: text;
	-webkit-text-fill-color: transparent;
	color: transparent;
	letter-spacing: 0.05em !important;
	font-weight: 600;
	font-feature-settings: "ss01" 1, "ss02" 1, "kern" 1, "liga" 1;
	margin-bottom: 0.4rem !important;
}

#skills .page-section-heading { color: transparent !important; }

/* ----- Refined dividers — hairline brass rule + brass-foil glyph ---------- */
.page-section .divider-custom {
	margin: 0.3rem auto 2.4rem;
	width: 100%;
	max-width: 18rem;
}

.page-section .divider-custom .divider-custom-line {
	max-width: none;
	flex: 1 1 auto;
	height: 1px;
	background: linear-gradient(90deg,
		transparent 0%,
		rgba(212, 175, 106, 0.55) 50%,
		transparent 100%) !important;
}

.page-section .divider-custom .divider-custom-icon {
	/* Solid brass — gradient text-fill broke the icon when Font Awesome
	   replaced <i> with inline <svg> (background-clip:text doesn't apply to
	   SVG glyphs the way it does to text). Solid color works on both. */
	color: #b59760 !important;
	background: none !important;
	-webkit-text-fill-color: currentColor !important;
	font-size: 0.95rem;
	margin: 0 1rem;
	filter: drop-shadow(0 0 8px rgba(181, 151, 96, 0.25));
}

/* Also force the SVG fill (inserted by Font Awesome JS) to inherit the
   brass color — covers the path inside the inline <svg> too. */
.page-section .divider-custom .divider-custom-icon svg {
	color: inherit;
	fill: currentColor;
}

/* ----- Press strip — magazine credit-line under the hero ------------------ */
.press-strip {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	align-items: center;
	gap: 0.85rem 1.4rem;
	list-style: none;
	margin: 1.6rem auto 0;
	padding: 0 1rem;
	max-width: 60rem;
	font-family: var(--font-family-heading);
	font-size: 0.66rem;
	font-weight: 500;
	letter-spacing: 0.32em;
	text-transform: uppercase;
	color: rgba(221, 211, 189, 0.6);
}

.press-strip li {
	position: relative;
	display: inline-flex;
	align-items: center;
	white-space: nowrap;
}

.press-strip li:not(:last-child)::after {
	content: '';
	margin-left: 1.4rem;
	width: 4px;
	height: 4px;
	transform: rotate(45deg);
	background: linear-gradient(135deg, #d4af6a, #66491c);
	box-shadow: 0 0 4px rgba(212, 175, 106, 0.45);
}

@media (max-width: 575px) {
	.press-strip {
		gap: 0.55rem 0.95rem;
		font-size: 0.58rem;
		letter-spacing: 0.22em;
	}
	.press-strip li:not(:last-child)::after { margin-left: 0.95rem; }
}

/* ----- Editorial pull-quote ----------------------------------------------- */
.atelier-quote {
	position: relative;
	max-width: 42rem;
	margin: 3.2rem auto 3rem;
	padding: 1.6rem 2rem 1.4rem;
	font-family: var(--mf-display, "Cormorant Garamond", serif);
	font-style: italic;
	font-weight: 400;
	font-size: clamp(1.05rem, 0.85rem + 0.7vw, 1.45rem);
	line-height: 1.55;
	color: rgba(221, 211, 189, 0.82);
	text-align: center;
	border-top: 1px solid rgba(212, 175, 106, 0.22);
	border-bottom: 1px solid rgba(212, 175, 106, 0.22);
}

.atelier-quote::before {
	content: '\201C';
	position: absolute;
	top: -1.05rem;
	left: 50%;
	transform: translateX(-50%);
	width: 2rem;
	height: 2rem;
	display: flex;
	align-items: center;
	justify-content: center;
	font-family: var(--mf-display, "Cormorant Garamond", serif);
	font-style: normal;
	font-size: 2.4rem;
	line-height: 1;
	color: var(--at-brass-1);
	background: var(--at-ink);
	border-radius: 50%;
}

.atelier-quote p { margin: 0 auto; max-width: 36rem; }

.atelier-quote cite {
	display: block;
	margin-top: 0.9rem;
	font-family: var(--font-family-heading);
	font-style: normal;
	font-size: 0.65rem;
	font-weight: 600;
	letter-spacing: 0.32em;
	text-transform: uppercase;
	color: rgba(212, 175, 106, 0.72);
}

/* ----- Tight Vlogs → Footer transition ---------------------------------- */
/* The Beyond Code section ends with the Vlogs grid; the next sibling is the
   compact footer. Halving the bottom padding here closes the visual dead
   space the user flagged without affecting any other section. */
#beyond.page-section {
	padding-bottom: 2.25rem;
}
@media (min-width: 992px) {
	#beyond.page-section {
		padding-bottom: 3rem;
	}
}

/* ----- Section rhythm + brass thread between sections -------------------- */
/* Halved from the original 8.5rem top+bottom (which was producing huge dead
   space between every section, particularly noticeable below the Vlogs grid
   where the next sibling is the compact footer). 5rem matches what the
   "Atelier" desktop pass intended. */
@media (min-width: 992px) {
	.page-section { padding-top: 5rem; padding-bottom: 5rem; }
}

.page-section { position: relative; }
.page-section + .page-section::before {
	content: '';
	position: absolute;
	top: 0;
	left: 50%;
	transform: translateX(-50%);
	width: clamp(8rem, 30vw, 22rem);
	height: 1px;
	background: linear-gradient(90deg,
		transparent 0%,
		rgba(212, 175, 106, 0.42) 50%,
		transparent 100%);
	pointer-events: none;
	z-index: 3;
}

/* ----- Body copy on dark slabs reads slightly warmer --------------------- */
.timeline-panel ul li,
.portfolio-card-body p,
.gh-repo-desc {
	color: rgba(221, 211, 189, 0.72) !important;
}

.timeline-panel strong,
.portfolio-card-body strong,
.lifestyle-body strong,
.edu-detail strong {
	color: var(--at-vellum) !important;
}

/* ----- Refined timeline rail — single brass thread tapering in & out ----- */
.timeline::before {
	background: linear-gradient(to bottom,
		transparent 0%,
		rgba(212, 175, 106, 0.06) 6%,
		rgba(212, 175, 106, 0.45) 50%,
		rgba(212, 175, 106, 0.06) 94%,
		transparent 100%) !important;
	width: 1px !important;
}

.timeline-badge {
	background: radial-gradient(circle at 30% 30%, #f1d99a 0%, #9a7a3e 55%, #5a3f17 100%) !important;
	color: #0a0a0a !important;
	box-shadow:
		0 0 0 1px rgba(212, 175, 106, 0.55),
		0 0 0 4px rgba(7, 7, 10, 0.85),
		0 0 24px rgba(212, 175, 106, 0.3) !important;
}

/* ----- Highlight chip — brass thread instead of steel-blue --------------- */
.highlight-chip {
	border: 1px solid rgba(212, 175, 106, 0.42) !important;
	background: rgba(7, 7, 10, 0.78) !important;
}

.highlight-chip i,
.highlight-chip svg {
	color: var(--at-brass-1) !important;
	fill: var(--at-brass-1) !important;
}

.highlight-chip:hover {
	border-color: rgba(212, 175, 106, 0.78) !important;
	box-shadow: 0 6px 22px rgba(212, 175, 106, 0.22) !important;
}

/* ----- Edu-card brass accent --------------------------------------------- */
.edu-card-accent {
	height: 2px !important;
	background: linear-gradient(90deg,
		transparent 0%,
		rgba(212, 175, 106, 0.0) 4%,
		rgba(212, 175, 106, 0.85) 50%,
		rgba(212, 175, 106, 0.0) 96%,
		transparent 100%) !important;
}

/* ----- Skill icons + portfolio badge in brass ---------------------------- */
.skill-badge i { color: var(--at-brass-1) !important; }

.portfolio-card-badge {
	color: var(--at-brass-1) !important;
	border-color: rgba(212, 175, 106, 0.42) !important;
	background: linear-gradient(180deg, rgba(212, 175, 106, 0.10), rgba(212, 175, 106, 0.02)) !important;
}

/* ----- Repo card titles + icons brass on hover --------------------------- */
.gh-repo-icon { color: var(--at-brass-1) !important; }
.gh-repo-name { color: var(--at-vellum) !important; transition: color 0.3s ease; }
.gh-repo-card:hover .gh-repo-name { color: var(--at-brass-1) !important; }

/* ----- Outline buttons — brass hairline -> filled brass on hover --------- */
.btn-outline-light {
	border-color: rgba(212, 175, 106, 0.55) !important;
	color: var(--at-vellum) !important;
}
.btn-outline-light:hover {
	background: linear-gradient(180deg, #f1d99a 0%, #9a7a3e 100%) !important;
	border-color: rgba(212, 175, 106, 0.95) !important;
	color: #0a0a0a !important;
	box-shadow: 0 8px 24px rgba(212, 175, 106, 0.28) !important;
}

.btn-resume {
	border-width: 1px !important;
	letter-spacing: 0.18em !important;
}

/* ----- Resume modal toolbar in brass ------------------------------------- */
.resume-modal-toolbar { border-bottom: 1px solid rgba(212, 175, 106, 0.18) !important; }
.resume-modal-download {
	background: linear-gradient(180deg, rgba(212, 175, 106, 0.18), rgba(212, 175, 106, 0.05)) !important;
	border-color: rgba(212, 175, 106, 0.45) !important;
	color: var(--at-vellum) !important;
}
.resume-modal-download:hover {
	background: linear-gradient(180deg, #f1d99a, #9a7a3e) !important;
	color: #0a0a0a !important;
}

/* ----- Lightbox close in brass ------------------------------------------ */
.lightbox-close { border-color: rgba(212, 175, 106, 0.30) !important; }
.lightbox-close:hover {
	background: linear-gradient(180deg, #d4af6a, #9a7a3e) !important;
	color: #0a0a0a !important;
}

/* ----- Beyond-sub headings as brass label -------------------------------- */
.beyond-sub {
	color: var(--at-brass-1) !important;
	letter-spacing: 0.32em !important;
	font-size: 0.7rem !important;
}
.beyond-sub i { color: var(--at-brass-1) !important; opacity: 0.85; }

/* ----- Heatmap cards & gh-langs strip with brass hairline frame ---------- */
#lc-heatmap-wrap,
#gh-heatmap-wrap {
	border: 1px solid rgba(212, 175, 106, 0.18) !important;
	background:
		linear-gradient(180deg, rgba(212, 175, 106, 0.025), transparent 30%),
		rgba(7, 7, 10, 0.6) !important;
}

.gh-langs {
	border: 1px solid rgba(212, 175, 106, 0.18) !important;
	background:
		linear-gradient(180deg, rgba(212, 175, 106, 0.03), transparent 40%),
		rgba(7, 7, 10, 0.55) !important;
}
.gh-langs__title { color: var(--at-brass-1) !important; }

/* ----- Section motto — italic Cormorant chapter-line --------------------- */
.section-motto {
	font-family: var(--mf-display, "Cormorant Garamond", serif);
	font-style: italic;
	font-weight: 400;
	font-size: clamp(0.95rem, 0.78rem + 0.5vw, 1.2rem);
	letter-spacing: 0.04em;
	color: rgba(221, 211, 189, 0.65);
	text-align: center;
	margin: -0.4rem auto 1.6rem;
	max-width: 38rem;
	text-transform: none;
}

/* ----- Footer + colophon ------------------------------------------------- */
.footer {
	/* No hard border-top — the brass thread + diamond pseudo-elements on
	   `.footer--compact` (in the layered Footer pass below) own the
	   chapter break. */
	border-top: 0;
	background:
		radial-gradient(ellipse at 50% 0%, rgba(212, 175, 106, 0.05), transparent 65%),
		var(--secondary) !important;
}

/* `.copyright` is no longer rendered — the footer owns the year line.
   Defensive reset kept in case any legacy markup ever slips back in. */
.copyright { display: none !important; }

.atelier-colophon {
	display: block;
	margin: 0.7rem auto 0;
	max-width: 38rem;
	font-family: var(--mf-display, "Cormorant Garamond", serif);
	font-style: italic;
	font-size: 0.78rem;
	color: rgba(221, 211, 189, 0.42);
	letter-spacing: 0.02em;
	line-height: 1.55;
}

.atelier-colophon::before {
	content: '— ';
	color: rgba(212, 175, 106, 0.7);
}

/* ----- Hero brass aura behind avatar + serif italic subheading ----------- */
.masthead-content { position: relative; }
.masthead-content::before {
	content: '';
	position: absolute;
	left: 50%;
	top: 5rem;
	transform: translateX(-50%);
	width: clamp(280px, 50vw, 520px);
	height: clamp(280px, 50vw, 520px);
	border-radius: 50%;
	background: radial-gradient(circle, rgba(212, 175, 106, 0.10) 0%, transparent 60%);
	filter: blur(40px);
	pointer-events: none;
	z-index: 0;
}

.masthead-heading {
	letter-spacing: 0.06em !important;
	font-weight: 700 !important;
}

.masthead .masthead-subheading {
	color: rgba(221, 211, 189, 0.78) !important;
	letter-spacing: 0.04em;
	font-style: italic;
	font-family: var(--mf-display, "Cormorant Garamond", serif);
	font-size: clamp(0.98rem, 0.85rem + 0.45vw, 1.22rem) !important;
}

.masthead .masthead-subheading strong {
	color: var(--at-brass-1) !important;
	font-style: normal;
	font-family: var(--font-family-heading);
	font-weight: 600;
	letter-spacing: 0.08em;
}

/* ----- Universal card chrome — brass inner-glow on hover ----------------- */
.gh-stat-card,
.gh-repo-card,
.edu-card,
.timeline-panel,
.lifestyle-card,
a.portfolio-card,
.portfolio-card,
.skill-badge {
	background: linear-gradient(180deg,
		rgba(212, 175, 106, 0.022) 0%,
		rgba(7, 7, 10, 0.4) 100%) !important;
	box-shadow:
		inset 0 1px 0 rgba(212, 175, 106, 0.06),
		0 12px 40px rgba(0, 0, 0, 0.45) !important;
}

.gh-stat-card:hover,
.gh-repo-card:hover,
.edu-card:hover,
.timeline-panel:hover,
.lifestyle-card:hover,
a.portfolio-card:hover,
.portfolio-card:hover,
.skill-badge:hover {
	box-shadow:
		inset 0 1px 0 rgba(212, 175, 106, 0.18),
		0 18px 50px rgba(0, 0, 0, 0.55),
		0 0 28px rgba(212, 175, 106, 0.10) !important;
}

a.portfolio-card.portfolio-card--featured {
	background:
		linear-gradient(180deg, rgba(212, 175, 106, 0.10) 0%, rgba(212, 175, 106, 0) 35%),
		linear-gradient(180deg, rgba(212, 175, 106, 0.022), rgba(7, 7, 10, 0.4)) !important;
	border-color: rgba(212, 175, 106, 0.32) !important;
}

a.portfolio-card.portfolio-card--featured:hover {
	border-color: rgba(212, 175, 106, 0.65) !important;
}

/* ----- Lifestyle, education, repo titles in vellum/brass ----------------- */
.lifestyle-body h5 { color: var(--at-vellum) !important; letter-spacing: 0.04em; }
.lifestyle-body h5 i { color: var(--at-brass-1) !important; opacity: 0.9; }
.edu-card h5 { color: var(--at-vellum) !important; }
.edu-card-icon { color: var(--at-brass-1) !important; }
.edu-extra-tag {
	border: 1px solid rgba(212, 175, 106, 0.22) !important;
	color: rgba(221, 211, 189, 0.55) !important;
}

/* ----- Reduced motion safety --------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
	body::after { display: none; }
}

/* End of Atelier layer */

/* ----- Bookshelf — alignment fix ----------------------------------------- */
/* Original `.book-card { width: 140px }` with a `120px` cover centred inside
   created a 10 px inset that read as misalignment between cards. Collapse
   the card width to match the cover so every cover is flush at the same x-
   position. The text below clamps to `120px` automatically. */
.bookshelf-scroll .book-card {
	width: 120px !important;
}

.bookshelf-scroll .book-cover-wrap {
	margin: 0 0 0.65rem !important;   /* drop the auto-centring; flush to card edge */
	width: 120px;
	/* Open Library cover aspect ratios vary (1:1.32 to 1:1.58). With
	   `object-fit: cover` the title was being clipped on tighter ratios
	   (Psychology of Money was a casualty). Show the full artwork on a
	   dark backdrop instead. */
	background:
		radial-gradient(ellipse at center, rgba(255,255,255,0.04) 0%, rgba(0,0,0,0.45) 100%),
		#0a0b10;
}

.bookshelf-scroll .book-cover-wrap img {
	object-fit: contain !important;
	object-position: center center;
}

/* When there are few cards the centred variant looks tidy; when there are
   many the row scrolls horizontally. The naïve `justify-content: center`
   bug-traps the leftmost card behind the scroll origin (centred overflow
   gets clipped equally on both sides, but you can only scroll right). The
   `safe` keyword tells the browser to fall back to `flex-start` whenever
   content overflows — so 4 cards stay centred and 14 cards align left and
   scroll cleanly. */
.bookshelf--centered .bookshelf-scroll {
	justify-content: safe center;
}

@media (max-width: 575px) {
	.bookshelf--centered .bookshelf-scroll {
		justify-content: flex-start;
	}
}

/* Add a small left padding so the first card doesn't sit awkwardly flush
   against the section's container edge. Mirrors what the filmshelf already
   does via its outer card gap. */
.bookshelf-scroll {
	padding-left: 0.4rem !important;
	padding-right: 0.4rem !important;
}

/* Brass 5★ badge — matches .film-rating exactly so the two shelves share
   a visual vocabulary (rating in the bottom-right of every cover). */
.book-rating {
	position: absolute;
	right: 6px;
	bottom: 6px;
	min-width: 30px;
	height: 22px;
	padding: 0 7px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	background: linear-gradient(180deg, rgba(8, 9, 13, 0.92), rgba(8, 9, 13, 0.96));
	border: 1px solid rgba(181, 151, 96, 0.6);
	border-radius: 999px;
	color: #f5e4b5;
	font-family: var(--font-family-heading);
	font-size: 0.66rem;
	font-weight: 700;
	letter-spacing: 0.04em;
	box-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
	pointer-events: none;
}

.book-rating--reading {
	border-color: rgba(52, 211, 153, 0.6);
	color: #6ee7b7;
	font-size: 0.6rem;
}

/* On hover, 5★ books pick up the brass-rim treatment — same as film-card. */
.book-card--star5:hover .book-cover-wrap {
	box-shadow:
		0 14px 32px rgba(0, 0, 0, 0.7),
		0 0 0 1px rgba(181, 151, 96, 0.55);
}

/* The Berserk card author line is longer than usual; clamp to two lines so
   no single shelf row breaks. */
.book-card--star5 .book-author {
	-webkit-line-clamp: 2;
	display: -webkit-box;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

/* ----- Series-clubbed book card — single cover + "× N vols" badge ------- */
/* When the renderer (or the static-DOM clubber) collapses a multi-volume
   series like Berserk into a single card, we mark it with .book-card--series
   and stamp a brass-toned count badge in the top-left of the cover. The
   badge mirrors `.book-rating` (bottom-right) for visual rhyme — same
   pill, same brass border, same font — so the two corners read as a pair. */
.book-series-count {
	position: absolute;
	left: 6px;
	top: 6px;
	min-width: 30px;
	height: 22px;
	padding: 0 8px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	background: linear-gradient(180deg, rgba(8, 9, 13, 0.92), rgba(8, 9, 13, 0.96));
	border: 1px solid rgba(181, 151, 96, 0.6);
	border-radius: 999px;
	color: #f5e4b5;
	font-family: var(--font-family-heading);
	font-size: 0.62rem;
	font-weight: 700;
	letter-spacing: 0.05em;
	text-transform: lowercase;
	box-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
	pointer-events: none;
}

/* Subtle layered-paper effect so a clubbed series card visibly reads as
   "this is a stack of books" not "this is one book". A pair of pseudo-
   shadows fans out behind the cover. */
.bookshelf-scroll .book-card--series .book-cover-wrap {
	box-shadow:
		0 14px 28px rgba(0, 0, 0, 0.55),
		3px 3px 0 -1px rgba(20, 16, 10, 0.85),
		6px 6px 0 -2px rgba(20, 16, 10, 0.7);
}

.bookshelf-scroll .book-card--series:hover .book-cover-wrap {
	box-shadow:
		0 18px 36px rgba(0, 0, 0, 0.7),
		3px 3px 0 -1px rgba(30, 24, 14, 0.9),
		6px 6px 0 -2px rgba(30, 24, 14, 0.78),
		0 0 0 1px rgba(181, 151, 96, 0.55);
}

/* ----- Section sub-deks — short prose under a `.beyond-sub` heading ----- */
.beyond-sub-dek {
	font-size: 0.86rem;
	color: rgba(255, 255, 255, 0.5);
	letter-spacing: 0.01em;
	margin: -0.5rem auto 1.4rem;
	max-width: 38rem;
}

.beyond-sub-dek .link-amber,
.link-amber {
	color: rgba(212, 175, 106, 0.85);
	text-decoration: none;
	border-bottom: 1px solid rgba(212, 175, 106, 0.35);
	transition: color 0.2s ease, border-color 0.2s ease;
}

.beyond-sub-dek .link-amber:hover,
.link-amber:hover {
	color: #f5e4b5;
	border-bottom-color: rgba(245, 228, 181, 0.7);
}

/* ----- Copyright bar — retired (footer owns the year line now) ---------- */
/* The single-line footer shows year + name + legacy link inline with the
   socials; this old `.copyright` block is only kept here so any cached
   page that still contains the old `<div class="copyright">` markup
   stays invisible instead of stacking under the footer. */

.copyright {
	display: none !important;
	padding: 0 !important;
	margin: 0 !important;
}

.copyright .container {
	position: relative;
}
.copyright .container::before {
	content: '';
	display: block;
	width: clamp(4rem, 12vw, 8rem);
	height: 1px;
	background: linear-gradient(90deg,
		transparent 0%,
		rgba(154, 122, 62, 0.35) 50%,
		transparent 100%);
	margin: 0 auto 1.1rem;
}

.copyright-line {
	display: inline-flex;
	flex-wrap: wrap;
	justify-content: center;
	align-items: center;
	gap: 0.55rem 1rem;
	font-family: var(--font-family-heading);
	font-size: 0.74rem;
	letter-spacing: 0.06em;
	color: rgba(255, 255, 255, 0.55);
	max-width: 100%;
}

.copyright-line .copyright-mark {
	color: rgba(181, 151, 96, 0.85);
	font-weight: 600;
	letter-spacing: 0.04em;
	margin-left: 0.15rem;
}

.copyright-line .copyright-sep {
	color: rgba(154, 122, 62, 0.5);
	font-weight: 400;
}

/* Override the older `.legacy-link` block (mt-0.5rem rule) so it sits inline
   with the copyright on the same line. */
.copyright-line .legacy-link {
	display: inline;
	margin-top: 0;
	font-size: 0.74rem;
	color: rgba(255, 255, 255, 0.55);
	letter-spacing: 0.04em;
	text-decoration: none;
	transition: color 0.25s ease;
}

.copyright-line .legacy-link:hover {
	color: rgba(181, 151, 96, 0.95);
	text-decoration: none;
}

/* Hide the lingering forge-manifesto + atelier-colophon if they ever come
   back in cached HTML — defensive only, current markup doesn't have them. */
.copyright .forge-manifesto,
.copyright .atelier-colophon {
	display: none;
}

/* ----- YouTube video skeleton — shimmer fill while latest videos load ---- */
.beyond-video-skeleton {
	position: absolute;
	inset: 0;
	background: linear-gradient(110deg,
		rgba(255, 255, 255, 0.04) 8%,
		rgba(255, 255, 255, 0.08) 18%,
		rgba(255, 255, 255, 0.04) 33%);
	background-size: 200% 100%;
	animation: shimmer 1.6s linear infinite;
}

/* ============================================================================
   ===== Typography polish — Apple-adjacent display rhythm ===================
   ============================================================================
   Goal: the page reads "premium tech site" rather than "dev resume". Levers:
     1. Inter for headings (geometric, tight; matches Apple/Linear/Stripe).
     2. Tight letter-spacing on big text (-0.02em); slightly loose on body.
     3. Body line-height 1.7 + word-spacing 0.02em for a magazine cadence.
     4. Hairline -0.03em on hero h1 (Apple's signature signature).
     5. OpenType features: kerning, ligatures, contextual alts, tabular-nums
        on metrics, opsz axis for crisp glyph at every size.
   Additive only — every rule below either targets a class that already exists
   or wins via specificity over an earlier-declared shorthand. ============= */

/* Body cadence — Apple's reading text rhythm. Word-spacing is the secret
   ingredient: 0.02em is enough to feel intentional but not a stretch. */
body {
	line-height: 1.7;
	letter-spacing: 0.005em;
	word-spacing: 0.02em;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	text-rendering: optimizeLegibility;
	font-feature-settings: "kern" 1, "liga" 1, "calt" 1;
}

/* Headings — tighter tracking, Inter, no all-caps stretch by default */
h1, h2, h3, h4, h5, h6 {
	letter-spacing: -0.015em;
	font-feature-settings: "kern" 1, "liga" 1, "calt" 1, "ss01" 1;
	font-optical-sizing: auto;
}

/* Hero h1 — the page's biggest moment. Pulls in tighter than other headings. */
.masthead-heading {
	letter-spacing: -0.03em !important;
	font-weight: 700 !important;
	font-size: clamp(2.4rem, 6vw, 4rem) !important;
	line-height: 1.04 !important;
}

/* Subheading — paper-italic-like restraint. Lato's italic is decent. */
.masthead-subheading {
	letter-spacing: -0.01em !important;
	word-spacing: 0.04em;
	font-weight: 300;
	color: rgba(207, 210, 214, 0.85);
}

/* Section headings — pull tracking back from the loose +0.05em the
   blue theme used. Inter's geometric forms read better tight. */
.page-section .page-section-heading {
	letter-spacing: -0.012em !important;
	font-weight: 600 !important;
	font-size: clamp(1.85rem, 3.4vw, 2.6rem) !important;
	line-height: 1.1 !important;
}

/* Body paragraphs in the timeline / portfolio cards / edu cards — give them
   the same comfortable reading rhythm. */
.timeline-panel ul li,
.timeline-panel p,
.edu-card p,
.portfolio-card-body p,
.lifestyle-body p,
.gh-repo-desc {
	line-height: 1.72 !important;
	letter-spacing: 0.005em;
	word-spacing: 0.02em;
}

/* Beyond Code sub-section labels (Reading, Music, Coding Activity, etc.)
   — these are deliberately tracked-caps for editorial contrast against the
   tight Inter headings above. Use Montserrat (kept under --font-family-mono-display)
   so the contrast reads "small caps as section dividers". */
.beyond-sub {
	font-family: var(--font-family-mono-display) !important;
	letter-spacing: 0.28em !important;
	font-size: 0.78rem !important;
	font-weight: 500 !important;
	color: rgba(255, 255, 255, 0.5) !important;
	text-indent: 0.28em;  /* visually re-centre after the trailing tracking */
}

/* Buttons — tracked caps but slightly looser than before (more breathable),
   and tightened weight so they feel premium not chunky. */
.btn,
.btn-outline-light,
.btn-outline-light.btn-sm {
	font-family: var(--font-family-mono-display);
	letter-spacing: 0.18em;
	font-weight: 500;
	font-size: 0.82rem;
}

.btn-outline-light.btn-sm {
	padding: 0.5rem 1.05rem;
}

/* Nav — loosen the link spacing to give them room. */
#mainNav .navbar-nav .nav-link {
	font-family: var(--font-family-mono-display);
	letter-spacing: 0.15em;
	font-weight: 500;
}

/* Numbers (the metrics) — switch to tabular monospaced figures for column
   alignment, and pull spacing in tight so they look like dashboard counters. */
.gh-stat-number,
.lc-bar,
.lc-streak-line,
.gh-langs__summary {
	font-family: var(--font-family-heading);
	font-feature-settings: "tnum" 1, "lnum" 1, "ss01" 1, "kern" 1;
	font-variant-numeric: tabular-nums lining-nums;
	letter-spacing: -0.015em;
}

/* Card titles (timeline h4, edu h5, portfolio h5, etc.) — tighten and uplift. */
.timeline-panel h4,
.edu-card h5,
.portfolio-card-body h5,
.gh-repo-name,
.lifestyle-body h5,
.book-title,
.film-title {
	letter-spacing: -0.012em !important;
}

/* Cmdk + kbd — leave these tracked-caps Montserrat for the keyboard-shortcut
   visual idiom. */
.cmdk-input,
.cmdk-item-title,
.cmdk-kbd,
.cmdk-item-kind {
	font-family: var(--font-family-mono-display);
}

/* Press strip / footer manifesto / copyright — stay tracked Montserrat too. */
.press-strip,
.forge-manifesto,
.copyright-line,
.atelier-colophon {
	font-family: var(--font-family-mono-display);
}

/* Reduce the all-caps shouting on the navbar brand: keep slightly tighter. */
.navbar-brand {
	font-family: var(--font-family-heading);
	letter-spacing: -0.02em;
	font-weight: 700;
}

/* End of Typography polish */

/* ----- Scroll-to-top/bottom FAB — Midnight Forge palette ----------------- */
/* The FAB existed but was rendering invisible because the body::before
   whisper-vignette sits at z-index 9999 (above the FAB's 1042). Bump the
   FAB above the vignette and recolor the ring/icon from steel-blue to brass
   so it matches the rest of the page's atelier palette. */

.scroll-fab {
	z-index: 10000 !important;
	background: rgba(8, 9, 13, 0.78) !important;
	border-color: rgba(154, 122, 62, 0.35) !important;
	box-shadow:
		0 10px 28px rgba(0, 0, 0, 0.55),
		0 0 0 1px rgba(154, 122, 62, 0.15),
		0 0 22px rgba(154, 122, 62, 0.08) !important;
}

.scroll-fab:hover {
	background: rgba(8, 9, 13, 0.92) !important;
	border-color: rgba(181, 151, 96, 0.7) !important;
	box-shadow:
		0 14px 36px rgba(0, 0, 0, 0.6),
		0 0 0 1px rgba(181, 151, 96, 0.45),
		0 0 36px rgba(181, 151, 96, 0.18) !important;
}

.scroll-fab-track {
	stroke: rgba(255, 255, 255, 0.06) !important;
}

.scroll-fab-progress {
	stroke: #b59760 !important;       /* brass progress arc */
	filter: drop-shadow(0 0 4px rgba(181, 151, 96, 0.45));
}

.scroll-fab-icon {
	color: #b59760;
	font-size: 0.92rem;
}

.scroll-fab-icon svg {
	color: inherit;
	fill: currentColor;
}

/* ----- Codeforces card — bump the logo 15% so it fills the card frame
   like StopStalk and the other compact-variant cards. The compact variant
   uses `object-fit: contain`, so without a transform the CF banner reads
   smaller than its peers. ------------------------------------------------- */
.portfolio-card-img--cf {
	background: #ffffff !important;
	padding: 0.9rem 1rem !important;   /* tighter padding since we removed
	                                      the dark-card breathing room */
}

.portfolio-card-img--cf img {
	transform: scale(1.12);
	transition: transform 0.5s ease;
}

/* Preserve the hover-scale on top of the base zoom — it composes (the
   selector below applies an extra `scale(1.08)` from `.portfolio-card:hover
   .portfolio-card-img img`, so on hover the CF logo will land at
   1.12 × 1.08 ≈ 1.21, still in good taste). */
.portfolio-card:hover .portfolio-card-img--cf img {
	transform: scale(1.21);
}

/* ----- Hero avatar — ensure clicks reach it ------------------------------ */
/* The masthead-content::before brass aura at z-index 0 was ending up on
   the same stacking layer as the avatar; with `pointer-events: none` it
   shouldn't intercept, but giving the avatar an explicit z-index removes
   any ambiguity and guarantees its click handler fires. */
.masthead .masthead-avatar.zoomable,
.masthead-avatar.zoomable {
	position: relative;
	z-index: 5;
	cursor: zoom-in !important;
	pointer-events: auto !important;
}

/* The masthead's parallax wrapper (`.masthead-content`) gets a JS-driven
   `transform` on scroll, which establishes a new stacking context. Make sure
   the wrapper itself accepts pointer events — earlier rules elsewhere put a
   blanket pointer-events: none on `body:not(.ready) main`, which (combined
   with the wrapper's transform creating a containing block) was leaving the
   avatar non-clickable until after page-ready. The `pointer-events: auto`
   here is belt-and-braces. */
.masthead .masthead-content {
	pointer-events: auto;
}

/* ----- AOS interaction guarantee --------------------------------------------
   AOS (the scroll-triggered animation library) puts `pointer-events: none`
   on un-animated `[data-aos]` elements and only flips them back to `auto`
   once `aos-animate` is added. If AOS never fires for an element (race
   conditions, intersection-observer not seeing it during a fast scroll, or
   re-init timing), the element stays click-dead forever.

   Force pointer-events back on for the elements that MUST stay clickable
   regardless of animation state (lifestyle photos, portfolio cards, films,
   books, awards, etc.). Visual entry animation still runs; only the click
   gate is removed. */
[data-aos] .lifestyle-img,
[data-aos] .lifestyle-card,
[data-aos].lifestyle-img,
[data-aos] .portfolio-card,
[data-aos] .film-card,
[data-aos] .book-card,
[data-aos] .zoomable,
[data-aos] .zoomable-btn,
[data-aos] .zoomable-figure,
[data-aos] .portfolio-card-img--button,
.lifestyle-img,
.lifestyle-card,
.portfolio-card,
.film-card,
.book-card,
.zoomable-btn,
.zoomable-figure {
	pointer-events: auto !important;
}

/* AOS sets opacity:0 on the parent `[data-aos]` wrapper before animating.
   For the lifestyle row specifically — the user reported the photos never
   become clickable — we ensure the wrapper itself eventually reaches
   opacity 1 even if intersection-observer never fires. AOS will still run
   normally if it does fire (once-mode); this is the failsafe. */
@keyframes aos-failsafe-reveal {
	to { opacity: 1; transform: none; }
}
[data-aos]:not(.aos-animate) {
	animation: aos-failsafe-reveal 0s ease 3s forwards;
}

/* ============================================================================
   ===== Per-repo meta strip + language chips + CP stat cards =================
   ============================================================================
   Replaces the old `.gh-repo-footer` row (single language pill + activity
   indicator) with a richer two-row footer:
     1. `.gh-repo-meta` — LOC count and creation date
     2. `.gh-repo-langs` — up to 3 language chips
   Both populated by JS at runtime via the GitHub API. The static "—"
   placeholders are styled to look intentional even before the fetch lands.

   `.cp-stat-card` is a hoverable variant of `.gh-stat-card` used in the
   competitive-programming section so the four platform numbers behave
   like links (cursor, lift on hover, subtle brass border on focus).
   ============================================================================ */

.gh-repo-meta {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	font-size: 0.72rem;
	color: rgba(255, 255, 255, 0.45);
	padding-top: 0.55rem;
	border-top: 1px solid rgba(255, 255, 255, 0.05);
	letter-spacing: 0.04em;
	margin-top: auto;     /* pin to bottom of flex card */
	font-feature-settings: "tnum" 1, "lnum" 1;
}

.gh-repo-meta__loc,
.gh-repo-meta__date {
	display: inline-flex;
	align-items: center;
	gap: 0.3rem;
	white-space: nowrap;
}

.gh-repo-meta__loc i,
.gh-repo-meta__date i {
	color: rgba(212, 175, 106, 0.55);
	font-size: 0.78em;
}

.gh-repo-langs {
	display: flex;
	flex-wrap: wrap;
	gap: 0.45rem;
	margin-top: 0.6rem;
	min-height: 1.4rem;        /* hold space before fetch lands */
}

.gh-lang-chip {
	display: inline-flex;
	align-items: center;
	gap: 0.32rem;
	font-size: 0.7rem;
	color: rgba(255, 255, 255, 0.55);
	background: rgba(255, 255, 255, 0.03);
	border: 1px solid rgba(255, 255, 255, 0.06);
	padding: 0.18rem 0.55rem;
	border-radius: 999px;
	letter-spacing: 0.02em;
	transition: background 0.25s ease, border-color 0.25s ease, color 0.25s ease;
}
.gh-repo-card:hover .gh-lang-chip {
	background: rgba(255, 255, 255, 0.05);
	border-color: rgba(154, 122, 62, 0.25);
	color: rgba(255, 255, 255, 0.75);
}

/* ----- Competitive-programming stat cards — clickable variant of .gh-stat-card */
.cp-stat-card {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	cursor: pointer;
	text-decoration: none !important;
	transition: transform 0.35s cubic-bezier(0.16, 1, 0.3, 1), background 0.25s ease, border-color 0.25s ease, box-shadow 0.35s ease;
}
.cp-stat-card:hover,
.cp-stat-card:focus {
	transform: translateY(-3px);
	background: rgba(255, 255, 255, 0.04);
	border-color: rgba(154, 122, 62, 0.35);
	box-shadow: 0 10px 26px rgba(0, 0, 0, 0.45),
		0 0 0 1px rgba(154, 122, 62, 0.18);
	text-decoration: none !important;
}
.cp-stat-card .gh-stat-label i {
	color: rgba(212, 175, 106, 0.7);
}

.cp-peak {
	display: block;
	margin-top: 0.4rem;
	font-size: 0.68rem;
	color: rgba(255, 255, 255, 0.45);
	letter-spacing: 0.02em;
}

.cp-peak strong {
	color: rgba(255, 255, 255, 0.75);
}

/* End of Midnight Forge layer */
