/* INHERIT */

html {
    font-family: 'epilogue', sans-serif;
    color: #ffffff;
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    background-color: #0D0D0D;
    scroll-behavior: smooth;
}

body {
    background-color: #0D0D0D;
    max-width: 800px;
    min-width: 320px;
    margin: 0 auto;
    padding-left: 16px;
    padding-right: 16px;
    padding-bottom: 16px;
    padding-top: 40px;
}

h1 {
    font-weight: 700;
    font-size: 80px;
    line-height: 100%;
    margin-bottom: 0px;
    margin-top: 24px;
}

h2 {
    font-weight: 500;
    font-size: 2.5em;
    line-height: 150%;
    margin: 0px;
    cursor: pointer;
    transition: transform 0.2s ease-in-out;
    touch-action: manipulation;
    display: inline-block;
    transform-origin: left center;
}

h2:hover,
h2:focus-visible {
    transform: scale(1.03);
}

h2:active {
    transform: scale(0.99);
}

h2:focus-visible {
    outline: 2px solid #2086DF;
    outline-offset: 4px;
}

h3 {
    font-weight: 500;
    font-size: 24px;
    line-height: 150%;
    margin: 0px;
}

p, li {
    font-family: 'epilogue', sans-serif;
    font-weight: 350;
    font-size: 24px;
    line-height: 150%;
    color: #808080;
    margin: 0px;
}





/* CLASSES */

.case-study-surface {
    padding-top: 40px;
    display: flex;
    flex-direction: column;
    gap: 24px;
}

.section {
    margin-top: 160px;
    display: flex;
    flex-direction: column;
    align-items: left;
    justify-content: center;
    gap: 24px;
    scroll-margin-top: 80px;
}

.hero-section {
    display: flex;
    flex-direction: column;
    align-items: left;
    justify-content: center;
}

/* Disable hover transform for the hero header only (primary-surface contains the hero h2). */
.primary-surface h2 {
    cursor: default; /* not interactive */
}

.primary-surface h2:hover,
.primary-surface h2:active {
    transform: none !important; /* override global h2 hover transform */
    cursor: default;
    transition: none; /* avoid visual jitter */
}

/*
 * Breathing room above the hero, on top of the body's own top padding. Desktop
 * gets the larger share — there's more screen to spend, and the signature has
 * further to fall before the headline reads as the top of the page.
 */
#hero {
    margin-top: 112px;
}

@media (max-width: 600px) {
    #hero {
        margin-top: 56px;
    }
}

.case-study {
    box-sizing: border-box;
    background-color: #1B1B1B;
    padding: 16px;
    border-radius: 24px;
    display: flex;
    flex-direction: column;
    align-items: left;
    justify-content: center;
    gap: 16px;
    min-height: 373px;
    position: relative;
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
    transition: transform 0.2s ease-in-out, box-shadow 0.3s ease-in-out;
}

.case-study:hover,
.case-study:focus-visible {
    background-color: #1f1f1f; 
    box-shadow: 0 12px 24px rgba(0, 0, 0, 0.15);
    transform: scale(1.02) rotate(-1deg);
    cursor: pointer; 
    transition: transform 0.2s ease-in-out;
}

.case-study:active {
    background-color: #1f1f1f;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
    transform: scale(0.99) rotate(-1deg);
}

/* Disabled card: "Changed Mental Models to Increase Technician Productivity" */
#communications {
    position: relative;
    background-color: rgba(27, 27, 27, 0.5); /* ghosted card surface */
    cursor: default;
}

/* Ghost the card's content, but keep the scribble overlay and the
   "Locked" chip at full strength — the chip is what explains the ghosting */
#communications > *:not(.case-study-scribble):not(.card-chip) {
    opacity: 0.5;
}

/* No hover/focus visual change on the disabled card */
#communications:hover,
#communications:focus-visible,
#communications:active {
    background-color: rgba(27, 27, 27, 0.5);
    box-shadow: none;
    transform: none;
    cursor: default;
}

/* lock.svg has extra empty padding baked into its viewBox, making it render smaller than sibling case-study images at the same size; scale it up to match */
#communications .case-study-image {
    transform: scale(1.4);
}

/* big-scribble.svg overlaid on the disabled card, scaled up and allowed to overflow the card edges rather than being clipped */
.case-study-scribble {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 100%;
    height: 100%;
    transform: translate(-50%, -50%);
    object-fit: contain;
    pointer-events: none;
    z-index: 1;
}

.case-study-static {
    margin-top: 40px;
    width: 100%;
    padding: 24px;
    margin-left: auto;
    margin-right: auto;
    background-color: #1f1f1f;
    box-shadow: 0 12px 24px rgba(0, 0, 0, 0.15);
    transform: scale(1.02) rotate(-1deg);
    cursor: default;
    transition: none;
        animation: slideInFromBottom 0.3s ease-out forwards;
}

/* Maintain the "hovered" appearance on hover (no interactive change) */
.case-study-static:hover,
.case-study-static:focus-visible,
.case-study-static:active {
    background-color: #1f1f1f;
    box-shadow: 0 12px 24px rgba(0, 0, 0, 0.15);
    transform: scale(1.02) rotate(-1deg);
    cursor: default;
    transition: none;
}

@keyframes slideInFromBottom {
    0% {
        opacity: 0;
        transform: translateY(50px);
    }
    100% {
        opacity: 1;
        transform: scale(1.02) rotate(-1deg) translateY(0);
    }
}

/* Exit animation — triggered when navigating back to home */
.case-study-static.slide-out {
        animation: slideOutToBottom 0.3s ease-in forwards;
    pointer-events: none;
}

@keyframes slideOutToBottom {
    0% {
        opacity: 1;
        transform: scale(1.02) rotate(-1deg) translateY(0);
    }
    100% {
        opacity: 0;
        transform: translateY(50px);
    }
}

.case-study-aside {
    box-sizing: border-box;
    margin: 40px auto 0;
    width: 100%;
    padding: 16px 20px;
    background-color: rgba(32, 134, 223, 0.08);
    border: 1px solid rgba(32, 134, 223, 0.24);
    border-radius: 16px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    transform: rotate(1deg);
    opacity: 0;
    animation: slideInFromBottomTilted 0.3s ease-out 0.15s forwards;
}

@keyframes slideInFromBottomTilted {
    0% {
        opacity: 0;
        transform: translateY(50px);
    }
    100% {
        opacity: 1;
        transform: rotate(1deg) translateY(0);
    }
}

/* Exit animation — mirrors the hero card's slide-out on navigation home */
.case-study-page.fade-out .case-study-aside {
    animation: slideOutToBottomTilted 0.3s ease-in forwards;
    pointer-events: none;
}

@keyframes slideOutToBottomTilted {
    0% {
        opacity: 1;
        transform: rotate(1deg) translateY(0);
    }
    100% {
        opacity: 0;
        transform: translateY(50px);
    }
}

.case-study-aside-label {
    font-family: 'epilogue', sans-serif;
    font-weight: 500;
    font-size: 16px;
    line-height: 1;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: #2086DF;
}

.case-study-aside p {
    font-size: 18px;
}

/*
 * Entrance: fade in navigation bar and content sections
 * (The hero card has its own slide-in animation)
 */
.case-study-page .navigation-bar,
.case-study-page .section {
    opacity: 0;
    animation: fadeInContent 0.3s ease-out forwards;
}

@keyframes fadeInContent {
    from {
        opacity: 0;
        transform: translateY(10px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/*
 * Exit: fade out navigation bar and content sections
 * (The hero card has its own slide-out animation)
 */
.case-study-page.fade-out .navigation-bar,
.case-study-page.fade-out .section {
    animation: fadeOutContent 0.3s ease-in forwards;
}

@keyframes fadeOutContent {
    from {
        opacity: 1;
        transform: translateY(0);
    }
    to {
        opacity: 0;
        transform: translateY(10px);
    }
}

.case-study-image {
    width: 25%;
    object-fit: cover;
    height: auto;
    max-width: 400px;
    border-radius: 24px;;
}

.card-chip {
    position: absolute;
    top: 16px;
    right: 16px;
    background-color: #0D0D0D;
    color: #808080;
    font-size: 16px;
    font-weight: 350;
    line-height: 1;
    padding: 8px 14px;
    border-radius: 9999px;
    border: 1px solid rgba(255, 255, 255, 0.08);
    pointer-events: none;
    z-index: 2;
}

.signature-image {
    width: 25%;
    object-fit: cover; 
    height: auto;
    max-width: 155px;
}

@media (max-width: 600px) {
    .signature-image {
        width: 45%;
        max-width: 260px;
    }
}

.primary-btn {
    width: 90%;
    color: #2086DF;
    border-radius: 16px;
    border-style: none;
    padding-bottom: 16px;
    font-weight: 300;
    font-size: 24px;
    align-items: center;
    text-align: left;
    text-decoration: none;
}

.segmented-button {
    background: none;
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
    color: white;
    border-radius: 16px;
    border-style: none;
    font-weight: 300;
    font-size: 18px;
    align-items: center;
    text-align: center;
    padding: 4px 12px 4px 12px;
    margin-right: 8px;
    margin-top: 32px;
    transition: transform 0.2s ease-in-out;
}

.segmented-button:hover,
.segmented-button:focus-visible {
    background-color: #1f1f1f; 
    box-shadow: 0 12px 24px rgba(0, 0, 0, 0.15);
    transform: scale(1.05) rotate(-1deg); 
    cursor: pointer; 
    transition: transform 0.2s ease-in-out;
}

.segmented-button:active {
    background-color: #2086DF15;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
    transform: scale(0.97) rotate(-1deg);
}

.segmented-button-active {
    color: #2086DF;
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
    border-radius: 16px;
    border-style: none;
    font-weight: 600;
    font-size: 18px;
    align-items: center;
    text-align: center;
    padding: 4px 12px 4px 12px;
    margin-right: 8px;
    margin-top: 32px;
    transition: transform 0.2s ease-in-out;
}

.segmented-button-active:hover,
.segmented-button-active:focus-visible {
    box-shadow: 0 12px 24px rgba(0, 0, 0, 0.15);
    transform: scale(1.02) rotate(-1deg); 
    cursor: pointer; 
    transition: transform 0.2s ease-in-out;
}

.segmented-button-active:active {
    background-color: #2086DF15;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
    transform: scale(0.97) rotate(-1deg);
}


.contact-links {
    display: flex;
    gap: 16px;
    justify-content: center;

    @media (max-width: 600px) {
        flex-direction: column;
    }
}

.contact-button {
    flex-grow: 1;
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
    display: flex;
    justify-content: center;
    gap: 8px;
    border-radius: 24px;
    padding: 16px;
    font-weight: 300;
    font-size: 24px;
    transition: transform 0.2s ease-in-out;
}

.contact-button:hover,
.contact-button:focus-visible { 
    box-shadow: 0 12px 24px rgba(0, 0, 0, 0.15);
    transform: scale(1.04) rotate(-1deg);
    cursor: pointer; 
    transition: transform 0.2s ease-in-out;
}

.contact-button:active {
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
    transform: scale(0.98) rotate(-1deg);
}

.major-emphasis {
    font-style: italic;
    color: #2086DF;
}

.total-emphasis {
    font-weight: 800;
}

.subtle-emphasis {
    font-style: italic;
    font-weight: 600;
}

.quote {
    font-size: 3em;
    line-height: 150%;
    font-weight: 500;
    color: #ffffff;
}

.quote-author {
    font-weight: 350;
    font-size: 24px;
    line-height: 125%;
    color: #808080;
    margin-bottom: 80px;
}

.custom-link {
    font-family: epilogue, sans-serif;
    font-size: 24px;
    line-height: 125%;
    color: #2086DF;
    text-decoration: underline;
}

.scribble-effect { 
    position: relative;
    display: inline-block;
    text-decoration: none;
    svg {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        fill: none;
        stroke: #2086DF;
    }
}

.button-arrow {
    vertical-align: middle;
    padding: 4px;
    width: 1em;
}

.back-btn .custom-link {
    display: inline-flex;
    align-items: center;
    border-radius: 9999px;
    padding-left: 8px;
    padding-right: 12px;
    transform-origin: left center;
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
    transition: transform 0.2s ease-in-out, background-color 0.2s ease-in-out;
}

.back-btn .custom-link .button-arrow {
    transition: translate 0.2s ease-in-out;
}

.back-btn .custom-link:hover,
.back-btn .custom-link:focus-visible {
    background-color: #1f1f1f;
    transform: scale(1.05);
    cursor: pointer;
}

.back-btn .custom-link:hover .button-arrow,
.back-btn .custom-link:focus-visible .button-arrow {
    translate: -4px;
}

.back-btn .custom-link:active {
    background-color: #2086DF15;
    transform: scale(0.98);
}

.back-btn .custom-link:active .button-arrow {
    translate: -2px;
}

.link-icon {
    vertical-align: middle;
    padding: 4px;
    width: .75em;
}

.case-study-h1 {
    font-weight: 700;
    font-size: 40px;
    line-height: 125%;
    margin-top: 24px;
}

.case-study-hero {
    width: 50%;
    align-self: center;
}

.navigation-bar {
    display: flex;
    background-color: rgba(13, 13, 13, 0.7);
    border-style: none;
    backdrop-filter: blur(10px);
    flex-direction: row;
    height: 60px;
    align-items: center;
    position: sticky;
    top: 0;
    z-index: 100;
    margin-left: -16px;
    margin-right: -16px;
    justify-content: space-between;
}

.navigation-bar > :nth-child(2) {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
}

.page-title {
    font-size: 18px;
    font-weight: 500;
    margin: auto;
}

.applications-grid {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    justify-items: center;
    align-items: center;

    @media (max-width: 700px) {
        grid-template-columns: 1fr 1fr;
    }

    img {
        width: 65%;
        object-fit: scale-down;
        display: block;
    }

    /* Larger icons in the two-column mobile range (321–700px) */
    @media (max-width: 500px) {
        .applications-grid img,
        .application-image {
            width: 85%;
        }
    }

}

.application-link {
    display: flex;
    justify-content: center;
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
}

.application-image {
    transition: transform 0.2s ease-in-out;
}

.application-image:hover {
    transform: scale(1.10) rotate(-1deg);
    transition: transform 0.2s ease-in-out;
}

.application-link:focus-visible .application-image,
.application-image:focus-visible {
    transform: scale(1.10) rotate(-1deg);
}

.application-link:active .application-image {
    transform: scale(0.95) rotate(-1deg);
}




/* ID's */

#profile-image {
    width: 80px;
    height: 80px;
    border-radius: 100px;
}

#hero-img-yeah {
    width: 100%;
    align-self: center;
}

#hero-signature {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 32px;
}

.polaroid {
    position: relative;
    width: 50%;
    align-self: center;
    cursor: pointer;
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
}

.polaroid:focus-visible {
    outline: 2px solid #2086DF;
    outline-offset: 6px;
    border-radius: 4px;
}

.neon-visor {
    display: block;
    width: 100%;
}

/*
 * Marker moustache overlay: the drawn SVG dropped in as-authored, sized and
 * placed as a percentage of the portrait so it stays on the face at any
 * rendered width. Percentages resolve against .polaroid, whose box is exactly
 * the portrait's box.
 */
.moustache {
    position: absolute;
    left: 50.23%;
    top: 35.92%;
    width: 17%;
    height: auto;
    pointer-events: none;
}

/*
 * Each half is dashed by its own length (--moustache-length, measured in
 * index.js) and offset out of sight; index.js toggles .is-drawn to pull the
 * offset back to 0, which reads as a marker travelling along the path. Both
 * halves start at the philtrum, so they draw outward from the middle. Stroke
 * colour, weight and the paper-grain filter are the SVG's own.
 */
.moustache-stroke {
    stroke-dasharray: var(--moustache-length, 0px);
    stroke-dashoffset: var(--moustache-length, 0px);
}

.polaroid.is-drawn .moustache-stroke {
    stroke-dashoffset: 0;
}

/*
 * Transitions only switch on once index.js has measured the paths: measuring
 * is itself a change to stroke-dashoffset, and with the transition already
 * live the moustache would draw and then wipe itself on first paint.
 */
.polaroid.is-inked .moustache-stroke {
    transition-property: stroke-dashoffset;
    transition-timing-function: cubic-bezier(0.45, 0.05, 0.35, 1);
    transition-duration: var(--moustache-duration, 400ms);
    /* Wiping replays the halves in reverse, so each one gets two delays. */
    transition-delay: var(--moustache-erase-delay, 0ms);
}

.polaroid.is-inked.is-drawn .moustache-stroke {
    transition-delay: var(--moustache-draw-delay, 0ms);
}

@media (prefers-reduced-motion: reduce) {
    .polaroid.is-inked .moustache-stroke,
    .polaroid.is-inked.is-drawn .moustache-stroke {
        transition: none;
    }
}

@media (max-width: 500px) {
    .polaroid {
        width: 87%;
    }
}

#traditional-art {
    mix-blend-mode: lighten;
}

#hero-image {
    margin-top: none;
    max-width: 320px;
    filter: grayscale();
}

#linkedin-btn {
    color: #0E76A8;
    font-weight: 400;
    background-color: #0E76A815;
    /* text-align: center; */
    text-decoration: none;
}

#about-me {
    margin-bottom: 120px;
}

#contact-me {
    margin-bottom: 120px;
}

#hero-sub {
    margin-bottom: -80px;
}

#dribbble-btn {
    color: #EA4C89;
    background-color: #EA4C8915;
    /* text-align: center; */
    text-decoration: none;
}

#gmail-btn {
    color: #4285F4;
    font-weight: 325;
    background-color: #4285F415;
    /* text-align: center; */
    text-decoration: none;
}

#applications {
    width: 100%;
    margin-top: 40px;
    display: block;
    margin-left: auto;
    margin-right: auto;
}

#gallery {
    display: grid;
    grid-template-columns: 1fr 1fr;
    justify-items: center;
    align-items: center;

    @media (max-width: 800px) {
        grid-template-columns: 1fr;
    }

    img {
        width: 100%;
        object-fit: scale-down;
        display: block;
    }

}

.gallery-item {
    /* content-box + width:100% + padding would overflow the viewport */
    box-sizing: border-box;
    height: 160px;
    padding: 24px;
}

#my-work {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 32px;

    @media (max-width: 700px) {
        grid-template-columns: 1fr;
    }
}

#footer-icon {
    width: 48px;
    height: 48px;
    align-self: center;
    color: #5E5E5E;
}

#site-footer p {
    align-self: center;
    text-align: center;
    margin-bottom: 16px;
    color: #5E5E5E;
}

#footer-image {
    width: 105%;
    align-self: center;
}

/* Keep native scrollbars visible for accessibility. */

/* Skip-link style: visible on keyboard focus */
.skip-link {
    position: absolute;
    left: -999px;
    top: auto;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

.skip-link:focus,
.skip-link:active {
    position: fixed;
    left: 16px;
    top: 16px;
    width: auto;
    height: auto;
    padding: 12px 20px;
    background: #111b2f;
    color: #2086DF;
    border-radius: 9999px;
    border: 1px solid rgba(255, 255, 255, 0.08);
    text-decoration: none;
    font-weight: 500;
    font-size: 18px;
    box-shadow: 0 12px 24px rgba(0, 0, 0, 0.2);
    z-index: 9999;
}

/* Respect users who prefer reduced motion */
@media (prefers-reduced-motion: reduce) {
    * {
        animation: none !important;
        transition: none !important;
        scroll-behavior: auto !important;
    }

    /* Ensure page content is visible when animations are disabled */
    .case-study-page .navigation-bar,
    .case-study-page .case-study-aside,
    .case-study-page .section {
        opacity: 1;
    }
}

/* Visible focus outline for interactive controls */
:focus-visible {
    outline: 2px solid #2086DF;
    outline-offset: 4px;
}

a:focus-visible, .contact-button:focus-visible, .primary-btn:focus-visible, .application-link:focus-visible, .case-study:focus-visible {
    outline: 2px solid #2086DF;
    outline-offset: 4px;
}

/*
 * Back-to-top button — fades/slides in a beat after the reader starts
 * scrolling down, and hides immediately when they return to the top.
 * Injected by index.js so every page picks it up automatically.
 */
.back-to-top {
    /* Laid out by .floating-dock, which owns the positioning for the pair. */
    order: 2;
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    padding: 0;
    border: none;
    border-radius: 9999px;
    /*
     * Opaque, with no backdrop-filter. A blurred backdrop on a fixed element
     * forces a compositing layer that mobile browsers rasterize against the
     * scrolling content, which makes the button visibly lag and drift while
     * the page moves. Desktop composites every frame, so it only showed on
     * mobile.
     */
    background-color: #242424;
    box-shadow: 0 12px 24px rgba(0, 0, 0, 0.3);
    cursor: pointer;
    /* No grey flash box when tapped on touch devices */
    -webkit-tap-highlight-color: transparent;

    /*
     * Hidden resting state — the visible state is .back-to-top.is-visible.
     * Scale only, no translate: a translate would drag the button toward the
     * bottom edge of the screen on the way out.
     *
     * The negative margin cancels the button's own width plus the dock's gap,
     * so while it is away the dock measures exactly as wide as the section nav
     * and centers the bar alone. Animating the margin back to 0 grows the dock
     * from the right, and `margin: 0 auto` re-centers it every frame — that is
     * the scoot. The button is laid over the bar's end meanwhile, harmless at
     * zero opacity.
     */
    opacity: 0;
    transform: scale(0.8);
    margin-left: -68px;
    pointer-events: none;
    transition: opacity 0.2s ease-in,
                transform 0.2s ease-in,
                margin-left 0.3s ease-in-out,
                background-color 0.2s ease-in-out;
    /* Hiding is immediate; the reveal delay lives on .is-visible below. */
    transition-delay: 0s;
}

.back-to-top.is-visible {
    opacity: 1;
    transform: scale(1);
    margin-left: 0;
    pointer-events: auto;
    /* Pop in with a touch of overshoot; the bar slides aside underneath it. */
    transition: opacity 0.2s ease-out,
                transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1),
                margin-left 0.3s ease-in-out,
                background-color 0.2s ease-in-out;
    /* Ease in a beat after the scroll rather than snapping in with it. */
    transition-delay: 0.45s;
}

.back-to-top.is-visible:hover,
.back-to-top.is-visible:focus-visible {
    background-color: #2b2b2b;
    transform: scale(1.08) rotate(-1deg);
    /* Snappy on hover — the overshoot belongs to the reveal only. */
    transition: transform 0.2s ease-in-out, background-color 0.2s ease-in-out;
    transition-delay: 0s;
}

/* Press state follows the house convention: subtle scale, softened shadow. */
.back-to-top.is-visible:active {
    transform: scale(0.97);
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
    transition-duration: 0.1s;
    transition-delay: 0s;
}

/*
 * Only keyboard focus gets a ring — a tap or click must never leave one
 * behind on mobile.
 */
.back-to-top:focus {
    outline: none;
}

.back-to-top:focus-visible {
    outline: 2px solid #2086DF;
    outline-offset: 4px;
}

.back-to-top img {
    width: 24px;
    height: 24px;
    /* arrow.svg points right — turn it upward */
    transform: rotate(-90deg);
}

@media (max-width: 600px) {
    .back-to-top {
        width: 48px;
        height: 48px;
        /* Smaller button, smaller dock gap — 48 + 8. */
        margin-left: -56px;
    }
}

@media (prefers-reduced-motion: reduce) {
    /* Animations are globally disabled above; keep the show/hide functional. */
    .back-to-top {
        transform: none;
    }

    .back-to-top.is-visible:hover,
    .back-to-top.is-visible:focus-visible,
    .back-to-top.is-visible:active {
        transform: none;
    }
}

/*
 * Floating section nav — the left half of the dock.
 *
 * Same surface, same height, and the same reveal as the back-to-top button, so
 * the pair reads as one control. .floating-dock owns the positioning.
 *
 * Injected by index.js on pages that actually have the sections it points at.
 */
.section-nav {
    /* Anchors the sliding selected pill. */
    position: relative;
    order: 1;
    flex: none;
    display: flex;
    align-items: center;
    gap: 12px;
    height: 56px;
    padding: 0 12px;
    border-radius: 9999px;
    /* Matches the back-to-top surface — opaque, no backdrop-filter. */
    background-color: #242424;
    box-shadow: 0 12px 24px rgba(0, 0, 0, 0.3);

    /* Hidden resting state — the visible state is .section-nav.is-visible. */
    opacity: 0;
    transform: scale(0.8);
    pointer-events: none;
    transition: opacity 0.2s ease-in,
                transform 0.2s ease-in;
    transition-delay: 0s;
}

.section-nav.is-visible {
    opacity: 1;
    transform: scale(1);
    pointer-events: auto;
    /* Pop in with a touch of overshoot, in step with the back-to-top button. */
    transition: opacity 0.2s ease-out,
                transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
    transition-delay: 0.45s;
}

.section-nav button {
    /* Above the sliding pill, which sits at the bar's base layer. */
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    padding: 0;
    border: none;
    border-radius: 9999px;
    background-color: transparent;
    cursor: pointer;
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
    transition: transform 0.2s ease-in-out, background-color 0.2s ease-in-out;
}

/*
 * Hover, on pointing devices only.
 *
 * Gated behind (hover: hover) because touch browsers leave :hover stuck on the
 * last thing tapped. That left a second, motionless mark sitting on the icon
 * you last pressed — which is usually the current one — competing with the pill
 * that actually tracks the section.
 *
 * Darker rather than lighter: the icon presses into the bar instead of lifting
 * off it, which reads as a different kind of thing from the selected pill.
 * Translucent so the pill still shows through when it slides underneath.
 */
@media (hover: hover) {
    .section-nav button:hover {
        background-color: rgba(0, 0, 0, 0.25);
        transform: scale(1.08) rotate(-1deg);
    }
}

/* Keyboard focus gets the same treatment, on every kind of device. */
.section-nav button:focus-visible {
    background-color: rgba(0, 0, 0, 0.25);
    transform: scale(1.08) rotate(-1deg);
}

/*
 * Selected state — the section the reader is currently in.
 *
 * The tint isn't painted on the button itself: it's a single pill that slides
 * between them (see .section-nav-indicator), so moving from one section to the
 * next reads as one mark travelling rather than two lights blinking. The button
 * only carries the class so the JS and assistive tech agree on which is which.
 */

/*
 * The sliding selected pill.
 *
 * One element that travels between the icons instead of a tint switching off
 * one button and on the next, so a section change reads as a single mark moving
 * along the bar. JS sets its size and translateX from whichever button is
 * current; everything else lives here.
 *
 * It sits behind the buttons (they carry z-index: 1) and never takes a click.
 * The global prefers-reduced-motion rule kills the transition, leaving the pill
 * to jump straight to its new spot.
 */
.section-nav-indicator {
    position: absolute;
    top: 50%;
    left: 0;
    /* Sized in JS to match the current button; centered on the bar's midline. */
    margin-top: -22px;
    width: 44px;
    height: 44px;
    border-radius: 9999px;
    background-color: #2086DF2E;
    pointer-events: none;
    opacity: 0;
    transition: transform 0.35s cubic-bezier(0.34, 1.4, 0.64, 1),
                opacity 0.2s ease-out;
}

/*
 * Only animate once the pill has been placed. Without this it would slide in
 * from the left edge of the bar the first time the nav appears.
 */
.section-nav-indicator:not(.is-placed) {
    transition: none;
}

.section-nav-indicator.is-placed {
    opacity: 1;
}

/* Press state follows the house convention: subtle scale, blue wash. */
.section-nav button:active {
    background-color: #2086DF15;
    transform: scale(0.97);
    transition-duration: 0.1s;
}

.section-nav button:focus {
    outline: none;
}

.section-nav button:focus-visible {
    outline: 2px solid #2086DF;
    outline-offset: 2px;
}

.section-nav img {
    display: block;
    width: 22px;
    height: 22px;
}

@media (max-width: 600px) {
    .section-nav {
        height: 52px;
        /* Still tighter than desktop, but the icons get room to breathe. */
        gap: 6px;
        padding: 0 8px;
    }

    .section-nav button {
        width: 44px;
        height: 44px;
    }

    .section-nav img {
        width: 22px;
        height: 22px;
    }

    .section-nav-indicator {
        margin-top: -22px;
        width: 44px;
        height: 44px;
    }
}

/*
 * The very narrowest phones, and the 320px minimum the site declares.
 *
 * Five icons at the larger size plus the back-to-top button overrun the screen
 * here, so this stays at the smaller scale. Everything from 360px up — which is
 * every current phone — gets the roomier bar above.
 */
@media (max-width: 359px) {
    .section-nav {
        height: 48px;
    }

    .section-nav button {
        width: 40px;
        height: 40px;
    }

    .section-nav img {
        width: 20px;
        height: 20px;
    }

    .section-nav-indicator {
        margin-top: -20px;
        width: 40px;
        height: 40px;
    }
}

@media (prefers-reduced-motion: reduce) {
    /* Animations are globally disabled above; keep the show/hide functional. */
    .section-nav,
    .section-nav button:hover,
    .section-nav button:focus-visible,
    .section-nav button:active {
        transform: none;
    }
}

/*
 * `display: flex` on these two outranks the UA's [hidden] rule, so the JS
 * `hidden` flag needs backing up in CSS to actually take them out of layout
 * (and out of the accessibility tree) on pages too short to scroll.
 */
.back-to-top[hidden],
.section-nav[hidden] {
    display: none;
}

/*
 * The floating dock — one centered row holding the section nav and the
 * back-to-top button.
 *
 * Both used to be positioned independently against the viewport edges. Grouping
 * them means the pair centers as a unit, and the button always sits flush
 * against the right end of the bar no matter how many icons the bar carries.
 *
 * Plain fixed positioning — let the browser glue this to the visual viewport
 * itself. Compensating in JS from VisualViewport fought the browser and
 * double-shifted the dock while the mobile toolbar animated. env() clears the
 * iOS home indicator.
 *
 * Centered without a translate, so transform stays free for the children's
 * reveal animations.
 */
.floating-dock {
    position: fixed;
    left: 0;
    right: 0;
    margin: 0 auto;
    width: fit-content;
    max-width: calc(100vw - 32px);
    bottom: calc(28px + env(safe-area-inset-bottom, 0px));
    z-index: 200;
    display: flex;
    align-items: center;
    gap: 12px;
    /*
     * The dock is only a layout wrapper: it must never swallow clicks meant for
     * the page behind it. Its children opt back in when they become visible.
     */
    pointer-events: none;
}

@media (max-width: 600px) {
    .floating-dock {
        bottom: calc(20px + env(safe-area-inset-bottom, 0px));
        /* Same reason as the nav's tighter mobile gap — 320px has to fit. */
        max-width: calc(100vw - 16px);
        gap: 8px;
    }
}


/*
 * "Leaving so soon?" dialogue.
 *
 * Any link that points off this site opens this first, so an outbound click is
 * a decision rather than an accident. Injected by index.js, so every page —
 * home, case studies, support — picks it up without markup of its own.
 *
 * The card borrows the case-study surface: same #1f1f1f, same tilt, same
 * slideInFromBottom entrance, so it reads as a piece of this site rather than
 * a browser alert.
 */
.exit-dialogue {
    position: fixed;
    inset: 0;
    /* Above the floating dock (200), below the skip link (9999). */
    z-index: 500;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
}

.exit-dialogue[hidden] {
    display: none;
}

.exit-dialogue-backdrop {
    position: absolute;
    inset: 0;
    /*
     * Flat colour, no backdrop-filter — same reasoning as the floating dock: a
     * blurred fixed layer is expensive for mobile browsers to rasterize.
     */
    background-color: rgba(13, 13, 13, 0.85);
    animation: exitDialogueFadeIn 0.2s ease-out;
}

@keyframes exitDialogueFadeIn {
    from { opacity: 0; }
    to   { opacity: 1; }
}

.exit-dialogue-card {
    position: relative;
    box-sizing: border-box;
    width: 100%;
    max-width: 520px;
    max-height: calc(100vh - 32px);
    overflow-y: auto;
    padding: 24px;
    border-radius: 24px;
    background-color: #1f1f1f;
    box-shadow: 0 12px 24px rgba(0, 0, 0, 0.15);
    display: flex;
    flex-direction: column;
    gap: 16px;
    /*
     * The site's card tilt. It's also the animation's resting state, so the
     * card still lands here when prefers-reduced-motion turns the animation off.
     */
    transform: scale(1.02) rotate(-1deg);
    animation: slideInFromBottom 0.3s ease-out forwards;
}

/*
 * The card takes focus on a tap so the tab order and the screen reader cursor
 * move into the dialogue. It isn't a control, so it shouldn't draw a ring.
 */
.exit-dialogue-card:focus,
.exit-dialogue-card:focus-visible {
    outline: none;
}

/* Dismissal — mirrors the case-study exit on the way back home. */
.exit-dialogue.is-closing .exit-dialogue-card {
    animation: slideOutToBottom 0.3s ease-in forwards;
    pointer-events: none;
}

.exit-dialogue.is-closing .exit-dialogue-backdrop {
    animation: exitDialogueFadeOut 0.3s ease-in forwards;
}

@keyframes exitDialogueFadeOut {
    from { opacity: 1; }
    to   { opacity: 0; }
}

.exit-dialogue-title {
    font-weight: 500;
    font-size: 32px;
    line-height: 125%;
    color: #ffffff;
    margin: 0;
}

.exit-dialogue-body {
    font-size: 20px;
    line-height: 150%;
    color: #808080;
    margin: 0;
}

/* Mirrors .card-chip: the destination, stated plainly, under the joke. */
.exit-dialogue-destination {
    align-self: flex-start;
    max-width: 100%;
    background-color: #0D0D0D;
    color: #808080;
    font-size: 16px;
    font-weight: 350;
    line-height: 1.4;
    padding: 8px 14px;
    border-radius: 9999px;
    border: 1px solid rgba(255, 255, 255, 0.08);
    overflow-wrap: anywhere;
}

.exit-dialogue-destination .exit-dialogue-host {
    color: #ffffff;
}

/* The two actions reuse .contact-links / .contact-button for layout and hover. */
/*
 * Stacked at every width rather than side by side. Two 24px buttons don't fit
 * across a 520px card, and dropping them to 20px would put #2086DF under the
 * 4.5:1 contrast floor that applies below 24px.
 */
.exit-dialogue .contact-links {
    flex-direction: column;
    margin-top: 8px;
}

.exit-dialogue .contact-button {
    text-decoration: none;
    /* An <a> inherits the site's font; a <button> doesn't. */
    font-family: 'epilogue', sans-serif;
    border: none;
    cursor: pointer;
}

/*
 * Stacked, the arrow's padding would make the leave button 4px taller than the
 * one under it. Trim it to the text's own height so the pair matches.
 */
.exit-dialogue .contact-button .button-arrow {
    width: 1em;
    height: 1em;
    padding: 0;
    align-self: center;
}

/* Leaving is what they asked for, so it keeps the primary treatment. */
#exit-dialogue-go {
    color: #2086DF;
    background-color: #2086DF15;
    font-weight: 325;
}

/* Staying is the quieter option — #808080 would fail contrast at this size. */
#exit-dialogue-stay {
    color: #A6A6A6;
    background-color: rgba(255, 255, 255, 0.06);
    font-weight: 325;
}

@media (max-width: 600px) {
    .exit-dialogue-card {
        padding: 20px;
        gap: 12px;
    }

    .exit-dialogue-title {
        font-size: 28px;
    }

    .exit-dialogue-body {
        font-size: 18px;
    }
}
