html {
    scroll-behavior: smooth;
    scroll-padding-top: 96px;
    scrollbar-gutter: stable;
}

@media (prefers-reduced-motion: reduce) {
    html {
        scroll-behavior: auto;
    }
}

body {
    background-color: #0A0A0B;
    color: #e4e2e4;
    overflow-x: hidden;
}

.icon {
    display: inline-block;
    flex: none;
    width: 1em;
    height: 1em;
}

.glass-card {
    backdrop-filter: blur(20px);
    background: rgba(255, 255, 255, 0.03);
    border: 1px solid rgba(145, 144, 148, 0.1);
}

.iridescent-border {
    position: relative;
}

.iridescent-border::after {
    content: "";
    position: absolute;
    inset: -1px;
    background: linear-gradient(45deg, #3b5bdb, #c8c6c7, #b9c6ff, #313031);
    z-index: -1;
    opacity: 0.2;
    mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    mask-composite: exclude;
    -webkit-mask-composite: destination-out;
}

.shimmer-hover:hover .shimmer-layer {
    transform: translateX(100%);
    transition: transform 0.8s ease-in-out;
}

.prompt-glow {
    box-shadow: 0 0 40px rgba(59, 91, 219, 0.1);
}

.skill-logo {
    display: inline-block;
    flex: none;
    width: 1.25rem;
    height: 1.25rem;
    background-color: currentColor;
    -webkit-mask: var(--logo) center / contain no-repeat;
    mask: var(--logo) center / contain no-repeat;
    transition: background-color 0.3s;
}

.group:hover .skill-logo {
    background-color: #3b5bdb;
}

.brand-glyph {
    display: inline-block;
    flex: none;
    width: 1.25rem;
    height: 1.25rem;
    transition: color 0.3s;
}

.group:hover .brand-glyph {
    color: #3b5bdb;
}

.blueprint-grid-fine {
    background-image:
        linear-gradient(to right, rgba(145, 144, 148, 0.09) 1px, transparent 1px),
        linear-gradient(to bottom, rgba(145, 144, 148, 0.09) 1px, transparent 1px);
    background-size: 12px 12px;
}

/* Hero visual (specimen + blueprint) behaves as ONE object.
   Three container-query tiers driven by #hero's inline size.
   Design width = 678px (220 specimen + 458 panel overlap).
   Min scale ~0.83 keeps marks legible at full size. */
#hero {
    container-type: inline-size;
}

.hero-visual {
    display: none;
    position: absolute;
    top: 50%;
    right: 32px;
    z-index: 20;
    width: 678px;
    height: 480px;
    pointer-events: none;
    translate: 0 -50%;
    transform-origin: right center;
    scale: clamp(0.83, (100cqw - 660px) / 678px, 1);
}

#hero .hero-circley {
    display: none;
}

/* Show visual when it can scale to ≥0.83 */
@container (min-width: 1225px) {
    .hero-visual {
        display: block;
    }
}

/* Show circley instead when full object can't fit */
@container (max-width: 1224px) {
    #hero .hero-circley {
        display: flex;
    }
}

.glass-blue {
    position: relative;
    background:
        radial-gradient(125% 90% at 0% 0%, rgba(232, 238, 255, 0.50) 0%, rgba(188, 204, 240, 0.18) 24%, rgba(188, 204, 240, 0) 52%),
        linear-gradient(180deg, rgba(198, 210, 238, 0.11) 0%, rgba(118, 133, 172, 0.05) 34%, rgba(6, 10, 20, 0.40) 100%),
        rgba(255, 255, 255, 0.02);
    backdrop-filter: blur(18px) saturate(120%);
    -webkit-backdrop-filter: blur(18px) saturate(120%);
    border: 1px solid rgba(208, 220, 255, 0.28);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.45),
        inset 1px 1px 0 rgba(255, 255, 255, 0.30),
        0 30px 60px rgba(0, 0, 0, 0.55);
}

.sheen-tl {
    background-image: radial-gradient(circle 90px at 0% 0%, rgba(232, 238, 255, 0.14) 0%, rgba(188, 204, 240, 0.04) 45%, rgba(188, 204, 240, 0) 100%);
    background-clip: padding-box;
}

.sheen-edge {
    position: relative;
}

.sheen-edge::before {
    content: "";
    position: absolute;
    top: -1px;
    left: -1px;
    right: 0;
    height: 1px;
    background: linear-gradient(90deg, rgba(255, 255, 255, 0.55) 0%, rgba(255, 255, 255, 0.12) 30%, rgba(255, 255, 255, 0) 65%);
    pointer-events: none;
}

.sheen-edge::after {
    content: "";
    position: absolute;
    top: -1px;
    left: -1px;
    bottom: 0;
    width: 1px;
    background: linear-gradient(180deg, rgba(255, 255, 255, 0.55) 0%, rgba(255, 255, 255, 0.12) 30%, rgba(255, 255, 255, 0) 65%);
    pointer-events: none;
}

.text-flow {
    background-size: 220% 100%;
    animation: text-flow 8s ease-in-out infinite alternate;
}

@keyframes text-flow {
    from {
        background-position: 0% 50%;
    }

    to {
        background-position: 100% 50%;
    }
}

@media (prefers-reduced-motion: reduce) {
    .text-flow {
        animation: none;
    }
}

.circley {
    width: 220px;
    height: 220px;
    border-radius: 100vmax;
    display: flex;
    align-items: center;
    justify-content: center;
}

.logoist {
    position: absolute;
    width: 150px;
    height: 150px;
    background: url("../images/avatar.webp") center / cover no-repeat;
    border-radius: 100vmax;
    box-shadow: 0 0 0 1px rgba(59, 91, 219, 0.35);
}

.texti {
    position: absolute;
    width: 100%;
    height: 100%;
    font-family: "Space Mono", monospace;
    color: #c8c6c7;
    font-size: 13px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    animation: textRotation 14s linear infinite;
}

@keyframes textRotation {
    to {
        transform: rotate(360deg);
    }
}

.texti span {
    position: absolute;
    left: 50%;
    font-size: 1.2em;
    transform-origin: 0 110px;
}

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

#indie-track.rubberband-next {
    animation: rubberband-next 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
}

#indie-track.rubberband-prev {
    animation: rubberband-prev 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
}

@keyframes rubberband-next {
    0% {
        transform: translateX(0);
    }

    35% {
        transform: translateX(-28px);
    }

    65% {
        transform: translateX(8px);
    }

    100% {
        transform: translateX(0);
    }
}

@keyframes rubberband-prev {
    0% {
        transform: translateX(0);
    }

    35% {
        transform: translateX(28px);
    }

    65% {
        transform: translateX(-8px);
    }

    100% {
        transform: translateX(0);
    }
}

@media (prefers-reduced-motion: reduce) {

    #indie-track.rubberband-next,
    #indie-track.rubberband-prev {
        animation: none;
    }
}

.works-modal__input {
    position: fixed;
    top: 0;
    left: 0;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

.works-modal__overlay {
    position: fixed;
    inset: 0;
    z-index: 200;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    visibility: hidden;
    pointer-events: none;
    transition: visibility 0s linear 0.25s;
}

/* Modal cards sit over a solid backdrop, so the glass blur buys nothing
   visually but forces a backdrop-filter compositing layer inside the
   animated panel — the source of the cursor-driven sheen banding glitch.
   Solid fill keeps the exact same look without the artifact. */
.works-modal__column .glass-card {
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    background-color: #141416;
}

.works-modal__input:checked + .works-modal__overlay {
    visibility: visible;
    pointer-events: auto;
    transition: visibility 0s linear 0s;
}

.works-modal__backdrop {
    position: absolute;
    inset: 0;
    cursor: default;
    background: #0A0A0B;
    opacity: 0;
    transition: opacity 200ms cubic-bezier(0.4, 0, 1, 1);
}

.works-modal__input:checked + .works-modal__overlay .works-modal__backdrop {
    opacity: 1;
    transition: opacity 240ms cubic-bezier(0.16, 1, 0.3, 1);
}

.works-modal__panel {
    position: relative;
    width: min(1120px, 100%);
    max-height: 90vh;
    overflow-y: auto;
    overflow-x: hidden;
    scrollbar-width: none;
    -ms-overflow-style: none;
    opacity: 0;
    transform: translateY(8px) scale(0.96);
    transform-origin: center center;
    will-change: opacity, transform;
    transition:
        opacity 180ms cubic-bezier(0.4, 0, 1, 1),
        transform 180ms cubic-bezier(0.4, 0, 1, 1);
}

.works-modal__panel::-webkit-scrollbar {
    display: none;
}

.works-modal__input:checked + .works-modal__overlay .works-modal__panel {
    opacity: 1;
    transform: translateY(0) scale(1);
    transition:
        opacity 240ms cubic-bezier(0.16, 1, 0.3, 1),
        transform 240ms cubic-bezier(0.16, 1, 0.3, 1);
}

@media (min-width: 768px) {
    /* Room for the detached X (-48px) plus viewport clearance; panel stays unclipped. */
    .works-modal__overlay {
        padding: 72px;
    }

    /* Panel must not clip the outside close button; inner media handles its own image clipping. */
    .works-modal__panel {
        overflow: visible;
    }
}

/* Subtle inner stagger: panel moves as a unit, content follows with 60ms offset. */
.works-modal__media,
.works-modal__column {
    opacity: 0;
    transform: translateY(10px);
    transition:
        opacity 180ms ease,
        transform 180ms ease;
}

.works-modal__input:checked + .works-modal__overlay .works-modal__media {
    opacity: 1;
    transform: translateY(0);
    transition:
        opacity 260ms cubic-bezier(0.16, 1, 0.3, 1) 40ms,
        transform 260ms cubic-bezier(0.16, 1, 0.3, 1) 40ms;
}

.works-modal__input:checked + .works-modal__overlay .works-modal__column {
    opacity: 1;
    transform: translateY(0);
    transition:
        opacity 260ms cubic-bezier(0.16, 1, 0.3, 1) 100ms,
        transform 260ms cubic-bezier(0.16, 1, 0.3, 1) 100ms;
}

.works-modal__close {
    position: absolute;
    top: -64px;
    right: 0;
    z-index: 2;
    display: none;
    align-items: center;
    justify-content: center;
    padding: 12px 20px;
    border-radius: 0;
    border: 1px solid rgba(145, 144, 148, 0.35);
    background: rgba(255, 255, 255, 0.05);
    color: #c8c6c7;
    font-family: "Space Mono", monospace;
    font-size: 11px;
    line-height: 16px;
    letter-spacing: 0.15em;
    font-weight: 700;
    cursor: pointer;
    opacity: 0;
    transition:
        opacity 0.25s ease,
        color 0.3s,
        border-color 0.3s,
        background-color 0.3s;
}

.works-modal__input:checked + .works-modal__overlay .works-modal__close {
    opacity: 1;
    transition:
        opacity 200ms ease 120ms,
        color 0.3s,
        border-color 0.3s,
        background-color 0.3s;
}

.works-modal__close:hover {
    color: #3b5bdb;
    border-color: rgba(59, 91, 219, 0.5);
    background: rgba(5, 9, 28, 0.4);
}

/* Mobile: in-flow CLOSE bar-button, top-left. X-circle stays desktop-only. */
.works-modal__close-mobile {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    align-self: flex-start;
    margin-bottom: 24px;
    padding: 12px 20px;
    border: 1px solid rgba(145, 144, 148, 0.35);
    border-radius: 0;
    background: rgba(255, 255, 255, 0.05);
    color: #c8c6c7;
    font-family: "Space Mono", monospace;
    font-size: 11px;
    line-height: 16px;
    letter-spacing: 0.15em;
    font-weight: 700;
    cursor: pointer;
    opacity: 0;
    transition:
        opacity 0.25s ease,
        color 0.3s,
        border-color 0.3s,
        background-color 0.3s;
}

.works-modal__input:checked + .works-modal__overlay .works-modal__close-mobile {
    opacity: 1;
    transition:
        opacity 200ms ease 120ms,
        color 0.3s,
        border-color 0.3s,
        background-color 0.3s;
}

.works-modal__close-mobile:hover {
    color: #3b5bdb;
    border-color: rgba(59, 91, 219, 0.5);
    background: rgba(5, 9, 28, 0.4);
}

@media (min-width: 768px) {
    .works-modal__close {
        display: flex;
    }

    .works-modal__close-mobile {
        display: none;
    }
}

/* Emails modal: 4-up image gallery with mirrored prev/next controls.
   The bordered box hugs the active image (width derived from its aspect
   ratio) so no letterbox bars appear; the description cards flex to fill
   the remaining space and resize as the box changes. Images crossfade with
   the same curve as the modal's own entry animation. */
.mail-gallery {
    transition: width 260ms cubic-bezier(0.16, 1, 0.3, 1);
}

.mail-gallery__stage {
    position: relative;
    overflow: hidden;
    transition:
        width 260ms cubic-bezier(0.16, 1, 0.3, 1),
        height 260ms cubic-bezier(0.16, 1, 0.3, 1);
}

.mail-gallery.is-instant,
.mail-gallery__stage.is-instant,
.mail-gallery__stage.is-instant .mail-gallery__img {
    transition: none;
}

.mail-gallery__img {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    opacity: 0;
    transform: translateY(10px);
    pointer-events: none;
    transition:
        opacity 180ms cubic-bezier(0.4, 0, 1, 1),
        transform 180ms cubic-bezier(0.4, 0, 1, 1);
}

.mail-gallery__img.is-active {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
    transition:
        opacity 260ms cubic-bezier(0.16, 1, 0.3, 1) 40ms,
        transform 260ms cubic-bezier(0.16, 1, 0.3, 1) 40ms;
}

.mail-gallery__nav {
    position: static;
    z-index: 3;
    display: flex;
    gap: 8px;
}

.mail-gallery__nav-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 12px;
    border: 1px solid rgba(145, 144, 148, 0.35);
    border-radius: 0;
    background: rgba(10, 10, 11, 0.6);
    color: #c8c6c7;
    cursor: pointer;
    transition:
        color 0.3s,
        border-color 0.3s,
        background-color 0.3s;
}

.mail-gallery__nav-button:hover {
    color: #3b5bdb;
    border-color: rgba(59, 91, 219, 0.5);
    background: rgba(5, 9, 28, 0.6);
}

@media (min-width: 768px) {
    /* Mirrors .works-modal__close, detached above the cards' top-left. */
    .mail-gallery__nav {
        position: absolute;
        top: -64px;
        left: 0;
    }

    .mail-gallery__nav-button {
        background: rgba(255, 255, 255, 0.05);
    }
}

html {
    transition-property: overflow;
    transition-duration: 0s;
    transition-delay: 0.25s;
    transition-behavior: allow-discrete;
}

html:has(.works-modal__input:checked) {
    overflow: hidden;
    transition-delay: 0s;
}

/* Contact form: off-screen post target, so the page never redirects to JotForm. */
.jotform-target-frame {
    position: absolute;
    width: 0;
    height: 0;
    border: 0;
    visibility: hidden;
}

/* Self-dismissing confirmation shown when JotForm answers the hidden post. */
.form-toast {
    position: fixed;
    left: 50%;
    bottom: 120px;
    z-index: 300;
    width: min(420px, calc(100vw - 48px));
    padding: 16px 20px;
    cursor: pointer;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transform: translate(-50%, 16px);
    transition:
        opacity 240ms cubic-bezier(0.16, 1, 0.3, 1),
        transform 240ms cubic-bezier(0.16, 1, 0.3, 1),
        visibility 0s linear 240ms;
}

.form-toast.is-visible {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transform: translate(-50%, 0);
    transition:
        opacity 240ms cubic-bezier(0.16, 1, 0.3, 1),
        transform 240ms cubic-bezier(0.16, 1, 0.3, 1),
        visibility 0s linear 0s;
}

@media (min-width: 768px) {
    .form-toast {
        bottom: 32px;
    }
}

/* Right-click credit tooltip that trails the cursor.
   Uses the glass-card + sheen-tl + sheen-edge treatment of the
   "Brand Identity" expertise card over a translucent near-black fill. */
.cursor-tooltip {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 400;
    padding: 6px 10px;
    background-color: rgba(80, 80, 86, 0.45);
    backdrop-filter: blur(18px) saturate(140%);
    -webkit-backdrop-filter: blur(18px) saturate(140%);
    color: #c8c6c7;
    white-space: nowrap;
    pointer-events: none;
    opacity: 0;
    transition: opacity 160ms ease;
    will-change: transform, opacity;
}

.cursor-tooltip.is-visible {
    opacity: 1;
}

/* One-shot blue border sweep around the contact form, shown with the toast.
   Technique adapted from the conic `--angle` border in animations.html. */
@property --contact-border-angle {
    syntax: "<angle>";
    initial-value: 90deg;
    inherits: true;
}

.form-border-pulse {
    position: absolute;
    inset: -1px;
    z-index: 1;
    pointer-events: none;
    border: 1px solid transparent;
    border-image: conic-gradient(from var(--contact-border-angle),
            rgba(59, 91, 219, 0),
            #3b5bdb 0.1turn,
            #3b5bdb 0.15turn,
            rgba(59, 91, 219, 0) 0.25turn) 1;
    opacity: 0;
}

/* The span is the form's first child, so space-y-6 leaves it margin-free.
   Plays once: the blue segment sweeps a full lap while it fades in and out. */
.form-border-pulse.is-visible {
    animation: contact-border-sweep 1600ms linear 1 both;
}

@keyframes contact-border-sweep {
    0% {
        --contact-border-angle: 90deg;
        opacity: 0;
    }

    10% {
        opacity: 1;
    }

    75% {
        opacity: 1;
    }

    100% {
        --contact-border-angle: 450deg;
        opacity: 0;
    }
}

@media (prefers-reduced-motion: reduce) {
    html,
    .works-modal__backdrop,
    .works-modal__panel,
    .works-modal__media,
    .works-modal__column,
    .works-modal__close,
    .works-modal__close-mobile,
    .works-modal__input:checked + .works-modal__overlay .works-modal__backdrop,
    .works-modal__input:checked + .works-modal__overlay .works-modal__panel,
    .works-modal__input:checked + .works-modal__overlay .works-modal__media,
    .works-modal__input:checked + .works-modal__overlay .works-modal__column,
    .works-modal__input:checked + .works-modal__overlay .works-modal__close,
    .works-modal__input:checked + .works-modal__overlay .works-modal__close-mobile {
        transition: none;
    }

    .mail-gallery,
    .mail-gallery__stage,
    .mail-gallery__img,
    .mail-gallery__img.is-active,
    .mail-gallery__nav-button,
    .form-toast,
    .form-border-pulse {
        transition: none;
    }

    .cursor-tooltip {
        transition: none;
    }

    .form-border-pulse.is-visible {
        animation: none;
    }
}
