:root {
  --portfolio-top-bg: #0e0a1c;
  --portfolio-top-text: #c9a8ff;
  --portfolio-top-strong: #f5f1fa;
  --portfolio-top-accent: #9a62f6;
  --portfolio-top-accent-hover: #8447ec;
  --portfolio-top-accent-ink: #ffffff;
  --portfolio-top-focus: #f5f1fa;
  --portfolio-top-font: "Plus Jakarta Sans", sans-serif;
  --portfolio-skill-font-size: clamp(16px, 1.5vw, 22px);
}

:root[data-portfolio-theme="light"] {
  --portfolio-top-bg: #f5f1fa;
  --portfolio-top-text: #4d317b;
  --portfolio-top-strong: #0e0a1c;
  --portfolio-top-focus: #4d317b;
}

/* Case study pages reuse the homepage header with its light-mode colours */
.portfolio-header--case-study {
  --portfolio-top-bg: transparent;
  --portfolio-top-text: #4d317b;
  --portfolio-top-strong: #0e0a1c;
  --portfolio-top-focus: #4d317b;
  --portfolio-menu-bg: #ffffff;
}

:root[data-portfolio-theme="dark"] .portfolio-header--case-study {
  --portfolio-top-text: #c9a8ff;
  --portfolio-top-strong: #f5f1fa;
  --portfolio-top-focus: #f5f1fa;
  --portfolio-menu-bg: #0e0a1c;
}

.portfolio-header,
#bio.portfolio-hero {
  box-sizing: border-box;
  width: calc(100% + 5rem);
  margin-left: calc(-2rem - 8px);
  color: var(--portfolio-top-strong);
  background-color: var(--portfolio-top-bg);
  font-family: var(--portfolio-top-font);
}

.portfolio-header {
  position: relative;
  z-index: 10;
  margin-top: calc(-2rem - 8px);
  border: 0;
}

.portfolio-nav {
  position: relative;
  width: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  background-color: var(--portfolio-top-bg);
  box-shadow: none;
  animation: none;
}

.portfolio-container {
  box-sizing: border-box;
  width: min(1150px, calc(100% - clamp(40px, 11.4vw, 168px)));
  margin: 0 auto;
}

.portfolio-nav__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: clamp(76px, 7.2vw, 104px);
}

.portfolio-nav__primary,
.portfolio-nav__actions,
.portfolio-nav__links {
  display: flex;
  align-items: center;
}

.portfolio-nav__primary {
  gap: clamp(16px, 2.4vw, 36px);
}

.portfolio-nav__actions {
  flex: 0 0 auto;
  gap: clamp(12px, 1.4vw, 20px);
}

.portfolio-logo {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
}

.portfolio-logo img {
  display: block;
  width: clamp(72px, 7.8vw, 112px);
  height: auto;
}

.portfolio-nav__links {
  gap: clamp(20px, 3vw, 44px);
}

.portfolio-nav a {
  color: var(--portfolio-top-text);
  font-family: var(--portfolio-top-font);
  font-size: clamp(16px, 1.8vw, 24px);
  line-height: 1.3;
  text-decoration: none;
}

.portfolio-nav__links a[aria-current="page"] {
  color: var(--portfolio-top-strong);
  font-weight: 700;
}

.portfolio-nav a:hover {
  color: var(--portfolio-top-strong);
}

.portfolio-theme-toggle,
.portfolio-menu-toggle {
  display: inline-flex;
  flex: 0 0 auto;
  width: clamp(44px, 3.75vw, 54px);
  height: clamp(44px, 3.75vw, 54px);
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  border-radius: 50%;
  color: #ffffff;
  background-color: var(--portfolio-top-accent);
  cursor: pointer;
  transition: background-color 150ms ease, box-shadow 150ms ease;
}

.portfolio-theme-toggle:hover,
.portfolio-menu-toggle:hover {
  background-color: var(--portfolio-top-accent-hover);
  box-shadow: 0 0 0 4px rgb(154 98 246 / 30%);
}

.portfolio-theme-toggle:active,
.portfolio-menu-toggle:active {
  box-shadow: 0 0 0 2px rgb(154 98 246 / 30%);
}

.portfolio-icon {
  display: block;
  width: 24px;
  height: 24px;
}

/* Theme switch: the new theme grows in a circle from the clicked toggle */
html.is-revealing-theme::view-transition-old(root),
html.is-revealing-theme::view-transition-new(root) {
  animation: none;
  mix-blend-mode: normal;
}

/* Optional warm glow just inside the theme reveal circle's edge, used for
   the PhoenixRise sunrise (see switchTheme in js/theme.js) */
.portfolio-theme-sunrise {
  position: fixed;
  z-index: 2147483000;
  border-radius: 50%;
  box-shadow: inset 0 0 60px 24px rgb(255 190 100 / 45%);
  pointer-events: none;
  transform: translate(-50%, -50%);
}

.portfolio-theme-cover {
  position: fixed;
  z-index: 2147483000;
  inset: 0;
  opacity: 0;
  pointer-events: none;
}

.portfolio-theme-toggle .portfolio-icon {
  width: 30px;
  height: 30px;
  fill: none;
}

.portfolio-theme-icon--moon {
  fill: currentColor;
}

.portfolio-theme-icon--sun-disc,
.portfolio-theme-icon--sun-rays {
  display: none;
}

.portfolio-theme-icon--sun-disc {
  fill: currentColor;
}

.portfolio-theme-icon--sun-rays {
  stroke: currentColor;
  stroke-linecap: round;
  stroke-width: 2;
}

:root[data-portfolio-theme="light"] .portfolio-theme-icon--moon {
  display: none;
}

:root[data-portfolio-theme="light"] .portfolio-theme-icon--sun-disc,
:root[data-portfolio-theme="light"] .portfolio-theme-icon--sun-rays {
  display: block;
}

.portfolio-menu-toggle .portfolio-icon {
  fill: none;
  stroke: currentColor;
  stroke-linecap: round;
  stroke-width: 2;
}

.portfolio-menu-toggle {
  display: none;
}

.portfolio-nav a:focus-visible,
.portfolio-nav button:focus-visible {
  outline: 3px solid var(--portfolio-top-focus);
  outline-offset: 3px;
}

#bio.portfolio-hero {
  position: relative;
  display: block;
  margin-top: 0;
  padding: 0;
  transform: none;
}

.portfolio-hero__inner {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
  align-items: start;
  gap: clamp(36px, 4.4vw, 64px);
  padding-top: clamp(24px, 2vw, 30px);
}

.portfolio-hero__copy {
  min-width: 0;
  padding-top: clamp(28px, 2.9vw, 42px);
}

.portfolio-hero__copy h1 {
  width: auto;
  margin: 0 0 clamp(20px, 2vw, 30px);
  padding: 0;
  border: 0;
  color: var(--portfolio-top-strong);
  font-family: var(--portfolio-top-font);
  font-size: clamp(32px, 3.5vw, 52px);
  font-weight: 800;
  line-height: 1.12;
  text-align: left;
}

.portfolio-hero__greeting {
  color: var(--portfolio-top-text);
}

.portfolio-hero__name {
  position: relative;
  display: inline-block;
  white-space: nowrap;
}

.portfolio-hero__scribble {
  position: absolute;
  right: -0.02em;
  bottom: -0.34em;
  left: -0.02em;
  width: calc(100% + 0.04em);
  height: clamp(12px, 1.4vw, 20px);
  overflow: visible;
}

/* The scribble draws itself along the pen path shortly after load */
.portfolio-hero__scribble-pen {
  stroke-dasharray: 1;
  stroke-dashoffset: 0;
  animation: portfolio-scribble-draw 900ms cubic-bezier(0.65, 0, 0.35, 1) 400ms both;
}

@keyframes portfolio-scribble-draw {
  from {
    stroke-dashoffset: 1;
  }

  to {
    stroke-dashoffset: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .portfolio-hero__scribble-pen {
    animation: none;
  }

  .portfolio-hero__case-studies-arrow {
    transition: none;
  }
}

.portfolio-hero__copy p {
  margin: 0;
  color: var(--portfolio-top-text);
  font-family: var(--portfolio-top-font);
  font-size: clamp(18px, 2.1vw, 31px);
  font-weight: 500;
  line-height: 1.52;
}

.portfolio-hero__copy strong {
  color: var(--portfolio-top-strong);
  font-weight: 800;
}

.portfolio-hero__case-studies-link {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-top: clamp(16px, 1.6vw, 24px);
  color: var(--portfolio-top-text);
  font-family: var(--portfolio-top-font);
  font-size: clamp(16px, 1.4vw, 20px);
  font-weight: 600;
  line-height: 1.5;
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* image/scribble-arrow.png, inlined as a mask so it takes the link's text color
   (a file URL mask is blocked when the page is opened from disk) */
.portfolio-hero__case-studies-arrow {
  display: block;
  width: 24px;
  height: 24px;
  flex: 0 0 auto;
  background-color: currentColor;
  -webkit-mask: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAiCAYAAABbXymAAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAOdEVYdFNvZnR3YXJlAEZpZ21hnrGWYwAAAldJREFUeAGtVruSEkEUPbfnUVsbrZmZGFoG8gkYW1axoFWGbmBRrIHLF4BfsGugiAkYWq5AYK5/AJHpsl8gmdQO022/YGGAYWarTxU9Q8/t07fPvX27CWl41S4EERsJgd68X2sgB1jaxzBiRQKOGOEM5e4RXBGzmE8X7x7+leCKWGKiGgFM4+HpEK6IZ8P6RD2VHMiJfR4rXKvmoNwuIAcyENNf1cYBdxc8A6495hEVkAMZiIXODMbIrceCk0054ZaYyHhMcO2xlUJSP0AOZMmKKe6ADFIwQ0y4hxzYS7yoF0KQ6zw29UJua9ca3w17iWc4MFIQHEsxPLF5DOca3yLHKZKV2JROzLITB5VPZ0H18zs4hg/ymkq/oPqlHMXB8ULTVRDElZBbeu6jAJt+uxBU2q/Vk8ny1bCDSyG7GSHnSbHhBLGu+rGoX+8JwU+sa4WQsV/By4/FVWNZiLTGxLXHOyGPr5Kxx1gHL0lO3B8p7ZfEtiZLyVKJuce6ZkD8dZkVa+R6Sd65X+mcmz9ibDuLu0jDSqcJNbHAJOqfXqylW5Jc3YDkgCvBbMAEPdlGqldHaGkTb36sxyaNFLk0er/skNIwbpdIm1KE1U5Zrc7Mi0b0/e14K7HCzWWtlSRfvK7dL2SQZaD0pFzaR5e1i+VqsQMb5BaLoqRuoiH3B2oPKNK5sl+BhxTEf37+9h4/l2NR0h1C9OLBm2++TCtfsAFMlgyjH7V6ciwhA8IXnZaMdnPzC40P4+DpdMtuTfV41XP26Nm1vAI8lK7chypKhA+HcVjfRqrwH5vr1pnP/pKuAAAAAElFTkSuQmCC") center / contain no-repeat;
  mask: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAiCAYAAABbXymAAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAOdEVYdFNvZnR3YXJlAEZpZ21hnrGWYwAAAldJREFUeAGtVruSEkEUPbfnUVsbrZmZGFoG8gkYW1axoFWGbmBRrIHLF4BfsGugiAkYWq5AYK5/AJHpsl8gmdQO022/YGGAYWarTxU9Q8/t07fPvX27CWl41S4EERsJgd68X2sgB1jaxzBiRQKOGOEM5e4RXBGzmE8X7x7+leCKWGKiGgFM4+HpEK6IZ8P6RD2VHMiJfR4rXKvmoNwuIAcyENNf1cYBdxc8A6495hEVkAMZiIXODMbIrceCk0054ZaYyHhMcO2xlUJSP0AOZMmKKe6ADFIwQ0y4hxzYS7yoF0KQ6zw29UJua9ca3w17iWc4MFIQHEsxPLF5DOca3yLHKZKV2JROzLITB5VPZ0H18zs4hg/ymkq/oPqlHMXB8ULTVRDElZBbeu6jAJt+uxBU2q/Vk8ny1bCDSyG7GSHnSbHhBLGu+rGoX+8JwU+sa4WQsV/By4/FVWNZiLTGxLXHOyGPr5Kxx1gHL0lO3B8p7ZfEtiZLyVKJuce6ZkD8dZkVa+R6Sd65X+mcmz9ibDuLu0jDSqcJNbHAJOqfXqylW5Jc3YDkgCvBbMAEPdlGqldHaGkTb36sxyaNFLk0er/skNIwbpdIm1KE1U5Zrc7Mi0b0/e14K7HCzWWtlSRfvK7dL2SQZaD0pFzaR5e1i+VqsQMb5BaLoqRuoiH3B2oPKNK5sl+BhxTEf37+9h4/l2NR0h1C9OLBm2++TCtfsAFMlgyjH7V6ciwhA8IXnZaMdnPzC40P4+DpdMtuTfV41XP26Nm1vAI8lK7chypKhA+HcVjfRqrwH5vr1pnP/pKuAAAAAElFTkSuQmCC") center / contain no-repeat;
  transition: transform 220ms ease;
}

.portfolio-hero__case-studies-link:hover .portfolio-hero__case-studies-arrow,
.portfolio-hero__case-studies-link:focus-visible .portfolio-hero__case-studies-arrow {
  transform: translateY(4px);
}

.portfolio-hero__case-studies-link:focus-visible {
  outline: 2px solid var(--portfolio-top-focus);
  outline-offset: 4px;
}

.portfolio-hero__art {
  position: relative;
  display: flex;
  width: min(100%, 560px);
  margin: 0 auto;
  justify-content: center;
  min-width: 0;
}

.portfolio-venn-frame {
  position: relative;
  width: 100%;
}

.portfolio-venn {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

/* Sunlight from the theme toggle (the sun, or the moon in dark mode, at the
   top right): each circle floats a little above the page and casts its
   shadow away from the light, longer the farther it is from it, as a point
   light does. js/venn-light.js measures where the light and each circle
   are and sets each circle's shadow offset and softness, at rest and when
   it's selected and lifts higher (a longer, softer shadow). Two layers: a
   tight contact shadow and the cast shadow. Purple-tinted in light mode,
   deeper in dark. Before the script runs, there's no shadow.
   In light mode, hovering or focusing the sun swaps in a clearer pair: a crisp
   short shadow that shows the direction and a long soft one for depth. */
.portfolio-venn {
  --venn-contact-colour: rgb(45 28 85 / 28%);
  --venn-cast-colour: rgb(60 38 110 / 34%);
  --venn-sun-contact-colour: rgb(60 38 110 / 25%);
  --venn-sun-cast-colour: rgb(60 38 110 / 20%);
  --venn-ease: 350ms;
}

:root[data-portfolio-theme="dark"] .portfolio-venn {
  --venn-contact-colour: rgb(0 0 0 / 60%);
  --venn-cast-colour: rgb(0 0 0 / 70%);
  --venn-ease: 200ms;
}

.portfolio-venn__circle {
  --venn-rest: drop-shadow(var(--rest-contact-x, 0) var(--rest-contact-y, 0) var(--rest-contact-blur, 0) var(--venn-contact-colour))
    drop-shadow(var(--rest-x, 0) var(--rest-y, 0) var(--rest-blur, 0) var(--venn-cast-colour));
  --venn-shadow: drop-shadow(var(--lift-contact-x, 0) var(--lift-contact-y, 0) var(--lift-contact-blur, 0) var(--venn-contact-colour))
    drop-shadow(var(--lift-x, 0) var(--lift-y, 0) var(--lift-blur, 0) var(--venn-cast-colour));
  --venn-sun: drop-shadow(var(--sun-contact-x, 0) var(--sun-contact-y, 0) var(--sun-contact-blur, 0) var(--venn-sun-contact-colour))
    drop-shadow(var(--sun-x, 0) var(--sun-y, 0) var(--sun-blur, 0) var(--venn-sun-cast-colour));
}

.portfolio-venn__circle {
  --venn-brighten: 1.12;
  fill-opacity: 0.8;
  transition: filter var(--venn-ease) ease;
}

.portfolio-venn__circle[data-circle="accessibility"] {
  --venn-brighten: 1.5;
}

/* Rings drawn over all three circles, just outside each edge, shown for the
   selected one: the resume's soft 4px purple ring at 30% */
.portfolio-venn__outlines circle {
  fill: none;
  stroke: rgb(154 98 246);
  stroke-opacity: 0;
  stroke-width: 4;
  pointer-events: none;
  transition: stroke-opacity 200ms ease;
}

.portfolio-venn__labels {
  fill: #0e0a1c;
  font-family: var(--portfolio-top-font);
  font-size: 34px;
  pointer-events: none;
}

.portfolio-venn__label--light {
  fill: #ffffff;
}

/* Each circle links to its part of the About page */
.portfolio-venn__link {
  cursor: pointer;
  outline: none;
}

/* A circle is selected while it's hovered or has keyboard focus. Only the
   topmost circle under the pointer is hovered, so just one circle is ever
   selected. */
.portfolio-hero__art:has([data-circle="empathy"]:is(:hover, :focus-visible))
  [data-circle="empathy"],
.portfolio-hero__art:has([data-circle="human-centered"]:is(:hover, :focus-visible))
  [data-circle="human-centered"],
.portfolio-hero__art:has([data-circle="accessibility"]:is(:hover, :focus-visible))
  [data-circle="accessibility"] {
  --venn-selected: 1;
  --venn-ease: 200ms;
}

.portfolio-venn__circle {
  filter: brightness(calc(1 + (var(--venn-brighten) - 1) * var(--venn-selected, 0)))
    var(--venn-cast, var(--venn-rest));
}

/* The sun casts the clearer shadows, in light mode only. Hover is for real
   pointers, since a tap would leave it stuck on. A selected circle keeps its
   own shadow (below). */
:root[data-portfolio-theme="light"]:has(.portfolio-theme-toggle:focus-visible)
  .portfolio-venn__circle {
  --venn-cast: var(--venn-sun);
}

@media (hover: hover) {
  :root[data-portfolio-theme="light"]:has(.portfolio-theme-toggle:hover)
    .portfolio-venn__circle {
    --venn-cast: var(--venn-sun);
  }
}

.portfolio-hero__art:has([data-circle="empathy"]:is(:hover, :focus-visible))
  .portfolio-venn__circle[data-circle="empathy"],
.portfolio-hero__art:has([data-circle="human-centered"]:is(:hover, :focus-visible))
  .portfolio-venn__circle[data-circle="human-centered"],
.portfolio-hero__art:has([data-circle="accessibility"]:is(:hover, :focus-visible))
  .portfolio-venn__circle[data-circle="accessibility"] {
  filter: brightness(var(--venn-brighten)) var(--venn-shadow);
}

.portfolio-venn__outlines circle {
  stroke-opacity: calc(0.3 * var(--venn-selected, 0));
}

/* Keyboard focus shows the outline in full, in the focus colour */
.portfolio-venn__link[data-circle="empathy"]:focus-visible
  ~ .portfolio-venn__outlines [data-circle="empathy"],
.portfolio-venn__link[data-circle="human-centered"]:focus-visible
  ~ .portfolio-venn__outlines [data-circle="human-centered"],
.portfolio-venn__link[data-circle="accessibility"]:focus-visible
  ~ .portfolio-venn__outlines [data-circle="accessibility"] {
  stroke: var(--portfolio-top-focus);
  stroke-opacity: 1;
  stroke-width: 4;
}

.portfolio-home {
  overflow-x: clip;
  background-color: var(--portfolio-top-bg);
  margin-bottom: 0;
  padding-bottom: 0;
}

.portfolio-home,
.portfolio-home a,
.portfolio-home button {
  cursor: url("../image/scribble-mouse.png") 8 8, auto;
}

.portfolio-skills {
  padding: clamp(24px, 4vw, 56px) 0 clamp(24px, 3vw, 40px);
  color: var(--portfolio-top-strong);
  background-color: var(--portfolio-top-bg);
  font-family: var(--portfolio-top-font);
}

.portfolio-skills h2 {
  margin: 0 0 16px;
  color: var(--portfolio-top-strong);
  font-family: var(--portfolio-top-font);
  font-size: var(--portfolio-skill-font-size);
  font-weight: 500;
  line-height: 1.52;
  text-align: left;
}

.portfolio-skills__content {
  width: 100%;
  max-width: 100%;
}

.portfolio-skills__list {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-start;
  gap: 12px;
}

.portfolio-skills__list button {
  display: inline-flex;
  min-height: 44px;
  box-sizing: border-box;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding-block: 10px;
  padding-inline: 24px;
  border: 2px solid var(--portfolio-top-accent);
  border-radius: 999px;
  color: var(--portfolio-top-strong);
  background-color: transparent;
  font-family: var(--portfolio-top-font);
  font-size: var(--portfolio-skill-font-size);
  font-weight: 400;
  line-height: 1.2;
  cursor: pointer;
  transition: background-color 150ms ease, color 150ms ease, border-color 150ms ease;
}

.portfolio-skills__list button:hover {
  background-color: rgb(154 98 246 / 10%);
}

.portfolio-skills__list button[aria-pressed="true"],
.portfolio-skills__list button[aria-pressed="true"]:hover {
  color: #0e0a1c;
  background-color: var(--portfolio-top-accent);
}

.portfolio-skills__list button:focus-visible {
  outline: 2px solid var(--portfolio-top-accent);
  outline-offset: 2px;
}

#featured-projects {
  box-sizing: border-box;
  width: calc(100% + 5rem);
  margin: 0 0 0 calc(-2rem - 8px);
  padding: clamp(24px, 3vw, 40px) 0 clamp(40px, 5vw, 72px);
  color: var(--portfolio-top-strong);
  font-family: var(--portfolio-top-font);
  background-color: var(--portfolio-top-bg);
  /* Nothing here, such as the orbiting satellite, may scroll the page
     sideways */
  overflow-x: clip;
}

/* The wide spacing around the cards leaves room for the ALEASAT satellite
   to orbit past its card's edges without covering anything */
.portfolio-featured-projects__title {
  margin: 0 0 clamp(56px, 8vw, 112px);
  padding: 0;
  border: 0;
  color: var(--portfolio-top-strong);
  font-family: var(--portfolio-top-font);
  font-size: clamp(32px, 4vw, 56px);
  font-weight: 800;
  line-height: 1.2;
  text-align: center;
}

.portfolio-case-studies {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  align-items: stretch;
  gap: clamp(56px, 8vw, 112px);
  width: min(1280px, calc(100% - clamp(112px, 16vw, 224px)));
  margin: 0 auto;
}

.portfolio-visually-hidden {
  position: absolute;
  overflow: hidden;
  width: 1px;
  height: 1px;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  clip-path: inset(50%);
}

.portfolio-case-card {
  --portfolio-case-padding: clamp(24px, 2.4vw, 36px);
  position: relative;
  display: flex;
  min-width: 0;
  min-height: clamp(380px, 26vw, 420px);
  box-sizing: border-box;
  flex-direction: column;
  overflow: hidden;
  padding: var(--portfolio-case-padding);
  border-radius: clamp(14px, 1.5vw, 22px);
  text-decoration: none;
  transform: rotate(0);
  transition: opacity 200ms ease, transform 180ms ease, box-shadow 180ms ease;
}

.portfolio-case-card.is-filtering-out {
  opacity: 0;
  pointer-events: none;
}

.portfolio-case-card[hidden] {
  display: none;
}

/* Hover lifts the card with a shadow only; it no longer tilts */
.portfolio-case-card:hover,
.portfolio-case-card:focus-visible {
  box-shadow: 0 18px 40px rgb(0 0 0 / 20%);
}

.portfolio-case-card:focus-visible {
  outline: 3px solid var(--portfolio-top-focus);
  outline-offset: 5px;
}

.portfolio-cursor-label {
  position: fixed;
  z-index: 10000;
  top: 0;
  left: 0;
  padding: 0.22em 0.65em;
  border-radius: 7px;
  color: #ffffff;
  background-color: #a68aec;
  font-family: var(--portfolio-top-font);
  font-size: clamp(13px, 1.2vw, 17px);
  line-height: 1.35;
  pointer-events: none;
  visibility: hidden;
  opacity: 0;
  transition: opacity 140ms ease;
  text-align: center;
  white-space: pre;
}

.portfolio-cursor-label.is-visible {
  visibility: visible;
  opacity: 1;
}

.portfolio-case-card--aleasat {
  color: #ffffff;
  background-color: #050505;
}

/* main.css gives every hovered link an invalid colour, which falls back to
   the page's text colour (dark in light mode); keep the dark card's text
   white in either theme */
.portfolio-case-card--aleasat:hover,
.portfolio-case-card--aleasat:focus-visible,
.portfolio-case-card--aleasat:visited,
.portfolio-case-card--aleasat .portfolio-case-card__copy,
.portfolio-case-card--aleasat h3,
.portfolio-case-card--aleasat .portfolio-case-card__eyebrow {
  color: #ffffff;
}

.portfolio-case-card--phoenixrise {
  color: #0e0a1c;
  background-color: #b5eaf5;
}

/* A soft sage from UX Was Here's green Beginner milestone badge (#88a860),
   a pastel like PhoenixRise's cyan and Quebec's grey-lavender */
.portfolio-case-card--ux-was-here {
  color: #0e0a1c;
  background-color: #d7e8c6;
  align-self: start;
  min-height: 0;
}

.portfolio-case-card--quebec {
  color: #0e0a1c;
  background: linear-gradient(155deg, #e8e0e9 0%, #77778e 100%);
}

.portfolio-case-card--ux-was-here,
.portfolio-case-card--ux-was-here:hover,
.portfolio-case-card--ux-was-here:focus-visible,
.portfolio-case-card--ux-was-here:visited,
.portfolio-case-card--quebec,
.portfolio-case-card--quebec:hover,
.portfolio-case-card--quebec:focus-visible,
.portfolio-case-card--quebec:visited,
.portfolio-case-card--ux-was-here .portfolio-case-card__copy,
.portfolio-case-card--quebec .portfolio-case-card__copy,
.portfolio-case-card--ux-was-here h3,
.portfolio-case-card--quebec h3 {
  color: #000000;
}

.portfolio-case-card--ux-was-here .portfolio-case-card__eyebrow span,
.portfolio-case-card--quebec .portfolio-case-card__eyebrow span {
  color: #5b2fb3;
}

.portfolio-case-card--phoenixrise,
.portfolio-case-card--phoenixrise:hover,
.portfolio-case-card--phoenixrise:focus-visible,
.portfolio-case-card--phoenixrise:visited,
.portfolio-case-card--phoenixrise .portfolio-case-card__copy,
.portfolio-case-card--phoenixrise h3,
.portfolio-case-card--phoenixrise .portfolio-case-card__eyebrow,
.portfolio-case-card--phoenixrise .portfolio-case-card__tags li {
  color: #0e0a1c;
}

.portfolio-case-card__copy {
  position: relative;
  z-index: 1;
}

/* PhoenixRise: the layered Auri (body and two wings) and the painted-out
   sky behind it, laid over the leftmost phone's welcome screen
   (js/phoenixrise-card.js places and flies them). Hidden until its layers
   have loaded, so the screen always shows an Auri. */
.portfolio-case-card__auri {
  position: absolute;
  z-index: 2;
  inset: 0;
  pointer-events: none;
}

.portfolio-case-card__auri img {
  position: absolute;
  display: block;
  max-width: none;
  margin: 0;
  opacity: 0;
}

.portfolio-case-card__auri.is-active img {
  opacity: 1;
}

/* The flight moves the outer wrapper; the inner one lifts the body on each
   downstroke and swells it as it ignites. Inside, each layer sits at its
   share of Auri's box; the wings turn from their roots (set by the
   script). */
.portfolio-case-card__auri-flyer,
.portfolio-case-card__auri-beat,
.portfolio-case-card__auri-rig {
  position: absolute;
  display: block;
}

.portfolio-case-card__auri-flyer,
.portfolio-case-card__auri-beat {
  will-change: transform;
}

.portfolio-case-card__auri-beat,
.portfolio-case-card__auri-rig {
  inset: 0;
}

.portfolio-case-card__auri-beat {
  transform-origin: 50% 55%;
}

.portfolio-case-card__auri-wing {
  will-change: transform;
}

/* Auri catching fire: a gold-and-orange copy that fades in over it */
.portfolio-case-card__auri-rig--flame {
  opacity: 0;
  filter: sepia(1) saturate(5) hue-rotate(-18deg) brightness(1.15)
    drop-shadow(0 0 6px rgb(255 160 50 / 80%));
}

/* The gold bursts and embers, as when the egg on the PhoenixRise case
   study cracks (css/phoenixrise.css), and the ashes Auri is reborn from */
.portfolio-case-card__auri-burst,
.portfolio-case-card__auri-ash,
.portfolio-case-card__auri-ember {
  position: absolute;
  border-radius: 50%;
  opacity: 0;
  pointer-events: none;
}

.portfolio-case-card__auri-burst {
  background: radial-gradient(
    circle,
    rgb(255 210 122 / 90%) 0%,
    rgb(255 179 71 / 45%) 40%,
    rgb(255 179 71 / 0%) 70%
  );
}

.portfolio-case-card__auri-ember {
  width: 5px;
  height: 5px;
  background: radial-gradient(circle, #ffe6b0 0%, #f5b544 55%, rgb(245 140 40 / 0%) 100%);
  box-shadow: 0 0 6px rgb(245 181 68 / 55%);
}

/* Small grey flakes with a dying ember glow */
.portfolio-case-card__auri-ash {
  width: 4px;
  height: 3px;
  border-radius: 40% 60% 50% 45%;
  background: radial-gradient(circle, #f0b56a 0%, #8d8279 55%, #5f5a56 100%);
  box-shadow: 0 0 4px rgb(245 160 70 / 45%);
}

/* Reduced motion: Auri stays on the screen and only fades a little */
@media (prefers-reduced-motion: reduce) {
  .portfolio-case-card__auri-rig:not(.portfolio-case-card__auri-rig--flame) {
    transition: opacity 250ms ease;
  }

  .portfolio-case-card--phoenixrise:is(:hover, :focus-visible)
    .portfolio-case-card__auri-rig:not(.portfolio-case-card__auri-rig--flame) {
    opacity: 0.7;
  }
}

.portfolio-case-card__eyebrow {
  margin: 0 0 clamp(14px, 1.4vw, 20px);
  color: inherit;
  font-family: var(--portfolio-top-font);
  font-size: clamp(16px, 1.4vw, 20px);
  font-weight: 800;
  line-height: 1.4;
}

.portfolio-case-card__eyebrow span {
  margin-left: 0.35em;
  color: #c9a8ff;
}

.portfolio-case-card--phoenixrise .portfolio-case-card__eyebrow span {
  color: #3e2762;
}

.portfolio-case-card h3 {
  margin: 0 0 clamp(12px, 1.2vw, 18px);
  color: inherit;
  font-family: var(--portfolio-top-font);
  font-size: clamp(22px, 2.3vw, 34px);
  font-weight: 800;
  line-height: 1.35;
}

.portfolio-case-card__tags {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 10px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.portfolio-case-card__tags li {
  margin: 0;
  padding: 0.22em 0.65em;
  border: 1px solid rgb(154 98 246 / 35%);
  border-radius: 7px;
  color: #e2d3ff;
  background-color: rgb(154 98 246 / 14%);
  font-family: var(--portfolio-top-font);
  font-size: clamp(13px, 1.2vw, 17px);
  line-height: 1.35;
  /* Wrap between tags, never inside one */
  white-space: nowrap;
}

.portfolio-case-card--phoenixrise .portfolio-case-card__tags li {
  color: #3c3489;
  border-color: #c4b8e8;
  background-color: #ede9fb;
}

.portfolio-case-card--ux-was-here .portfolio-case-card__tags li,
.portfolio-case-card--quebec .portfolio-case-card__tags li {
  color: #3c3489;
  border-color: #c4b8e8;
  background-color: #ede9fb;
}

.portfolio-case-card__aleasat-art {
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  aspect-ratio: 2.45;
  height: auto;
}

.portfolio-case-card__website {
  position: absolute;
  right: 0;
  bottom: 0;
  display: block;
  width: 74%;
  /* Leaves breathing room between the laptop and the tags above it */
  height: 84%;
  object-fit: contain;
  object-position: right bottom;
  border-radius: 5px;
}

/* ALEASAT "Coming soon" tag, a small amber pill riding above the orbiting
   satellite. Solid dark so it reads over the card and over the page in
   either theme. */
.portfolio-case-card__orbiter .portfolio-case-card__status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 0.18em 0.6em;
  border: 1px solid rgb(245 181 68 / 40%);
  border-radius: 7px;
  color: #f8e7c4;
  background-color: #1a1611;
  font-family: var(--portfolio-top-font);
  font-size: 13px;
  font-weight: 500;
  line-height: 1.35;
  white-space: nowrap;
}

.portfolio-case-card__status-dot {
  position: relative;
  flex: 0 0 auto;
  width: 6px;
  height: 6px;
  margin: 0;
  border-radius: 50%;
  background-color: #f5b544;
}

/* The dot pulses twice when the card first comes into view, then rests */
.portfolio-case-card__status-dot::after {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background-color: #f5b544;
  content: "";
  opacity: 0;
}

.portfolio-case-card-orbit.is-pulsing .portfolio-case-card__status-dot::after {
  animation: portfolio-status-pulse 2s ease-out 2;
}

@keyframes portfolio-status-pulse {
  0% {
    opacity: 0.6;
    transform: scale(1);
  }

  100% {
    opacity: 0;
    transform: scale(1.6);
  }
}

/* The ALEASAT card sits in a wrapper with the satellite beside it, so the
   satellite can orbit past the card's edges. The wrapper is its own stacking
   context: the orbiter's z-index (set by js/aleasat-card.js) puts it in
   front of the card or behind it. */
.portfolio-case-card-orbit {
  position: relative;
  z-index: 0;
  display: flex;
  min-width: 0;
  flex-direction: column;
  container-type: inline-size;
  transition: opacity 200ms ease, transform 180ms ease;
}

.portfolio-case-card-orbit > .portfolio-case-card {
  z-index: 1;
  flex: 1 1 auto;
}

/* The skill filter hides or fades the card; the wrapper follows */
.portfolio-case-card-orbit:has(> .portfolio-case-card[hidden]) {
  display: none;
}

.portfolio-case-card-orbit:has(> .portfolio-case-card.is-filtering-out) {
  opacity: 0;
}

.portfolio-case-card-orbit > .portfolio-case-card.is-filtering-out {
  opacity: 1;
}

/* The orbiter carries the satellite and its "Coming soon" tag. It's a
   point: the satellite's centre sits on it, and the tag (centred on it)
   just above. At rest it's in front of the card in the empty lower left,
   beside the laptop, with the tag's left edge in line with the card's text
   (the card's padding plus half the tag's 112px width). */
.portfolio-case-card__orbiter {
  --sat-width: 25cqw;
  position: absolute;
  z-index: 2;
  bottom: 21cqw;
  left: calc(clamp(24px, 2.4vw, 36px) + 56px);
  width: 0;
  height: 0;
  pointer-events: none;
}

/* The orbit: one thin ellipse along the card's diagonal, a little past the
   bottom-left and top-right corners. js/aleasat-card.js sizes the path to
   the card (--orbit-path) and starts the loop at the resting spot
   (--orbit-delay); the motion itself is this one linear animation, so the
   speed is the same all the way round. The first half is the front pass,
   bottom-left to top-right in front of the card; the second half is the
   back pass, behind it. The layer changes only at those two ends, outside
   the card. The orbiter never rotates, so the tag stays upright. */
.portfolio-case-card__orbiter.has-orbit {
  top: 0;
  bottom: auto;
  left: 0;
  offset-path: var(--orbit-path);
  offset-rotate: 0deg;
  animation: portfolio-aleasat-orbit 10s linear var(--orbit-delay, 0s) infinite paused;
}

@keyframes portfolio-aleasat-orbit {
  0% {
    offset-distance: 0%;
    z-index: 2;
  }

  50% {
    z-index: 2;
  }

  50.01% {
    z-index: 0;
  }

  100% {
    offset-distance: 100%;
    z-index: 0;
  }
}

/* Plays only while the card is hovered or keyboard focused; otherwise it
   holds still where it is. Touch screens, reduced motion and stacked (one-column)
   layouts never play it. */
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) and (min-width: 901px) {
  .portfolio-case-card-orbit:has(> .portfolio-case-card:hover) .portfolio-case-card__orbiter.has-orbit,
  .portfolio-case-card-orbit:has(> .portfolio-case-card:focus-visible) .portfolio-case-card__orbiter.has-orbit {
    animation-play-state: running;
  }

  /* Pressing and holding on the satellite stops it; letting go lets it
     carry on (js/aleasat-card.js) */
  .portfolio-case-card.is-over-satellite {
    cursor: grab;
  }

  .portfolio-case-card.is-holding-satellite {
    cursor: grabbing;
  }
}

/* Held, or done its one loop (js/aleasat-card.js) */
.portfolio-case-card__orbiter.has-orbit.is-held,
.portfolio-case-card__orbiter.has-orbit.is-done {
  animation-play-state: paused !important;
}

.portfolio-case-card__orbiter .portfolio-case-card__status {
  position: absolute;
  /* Clears the top of the satellite (its image is 0.68 times as tall as
     wide, with the satellite's centre 45% down) */
  bottom: calc(var(--sat-width) * 0.26);
  left: 0;
  transform: translateX(-50%);
}

.portfolio-case-card__satellite {
  position: absolute;
  /* The satellite's own centre sits 55% across and 45% down its image */
  top: calc(var(--sat-width) * -0.304);
  left: calc(var(--sat-width) * -0.55);
  display: block;
  width: var(--sat-width);
  height: auto;
  pointer-events: none;
}

@media (max-width: 660px) {
  .portfolio-case-card__orbiter .portfolio-case-card__status {
    font-size: 12px;
  }

  /* The phone card's 22px padding plus half the smaller tag's width */
  .portfolio-case-card__orbiter {
    left: calc(22px + 52.5px);
  }
}

/* The five phones span the card edge to edge (a small inset keeps the outer
   bezels off the rounded corners) and run off the bottom edge, like the
   ALEASAT laptop, so they read as large as the card allows */
.portfolio-case-card__phoenixrise-art {
  --portfolio-phones-inset: clamp(8px, 1.2vw, 16px);
  display: block;
  width: calc(100% + 2 * (var(--portfolio-case-padding) - var(--portfolio-phones-inset)));
  max-width: none;
  height: auto;
  flex: 0 0 auto;
  min-height: 0;
  margin: auto 0 calc(-1 * var(--portfolio-case-padding));
  margin-left: calc(var(--portfolio-phones-inset) - var(--portfolio-case-padding));
  padding-top: clamp(24px, 2.4vw, 36px);
}

.portfolio-case-card__feature-art {
  display: block;
  width: 100%;
  height: auto;
  min-height: 0;
  flex: 0 0 auto;
  margin: 12px 0 0;
  object-fit: contain;
  object-position: center bottom;
}

.portfolio-case-card__ux-art {
  margin-bottom: calc(-1 * var(--portfolio-case-padding));
}

/* UX Was Here: the mockup sits in a wrapper (which takes over its spacing)
   that the shared portfolios fly in. On hover or keyboard focus three small
   portfolios rise one at a time out of the front laptop's screen, curve up
   and to the right over the back laptop, and fade away, as if designers
   were sharing their work (js/ux-was-here-card.js, which sets the path).
   They're in the wrapper's width (cqw), which is the mockup's, so they
   follow the laptops as the card resizes. */
.portfolio-case-card__ux-preview {
  position: relative;
  flex: 0 0 auto;
  margin: 12px 0 calc(-1 * var(--portfolio-case-padding));
  container-type: inline-size;
}

.portfolio-case-card__ux-preview .portfolio-case-card__ux-art {
  margin: 0;
}

.portfolio-case-card__ux-docs {
  position: absolute;
  z-index: 1;
  inset: 0;
  pointer-events: none;
}

/* A portfolio: white card, light border, a project thumbnail in the card's
   sage (lavender and blue for the next two) and two short grey lines. It
   rests hidden; the script moves it from its centre. */
.portfolio-case-card__ux-doc {
  --doc-w: clamp(22px, 6.6cqw, 34px);
  position: absolute;
  top: 0;
  left: 0;
  display: flex;
  box-sizing: border-box;
  width: var(--doc-w);
  aspect-ratio: 5 / 6;
  flex-direction: column;
  gap: calc(var(--doc-w) * 0.08);
  padding: calc(var(--doc-w) * 0.12);
  border: 1px solid #d3d8df;
  border-radius: 3px;
  background: #ffffff;
  box-shadow: 0 2px 5px rgb(30 45 20 / 16%);
  opacity: 0;
  translate: -50% -50%;
}

.portfolio-case-card__ux-doc b {
  display: block;
  flex: 1 1 auto;
  border-radius: 2px;
  background: #a9c58c;
}

.portfolio-case-card__ux-doc:nth-child(2) b {
  background: #c7b6f2;
}

.portfolio-case-card__ux-doc:nth-child(3) b {
  background: #a8c8e8;
}

.portfolio-case-card__ux-doc i {
  display: block;
  flex: 0 0 auto;
  width: 80%;
  height: max(2px, calc(var(--doc-w) * 0.07));
  border-radius: 1px;
  background: #cdd3db;
}

.portfolio-case-card__ux-doc i:last-child {
  width: 52%;
}

/* Quebec Winter Carnival: the snow globe with the case study inside it, and
   Bonhomme, the carnival's mascot, beside it. They fill the space under the
   tags (a size container, so the card keeps its height) and size from
   whichever is tighter, its height or its width. All the measurements are
   of what's visible, not the image boxes:
   - the globe's box is 1040 x 1015. image/globe.png (590 x 858) sits in it
     cut to its glass and base, x 8-583, y 306-847, as wide as the box and
     level with its bottom, so the ribbon above and the transparent padding
     round it don't count;
   - Bonhomme (358 x 444, visible 12-342 x 11-430) is 52% of the globe's
     visible height, his visible bottom level with the base's, a small gap
     from the glass;
   - so the pair is 1.434 globe-heights wide plus the gap, centred. */
.portfolio-case-card__globe-scene {
  --globe-gap: clamp(10px, 1.2vw, 16px);
  --globe-h: min(100cqh, calc((100cqw - var(--globe-gap)) / 1.434), 340px);
  --globe-w: calc(var(--globe-h) * 1040 / 1015);
  --globe-left: calc((100cqw - var(--globe-h) * 1.434 - var(--globe-gap)) / 2);
  position: relative;
  display: flex;
  flex: 1 1 0;
  min-height: 0;
  align-items: flex-end;
  justify-content: center;
  margin-top: clamp(16px, 1.8vw, 24px);
  container-type: size;
  pointer-events: none;
}

.portfolio-case-card__globe {
  position: relative;
  display: block;
  flex: none;
  height: var(--globe-h);
  aspect-ratio: 1040 / 1015;
  overflow: hidden;
}

/* The whole image, placed so the frame shows just the glass and base, with
   the ribbon clipped off. It fades out and back as the map opens and closes,
   starting once the map is showing and ending once it has gone. */
.portfolio-case-card__globe-img {
  position: absolute;
  bottom: -1.779%;
  left: -1.389%;
  display: block;
  width: 102.431%;
  max-width: none;
  height: auto;
  margin: 0;
  clip-path: inset(35.664% 0 0 0);
  filter: blur(0);
  transition:
    opacity 300ms ease 500ms,
    filter 450ms ease-out 500ms;
}

.portfolio-case-card__globe-scene.is-map .portfolio-case-card__globe-img {
  opacity: 0;
  filter: blur(calc(var(--globe-h) * 0.012));
  transition:
    opacity 180ms ease 60ms,
    filter 180ms ease 60ms;
}

/* The globe's first-hover morph (js/quebec-card.js): a window onto
   image/map.png, in the same scene but out of its flow, so nothing else moves.
   It starts over the glass as an invisible oval and opens into the map, its
   right edge just inside the globe's so it stays clear of Bonhomme, even
   mid-wave, and its bottom level with his base. It's as wide as the room to the left allows,
   and no taller than 90% of the scene. The image is 1260 x 602, shown to y 588
   to leave out the browser's status bar along its bottom. */
.portfolio-case-card__globe-morph {
  --map-border: 2px;
  --map-right: calc(var(--globe-left) + var(--globe-w) - var(--globe-h) * 0.02);
  --map-w: min(var(--map-right), calc(100cqh * 1.93));
  position: absolute;
  bottom: calc(var(--globe-w) * 0.118);
  left: var(--globe-left);
  display: block;
  overflow: hidden;
  box-sizing: border-box;
  width: var(--globe-w);
  height: calc(var(--globe-w) * 0.8073);
  border: var(--map-border) solid transparent;
  border-radius: 50%;
  box-shadow: 0 6px 18px rgba(14, 10, 28, 0);
  opacity: 0;
}

/* 602 / 588 of the window's height, so its overflow always hides that strip.
   The map goes soft and pale as it sinks into the glass, like the map drawn
   inside the globe, and sharpens as it comes out. The slight scale keeps the
   blur's faded edge outside the window. */
.portfolio-case-card__globe-morph img {
  display: block;
  width: 100%;
  max-width: none;
  height: 102.381%;
  margin: 0;
  object-fit: cover;
  object-position: 50% 0;
  filter: blur(calc(var(--globe-h) * 0.02)) saturate(0.7) brightness(1.08);
  transform: scale(1.06);
  transition:
    filter 500ms ease-in-out,
    transform 500ms ease-in-out;
}

.portfolio-case-card__globe-scene.is-map .portfolio-case-card__globe-morph img {
  filter: blur(0) saturate(1) brightness(1);
  transform: none;
  transition:
    filter 700ms ease-out,
    transform 700ms ease-out;
}

/* Closing: the map holds until it's nearly back to the glass, then fades */
.portfolio-case-card__globe-scene .portfolio-case-card__globe-morph {
  transition:
    left 1000ms cubic-bezier(0.22, 1, 0.36, 1),
    bottom 1000ms cubic-bezier(0.22, 1, 0.36, 1),
    width 1000ms cubic-bezier(0.22, 1, 0.36, 1),
    height 1000ms cubic-bezier(0.22, 1, 0.36, 1),
    border-radius 1000ms cubic-bezier(0.22, 1, 0.36, 1),
    border-color 1000ms cubic-bezier(0.22, 1, 0.36, 1),
    box-shadow 1000ms cubic-bezier(0.22, 1, 0.36, 1),
    opacity 300ms ease 450ms;
}

/* Opening: the map shows straight away, while the shape is on the move */
.portfolio-case-card__globe-scene.is-map .portfolio-case-card__globe-morph {
  bottom: 0;
  left: calc(var(--map-right) - var(--map-w));
  width: var(--map-w);
  height: calc((var(--map-w) - var(--map-border) * 2) * 588 / 1260 + var(--map-border) * 2);
  border-color: rgba(154, 98, 246, 0.6);
  border-radius: 16px;
  box-shadow: 0 6px 18px rgba(14, 10, 28, 0.16);
  opacity: 1;
  transition:
    left 1000ms cubic-bezier(0.22, 1, 0.36, 1),
    bottom 1000ms cubic-bezier(0.22, 1, 0.36, 1),
    width 1000ms cubic-bezier(0.22, 1, 0.36, 1),
    height 1000ms cubic-bezier(0.22, 1, 0.36, 1),
    border-radius 1000ms cubic-bezier(0.22, 1, 0.36, 1),
    border-color 1000ms cubic-bezier(0.22, 1, 0.36, 1),
    box-shadow 1000ms cubic-bezier(0.22, 1, 0.36, 1),
    opacity 160ms ease;
}

/* Bonhomme beside the globe: his element is 55.1% of the globe's height
   (so what's visible of him is 52%); the margins take away his transparent
   edges so the gap and the centring use what's visible, and pull his
   visible bottom down level with the base. js/quebec-card.js makes him
   wave. */
.portfolio-case-card__globe-scene .portfolio-case-card__bonhomme {
  position: relative;
  display: block;
  flex: none;
  width: auto;
  height: calc(var(--globe-h) * 0.551);
  aspect-ratio: 358 / 444;
  margin: 0 calc(var(--globe-h) * -0.0199) calc(var(--globe-h) * -0.01737)
    calc(var(--globe-gap) - var(--globe-h) * 0.01489);
  /* His slight lean during the wave pivots at his base */
  transform-origin: 50% 100%;
}

/* Two layers of image/bonhomme.png: his raised arm, then the body over it,
   so the arm's base stays tucked behind his shoulder as it swings. The arm
   pivots at the shoulder (53, 253 in the 358 x 444 image). */
.portfolio-case-card__bonhomme img {
  display: block;
  width: 100%;
  max-width: none;
  height: auto;
  margin: 0;
}

.portfolio-case-card__bonhomme .portfolio-case-card__bonhomme-arm {
  position: absolute;
  inset: 0;
  transform-origin: 14.8% 57%;
}

.portfolio-case-card__bonhomme .portfolio-case-card__bonhomme-body {
  position: relative;
}

@media (max-width: 900px) {
  /* One column: the spacing tightens */
  .portfolio-featured-projects__title {
    margin-bottom: clamp(32px, 4vw, 56px);
  }

  .portfolio-case-studies {
    grid-template-columns: minmax(0, 1fr);
    gap: clamp(24px, 4vw, 56px);
    width: min(620px, calc(100% - 40px));
  }

  .portfolio-case-card {
    min-height: 0;
    padding-bottom: var(--portfolio-case-padding);
  }

  .portfolio-case-card__aleasat-art {
    position: relative;
    right: auto;
    bottom: auto;
    left: auto;
    width: calc(100% + 48px);
    height: auto;
    min-height: 0;
    flex: 0 0 auto;
    margin: 12px 0 0 -24px;
    margin-bottom: calc(-1 * var(--portfolio-case-padding));
  }

  /* Stacked, cards are as tall as their content, so the globe's space has
     its own height */
  .portfolio-case-card__globe-scene {
    flex: 0 0 auto;
    height: clamp(180px, 36vw, 260px);
  }
}

@media (max-width: 660px) {
  #featured-projects {
    width: calc(100% + 5rem);
    margin-left: calc(-2rem - 8px);
  }

  .portfolio-case-studies {
    width: calc(100% - 40px);
  }

  .portfolio-case-card {
    min-height: 0;
    --portfolio-case-padding: 22px;
    padding: 22px;
  }

  .portfolio-case-card__aleasat-art {
    width: calc(100% + 44px);
    height: auto;
    min-height: 0;
    flex-basis: auto;
    margin-left: -22px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .portfolio-case-card-orbit.is-pulsing .portfolio-case-card__status-dot::after {
    animation: none;
  }

  html {
    scroll-behavior: auto;
  }

  .portfolio-venn__circle,
  .portfolio-venn__outlines circle {
    transition: none;
  }

  .portfolio-skills__list button {
    transition: none;
  }

  .portfolio-theme-toggle,
  .portfolio-menu-toggle {
    transition: none;
  }

  .portfolio-case-card {
    transition: none;
  }

  .portfolio-case-card.is-filtering-out {
    opacity: 1;
  }

  .portfolio-cursor-label {
    transition: none;
  }
}

@media (max-width: 660px) {
  .portfolio-skills {
    --portfolio-skill-font-size: clamp(15px, 3.8vw, 22px);
  }

  .portfolio-container {
    width: calc(100% - 40px);
  }

  .portfolio-nav__primary {
    gap: 12px;
  }

  .portfolio-logo img {
    width: 56px;
  }

  .portfolio-nav__inner {
    position: relative;
    min-height: 64px;
  }

  .portfolio-nav__links {
    position: absolute;
    top: calc(100% - 1px);
    right: 0;
    left: 0;
    z-index: 20;
    display: none;
    align-items: stretch;
    flex-direction: column;
    gap: 0;
    padding: 8px 16px;
    border: 1px solid var(--portfolio-top-text);
    border-radius: 8px;
    background-color: var(--portfolio-top-bg);
  }

  .portfolio-nav[data-menu-open="true"] .portfolio-nav__links {
    display: flex;
  }

  .portfolio-header--case-study .portfolio-nav__links {
    background-color: var(--portfolio-menu-bg);
    box-shadow: 0 16px 40px rgb(14 10 28 / 14%);
  }

  .portfolio-nav__links a {
    padding: 12px 0;
  }

  .portfolio-menu-toggle {
    display: inline-flex;
  }

  #bio.portfolio-hero {
    padding-bottom: 0;
  }

  .portfolio-hero__inner {
    grid-template-columns: minmax(0, 1fr);
    gap: 34px;
    padding-top: clamp(38px, 8vw, 56px);
  }

  .portfolio-hero__copy {
    padding-top: 0;
  }

  .portfolio-venn-frame {
    width: min(100%, 86vw, 420px);
  }

}

@media (max-width: 380px) {
  .portfolio-nav__actions {
    gap: 12px;
  }
}
