@import url("https://fonts.googleapis.com/css2?family=Fira+Code:wght@300;400;500;600&family=Cabin+Sketch&family=VT323&display=swap");

:root {
  --primary: #C778DD;
  --gray: #ABB2BF;
  --bg: #282c33;
  --surface: #2f333b;
  --white: #F5F7F8;
  --border: #3a3f47;
  --accent: #9b8fef;
  --warn: #e5a96a;
  --red: #e06c75;
  --green: #98c379;
  --texture: #9052a8;
}

*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  -webkit-tap-highlight-color: transparent
}

html {
  scroll-behavior: smooth
}

body {
  font-family: "Fira Code", "Courier New", monospace;
  background: var(--bg);
  color: var(--gray)
}

h1,
h2,
h3,
h4 {
  color: var(--white)
}

h2 {
  font-size: 32px;
  font-weight: 500
}

@media(max-width:480px) {
  .section-header h2 {
    font-size: 24px
  }
}

ul {
  list-style: none
}

button {
  background: transparent;
  border: 1px solid var(--primary);
  color: var(--white);
  padding: 8px 16px;
  cursor: pointer;
  font-family: inherit;
  font-size: 14px;
  transition: background .3s
}

button:has(a) {
  animation: redirectPulse 2.4s ease-in-out infinite
}

button:has(a):hover {
  animation: none
}

@keyframes redirectPulse {

  0%,
  100% {
    box-shadow: 0 0 0 0 rgba(199, 120, 221, .45)
  }

  50% {
    box-shadow: 0 0 0 5px rgba(199, 120, 221, 0)
  }
}

button:hover {
  background: var(--primary)
}

a {
  color: var(--white);
  text-decoration: none
}

/* ── HEADER ── */
header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 1000;
  background: var(--bg);
  padding: 28px 0 8px;
  border-bottom: 1px solid var(--border)
}

header.scrolled {
  box-shadow: 0 2px 12px rgba(0, 0, 0, .5)
}

.navbar {
  max-width: 1024px;
  margin: 0 auto;
  padding: 0 24px;
  display: flex;
  justify-content: space-between;
  align-items: center
}

.logo-link {
  display: flex;
  align-items: center;
  gap: 8px
}

.logo {
  font-size: 20px;
  color: var(--white);
  margin: 0;
  text-shadow: 0 0 14px rgba(229, 169, 106, .8);
  animation: wobble 4s infinite
}

@keyframes wobble {

  0%,
  100% {
    transform: rotate(0)
  }

  25% {
    transform: rotate(7deg)
  }

  75% {
    transform: rotate(-7deg)
  }
}

.nav-list {
  display: flex;
  gap: 28px
}

.nav-link {
  color: var(--gray);
  font-size: 16px;
  transition: color .2s
}

.nav-link:hover {
  color: var(--white)
}

.nav-link::before {
  content: "#";
  color: var(--primary)
}

.burger {
  display: none;
  background: none;
  border: none;
  cursor: pointer;
  flex-direction: column;
  gap: 5px;
  padding: 4px
}

.burger span {
  display: block;
  width: 22px;
  height: 2px;
  background: var(--white)
}

@media(max-width:600px) {
  .nav-list {
    display: none
  }

  .burger {
    display: flex
  }

  .nav-list.open {
    display: flex;
    flex-direction: column;
    position: fixed;
    top: 64px;
    left: 0;
    right: 0;
    background: var(--bg);
    border-bottom: 1px solid var(--border);
    padding: 16px 24px;
    gap: 16px
  }
}

/* ── SIDEBAR ── */
.sidebar {
  position: fixed;
  left: 14px;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  z-index: 99
}

.sidebar-line {
  width: 1px;
  height: 150px;
  background: var(--gray)
}

.sidebar ul {
  display: flex;
  flex-direction: column;
  gap: 10px
}

.sidebar a svg {
  fill: var(--gray);
  transition: fill .25s;
  display: block
}

.sidebar a:hover svg {
  fill: var(--white)
}

.sidebar-email svg {
  animation: sidebarEmailPulse 2.4s ease-in-out infinite
}

.sidebar-email:hover svg {
  fill: var(--primary) !important;
  animation: none
}

@keyframes sidebarEmailPulse {

  0%,
  100% {
    opacity: 1
  }

  50% {
    opacity: .5
  }
}

@media(max-width:1100px) {
  .sidebar {
    display: none
  }
}

/* ── MAIN ── */
.main-container {
  max-width: 1024px;
  margin: 0 auto;
  padding: 105px 24px 0;
  display: flex;
  flex-direction: column;
  gap: 96px
}

@media(max-width:700px) {
  .main-container {
    gap: 56px
  }
}

/* ── HERO ── */
.hero {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 24px;
  margin-top: 40px
}

@media(max-width:700px) {
  .hero {
    flex-direction: column;
    align-items: stretch
  }

  /* Photo first, then the auto-rotating bio -- leads with a face instead
     of a wall of text on mobile. */
  .hero-image {
    order: -1
  }
}

.hero-content {
  flex: 1
}

.hero-role {
  font-size: 13px;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--primary);
  margin-bottom: 12px
}

.hero-role::before {
  content: "// "
}

.hero-content h2 {
  font-size: clamp(20px, 3vw, 30px);
  line-height: 1.3;
  margin-bottom: 14px;
  opacity: 0;
  transform: translateX(-28px);
  animation: slideIn 1s ease forwards
}

.hero-content h2 span {
  color: var(--primary)
}

@keyframes slideIn {
  to {
    opacity: 1;
    transform: translateX(0)
  }
}

.hero-content p {
  line-height: 1.9;
  font-size: 16px;
  border-left: 2px solid var(--primary);
  padding-left: 14px;
  margin-top: 24px
}

.hero-image {
  display: flex;
  flex-direction: column;
  align-items: center;
  animation: float 4s ease-in-out infinite
}

@keyframes float {

  0%,
  100% {
    transform: translateY(0)
  }

  50% {
    transform: translateY(-14px)
  }
}

.hero-image img {
  width: 240px;
  border-radius: 5px;
  object-fit: cover
}

.portfolio-note-wrapper {
  display: flex;
  align-items: center;
  gap: 10px;
  border: 1px solid var(--gray);
  padding: 8px 14px;
  width: fit-content;
  max-width: 100%
}

.purple-square {
  width: 14px;
  height: 14px;
  background: var(--primary);
  flex-shrink: 0
}

.portfolio-note-text {
  display: flex;
  flex-direction: column;
  gap: 3px
}

.portfolio-note {
  font-size: 13px;
  margin: 0;
  white-space: nowrap
}

.portfolio-note span {
  color: var(--white);
  font-weight: bold
}

.portfolio-note-sub {
  font-size: 11px;
  margin: 0
}

.os-link {
  color: var(--white);
  font-weight: bold;
  text-decoration: none;
  border-bottom: 1px dashed var(--primary);
  transition: color .2s, border-color .2s
}

.os-link:hover {
  color: var(--primary);
  border-bottom-style: solid
}

@media(max-width:700px) {
  .portfolio-note-wrapper {
    width: 100%
  }
}

/* ── QUOTE ── */
.quote {
  border: 1px solid var(--gray);
  position: relative
}

.quote blockquote {
  color: var(--white);
  font-size: 22px;
  padding: 36px 48px 12px;
  text-align: center;
  font-style: italic
}

.quote blockquote::before {
  content: '"';
  position: absolute;
  top: -20px;
  left: 8px;
  color: var(--gray);
  font-size: 52px;
  font-weight: 700;
  background: var(--bg);
  padding: 0 4px;
  line-height: 1
}

.quote figcaption {
  display: block;
  text-align: right;
  font-size: 15px;
  color: var(--gray);
  padding: 4px 16px 14px
}

/* ── SECTION HEADER ── */
.section-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 24px
}

.section-header h2 {
  position: relative
}

.section-header h2::before {
  content: "#";
  color: var(--primary)
}

.section-header h2::after {
  content: "";
  position: absolute;
  left: calc(100% + 14px);
  top: 50%;
  transform: translateY(-50%);
  width: 380px;
  height: 1px;
  background: var(--primary)
}

@media(max-width:900px) {
  .section-header h2::after {
    display: none
  }
}

.section-header a {
  color: var(--white);
  text-decoration: underline;
  font-size: 15px
}

/* ── PROJECT CARDS ── */
.project-cards {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 20px;
  align-items: stretch
}

@media(max-width:768px) {
  .project-cards {
    grid-template-columns: repeat(2, minmax(0, 1fr))
  }
}

@media(max-width:480px) {
  .project-cards {
    grid-template-columns: 1fr
  }
}

/* ── MOBILE TEASER CAROUSELS ── */
/* Below 480px, homepage "highlighted" card rows (Projects, Delivery
   Oversight, Tooling teaser, Skills) become swipeable rows -- one
   card/skill-card per view, auto-rotating on their own, but also
   manually swipeable so visitors can skim through faster than the
   auto-advance without opening "View all". Scoped to these rows only --
   the "View all" modals (which reuse .auto-grid too) keep stacking/
   scrolling normally, since browsing everything is the point there.
   JS (initTeaserCarousel in main.js) drives the auto-advance and reads the
   user's manual scroll position back into the rotation index. */
@media(max-width:480px) {

  #projects-container,
  #automation-teaser,
  #delivery-teaser,
  #skills-rows,
  #badges-grid {
    display: flex;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    gap: 0;
    scroll-behavior: smooth;
    scrollbar-width: none
  }

  #projects-container::-webkit-scrollbar,
  #automation-teaser::-webkit-scrollbar,
  #delivery-teaser::-webkit-scrollbar,
  #skills-rows::-webkit-scrollbar,
  #badges-grid::-webkit-scrollbar {
    display: none
  }

  #projects-container .project-card,
  #delivery-teaser .project-card {
    flex: 0 0 100%;
    min-width: 100%;
    height: 460px;
    scroll-snap-align: start
  }

  #automation-teaser .project-card {
    flex: 0 0 100%;
    min-width: 100%;
    height: 250px;
    scroll-snap-align: start
  }

  #skills-rows .skill-row {
    flex: 0 0 100%;
    min-width: 100%;
    height: 366px;
    scroll-snap-align: start
  }

  #badges-grid .badge-board {
    flex: 0 0 100%;
    min-width: 100%;
    scroll-snap-align: start
  }

  /* #skills-rows sits inside .skills-area, a flex row/column with its own
     gap:32px -- the swipe nav, inserted right after #skills-rows, is a
     flex sibling within that same container and inherits that 32px on
     top of its own 4px margin (36px total vs every other row's plain
     4px). Cancel it back down to match. */
  #skills-rows + .swipe-nav {
    margin-top: -28px
  }

  /* Every card in a mobile carousel row is now a fixed height (was
     letting content decide, so cards in the same row landed anywhere
     from 178px to 499px depending on how long that project's/tool's
     copy happened to be) -- clamp the text that used to drive that
     variance instead of letting it overflow the fixed box. */
  #projects-container .project-info h3,
  #delivery-teaser .project-info h3 {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden
  }

  #projects-container .project-info p,
  #delivery-teaser .project-info p {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden
  }

  /* Tech stack, not the detailed fix-line explanation -- keep prob-line
     (the short lightning-icon problem summary) as the card's header
     line, drop only the longer "-> how it was fixed" sentence, and let
     the tech-stack tag list (already present on the gist-sourced cards)
     carry the rest. */
  #automation-teaser .prob-line {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden
  }

  #automation-teaser .cat-tag {
    display: none
  }

  #automation-teaser .fix-line {
    display: none
  }

  /* .acard-header's border-bottom sat with zero gap before the tag
     text's own line-height, so ascenders (P, T, g) nearly touched the
     border -- read at a glance as a line striking through the tags. */
  #automation-teaser .project-card ul {
    display: flex;
    height: auto;
    padding-top: 12px
  }
}

/* Extra cards JS clones in from the "View all" modals so the Projects and
   Tooling teaser rows swipe through everything on mobile, not just the 3
   featured ones -- hidden everywhere except inside that mobile carousel,
   so desktop's normal 3-card teaser grid is untouched. */
.project-card.teaser-extra {
  display: none
}

@media(max-width:480px) {
  .project-card.teaser-extra {
    display: flex
  }
}

/* Swipe nav -- JS inserts one right after each carousel row: a back
   arrow, a "swipe" hint, and a forward arrow. Explicit tappable controls
   for visitors who want them, alongside native touch swiping. */
.swipe-nav {
  display: none
}

@media(max-width:480px) {
  .swipe-nav {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    width: 100%;
    margin-top: 4px;
    padding: 4px 0
  }

  .swipe-hint {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 13px;
    font-weight: 600;
    color: var(--white);
    letter-spacing: .04em
  }

  .swipe-hint-icon {
    display: inline-block;
    font-size: 15px;
    color: var(--primary);
    animation: swipeHintPulse 1.6s ease-in-out infinite
  }

  .swipe-arrow {
    -webkit-appearance: none;
    appearance: none;
    background: none;
    border: 1px solid var(--border);
    color: var(--white);
    width: 28px;
    height: 28px;
    border-radius: 50%;
    font-size: 16px;
    line-height: 1;
    cursor: pointer
  }
}

@media(max-width:480px) and (prefers-reduced-motion: reduce) {
  .swipe-hint-icon {
    animation: none
  }
}

@keyframes swipeHintPulse {

  0%,
  100% {
    transform: translateX(0);
    opacity: .6
  }

  50% {
    transform: translateX(4px);
    opacity: 1
  }
}

.project-card {
  border: 1px solid var(--gray);
  cursor: pointer;
  transition: transform .3s, border-color .3s;
  display: flex;
  flex-direction: column;
  height: 100%;
  overflow: hidden
}

/* hover:hover excludes touch devices -- without this, a tap/swipe-start
   on mobile latches :hover, and the scaled-up card's edge bleeds past its
   own box into the next card's space in the swipeable rows (visible as a
   stray purple line from the border-color change during a swipe). */
@media(hover:hover) {
  .project-card:hover {
    transform: scale(1.03);
    border-color: var(--primary)
  }
}

.card-preview {
  width: 100%;
  height: 188px;
  overflow: hidden;
  border-bottom: 1px solid var(--gray);
  flex-shrink: 0
}

.card-preview.split {
  display: flex;
}

.card-preview.split img {
  width: 50%;
  height: 100%;
  border-right: 1px solid var(--gray);
  border-bottom: none;
  object-fit: contain;
  object-position: center;
}

.card-preview.split img:last-child {
  border-right: none;
}

.card-preview img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: center;
  display: block;
  transition: transform .4s
}

@media(hover:hover) {
  .project-card:hover .card-preview img {
    transform: scale(1.04)
  }
}

.acard-header {
  height: 44px;
  border-bottom: 1px solid var(--gray);
  display: flex;
  align-items: center;
  padding: 0 12px;
  gap: 10px;
  background: var(--surface);
  flex-shrink: 0
}

.acard-emoji {
  font-size: 18px;
  line-height: 1;
  flex-shrink: 0
}

.acard-accent-line {
  height: 2px;
  flex: 1;
  border-radius: 1px;
  opacity: .6
}

.project-card ul {
  display: flex;
  flex-wrap: wrap;
  gap: 0;
  color: var(--gray);
  border-bottom: 1px solid var(--gray);
  padding: 8px;
  font-size: 12px;
  height: 52px;
  overflow: hidden;
  align-content: flex-start
}

.project-card ul li {
  white-space: nowrap
}

.project-card ul li::after {
  content: " | ";
  color: var(--gray);
  opacity: .4
}

.project-card ul li:last-child::after {
  content: ""
}

.project-info {
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex: 1
}

.prob-line {
  color: var(--warn) !important
}

.fix-line {
  color: var(--accent) !important;
  flex: 1
}

.project-links {
  display: flex;
  gap: 6px;
  align-items: center;
  flex-wrap: wrap;
  margin-top: auto;
  padding-top: 8px;
  min-width: 0
}

.project-links button {
  font-size: 11px;
  padding: 5px 8px;
  white-space: nowrap;
  min-width: 0;
  flex-shrink: 1;
  overflow: hidden;
  text-overflow: ellipsis
}

.project-links button a {
  font-size: 11px;
  overflow: hidden;
  text-overflow: ellipsis;
  display: block
}

.os-badge {
  font-size: 10px;
  padding: 3px 6px;
  border: 1px solid #fde68a;
  color: #fbbf24;
  background: transparent;
  display: inline-block;
  white-space: nowrap;
  flex-shrink: 0
}

@media(max-width:500px) {
  .project-links {
    gap: 4px
  }

  .project-links button {
    font-size: 10px;
    padding: 4px 6px
  }

  .os-badge {
    font-size: 9px;
    padding: 2px 5px
  }
}

/* ── AUTOMATION ── */
.auto-intro {
  font-size: 16px;
  line-height: 1.9;
  margin-bottom: 32px;
  border-left: 2px solid var(--primary);
  padding-left: 14px
}

.auto-cats {
  display: flex;
  flex-direction: column;
  gap: 32px
}

.cat-label {
  font-size: 11px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--primary);
  margin-bottom: 20px;
  display: flex;
  align-items: center;
  gap: 10px
}

.cat-label::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--primary);
  opacity: .25
}

.auto-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 20px
}

@media(max-width:768px) {
  .auto-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr))
  }
}

@media(max-width:480px) {
  .auto-grid {
    grid-template-columns: 1fr
  }
}

.cat-tag {
  font-size: 10px;
  text-transform: uppercase;
  color: var(--primary);
  margin-bottom: 4px;
  letter-spacing: .1em
}

#automation-teaser .project-card {
  min-height: 140px
}

#automation-teaser .project-info {
  justify-content: center
}

/* ── SKILLS — row layout ── */
.skills-area {
  display: flex;
  gap: 32px;
  align-items: flex-start
}

.skills-illustration {
  flex-shrink: 0;
  width: 160px
}

.skills-illustration img {
  width: 100%;
  height: auto;
  display: block
}

.skills-rows {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 12px;
  flex: 1;
  width: 100%
}

.skill-row {
  border: 1px solid var(--gray);
  display: flex;
  flex-direction: column;
  height: 100%
}

.skill-row-header {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--gray);
  background: var(--surface);
}

.skill-header-top {
  display: flex;
  align-items: center;
  gap: 8px
}

.skill-row-icon {
  font-size: 16px;
  line-height: 1;
  flex-shrink: 0
}

.skill-row-title {
  color: var(--white);
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .06em
}

.skill-row-sub {
  color: var(--primary);
  font-size: 9px;
  line-height: 1.2
}

.skill-row-body {
  display: flex;
  flex-direction: column;
  padding: 0;
  flex: 1
}

.skill-sub {
  padding: 10px 12px;
  border-bottom: 1px solid var(--border)
}

.skill-sub:last-child {
  border-bottom: none
}

.skill-sub h4 {
  font-size: 10px;
  line-height: 1.4;
  height: 28px;
  overflow: hidden;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--gray);
  margin-bottom: 8px;
  font-weight: 400
}

.skill-grid {
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  gap: 10px;
  height: 96px;
  overflow: hidden;
  color: var(--gray);
  font-size: 11px
}

/* Row height is per row-position (matches across all 3 cards), not
   uniform across a card's own 4 rows — rows 1-2 need 2 lines of
   icons, rows 3-4 now fit in 1 after the badge trim. */
.skill-sub:nth-child(3) .skill-grid,
.skill-sub:nth-child(4) .skill-grid {
  height: 50px;
}

.skill-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  min-width: 40px;
  text-align: center
}

.skill-item i,
.skill-item .skill-glyph {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  font-size: 20px;
  line-height: 1;
  color: var(--gray);
  transition: color .2s
}

.skill-item:hover i,
.skill-item:hover .skill-glyph {
  color: var(--primary)
}

.skill-emoji-gray {
  filter: grayscale(100%) opacity(0.75);
  transition: filter .2s;
}

li:hover .skill-emoji-gray {
  filter: grayscale(0%) opacity(1);
}

.skill-item span {
  font-size: 9px;
  color: var(--gray)
}

@media(max-width:700px) {
  .skills-area {
    flex-direction: column
  }
}

@media(max-width:480px) {
  .skill-row-body {
    flex-direction: column
  }

  .skill-sub {
    border-right: none;
    border-bottom: 1px solid var(--border)
  }

  .skill-sub:last-child {
    border-bottom: none
  }

  /* The fixed heights on .skill-grid/.skill-sub h4 exist to keep dividers
     aligned across the 3 cards when they sit side-by-side on desktop. Once
     stacked full-width on mobile there's nothing to align against, and
     items need fewer lines at this width -- so let both size to content
     instead of reserving desktop-sized empty space. */
  .skill-sub h4 {
    height: auto;
    overflow: visible
  }

  .skill-grid,
  .skill-sub:nth-child(3) .skill-grid,
  .skill-sub:nth-child(4) .skill-grid {
    height: auto;
    overflow: visible
  }
}

/* ── BADGES ── */
.holopin-desc {
  font-size: 13px;
  line-height: 1.8;
  margin-bottom: 18px
}

.badges-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 20px
}

@media(max-width:600px) and (min-width:481px) {
  .badges-grid {
    grid-template-columns: 1fr
  }
}

.badge-board {
  border: 1px solid var(--gray);
  background: #1a1d22;
  display: flex;
  flex-direction: column;
  gap: 0
}

.badge-board-label {
  font-size: 10px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--primary);
  padding: 8px 14px;
  border-bottom: 1px solid var(--gray);
  background: var(--surface)
}

.badge-board a {
  display: block;
  overflow: hidden
}

.badge-board img {
  max-width: 100%;
  display: block
}

.badge-placeholder {
  min-height: 160px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg);
  border-bottom: 1px solid var(--gray);
  padding: 20px
}

.badge-placeholder img {
  max-width: 100%;
  display: block
}

.badge-board button {
  margin: 12px 14px;
  width: calc(100% - 28px);
  align-self: flex-start
}

/* ── HOLOPIN ── */
.holopin-desc {
  font-size: 13px;
  line-height: 1.8;
  margin-bottom: 18px
}




/* ── CONTACTS ── */
.contacts-card {
  border: 1px solid var(--gray);
  padding: 24px
}

.contacts-header {
  display: flex;
  align-items: stretch;
  gap: 40px
}

.contacts-left {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column
}

.contacts-banner {
  width: 100%;
  max-width: 460px;
  height: auto;
  display: block;
  margin-bottom: 8px
}

.contact-form-card {
  position: relative;
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  padding: 24px
}

.contact-form-card .contact-form {
  flex: 1;
  display: flex;
  flex-direction: column
}

.contact-form-card .contact-form textarea {
  flex: 1
}

.contacts-copy {
  font-size: 12px;
  line-height: 1.8;
  margin-top: 24px
}

.contacts-links-card {
  max-width: 320px;
  width: 100%;
  margin: 20px auto 0 auto;
  border: 1px solid var(--border);
  background: var(--surface);
  padding: 20px;
  text-align: left
}

.contacts-info-divider {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 11px;
  color: var(--gray);
  text-align: center;
  margin-bottom: 14px
}

.contacts-info-divider::before,
.contacts-info-divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--primary)
}

.contacts-links {
  display: flex;
  flex-direction: column;
  align-items: flex-start
}

@media(max-width:700px) {
  .contacts-header {
    flex-direction: column
  }

  /* Order: banner/tagline first (unchanged), then the form, then "or find
     me here" as its own plain label, then the links card. .contacts-left
     is unwrapped via display:contents so its children (banner, copy,
     divider) can each be ordered independently rather than moving as one
     block. */
  .contacts-left {
    display: contents
  }

  /* .contacts-header's gap (built for spacing 2 big columns) now applies
     between every one of these unwrapped items instead -- inflating the
     banner-to-copy gap to ~72px with nothing visually filling it. Shrink
     the gap and let the now-redundant individual margins go, since gap
     covers that spacing uniformly. */
  .contacts-header {
    gap: 14px
  }

  .contacts-banner {
    order: 1;
    margin-bottom: 0
  }

  .contacts-copy {
    order: 2;
    margin-top: 0
  }

  .contact-form-card {
    order: 3
  }

  .contacts-info-divider {
    order: 4;
    margin: 0
  }

  .contacts-links-card {
    order: 5
  }

  /* Trim the card's own padding and the gap the form leaves below its
     last field -- 24px card padding + 16px form margin was reserving
     ~40px of dead space below "Send inquiry" for no reason once the
     textarea's flex:1 stretch (a desktop-only side effect of
     align-items:stretch matching the taller sibling column) doesn't
     apply here. */
  .contact-form-card {
    padding: 16px
  }

  .contact-form {
    margin-bottom: 4px
  }
}

.contact-form-card h4 {
  margin-bottom: 14px;
  font-size: 18px;
  line-height: 1.35
}

.required-mark {
  color: var(--primary)
}

.contact-form {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 16px
}

.contact-form label {
  font-size: 10px;
  color: var(--gray);
  margin-top: 6px
}

.contact-form label:first-child {
  margin-top: 0
}

.contact-form input,
.contact-form textarea {
  background: var(--bg);
  border: 1px solid var(--border);
  color: var(--white);
  font-family: inherit;
  font-size: 13px;
  padding: 9px 10px;
  resize: none;
  transition: border-color .2s
}

.contact-form input::placeholder,
.contact-form textarea::placeholder {
  color: var(--gray);
  font-size: 12px
}

.contact-form input:focus,
.contact-form textarea:focus {
  outline: none;
  border-color: var(--primary)
}

.contact-form button {
  width: 100%;
  font-size: 13px
}

.contact-form-error {
  color: var(--red);
  font-size: 12px;
  margin-top: 10px
}

.contact {
  color: var(--gray);
  display: flex;
  gap: 10px;
  align-items: center;
  margin-top: 6px;
  min-width: 0;
  padding: 6px 8px;
  margin-left: -8px;
  transition: background .2s
}

.contact:hover {
  background: var(--bg)
}

.contact svg {
  flex-shrink: 0;
  transition: fill .2s
}

.contact:hover svg {
  fill: var(--primary) !important
}

.contact a {
  color: var(--gray);
  font-size: 15px;
  transition: color .2s;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0
}

.contact a:hover {
  color: var(--white)
}

/* ── FOOTER ── */
footer {
  border-top: 1px solid var(--gray);
  padding: 18px 0;
  margin-top: 100px
}

@media(max-width:700px) {
  footer {
    margin-top: 48px
  }
}

.footer-container {
  max-width: 1024px;
  margin: 0 auto;
  padding: 0 24px;
  display: flex;
  justify-content: space-between;
  align-items: center
}

.footer-row {
  display: flex;
  justify-content: flex-start;
  align-items: center;
  gap: 8px
}

.footer-divider {
  color: var(--border);
  font-size: 14px
}

.copyright {
  font-size: 12px;
  color: var(--gray);
  margin: 0;
  text-align: center;
  flex: 1
}

@media(max-width:600px) {
  /* One line total, not two -- shrink both halves and stop the copyright
     text from claiming the flex remainder (which squeezed it into
     wrapping). !important overrides the inline font-size on the logo
     row's h4/span. */
  .footer-container {
    flex-wrap: nowrap;
    justify-content: center;
    gap: 6px
  }

  .footer-row h4 {
    font-size: 11px !important
  }

  .footer-row span {
    font-size: 9px !important
  }

  .copyright {
    flex: none;
    font-size: 9px;
    white-space: nowrap;
    text-align: center
  }
}

/* ── CREDLY BADGES ── */
.credly-section {
  margin-top: 0
}

.credly-intro {
  font-size: 13px;
  line-height: 1.8;
  margin-bottom: 18px
}

.credly-board {
  background: #111317;
  border: 1px solid var(--gray);
  padding: 28px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px
}

.credly-board-inner {
  width: 100%;
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  justify-content: center;
  align-items: center;
  min-height: 120px
}

.credly-placeholder {
  color: var(--gray);
  font-size: 12px;
  text-align: center;
  border: 1px dashed var(--border);
  padding: 20px 40px;
  font-style: italic
}

.credly-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--primary);
  border: 1px solid var(--primary);
  padding: 8px 16px;
  transition: background .2s
}

.credly-link:hover {
  background: var(--primary);
  color: #fff
}

.credly-note {
  font-size: 11px;
  color: var(--gray);
  opacity: .6;
  text-align: center
}

/* ── MODAL ── */
.modal-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, .88);
  z-index: 9999;
  align-items: center;
  justify-content: center
}

.modal-overlay.open {
  display: flex
}

.modal-box {
  background: var(--bg);
  border: 1px solid var(--primary);
  width: 92vw;
  max-width: 1080px;
  height: 87vh;
  display: flex;
  flex-direction: column
}

.modal-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 11px 16px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0
}

.modal-title {
  font-size: 13px
}

.modal-title span {
  color: var(--primary)
}

.modal-external {
  color: var(--primary);
  font-size: 12px;
  text-decoration: underline
}

.modal-close {
  width: 26px;
  height: 26px;
  background: none;
  border: 1px solid var(--gray);
  color: var(--gray);
  font-size: 14px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center
}

.modal-close:hover {
  border-color: var(--primary);
  color: var(--white);
  background: transparent
}

.modal-body {
  flex: 1;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center
}

.modal-body iframe {
  width: 100%;
  height: 100%;
  border: none
}

.modal-no-embed {
  display: none;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  padding: 24px;
  text-align: center
}

.modal-no-embed p {
  font-size: 13px;
  max-width: 340px;
  line-height: 1.7
}

.modal-no-embed a {
  color: var(--primary);
  text-decoration: underline
}

/* ── BACK TO TOP ── */
#btt {
  position: fixed;
  bottom: 28px;
  right: 24px;
  width: 38px;
  height: 38px;
  background: var(--primary);
  border: none;
  color: #fff;
  font-size: 18px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity .3s;
  z-index: 998;
  clip-path: polygon(50% 0%, 100% 100%, 0% 100%)
}

#btt.visible {
  opacity: 1;
  pointer-events: auto
}

#btt:hover {
  background: var(--accent)
}

@media(max-width:700px) {
  #btt {
    display: none
  }
}

/* ── ALL PROJECTS MODAL ── */
.all-projects-modal {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.85);
  z-index: 2000;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 40px 20px;
  overflow-y: auto
}

.all-projects-modal.open {
  display: flex
}

.all-projects-content {
  background: var(--bg);
  border: 1px solid var(--border);
  max-width: 1200px;
  width: 100%;
  max-height: 90vh;
  overflow-y: auto;
  padding: 24px
}

.all-projects-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 32px;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--border)
}

.all-projects-header h2 {
  color: var(--white);
  margin: 0
}

.close-modal {
  background: none;
  border: 1px solid var(--gray);
  color: var(--gray);
  font-size: 24px;
  width: 36px;
  height: 36px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1
}

.close-modal:hover {
  border-color: var(--primary);
  color: var(--white)
}

.all-projects-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 20px
}

@media(max-width:900px) {
  .all-projects-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr))
  }
}

@media(max-width:600px) {
  .all-projects-grid {
    grid-template-columns: 1fr
  }
}

/* ── LOADER ── */
.loader-overlay {
  position: fixed;
  top: 0; left: 0; width: 100%; height: 100%;
  background-color: var(--bg);
  z-index: 9999;
  display: flex;
  justify-content: center;
  align-items: center;
  transition: opacity 0.5s ease;
}
.loader-mark {
  width: min(180px, 50vw);
  height: auto;
  animation: loaderPulse 1.4s ease-in-out infinite;
}
@keyframes loaderPulse {
  0%, 100% { transform: scale(1); opacity: 0.85; }
  50% { transform: scale(1.08); opacity: 1; }
}

/* ── MARQUEE (Trusted By) ── */
.marquee-header {
  align-items: center;
  gap: 16px;
  margin-bottom: 20px;
}
.marquee-header h2 {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}
.marquee-header h2::before {
  content: none;
}
.marquee-header h2::after {
  display: none;
}
.marquee-header .marquee-line {
  flex: 1;
  height: 1px;
  background: var(--primary);
}
.marquee-section {
  padding-top: 32px;
  padding-bottom: 8px;
  margin-top: -56px;
  margin-bottom: -56px;
  overflow: hidden;
}

@media(max-width:700px) {
  /* These negative margins were tuned against the desktop 96px
     .main-container gap (leaving ~40px on each side) -- at the mobile
     56px gap they cancelled it out completely, leaving 0px between
     Skills/Marquee and Marquee/Badges while every other section kept
     its full 56px, which is what actually made the Tooling-to-Skills
     gap look oversized: it wasn't wrong, its neighbors were both 0. */
  .marquee-section {
    margin-top: -33px;
    margin-bottom: -33px
  }
}
.marquee-container {
  overflow: hidden;
  white-space: nowrap;
  display: flex;
  align-items: center;
  position: relative;
  mask-image: linear-gradient(to right, transparent, black 10%, black 90%, transparent);
  -webkit-mask-image: linear-gradient(to right, transparent, black 10%, black 90%, transparent);
}
.marquee-track {
  display: flex;
  align-items: center;
  gap: 64px;
  animation: marquee 35s linear infinite;
}
.marquee-container:hover .marquee-track {
  animation-play-state: paused;
}
.marquee-track img {
  height: 64px;
  width: auto;
  max-width: 220px;
  object-fit: contain;
  filter: grayscale(100%) opacity(0.7);
  transition: filter 0.3s ease;
  flex-shrink: 0;
}
.marquee-track img:hover {
  filter: grayscale(0%) opacity(1);
}
@keyframes marquee {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

/* ── PROJECT CARD CAROUSEL ── */
.carousel-container {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
}
.carousel-track {
  display: flex;
  width: 100%;
  height: 100%;
  transition: transform 0.4s ease-in-out;
}
.carousel-slide {
  flex: 0 0 100%;
  width: 100%;
  height: 100%;
}
.carousel-slide img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top;
  background-color: var(--surface);
}
.carousel-slide img.hero-align-left {
  object-position: left top;
}

.carousel-slide.split {
  display: flex
}

.carousel-slide.split img {
  width: 50%;
  height: 100%;
  border-right: 1px solid var(--gray);
  object-fit: contain;
  object-position: center;
  background-color: var(--surface)
}

.carousel-slide.split img:last-child {
  border-right: none
}

.carousel-slide.full img {
  object-fit: contain;
  object-position: center
}

/* ── CONTACT FORM SUCCESS TERMINAL ── */
.cf-result-title {
  margin-top: 44px;
  text-align: center;
  font-size: 22px;
  color: var(--primary);
  text-shadow: 0 0 20px rgba(199, 120, 221, .4)
}

.cf-terminal {
  margin-top: 16px;
  background: #1a1c23;
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 14px;
  font-size: 12px;
  text-align: left
}

.cf-terminal-line {
  color: var(--gray);
  opacity: .85;
  margin-bottom: 8px;
  line-height: 2.2
}

.cf-terminal-line:last-child {
  margin-bottom: 0
}

.cf-terminal-line span {
  color: var(--primary)
}

.cf-cursor {
  display: inline-block;
  width: 7px;
  height: 12px;
  background: var(--primary);
  margin-left: 4px;
  vertical-align: middle;
  animation: cfCursorBlink 1s infinite
}

@keyframes cfCursorBlink {
  50% {
    opacity: 0
  }
}

/* ── MINI MONSTER (contact form success state) ── */
/* Straddles the card's top border, same relationship as the 404 page:
   Body spans 320px from the stage top, the card itself covers the
   bottom part, so only the head/horns/eyes poke out above the card. */
.mini-monster-frame {
  position: absolute;
  top: -66px;
  left: 50%;
  transform: translateX(-50%);
  width: 165px;
  height: 70px;
  overflow: hidden;
  pointer-events: none;
  z-index: 1
}

.mini-monster-stage {
  position: relative;
  width: 500px;
  height: 400px;
  transform: scale(.33);
  transform-origin: top left
}

.mini-monster-stage .Body {
  position: absolute;
  z-index: 1;
  overflow: hidden;
  left: 160px;
  width: 180px;
  height: 320px;
  background-color: var(--primary);
  border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%
}

.mini-monster-stage .Body::before {
  content: "";
  width: 35px;
  height: 4px;
  background: var(--bg);
  left: 48px;
  top: 70px;
  position: absolute;
  z-index: 1;
  transform: rotate(30deg)
}

.mini-monster-stage .Body::after {
  content: "";
  width: 35px;
  height: 4px;
  background: var(--bg);
  right: 48px;
  top: 70px;
  position: absolute;
  z-index: 100;
  transform: rotate(-30deg)
}

.mini-monster-stage .LeftEye,
.mini-monster-stage .LeftEyeLeft {
  width: 30px;
  height: 30px;
  background: var(--white);
  border-radius: 30px;
  border: solid 1px var(--bg);
  left: 45px;
  top: 70px;
  position: absolute;
  overflow: hidden
}

.mini-monster-stage .LeftEye::after {
  content: "";
  width: 20px;
  height: 20px;
  background: var(--bg);
  border-radius: 30px;
  right: -3px;
  top: 5px;
  position: absolute;
  z-index: 1;
  animation: miniRERight 1s forwards
}

.mini-monster-stage .LeftEyeLeft::after {
  content: "";
  width: 20px;
  height: 20px;
  background: var(--bg);
  border-radius: 30px;
  right: 13px;
  top: 5px;
  position: absolute;
  z-index: 1;
  animation: miniRELeft 1s forwards
}

.mini-monster-stage .RightEye,
.mini-monster-stage .RightEyeRight {
  width: 30px;
  height: 30px;
  background: var(--white);
  border-radius: 30px;
  border: solid 1px var(--bg);
  right: 45px;
  top: 70px;
  position: absolute;
  overflow: hidden
}

.mini-monster-stage .RightEye::after {
  content: "";
  width: 20px;
  height: 20px;
  background: var(--bg);
  border-radius: 30px;
  left: -4px;
  top: 5px;
  position: absolute;
  z-index: 1;
  animation: miniRELeft 1s forwards
}

.mini-monster-stage .RightEyeRight::after {
  content: "";
  width: 20px;
  height: 20px;
  background: var(--bg);
  border-radius: 30px;
  left: -4px;
  top: 5px;
  position: absolute;
  z-index: 1;
  animation: miniRERight 1s forwards
}

@keyframes miniRERight {
  from {
    left: -4px
  }

  to {
    left: 15px
  }
}

@keyframes miniRELeft {
  from {
    left: 15px
  }

  to {
    left: -4px
  }
}

.mini-monster-stage .EyeShadows {
  width: 35px;
  height: 27px;
  background: rgba(0, 0, 0, .4);
  border-radius: 100px / 50px;
  opacity: .1;
  right: 35px;
  top: 70px;
  position: absolute;
  z-index: -1;
  transform: rotate(-50deg)
}

.mini-monster-stage .EyeShadows::after {
  content: "";
  width: 35px;
  height: 27px;
  background: rgba(0, 0, 0, .4);
  border-radius: 100px / 50px;
  opacity: 1;
  left: -47px;
  top: -58px;
  position: absolute;
  z-index: 5;
  transform: rotate(-90deg)
}

.mini-monster-stage .MouthShadows {
  width: 15px;
  height: 20px;
  background: rgba(0, 0, 0, .4);
  border-radius: 50%;
  opacity: .1;
  right: 25px;
  top: 130px;
  position: absolute;
  z-index: -1;
  transform: rotate(-50deg)
}

.mini-monster-stage .MouthShadows::after {
  content: "";
  width: 15px;
  height: 20px;
  background: rgba(0, 0, 0, .4);
  border-radius: 80%;
  left: -70px;
  top: -85px;
  position: absolute;
  z-index: 5;
  transform: rotate(-90deg);
  opacity: 1
}

.mini-monster-stage .Mouth {
  width: 50px;
  height: 20px;
  left: 67px;
  top: 125px;
  position: absolute;
  z-index: 1;
  background: var(--bg);
  border-radius: 100px / 50px;
  overflow: hidden
}

.mini-monster-stage .Mouth::before {
  content: "";
  left: 30px;
  top: 0;
  position: absolute;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-top: 10px solid var(--white)
}

.mini-monster-stage .Theet {
  width: 50px;
  height: 20px;
  left: 67px;
  top: 125px;
  position: absolute;
  z-index: 1;
  border-radius: 100px / 50px;
  overflow: hidden
}

.mini-monster-stage .Theet::after {
  content: "";
  left: 20px;
  top: 0;
  position: absolute;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-top: 10px solid var(--white)
}

.mini-monster-stage .Theet::before {
  content: "";
  left: 10px;
  top: 0;
  position: absolute;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-top: 10px solid var(--white)
}

.mini-monster-stage .RightHand {
  width: 100px;
  height: 200px;
  right: 120px;
  top: 149px;
  position: absolute;
  border-top: 10px solid var(--accent);
  border-left: 0;
  border-right: 0;
  border-bottom: 0;
  border-radius: 50% / 80px 100px 0 0
}

.mini-monster-stage .RightHand::before {
  right: -3px;
  top: 30px;
  position: absolute;
  content: "";
  background: var(--accent);
  transform: rotate(50deg);
  width: 20px;
  height: 3px;
  border-radius: 50%
}

.mini-monster-stage .RightHand::after {
  right: 4px;
  top: 33px;
  position: absolute;
  content: "";
  background: var(--accent);
  transform: rotate(-90deg);
  width: 20px;
  height: 3px;
  border-radius: 50%
}

.mini-monster-stage .LeftHand {
  width: 100px;
  height: 200px;
  left: 120px;
  top: 150px;
  position: absolute;
  border-top: 10px solid var(--accent);
  border-left: 0;
  border-right: 0;
  border-bottom: 0;
  border-radius: 50% / 80px 100px 0 0
}

.mini-monster-stage .LeftHand::before {
  left: 0;
  top: 33px;
  position: absolute;
  content: "";
  background: var(--accent);
  transform: rotate(90deg);
  width: 20px;
  height: 3px;
  border-radius: 50%
}

.mini-monster-stage .LeftHand::after {
  left: -7px;
  top: 32px;
  position: absolute;
  content: "";
  background: var(--accent);
  transform: rotate(-50deg);
  width: 20px;
  height: 3px;
  border-radius: 50%
}

.mini-monster-stage .Horns {
  width: 150px;
  height: 90px;
  border-radius: 50%;
  left: 169px;
  top: -30px;
  border: 4px solid transparent;
  box-shadow: inset 0px 16px var(--primary), inset 0px 16px 1px 1px var(--primary);
  transform: rotate(-180deg);
  position: absolute;
  overflow: hidden;
  z-index: 0
}

.mini-monster-stage .Horns::after {
  right: 5px;
  top: 30px;
  position: absolute;
  content: "";
  background: var(--warn);
  width: 5px;
  height: 5px;
  border-radius: 50%;
  opacity: .7
}

.mini-monster-stage .Horns::before {
  right: 15px;
  top: 22px;
  position: absolute;
  content: "";
  background: var(--warn);
  width: 7px;
  height: 7px;
  border-radius: 50%;
  opacity: .7
}

.mini-monster-stage .HornsExtras {
  width: 150px;
  height: 90px;
  border-radius: 50%;
  left: 135px;
  top: -30px;
  border: 4px solid transparent;
  background: transparent;
  position: absolute;
  overflow: hidden;
  z-index: 1
}

.mini-monster-stage .HornsExtras::after {
  left: 9px;
  top: 29px;
  position: absolute;
  content: "";
  background: var(--warn);
  width: 5px;
  height: 5px;
  border-radius: 50%;
  opacity: .7
}

.mini-monster-stage .HornsExtras::before {
  left: 1px;
  top: 37px;
  position: absolute;
  content: "";
  background: var(--warn);
  width: 6px;
  height: 6px;
  border-radius: 50%;
  opacity: .7
}

.mini-monster-stage .BodyTexture {
  width: 500px;
  height: 100px;
  border: solid 3px var(--texture);
  border-color: var(--texture) transparent transparent transparent;
  border-radius: 60% / 100px 100px 0 0;
  right: -150px;
  top: 80px;
  position: absolute;
  transform: rotate(180deg);
  opacity: .35
}
