/* ==========================================================================
   portfolio.css — portfolio.html only
   Header, section grids, media cards, lightbox, back-to-top.
   ========================================================================== */

/* The portfolio runs blue where the homepage runs crimson, and flips to
   crimson on hover for video cards. Overriding --accent-rgb re-themes every
   glow, border and shadow inherited from base.css. */
:root {
    --accent-rgb: 19, 70, 220;
    --accent-hover-rgb: 220, 20, 60;
    --accent-hover: rgb(var(--accent-hover-rgb));
    --accent-hover-glow: rgba(var(--accent-hover-rgb), 0.45);

    /* The blue counterpart to base.css's crimson atmosphere. Same three roles
       — mass, shadow, highlight — so the aurora layers need no page-specific
       rules; only the pigment changes. */
    --glow-1: 22, 58, 186;    /* deep sapphire — primary mass */
    --glow-2: 10, 26, 108;    /* navy — the shadow side of the glow */
    --glow-3: 48, 100, 232;   /* lifted blue — the highlight that drifts */

    --radius-card: 10px;
}

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

.page-title,
.section-title,
.subsection-title {
    font-family: var(--font-display);
    text-transform: uppercase;
}

/* Every clickable surface on this page is a real <button> so it's keyboard
   reachable and announced correctly. These reset the UA chrome that would
   otherwise fight the card styling (notably -webkit-appearance in Safari). */
.graphic-card,
.video-frame-wrap,
.lightbox-close,
.lightbox-nav,
.back-to-top {
    appearance: none;
    -webkit-appearance: none;
    font: inherit;
}

.page {
    position: relative;
    z-index: 1;
    width: 100%;
    max-width: 1100px;
    margin: 0 auto;
    padding: 40px 20px 60px;
    padding-left: max(20px, env(safe-area-inset-left));
    padding-right: max(20px, env(safe-area-inset-right));
}

/* --------------------------------------------------------------------------
   Header
   -------------------------------------------------------------------------- */

.site-header {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    margin-bottom: 46px;
    text-align: center;
}

.home-logo-link {
    position: relative;
    display: inline-block;
    filter:
        drop-shadow(0 0 16px rgba(255, 255, 255, 0.06))
        drop-shadow(0 0 28px var(--accent-glow));
    animation: fadeInUp 0.5s var(--ease) both;
    transition:
        transform var(--speed) var(--ease),
        filter var(--speed) var(--ease);
}

.home-logo-link:hover {
    transform: translateY(-2px);
    filter:
        drop-shadow(0 0 20px rgba(255, 255, 255, 0.1))
        drop-shadow(0 0 34px var(--accent-glow));
}

.home-logo-link img {
    display: block;
    width: min(440px, 97vw);
    height: auto;
    pointer-events: none;
}

.page-title {
    margin: 6px 0 0;
    font-size: clamp(22px, 5vw, 32px);
    letter-spacing: 3px;
    text-shadow: 0 0 18px var(--accent-glow);
    animation: fadeInUp 0.5s var(--ease) 0.1s both;
}

.tagline {
    margin: 4px 0 0;
    font-size: clamp(11px, 3vw, 14px);
    letter-spacing: 2px;
    color: var(--fg-dim);
    animation: fadeInUp 0.5s var(--ease) 0.2s both;
}

.headshot {
    width: 220px;
    height: 220px;
    margin: 28px 0 12px;
    display: block;
    object-fit: cover;
    border-radius: 24px;
    box-shadow: 0 0 0 1px #fff;
    animation: fadeInUp 0.5s var(--ease) 0.3s both;
}

.disclaimer {
    max-width: 720px;
    margin: 6px auto 0;
    font-size: 11.5px;
    line-height: 1.7;
    letter-spacing: 0.5px;
    color: #ffffff;
    text-align: center;
    animation: fadeInUp 0.5s var(--ease) 0.4s both;
}

.disclaimer p {
    margin: 0 0 12px;
}

.disclaimer p:last-child {
    margin-bottom: 0;
}

.jump-nav {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 10px 18px;
    margin-top: 16px;
    animation: fadeInUp 0.5s var(--ease) 0.5s both;
}

.jump-nav a {
    padding: 7px 14px;
    font-size: 11px;
    letter-spacing: 1.5px;
    color: var(--fg-dim);
    text-decoration: none;
    background: var(--surface);
    border: 1px solid var(--line-soft);
    border-radius: 999px;
    transition:
        color 0.35s var(--ease),
        border-color 0.35s var(--ease),
        background 0.35s var(--ease),
        box-shadow 0.35s var(--ease);
}

/* .active is set by the scrollspy in portfolio.js */
.jump-nav a:hover,
.jump-nav a.active {
    color: var(--fg);
    background: var(--surface-hover);
    border-color: var(--accent);
    box-shadow: 0 0 14px rgba(var(--accent-rgb), 0.25);
}

/* The space above this used to be 14px from three separate sources stacked:
   .site-header's 8px flex gap, 4px of margin-bottom on the logo, and 2px of
   margin-top here. Flex gap does not collapse with margins the way ordinary
   block margins do — they add — so the two margins are gone and the gap alone
   sets the distance. Change .site-header's gap to move it further. */
.back-link {
    margin-bottom: 2px;
    font-size: 12px;
    letter-spacing: 2px;
    color: var(--fg-dim);
    text-decoration: none;
    border-bottom: 1px solid transparent;
    animation: fadeInUp 0.5s var(--ease) 0.6s both;
    transition:
        color var(--speed-fast) ease,
        border-color var(--speed-fast) ease;
}

.back-link:hover,
.back-link:active {
    color: var(--accent);
    border-bottom-color: var(--accent);
}

/* --------------------------------------------------------------------------
   Section scaffolding
   -------------------------------------------------------------------------- */

.section {
    margin-bottom: 68px;
    scroll-margin-top: 20px;
}

.section-title {
    display: flex;
    align-items: center;
    gap: 14px;
    margin-bottom: 6px;
    font-size: clamp(15px, 3.5vw, 18px);
    letter-spacing: 3px;
    color: var(--fg);
    animation: fadeInUp 0.5s var(--ease) both;
}

.section-title::before {
    content: "//";
    color: var(--accent);
    text-shadow: 0 0 10px var(--accent-glow);
}

.section-title::after {
    content: "";
    flex: 1;
    height: 1px;
    background: linear-gradient(90deg, rgba(var(--accent-rgb), 0.4), rgba(255, 255, 255, 0.04));
}

.section-sub {
    margin: 0 0 22px;
    font-size: 11px;
    letter-spacing: 1px;
    color: var(--fg-dim);
    animation: fadeInUp 0.5s var(--ease) 0.05s both;
}

.subsection {
    margin-top: 34px;
    padding-top: 28px;
    border-top: 1px dashed var(--line);
}

.subsection-title {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 18px;
    font-size: clamp(13px, 3vw, 15px);
    letter-spacing: 2px;
    color: var(--fg-dim);
}

.subsection-title::before {
    content: ">";
    color: var(--accent);
}

.view-hint {
    margin: 16px 0 0;
    font-size: 11px;
    letter-spacing: 1.5px;
    color: #ffffff;
    text-align: center;
    opacity: 0.7;
}

/* Replaces the inline margin-top that used to sit on a few grids */
.spaced {
    margin-top: 22px;
}

/* --------------------------------------------------------------------------
   Video cards
   -------------------------------------------------------------------------- */

/* Cards pack from the left. A short final row now sits under the first
   column rather than floating to the middle, so every card in the section
   shares one left edge with the section title above it. */
.video-grid {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-start;
    gap: 22px;
}


.video-grid.single {
    display: grid;
    grid-template-columns: 1fr;
}

/* A consistent three-column card width. Incomplete final rows stay
   left-aligned with the rows above them.

   No min-width. It used to be 280px, which fought the flex-basis instead of
   supporting it: just above each breakpoint the computed third (or half) of
   the row falls under 280px, the min-width overrides it, and the row wraps to
   one fewer card than the rule intends — a stranded narrow card at ~920px and
   again at ~601px. Centering used to disguise that; left alignment would not.
   The column count is already fully determined by the breakpoint ladder below
   (3-up above 920px, 2-up down to 601px, single column under that), so the
   floor has nothing left to protect. */
.video-grid:not(.single) .video-card {
    flex: 0 1 calc((100% - 44px) / 3);
    max-width: calc((100% - 44px) / 3);
}

.graphics-grid.compact .graphic-card,
.graphics-grid.cards-grid .graphic-card {
    flex: 0 1 340px;
    max-width: 360px;
}

/* Business-card previews are intentionally larger than the general branding
   tiles so the actual card designs are readable at a glance. */
.graphics-grid.cards-grid .graphic-card {
    width: min(100%, 360px);
}

.video-card {
    overflow: hidden;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-card);
    animation: fadeInUp 0.5s var(--ease) both;
    transition:
        border-color var(--speed) var(--ease),
        box-shadow var(--speed) var(--ease),
        transform var(--speed) var(--ease);
}

.video-card:nth-child(1) { animation-delay: 0.1s; }
.video-card:nth-child(2) { animation-delay: 0.2s; }
.video-card:nth-child(3) { animation-delay: 0.3s; }
.video-card:nth-child(4) { animation-delay: 0.4s; }
.video-card:nth-child(5) { animation-delay: 0.5s; }
.video-card:nth-child(6) { animation-delay: 0.6s; }

.video-card:hover {
    transform: translateY(-3px);
    border-color: var(--accent-hover);
    box-shadow:
        0 12px 32px rgba(0, 0, 0, 0.5),
        0 0 22px rgba(var(--accent-hover-rgb), 0.18);
}

/* A <button> so it's reachable by keyboard and announced as clickable;
   the appearance resets below make it look like the plain frame it was. */
.video-frame-wrap {
    position: relative;
    display: block;
    width: 100%;
    padding: 0;
    padding-top: 56.25%; /* 16:9 */
    background: #050505;
    border: 0;
    color: inherit;
    font: inherit;
    cursor: pointer;
}

.video-frame-wrap video {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
    background: #000;
    /* clicks belong to the wrapper, not the media element... */
    pointer-events: none;
}

/* ...except once the inline player is actually running, when the native
   controls need to receive them. */
.video-frame-wrap.is-playing {
    cursor: default;
}

.video-frame-wrap.is-playing video {
    pointer-events: auto;
}

/* Bottom scrim so the play button and native controls stay legible over
   any poster frame. */
.video-frame-wrap::before {
    content: "";
    position: absolute;
    inset: auto 0 0 0;
    height: 42%;
    z-index: 1;
    background: linear-gradient(to top, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.35s ease;
}

.video-card:hover .video-frame-wrap::before,
.video-frame-wrap.is-playing::before {
    opacity: 1;
}

.play-overlay {
    position: absolute;
    top: 50%;
    left: 50%;
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 60px;
    height: 60px;
    transform: translate(-50%, -50%) scale(1);
    color: var(--fg);
    background: rgba(8, 8, 8, 0.6);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    border: 1px solid rgba(var(--accent-rgb), 0.75);
    border-radius: 50%;
    box-shadow:
        0 0 0 0 rgba(var(--accent-rgb), 0.25),
        0 10px 22px rgba(0, 0, 0, 0.5);
    transition:
        transform 0.3s var(--ease),
        box-shadow 0.35s ease,
        background 0.3s ease,
        border-color 0.3s ease,
        opacity var(--speed-fast) ease;
}

.play-overlay svg {
    width: 20px;
    height: 20px;
    margin-left: 3px;
    fill: currentColor;
    filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.5));
}

.video-card:hover .play-overlay {
    transform: translate(-50%, -50%) scale(1.1);
    background: rgba(8, 8, 8, 0.78);
    border-color: var(--accent-hover);
    box-shadow:
        0 0 0 9px rgba(var(--accent-hover-rgb), 0.1),
        0 12px 28px rgba(0, 0, 0, 0.55),
        0 0 22px var(--accent-hover-glow);
}

/* Once the inline player starts, hand the frame over to the native
   controls and fade the custom button out. */
.video-frame-wrap.is-playing .play-overlay {
    opacity: 0;
    transform: translate(-50%, -50%) scale(0.85);
    pointer-events: none;
}

/* Spinner shown over the poster while the video file loads */
.card-spinner {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 26px;
    height: 26px;
    margin: -13px 0 0 -13px;
    border: 2px solid rgba(232, 232, 232, 0.25);
    border-top-color: var(--accent);
    border-radius: 50%;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s ease;
    animation: spin 0.8s linear infinite;
}

.video-frame-wrap.is-loading .card-spinner {
    opacity: 1;
}

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

.video-meta {
    padding: 12px 14px 16px;
}

.v-title {
    margin: 0;
    font-size: 13px;
    letter-spacing: 1px;
    color: var(--fg);
    word-break: break-word;
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.7);
}

/* --------------------------------------------------------------------------
   Graphic cards
   -------------------------------------------------------------------------- */

.graphics-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 18px;
}

.graphics-grid.compact {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-start;
    gap: 18px;
}

.graphics-grid.cards-grid {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-start;
    gap: 18px;
}

/* Full-width, one above the other rather than side by side */
.graphics-grid.stacked {
    grid-template-columns: 1fr;
    gap: 20px;
}

.graphic-card {
    position: relative;
    display: block;
    width: 100%;
    aspect-ratio: 1 / 1;
    padding: 0;
    overflow: hidden;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-card);
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
    animation: fadeInUp 0.5s var(--ease) both;
    transition:
        border-color var(--speed) var(--ease),
        box-shadow var(--speed) var(--ease),
        transform var(--speed) var(--ease);
}

.graphic-card:nth-child(1) { animation-delay: 0.1s; }
.graphic-card:nth-child(2) { animation-delay: 0.2s; }
.graphic-card:nth-child(3) { animation-delay: 0.3s; }
.graphic-card:nth-child(4) { animation-delay: 0.4s; }
.graphic-card:nth-child(5) { animation-delay: 0.5s; }
.graphic-card:nth-child(6) { animation-delay: 0.6s; }
.graphic-card:nth-child(7) { animation-delay: 0.7s; }
.graphic-card:nth-child(8) { animation-delay: 0.8s; }

.graphic-card:hover {
    transform: translateY(-3px);
    border-color: var(--accent);
    box-shadow:
        0 12px 32px rgba(0, 0, 0, 0.5),
        0 0 22px rgba(var(--accent-rgb), 0.18);
}

.graphic-card img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    /* faded in by portfolio.js once the bytes actually arrive, so images
       don't pop in abruptly on a slow connection */
    opacity: 0;
    transition: opacity var(--speed) ease;
}

.graphic-card img.loaded {
    opacity: 1;
}

/* display:block matters: the label is a <span> (buttons only accept phrasing
   content), and the variants below un-position it, at which point an inline
   box would ignore its padding and text-align. */
.g-label {
    display: block;
    position: absolute;
    inset: auto 0 0 0;
    padding: 8px 10px;
    font-size: 11px;
    letter-spacing: 1px;
    color: var(--fg);
    background: linear-gradient(0deg, rgba(0, 0, 0, 0.85), rgba(0, 0, 0, 0));
    text-shadow:
        0 1px 3px rgba(0, 0, 0, 0.9),
        0 2px 10px rgba(0, 0, 0, 0.6);
}

/* --- wide: full-bleed, label floated top-right ---------------------------- */

.graphic-card.wide {
    aspect-ratio: auto;
}

.graphic-card.wide img {
    height: auto;
    max-height: 520px;
    object-fit: contain;
    background: #050505;
}

.graphic-card.wide .g-label {
    inset: 0 0 auto auto;
    max-width: 72%;
    padding: 12px 16px;
    font-size: 13px;
    background: none;
    text-align: right;
}

/* Fills the box edge to edge with no side bars, cropping the bottom instead
   so the top — where the text and logo sit — stays fully legible. */
.graphic-card.wide.fill-top {
    height: 460px;
}

.graphic-card.wide.fill-top img {
    height: 100%;
    max-height: none;
    object-fit: cover;
    object-position: top center;
}

/* --- logo: shown whole, never cropped ------------------------------------ */

.graphic-card.logo img {
    padding: 20px;
    object-fit: contain;
    background: radial-gradient(circle at 50% 42%, #101010 0%, #0a0a0a 65%, #050505 100%);
}

/* The Degen Rips mark is drawn for solid black, not the gradient above */
#degen .graphic-card.logo img {
    background: #000000;
}

/* --- card previews: label sits below the artwork ------------------------- */

.graphic-card.card-preview,
.graphic-card.banner-wide {
    aspect-ratio: auto;
}

.graphic-card.card-preview img,
.graphic-card.banner-wide img {
    height: auto;
    object-fit: contain;
}

.graphic-card.card-preview .g-label,
.graphic-card.banner-wide .g-label {
    position: static;
    padding: 10px 2px 0;
    background: none;
    text-align: center;
}

/* --- Mindy campaign: caption in its own box under the image -------------- */

#mindy .graphic-card {
    aspect-ratio: auto;
}

#mindy .graphic-card img {
    aspect-ratio: 1 / 1;
    height: auto;
}

#mindy .graphic-card .g-label {
    position: static;
    padding: 10px 8px 12px;
    background: var(--surface);
    border-top: 1px solid var(--line);
    text-align: center;
    text-shadow: none;
}

/* --------------------------------------------------------------------------
   Lightbox
   -------------------------------------------------------------------------- */

.lightbox {
    position: fixed;
    inset: 0;
    z-index: 10;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 30px;
    background: rgba(0, 0, 0, 0.92);
    opacity: 0;
    visibility: hidden;
    /* visibility is stepped rather than transitioned. Closing: hold it
       visible for the full 0.3s so the fade-out is actually seen. Opening:
       flip to visible immediately (0s delay) — transitioning it instead
       would leave the dialog computed-hidden for a frame, and a hidden
       element can't take focus, which breaks the keyboard handoff. */
    transition:
        opacity 0.3s ease,
        visibility 0s linear 0.3s;
}

.lightbox.active {
    opacity: 1;
    visibility: visible;
    transition:
        opacity 0.3s ease,
        visibility 0s linear 0s;
}

.lightbox-content {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    max-width: 100%;
    max-height: 100%;
}

.lightbox img,
.lightbox video {
    max-width: 90vw;
    max-height: 85vh;
    border: 1px solid var(--accent);
    border-radius: 4px;
    box-shadow: 0 0 40px var(--accent-glow);
    opacity: 0;
    transform: scale(0.97);
    transition:
        opacity 0.3s ease,
        transform 0.3s ease;
}

.lightbox img.loaded,
.lightbox video.loaded {
    opacity: 1;
    transform: scale(1);
}

.lightbox-close,
.lightbox-nav {
    position: fixed;
    z-index: 12;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #ffffff;
    background: rgba(0, 0, 0, 0.45);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid rgba(255, 255, 255, 0.22);
    border-radius: 50%;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.35);
    cursor: pointer;
    transition:
        background var(--speed-fast) ease,
        border-color var(--speed-fast) ease,
        transform var(--speed-fast) ease;
}

/* Fixed white throughout — hover/active only nudge the backdrop darker
   and the border brighter, never a hue change. */
.lightbox-close:hover,
.lightbox-nav:hover,
.lightbox-close:active,
.lightbox-nav:active {
    background: rgba(0, 0, 0, 0.65);
    border-color: rgba(255, 255, 255, 0.5);
}

/* The site-wide focus ring (base.css) is accent-coloured for keyboard
   nav elsewhere; these buttons get tapped constantly on mobile and a
   coloured ring flashing on every tap read as the "colored highlight."
   Override it to white here specifically. */
.lightbox-close:focus-visible,
.lightbox-nav:focus-visible {
    outline: 2px solid rgba(255, 255, 255, 0.85);
    outline-offset: 3px;
}

.lightbox-close:active {
    transform: scale(0.92);
}

.lightbox-nav:active {
    transform: translateY(-50%) scale(0.92);
}

.lightbox-close {
    top: 20px;
    right: 24px;
    width: 40px;
    height: 40px;
    font-size: 22px;
}

.lightbox-nav {
    top: 50%;
    width: 44px;
    height: 44px;
    font-size: 20px;
    transform: translateY(-50%);
}

.lightbox-prev { left: 20px; }
.lightbox-next { right: 20px; }

.lightbox-counter {
    position: fixed;
    bottom: max(20px, env(safe-area-inset-bottom));
    left: 50%;
    z-index: 12;
    transform: translateX(-50%);
    margin: 0;
    padding: 6px 14px;
    font-size: 12px;
    letter-spacing: 2px;
    color: var(--fg-dim);
    background: rgba(0, 0, 0, 0.5);
    border: 1px solid var(--line-soft);
    border-radius: 999px;
}

/* --------------------------------------------------------------------------
   Back to top
   -------------------------------------------------------------------------- */

.back-to-top {
    position: fixed;
    right: max(20px, env(safe-area-inset-right));
    bottom: max(20px, env(safe-area-inset-bottom));
    z-index: 8;
    width: 42px;
    height: 42px;
    font-size: 16px;
    color: var(--fg);
    background: var(--surface);
    border: 1px solid var(--line-soft);
    border-radius: 50%;
    cursor: pointer;
    opacity: 0;
    visibility: hidden;
    transform: translateY(8px);
    transition:
        opacity var(--speed-fast) ease,
        transform var(--speed-fast) ease,
        border-color var(--speed-fast) ease,
        box-shadow var(--speed-fast) ease;
}

.back-to-top.visible {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}

.back-to-top:hover {
    border-color: var(--accent);
    box-shadow: 0 0 14px rgba(var(--accent-rgb), 0.25);
}

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

.site-footer {
    margin-top: 8px;
    padding-top: 42px;
    border-top: 1px solid #1a1a1a;
    text-align: center;
}

.footer-contact {
    margin: 0;
    font-size: clamp(13px, 3vw, 16px);
    letter-spacing: 2.5px;
    line-height: 2;
    color: var(--accent);
    text-shadow: 0 0 20px var(--accent-glow);
}

.footer-contact a {
    padding-bottom: 1px;
    color: inherit;
    text-decoration: none;
    border-bottom: 1px solid rgba(var(--accent-rgb), 0.35);
    transition:
        border-color var(--speed) var(--ease),
        text-shadow var(--speed) var(--ease);
}

.footer-contact a:hover {
    border-bottom-color: var(--accent);
    text-shadow: 0 0 26px var(--accent-glow);
}

.copyright {
    margin: 20px 0 0;
}

.footer-image {
    margin-top: 20px;
}

/* --------------------------------------------------------------------------
   Responsive
   -------------------------------------------------------------------------- */

@media (max-width: 768px) {
    .home-logo-link img {
        width: min(275px, 72vw);
    }

    /* drop-shadow() on a near-viewport-width element can clip into a hard
       rectangular block on some mobile GPUs (same fix as the homepage
       logo). Scoped to 768px rather than phone widths because the bug
       shows up on any touch-first viewport. */
    .home-logo-link {
        filter: none;
    }

    .home-logo-link::before {
        content: "";
        position: absolute;
        inset: -18px;
        z-index: -1;
        pointer-events: none;
        background: radial-gradient(ellipse 62% 55% at 50% 50%, var(--accent-glow) 0%, rgba(var(--accent-rgb), 0) 70%);
        filter: blur(14px);
    }
}

@media (max-width: 920px) and (min-width: 601px) {
    .video-grid:not(.single) .video-card {
        flex-basis: calc((100% - 22px) / 2);
        max-width: calc((100% - 22px) / 2);
    }
}

@media (max-width: 600px) {
    .site-header {
        margin-bottom: 34px;
    }

    .disclaimer {
        padding: 0 4px;
        font-size: 12px;
        line-height: 1.65;
    }

    .jump-nav {
        gap: 8px 10px;
    }

    .jump-nav a {
        padding: 7px 12px;
        font-size: 10px;
    }

    .section {
        margin-bottom: 42px;
    }

    .subsection {
        margin-top: 26px;
        padding-top: 22px;
    }

    .video-grid,
    .graphics-grid {
        gap: 14px;
    }

    .video-grid {
        display: flex;
        flex-direction: column;
        align-items: stretch;
    }

    .video-grid:not(.single) .video-card {
        flex: 0 1 auto;
        width: 100%;
        max-width: none;
        min-width: 0;
    }

    .graphics-grid.compact,
    .graphics-grid.cards-grid {
        display: flex;
        flex-wrap: wrap;
        justify-content: flex-start;
    }

    .graphics-grid.cards-grid .graphic-card {
        width: min(100%, 360px);
        flex-basis: min(100%, 360px);
        max-width: 360px;
    }

    .play-overlay {
        width: 48px;
        height: 48px;
    }

    .play-overlay svg {
        width: 17px;
        height: 17px;
    }

    .lightbox {
        padding: 16px;
    }

    .lightbox-close {
        top: max(16px, env(safe-area-inset-top));
        right: max(16px, env(safe-area-inset-right));
    }

    .lightbox-nav {
        width: 46px;
        height: 46px;
        font-size: 18px;
    }

    .lightbox-prev { left: 10px; }
    .lightbox-next { right: 10px; }

    .lightbox-counter {
        padding: 5px 12px;
        font-size: 11px;
    }

    .back-to-top {
        width: 38px;
        height: 38px;
        font-size: 14px;
    }
}

@media (max-width: 480px) {
    .page {
        padding: 30px 14px 46px;
        padding-left: max(14px, env(safe-area-inset-left));
        padding-right: max(14px, env(safe-area-inset-right));
    }

    .headshot {
        width: 180px;
        height: 180px;
        margin: 22px 0 10px;
    }

    .graphic-card.wide.fill-top {
        height: 300px;
    }
}
