/* ==========================================================================
   Justin Allen Cruz — Portfolio
   ========================================================================== */

:root {
  --cream: #f6f1e8;
  --cream-deep: #efe7d9;
  --ink: #2b2317;
  --ink-soft: #5c5140;
  --accent: #8a6f4d;
  --line: rgba(43, 35, 23, 0.18);
  --white: #ffffff;
  --hero-text: #eceae4;
  --nav-h: 5.25rem;
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  scroll-padding-top: var(--nav-h);
  /* Clip horizontal overflow at the ROOT so nothing can be swiped sideways.
     `clip` (not `hidden`) doesn't create a scroll container, so vertical
     scroll, scroll-snap and scroll-padding all keep working — and unlike
     body's clip it also reins in position:fixed layers (hero, resume modal).
     overscroll-behavior-x kills the sideways rubber-band bounce on mobile. */
  overflow-x: clip;
  overscroll-behavior-x: none;
}

/* Zoom-out lock: past the 1920px design width (ultra-wide screens or the
   browser zoomed out), the root font grows proportionally with the viewport.
   Every rem-based size — layout caps, cards, images — scales with it, so the
   composition stays visually locked at its 100% look instead of shrinking
   and revealing multiple slides. (1920 / 16px root = 120.) */
@media (min-width: 1921px) {
  html { font-size: calc(100vw / 120); }
}

/* Desktop: when the user stops scrolling near a slide boundary, the page
   gently settles on that slide's start ("proximity" never traps the scroll
   inside long sections the way "mandatory" can). */
@media (min-width: 769px) {
  html { scroll-snap-type: y proximity; }

  .hero,
  .about,
  .section {
    scroll-snap-align: start;
  }
}

body {
  font-family: "Poppins", system-ui, -apple-system, "Segoe UI", sans-serif;
  background: var(--cream);
  color: var(--ink);
  overflow-x: clip;
  overscroll-behavior-x: none;
  -webkit-font-smoothing: antialiased;
}

img { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
ul { list-style: none; }

.eyebrow {
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.35em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 1rem;
}

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

.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
  padding: 1rem 1.9rem;
  border-radius: 999px;
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  transition: transform 0.35s var(--ease-out), box-shadow 0.35s var(--ease-out), background 0.35s;
}

.btn svg { width: 1.05em; height: 1.05em; transition: transform 0.35s var(--ease-out); }
.btn:hover svg { transform: translateX(4px); }
.btn:hover { transform: translateY(-2px); }

.btn--light {
  background: var(--white);
  color: #1c1a16;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.28);
}

.btn--dark {
  background: var(--ink);
  color: var(--cream);
  box-shadow: 0 12px 32px rgba(43, 35, 23, 0.25);
}

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

.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 100;
  height: var(--nav-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 clamp(1.25rem, 4vw, 3.5rem);
  /* text colour fades slowly between per-slide inks (data-nav-ink);
     the bar background itself never changes */
  color: var(--nav-ink, var(--hero-text));
  transition: height 0.4s, color 0.9s ease;
}

/* The scrolled bar's blur/background lives on this layer, NOT on .nav itself.
   backdrop-filter on .nav would make it the containing block for its fixed
   children, collapsing the fullscreen mobile menu to the navbar's height. */
.nav::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: rgba(20, 22, 14, 0.72);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  box-shadow: 0 4px 24px rgba(0, 0, 0, 0.18);
  opacity: 0;
  transition: opacity 0.4s;
}

.nav.is-scrolled { height: 4rem; }
.nav.is-scrolled::before { opacity: 1; }

.nav__logo {
  font-size: 1.5rem;
  font-weight: 600;
  letter-spacing: 0.02em;
}

.nav__links {
  display: flex;
  align-items: center;
  gap: clamp(1.25rem, 3vw, 2.75rem);
}

.nav__link {
  position: relative;
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  opacity: 0.75;
  transition: opacity 0.3s;
  padding: 0.4rem 0;
}

.nav__link::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.35s var(--ease-out);
}

.nav__link:hover,
.nav__link.is-active { opacity: 1; }
.nav__link:hover::after,
.nav__link.is-active::after { transform: scaleX(1); }

.nav__resume {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.75rem 1.5rem;
  border: 1px solid rgba(255, 255, 255, 0.55);
  /* follows the per-slide ink colour where supported */
  border-color: color-mix(in srgb, currentColor 55%, transparent);
  border-radius: 999px;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  transition: background 0.3s, color 0.3s, border-color 0.3s;
}

.nav__resume svg { width: 1em; height: 1em; }

.nav__resume:hover {
  background: var(--white);
  color: #1c1a16;
  border-color: var(--white);
}

.nav__resume--mobile { display: none; }

.nav__burger {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 6px;
  width: 44px;
  height: 44px;
  background: none;
  border: 0;
  /* buttons don't inherit color by default — without this the burger lines
     render black and vanish against the dark navbar */
  color: inherit;
  cursor: pointer;
  z-index: 110;
}

.nav__burger span {
  display: block;
  width: 26px;
  height: 2px;
  margin: 0 auto;
  background: currentColor;
  border-radius: 2px;
  transition: transform 0.35s var(--ease-out), opacity 0.25s;
}

body.nav-open .nav__burger span:nth-child(1) { transform: translateY(8px) rotate(45deg); }
body.nav-open .nav__burger span:nth-child(2) { opacity: 0; }
body.nav-open .nav__burger span:nth-child(3) { transform: translateY(-8px) rotate(-45deg); }

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

.hero {
  position: relative;
  height: 100vh;
  height: 100svh;
  min-height: 35rem;
  overflow: hidden;
  background: #1d2410;
}

/* Pinned to the viewport: the About section (and its fog) scrolls up OVER the
   hero scene, connecting the two slides the way the reference mockup does.
   Height uses 100lvh (LARGEST viewport) + a min-height matching .hero so the
   photo always covers the screen — with 100svh the fixed layer was shorter
   than the visible area whenever iOS Safari's chrome retracted (or on short
   viewports), leaving a dark strip of the section background at the bottom. */
.hero__bg,
.hero__subject {
  position: fixed;
  inset: 0;
  height: 100vh;
  height: 100lvh;
  min-height: 35rem;
}

.hero__intro { transform: translate3d(0, var(--py, 0px), 0); }

.hero__bg img,
.hero__subject img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 30% 50%;
}

.hero__bg { z-index: 1; }
.hero__bg::after {
  /* subtle vignette for text legibility */
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(15, 18, 8, 0.35) 0%, rgba(15, 18, 8, 0) 30%),
              linear-gradient(90deg, rgba(15, 18, 8, 0) 55%, rgba(15, 18, 8, 0.25) 100%);
}

.hero__name {
  position: absolute;
  z-index: 2;
  left: 30%;
  top: 50%;
  transform: translateY(calc(-50% + var(--py, 0px)));
  font-size: clamp(4.5rem, 12.5vw, 12rem);
  font-weight: 600;
  line-height: 0.98;
  letter-spacing: -0.015em;
  color: var(--hero-text);
  will-change: transform, opacity;
  animation: heroNameIn 1.4s var(--ease-out) 0.2s backwards;
}

.hero__subject { z-index: 3; animation: heroSubjectIn 1.6s var(--ease-out) backwards; }

.hero__intro {
  position: absolute;
  z-index: 4;
  left: 64%;
  top: 42%;
  max-width: 22.5rem;
  color: var(--white);
  will-change: transform, opacity;
  animation: heroIntroIn 1.2s var(--ease-out) 0.8s backwards;
}

.hero__role {
  position: relative;
  font-size: 1.5rem;
  font-weight: 600;
  padding-left: 1.1rem;
  margin-bottom: 1rem;
}

.hero__role::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.2em;
  bottom: 0.2em;
  width: 3px;
  background: var(--white);
}

.hero__tagline {
  font-size: 1.02rem;
  font-weight: 300;
  line-height: 1.7;
  color: rgba(255, 255, 255, 0.88);
  margin-bottom: 2rem;
}

.hero__scroll {
  position: absolute;
  z-index: 4;
  right: clamp(1.5rem, 5vw, 4rem);
  bottom: 2.25rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.9rem;
  color: rgba(255, 255, 255, 0.85);
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.35em;
  text-transform: uppercase;
  animation: heroFadeUp 1.2s var(--ease-out) 1.2s backwards;
}

.hero__scroll-line {
  position: relative;
  width: 1px;
  height: 4.5rem;
  background: rgba(255, 255, 255, 0.4);
  overflow: hidden;
}

.hero__scroll-line::after {
  content: "";
  position: absolute;
  left: -2.5px;
  top: 0;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--white);
  animation: scrollDot 2.2s ease-in-out infinite;
}

@keyframes scrollDot {
  0%   { transform: translateY(-8px); opacity: 0; }
  25%  { opacity: 1; }
  75%  { opacity: 1; }
  100% { transform: translateY(4.5rem); opacity: 0; }
}

/* Entrance animations declare only a `from` frame and fill backwards, so they
   settle onto the element's natural (parallax-var-driven) style when done. */
@keyframes heroNameIn {
  from { opacity: 0; transform: translateY(calc(-50% + var(--py, 0px) + 60px)); }
}

@keyframes heroSubjectIn {
  from { opacity: 0; transform: translate3d(0, calc(var(--py, 0px) + 40px), 0) scale(1.02); }
}

@keyframes heroIntroIn {
  from { opacity: 0; transform: translate3d(0, calc(var(--py, 0px) + 30px), 0); }
}

@keyframes heroFadeUp {
  from { opacity: 0; transform: translateY(30px); }
}

/* ==========================================================================
   About
   ========================================================================== */

.about {
  position: relative;
  z-index: 10;
  background: linear-gradient(180deg, #f9f5ec 0%, var(--cream) 45%, var(--cream-deep) 100%);
  padding: clamp(6rem, 12vh, 9rem) clamp(1.5rem, 6vw, 6rem) clamp(4rem, 8vh, 6rem);
}

/* Straight fade connecting the pinned hero to this slide.
   --overlap = how far the fade reaches up over the hero image. */
.about__fog {
  --overlap: 18.75rem;

  position: absolute;
  left: 0;
  right: 0;
  top: calc(-1 * var(--overlap));
  height: var(--overlap);
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(249, 245, 236, 0) 0%, #f9f5ec 100%);
}

.about__inner {
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: minmax(0, 46%) minmax(0, 54%);
  gap: clamp(2rem, 5vw, 4rem);
  align-items: center;
  max-width: 87.5rem;
  margin: 0 auto;
}

/* reserves room for the UST card's negative pull-up margin, so it never
   overlaps the facts when the text column is taller than the collage */
.about__text {
  padding-bottom: clamp(2.5rem, 6vh, 4.5rem);
}

.about__title {
  font-size: clamp(2.4rem, 4.5vw, 3.6rem);
  font-weight: 600;
  line-height: 1.15;
  margin-bottom: 1.75rem;
}

.about__blurb {
  position: relative;
  max-width: 26.25rem;
  padding-left: 1.4rem;
  font-size: 1rem;
  font-weight: 300;
  line-height: 1.85;
  color: var(--ink-soft);
  margin-bottom: 3rem;
}

.about__blurb::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.3em;
  bottom: 0.3em;
  width: 2px;
  background: var(--accent);
}

.about__facts {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1.5rem 1.25rem;
}

.about__facts svg {
  width: 1.625rem;
  height: 1.625rem;
  color: var(--ink);
  margin-bottom: 0.7rem;
}

.about__facts h3 {
  font-size: 0.92rem;
  font-weight: 600;
  margin-bottom: 0.25rem;
}

.about__facts p {
  font-size: 0.75rem;
  font-weight: 400;
  line-height: 1.5;
  color: var(--ink-soft);
}

/* --- Collage --- */

.about__collage {
  position: relative;
  min-height: clamp(28.75rem, 48vw, 41.25rem);
}

/* ═══════════════════════════════════════════════════════════════════
   COLLAGE TUNING
   Select any of these elements in DevTools and edit the variables at
   the top of its rule — position, size, blur, and mask (the soft-edge
   fade) are all live-tweakable. The mask is a gradient: "solid" is
   where the image is still 100% visible, "fade" is where it reaches
   0%; the gap between the two is the softness of the edge.
   ═══════════════════════════════════════════════════════════════════ */

/* ---- school building (UST) ---- */
.about__building {
  --pos-x: -31%;      /* ← / → (of collage box) */
  --pos-y: -6%;       /* ↑ / ↓ */
  --width: 186%;
  --blur: 1px;        /* blur of the photo itself */
  --mask-w: 55%;      /* fade ellipse width  */
  --mask-h: 58%;      /* fade ellipse height */
  --mask-x: 54%;      /* fade ellipse centre ↔ */
  --mask-y: 46%;      /* fade ellipse centre ↕ */
  --mask-solid: 43%;
  --mask-fade: 84%;

  position: absolute;
  left: var(--pos-x);
  top: var(--pos-y);
  width: var(--width);
  z-index: 1;
  will-change: transform;
  filter: blur(var(--blur));
  -webkit-mask-image: radial-gradient(var(--mask-w) var(--mask-h) at var(--mask-x) var(--mask-y), #000 var(--mask-solid), transparent var(--mask-fade));
          mask-image: radial-gradient(var(--mask-w) var(--mask-h) at var(--mask-x) var(--mask-y), #000 var(--mask-solid), transparent var(--mask-fade));
}

/* ---- graduation picture ---- */
.about__grad {
  --pos-right: -25%;  /* ← / → (of collage box) */
  --pos-bottom: -16%; /* ↑ / ↓ */
  --width: 75%;
  --blur: 0px;        /* NOTE: negative blur is invalid CSS and disables the shadow too */
  --fade-solid: 74%;  /* gown fully visible until here… */
  --fade-end: 100%;   /* …and fully gone here (straight bottom fade) */
  --shadow: drop-shadow(0 18px 32px rgba(43, 35, 23, 0.18));

  position: absolute;
  right: var(--pos-right);
  bottom: var(--pos-bottom);
  width: var(--width);
  z-index: 3;
  will-change: transform;
  filter: var(--shadow) blur(var(--blur));
}

.about__grad img {
  -webkit-mask-image: linear-gradient(180deg, #000 var(--fade-solid), transparent var(--fade-end));
          mask-image: linear-gradient(180deg, #000 var(--fade-solid), transparent var(--fade-end));
}

/* ---- leaves (anchored to the SECTION, not the collage, so the PNG's
        right edge always bleeds off-screen and its bottom edge hides
        under the next section) ---- */
.about__leaves {
  --pos-right: 0vw;   /* ← / → (of the whole about section) */
  --pos-bottom: -1vh; /* ↑ / ↓ */
  --width: clamp(6.25rem, 42vw, 93.75rem);
  --blur: 2px;
  --mask-w: 105%;
  --mask-h: 65%;
  --mask-x: 94%;
  --mask-y: 47%;
  --mask-solid: 50%;
  --mask-fade: 77%;

  position: absolute;
  right: var(--pos-right);
  bottom: var(--pos-bottom);
  width: var(--width);
  z-index: 5;
  will-change: transform;
  pointer-events: none;
  filter: blur(var(--blur));
  -webkit-mask-image: radial-gradient(var(--mask-w) var(--mask-h) at var(--mask-x) var(--mask-y), #000 var(--mask-solid), transparent var(--mask-fade));
          mask-image: radial-gradient(var(--mask-w) var(--mask-h) at var(--mask-x) var(--mask-y), #000 var(--mask-solid), transparent var(--mask-fade));
}

/* Fill the tuned boxes even when they grow past the images' natural pixel
   size (zoom-out lock) — the global img rule only caps, it never stretches. */
.about__building img,
.about__grad img,
.about__leaves img {
  width: 100%;
  height: auto;
}

/* ---- cloud puffs (soft blurred ellipses layered around the pictures) ---- */
.about__cloud {
  position: absolute;
  left: var(--pos-x);
  bottom: var(--pos-y);
  width: var(--width);
  height: var(--height);
  opacity: var(--opacity, 1);
  border-radius: 50%;
  background: rgba(252, 249, 242, 0.92);
  filter: blur(var(--blur, 2.25rem));
  pointer-events: none;
}

/* in front of the graduate — swallow the bottom edge of his gown */
.about__cloud--3 { --pos-x: 26%; --pos-y: -16%; --width: 66%; --height: 28%; z-index: 4; }
.about__cloud--4 { --pos-x: 4%; --pos-y: -8%; --width: 45%; --height: 22%; --opacity: 0.9; z-index: 4; }

/* --- UST card --- */

.about__card {
  position: relative;
  z-index: 6;
  display: grid;
  grid-template-columns: auto auto 1fr;
  align-items: center;
  gap: clamp(1.25rem, 3vw, 2.5rem);
  max-width: 62.5rem;
  /* pulled up so the graduate's gown sits behind the card, like the mockup */
  margin: clamp(-4.5rem, -6vh, -2.5rem) auto 0;
  padding: clamp(1.5rem, 3vw, 2.25rem) clamp(1.5rem, 3.5vw, 3rem);
  background: rgba(255, 255, 255, 0.65);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid rgba(255, 255, 255, 0.8);
  border-radius: 24px;
  box-shadow: 0 24px 60px rgba(43, 35, 23, 0.12);
}

.about__seal {
  width: 4.5rem;
  flex-shrink: 0;
}

.about__seal img { width: 100%; height: auto; }

.about__card-title h3 {
  font-size: 0.95rem;
  font-weight: 400;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  line-height: 1.4;
  white-space: nowrap;
}

.about__card-title h3 strong { font-weight: 700; }

.about__card-title p {
  font-size: 0.72rem;
  color: var(--ink-soft);
  margin-top: 0.4rem;
}

.about__card-text {
  font-size: 0.9rem;
  font-weight: 300;
  line-height: 1.8;
  color: var(--ink-soft);
  border-left: 1px solid var(--line);
  padding-left: clamp(1.25rem, 3vw, 2.5rem);
}

/* ==========================================================================
   Generic sections (Projects / Skills / Contact)
   ========================================================================== */

.section {
  position: relative;
  z-index: 10; /* keeps the fixed hero layers hidden behind these sections */
  padding: clamp(5rem, 12vh, 8rem) clamp(1.5rem, 6vw, 6rem);
}

.section__inner {
  max-width: 75rem;
  margin: 0 auto;
}

.section__title {
  font-size: clamp(2rem, 4vw, 3rem);
  font-weight: 600;
  margin-bottom: 3rem;
}

/* ==========================================================================
   Projects slide
   ========================================================================== */

.projects {
  background: var(--cream-deep);
  overflow: hidden;
}

.projects .section__inner { position: relative; }

/* blurred foliage accent bleeding off the right edge, per the mockup */
.projects__leaves {
  --pos-right: -10vw;
  --pos-top: 10rem;
  --width: 36vw;
  --blur: 9px;
  --opacity: 0.45;

  position: absolute;
  right: var(--pos-right);
  top: var(--pos-top);
  width: var(--width);
  opacity: var(--opacity);
  filter: blur(var(--blur));
  pointer-events: none;
  -webkit-mask-image: radial-gradient(110% 90% at 100% 50%, #000 40%, transparent 74%);
          mask-image: radial-gradient(110% 90% at 100% 50%, #000 40%, transparent 74%);
}

/* --- header row: title + quote --- */

.projects__head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 2rem clamp(2rem, 6vw, 6rem);
  align-items: end;
  margin-bottom: 3rem;
}

.projects__head .section__title { margin-bottom: 1.25rem; }

.projects__sub {
  max-width: 29.375rem;
  font-size: 0.95rem;
  font-weight: 300;
  line-height: 1.75;
  color: var(--ink-soft);
}

.projects__quote {
  position: relative;
  max-width: 18.75rem;
  padding-left: 1.5rem;
  border-left: 2px solid var(--accent);
  font-size: 1.05rem;
  font-weight: 400;
  line-height: 1.6;
  color: var(--ink-soft);
}

.projects__quote::before {
  content: "\201C\201C";
  display: block;
  font-family: Georgia, "Times New Roman", serif;
  font-size: 2.6rem;
  line-height: 1;
  letter-spacing: -0.08em;
  color: var(--accent);
  margin-bottom: 0.35rem;
}

.projects__label {
  display: block;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--accent);
}

/* --- main project cards --- */

.projects__cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 18.75rem), 1fr));
  gap: 1.75rem;
  margin-bottom: 3.5rem;
}

.pcard {
  display: flex;
  flex-direction: column;
  padding: 0.9rem 0.9rem 0;
  background: rgba(255, 255, 255, 0.78);
  border: 1px solid rgba(255, 255, 255, 0.9);
  border-radius: 22px;
  box-shadow: 0 16px 40px rgba(43, 35, 23, 0.08);
  cursor: pointer;
  transition: transform 0.4s var(--ease-out), box-shadow 0.4s var(--ease-out);
}

.pcard:hover,
.pcard:focus-visible {
  transform: translateY(-8px);
  box-shadow: 0 28px 56px rgba(43, 35, 23, 0.14);
  outline: none;
}

/* "jump to project" affordance — arrow badge that lifts in on hover/focus */
.pcard__go {
  position: absolute;
  top: 0.8rem;
  right: 0.8rem;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.9);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  color: #1c1a16;
  opacity: 0;
  transform: translateY(-0.35rem);
  transition: opacity 0.35s var(--ease-out), transform 0.35s var(--ease-out);
}

.pcard__go svg { width: 1rem; height: 1rem; }

.pcard:hover .pcard__go,
.pcard:focus-visible .pcard__go {
  opacity: 1;
  transform: translateY(0);
}

.pcard__img {
  position: relative;
  border-radius: 14px;
  overflow: hidden;
  aspect-ratio: 16 / 10;
}

.pcard__img img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.pcard__num {
  position: absolute;
  top: 0.8rem;
  left: 0.8rem;
  z-index: 2;
  padding: 0.3rem 0.6rem;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.85);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.08em;
}

.pcard__body {
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  flex: 1;
  padding: 1.3rem 0.8rem 1.5rem;
}

.pcard__head {
  display: flex;
  align-items: center;
  gap: 0.8rem;
}

.pcard__logo {
  width: 2.75rem;
  height: 2.75rem;
  object-fit: contain;
  flex-shrink: 0;
}

.pcard__logo--text {
  display: grid;
  place-items: center;
  border-radius: 12px;
  background: #fdeff5;
  color: #c2417e;
  font-family: Georgia, "Times New Roman", serif;
  font-size: 1.15rem;
  font-weight: 700;
  letter-spacing: -0.06em;
}

.pcard__head h3 {
  font-size: 1.12rem;
  font-weight: 600;
  line-height: 1.25;
}

.pcard__head p {
  font-size: 0.76rem;
  color: var(--ink-soft);
  margin-top: 0.15rem;
}

.pcard__role {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.42rem 0.85rem;
  border: 1px solid;
  border-radius: 999px;
  font-size: 0.73rem;
  font-weight: 500;
}

.pcard__role svg { width: 0.9em; height: 0.9em; flex-shrink: 0; }

.pcard__role--green { color: #3f7a3f; background: #eef5eb; border-color: #cfe3cb; }
.pcard__role--blue  { color: #2b6cb0; background: #ecf2fa; border-color: #cddef0; }
.pcard__role--pink  { color: #c2417e; background: #fdeff5; border-color: #f3d3e2; }

.pcard__desc {
  font-size: 0.86rem;
  font-weight: 300;
  line-height: 1.7;
  color: var(--ink-soft);
}

.pcard__stack {
  margin-top: auto;
  padding-top: 0.9rem;
  border-top: 1px solid var(--line);
}

/* Reserve the same icon-area height (two rows) in every card so the divider
   line sits at an identical position across all three project cards, instead
   of shifting with how many icons wrap. Only matters when cards sit side by
   side. */
@media (min-width: 640px) {
  .pcard__stack .tech {
    min-height: 3.75rem;
    align-content: flex-start;
  }
}

/* --- tech icon rows --- */

.tech {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.7rem 1rem;
  margin-top: 0.7rem;
}

.tech img {
  display: block;
  height: 1.5rem;
  width: auto;
  max-width: 4.75rem;
}

.tech--sm { margin-top: 0; }
.tech--sm img { height: 1.25rem; max-width: 3.875rem; }

.tech__text {
  display: inline-block;
  padding: 0.25rem 0.55rem;
  border: 1px solid var(--line);
  border-radius: 6px;
  font-size: 0.66rem;
  font-weight: 600;
  color: var(--ink-soft);
}

/* --- notable mentions + tech stack overview --- */

.projects__bottom {
  display: grid;
  grid-template-columns: minmax(0, 1.8fr) minmax(0, 1fr);
  gap: 2.5rem;
  align-items: start;
  margin-bottom: 3.5rem;
}

.projects__mentions {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}

.mcard {
  display: grid;
  grid-template-columns: 14.375rem minmax(0, 1fr);
  gap: 1.4rem;
  align-items: center;
  padding: 0.9rem;
  background: rgba(255, 255, 255, 0.78);
  border: 1px solid rgba(255, 255, 255, 0.9);
  border-radius: 18px;
  box-shadow: 0 12px 32px rgba(43, 35, 23, 0.07);
}

.mcard__img {
  border-radius: 12px;
  overflow: hidden;
  aspect-ratio: 16 / 10;
}

.mcard__img img,
.mcard__img svg {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.mcard__body { padding: 0.4rem 0.5rem 0.4rem 0; }

.mcard__body h3 {
  font-size: 1.02rem;
  font-weight: 600;
  line-height: 1.3;
}

.mcard__role {
  display: block;
  margin: 0.3rem 0 0.55rem;
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--accent);
}

.mcard__body > p {
  font-size: 0.82rem;
  font-weight: 300;
  line-height: 1.65;
  color: var(--ink-soft);
  margin-bottom: 0.9rem;
}

.projects__experience .projects__label { margin-bottom: 1.1rem; }

/* Experience card — vertical, matching the notable-mention cards' surface */
.expcard {
  background: rgba(255, 255, 255, 0.78);
  border: 1px solid rgba(255, 255, 255, 0.9);
  border-radius: 18px;
  box-shadow: 0 12px 32px rgba(43, 35, 23, 0.07);
  overflow: hidden;
}

.expcard__img {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  aspect-ratio: 16 / 7;
  background: rgba(43, 35, 23, 0.05);
  color: var(--ink-soft);
}

.expcard__img svg { width: 1.75rem; height: 1.75rem; opacity: 0.55; }

.expcard__img span {
  font-size: 0.65rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  opacity: 0.6;
}

.expcard__body { padding: 1.2rem 1.3rem 1.4rem; }

.expcard__role {
  display: block;
  margin-bottom: 0.3rem;
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--accent);
}

.expcard__body h3 {
  font-size: 1.02rem;
  font-weight: 600;
  line-height: 1.3;
  margin-bottom: 0.6rem;
}

.expcard__body p {
  font-size: 0.82rem;
  font-weight: 300;
  line-height: 1.65;
  color: var(--ink-soft);
}

/* --- Certifications --- */

.projects__certs { margin-bottom: 3.5rem; }
.projects__certs .projects__label { margin-bottom: 1.25rem; }

.certgrid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1.25rem;
}

.certcard {
  display: flex;
  flex-direction: column;
  padding: 1.4rem 1.4rem 1.2rem;
  background: rgba(255, 255, 255, 0.78);
  border: 1px solid rgba(255, 255, 255, 0.9);
  border-radius: 16px;
  box-shadow: 0 12px 32px rgba(43, 35, 23, 0.07);
  transition: transform 0.4s var(--ease-out), box-shadow 0.4s var(--ease-out);
}

.certcard:hover {
  transform: translateY(-6px);
  box-shadow: 0 20px 44px rgba(43, 35, 23, 0.12);
}

.certcard__logo {
  object-fit: contain;
  margin-bottom: 0.75rem;
  align-self: center;
}

.certcard h3 {
  font-size: 0.9rem;
  font-weight: 600;
  line-height: 1.35;
  margin-bottom: 1rem;
}

.certcard dl {
  display: grid;
  gap: 0.55rem;
  margin-bottom: 1.1rem;
}

.certcard dl div {
  display: flex;
  justify-content: space-between;
  gap: 0.75rem;
  font-size: 0.75rem;
}

.certcard dt {
  color: var(--ink-soft);
  font-weight: 400;
  flex-shrink: 0;
}

.certcard dd {
  font-weight: 600;
  text-align: right;
  word-break: break-word;
}

.certcard__verify {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: auto;
  align-self: flex-start;
  padding: 0.5rem 0.95rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--accent);
  transition: background 0.3s, color 0.3s, border-color 0.3s;
}

.certcard__verify svg { width: 0.9em; height: 0.9em; }

.certcard__verify:hover {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

/* ==========================================================================
   Project detail slide — EcoGuardian (dark, video hero)
   ========================================================================== */

.pdetail {
  --fade-height: 9.375rem; /* how tall the cream → dark blend at the top is */

  position: relative;
  background: #0c100a;
  color: #ece9e2;
  overflow: hidden;
  padding-top: clamp(12rem, 20vh, 15rem);
}

/* the previous (cream) slide melts into the darkness instead of a hard cut */
.pdetail::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: var(--fade-height);
  z-index: 2;
  pointer-events: none;
  background: linear-gradient(180deg, var(--cream-deep) 0%, rgba(239, 231, 217, 0) 100%);
}

/* Video sits on the right and dissolves into the dark. The "mask" is an
   inverse radial gradient painted OVER the video (transparent centre →
   solid slide colour at the edges) — identical look to a real mask because
   the slide background is uniform dark, but far cheaper to composite.
   Move/resize the fade ellipse with --mask-*, reposition the footage
   inside it with --video-pos. */
.pdetail__bg {
  /* The box the footage fills. Keep it near the video's own 16:9 shape and
     nothing gets cropped/zoomed; make it taller/narrower and object-fit
     crops into the footage. Size and place it freely: */
  --width: min(56vw, 65rem);
  --height: min(38vw, 37.5rem);
  --top: clamp(7rem, 10vh, 8rem);
  /* slides smoothly from 10.375rem (166px @ wide screens) to 0 as the window
     narrows to 1100px — tune the 1100px start point and the 0.2 slope */
  --right: clamp(0px, calc((100vw - 1100px) * 0.2), 10.375rem);
  --video-pos: 82% 50%;   /* object-position: which part of the footage shows */
  --overlay: 0.3;         /* extra darkening on top of the video */
  --mask-w: 85%;          /* fade ellipse width  */
  --mask-h: 77%;          /* fade ellipse height */
  --mask-x: 50%;          /* fade ellipse centre ↔ */
  --mask-y: 54%;          /* fade ellipse centre ↕ */
  --mask-solid: -6%;      /* fade starts immediately (soft veil over centre) */
  /* keep below the ellipse-to-edge distances (left/right 50/85 ≈ 59%, top
     54/77 ≈ 70%, bottom 46/77 ≈ 60%) or a faint rectangle edge shows */
  --mask-fade: 61%;

  position: absolute;
  top: var(--top);
  right: var(--right);
  width: var(--width);
  height: var(--height);
}

/* Eases the box between states (e.g. crossing the phone breakpoint) instead
   of snapping. Gated behind .is-ready (added by JS after first paint) so the
   box never animates from its pre-layout size on page load. */
body.is-ready .pdetail__bg {
  transition: width 0.5s var(--ease-out), height 0.5s var(--ease-out),
              top 0.5s var(--ease-out), right 0.5s var(--ease-out);
}

.pdetail__bg video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--video-pos);
}

.pdetail__bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(var(--mask-w) var(--mask-h) at var(--mask-x) var(--mask-y),
      rgba(12, 16, 10, 0) var(--mask-solid), #0c100a var(--mask-fade)),
    rgba(10, 13, 8, var(--overlay));
}

.pdetail .section__inner {
  position: relative;
  z-index: 3;
}

.pdetail__back {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  margin-bottom: 2rem;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: rgba(236, 233, 226, 0.75);
  transition: color 0.3s, gap 0.3s;
}

.pdetail__back svg { width: 1.1em; height: 1.1em; }
.pdetail__back:hover { color: #ece9e2; }

.pdetail__intro { max-width: 35rem; margin-bottom: 3rem; }

.pdetail__title {
  font-size: clamp(2.8rem, 6vw, 4.6rem);
  font-weight: 600;
  line-height: 1.05;
}

.pdetail__tagline {
  margin: 0.6rem 0 1.5rem;
  font-size: clamp(1.05rem, 1.8vw, 1.4rem);
  font-weight: 400;
  color: #d8a25e;
}

.pdetail__desc {
  font-size: 0.95rem;
  font-weight: 300;
  line-height: 1.85;
  color: rgba(236, 233, 226, 0.85);
  margin-bottom: 2rem;
}

.pdetail__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.8rem;
}

.pdetail__chips li {
  display: inline-flex;
  align-items: center;
  gap: 0.65rem;
  padding: 0.8rem 1.1rem;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 12px;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  font-size: 0.78rem;
  font-weight: 400;
}

.pdetail__chips img {
  width: 1.25rem;
  height: 1.25rem;
  filter: invert(1);  /* the source icons are black */
  opacity: 0.9;
}

.pdetail__label {
  margin-bottom: 1.1rem;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: #d8a25e;
}

/* --- how it works flow --- */

.pdetail__flow {
  display: grid;
  grid-template-columns: 1fr auto 1fr auto 1fr auto 1fr;
  gap: 1rem;
  align-items: center;
  max-width: 56.25rem;
  padding: 1.75rem 2rem;
  margin-bottom: 3rem;
  background: rgba(12, 15, 10, 0.68);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 18px;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}

.pdetail__step { text-align: center; }

.pdetail__step-img {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 5.25rem;
  margin-bottom: 0.9rem;
}

.pdetail__step-img img {
  max-height: 100%;
  max-width: 100%;
  object-fit: contain;
}

/* wordmark logos (LoRaWAN) need breathing room + a light tile to stay legible */
.pdetail__step-img--pad {
  padding: 0.6rem;
}

.pdetail__step-img--pad img {
  background: rgba(255, 255, 255, 0.88);
  border-radius: 10px;
  padding: 0.55rem 0.7rem;
  max-height: 3.625rem;
}

.pdetail__step h3 {
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: #d8a25e;
  margin-bottom: 0.45rem;
}

.pdetail__step p {
  font-size: 0.78rem;
  font-weight: 300;
  line-height: 1.55;
  color: rgba(236, 233, 226, 0.72);
}

.pdetail__arrow {
  width: 1.375rem;
  height: 1.375rem;
  color: rgba(236, 233, 226, 0.5);
}

/* --- award rows: name | certificate | moment --- */

.pdetail__awardrows {
  display: grid;
  gap: 1.25rem;
  max-width: 56.25rem;
}

.pdetail__awardrow {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr) minmax(0, 1fr);
  gap: 1.5rem;
  align-items: center;
  padding: 1.25rem 1.5rem;
  background: rgba(12, 15, 10, 0.68);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 18px;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}

.pdetail__award {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.pdetail__award img {
  width: 4.5rem;
  height: 4.5rem;
  object-fit: contain;
  flex-shrink: 0;
}

.pdetail__award h3 {
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.pdetail__award p {
  margin-top: 0.35rem;
  font-size: 0.78rem;
  font-weight: 300;
  line-height: 1.5;
  color: rgba(236, 233, 226, 0.7);
}

.pdetail__shot {
  position: relative;
  display: block;
  border-radius: 12px;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.14);
  aspect-ratio: 3 / 2;
  background: rgba(255, 255, 255, 0.04);
}

.pdetail__shot img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.5s var(--ease-out);
}

.pdetail__shot:hover img { transform: scale(1.05); }

.pdetail__shot span {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 1.4rem 0.9rem 0.6rem;
  background: linear-gradient(0deg, rgba(8, 10, 6, 0.85) 0%, rgba(8, 10, 6, 0) 100%);
  font-size: 0.68rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  color: rgba(236, 233, 226, 0.9);
}

/* ==========================================================================
   Project detail slide — CICS Learning Commons (light, maroon)
   ========================================================================== */

.cics {
  --maroon: #7d1c2c;
  --maroon-soft: #a34c58;
  --panel-line: #e9dcd2;
  --fade-height: 9.375rem; /* dark → light blend from the previous slide */

  position: relative;
  background: linear-gradient(180deg, #f9f3ec 0%, #f5eee6 100%);
  color: #4f463f;
  overflow: hidden;
}

.cics::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: var(--fade-height);
  z-index: 2;
  pointer-events: none;
  background: linear-gradient(180deg, #0c100a 0%, rgba(12, 16, 10, 0) 100%);
}

/* ghosted Frassati building behind the intro */
.cics__bg {
  --width: 46%;
  --opacity: 0.13;

  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: var(--width);
  opacity: var(--opacity);
  pointer-events: none;
  /* anchored top-left, fully dissolved before the right/bottom box edges so
     no straight cut ever shows */
  -webkit-mask-image: radial-gradient(130% 115% at 0% 20%, #000 38%, transparent 68%);
          mask-image: radial-gradient(130% 115% at 0% 20%, #000 38%, transparent 68%);
}

.cics__bg img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 18%;
}

.cics .section__inner {
  position: relative;
  z-index: 3;
}

.cics__back {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  margin-bottom: 2rem;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--maroon);
  opacity: 0.85;
  transition: opacity 0.3s;
}

.cics__back svg { width: 1.1em; height: 1.1em; }
.cics__back:hover { opacity: 1; }

/* --- hero: intro + feature cards | device mockup --- */

.cics__hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  gap: clamp(2rem, 4vw, 4rem);
  align-items: center;
  margin-bottom: 3rem;
}

.cics__title {
  font-size: clamp(2.2rem, 3.6vw, 3.4rem);
  font-weight: 600;
  line-height: 1.12;
  color: var(--maroon);
}

.cics__tagline {
  margin: 0.9rem 0 1.4rem;
  font-size: clamp(1rem, 1.5vw, 1.3rem);
  font-weight: 500;
  color: var(--maroon-soft);
}

.cics__desc {
  max-width: 30rem;
  font-size: 0.95rem;
  font-weight: 300;
  line-height: 1.8;
  color: #5d5450;
  margin-bottom: 2rem;
}

.cics__features {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.9rem;
}

.cics__features li {
  padding: 1.1rem 0.95rem;
  background: rgba(255, 255, 255, 0.82);
  border: 1px solid var(--panel-line);
  border-radius: 14px;
}

.cics__features svg {
  width: 1.5rem;
  height: 1.5rem;
  color: var(--maroon);
  margin-bottom: 0.65rem;
}

.cics__features h3 {
  font-size: 0.82rem;
  font-weight: 600;
  line-height: 1.3;
  color: #2f2823;
  margin-bottom: 0.4rem;
}

.cics__features p {
  font-size: 0.72rem;
  font-weight: 300;
  line-height: 1.55;
  color: #6b625c;
}

.cics__mockup img {
  width: 100%;
  height: auto;
  filter: drop-shadow(0 1.5rem 2.5rem rgba(70, 25, 30, 0.18));
}

/* --- bottom panel: role | stack | key features --- */

.cics__panel {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.5fr);
  gap: clamp(1.5rem, 3vw, 2.75rem);
  padding: clamp(1.5rem, 3vw, 2.5rem);
  background: rgba(255, 255, 255, 0.85);
  border: 1px solid var(--panel-line);
  border-radius: 20px;
  box-shadow: 0 1.5rem 3rem rgba(80, 40, 30, 0.07);
}

.cics__panel > div + div {
  border-left: 1px solid var(--panel-line);
  padding-left: clamp(1.5rem, 3vw, 2.75rem);
}

.cics__label {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--maroon);
  margin-bottom: 1.2rem;
}

.cics__role-head {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  margin-bottom: 0.9rem;
}

.cics__avatar {
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 50%;
  background: #f5e4e4;
  color: var(--maroon);
  flex-shrink: 0;
}

.cics__avatar svg { width: 1.4rem; height: 1.4rem; }

.cics__role-head h3 {
  font-size: 1.05rem;
  font-weight: 600;
  color: #2f2823;
}

.cics__role-desc {
  font-size: 0.82rem;
  font-weight: 300;
  line-height: 1.7;
  color: #6b625c;
  margin-bottom: 1.2rem;
}

.cics__checks {
  display: grid;
  gap: 0.7rem;
}

.cics__checks li {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  font-size: 0.8rem;
  line-height: 1.45;
  color: #4f463f;
}

.cics__checks svg {
  width: 1.05rem;
  height: 1.05rem;
  color: var(--maroon);
  flex-shrink: 0;
  margin-top: 0.1em;
}

.cics__stack h4 {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--maroon-soft);
  margin: 1.2rem 0 0.7rem;
  padding-bottom: 0.35rem;
  border-bottom: 1px solid var(--panel-line);
}

.cics__stack h4:first-of-type { margin-top: 0; }

.cics__techlist {
  display: grid;
  gap: 0.65rem;
}

.cics__techlist li {
  display: flex;
  align-items: center;
  gap: 0.7rem;
}

.cics__tech-icon {
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 10px;
  background: #fff;
  border: 1px solid var(--panel-line);
  flex-shrink: 0;
}

.cics__tech-icon img {
  width: 70%;
  height: 70%;
  object-fit: contain;
}

.cics__tech-icon--ph {
  font-size: 0.7rem;
  font-weight: 700;
  color: var(--maroon);
  background: #f7ebe4;
}

.cics__tech-icon--glyph {
  font-size: 0.95rem;
  font-weight: 600;
  color: #4f463f;
}

.cics__techlist strong {
  display: block;
  font-size: 0.84rem;
  font-weight: 600;
  color: #2f2823;
}

.cics__techlist li > div > span {
  font-size: 0.7rem;
  color: #8a7f76;
}

/* key features: checklist beside the CICS crest */
.cics__key {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  gap: 0.5rem 1.25rem;
  align-content: start;
}

.cics__key .cics__label { grid-column: 1 / -1; }

.cics__crest {
  display: grid;
  place-items: center;
  align-self: stretch;
  padding: 1.25rem;
  background: #faf3ee;
  border: 1px solid var(--panel-line);
  border-radius: 16px;
}

.cics__crest img {
  width: 100%;
  max-width: 11rem;
  height: auto;
}

/* ==========================================================================
   Project detail slide — Beyond Beautiful ("The Curated Atelier")
   Governed by design.md (this slide ONLY): monochrome editorial, Newsreader
   italics for headlines, Manrope body, 0 border radius, no divider lines —
   boundaries come from tonal background shifts (L0–L3), no drop shadows.
   ========================================================================== */

.bb {
  --ink: #000000;
  --text: #1a1c1c;
  --grey: #5e5e5e;
  --ghost: #c6c6c6;
  --l0: #f9f9f9;
  --l1: #f3f3f4;
  --l2: #e8e8e8;
  --l3: #ffffff;
  --fade-height: 9.375rem;

  position: relative;
  background: var(--l0);
  color: var(--text);
  font-family: "Manrope", "Poppins", sans-serif;
  overflow: hidden;
}

/* the CICS slide's cream melts into the atelier canvas */
.bb::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: var(--fade-height);
  z-index: 2;
  pointer-events: none;
  background: linear-gradient(180deg, #f5eee6 0%, rgba(245, 238, 230, 0) 100%);
}

.bb .section__inner {
  position: relative;
  z-index: 3;
}

/* ghost button — sharp rectangle, black outline */
.bb__back {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  margin-bottom: 3rem;
  padding: 0.75rem 1.4rem;
  border: 1px solid var(--text);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text);
  transition: background 0.3s, color 0.3s;
}

.bb__back svg { width: 1.1em; height: 1.1em; }

.bb__back:hover {
  background: var(--ink);
  color: #fff;
  border-color: var(--ink);
}

/* --- hero --- */

.bb__hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  gap: clamp(2rem, 4vw, 4.5rem);
  align-items: center;
  margin-bottom: 4rem;
}

.bb__eyebrow {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--grey);
  margin-bottom: 1.5rem;
}

.bb__title {
  font-family: "Newsreader", Georgia, serif;
  font-style: italic;
  font-weight: 400;
  font-size: clamp(2.5rem, 4.2vw, 4rem);
  line-height: 1.125;
  color: var(--text);
  margin-bottom: 1.75rem;
}

.bb__desc {
  max-width: 30rem;
  font-size: 1rem;
  font-weight: 400;
  line-height: 1.5;
  color: var(--grey);
}

/* primary button — solid black sharp rectangle, white tracked text */
.bb__github {
  display: inline-flex;
  align-items: center;
  gap: 0.65rem;
  margin-top: 2rem;
  padding: 0.85rem 1.6rem;
  background: var(--ink);
  color: #fff;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  transition: opacity 0.3s;
}

.bb__github svg { width: 1.1em; height: 1.1em; }
.bb__github:hover { opacity: 0.82; }

.bb__mockup img {
  width: 100%;
  height: auto;
}

/* --- feature band: tonal tiles separated by hairline canvas gaps --- */

.bb__features {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.125rem;
  margin-bottom: 4rem;
}

.bb__features li {
  padding: 1.75rem 1.5rem;
  background: var(--l1);
}

.bb__features svg {
  width: 1.5rem;
  height: 1.5rem;
  color: var(--ink);
  margin-bottom: 1rem;
}

.bb__features h3 {
  font-family: "Newsreader", Georgia, serif;
  font-weight: 500;
  font-size: 1.125rem;
  line-height: 1.3;
  color: var(--text);
  margin-bottom: 0.5rem;
}

.bb__features p {
  font-size: 0.8rem;
  font-weight: 400;
  line-height: 1.55;
  color: var(--grey);
}

/* --- panel: one tonal slab, columns divided by whitespace only --- */

.bb__panel {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.45fr);
  gap: clamp(2rem, 4vw, 4rem);
  padding: clamp(2rem, 4vw, 3.5rem);
  background: var(--l1);
}

.bb__label {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text);
  margin-bottom: 1.5rem;
}

.bb__role-head {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  margin-bottom: 1rem;
}

.bb__avatar {
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  background: var(--ink);
  color: #fff;
  flex-shrink: 0;
}

.bb__avatar svg { width: 1.3rem; height: 1.3rem; }

.bb__role-head h3 {
  font-family: "Newsreader", Georgia, serif;
  font-weight: 500;
  font-size: 1.4rem;
  line-height: 1.3;
  color: var(--text);
}

.bb__body {
  font-size: 0.85rem;
  font-weight: 400;
  line-height: 1.6;
  color: var(--grey);
  margin-bottom: 1.4rem;
}

.bb__checks {
  display: grid;
  gap: 0.75rem;
}

.bb__checks li {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  font-size: 0.82rem;
  line-height: 1.5;
  color: var(--text);
}

.bb__checks svg {
  width: 1rem;
  height: 1rem;
  color: var(--ink);
  flex-shrink: 0;
  margin-top: 0.15em;
}

.bb__group {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--grey);
  margin: 1.5rem 0 0.8rem;
}

.bb__group:first-of-type { margin-top: 0; }

.bb__techlist {
  display: grid;
  gap: 0.7rem;
}

.bb__techlist li {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

/* L3 tile on L1 — boundary by tonal shift, no border */
.bb__tech-icon {
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  background: var(--l3);
  flex-shrink: 0;
}

.bb__tech-icon img {
  width: 65%;
  height: 65%;
  object-fit: contain;
}

.bb__techlist strong {
  display: block;
  font-size: 0.84rem;
  font-weight: 600;
  color: var(--text);
}

.bb__techlist li > div > span {
  font-size: 0.72rem;
  color: var(--grey);
}

.bb__col--key {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: 0.5rem 1.5rem;
  align-content: start;
}

.bb__col--key .bb__label { grid-column: 1 / -1; }

/* the wordmark, serif italic on an L2 nesting surface */
.bb__wordmark {
  display: grid;
  place-items: center;
  align-self: stretch;
  padding: 1.5rem;
  background: var(--l2);
  font-family: "Newsreader", Georgia, serif;
  font-style: italic;
  font-weight: 500;
  font-size: clamp(1.6rem, 2vw, 2rem);
  line-height: 1.3;
  text-align: center;
  color: var(--ink);
}

/* --- scroll hint --- */

.projects__hint {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.68rem;
  font-weight: 500;
  letter-spacing: 0.35em;
  text-transform: uppercase;
  text-align: center;
  color: var(--ink-soft);
}

.projects__hint svg {
  width: 1rem;
  height: 1rem;
  animation: hintBob 2s ease-in-out infinite;
}

@keyframes hintBob {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(6px); }
}

.contact {
  background: linear-gradient(180deg, var(--cream) 0%, var(--cream-deep) 100%);
  padding-bottom: 0;
  text-align: center;
}

.contact .eyebrow { text-align: center; }

.contact__blurb {
  max-width: 27.5rem;
  margin: -1.5rem auto 2.5rem;
  font-size: 1rem;
  font-weight: 300;
  line-height: 1.8;
  color: var(--ink-soft);
}

.contact__buttons {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  justify-content: center;
  align-items: center;
}

.footer {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.75rem;
  margin-top: clamp(4rem, 8vh, 6rem);
  padding: 2.5rem 1.5rem;
  border-top: 1px solid var(--line);
}

.footer span { font-size: 1.25rem; font-weight: 600; }

.footer p {
  font-size: 0.75rem;
  color: var(--ink-soft);
}

/* ==========================================================================
   Reveal animations (appear / disappear on scroll)
   ========================================================================== */

[data-reveal] {
  opacity: 0;
  transform: translateY(44px);
  transition: opacity 0.9s var(--ease-out), transform 0.9s var(--ease-out);
}

[data-reveal].is-visible {
  opacity: 1;
  transform: translateY(0);
}

[data-reveal][data-reveal-delay="1"] { transition-delay: 0.1s; }
[data-reveal][data-reveal-delay="2"] { transition-delay: 0.22s; }
[data-reveal][data-reveal-delay="3"] { transition-delay: 0.34s; }
[data-reveal][data-reveal-delay="4"] { transition-delay: 0.46s; }
[data-reveal][data-reveal-delay="5"] { transition-delay: 0.58s; }
[data-reveal][data-reveal-delay="6"] { transition-delay: 0.7s; }

/* Parallax-driven elements combine transforms via CSS var */
[data-parallax] { transform: translate3d(0, var(--py, 0px), 0); }

[data-parallax][data-reveal] {
  transform: translate3d(0, calc(var(--py, 0px) + 44px), 0);
}

[data-parallax][data-reveal].is-visible {
  transform: translate3d(0, var(--py, 0px), 0);
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  [data-reveal] { opacity: 1; transform: none; }
}

/* ==========================================================================
   Responsive — tablets
   ========================================================================== */

@media (max-width: 1100px) {
  .hero__name { left: 24%; }
  .hero__intro { left: 58%; max-width: 320px; }

  .projects__head { grid-template-columns: 1fr; align-items: start; }
  .projects__quote { max-width: 420px; }
  .projects__bottom { grid-template-columns: 1fr; }
  .certgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  .pdetail__flow { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.75rem 1.25rem; max-width: 40rem; }
  .pdetail__arrow { display: none; }

  .cics__hero { grid-template-columns: 1fr; }
  .cics__mockup { max-width: 40rem; margin: 0 auto; }
  .cics__features { grid-template-columns: repeat(2, minmax(0, 1fr)); max-width: 36rem; }
  .cics__panel { grid-template-columns: 1fr; }
  .cics__panel > div + div {
    border-left: 0;
    padding-left: 0;
    border-top: 1px solid var(--panel-line);
    padding-top: 1.5rem;
  }

  .bb__hero { grid-template-columns: 1fr; }
  .bb__mockup { max-width: 40rem; margin: 0 auto; }
  .bb__features { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .bb__panel { grid-template-columns: 1fr; gap: 2.5rem; }

  .about__inner { grid-template-columns: 1fr; }
  .about__collage { min-height: clamp(380px, 60vw, 560px); max-width: 640px; margin: 0 auto; width: 100%; }
  .about__facts { max-width: 560px; }
}

/* ==========================================================================
   Responsive — phones
   ========================================================================== */

@media (max-width: 768px) {
  :root { --nav-h: 68px; }

  /* --- nav collapses to burger --- */
  .nav__burger { display: flex; }
  .nav__resume--desktop { display: none; }
  .nav__resume--mobile { display: inline-flex; margin-top: 1.5rem; }

  .nav__links {
    position: fixed;
    inset: 0;
    z-index: 105;
    flex-direction: column;
    justify-content: center;
    gap: 2rem;
    background: rgba(18, 20, 12, 0.96);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    color: var(--hero-text);
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.4s var(--ease-out), visibility 0.4s;
  }

  body.nav-open .nav__links {
    opacity: 1;
    visibility: visible;
  }

  body.nav-open { overflow: hidden; }

  .nav__link { font-size: 1rem; }

  /* --- hero --- */
  .hero { min-height: 640px; }
  /* keep the fixed photo layers as tall as the section so no dark strip shows */
  .hero__bg,
  .hero__subject { min-height: 640px; }

  .hero__bg img,
  .hero__subject img {
    object-position: 26% 100%;
  }

  /* darkens the lower third above the subject so the intro stays legible */
  .hero__subject::after {
    content: "";
    position: absolute;
    inset: 55% 0 0 0;
    background: linear-gradient(0deg, rgba(15, 18, 8, 0.62) 0%, rgba(15, 18, 8, 0) 100%);
  }

  .hero__name {
    left: 1.5rem;
    right: 1.25rem;
    top: 14%;
    transform: translate3d(0, var(--py, 0px), 0);
    font-size: clamp(3rem, 15vw, 5rem);
    text-align: right;
    animation-name: heroIntroIn;
  }

  .hero__intro {
    left: 1.5rem;
    right: 1.5rem;
    top: auto;
    /* lift the intro + CTA clear of iOS Safari's floating address bar and the
       home indicator so "View my work" isn't hidden behind them */
    bottom: calc(env(safe-area-inset-bottom, 0px) + 5.5rem);
    max-width: none;
  }

  .hero__role { font-size: 1.25rem; margin-bottom: 0.6rem; }

  .hero__tagline {
    font-size: 0.92rem;
    margin-bottom: 1.4rem;
    max-width: 30ch;
    text-shadow: 0 2px 12px rgba(0, 0, 0, 0.45);
  }

  .btn { padding: 0.85rem 1.5rem; }

  .hero__scroll { display: none; }

  /* extra darkening for legibility over the photo */
  .hero__bg::after {
    background: linear-gradient(180deg, rgba(15, 18, 8, 0.45) 0%, rgba(15, 18, 8, 0.05) 40%),
                linear-gradient(0deg, rgba(15, 18, 8, 0.55) 0%, rgba(15, 18, 8, 0) 45%);
  }

  /* --- about --- */
  .about__fog { --overlap: 200px; }

  .about__facts { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  .about__collage { min-height: 84vw; }
  .about__grad {
    --pos-right: 8%;
    --pos-bottom: -10%;
    --width: 79%;
    --fade-solid: 83%;
    --fade-end: 92%;
  }
  .about__leaves {
    --pos-right: -5vw;
    --pos-bottom: 37vh;
    --width: 83vw;
    --blur: 1px;
  }

  .about__card {
    grid-template-columns: auto 1fr;
    grid-template-areas:
      "seal title"
      "text text";
    gap: 1.25rem;
    margin-top: -1rem;
  }

  .about__seal { grid-area: seal; width: 56px; }
  .about__card-title { grid-area: title; }
  .about__card-title h3 { white-space: normal; }
  .about__card-text {
    grid-area: text;
    border-left: 0;
    border-top: 1px solid var(--line);
    padding-left: 0;
    padding-top: 1.25rem;
  }

  /* --- sections --- */
  .projects__leaves { display: none; }
  .pdetail { padding-top: clamp(9rem, 16vh, 12rem); --fade-height: 170px; }
  /* Phone view of the video — same knobs as desktop, tune freely here.
     Defaults: a tall backdrop behind the title/chips that fades to dark
     before the "How it works" card. */
  .pdetail__bg {
    --width: 100vw;
    --height: 135vw;
    --top: 0px;
    --right: 0px;
    --video-pos: 62% 50%;
    --overlay: 0.5;
    --mask-w: 130%;
    --mask-h: 95%;
    --mask-x: 60%;
    --mask-y: 42%;
    --mask-solid: 10%;
    --mask-fade: 62%;
  }
  /* award rows stack: name on top, certificate + moment side by side */
  .pdetail__awardrow { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; }
  .pdetail__awardrow .pdetail__award { grid-column: 1 / -1; }

  .cics__bg { --width: 100%; --opacity: 0.09; }
  .cics__key { grid-template-columns: 1fr; }
  .cics__crest { max-width: 14rem; margin: 0.75rem auto 0; }

  .bb__features { grid-template-columns: 1fr; }
  .bb__col--key { grid-template-columns: 1fr; }
  .bb__wordmark { padding: 2rem 1.5rem; margin-top: 0.75rem; }
  .pdetail__chips { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .pdetail__chips li { justify-content: flex-start; }
  .mcard { grid-template-columns: 1fr; gap: 1rem; }
  .mcard__body { padding: 0 0.35rem 0.5rem; }
  .certgrid { grid-template-columns: 1fr; }
}

@media (max-width: 420px) {
  .about__facts { gap: 1.25rem 1rem; }
}

/* ==========================================================================
   Resume Modal (Glassmorphism & premium feel)
   ========================================================================== */
/* iOS-safe scroll lock companion for openModal/closeModal in main.js */
body.has-modal {
  position: fixed;
  left: 0;
  right: 0;
  width: 100%;
  overflow: hidden;
}

.modal {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100vh;
  height: 100dvh; /* fit the VISIBLE area on iOS, not the large viewport */
  z-index: 10000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: max(1rem, env(safe-area-inset-top)) 1rem max(1rem, env(safe-area-inset-bottom));
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}

.modal.is-open {
  opacity: 1;
  pointer-events: auto;
}

.modal__overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(28, 26, 22, 0.45);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

.modal__window {
  position: relative;
  /* fits within the safe-area-padded .modal container: capped on big screens,
     100% (of the visible area) on phones so it never overflows off-screen */
  width: min(950px, 100%);
  height: min(850px, 100%);
  background: rgba(255, 255, 255, 0.85);
  border: 1px solid rgba(255, 255, 255, 0.5);
  border-radius: 24px;
  box-shadow: 0 24px 64px rgba(0, 0, 0, 0.15);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  transform: scale(0.95) translateY(10px);
  transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1);
  z-index: 2;
}

.modal.is-open .modal__window {
  transform: scale(1) translateY(0);
}

.modal__header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 1.25rem 2rem;
  border-bottom: 1px solid rgba(0, 0, 0, 0.05);
}

.modal__header h3 {
  font-family: 'Manrope', sans-serif;
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--ink);
}

.modal__controls {
  display: flex;
  align-items: center;
  gap: 1.25rem;
}

.modal__download.btn {
  padding: 0.6rem 1.25rem;
  font-size: 0.75rem;
  background: var(--ink);
  color: var(--cream);
  border: none;
  cursor: pointer;
  box-shadow: none;
}

.modal__download.btn svg {
  width: 1.1em;
  height: 1.1em;
  margin-left: 0;
  transition: transform 0.3s;
}

.modal__download.btn:hover svg {
  transform: translateY(2px);
}

.modal__close {
  background: transparent;
  border: none;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--ink);
  cursor: pointer;
  transition: background 0.3s, transform 0.3s;
}

.modal__close:hover {
  background: rgba(0, 0, 0, 0.05);
  transform: scale(1.05);
}

.modal__close svg {
  width: 20px;
  height: 20px;
}

.modal__body {
  flex: 1;
  background: #f7f7f7;
  overflow: hidden;
}

.modal__body iframe {
  border: none;
}

@media (max-width: 768px) {
  .modal__window {
    border-radius: 16px;
  }
  .modal__header {
    padding: 1rem 1.25rem;
  }
  /* keep the header controls on one line without crowding the title */
  .modal__header h3 { font-size: 1.1rem; }
  .modal__controls { gap: 0.75rem; }
  .modal__download.btn { padding: 0.55rem 1rem; letter-spacing: 0.12em; }
}
