/* Portfolio styles: edit shared foundations here to update every page.
Layout classes live on <html>; project-template.html uses page-project. */

/* Colours and spacing used across the page (same as the homepage) */
:root {
  /* Shared layout and typography */
  --page-width: 1280px;
  --font-family: "Finlandica Text", "Helvetica Neue", Arial, sans-serif;
  /* Dark mode palette */
  color-scheme: dark;
  --background: #111111;
  --text: #f6f6f6;
  --muted: #d2d2d2;
  --card: #1a1818;
  --border: #2e2e2e;
  --subtle: #9a9a9a;
}

/* Light mode palette: switched on by data-theme="light" on the <html> tag.
Remove that attribute to go back to dark mode */
:root[data-theme="light"] {
  color-scheme: light;
  --background: #f6f6f4;
  --text: #111111;
  --muted: #3d3d3d;
  --card: #ececea;
  --border: #dcdcd8;
  --subtle: #6b6b6b;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  padding: 32px 24px 64px;
  background: var(--background);
  color: var(--text);
  font-family: var(--font-family);
  font-weight: 200;
  line-height: 1.5;
}

.page {
  max-width: var(--page-width);
  margin: 0 auto;
}

/* Top navigation: name on the left, links on the right */
.site-nav {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 24px;
  margin-bottom: var(--nav-bottom, 24px);
}

/* Footer: the same navigation repeated at the end of the page */
.site-footer {
  max-width: var(--page-width);
  margin: 112px auto 0;
}

.site-footer .site-nav {
  margin-bottom: 0;
}

.site-nav a {
  color: var(--text);
  text-decoration: none;
  font-size: 18px;
}

/* Same light weight as the titles and headings */
.site-name {
  font-weight: 200;
}

.site-nav a:hover {
  text-decoration: underline;
  text-underline-offset: 4px;
}

.site-nav a:focus-visible {
  outline: 2px solid var(--text);
  outline-offset: 4px;
}


:root.page-home { --nav-bottom: 168px; }
:root.page-contact { --nav-bottom: 48px; }
.page-home body, .page-contact body { overflow-x: clip; }

/* CASE STUDIES: shared by every project, including the template. */


:where(.page-project) img,
:where(.page-project) video {
  display: block;
  width: 100%;
  height: auto;
}

/* 1. Hero image: fills the page width in a wide frame */
:where(.page-project) .hero {
  margin: 0 0 56px;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: var(--border);
}

:where(.page-project) .hero img {
  height: 100%;
  object-fit: cover;
  object-position: center;
}

/* Collage hero: photos on a transparent background, shown whole in
their own shape, with no grey frame behind them */
:where(.page-project) .hero.hero-collage {
  aspect-ratio: auto;
  overflow: visible;
  background: none;
}

:where(.page-project) .hero.hero-collage img {
  height: auto;
}

/* Title and lead start at the second half of the page, lined up with
the paragraphs in the text blocks (half the 40px column gap = 20px) */
:where(.page-project) .project-intro {
  padding-left: calc(50% + 20px);
  margin-bottom: 72px;
  /* Fade mask, the same as the homepage bio: everything below the fade
  edge is hidden, with a soft 40% blend above it. The script moves the
  edge up as you scroll */
  --fade-edge: -40%;
  -webkit-mask-image: linear-gradient(to top, transparent var(--fade-edge), black calc(var(--fade-edge) + 40%));
  mask-image: linear-gradient(to top, transparent var(--fade-edge), black calc(var(--fade-edge) + 40%));
}

/* The navigation, title and lead stay still, and the hero image and the
rest of the page slide up over them, the same as on the homepage */
:where(.page-project) .intro {
  position: sticky;
  top: 32px;
  z-index: 0;
}

:where(.page-project) main {
  position: relative;
  z-index: 1;
  background: var(--background);
}

/* 2 + 3. Title and lead use the homepage bio style (34px, light weight)
and read as one unit with no gap. Only colour tells them apart */
:where(.page-project) .project-title {
  margin: 0;
  font-size: 34px;
  font-weight: 200;
  line-height: 1.5;
  color: var(--text);
}

/* 3. Lead paragraph: a softer grey than the homepage bio, so the
white title stands out more */
:where(.page-project) .lead {
  margin: 0;
  max-width: 1080px;
  font-size: 34px;
  font-weight: 200;
  line-height: 1.5;
  color: var(--subtle);
}

/* Summary: a text block with the project facts (role, timeline) under
the paragraph, and a divider that runs the full window width */
:where(.page-project) .text-block.summary {
  position: relative;
  padding-top: 56px;
  border-bottom: none;
}

:where(.page-project) .summary::after {
  content: "";
  position: absolute;
  bottom: 0;
  left: calc(50% - 50vw);
  width: 100vw;
  height: 1px;
  background: var(--border);
}

/* Project facts: small labels with their answers below, side by side */
:where(.page-project) .project-facts {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 40px;
  margin: 40px 0 0;
}

:where(.page-project) .project-facts dt {
  margin: 0 0 8px;
  font-size: 14px;
  font-weight: 400;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--subtle);
}

:where(.page-project) .project-facts dd {
  margin: 0;
  font-size: 18px;
  font-weight: 300;
  color: var(--text);
}

/* 4. Text block: heading on the left half, paragraph on the right half,
with a slim divider underneath. Reuse it as many times as you like */
:where(.page-project) .text-block {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 40px;
  padding: 112px 0;
  border-bottom: 1px solid var(--border);
}

/* Optional heading: a lone text container keeps the right-hand column. */
@media (min-width: 921px) {
  :where(.page-project) .text-block:not(.diagram-wide) > div:only-child {
    grid-column: 2;
  }
}

/* Project highlights: a text block whose right half holds a two-column
grid of short highlights, each with a title and a description or list.
Reuse it by copying a <section class="text-block highlights"> */
:where(.page-project) .highlights-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 64px 40px;
  align-items: start;
}

/* Optional intro paragraph above the grid, across both columns */
:where(.page-project) .highlights-grid .highlights-intro {
  grid-column: 1 / -1;
}

:where(.page-project) .highlight h3 {
  margin: 0 0 24px;
  font-size: 18px;
  font-weight: 400;
  line-height: 1.5;
  color: var(--text);
}

/* List inside a highlight, each item starting with an arrow */
:where(.page-project) .arrow-list {
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 18px;
  font-weight: 300;
  color: var(--muted);
}

:where(.page-project) .arrow-list li::before {
  content: "→ ";
}

/* Space between list items */
:where(.page-project) .arrow-list li + li {
  margin-top: 12px;
}

/* Text block heading: the same style as the project title */
:where(.page-project) .text-block h2 {
  margin: 0;
  font-size: 34px;
  font-weight: 200;
  line-height: 1.5;
  color: var(--text);
}

/* Scroll reveal: each heading sits under a gradient mask, solid on the
left and fading to clear on the right. The mask is 2.5 times wider than
the heading and starts with only its clear part over the text. Sliding
it across uncovers the heading from left to right, with a soft edge */
:where(.page-project) .reveal-ready .text-block h2 {
  /* Only as wide as its words, so the fade travels across the text itself */
  justify-self: start;
  -webkit-mask-image: linear-gradient(to right, black 40%, transparent 60%);
  mask-image: linear-gradient(to right, black 40%, transparent 60%);
  -webkit-mask-size: 250% 100%;
  mask-size: 250% 100%;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: 100% 0;
  mask-position: 100% 0;
  transition: -webkit-mask-position 1.2s ease-out, mask-position 1.2s ease-out;
}
:where(.page-project) .reveal-ready .text-block h2.is-visible {
  -webkit-mask-position: 0 0;
  mask-position: 0 0;
}

/* Skip the animation for people who have turned on "Reduce motion" */
@media (prefers-reduced-motion: reduce) {
  :where(.page-project) .reveal-ready .text-block h2 {
    -webkit-mask-image: none;
    mask-image: none;
    transition: none;
  }
}

:where(.page-project) .text-block p {
  margin: 0;
  font-size: 18px;
  font-weight: 300;
  color: var(--muted);
}

/* Callout: highlights an important paragraph inside a text block, with a
thin line on its left and slightly bigger text. Use: <p class="callout"> */
:where(.page-project) .text-block p.callout {
  position: relative;
  margin-top: 32px;
  margin-bottom: 32px;
  padding-left: 24px;
  font-size: 20px;
}

:where(.page-project) .text-block p.callout:last-child {
  margin-bottom: 0;
}

/* The line on the left */
:where(.page-project) .callout::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 1px;
  background: var(--text);
  transform-origin: top;
}

/* The first time the callout scrolls into view, the line draws itself from
top to bottom: a quick start that eases into a soft stop */
:where(.page-project) .reveal-ready .callout::before {
  transform: scaleY(0);
  transition: transform 0.9s cubic-bezier(0.16, 1, 0.3, 1) 0.15s;
}

:where(.page-project) .reveal-ready .callout.is-visible::before {
  transform: scaleY(1);
}

/* With "Reduce motion" on, the line is simply there */
@media (prefers-reduced-motion: reduce) {
  :where(.page-project) .reveal-ready .callout::before {
    transform: none;
    transition: none;
  }
}

/* Tinted section: a text block on a coloured background that runs edge to
edge across the whole window. Change --tint per page to match its hero.
Use: <section class="text-block tinted"> */
:where(.page-project) .text-block.tinted {
  --tint: #d6deff;
  /* Grey detail text darkened slightly so it stays readable on the colour */
  --subtle: #555555;
  position: relative;
  isolation: isolate;
  border-bottom: none;
}

:where(.page-project) .text-block.tinted::before {
  content: "";
  position: absolute;
  inset: 0 calc(50% - 50vw);
  z-index: -1;
  background: var(--tint);
}

/* Bold text inside a paragraph, such as "The opportunity" sentence */
:where(.page-project) .text-block p strong {
  font-weight: 500;
}

/* Space between paragraphs inside the same text block */
:where(.page-project) .text-block p + p {
  margin-top: 16px;
}

/* Space between a paragraph and an arrow list that follows it */
:where(.page-project) .text-block p + .arrow-list {
  margin-top: 24px;
}

/* Column image: as wide as a whole text block, from the heading's left
edge to the paragraph's right edge. Reuse it as many times as you like */
:where(.page-project) .column-image {
  margin: 0;
  padding: 56px 0;
}

/* Image pair: two photos side by side at the same height. Each photo's
share of the width follows its own shape, so neither gets cropped */
:where(.page-project) .image-pair {
  display: flex;
  gap: 40px;
  align-items: flex-start;
}

:where(.page-project) .image-pair img {
  flex: var(--ratio) 1 0;
  min-width: 0;
  height: auto;
}

/* Fade cut: shows only the top part of a tall image, and fades its
bottom edge into the page background. --cut is how much of the image
height to keep, --fade-from is where the fade starts within that */
:where(.page-project) .fade-cut {
  overflow: hidden;
  aspect-ratio: var(--image-ratio) / var(--cut);
  -webkit-mask-image: linear-gradient(to bottom, black var(--fade-from), transparent 100%);
  mask-image: linear-gradient(to bottom, black var(--fade-from), transparent 100%);
}

/* Optional caption under the image */
:where(.page-project) .column-image figcaption {
  margin-top: 12px;
  font-size: 14px;
  font-weight: 300;
  color: var(--muted);
}

/* 5. Quote: big centred text, with the person's name and role below */
:where(.page-project) .quote {
  margin: 112px auto;
  max-width: 960px;
  text-align: center;
}

:where(.page-project) .quote blockquote {
  margin: 0 0 32px;
  font-size: 40px;
  font-weight: 200;
  line-height: 1.3;
}

/* Curly quote marks are added around the text automatically */
:where(.page-project) .quote blockquote p {
  margin: 0;
}

:where(.page-project) .quote blockquote p::before {
  content: "“";
}

:where(.page-project) .quote blockquote p::after {
  content: "”";
}

:where(.page-project) .quote-name {
  display: block;
  font-size: 18px;
  font-weight: 500;
  font-style: normal;
}

:where(.page-project) .quote-role {
  display: block;
  font-size: 16px;
  font-weight: 300;
  color: var(--muted);
}

/* 6. Full-width image: breaks out of the page column and runs edge to edge */
:where(.page-project) .full-bleed {
  margin: 112px 0;
  margin-left: calc(50% - 50vw);
  width: 100vw;
}

/* Caption under a full-width image or video: same style as column
captions, but lined up with the page column rather than the window edge */
:where(.page-project) .full-bleed figcaption {
  max-width: calc(var(--page-width) + 48px);
  margin: 12px auto 0;
  padding: 0 24px;
  font-size: 14px;
  font-weight: 300;
  color: var(--muted);
}

/* Previous and next project: at the end of the page, previous on the
left half and next on the right half, lined up with the text blocks.
The first project's previous is the last one, so the list loops */
:where(.page-project) .project-pager {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 40px;
  padding-top: 112px;
}

:where(.page-project) .pager-link {
  position: relative;
  display: block;
  color: var(--text);
  text-decoration: none;
}

/* The project's hero image appears above the link on hover, floating
over the page so nothing moves */
:where(.page-project) .pager-image {
  position: absolute;
  bottom: calc(100% + 16px);
  left: 0;
  z-index: 2;
  display: block;
  /* Never wider than the screen, minus the page margins */
  width: min(560px, calc(100vw - 48px));
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  background: var(--border);
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 0.3s ease, transform 0.3s ease;
  pointer-events: none;
}

:where(.page-project) .pager-link:hover .pager-image,
:where(.page-project) .pager-link:focus-visible .pager-image {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  :where(.page-project) .pager-image {
    transition: none;
  }
}

:where(.page-project) .pager-label {
  display: block;
  margin-bottom: 8px;
  font-size: 14px;
  font-weight: 400;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--subtle);
}

:where(.page-project) .pager-name {
  font-size: 34px;
  font-weight: 200;
  line-height: 1.5;
}

:where(.page-project) .pager-link:hover .pager-name {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 6px;
}

:where(.page-project) .pager-link:focus-visible {
  outline: 2px solid var(--text);
  outline-offset: 4px;
}

@media (max-width: 920px) {
  :where(.page-project) .project-pager {
    gap: 24px;
    padding-top: 80px;
  }
  :where(.page-project) .pager-name {
    font-size: 20px;
  }
  :where(.page-project) .pager-image {
    width: min(320px, calc(100vw - 48px));
  }
  /* On phones the next project's image lines up with the right edge,
  so it stays on screen */
  :where(.page-project) .pager-link + .pager-link .pager-image {
    left: auto;
    right: 0;
  }
}

/* On narrow screens, stack the text block and shrink the big type */
@media (max-width: 920px) {
  :where(.page-project) .project-title {
    font-size: 24px;
  }
  :where(.page-project) .lead {
    font-size: 24px;
  }
  :where(.page-project) .project-intro {
    padding-left: 0;
    margin-bottom: 48px;
  }
  :where(.page-project) .hero {
    aspect-ratio: 4 / 3;
    margin-bottom: 40px;
  }
  :where(.page-project) .hero.hero-collage {
    aspect-ratio: auto;
  }
  :where(.page-project) .text-block.summary {
    padding-top: 40px;
  }
  :where(.page-project) .project-facts {
    gap: 24px;
    margin-top: 32px;
  }
  :where(.page-project) .text-block {
    grid-template-columns: 1fr;
    gap: 16px;
    padding: 80px 0;
  }
  :where(.page-project) .highlights-grid {
    grid-template-columns: 1fr;
    gap: 40px;
  }
  :where(.page-project) .highlight h3 {
    margin-bottom: 8px;
  }
  :where(.page-project) .text-block h2 {
    font-size: 24px;
  }
  :where(.page-project) .column-image {
    padding: 40px 0;
  }
  :where(.page-project) .image-pair {
    flex-direction: column;
    gap: 16px;
  }
  :where(.page-project) .image-pair img {
    flex: none;
    width: 100%;
  }
  :where(.page-project) .quote {
    margin: 72px auto;
  }
  :where(.page-project) .quote blockquote {
    font-size: 28px;
  }
  :where(.page-project) .full-bleed {
    margin-top: 72px;
    margin-bottom: 72px;
  }
}

/* Page load animation: the hero image rises in first, then the title
and lead follow one line at a time */
/* The hero waits, hidden, until the script starts the whole sequence,
so the image and text always play in the right order */
.animate-in:where(.page-project) .hero {
  opacity: 0;
}

.animate-in:where(.page-project).intro-playing .hero {
  animation: project-rise-in 1.1s cubic-bezier(0.22, 1, 0.36, 1) both;
}

@keyframes project-rise-in {
  from {
    opacity: 0;
    transform: translateY(80px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* Keep the title and lead hidden until the script has split them into lines */
.animate-in:where(.page-project) .project-intro:not(.lines-ready) {
  visibility: hidden;
}

/* The title and lead are split into small word boxes. Every box on the
same line shares a delay, so each line rises a short way and fades in together */
:where(.page-project) .text-piece {
  display: inline-block;
}

:where(.page-project) .lines-ready .text-piece {
  animation: project-rise-in-line 0.9s cubic-bezier(0.22, 1, 0.36, 1) both;
  animation-delay: var(--delay);
}

/* Tags enter as the first intro line, immediately before the title. */
.animate-in:where(.page-project) .lines-ready .project-tags {
  animation: project-rise-in-line 0.9s cubic-bezier(0.22, 1, 0.36, 1) both;
  animation-delay: var(--delay);
}

@media (prefers-reduced-motion: reduce) {
  .animate-in:where(.page-project) .lines-ready .project-tags {
    animation: none;
  }
}

@keyframes project-rise-in-line {
  from {
    opacity: 0;
    transform: translateY(24px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* Passenger journey: crop off the original title and timeline while
   preserving the source image. The remaining photograph is 2160 × 1420. */
:where(.page-project) .journey-crop {
  aspect-ratio: 108 / 71;
  overflow: hidden;
}

:where(.page-project) .journey-crop img {
  height: 100%;
  object-fit: cover;
  object-position: bottom;
}

/* Separate the diagram from preceding prose or scenario lists. */
:where(.page-project) .text-block p + .journey-diagram,
:where(.page-project) .text-block .arrow-list + .journey-diagram {
  margin-top: 40px;
}

/* A simple line diagram, using the same type and colours as the case study. */
:where(.page-project) .journey-diagram {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  align-self: start;
  list-style: none;
  margin: 0;
  padding: 0;
  color: var(--text);
  font-size: 18px;
  font-weight: 300;
}

:where(.page-project) .journey-diagram li {
  position: relative;
  border-top: 1px solid var(--text);
  padding: 24px 12px 0 0;
}

:where(.page-project) .journey-diagram li:last-child {
  border-top-style: dotted;
}

:where(.page-project) .journey-diagram li::before {
  content: "";
  position: absolute;
  top: -6px;
  left: 0;
  height: 11px;
  border-left: 1px solid var(--text);
}

@media (max-width: 920px) {
  :where(.page-project) .passenger-journey {
    gap: 40px;
  }
  :where(.page-project) .journey-diagram {
    font-size: 16px;
  }
}

/* Full-width variation of the journey diagram for the HMI process. */
:where(.page-project) .text-block.diagram-wide {
  grid-template-columns: minmax(0, 1fr);
  gap: 56px;
}

:where(.page-project) .hmi-paradigm {
  grid-template-columns: repeat(5, minmax(0, 1fr));
  font-weight: 200;
  line-height: 1.4;
}

:where(.page-project) .hmi-paradigm li:last-child {
  border-top-style: solid;
}

:where(.page-project) .diagram-detail {
  display: block;
  /* Match the homepage cards: title and muted detail read as one block. */
  margin-top: 0;
  color: var(--subtle);
}

@media (max-width: 920px) {
  :where(.page-project) .hmi-paradigm {
    grid-template-columns: minmax(0, 1fr);
    gap: 32px;
  }
  :where(.page-project) .text-block.diagram-wide {
    gap: 40px;
  }
}

/* Workflow comparisons share the HMI diagrams' type, palette and thin lines.
HTML labels keep their size on narrow screens while the arrows scale. */
:where(.page-project) .workflow-comparison {
  max-width: 1000px;
  margin: 0 auto;
  padding: 56px 0;
  color: var(--text);
  font-size: 18px;
  font-weight: 200;
  line-height: 1.4;
}

:where(.page-project) .workflow-panel {
  margin: 0;
}

:where(.page-project) .workflow-panel + .workflow-panel {
  margin-top: 40px;
  padding-top: 40px;
  border-top: 1px solid var(--border);
}

:where(.page-project) .workflow-panel figcaption {
  margin-bottom: 32px;
  color: var(--subtle);
  font-size: 14px;
  font-weight: 400;
  letter-spacing: 0.08em;
  text-align: center;
  text-transform: uppercase;
}

:where(.page-project) .workflow-map {
  position: relative;
  height: 280px;
}

:where(.page-project) .workflow-arrows {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  fill: none;
  stroke: var(--text);
  stroke-width: 1;
}

:where(.page-project) .workflow-arrows path {
  vector-effect: non-scaling-stroke;
}

:where(.page-project) .workflow-stages {
  list-style: none;
  margin: 0;
  padding: 0;
}

:where(.page-project) .workflow-stages li {
  position: absolute;
  display: grid;
  place-items: center;
  width: 28%;
  height: 48px;
  border: 1px solid var(--text);
  background: var(--background);
}

:where(.page-project) .workflow-design { left: 8%; top: 0; }
:where(.page-project) .workflow-dev { left: 36%; top: 72px; }
:where(.page-project) .workflow-qa { left: 64%; top: 144px; }

:where(.page-project) .workflow-overlapping .workflow-design-continued {
  left: 40%;
  top: 0;
  width: 52%;
}

:where(.page-project) .workflow-overlapping .workflow-dev {
  left: 10%;
  width: 82%;
}

:where(.page-project) .workflow-overlapping .workflow-qa {
  left: 12%;
  width: 80%;
}

:where(.page-project) .workflow-feedback {
  position: absolute;
  top: 224px;
  left: 8%;
  right: 8%;
  margin: 0;
  text-align: center;
}

@media (max-width: 920px) {
  :where(.page-project) .workflow-comparison {
    padding: 40px 0;
    font-size: 16px;
  }
}

/* Iterative HMI process: a shared artefact surrounded by five activities. */
:where(.page-project) .hmi-cycle {
  position: relative;
  font-size: 18px;
  font-weight: 200;
  line-height: 1.4;
  color: var(--text);
}

:where(.page-project) .hmi-cycle-roles {
  display: flex;
  justify-content: space-between;
  gap: 24px;
}

:where(.page-project) .hmi-cycle-roles span:last-child {
  text-align: right;
}

:where(.page-project) .hmi-cycle-map {
  position: relative;
  width: min(100%, 760px);
  aspect-ratio: 1;
  margin: 40px auto 0;
  border: 1px solid var(--border);
  border-radius: 50%;
}

:where(.page-project) .hmi-cycle-core {
  position: absolute;
  inset: 31%;
  display: grid;
  place-items: center;
  text-align: center;
  font-size: 24px;
}

:where(.page-project) .hmi-cycle-loop {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  fill: none;
  stroke: var(--text);
  stroke-width: 1;
}

:where(.page-project) .hmi-cycle-stages {
  list-style: none;
  margin: 0;
  padding: 0;
}

:where(.page-project) .hmi-cycle-stages li {
  position: absolute;
  width: 30%;
  text-align: center;
  transform: translate(-50%, -50%);
}

:where(.page-project) .hmi-cycle-stages li:nth-child(1) { left: 50%; top: 15%; }
:where(.page-project) .hmi-cycle-stages li:nth-child(2) { left: 81%; top: 38%; }
:where(.page-project) .hmi-cycle-stages li:nth-child(3) { left: 73%; top: 76%; }
:where(.page-project) .hmi-cycle-stages li:nth-child(4) { left: 27%; top: 76%; }
:where(.page-project) .hmi-cycle-stages li:nth-child(5) { left: 19%; top: 38%; }

:where(.page-project) .hmi-cycle .hmi-cycle-caption {
  margin-top: 32px;
  text-align: center;
  color: var(--subtle);
}

:where(.page-project) .hmi-cycle-human {
  margin-top: 16px;
  text-align: center;
}

@media (max-width: 920px) {
  :where(.page-project) .hmi-cycle { font-size: 16px; }
  :where(.page-project) .hmi-cycle-map {
    width: 100%;
    aspect-ratio: auto;
    margin-top: 32px;
    border: 0;
    border-radius: 0;
  }
  :where(.page-project) .hmi-cycle-core {
    position: relative;
    inset: auto;
    width: 240px;
    height: 240px;
    margin: 0 auto 40px;
    font-size: 20px;
  }
  :where(.page-project) .hmi-cycle-stages {
    display: grid;
    gap: 32px;
  }
  :where(.page-project) .hmi-cycle-stages li:nth-child(n) {
    position: relative;
    left: auto;
    top: auto;
    width: auto;
    transform: none;
    text-align: left;
    border-top: 1px solid var(--text);
    padding-top: 24px;
  }
}

/* A paradigm visual spans both columns below its heading and introduction. */
:where(.page-project) .paradigm-section > .paradigm-desktop,
:where(.page-project) .paradigm-section > .paradigm-mobile {
  grid-column: 1 / -1;
}

:where(.page-project) .text-block.paradigm-section {
  row-gap: 56px;
}

/* The challenge: the line diagram sits closer to its text */
@media (min-width: 921px) {
  :where(.page-project) .text-block.paradigm-section:has(> .hmi-paradigm) {
    row-gap: 72px;
  }
}

@media (max-width: 920px) {
  :where(.page-project) .text-block.paradigm-section {
    row-gap: 24px;
  }
}

/* Each paradigm shares one editable heading across desktop and mobile. */
:where(.page-project) .paradigm-mobile {
  display: none;
  margin: 0;
}

@media (max-width: 920px) {
  :where(.page-project) .paradigm-desktop {
    display: none;
  }
  :where(.page-project) .paradigm-mobile {
    display: block;
  }
}

/* HOMEPAGE */

/* Clicking a menu link glides to that section instead of jumping */
@media (prefers-reduced-motion: no-preference) {
  html:where(.page-home) {
    scroll-behavior: smooth;
  }
}

/* Intro: name and bio */
:where(.page-home) header {
  margin-bottom: 72px;
  /* Fade mask: everything below the fade edge is hidden, with a soft
  40% blend above it. The script moves the edge up as you scroll */
  --fade-edge: -40%;
  -webkit-mask-image: linear-gradient(to top, transparent var(--fade-edge), black calc(var(--fade-edge) + 40%));
  mask-image: linear-gradient(to top, transparent var(--fade-edge), black calc(var(--fade-edge) + 40%));
}

/* The project list sits on its own layer above the bio */
:where(.page-home) main {
  position: relative;
  z-index: 1;
  background: var(--background);
}

/* On all screen sizes the navigation and bio stay still from the start,
and the cards slide up over them */
:where(.page-home) .intro {
  position: sticky;
  top: 32px;
  z-index: 0;
}

:where(.page-home) h1 {
  margin: 0 0 8px;
  font-size: 50px;
  font-weight: 700;
  letter-spacing: -0.02em;
}

:where(.page-home) .bio {
  margin: 0;
  font-size: 34px;
  font-weight: 200;
  color: var(--muted);
  max-width: 1080px;
}

/* Space between bio paragraphs */
:where(.page-home) .bio + .bio {
  margin-top: 12px;
}

/* "I'm Daniel" in the bio: a link to the Contact page. On hover a photo
collage opens just below it, on top of everything, and a white veil
softens the page behind it */
:where(.page-home) .bio-link {
  position: relative;
  color: var(--text);
  white-space: nowrap;
  text-decoration: none;
  /* One collage unit: 1.5px on big screens, smaller when the screen is
  too narrow for the 840 unit wide collage */
  --u: min(1.5px, calc((100vw - 160px) / 840));
}

:where(.page-home) .bio-link:focus-visible {
  outline: 2px solid var(--text);
  outline-offset: 4px;
}

/* The underline under "I'm Daniel" is drawn as a thin line. On page load
it's the last thing to appear: once every line of the bio has landed,
it draws itself from left to right, easing in and out */
:where(.page-home) .bio-link::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: var(--text);
  transform-origin: left;
}

.animate-in:where(.page-home) .bio-link::after {
  transform: scaleX(0);
}

.animate-in:where(.page-home).link-drawn .bio-link::after {
  transform: scaleX(1);
  transition: transform 1.2s cubic-bezier(0.65, 0, 0.35, 1);
}

/* "I'm Daniel" stays crisp above the veil */
:where(.page-home) .bio-link-text {
  position: relative;
  z-index: 11;
}

/* White layer at 90% over the whole page, behind the collage */
:where(.page-home) .collage-veil {
  position: fixed;
  inset: 0;
  z-index: 9;
  background: rgba(255, 255, 255, 0.9);
  opacity: 0;
  transition: opacity 0.3s ease;
  pointer-events: none;
}

/* The collage: four photos laid out like tiles that touch only at their
corners. The portrait hangs just below "I'm Daniel", Iceland climbs up
from its top-right corner, and the beach steps down again from
Iceland's bottom-right corner, in a zigzag. The building floats on its
own, apart from the others. Positions are measured from the portrait's
top-left corner */
:where(.page-home) .collage {
  position: absolute;
  top: calc(100% + 12px);
  left: 0;
  z-index: 10;
  pointer-events: none;
}

:where(.page-home) .collage img {
  position: absolute;
  display: block;
  max-width: none;
  object-fit: cover;
  background: var(--border);
  opacity: 0;
  transform: scale(0.94);
  /* Leaving: every photo fades out together, at the same speed as the
  white layer */
  transition: opacity 0.3s ease, transform 0.3s ease;
}

/* Biggest tile: the portrait with the camera, right below "I'm Daniel".
It runs down to the bottom edge of the screen: the script measures
that height (--ph) when the collage opens. The tiles to its right
move along with its width */
:where(.page-home) .collage {
  --ph: var(--collage-height, calc(var(--u) * 347));
  --pw: calc(var(--ph) * 0.75);
}

:where(.page-home) .collage-portrait {
  left: 0;
  top: 0;
  width: var(--pw);
  height: var(--ph);
}

/* Iceland: its bottom-left corner meets the portrait's top-right corner */
:where(.page-home) .collage-iceland {
  left: var(--pw);
  top: calc(var(--u) * -240);
  width: calc(var(--u) * 180);
  height: calc(var(--u) * 240);
}

/* The beach: its top-left corner meets Iceland's bottom-right corner */
:where(.page-home) .collage-beach {
  left: calc(var(--pw) + var(--u) * 180);
  top: 0;
  width: calc(var(--u) * 200);
  height: calc(var(--u) * 267);
}

/* The building, on its own to the top right */
:where(.page-home) .collage-building {
  left: calc(var(--pw) + var(--u) * 440);
  top: calc(var(--u) * -190);
  width: calc(var(--u) * 140);
  height: calc(var(--u) * 210);
}

/* On phones there's no room for the zigzag to the right, so the tiles
are sized to the screen width instead. The portrait takes about half
the width, Iceland still meets its top-right corner, and the beach and
the building form a separate stack to the right of the portrait */
@media (max-width: 920px) {
  /* On phones the portrait keeps a 3:4 shape instead of running down
  to the bottom of the screen */
  :where(.page-home) .collage {
    --pw: 52vw;
    --ph: 69.33vw;
  }
  :where(.page-home) .collage-iceland {
    top: -56vw;
    width: 42vw;
    height: 56vw;
  }
  :where(.page-home) .collage-beach {
    left: calc(var(--pw) + 6vw);
    top: calc(var(--ph) * 0.42);
    width: 32vw;
    height: 48vw;
  }
  /* Keep the building beside the portrait, above the beach tile. */
  :where(.page-home) .collage-building {
    left: calc(var(--pw) + 6vw);
    top: 0;
    height: 24vw;
    width: 18vw;
    aspect-ratio: 3 / 4;
  }
}

/* On hover the veil fades in and the tiles appear one after another,
the portrait first */
:where(.page-home) .bio-link:hover .collage-veil,
:where(.page-home) .bio-link:focus-visible .collage-veil,
:where(.page-home) .bio-link:hover .collage img,
:where(.page-home) .bio-link:focus-visible .collage img {
  opacity: 1;
  transform: none;
}

/* Arriving: a slower, softer entrance, one photo after another */
:where(.page-home) .bio-link:hover .collage img,
:where(.page-home) .bio-link:focus-visible .collage img {
  transition: opacity 0.4s ease, transform 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}

:where(.page-home) .bio-link:hover .collage-iceland,
:where(.page-home) .bio-link:focus-visible .collage-iceland {
  transition-delay: 0.08s;
}

:where(.page-home) .bio-link:hover .collage-beach,
:where(.page-home) .bio-link:focus-visible .collage-beach {
  transition-delay: 0.16s;
}

:where(.page-home) .bio-link:hover .collage-building,
:where(.page-home) .bio-link:focus-visible .collage-building {
  transition-delay: 0.28s;
}

/* While the collage is showing, lift the top of the page above the
project cards, and switch off the bio's scroll fade, which would
otherwise cut the collage off. The script below keeps this on until
the photos have finished fading out, so nothing gets cut off halfway */
.collage-open:where(.page-home) .intro {
  z-index: 2;
}

.collage-open:where(.page-home) header {
  -webkit-mask-image: none;
  mask-image: none;
}

@media (prefers-reduced-motion: reduce) {
  :where(.page-home) .collage-veil,
  :where(.page-home) .collage img {
    transform: none;
    transition: opacity 0.2s ease;
    transition-delay: 0s !important;
  }
}

/* Project cards */
:where(.page-home) h2 {
  margin: 0 0 20px;
  font-size: 22px;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
}

/* One card per row */
:where(.page-home) .projects {
  display: grid;
  grid-template-columns: 1fr;
  /* 48px from the bottom of one card to the line of the next */
  gap: 48px;
}

/* Inside each card: text takes 1/3 on the left, image takes 2/3 on the right */
:where(.page-home) .card {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 2fr;
  background: var(--background);
  /* The line along the top, then 48px of space before the card content */
  padding-top: 49px;
}

/* Thin line along the top of the card, running edge to edge across
the whole browser window, past the page margins */
:where(.page-home) .card::before {
  content: "";
  position: absolute;
  top: 0;
  left: calc(50% - 50vw);
  width: 100vw;
  height: 1px;
  background: var(--border);
}

/* The image frame: a wide 16:12 window, close to the shape of the project images */
:where(.page-home) .card-media {
  grid-column: 2;
  grid-row: 1;
  position: relative;
  aspect-ratio: 16 / 12;
  overflow: hidden;
  background: var(--border);
}

/* The photo is 10% taller than its frame, just enough room to slide for the parallax.
It stays centred, so any cropping is equal on the left and right */
:where(.page-home) .card-image {
  position: absolute;
  top: -5%;
  left: 0;
  display: block;
  width: 100%;
  height: 110%;
  object-fit: cover;
  object-position: center;
  will-change: transform;
}

/* A collage on a transparent background: shown whole inside the frame,
with no grey behind it */
:where(.page-home) .card-media-collage {
  background: none;
}

:where(.page-home) .card-media-collage .card-image {
  object-fit: contain;
}

:where(.page-home) .card-body {
  grid-column: 1;
  grid-row: 1;
  align-self: start;
  /* No padding on the outer side, so the text lines up with the page edge */
  padding: 40px 40px 40px 0;
}

/* Every other card (1st, 3rd, 5th…) flips: image on the left, text on the right */
@media (min-width: 921px) {
  :where(.page-home) .card:nth-child(odd) {
    grid-template-columns: 2fr 1fr;
  }
  :where(.page-home) .card:nth-child(odd) .card-media {
    grid-column: 1;
  }
  :where(.page-home) .card:nth-child(odd) .card-body {
    grid-column: 2;
    padding: 40px 0 40px 40px;
  }
}

/* Scroll reveal: cards start faded and slightly lower, then rise into place */
:where(.page-home) .reveal-ready .card {
  opacity: 0;
  transform: translateY(32px);
  transition: opacity 0.6s ease, transform 0.6s ease;
}
:where(.page-home) .reveal-ready .card.is-visible {
  opacity: 1;
  transform: none;
}

/* Skip the animation for people who have turned on "Reduce motion" */
@media (prefers-reduced-motion: reduce) {
  :where(.page-home) .reveal-ready .card {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* On narrow screens, stack the image above the text */
@media (max-width: 920px) {
  :where(.page-home) .card {
    grid-template-columns: 1fr;
  }
  :where(.page-home) .card-media,
  :where(.page-home) .card-body {
    grid-column: 1;
    grid-row: auto;
  }
  :where(.page-home) .card-body {
    padding: 20px 0;
  }
  :where(.page-home) .bio {
    font-size: 24px;
  }
  :where(.page-home) header {
    margin-bottom: 56px;
  }
  /* Smaller gap under the navigation, so the first card peeks in on load */
  :root.page-home {
    --nav-bottom: 144px;
  }
}

/* Card title and description: the same style as the project page title
and lead, at a smaller size. Light weight, no gap between them, and
only colour tells them apart */
:where(.page-home) .card h3 {
  margin: 0;
  font-size: 24px;
  font-weight: 200;
  line-height: 1.4;
  color: var(--text);
}

:where(.page-home) .card p {
  margin: 0;
  font-size: 24px;
  font-weight: 200;
  line-height: 1.4;
  color: var(--subtle);
}

@media (max-width: 920px) {
  :where(.page-home) .card h3,
  :where(.page-home) .card p {
    font-size: 20px;
  }
}

/* Shared tags for homepage cards, project introductions, and contact skills. */
:where(.page-home, .page-project, .page-contact) .project-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0 0 24px;
  padding: 0;
  list-style: none;
}

:where(.page-project) .project-intro .project-tags {
  margin: 0 0 24px;
}

:where(.page-home, .page-project, .page-contact) .project-tags li {
  max-width: 100%;
  padding: 4px 10px;
  border: 1px solid var(--border);
  border-radius: 999px;
  color: var(--muted);
  font-size: 14px;
  font-weight: 300;
  line-height: 1.4;
}

/* "View project" button */
:where(.page-home) .button {
  position: relative;
  display: inline-block;
  margin-top: 24px;
  /* No padding on the sides, so the text lines up with the card text.
  A little room underneath for the line */
  padding: 4px 0;
  background: transparent;
  color: var(--text);
  font-size: 16px;
  font-weight: 400;
  text-decoration: none;
}

/* The line under the button. Hidden at rest: squashed to zero width at
the left. When the hover ends, the whole line fades out at once, and
only after that is it quietly reset, so each hover draws from zero */
:where(.page-home) .button::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 1px;
  background: var(--text);
  transform: scaleX(0);
  transform-origin: left;
  opacity: 0;
  transition: opacity 0.3s ease, transform 0s linear 0.3s;
}

/* On hover the line grows from left to right, from zero to full width */
:where(.page-home) .button:hover::after,
:where(.page-home) .button:focus-visible::after {
  transform: scaleX(1);
  opacity: 1;
  transition: transform 0.6s ease, opacity 0s;
}

/* With "Reduce motion" on, the line just appears */
@media (prefers-reduced-motion: reduce) {
  :where(.page-home) .button::after,
  :where(.page-home) .button:hover::after,
  :where(.page-home) .button:focus-visible::after {
    transition: none;
  }
}

:where(.page-home) .button:focus-visible {
  outline: 2px solid var(--text);
  outline-offset: 3px;
}

:where(.page-home) .button.coming-soon {
  cursor: default;
}

:where(.page-home) .button.coming-soon::after {
  content: none;
}

/* Page load animation, the same as the project page: the bio comes in
one line at a time */
/* Keep the bio hidden until the script has split it into lines */
.animate-in:where(.page-home) .bio:not(.lines-ready) {
  visibility: hidden;
}

/* The bio is split into small word boxes. Every box on the same line
shares a delay, so each line rises a short way and fades in together */
:where(.page-home) .text-piece {
  display: inline-block;
}

:where(.page-home) .lines-ready .text-piece {
  animation: home-rise-in-line 0.9s cubic-bezier(0.22, 1, 0.36, 1) both;
  animation-delay: var(--delay);
}

@keyframes home-rise-in-line {
  from {
    opacity: 0;
    transform: translateY(24px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* CONTACT */

:where(.page-contact) body {
  min-height: 100dvh;
  padding-bottom: 48px;
}

:where(.page-contact) .site-nav {
  position: relative;
  z-index: 2;
}

/* Keep each menu link readable while the photos pass underneath. */
:where(.page-contact) .site-nav a {
  background: var(--background);
  box-shadow: 0 0 0 8px var(--background);
}

/* Profile: photo on the left half, description on the right half,
lined up with the text blocks on the project page */
:where(.page-contact) .profile {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 40px;
  align-items: start;
}

/* The text sets the page height; the gallery occupies the left column
but its photos scroll in a separate, full-window viewport. */
:where(.page-contact) .profile-gallery {
  position: relative;
  align-self: stretch;
  min-width: 0;
}

/* The mask reaches both window edges. Initial padding aligns the first
photos with the name, then scrolls away so photos can pass behind the menu. */
:where(.page-contact) .profile-collage {
  position: fixed;
  top: 0;
  bottom: 0;
  left: max(24px, calc((100vw - var(--page-width)) / 2));
  width: calc((min(100vw - 48px, var(--page-width)) - 40px) / 2);
  height: 100dvh;
  padding: calc(32px + 27px + var(--nav-bottom)) 0 32px;
  overflow-x: hidden;
  overflow-y: auto;
  scrollbar-width: none;
}

:where(.page-contact) .profile-collage::-webkit-scrollbar {
  display: none;
}

:where(.page-contact) .profile-collage:focus-visible {
  outline: 2px solid var(--text);
  outline-offset: -2px;
}

:where(.page-contact) .profile-collage-top {
  position: relative;
  aspect-ratio: 4 / 5;
}

:where(.page-contact) .profile-collage img {
  position: absolute;
  display: block;
  object-fit: cover;
  background: var(--border);
}

:where(.page-contact) .profile-collage-portrait {
  left: 0;
  top: 32%;
  width: 58%;
  height: 62%;
}

:where(.page-contact) .profile-collage-iceland {
  left: 58%;
  top: 0;
  width: 32%;
  height: 32%;
}

:where(.page-contact) .profile-collage-building {
  left: 16%;
  top: 0;
  width: 22%;
  height: 26%;
}

:where(.page-contact) .profile-collage-beach {
  left: 64%;
  top: 64%;
  width: 36%;
  height: 36%;
}

:where(.page-contact) .profile-collage .profile-collage-camera {
  position: static;
  width: 50%;
  height: auto;
  margin: 32px 0 0 42%;
}

/* Colombia's top-right corner meets the camera selfie's bottom-left. */
:where(.page-contact) .profile-collage .profile-collage-colombia {
  position: static;
  width: 42%;
  height: auto;
  margin: 0;
}

/* Name and intro: the same title and lead style as the project page */
:where(.page-contact) .profile-name {
  margin: 0;
  font-size: 34px;
  font-weight: 200;
  line-height: 1.2;
  color: var(--text);
}

:where(.page-contact) .profile-lead {
  margin: 6px 0 0;
  font-size: 34px;
  font-weight: 200;
  line-height: 1.3;
  color: var(--subtle);
}

/* Longer description: the same style as the project page paragraphs */
:where(.page-contact) .profile-description {
  margin-top: 32px;
}

:where(.page-contact) .profile-description p {
  margin: 0;
  font-size: 18px;
  font-weight: 300;
  color: var(--muted);
}

:where(.page-contact) .profile-description p + p {
  margin-top: 16px;
}

/* Contact details: small labels with the answer below, the same as the
role and timeline on the project page */
:where(.page-contact) .contact-details {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 40px;
  margin: 32px 0 0;
}

:where(.page-contact) .contact-details dt {
  margin: 0 0 8px;
  font-size: 14px;
  font-weight: 400;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--subtle);
}

:where(.page-contact) .contact-details dd {
  margin: 0;
  font-size: 18px;
  font-weight: 300;
  color: var(--text);
}

:where(.page-contact) .contact-details a {
  color: var(--text);
  text-underline-offset: 4px;
  overflow-wrap: anywhere;
}

:where(.page-contact) .core-skills {
  margin-top: 32px;
}

:where(.page-contact) .core-skills h2 {
  margin: 0 0 12px;
  font-size: 14px;
  font-weight: 400;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--subtle);
}

:where(.page-contact) .core-skills .project-tags {
  margin-bottom: 0;
}

/* On narrow screens, stack the photo above the text */
@media (min-width: 921px) {
  :where(.page-contact) .site-nav {
    position: sticky;
    top: 32px;
  }
}

@media (max-width: 920px) {
  :where(.page-contact) .site-nav {
    margin-bottom: 32px;
  }
  :where(.page-contact) .profile {
    grid-template-columns: minmax(0, 1fr);
    gap: 48px;
  }
  :where(.page-contact) .profile-gallery {
    width: calc(100% + 48px);
    margin-inline: -24px;
  }
  :where(.page-contact) .profile-collage {
    position: relative;
    inset: auto;
    display: flex;
    align-items: flex-end;
    gap: 16px;
    width: 100%;
    min-width: 0;
    max-width: none;
    height: clamp(160px, 50vw, 200px);
    padding: 0 24px;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x proximity;
    scroll-padding-inline: 24px;
  }
  :where(.page-contact) .profile-collage-top {
    display: contents;
  }
  :where(.page-contact) .profile-collage img,
  :where(.page-contact) .profile-collage .profile-collage-camera,
  :where(.page-contact) .profile-collage .profile-collage-colombia {
    position: static;
    display: block;
    flex: 0 0 auto;
    width: auto;
    height: 72%;
    margin: 0;
    scroll-snap-align: start;
  }
  :where(.page-contact) .profile-collage .profile-collage-portrait {
    order: -2;
    height: 100%;
  }
  :where(.page-contact) .profile-collage-building {
    order: -1;
  }
  :where(.page-contact) .profile-name,
  :where(.page-contact) .profile-lead {
    font-size: 24px;
  }
  :where(.page-contact) .contact-details {
    gap: 24px;
  }
}

@media (max-width: 560px) {
  :where(.page-contact) .contact-details {
    grid-template-columns: 1fr;
  }
}

/* Page load animation, the same feel as the other pages: the photo
rises in first, then the text follows */
.animate-in:where(.page-contact) .profile-collage,
.animate-in:where(.page-contact) .profile-text {
  animation: contact-rise-in 1.1s cubic-bezier(0.22, 1, 0.36, 1) both;
}

.animate-in:where(.page-contact) .profile-text {
  animation-duration: 0.9s;
  animation-delay: 0.5s;
}

@keyframes contact-rise-in {
  from {
    opacity: 0;
    transform: translateY(24px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* Optional contact portrait used by the draft project. */

/* Contact link in the corner: the profile photo is hidden, and appears
below the word Contact on hover. It floats over the page, so showing
it doesn't push anything down */
:where(.page-project) .nav-contact {
  position: relative;
  display: block;
}

:where(.page-project) .site-nav .nav-contact img {
  position: absolute;
  top: calc(100% + 12px);
  right: 0;
  z-index: 2;
  display: block;
  width: 115px;
  height: auto;
  background: var(--border);
  opacity: 0;
  transform: translateY(-8px);
  transition: opacity 0.3s ease, transform 0.3s ease;
  pointer-events: none;
}

:where(.page-project) .nav-contact:hover img,
:where(.page-project) .nav-contact:focus-visible img {
  opacity: 1;
  transform: none;
}

/* In the footer there's no room below, so the photo appears above */
:where(.page-project) .site-footer .site-nav .nav-contact img {
  top: auto;
  bottom: calc(100% + 12px);
  transform: translateY(8px);
}

:where(.page-project) .site-footer .nav-contact:hover img,
:where(.page-project) .site-footer .nav-contact:focus-visible img {
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  :where(.page-project) .site-nav .nav-contact img {
    transition: none;
  }
}

@media (max-width: 920px) {
  :where(.page-project) .site-nav .nav-contact img {
    width: 77px;
  }
}


