/* ==========================================================================
   SAINTCIP - site-specific styles

   Everything custom to this site, on top of the template (helper.css /
   theme.css). Loaded last in index.html, after modal.css, so rules here win
   over the template's.

   Moved here from the inline <style> block that used to live in index.html.
   Rule order is unchanged on purpose - later rules override earlier ones.
   ========================================================================== */

/* Mobile-only notice: this site is designed for desktop viewing.
   Full-bleed white bar at the very top of the page (sits before
   #scroll-container in the markup, so it's unaffected by the
   theme's smooth-scroll transform on the content below it),
   hidden entirely on tablet/desktop. Dismissible; remembered for
   the rest of the browser session via sessionStorage so it
   doesn't reappear on every scroll, but does come back on a
   fresh visit later. */
.mobile-desktop-notice {
	display: none;
}
@media (max-width: 767px) {
	.mobile-desktop-notice {
		display: flex;
		position: relative;
		align-items: center;
		justify-content: center;
		width: 100%;
		padding: 10px 40px;
		background: #FFF;
		box-sizing: border-box;
	}
}
.mobile-desktop-notice.is-dismissed {
	display: none !important;
}
.mobile-desktop-notice-text {
	font-family: 'Poppins', sans-serif;
	font-size: 12px;
	font-weight: 300;
	letter-spacing: 0.3px;
	line-height: 1.3;
	color: #000;
	text-align: center;
}
.mobile-desktop-notice-close {
	position: absolute;
	right: 16px;
	top: 50%;
	transform: translateY(-50%);
	margin: 0;
	padding: 0;
	border: 0;
	background: none;
	font-size: 20px;
	font-weight: 300;
	line-height: 1;
	color: #000;
	cursor: pointer;
}

.hero-video-embed video {
	width: 100%;
	height: 100%;
	object-fit: cover;
	border: 0;
	opacity: 0.9;
	pointer-events: none;
	display: block;
}

/* Footer social icons — clean, professional, responsive */
#tt-footer .footer-social-icons {
	display: flex !important;
	justify-content: center !important;
	gap: clamp(16px, 2vw, 24px) !important;
	margin-top: 18px !important;
}
#tt-footer .footer-social-icons .footer-social-link {
	font-size: clamp(23px, 2.3vw, 31px) !important;
	line-height: 1 !important;
	display: inline-flex !important;
	align-items: center !important;
	justify-content: center !important;
}
#tt-footer .footer-social-icons .footer-social-link i,
#tt-footer .footer-social-icons .footer-social-link svg {
	font-size: inherit !important;
	width: 1em !important;
	height: 1em !important;
}
#tt-footer .footer-social-icons + .tt-copyright,
#tt-footer .tt-copyright {
	padding-top: 8px !important;
	text-align: center !important;
}
#tt-footer .footer-col.tt-align-center .footer-col-inner {
	text-align: center !important;
	width: 100% !important;
}

/* About section: block stays centered on the page, but the text
   itself is left-aligned (not centered/justified) within it. */
.about-section {
	text-align: left;
}

/* Mobile: push the about/main text down from the hero */
@media (max-width: 767px) {
	.about-section {
		padding-top: 5px !important; /* was 15px, cut 65% per request (15 * 0.35 = 5.25, rounded to 5) */
	}
}

/* Client logo carousel: label + a slow, seamless auto-scrolling row of
   big logos. ".about-section" is a flex column with align-items:center
   (theme.css), so without "align-self: stretch" this section shrink-
   wraps to the animated track's full un-clipped width and blows out
   the whole layout — that's the fix for the width:max-content track
   below not to break the page. Track holds the logo set twice, back
   to back, and animates from translateX(0) to translateX(-50%) so the
   loop point is invisible. Placeholder logos — swap the <img> src's
   in the HTML later. */
.clients-marquee-section {
	align-self: stretch;
	width: 100%;
	max-width: 100%;
	margin: 20px 0 24px;
	padding-bottom: 24px;
}
.clients-marquee-label {
	margin: 0 0 10px;
	text-align: center;
	font-size: calc(12px + 0.1vw);
	font-weight: 600;
	letter-spacing: 1.5px;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.5);
}
/* "Some of My Skills" — standalone section label below the brands
   marquee and the "14+ years..." intro paragraph (.skills-intro-
   paragraph, moved here from the top bio block), reuses
   .clients-marquee-label's look with a little extra top spacing. */
.skills-section-label {
	margin-top: 10px;
}
/* "14+ years..." paragraph, relocated here (was originally part of
   the top bio-fade-group) so it introduces "Some of My Skills"
   directly instead of sitting up in the general intro blurb. Reuses
   the same text-xxlg/font-alter/text-gray-2 look as the rest of the
   bio text; .bio-fade-item still drives its fade-in (the reveal
   script below selects .bio-fade-item document-wide, not just
   inside #bio-fade-group). */
.skills-intro-paragraph {
	margin-top: 8px;
}
/* "UI/UX Design" + "Graphic & Visual Design" skill-summary blocks,
   replacing the old "fun fact" paragraph, closing out the About section
   right before "Case Studies" begins. Title (.skills-detail-title)
   reuses the section-label look (.clients-marquee-label, same size as
   "Some of My Skills" / the brands label above — calc(12px + 0.1vw)) per
   request, to match the site's other titles. The paragraph underneath
   (.skills-detail-text) is pinned to calc(100% + 0.7vw) — the same size
   as the rest of the About section's body copy (.text-xxlg) — so the
   list itself still reads consistent with the bio/skills-intro text. */
.skills-detail-group {
	margin-top: 40px;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 28px;
}
.skills-detail-block {
	max-width: 820px;
}
.skills-detail-title {
	margin: 0 0 8px;
	/* font-size intentionally NOT overridden here — inherits
	   .clients-marquee-label's calc(12px + 0.1vw), same size as the
	   site's other section-label titles ("Some of My Skills", the
	   brands label). Only .skills-detail-text below matches the larger
	   About-section body copy size. */
}
/* "Some Logos I've Designed" — 3 auto-scrolling carousel rows above
   "Tools & Technologies I Work With" (same feel as the brands marquee). Each track
   holds its row's logos 8x (so half the track is always wider than
   the screen); animating -50% loops seamlessly with no gap. The
   middle row scrolls the opposite way. Hover pauses that row. */
/* align-self: stretch (here AND on the parent .skills-detail-group)
   is the same fix the brands marquee uses — without it the flex
   parents shrink-wrap to the track's full un-clipped width, so the
   carousel was ~8800px wide and its edge gradients were off-screen. */
.skills-detail-group {
	align-self: stretch;
	width: 100%;
	max-width: 100%;
}
.designed-logos-block {
	align-self: stretch;
	margin: 30px 0 30px;
	width: 100%;
	max-width: 100%;
	min-width: 0;
}
.designed-logos-carousel,
.designed-logos-row {
	min-width: 0;
	max-width: 100%;
}
.designed-logos-carousel {
	position: relative;
	display: flex;
	flex-direction: column;
	gap: 14px;
	margin-top: 18px;
}
/* Black gradient on the left/right ends, spanning all 3 rows. */
.designed-logos-carousel::before,
.designed-logos-carousel::after {
	content: "";
	position: absolute;
	top: 0;
	bottom: 0;
	width: 220px;
	max-width: 22%;
	z-index: 3;
	pointer-events: none;
}
.designed-logos-carousel::before {
	left: 0;
	background: linear-gradient(to right, #000 0%, #000 15%, rgba(0, 0, 0, 0) 100%);
}
.designed-logos-carousel::after {
	right: 0;
	background: linear-gradient(to left, #000 0%, #000 15%, rgba(0, 0, 0, 0) 100%);
}
/* Fade to black at the left/right ends. Uses a mask on the row itself
   (instead of black overlay gradients) so the logos truly fade out
   into whatever is behind them. */
.designed-logos-row {
	position: relative;
	overflow: hidden;
	width: 100%;
}
.designed-logos-track {
	display: flex;
	align-items: center;
	width: max-content;
	animation: designed-logos-scroll 55s linear infinite;
	will-change: transform;
	backface-visibility: hidden;
}
.designed-logos-row--reverse .designed-logos-track {
	animation-direction: reverse;
}
.designed-logos-row:hover .designed-logos-track {
	animation-play-state: paused;
}
/* Spacing via margin (not flex gap) so the -50% loop point lands exactly. */
/* Size + look matched to the brands marquee (.clients-marquee-track):
   200px logos, 60px spacing, gray/dimmed until hover. */
.designed-logos-item {
	flex: none;
	width: 110px;
	height: 110px;
	margin-right: 48px;
	display: flex;
	align-items: center;
	justify-content: center;
}
.designed-logos-item img {
	max-width: 100%;
	max-height: 100%;
	object-fit: contain;
	filter: grayscale(100%) brightness(0.8);
	opacity: 0.7;
	transition: filter 0.3s ease, opacity 0.3s ease;
	user-select: none;
	pointer-events: none;
}
.designed-logos-item:hover img {
	filter: grayscale(0%) brightness(1.3);
	opacity: 1;
}
@keyframes designed-logos-scroll {
	from { transform: translate3d(0, 0, 0); }
	to { transform: translate3d(-50%, 0, 0); }
}
@media (prefers-reduced-motion: reduce) {
	.designed-logos-track {
		animation: none;
	}
}
@media (max-width: 767px) {
	.designed-logos-carousel::before,
	.designed-logos-carousel::after {
		width: 70px;
	}
	.designed-logos-carousel {
		gap: 10px;
	}
	.designed-logos-track {
		animation-duration: 50s;
	}
	.designed-logos-item {
		width: 72px;
		height: 72px;
		margin-right: 26px;
	}
}
.skills-detail-text {
	margin: 0;
	text-align: center;
	color: #CCC;
	font-family: 'Noto Serif JP', serif;
	font-size: calc(100% + 0.7vw);
	line-height: 1.6;
}
/* Photoshop / Illustrator / Blender tiles that drop in with gravity and
   can be grabbed and thrown around (Matter.js physics — same mechanism
   as the "Services We Offer" section on sharpstudiollc.com). Container
   stays pointer-events:none so empty space never blocks page scroll;
   each tile opts back in with pointer-events:auto so it's still
   grabbable. */
.skills-throwable-scene {
	align-self: stretch;
	position: relative;
	width: 100%;
	height: 265px; /* was 315px — cut to halve the empty space above the settled icons (~143px -> ~67px) */
	margin-top: 20px;
	overflow: hidden;
	pointer-events: none;
}
.skills-throwable-el {
	position: absolute;
	top: 0;
	left: 0;
	width: 72px;
	height: 72px;
	opacity: 0;
	pointer-events: auto;
	cursor: grab;
	-webkit-user-select: none;
	user-select: none;
	touch-action: none;
}
.skills-throwable-el:active {
	cursor: grabbing;
}
.skills-throwable-el-rot {
	display: block;
	width: 100%;
	height: 100%;
	transform: translate(-50%, -50%);
}
.skills-throwable-el img {
	display: block;
	width: 100%;
	height: 100%;
	pointer-events: none;
	border-radius: 0;
	box-shadow: 0 10px 24px rgba(0, 0, 0, 0.45);
}
/* Name tooltip: covers the icon (not floating above/below it) so it
   can never get clipped by ".skills-throwable-scene"'s overflow:
   hidden, since icons can land anywhere in the scene including right
   at the top/bottom edge. ".skills-throwable-el-rot" already gets a
   non-"none" transform each physics tick, which makes it a
   positioning context for this "inset:0" overlay for free. */
.skills-throwable-el-label {
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	text-align: center;
	padding: 6px;
	background: rgba(0, 0, 0, 0.85);
	color: #FFF;
	font-family: 'Poppins', sans-serif;
	font-size: 11px;
	font-weight: 600;
	line-height: 1.25;
	opacity: 0;
	pointer-events: none;
	transition: opacity 0.2s ease;
}
.skills-throwable-el:hover .skills-throwable-el-label {
	opacity: 1;
}
@media (max-width: 767px) {
	.skills-throwable-scene {
		/* 390px originally, then 315px, now 275px: each step cuts the empty
		   space above the settled icons roughly in half (on a typical phone
		   it is now about 55px, from about 110px). The icons land a little
		   differently every time, so this is as short as the box can go
		   before one occasionally ends up cut off at the top. */
		height: 275px;
	}
	.skills-throwable-el {
		width: 56px;
		height: 56px;
	}
	.skills-throwable-el-label {
		font-size: 9px;
		padding: 3px;
	}
}
/* Narrower phones fit fewer icons per row, so the pile is taller and
   needs a slightly taller box to keep every icon inside it. */
@media (max-width: 374px) {
	.skills-throwable-scene {
		height: 285px;
	}
}
@media (max-width: 339px) {
	.skills-throwable-scene {
		height: 305px;
	}
}
.clients-marquee {
	position: relative;
	overflow: hidden;
	width: 100%;
	max-width: 100%;
}
/* Fade the logos to black at the far left/right edges instead of a
   hard cutoff. Plain overlay divs (not mask-image) so they can't
   interfere with the flex/shrink-to-fit sizing of ".clients-marquee". */
.clients-marquee::before,
.clients-marquee::after {
	content: "";
	position: absolute;
	top: 0;
	bottom: 0;
	width: 120px;
	max-width: 15%;
	z-index: 2;
	pointer-events: none;
}
.clients-marquee::before {
	left: 0;
	background: linear-gradient(to right, #000 0%, rgba(0, 0, 0, 0) 100%);
}
.clients-marquee::after {
	right: 0;
	background: linear-gradient(to left, #000 0%, rgba(0, 0, 0, 0) 100%);
}
@media (max-width: 767px) {
	.clients-marquee::before,
	.clients-marquee::after {
		width: 48px;
	}
}
.clients-marquee-track {
	display: flex;
	align-items: center;
	width: max-content;
	gap: 60px;
	animation: clients-marquee-scroll 90s linear infinite;
	will-change: transform;
	backface-visibility: hidden;
}
.clients-marquee:hover .clients-marquee-track {
	animation-play-state: paused;
}
/* Logos are wrapped in <a> tags (click through to the client's site),
   so the anchor is now the flex item and carries the cursor. */
.clients-marquee-track a {
	display: block;
	flex: none;
	cursor: pointer;
}
.clients-marquee-track img {
	display: block;
	height: 200px;
	width: 200px;
	object-fit: contain;
	pointer-events: none;
	filter: grayscale(100%) brightness(0.8);
	opacity: 0.7;
	transition: filter 0.3s ease, opacity 0.3s ease;
}
.clients-marquee-track a:hover img {
	filter: grayscale(0%) brightness(1.3);
	opacity: 1;
}
@keyframes clients-marquee-scroll {
	from { transform: translate3d(0, 0, 0); }
	to { transform: translate3d(-50%, 0, 0); }
}
@media (prefers-reduced-motion: reduce) {
	.clients-marquee-track {
		animation: none;
	}
}
@media (max-width: 767px) {
	.clients-marquee-section {
		margin: 16px 0 20px;
	}
	.clients-marquee-track {
		gap: 32px;
		animation-duration: 65s;
	}
	.clients-marquee-track img {
		height: 130px;
		width: 130px;
	}
}

/* Tighten the gap before the "Selected Work" heading below. */
/* Top padding above the "About" section (the gap between the hero and
   the signature/bio intro) — was the theme's default .tt-section
   padding-top (80px desktop, 6% <=991px, 10% <=767px, 15% <=480px, see
   theme.css); cut by 65% per request (each value x0.35), same
   responsive shape kept via the media queries below. */
#about-outer-section {
	padding-top: 28px !important;
	padding-bottom: 20px !important;
}
@media (max-width: 991px) {
	#about-outer-section {
		padding-top: 2.1% !important;
	}
}
@media (max-width: 767px) {
	#about-outer-section {
		padding-top: 3.5% !important;
	}
}
@media (max-width: 480px) {
	#about-outer-section {
		padding-top: 5.25% !important;
	}
}
#portfolio-outer-section {
	padding-top: 50px !important;
	padding-bottom: 20px !important;
}

/* Bio intro paragraphs (Marcos Cipriano + the two lines under it):
   fade up one by one only once the section is actually scrolled into
   view (IntersectionObserver below), same reveal pattern as the
   skill pillars — replaces the old GSAP "anim-fadeinup", which could
   fire immediately on load if the section was already within the
   initial viewport instead of waiting for a real scroll. */
.bio-fade-item {
	opacity: 0;
	transform: translateY(40px);
	transition: opacity 0.9s cubic-bezier(0.16, 1, 0.3, 1), transform 0.9s cubic-bezier(0.16, 1, 0.3, 1);
}
.bio-fade-item.is-revealed {
	opacity: 1;
	transform: translateY(0);
}

/* Keeps the subtitle a normal inline element (not block) at every
   viewport width. */
.typewriter-text {
	display: inline;
}

/* On phone, keep the subtitle on a single line. Font size is
   inherited from the bio block (.text-xxlg) so it matches the
   description paragraph below it. */
@media (max-width: 767px) {
	#typewriter-subtitle {
		display: inline-block;
		white-space: nowrap;
	}
}

/* "Scroll down" button: pinned to the bottom-centre of the screen while
   the visitor is on the hero. Hidden until they've been at the top of
   the page for 3 seconds without scrolling, and hidden again the moment
   they scroll (timing lives in assets/js/site.js). position:fixed so it
   sits at the bottom of the *screen* on every device, whatever the hero
   height is. Base ".made-with-love" opacity is .5 when visible, so fade
   between 0 and that, not 0/1; full white on hover. Clicking it scrolls
   down to the content below the hero. */
.made-with-love.scroll-hint {
	position: fixed;
	left: 50%;
	right: auto;
	bottom: calc(32px + env(safe-area-inset-bottom, 0px));
	transform: translateX(-50%);
	padding: 8px 14px;
	white-space: nowrap;
	cursor: pointer;
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
	/* fades out fast when the user starts scrolling */
	transition: opacity 0.25s ease, visibility 0s linear 0.25s;
}
.made-with-love.scroll-hint.is-visible {
	opacity: .5;
	visibility: visible;
	pointer-events: auto;
	/* fades in gently */
	transition: opacity 0.8s ease, visibility 0s;
}
.made-with-love.scroll-hint.is-visible:hover,
.made-with-love.scroll-hint.is-visible:focus-visible {
	opacity: 1;
}
/* The theme rotates this label 90deg (it used to run up the right edge
   of the hero); keep it horizontal now that it's at the bottom. */
.made-with-love.scroll-hint .mwl-inner {
	transform: none;
	justify-content: center;
}

/* Portfolio grid images: smooth fade-up reveal. Hidden by default,
   revealed by adding "is-revealed" (see IntersectionObserver script). */
#portfolio-grid .ttgr-item-inner {
	opacity: 0;
	transform: translateY(40px);
	transition: opacity 0.9s cubic-bezier(0.16, 1, 0.3, 1), transform 0.9s cubic-bezier(0.16, 1, 0.3, 1);
}
#portfolio-grid .ttgr-item-inner.is-revealed {
	opacity: 1;
	transform: translateY(0);
}

/* Portfolio grid caption: plain, no overlay/hover effects at all —
   title sits in normal flow directly under the image (theme default
   for #portfolio-grid without "pgi-cap-inside"/"pgi-cap-hover"), and
   the project's tag renders small + grey right under the title via
   the theme's own .pgi-categories-wrap/.pgi-category pattern. Only
   overriding the title size down from the theme's very large
   default so it reads as a caption, not a heading. */
#portfolio-grid .pgi-title {
	font-size: calc(15px + 0.2vw);
}

/* Title row: project name + its date, same line. Date is smaller
   and grey (reuses .pgi-category's opacity), sits to the right of
   the title. ".pgi-title" keeps min-width:0 + flex so its existing
   ellipsis/nowrap truncation still wins over the date for long
   names; the date itself never shrinks/wraps. */
#portfolio-grid .pgi-title-row {
	display: flex;
	align-items: baseline;
	gap: 8px;
}
#portfolio-grid .pgi-title-row .pgi-title {
	flex: 0 1 auto;
	min-width: 0;
}
#portfolio-grid .pgi-date {
	flex-shrink: 0;
	font-size: calc(11px + 0.1vw);
	color: #FFF;
	opacity: .5;
	white-space: nowrap;
}

/* Caption row: title/tag on the left, a "Case Study" outline button
   on the right — vertically centered against, and stretched to,
   the same height as the title+tag text block (align-items:
   stretch on the row + the button centering its own label inside
   whatever height that gives it). ".pgi-caption-text" gets
   min-width:0 so the title's existing ellipsis truncation still
   works with a flex sibling next to it. */
#portfolio-grid .pgi-caption-inner {
	display: flex;
	align-items: stretch;
	justify-content: space-between;
	gap: 16px;
}
#portfolio-grid .pgi-caption-text {
	flex: 1 1 auto;
	min-width: 0;
}
/* "Case Study" button: minimalist outline, small arrow on the right
   (CSS-only, via ::after so no extra markup) that nudges further
   right on hover, when the outline also brightens to full white —
   the whole card (button included, since it's a plain descendant
   of ".portfolio-grid-item") is already the click target that
   opens item.link, see the click-delegation script near the end
   of the page. */
#portfolio-grid .pgi-case-study-btn {
	flex-shrink: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	padding: 0 20px;
	border: 1px solid rgba(255, 255, 255, 0.35);
	border-radius: 0;
	font-family: 'Poppins', sans-serif;
	font-size: calc(11px + 0.1vw);
	font-weight: 600;
	letter-spacing: 0.5px;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.75);
	white-space: nowrap;
	cursor: pointer;
	transition: border-color 0.25s ease, color 0.25s ease;
}
#portfolio-grid .pgi-case-study-btn::after {
	content: "\2192";
	display: inline-block;
	font-weight: 400;
	transition: transform 0.25s ease;
}
#portfolio-grid .pgi-case-study-btn:hover {
	border-color: #FFF;
	color: #FFF;
}
#portfolio-grid .pgi-case-study-btn:hover::after {
	transform: translateX(3px);
}
@media (max-width: 767px) {
	#portfolio-grid .pgi-case-study-btn {
		padding: 0 14px;
		font-size: 10px;
	}
}

/* Role + short description under the caption row. Same small grey
   type as the tag (.pgi-category: calc(13px + 0.1vw), white at 50%)
   so it reads as part of the existing caption; the "Role:" line is
   a touch brighter. Sits BELOW .pgi-caption-inner (not inside it)
   so the "Case Study" button keeps its title+tag height. */
#portfolio-grid .pgi-desc {
	margin: 14px 0 0;
	font-size: calc(13px + 0.1vw);
	line-height: 1.6;
	color: rgba(255, 255, 255, 0.5);
}
#portfolio-grid .pgi-desc-role {
	display: block;
	margin-bottom: 2px;
	color: rgba(255, 255, 255, 0.8);
}
@media (max-width: 767px) {
	#portfolio-grid .pgi-desc {
		margin-top: 12px;
	}
}

/* Wide screens show the three case studies in one row ("ttgr-layout-3"
   on the grid, three across from 1200px up), which makes each card
   narrower. With the "Case Study" button sitting beside the title there
   wasn't room for names like "Nakamoto Capital" — they were cut off with
   "...". So on those screens the title (and year) gets the full width of
   the card, and the button moves down next to the category line, a bit
   more compact. Below 1200px the cards are wider and keep the layout
   above. */
@media (min-width: 1200px) {
	#portfolio-grid .pgi-caption-inner {
		display: grid;
		grid-template-columns: minmax(0, 1fr) auto;
		align-items: center;
		column-gap: 16px;
		row-gap: 4px;
	}
	#portfolio-grid .pgi-caption-text {
		display: contents; /* its two lines (title row, category) are placed in the grid directly */
	}
	#portfolio-grid .pgi-title-row {
		grid-column: 1 / -1;
	}
	#portfolio-grid .pgi-categories-wrap {
		grid-column: 1;
		min-width: 0;
	}
	#portfolio-grid .pgi-case-study-btn {
		grid-column: 2;
		padding: 9px 16px;
	}
}

/* Portfolio section title — centered above the grid. */
.portfolio-section-heading {
	margin: 0 0 50px;
	text-align: center;
}
.portfolio-section-title {
	margin: 0 auto;
	max-width: 620px;
	font-family: 'Poppins', sans-serif;
	font-size: calc(12px + 0.1vw);
	font-weight: 600;
	letter-spacing: 1.5px;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.5);
	line-height: 1.4;
}
@media (max-width: 767px) {
	.portfolio-section-heading {
		margin-bottom: 32px;
		padding: 0 4vw;
	}
}

/* "Marcos Cipriano" signature image in the bio intro — replaces the
   plain text name. Scales with viewport like the old text heading
   did, and sits with a small negative margin so its bottom strokes
   overlap slightly onto the subtitle line below it. */
.name-signature {
	display: block;
	width: clamp(300px, 38vw, 520px);
	height: auto;
	margin: 24px auto -55px;
}
@media (max-width: 767px) {
	.name-signature {
		margin-bottom: -35px;
	}
}

/* "Thanks for stopping by" — closes out the page (now sits AFTER the
   testimonials, per request; the "explore more..." quote that used to
   live here moved out to its own button between the cards and the
   testimonials, see .explore-more-btn below). */
.portfolio-thanks-wrap {
	margin-top: 90px;
	text-align: center;
}
.portfolio-thanks-title {
	margin: 0 0 12px;
	font-family: 'Noto Serif JP', serif;
	font-size: clamp(40px, 6vw, 72px);
	font-weight: 600;
	color: #FFF;
	line-height: 1.3;
}
.portfolio-thanks-subtitle {
	margin: 0;
	font-family: 'Noto Serif JP', serif;
	font-size: calc(14px + 0.1vw);
	color: rgba(255, 255, 255, 0.6);
}
/* Email — white + underlined + clickable (mailto), called out against
   the muted subtitle text around it, same treatment the Instagram
   "click here" text used to get before that moved to its own button. */
.portfolio-thanks-email {
	color: #FFF;
	text-decoration: underline;
	text-underline-offset: 3px;
	cursor: pointer;
}
.portfolio-thanks-email:hover {
	opacity: .8;
}
@media (max-width: 767px) {
	.portfolio-thanks-wrap {
		margin-top: 60px;
	}
}

/* Bottom gap (subtitle -> footer). */
#creative-projects-outer-section {
	padding-bottom: 90px;
}
@media (min-width: 1025px) {
	#creative-projects-outer-section {
		padding-bottom: 130px;
	}
}
@media (max-width: 767px) {
	#creative-projects-outer-section {
		padding-bottom: 60px;
	}
}

/* "Explore more of my work" — was a plain "clickable quote" line inside
   the Thank You block; per request (2026-08-31) it's now styled as an
   actual button and moved to stand on its own between the portfolio
   grid and the testimonials. Flat outline + arrow, same visual language
   as the portfolio cards' "Case Study" button (border-radius:0, border
   brightens + arrow nudges right on hover). */
#explore-more-outer-section {
	padding-top: 20px;
	padding-bottom: 20px;
}
.explore-more-wrap {
	display: flex;
	justify-content: center;
}
.explore-more-btn {
	display: inline-flex;
	align-items: center;
	gap: 12px;
	padding: 16px 32px;
	border: 1px solid rgba(255, 255, 255, 0.35);
	border-radius: 0;
	color: #FFF;
	text-decoration: none;
	font-family: 'Noto Serif JP', serif;
	font-size: calc(14px + 0.1vw);
	transition: border-color 0.3s ease, background-color 0.3s ease;
}
.explore-more-btn:hover,
.explore-more-btn:focus-visible {
	border-color: #FFF;
	background-color: rgba(255, 255, 255, 0.05);
}
.explore-more-btn-arrow {
	transition: transform 0.3s ease;
}
.explore-more-btn:hover .explore-more-btn-arrow {
	transform: translateX(3px);
}

/* Testimonials — carousel (Swiper, already loaded elsewhere in the
   theme for the shop/portfolio sliders), between the "explore more of
   my work" button and the "Thank You!" block. PLACEHOLDER quotes/
   names/companies/avatars (assets/img/testimonials/testimonial-1..5.svg,
   flat monochrome initials tiles matching the site's no-rounded-corner
   look) — swap in real client testimonials + photos later; see
   testimonials_section.md project note.

   Centered/"peek" layout (2026-08-31, per request): slidesPerView is
   fractional + centeredSlides:true (set in the Swiper init JS near the
   end of the page), so neighboring slides show partial slivers on both
   sides instead of one full-bleed slide. .testimonials-fade-left/-right
   are flat gradient-to-#000 overlays (matches the page's pure black
   background) so those peeking slides visually fade into the edges
   instead of getting a hard clip. Non-active slides are also dimmed via
   opacity so the centered/active testimonial reads clearly as "the one
   in focus". Nav arrows removed per request — pagination bars plus
   swipe/drag/keyboard remain as the controls. */
#testimonials-outer-section {
	padding-top: 60px;
	padding-bottom: 90px;
}
@media (max-width: 767px) {
	#testimonials-outer-section {
		padding-top: 40px;
		padding-bottom: 60px;
	}
}
.testimonials-carousel {
	position: relative;
	width: 100%;
	margin-top: 36px;
}
.testimonials-carousel .swiper-slide {
	opacity: 0.35;
	transition: opacity 0.4s ease;
}
.testimonials-carousel .swiper-slide-active {
	opacity: 1;
}
.testimonial-slide {
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: center;
	padding: 0 20px;
	max-width: 480px;
	margin: 0 auto;
}
.testimonial-quote {
	font-family: 'Noto Serif JP', serif;
	font-size: clamp(15px, calc(85% + 0.4vw), 19px);
	color: #CCC;
	line-height: 1.6;
	margin: 0 0 20px;
}
.testimonial-quote::before {
	content: '\201C';
}
.testimonial-quote::after {
	content: '\201D';
}
.testimonial-author {
	display: flex;
	flex-direction: row;
	align-items: center;
	justify-content: center;
	gap: 14px;
}
.testimonial-avatar {
	width: 44px;
	height: 44px;
	display: block;
	flex-shrink: 0;
	border-radius: 50%;
	object-fit: cover;
}
/* Name + title: always left-aligned next to the avatar, on every slide.
   text-align:left is needed because the slide itself is text-align:center,
   so a title long enough to wrap onto two lines (Lou's) used to have its
   lines centred while the one-line titles looked left-aligned.
   Long titles carry a <br> in the markup at the spot where they should
   break: that keeps the text block only as wide as its longest line, so
   the avatar + text pair stays centred under the quote like the others. */
.testimonial-author-text {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	justify-content: center;
	gap: 2px;
	text-align: left;
}
.testimonial-name {
	font-size: calc(12px + 0.1vw);
	font-weight: 600;
	color: #FFF;
	text-decoration: none;
}
.testimonial-name:hover,
.testimonial-name:focus-visible {
	text-decoration: underline;
}
.testimonial-company {
	font-size: calc(10px + 0.1vw);
	color: rgba(255, 255, 255, 0.5);
	text-transform: uppercase;
	letter-spacing: 1px;
	line-height: 1.4;
}
/* <br class="testimonial-br-mobile"> = a line break that only applies on
   phones, for titles that fit on one line on bigger screens. */
.testimonial-company br.testimonial-br-mobile {
	display: none;
}
@media (max-width: 480px) {
	.testimonial-company br.testimonial-br-mobile {
		display: inline;
	}
}
/* Fade-to-black edges — flat gradients to #000 (the page's own
   background), pointer-events:none so clicks/drags pass through to the
   carousel underneath. */
.testimonials-fade {
	position: absolute;
	top: 0;
	bottom: 0;
	width: 7%; /* was 14%, cut 50% per request */
	min-width: 20px; /* was 40px */
	max-width: 80px; /* was 160px */
	z-index: 2;
	pointer-events: none;
}
.testimonials-fade-left {
	left: 0;
	background: linear-gradient(to right, #000 0%, rgba(0, 0, 0, 0) 100%);
}
.testimonials-fade-right {
	right: 0;
	background: linear-gradient(to left, #000 0%, rgba(0, 0, 0, 0) 100%);
}

/* Portfolio items read as clickable — either a real case-study link
   or an "under construction" notice for projects that don't have
   one yet. */
.portfolio-grid-item[data-link],
.portfolio-grid-item[data-under-construction] {
	cursor: pointer;
}

/* ==========================================================================
   Polaroid carousel — every portfolio piece as an instant photo, in the
   About section between the "14+ years..." paragraph and "Fun Fact About
   Me". Off-white cards with a wide bottom edge and a handwritten name,
   each tilted a little differently; three across on desktop, and on phones
   one in the middle with half of the next one on each side, fading to
   black. They slide on by themselves. Hovering one straightens and lifts it and turns the
   others black and white.
   The sliding is done by Swiper (see "Polaroid carousel" in
   assets/js/site.js). ".about-section" is a flex column that centres its
   children, hence align-self:stretch so the carousel can use the full
   width.
   ========================================================================== */
/* Title above the carousel — the same section-label look as "Some Logos
   I've Designed:" and "Tools & Technologies I Work With:"
   (.clients-marquee-label). */
.polaroid-title {
	margin-top: 10px;
	margin-bottom: 0;
}
.polaroid-row {
	align-self: stretch;
	width: 100%;
	margin: 0; /* the space under the title is the carousel's own top padding below */
	/* Room above and below for the tilt, the hover lift and the shadow —
	   the carousel hides anything that sticks out of its box. */
	padding: 22px 0 30px;
	cursor: grab;
}
.polaroid-row:active {
	cursor: grabbing;
}
/* One slide = one polaroid, centred, with a little space either side. The
   widths here (a third / a half) only matter for the instant before the
   carousel starts up; after that Swiper sets them itself. */
.polaroid-row .swiper-slide {
	display: flex;
	justify-content: center;
	box-sizing: border-box;
	width: 33.3333%;
	height: auto;
	padding: 0 13px;
}
.polaroid {
	flex: none;
	width: 100%;
	max-width: 240px; /* three across on desktop (was 196px with four) */
	margin: 0;
	container-type: inline-size; /* lets the caption size its writing from the card's width */
	transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1);
	will-change: transform;
}
/* The card itself. Its padding is a share of its own width, so the white
   border keeps the same proportions at any size. */
.polaroid-card {
	padding: 5.5% 5.5% 3%; /* the wide bottom edge is the caption below */
	background: linear-gradient(180deg, #F4F4F2 0%, #E9E9E6 100%);
	box-shadow: 0 1px 2px rgba(0, 0, 0, 0.5), 0 18px 34px rgba(0, 0, 0, 0.55), inset 0 0 0 1px rgba(255, 255, 255, 0.35);
}
.polaroid img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 702 / 650;
	object-fit: cover;
	box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.08);
	-webkit-user-select: none;
	user-select: none;
	transition: filter 0.4s ease;
}
/* Handwritten project name on the wide bottom edge. The box is as wide as
   the photo and a fixed share of that tall, so the card keeps its polaroid
   proportions; the name sits centred in it, on one line, tilted a touch
   like real handwriting. Font: Caveat (loaded in the <head> of index.html). */
.polaroid-caption {
	display: flex;
	align-items: center;
	justify-content: center;
	aspect-ratio: 100 / 22.5;
	margin: 0;
	padding: 0 2px;
	overflow: hidden;
	white-space: nowrap;
	font-family: 'Caveat', 'Bradley Hand', 'Segoe Print', cursive;
	/* "--fit" is normally 1. For a name too long for its card, site.js sets
	   it a little lower so the writing shrinks just enough to fit. */
	font-size: calc(20px * var(--fit, 1));       /* for older browsers */
	font-size: calc(10.3cqw * var(--fit, 1));    /* 10.3cqw = 10.3% of the polaroid's width, so the writing scales with the card */
	font-weight: 600;
	font-style: normal;
	line-height: 1;
	letter-spacing: 0.2px;
	text-align: center;
	color: #26231F;
	transform: rotate(-1.5deg);
	/* The template styles every <figcaption> as a dark, italic box pinned to
	   the corner of its figure; switch all of that off here. */
	position: static;
	max-width: none;
	background: none;
	opacity: 1;
	z-index: auto;
}
.polaroid-row .swiper-slide:nth-child(even) .polaroid-caption {
	transform: rotate(1deg);
}
/* The year after the name: a little smaller and in lighter ink. */
.polaroid-year {
	margin-left: 0.25em;
	font-size: 0.86em;
	color: rgba(38, 35, 31, 0.62);
}
/* A different tilt (and a small nudge up or down) from one to the next. */
.polaroid-row .swiper-slide:nth-child(5n + 1) .polaroid { transform: rotate(-3.2deg) translateY(4px); }
.polaroid-row .swiper-slide:nth-child(5n + 2) .polaroid { transform: rotate(1.3deg) translateY(-3px); }
.polaroid-row .swiper-slide:nth-child(5n + 3) .polaroid { transform: rotate(-1.4deg) translateY(5px); }
.polaroid-row .swiper-slide:nth-child(5n + 4) .polaroid { transform: rotate(2.6deg) translateY(-2px); }
.polaroid-row .swiper-slide:nth-child(5n + 5) .polaroid { transform: rotate(-2.2deg) translateY(1px); }
@media (hover: hover) {
	.polaroid-row .swiper-slide .polaroid:hover {
		transform: rotate(0deg) translateY(-8px) scale(1.05);
		position: relative;
		z-index: 2;
	}
	/* While one polaroid is hovered, the photos on the others turn black and white. */
	.polaroid-row:has(.polaroid:hover) .polaroid:not(:hover) img {
		filter: grayscale(1);
	}
}
/* Phones: one polaroid in the middle, half of the next one on each side,
   and the two sides fading to black (the page background). The fades are
   drawn over the carousel and let touches straight through. */
@media (max-width: 767px) {
	.polaroid-row {
		padding: 18px 0 22px;
	}
	.polaroid-row::before,
	.polaroid-row::after {
		content: "";
		position: absolute;
		top: 0;
		bottom: 0;
		width: 22%;          /* = the part of the neighbouring polaroid that shows on that side */
		z-index: 3;
		pointer-events: none;
	}
	.polaroid-row::before {
		left: 0;
		background: linear-gradient(to right, #000 0%, rgba(0, 0, 0, 0.75) 35%, rgba(0, 0, 0, 0) 100%);
	}
	.polaroid-row::after {
		right: 0;
		background: linear-gradient(to left, #000 0%, rgba(0, 0, 0, 0.75) 35%, rgba(0, 0, 0, 0) 100%);
	}
	.polaroid-row .swiper-slide {
		width: 55.5556%;     /* 1 / 1.8, to match slidesPerView in site.js */
		padding: 0 5px;      /* gap between polaroids = twice this (was 10px each side) */
	}
	.polaroid {
		max-width: 210px;    /* was 170px */
	}
	.polaroid-caption {
		font-size: calc(17px * var(--fit, 1));       /* older browsers only; newer ones use the 10.3cqw above */
		font-size: calc(10.3cqw * var(--fit, 1));
	}
}

/* ==========================================================================
   "Tools & Technologies I Work With" (the falling icons) now has its own
   section after the case studies, right above the "explore more of my
   creative work" button. Only the spacing around it is set here; the
   icons themselves are styled further up (".skills-throwable-...").
   ========================================================================== */
/* Gap between the last case study and the "Tools & Technologies" title:
   cut by 65% per request. Most of that gap is not on this section at all —
   it is the space the case-study grid leaves under its last row of cards
   (6% of the screen width; 5% on phones), plus 70px of section padding. So
   to end up with 35% of the old total, this section drops its own top
   padding (was 40px) and is pulled up into that empty space with a
   negative margin that scales with the screen the same way the grid's
   space does. (Old gap: 6vw + 70px. New gap: 35% of that.) */
#tools-outer-section {
	padding-top: 0;
	margin-top: calc(-5.5px - 3.9vw);
	padding-bottom: 30px;
}
@media (max-width: 768px) {
	#tools-outer-section {
		margin-top: calc(-5.5px - 3.25vw);
	}
}
/* Keep the same 30px between the label and the icons that they had in
   the About section (there the two margins added up; here they overlap). */
.tools-section .skills-throwable-scene {
	margin-top: 30px;
}
