/* ============================================================
   Portfolio — simple version (built from Paper "Portfolio — Simple")
   Desktop layout first, then narrower windows and phones at the end.
   ============================================================ */

:root {
    --color-bg:             #ffffff;
    --color-ink:            #141414;
    --color-body:           #4a4a4a;
    --color-secondary:      #6b6b6b;
    --color-statement:      #083542;
    --color-rule:           #b5b5b5;
    --color-link:           #0095ff;

    --color-top-bg:         #eef0ec;
    --color-panel:          #f4f4f3;
    --color-rowpal-bg:      #e6e5e3;
    --color-lookup-bg:      #3f4533;

    --color-brand-hailo:    #f6c033;
    --color-brand-trainline:#00b3a0;
    --color-brand-hedgehog: #fa5528;
    --color-brand-rowpal:   #2d56b8;
    --color-brand-albatross:#563e88;

    --font-sans:            'Inter', system-ui, sans-serif;
    --font-serif:           'Newsreader', Georgia, serif;

    --column:               960px;
    --meta-width:           240px;
    --measure:              640px;
    --radius-panel:         clamp(6px, (100vw - 96px) * 0.00625, 9px);  /* 6px at 960 wide, 9px at 1440 */
}

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

html, body {
    background: var(--color-bg);
    color: var(--color-ink);
    font-family: var(--font-sans);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

/* "More info" links glide down to the case study */
@media (prefers-reduced-motion: no-preference) {
    html {
        scroll-behavior: smooth;
    }
}

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

a:hover {
    text-decoration: underline;
}

/* Full-width tinted band holding the header, intro, skills and career */
.top,
.page {
    display: flex;
    flex-direction: column;
    align-items: center;
}

.top {
    padding: 96px 24px 0;
    background: var(--color-top-bg);
}

/* On load, the header, intro, skills, career and side projects fade up
   gently, one after another. Skipped with reduced motion turned on. */
@media (prefers-reduced-motion: no-preference) {
    .top .column > * {
        animation: fade-up 700ms cubic-bezier(0.2, 0.6, 0.2, 1) both;
    }

    .top .column > :nth-child(2) { animation-delay: 80ms; }
    .top .column > :nth-child(3) { animation-delay: 160ms; }
    .top .column > :nth-child(4) { animation-delay: 240ms; }
    .top .column > :nth-child(5) { animation-delay: 320ms; }
}

@keyframes fade-up {
    from {
        opacity: 0;
        transform: translateY(8px);
    }
    to {
        opacity: 1;
        transform: none;
    }
}

.page {
    padding: 96px 24px 120px;
}

.column {
    display: flex;
    flex-direction: column;
    width: var(--column);
    max-width: 100%;
}

/* ------------------------------------------------------------
   Text styles
   ------------------------------------------------------------ */

.label {
    font-size: 13px;
    line-height: 30px;
    font-weight: 500;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--color-secondary);
}

.lead {
    font-family: var(--font-serif);
    font-size: 30px;
    line-height: 40px;
    font-weight: 400;
    color: var(--color-ink);
}

.body {
    font-size: 18px;
    line-height: 30px;
    color: var(--color-body);
}

.role-text {
    font-size: 18px;
    line-height: 30px;
    color: var(--color-ink);
}

/* Bullets between the items in each "My role" list take the project's colour */
.role-text .bullet {
    color: var(--bullet, currentColor);
}

#hailo     { --bullet: var(--color-brand-hailo); }
#trainline { --bullet: var(--color-brand-trainline); }
#hedgehog  { --bullet: var(--color-brand-hedgehog); }

.text-link {
    font-size: 18px;
    line-height: 30px;
    font-weight: 500;
}

.caption {
    font-size: 14px;
    line-height: 20px;
    color: var(--color-secondary);
}

/* ------------------------------------------------------------
   Header and intro
   ------------------------------------------------------------ */

.site-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding-bottom: 20px;
    font-size: 15px;
    line-height: 20px;
}

.site-header .who {
    display: flex;
    align-items: center;
    gap: 12px;
}

.site-header img {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
}

.site-header .name {
    font-weight: 600;
    color: var(--color-ink);
}

.site-header .title {
    color: var(--color-secondary);
}

.site-header .who-text {
    display: flex;
    gap: 12px;
}

.intro {
    display: flex;
    flex-direction: column;
    gap: 48px;
    padding: 120px 0 96px;
}

.intro .statement {
    font-family: var(--font-serif);
    font-size: 44px;
    line-height: 56px;
    font-weight: 400;
    letter-spacing: -0.01em;
    color: var(--color-statement);
}

.intro .body {
    width: var(--measure);
    max-width: 100%;
}

/* ------------------------------------------------------------
   Rows: label on the left, content on the right
   ------------------------------------------------------------ */

.row {
    display: flex;
    border-top: 1px solid var(--color-rule);
    padding-top: 40px;
}

.row > .label {
    width: var(--meta-width);
    flex-shrink: 0;
}

.skills {
    padding-bottom: 40px;
}

.skills p {
    width: var(--measure);
    font-size: 18px;
    line-height: 30px;
}

.career {
    padding-bottom: 40px;
}

.career ol {
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 18px;
    flex: 1;
}

.career li {
    display: flex;
    gap: 24px;
}

.career .years {
    width: 120px;
    flex-shrink: 0;
    font-size: 15px;
    line-height: 30px;
    color: var(--color-secondary);
}

.career .role {
    font-size: 18px;
    line-height: 30px;
    font-weight: 600;
}

.career .role--plain {
    font-weight: 400;
}

/* Company and book links: black and underlined, not blue */
.career a {
    color: var(--color-ink);
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 3px;
}

.career a:hover {
    text-decoration-thickness: 2px;
}

.career .note {
    font-size: 15px;
    line-height: 24px;
    color: var(--color-secondary);
}

/* Side projects: app icon on the left, name, description and links beside it */
.side-projects {
    padding-bottom: 120px;
}

.side-projects ul {
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 62px;
    flex: 1;
}

.side-projects li {
    display: grid;
    grid-template-columns: 88px 1fr;
    column-gap: 16px;
    align-items: start;
}

.side-projects img {
    grid-row: 1 / span 2;
    width: 88px;
    height: 88px;
}

.side-projects h3 {
    font-size: 18px;
    line-height: 30px;
    font-weight: 600;
}

.side-projects .app-text p {
    font-size: 15px;
    line-height: 24px;
}

.app-links {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    padding-top: 10px;
}

.app-links a {
    padding: 2px 8px;
    border-radius: 4px;
    outline: 1px solid rgb(0 0 0 / 0.14);
    font-size: 14px;
    line-height: 18px;
    color: var(--color-ink);
}

.app-links a:hover {
    text-decoration: none;
    background: rgb(0 0 0 / 0.05);
}

/* ------------------------------------------------------------
   Work sections
   ------------------------------------------------------------ */

.work {
    display: flex;
    flex-direction: column;
    gap: 56px;
    padding: 40px 0 120px;
}

.story {
    display: flex;
}

.meta {
    width: var(--meta-width);
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.meta h2 {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 15px;
    line-height: 30px;
    font-weight: 600;
}

.meta h2::before {
    content: "";
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--dot);
    flex-shrink: 0;
}

.meta p {
    padding-left: 20px;
    font-size: 13px;
    line-height: 20px;
    color: var(--color-secondary);
}

/* Dates and role: two lines here, one line on phones */
.meta p span {
    display: block;
}

.story-text {
    display: flex;
    flex-direction: column;
    gap: 24px;
    width: var(--measure);
    flex-shrink: 0;
}

.my-role {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding-top: 16px;
}

.my-role .label {
    line-height: 20px;
}

.highlight {
    display: flex;
    padding-top: 24px;
}

.highlight > .label {
    width: var(--meta-width);
    flex-shrink: 0;
}

.highlight .story-text {
    gap: 20px;
}

/* "Highlight" label: a highlighter-pen stroke fills across it, left to
   right, as it scrolls up the window, and empties as you scroll back.
   The page script sets --mark from 0 (empty) to 1 (full). The stroke is
   a slightly uneven shape so it looks hand-drawn. */
.marker {
    position: relative;
    isolation: isolate;
    color: color-mix(in srgb, var(--color-ink) calc(var(--mark, 0) * 100%), var(--color-secondary));
}

.marker::before {
    content: "";
    position: absolute;
    z-index: -1;
    inset: -1px -6px -1px -5px;
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 20' preserveAspectRatio='none'%3E%3Cpath d='M3 4.5C22 3 55 4.2 97.5 2.8c1.2 3.5 1.6 9 .6 13.4C70 17.6 33 16.6 1.6 17.6.4 13.4.6 8.6 3 4.5z' fill='%23ffe66b'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
    transform: rotate(-1.2deg);
    clip-path: inset(0 calc(100% - var(--mark, 0) * 100%) 0 0);
}

.tools {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding-top: 16px;
}

.tools div {
    display: flex;
    align-items: flex-start;
}

.tools .label {
    width: 80px;
    flex-shrink: 0;
    line-height: 26px;
}

.tags {
    list-style: none;
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.tags li {
    padding: 2px 8px;
    border-radius: 4px;
    background: var(--color-top-bg);
    font-size: 14px;
    line-height: 22px;
}

/* ------------------------------------------------------------
   Image panels
   Each panel is one image exported from Paper at 3×, saved at
   2× and 1× of its widest size. The browser picks the smallest
   file that stays sharp on the screen it's showing on.
   ------------------------------------------------------------ */

figure {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.panel {
    position: relative;
    overflow: hidden;
    border-radius: var(--radius-panel);
    background: var(--color-panel);     /* shows while the image loads */
}

.panel img {
    display: block;
    width: 100%;
    height: auto;
}

/* <picture> wrappers shouldn't affect layout; the <img> inside is the box */
picture {
    display: contents;
}

/* Without this, each <source> becomes an empty item in flex rows and adds
   an extra gap (it pushed the header photo 12px in). Hiding it doesn't
   change which image the browser picks. */
picture source {
    display: none;
}

.panel--outline {
    outline: 1px solid #e3e3e3;
}

.pair {
    display: flex;
    gap: 16px;
}

.pair > * {
    flex: 1 1 0;
    min-width: 0;
}

/* Panels that sit closer together on phones (RowPal) */
.panel-group {
    display: flex;
    flex-direction: column;
    gap: 56px;
}

/* ------------------------------------------------------------
   Breakout: panels grow past the 960px text column on wider
   windows, up to 1440px, leaving at least 48px each side.
   ------------------------------------------------------------ */

.breakout {
    --breakout: clamp(100%, 100vw - 96px, 1440px);
    width: var(--breakout);
    margin-left: calc((100% - var(--breakout)) / 2);
}

/* 16px gap at 960px wide, growing to 24px at 1440px */
.breakout.pair,
.breakout .pair {
    gap: clamp(16px, 16px + (100vw - 1056px) / 60, 24px);
}

/* Two photos of different widths at the same height: each grows in
   proportion to its width in Paper (--w) */
.pair--photos > .panel {
    flex: var(--w) 1 0;
}

/* ------------------------------------------------------------
   Carousel (Hailo): one image per slide. Slides sit in a row
   you can swipe or scroll sideways; each one snaps into place.
   The arrows and bars below move between them.
   ------------------------------------------------------------ */

.carousel {
    gap: 16px;
}

.carousel-track {
    display: flex;
    list-style: none;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
}

.carousel-track::-webkit-scrollbar {
    display: none;
}

.carousel-track:focus-visible {
    outline: 2px solid var(--color-link);
    outline-offset: -2px;
}

@media (prefers-reduced-motion: no-preference) {
    .carousel-track {
        scroll-behavior: smooth;
    }
}

/* Desktop (a wide window with a mouse or trackpad): the image carousels
   drop their arrow buttons. The arrow cursors over the slides and the bars
   below are enough. Phones, tablets and touch screens keep the buttons. */
@media (min-width: 1024px) and (hover: hover) and (pointer: fine) {
    .breakout.carousel .carousel-arrow {
        display: none;
    }

    .breakout.carousel .carousel-bars {
        margin-right: 0;
    }
}

/* Pointing at an image slide: an arrow cursor for the way a click will go */
.carousel-track[data-side="prev"] {
    cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40' viewBox='0 0 40 40'%3E%3Ccircle cx='20' cy='20' r='19' fill='%23141414' stroke='%23fff' stroke-width='2'/%3E%3Cpath d='M22.5 14l-6 6 6 6' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") 20 20, w-resize;
}

.carousel-track[data-side="next"] {
    cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40' viewBox='0 0 40 40'%3E%3Ccircle cx='20' cy='20' r='19' fill='%23141414' stroke='%23fff' stroke-width='2'/%3E%3Cpath d='M17.5 14l6 6-6 6' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") 20 20, e-resize;
}

.carousel-slide {
    position: relative;     /* holds the prototype video and its play button */
    flex: 0 0 100%;
    scroll-snap-align: start;
    scroll-snap-stop: always;
}

.carousel-slide img {
    display: block;
    width: 100%;
    height: auto;
}

.carousel-controls {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 24px;
}

.carousel-count {
    margin-right: 6px;
    font-weight: 500;
    color: var(--color-ink);
    font-variant-numeric: tabular-nums;
}

.carousel-pager {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
}

.carousel-bars {
    display: flex;
    margin-right: 16px;
}

/* Each bar is a button with a taller area to click than the line it shows */
.carousel-bar {
    display: flex;
    align-items: center;
    height: 24px;
    padding: 0 3px;
    border: 0;
    background: none;
    cursor: pointer;
}

.carousel-bar::before {
    content: "";
    width: 10px;
    height: 2px;
    border-radius: 1px;
    background: #c4c4c4;
    transition: width 0.3s ease, background-color 0.3s ease;
}

.carousel-bar[aria-current="true"]::before {
    width: 28px;
    background: var(--color-ink);
}

/* Arrows: white chevron in a black circle so they stand out from the page */
.carousel-arrow {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border: 0;
    border-radius: 50%;
    background: var(--color-ink);
    color: #fff;
    cursor: pointer;
    transition: background-color 0.2s ease, color 0.2s ease, transform 0.2s ease;
}

.carousel-arrow:hover:not(:disabled) {
    background: #3a3a3a;
}

.carousel-arrow:active:not(:disabled) {
    transform: scale(0.94);
}

.carousel-arrow:focus-visible {
    outline: 2px solid var(--color-link);
    outline-offset: 2px;
}

/* First or last slide: the arrow that can't go further fades back */
.carousel-arrow:disabled {
    background: #e6e6e6;
    color: #a3a3a3;
    cursor: default;
}

.carousel-arrow path {
    fill: none;
    stroke: currentColor;
    stroke-width: 1.5;
    stroke-linecap: round;
    stroke-linejoin: round;
}

@media (prefers-reduced-motion: reduce) {
    .carousel-bar::before,
    .carousel-arrow {
        transition: none;
    }
}

/* ------------------------------------------------------------
   Passenger quotes (Hailo)
   ------------------------------------------------------------ */

.quotes {
    gap: 40px;
}

.quote-pair {
    display: flex;
    gap: 40px;
}

.quote--small {
    flex: 1 1 0;
    gap: 8px;
    padding-left: 20px;
    border-left: 2px solid var(--color-brand-hailo);
}

.quote--small blockquote {
    font-size: 17px;
    line-height: 28px;
    color: var(--color-body);
}

/* More quotes: two at a time in a carousel under the lead quote */
.carousel--quotes {
    display: flex;
    flex-direction: column;
    gap: 24px;
}

.carousel--quotes .carousel-track:focus-visible {
    outline-offset: 4px;
}

/* ------------------------------------------------------------
   Things placed over a panel image
   ------------------------------------------------------------ */

/* Prototype: clicking anywhere on the panel plays the video in place of the still */
.prototype {
    cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40' viewBox='0 0 40 40'%3E%3Ccircle cx='20' cy='20' r='19' fill='%23141414' stroke='%23fff' stroke-width='2'/%3E%3Cpath d='M16.5 13.5v13l10-6.5z' fill='%23fff' stroke='%23fff' stroke-width='1.5' stroke-linejoin='round'/%3E%3C/svg%3E") 20 20, pointer;
}

.prototype.is-playing {
    cursor: auto;
}

/* While the video shows: pause cursor when it's playing, play when it's paused */
.prototype video[data-cursor="pause"] {
    cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40' viewBox='0 0 40 40'%3E%3Ccircle cx='20' cy='20' r='19' fill='%23141414' stroke='%23fff' stroke-width='2'/%3E%3Crect x='14.5' y='13.5' width='3.5' height='13' rx='1' fill='%23fff'/%3E%3Crect x='22' y='13.5' width='3.5' height='13' rx='1' fill='%23fff'/%3E%3C/svg%3E") 20 20, pointer;
}

.prototype video[data-cursor="play"] {
    cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40' viewBox='0 0 40 40'%3E%3Ccircle cx='20' cy='20' r='19' fill='%23141414' stroke='%23fff' stroke-width='2'/%3E%3Cpath d='M16.5 13.5v13l10-6.5z' fill='%23fff' stroke='%23fff' stroke-width='1.5' stroke-linejoin='round'/%3E%3C/svg%3E") 20 20, pointer;
}

.play {
    position: absolute;
    top: 50%;
    left: 50%;
    translate: -50% -50%;
    padding: 13px 38px;
    border: 0;
    border-radius: 999px;
    background: #000;
    color: #fff;
    font-family: inherit;
    font-size: 14px;
    line-height: 20px;
    cursor: pointer;
}

.prototype:hover .play {
    background: #222;
}

/* The button shows the same play cursor as the rest of the slide */
.prototype .play {
    cursor: inherit;
}

/* Screen recordings sit over the screen in a panel image. Each
   video's position and corner radius are measured from the Paper
   export, as percentages of the panel. */
.screen-video {
    position: absolute;
    object-fit: cover;
}

.video-prototype {
    left: 8.287%;
    top: 8.372%;
    width: 83.449%;
    height: 82.868%;
    border-radius: 1.373% / 2.316%;
    outline: 1px solid #c6c6c6;
    outline-offset: -1px;
}

.video-rowpal {
    left: 25.706%;
    top: 8.185%;
    width: 48.776%;
    height: 83.667%;
    border-radius: 14.48% / 6.64%;
}

.video-lookup {
    left: 14.421%;
    top: 11.048%;
    width: 20.347%;
    height: 77.864%;
    border-radius: 10.47% / 4.82%;
}

/* ------------------------------------------------------------
   Footer
   ------------------------------------------------------------ */

.site-footer {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    padding-top: 40px;
}

/* Small line under the footer saying how the site was made */
.colophon {
    padding-top: 80px;
    font-size: 13px;
    line-height: 20px;
    color: var(--color-secondary);
}

/* ------------------------------------------------------------
   Section navigation (wide windows only): a short line per section
   close to the left edge of the window. The current section's line
   grows and fills with its brand colour as you scroll through it.
   Lines for sections you've passed turn darker. Pointing at the
   lines opens a small frosted panel with the names. Only the lines
   respond to the pointer, so the hidden names never block clicks on
   the page underneath. The script at the end of the page sets
   --progress and the is-active, is-past and is-announcing classes.
   ------------------------------------------------------------ */

.page-nav {
    display: none;
}

@media (min-width: 1280px) {
    .page-nav {
        --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
        --tick:      #d0d3cd;
        --tick-past: #9b9e98;
        --frost:     rgb(255 255 255 / 0.82);
        position: fixed;
        z-index: 10;
        top: 50%;
        left: 12px;
        transform: translateY(-50%);
        display: flex;
        flex-direction: column;
        pointer-events: none;
    }

    /* Frosted panel behind the names */
    .page-nav::before {
        content: "";
        position: absolute;
        z-index: -1;
        inset: -10px -6px -10px -8px;
        border-radius: 12px;
        background: var(--frost);
        -webkit-backdrop-filter: blur(16px) saturate(1.4);
        backdrop-filter: blur(16px) saturate(1.4);
        box-shadow: 0 1px 2px rgb(0 0 0 / 0.05), 0 12px 32px -8px rgb(0 0 0 / 0.14);
        opacity: 0;
        transform: scale(0.96);
        transform-origin: left center;
        transition: opacity 0.25s ease, transform 0.45s var(--ease-out);
    }

    .page-nav:hover::before,
    .page-nav:focus-within::before {
        opacity: 1;
        transform: none;
    }

    /* Lines sit in a 28px slot so the names line up whatever their length */
    .page-nav a {
        position: relative;
        display: grid;
        grid-template-columns: 28px auto;
        align-items: center;
        column-gap: 14px;
        height: 24px;
        padding-right: 14px;
        font-size: 13px;
        line-height: 20px;
        font-weight: 500;
        color: var(--color-secondary);
        animation: page-nav-in 0.7s var(--ease-out) both;
        animation-delay: calc(300ms + var(--i) * 50ms);
    }

    /* The pointer target: the strip of margin the lines sit in */
    .page-nav a::before {
        content: "";
        position: absolute;
        top: 0;
        bottom: 0;
        left: -12px;
        width: 60px;
        pointer-events: auto;
    }

    .page-nav:hover a,
    .page-nav:focus-within a {
        pointer-events: auto;
    }

    .page-nav a:hover {
        text-decoration: none;
    }

    .page-nav a:focus-visible {
        outline: 2px solid var(--color-link);
        outline-offset: 2px;
        border-radius: 4px;
    }

    .page-nav .tick {
        position: relative;
        flex-shrink: 0;
        width: 10px;
        height: 2px;
        border-radius: 1px;
        background: var(--tick);
        overflow: hidden;
        transition: width 0.5s var(--ease-out), background-color 0.3s ease;
    }

    .page-nav .fill {
        position: absolute;
        inset: 0;
        background: var(--dot, var(--color-ink));
        transform-origin: left;
        transform: scaleX(var(--progress, 0));
        opacity: 0;
        transition: opacity 0.3s ease;
    }

    .page-nav a.is-past .tick {
        background: var(--tick-past);
    }

    .page-nav a.is-active .tick {
        width: 28px;
        background: var(--tick);
    }

    .page-nav a.is-active .fill {
        opacity: 1;
    }

    .page-nav a:not(.is-active):hover .tick {
        width: 18px;
        background: var(--color-secondary);
    }

    .page-nav .name {
        margin-left: -8px;
        padding: 2px 8px;
        border-radius: 6px;
        white-space: nowrap;
        opacity: 0;
        transform: translateX(-6px);
        transition: opacity 0.2s ease, transform 0.4s var(--ease-out), color 0.2s ease, background-color 0.2s ease;
    }

    /* Names slide in one after another */
    .page-nav:hover .name,
    .page-nav:focus-within .name {
        opacity: 1;
        transform: none;
        transition-delay: calc(var(--i) * 30ms);
    }

    /* Entering a new section shows its name for a moment, on its own
       small frosted label so it can be read over a picture */
    .page-nav.is-announcing a.is-active .name {
        opacity: 1;
        transform: none;
    }

    .page-nav.is-announcing:not(:hover) a.is-active .name {
        background: var(--frost);
        -webkit-backdrop-filter: blur(16px) saturate(1.4);
        backdrop-filter: blur(16px) saturate(1.4);
    }

    .page-nav a.is-active .name,
    .page-nav a:hover .name {
        color: var(--color-ink);
    }
}

@keyframes page-nav-in {
    from {
        opacity: 0;
        transform: translateX(-8px);
    }
}

@media (prefers-reduced-motion: reduce) {
    .page-nav::before,
    .page-nav a,
    .page-nav .tick,
    .page-nav .fill,
    .page-nav .name {
        animation: none;
        transition: none;
    }
}

/* ------------------------------------------------------------
   Narrower windows (940px and below): labels and project
   details sit above their text instead of beside it
   ------------------------------------------------------------ */

@media (max-width: 940px) {
    .row,
    .story,
    .highlight {
        flex-direction: column;
        gap: 16px;
    }

    .story {
        gap: 20px;
    }

    .row > .label,
    .meta,
    .highlight > .label {
        width: auto;
    }

    .story-text,
    .skills p {
        width: auto;
        max-width: var(--measure);
    }
}

/* ------------------------------------------------------------
   Phones (640px and below), from Paper "Portfolio — Mobile".
   The <picture> elements switch to the phone versions of the
   rearranged panels at the same width.
   ------------------------------------------------------------ */

@media (max-width: 640px) {
    :root {
        --radius-panel: 0px;
    }

    .top {
        padding: 20px 24px 0;
    }

    .page {
        padding: 40px 24px 64px;
    }

    /* Header: title under the name; the email address is in the footer */
    .site-header .who-text {
        flex-direction: column;
        gap: 0;
    }

    .site-header .title {
        font-size: 13px;
        line-height: 18px;
    }

    .site-header > a {
        display: none;
    }

    .site-header {
        padding-bottom: 0;
    }

    .intro {
        gap: 24px;
        padding: 56px 0 48px;
    }

    .intro .statement {
        font-size: 30px;
        line-height: 38px;
    }

    .body,
    .role-text,
    .text-link,
    .skills p {
        font-size: 17px;
        line-height: 28px;
    }

    .lead {
        font-size: 24px;
        line-height: 32px;
    }

    .row {
        gap: 8px;
        padding-top: 24px;
    }

    .row > .label {
        line-height: 20px;
    }

    .skills {
        padding-bottom: 24px;
    }

    .career {
        gap: 16px;
        padding-bottom: 24px;
    }

    .career ol {
        gap: 20px;
    }

    .career li {
        flex-direction: column;
        gap: 0;
    }

    .career .years {
        width: auto;
        font-size: 14px;
        line-height: 22px;
    }

    .career .role {
        font-size: 17px;
        line-height: 26px;
    }

    .career .note {
        font-size: 14px;
        line-height: 22px;
    }

    /* Side projects: links move to their own line under the icon */
    .side-projects {
        gap: 16px;
        padding-bottom: 56px;
    }

    .side-projects ul {
        gap: 28px;
    }

    .side-projects li {
        grid-template-columns: 64px 1fr;
        column-gap: 14px;
        align-items: center;
    }

    .side-projects img {
        grid-row: auto;
        width: 64px;
        height: 64px;
    }

    .side-projects .app-text {
        display: flex;
        flex-direction: column;
        gap: 2px;
    }

    .side-projects h3 {
        font-size: 17px;
        line-height: 24px;
    }

    .side-projects .app-text p {
        line-height: 22px;
    }

    .app-links {
        grid-column: 1 / -1;
        gap: 8px;
        padding-top: 12px;
    }

    .app-links a {
        padding: 5px 12px;
    }

    .work {
        gap: 32px;
        padding: 24px 0 72px;
    }

    .story-text {
        gap: 20px;
    }

    .meta {
        gap: 2px;
    }

    .meta h2 {
        line-height: 26px;
    }

    .meta p span {
        display: inline;
    }

    .meta p span + span::before {
        content: "· ";
    }

    .my-role,
    .tools {
        padding-top: 8px;
    }

    .highlight {
        padding-top: 8px;
    }

    .highlight > .label {
        line-height: 20px;
    }

    .highlight .story-text {
        gap: 16px;
    }

    .tools .label {
        width: 64px;
    }

    /* Panels run edge to edge; captions keep the text margins */
    .breakout {
        width: calc(100% + 48px);
        margin-left: -24px;
    }

    figure {
        gap: 10px;
    }

    .caption {
        padding: 0 24px;
        font-size: 13px;
        line-height: 18px;
    }

    .panel--outline {
        outline: none;
    }

    .breakout.pair {
        flex-direction: column;
        gap: 32px;
    }

    .breakout.pair > * {
        flex: none;
    }

    .panel-group,
    .panel-group .breakout.pair {
        gap: 12px;
    }

    .pair--photos {
        flex-direction: column;
    }

    .breakout .pair--photos {
        gap: 12px;
    }

    .pair--photos > .panel {
        flex: none;
    }

    /* Apple Watch: trim the empty sides so the watches are bigger */
    .panel--watch img {
        aspect-ratio: 1100 / 760;
        object-fit: cover;
    }

    .carousel {
        gap: 12px;
    }

    .carousel-controls {
        align-items: flex-start;
        gap: 16px;
    }

    /* Image carousel runs edge to edge; its controls keep the text margins */
    .breakout.carousel .carousel-controls {
        padding: 0 24px;
    }

    .carousel--quotes {
        gap: 20px;
    }

    .carousel-controls .caption {
        padding: 0;
        padding-top: 9px;
    }

    .carousel-count {
        display: block;
        margin: 0;
    }

    .carousel-bars {
        display: none;
    }

    .carousel-arrow {
        width: 36px;
        height: 36px;
    }

    .quotes {
        gap: 28px;
    }

    .quote-pair {
        flex-direction: column;
        gap: 24px;
    }

    .quote .caption {
        padding: 0;
    }

    .quote--small {
        padding-left: 16px;
    }

    .play {
        padding: 10px 30px;
        font-size: 12px;
        line-height: 16px;
    }

    .video-lookup {
        left: 12.949%;
        top: 2.852%;
        width: 74.038%;
        height: 60.187%;
    }

    .video-rowpal {
        left: 14.359%;
        top: 6.643%;
        width: 71.410%;
        height: 86.714%;
    }

    .colophon {
        padding-top: 48px;
    }

    .site-footer {
        flex-direction: column;
        align-items: flex-start;
        gap: 8px;
        padding-top: 24px;
    }
}
