/* Research page styles — copied heading styles from timeline_style.css
   and adjusted to force a single-line title. */

/* Ensure the section heading area has a black background */
.section-timeline-heading{
    background-color: black;
}

/* Defensive: ensure the main sections and containers on the Research page
   remain dark in non-light-mode (prevent accidental white background). */
body:not(.light-mode) .section-timeline,
body:not(.light-mode) .section-timeline-heading,
body:not(.light-mode) .page-wrapper,
body:not(.light-mode) .container{
    background: #000000 !important;
    color: #e6e6e6 !important;
}

/* Container and spacing to match timeline page */
.container{
    width: 90vw;
    max-width: 1360px;
    margin-left: auto;
    margin-right: auto;
}

.padding-vertical-xlarge{
    /* Nudge the whole page content a bit closer to the fixed header */
    padding-top: 80px;
    padding-bottom: 80px;
}

.timeline-main-heading-wrapper{
    color: white;
    text-align: center;
    /* increased width so the title and paragraph have more horizontal room */
    max-width: 1100px;
    margin-left: auto;
    margin-right: auto;
    position: relative; /* allow absolute-positioned controls (theme toggle) inside */
}

/* Reserve a right gutter so heading text doesn't flow underneath the
   top-right controls when the page scrolls or when a clone is open. */
.timeline-main-heading-wrapper{ box-sizing: border-box; padding-right: 112px; }

/* Desktop-only: theme hint under the theme-toggle for Research page
   Matches the home page immersive hint styling but positioned under the
   theme button. Visible only in dark mode (body:not(.light-mode)) and
   only on desktop (min-width: 769px). Clicking or keyboard-activating
   the hint activates the main theme toggle. */
/* Ensure the hint is completely disabled in light mode (no layout or a11y impact) */
body.light-mode header nav .nav-hint-wrapper{ display: none !important; }

@media (min-width: 769px) {
    /* Anchor the hint absolutely to the nav so it doesn't affect inline layout
       and push navigation items left. This keeps nav alignment identical to
       other pages that don't include the hint element. */
    body:not(.light-mode) header nav{ position: relative; }
    body:not(.light-mode) header nav .nav-hint-wrapper{ position: absolute; display: block; }
    body:not(.light-mode) header nav .nav-hint-wrapper #theme-hint{
        position: absolute;
        top: calc(100% + 40px);
        /* anchor the hint to the right side of the header/nav area */
        right: -60vw;
        padding: 0.6rem 0.7rem;
        border-radius: 6px;
        font-size: 0.8rem;
        line-height: 1.25;
        width: 260px;
        z-index: 2000;
    /* smoother transitions for opacity/transform so hover/focus feels pleasing */
    transition: opacity 360ms cubic-bezier(0.2,0.9,0.2,1), transform 300ms cubic-bezier(0.22,0.1,0.22,1), max-height 320ms ease;
    will-change: opacity, transform;
    /* start fully transparent; animated in to 0.5 via `body.show-theme-hint` */
    opacity: 0;
    transform: translateY(-12px);
        pointer-events: auto;
        display: inline-block;
        border: 1px solid rgba(254,218,74,0.9);
        white-space: normal;
        word-break: break-word;
        overflow: hidden;
        max-height: 6.2rem;  

        /* visual match to homepage hint (dark-mode) */
        background: rgba(0,0,0,0.55);
        color: #fff;
        box-shadow: 0 6px 20px rgba(0,0,0,0.6);
    }

    body:not(.light-mode) header nav .nav-hint-wrapper #theme-hint:hover,
    body:not(.light-mode) header nav .nav-hint-wrapper #theme-hint:focus{
        /* Use !important so hover/focus overrides the animation layer and
           always brings the hint to full opacity and the hover transform. */
    opacity: 1 !important;
    box-shadow: 0 8px 28px rgba(0,0,0,0.35) !important;
        cursor: pointer;
        outline: none !important;
    }

    /* ensure keyboard focus shows same visual state */
    body:not(.light-mode) header nav .nav-hint-wrapper #theme-hint:focus{ box-shadow: 0 8px 28px rgba(0,0,0,0.35) !important; }

    /* Animation: fade down from above when the page has fully loaded.
       The page script will add `body.show-theme-hint` on window.load to
       trigger this. Keep the animation desktop-only and dark-mode-only. */
    @keyframes theme-hint-in {
        from { opacity: 0; transform: translateY(-12px); }
        to   { opacity: 0.5; transform: translateY(0); }
    }
    @keyframes theme-hint-out {
        from { opacity: 0.5; transform: translateY(0); }
        to   { opacity: 0;   transform: translateY(-12px); }
    }

    /* Play the intro animation, then after 5s play the outro animation
       so the hint fades out using pure CSS. Two animations are declared
       so the out animation starts after a 5000ms delay. */
    body.show-theme-hint:not(.light-mode) header nav .nav-hint-wrapper #theme-hint{
        animation: theme-hint-in 680ms cubic-bezier(0.22,0.1,0.22,1) 240ms both,
                   theme-hint-out 680ms cubic-bezier(0.22,0.1,0.22,1) 5000ms both;
    }

/* After the out-animation completes we mark the element hidden/inert via JS.
   Provide a defensive CSS rule so any element with the helper class is
   visually removed and non-interactive. */
header nav .nav-hint-wrapper #theme-hint.theme-hint-hidden{
    opacity: 0 !important;
    visibility: hidden !important;
    pointer-events: none !important;
}

}
/* Research page: place a small meme to the right of the intro paragraph.
   The meme wrapper stretches to match the height of the intro text column.
   Keep the meme visually small via a constrained width so it doesn't dominate. */
.research-heading-row{
    display: flex;
    gap: 1.6rem;
    align-items: stretch; /* ensure children match height */
    justify-content: center;
}
.research-intro-text{
    flex: 1 1 60%;
}
/* Intro paragraph styling (dark-mode defaults). Light mode overrides live in css/light_mode.css */
.research-intro-text .research-intro{
    color: #ffffff;
    font-size: 2.2vh;
    line-height: 1.45;
}
.research-meme{
    flex: 0 0 250px; /* slightly narrower so it sits closer to text */
    display: flex;
    align-items: center;
}
.research-meme .meme-wrapper{ /* stretch the wrapper to the full height of the text column */
    width: 100%;
    height: 100%;
    display: flex;
    align-items: flex-start; /* move meme slightly up */
    justify-content: center;
}
.research-meme .timeline-hero-image{
    height: 100%;
    width: auto;
    max-height: 360px; /* an extra safety cap so the meme stays reasonably small */
    object-fit: contain;
    transform: translateY(-8%); /* nudge image upward a bit */
}

/* Ensure the reveal button styling on Research matches Timeline in dark mode
   (use higher specificity so other page rules don't accidentally change it). */
/* Reveal button styling for research page: keep parity with timeline but
   let the shared utils.css handle the base look. Additional per-page
   adjustments can remain scoped or be removed if unnecessary. */
.research-meme #meme-wrapper .reveal-btn{ padding: 0.6rem 0.95rem; border-radius: 8px; }
.research-meme #meme-wrapper .reveal-btn:focus,
.research-meme #meme-wrapper .reveal-btn:hover{ transform: translateY(-1px); }

/* Force exact parity with the timeline reveal button in dark mode. We scope
   to non-light-mode pages so light-mode rules (in css/light_mode.css) still
   apply when the user enables light mode. */
body:not(.light-mode) .research-meme #meme-wrapper .reveal-btn,
body:not(.light-mode) #meme-wrapper .reveal-btn{
    background: rgba(255,255,255,0.06) !important;
    color: #ffffff !important;
    border: 2px solid transparent !important;
    padding: 0.6rem 1rem !important;
    border-radius: 8px !important;
    cursor: pointer !important;
    font-weight: 700 !important;
    letter-spacing: 0.02em !important;
}

body:not(.light-mode) .research-meme #meme-wrapper .reveal-btn:focus,
body:not(.light-mode) .research-meme #meme-wrapper .reveal-btn:hover,
body:not(.light-mode) #meme-wrapper .reveal-btn:focus,
body:not(.light-mode) #meme-wrapper .reveal-btn:hover{
    box-shadow: 0 0 0.2rem rgba(254, 218, 74, 0.8) !important;
    background: rgba(160, 138, 65, 0.179) !important;
    transition: transform 0.15s ease, background 0.3s ease, box-shadow 0.3s ease, border 0.15s ease !important;
}

.margin-bottom-medium{
    margin-top: -3vh; /* small upward lift so stacked elements sit closer */
    margin-bottom: 1vh; /* keep a small gap between stacked elements */
}

/* Reduce the large bottom padding under the heading for this page so the
   project cards sit closer to the subtitle. We scope to the heading section
   to avoid changing other pages that use the same utility class. */
.section-timeline-heading .padding-vertical-xlarge{
    padding-bottom: 6vh;
}

/* Exact gradient text styling copied from timeline_style.css but scoped to the
   intro heading on this page. white-space:nowrap forces one-line title. */
h2.intro-heading{
    font-size: 8vh;
    background: -webkit-linear-gradient(to right, gold, #ee0979);
    background: linear-gradient(to right, gold, #ee0979);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
    white-space: nowrap; /* force single-line */
    overflow-wrap: normal;
    display: block;
    margin-left: auto;
    margin-right: auto;
    text-align: center;
}

/* By default keep title on one line; the .break-after span will be turned
   into a block on phones to create the requested line-break after "Scientific". */
.intro-heading .break-after{ display: inline; }


/* Small responsive tweak: allow the font to shrink slightly on very narrow screens */
@media (max-width: 420px){
    h2.intro-heading{
        font-size: 6.6vh;
    }
}

/* Mobile reflow: place the meme above the intro text, then the project cards
   (meme -> text -> cards) on narrow screens. This keeps the visual focus
   on the image when users scroll on phones. */
@media (max-width: 768px){
    .research-heading-row{
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 1rem;
    }

    /* Move meme to the top of the column */
    .research-meme{ order: -1; flex: 0 0 auto; width: 100%; max-width: 420px; }
    .research-meme .meme-wrapper{ width: 100%; height: auto; display: flex; justify-content: center; }

/* Tablet / small-desktop: slightly reduce font sizes and image height so
   content fits comfortably on viewports up to 780px wide. This keeps the
   layout readable on small laptops and large tablets. */
@media (max-width: 780px){
    /* Slightly smaller heading */
    h2.intro-heading{ font-size: 6.6vh !important; }

    /* Project card typography tweaks */
    .project-title{ font-size: 2.0vh !important; }
    .project-subtitle{ font-size: 1.6vh !important; }
    .project-details{ font-size: 1.75vh !important; }
    .project-full{ font-size: 1.55vh !important; }

    /* Reduce intro paragraph a touch */
    .research-intro-text .research-intro{ font-size: 1.9vh !important; }

    /* Slightly reduce card image height so cards don't dominate the viewport */
    .project-image{ height: 160px !important; }

    /* Ensure cloned project sticky meta spacing still fits on narrower viewports */
    .project-clone .project-meta{ padding-right: 80px !important; }
}
    .research-meme .timeline-hero-image{
        /* reduce the meme size on phones to avoid visual dominance */
        max-height: 140px;
        width: auto;
        transform: none;
        margin: 0 auto;
    }

    /* Intro text flows under the meme and uses full width */
    .research-intro-text{ width: 100%; }
    .research-intro-text .research-intro{ text-align: center; }

    /* Reduce intro paragraph size slightly on phones */
    .research-intro-text .research-intro{ font-size: 1.6vh !important; text-align: center;}

    /* Force a line-break after the word "Scientific" by rendering the
       wrapped span as block-level on phones. */
    .intro-heading .break-after{ display: block !important; }

    /* Increase spacing between the fixed header and the heading on phones */
    .padding-vertical-xlarge{ padding-top: 100px; padding-bottom: 40px; }

    /* Prevent heading/subtitle from running under the top-right controls
       (close / theme buttons). On phones we allow the heading to wrap and
       reserve a right gutter so lines stop before the control area. */
    .timeline-main-heading-wrapper{ padding-right: 96px; }
    h2.intro-heading{
        white-space: normal; /* allow wrapping on phones */
        max-width: calc(100% - 96px);
        display: block;
        margin-left: auto;
        margin-right: auto;
    }
    /* slightly smaller gutter on very narrow phones */
    @media (max-width: 420px){
        .timeline-main-heading-wrapper{ padding-right: 56px; }
        h2.intro-heading{ max-width: calc(100% - 56px); }
    }
}

/* Projects grid and card styles */
/* Phone layout: place meme above intro and make both fill the viewport
   with equal left/right padding so they visually occupy the full phone
   width. We use 5vw padding on each side to keep comfortable margins. */
@media (max-width: 520px){
    .timeline-main-heading-wrapper{
        /* span the full viewport and center it */
        width: 100vw;
        left: 50%;
        transform: translateX(-50%);
        position: relative;
        padding-left: 1vw;
        padding-right: 1vw;
        box-sizing: border-box;
        max-width: none;
    }

    /* stack meme above intro and make them full-width with equal padding */
    .research-heading-row{
        display: flex;
        flex-direction: column;
        align-items: stretch;
        gap: 1rem;
        width: 100%;
    }

    .research-meme{
        order: -1;
        width: 100%;
        max-width: none;
        display: block;
        margin: 0 auto;
        padding: 0;
    }

    .research-meme .meme-wrapper{
        width: 60%;
        height: auto;
        display: flex;
        justify-content: center;
        align-items: center;
    }

    .research-meme .timeline-hero-image{
        width: 100%;
        max-width: 100%;
        height: auto;
        max-height: 45vh; /* limit height so it doesn't dominate the viewport */
        object-fit: contain;
        margin: 0 auto;
        transform: none;
    }

    .research-intro-text{
        width: 100%;
        padding: 0;
        margin: 0;
    }

    .research-intro-text .research-intro{
        text-align: center !important;
        margin: 0 auto;
    }
}

    /* Phone-specific: ensure the main heading row (h2, meme and intro paragraph)
       remains horizontally centered in the viewport even when we reserve a
       right gutter for top-right controls. We keep a small right gutter but
       center the visible content by translating the inner elements to the
       viewport center. This avoids visual offset when the wrapper itself is
       constrained by container widths. */
    @media (max-width: 520px){
        /* Ensure the inner heading/row do not apply a second translate when
           the wrapper is already centered relative to the viewport. Some
           earlier rules applied left:50%/translateX(-50%) to both the
           wrapper and the inner elements which caused the visible heading
           to shift right — reset those inner transforms here. */
        .timeline-main-heading-wrapper .intro-heading,
        .timeline-main-heading-wrapper .research-heading-row{
            position: relative;
            left: auto !important;
            transform: none !important;
            width: 100% !important;
            max-width: calc(100% - 96px);
            margin-left: auto !important;
            margin-right: auto !important;
        }

        /* Ensure the intro paragraph and meme content are centered inside the
           row (image already constrained elsewhere). */
        .research-intro-text .research-intro{ 
            text-align: center !important;
        }
        .research-meme{ display: flex; justify-content: center; }
    }
.projects-grid{
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 20px;
    margin-top: -2vh; /* pull cards slightly upward to sit closer to the heading */
}

.project-card{
    background: #0f0f10;
    border: 1px solid #232325;
    padding: 0;
    border-radius: 10px;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    box-shadow: 0 4px 18px rgba(0,0,0,0.6);
}

/* Defensive: ensure Research page cards stay dark unless light-mode is active. */
body:not(.light-mode) .project-card{
    background: #0f0f10 !important;
    border: 1px solid #232325 !important;
    box-shadow: 0 4px 18px rgba(0,0,0,0.6) !important;
    color: #e6e6e6 !important;
}
body:not(.light-mode) .project-card .project-title{ color: #ffffff !important; }
body:not(.light-mode) .project-card .project-subtitle{ color: #cfcfcf !important; }

.project-image{
    width: 100%;
    height: 180px;
    object-fit: cover;
    display: block;
    /* enforce a soft zoom transition and ensure it wins over other rules */
    transition: transform 480ms cubic-bezier(0.22, 0.1, 0.22, 1) !important;
    transform-origin: center center;
    will-change: transform;
}

/* Slight zoom on hover for closed cards (avoid affecting the animated clone) */
.project-card:not(.project-clone):hover .project-image{
    transform: scale(1.05) !important; /* enforce softer zoom */
}

.project-meta{
    padding: 16px;
}
.project-title{
    margin: 0 0 6px 0;
    color: white;
    font-size: 2.4vh;
}
.project-subtitle{
    margin: 0;
    color: #cfcfcf;
    font-size: 1.9vh;
}

.project-toggle{
    border: 0;
    background: transparent;
    color: #feda4a;
    padding: 12px 16px;
    text-align: left;
    font-weight: 700;
    cursor: pointer;
    border-top: 1px solid #222;
}

/* Slight yellow overlay on the "Learn more" control when cards are closed.
   This uses a pseudo-element so the button text remains readable. It is
   suppressed while a modal is open (body.project-modal-open). */
.project-toggle{ position: relative; }
.project-toggle::before{
    content: '';
    position: absolute;
    inset: 0;
    background: rgba(254,218,74,0.10);
    pointer-events: none;
    opacity: 0.5; /* default semi-visible; increases on hover */
    /* make overlay fade a touch smoother */
    transition: opacity 980ms cubic-bezier(0.22, 0.1, 0.22, 1);
    border-radius: 0;
}
/* show the subtle yellow overlay only when hovering the button or the card (closed state) */
.project-card:not(.project-clone):hover .project-toggle::before,
.project-toggle:hover::before{
    opacity: 1;
}

.project-details{
    color: #e6e6e6;
    padding: 12px 16px 20px 16px;
    font-size: 1.9vh;
    line-height: 1.45;
    overflow: hidden;
    max-height: 0; /* collapsed */
    transition: max-height 320ms ease;
}

@media (max-width: 520px){
    .project-image{ height: 140px; }
}

/* Fullscreen animated clone used when opening a project */
.project-clone{
    transition: top 480ms cubic-bezier(0.22, 0.1, 0.22, 1), left 480ms cubic-bezier(0.22, 0.1, 0.22, 1), width 480ms cubic-bezier(0.22, 0.1, 0.22, 1), height 480ms cubic-bezier(0.22, 0.1, 0.22, 1), border-radius 260ms ease, box-shadow 260ms ease;
    box-shadow: 0 18px 40px rgba(0,0,0,0.7);
    border-radius: 10px;
    background: #0b0b0b;
    overflow: hidden;
    display: flex;
    flex-direction: column;
}

.project-clone .project-image{ display: block; width: 100%; height: auto; object-fit: cover; }
.project-clone .project-meta{ padding: 18px; }
.project-clone .project-details{ padding: 12px 18px 20px 18px; color: #e6e6e6; }
.project-clone .project-full{ padding: 12px 18px 20px 18px; color: #e6e6e6; }

/* Make the entire cloned fullscreen card scrollable so the image scrolls
   together with the rest of the content. */
.project-clone{
    display: block;
    overflow: auto;
}
.project-clone .project-image{ will-change: auto; }
.project-clone .project-details,
.project-clone .project-full{
    overflow: visible;
}

/* When a project modal is open, make the image area show a normal pointer
   (indicating it's not text/selectable), while the textual content shows the
   text cursor so users get correct affordance for selecting/copying text. */
.project-clone .project-image,
.project-clone .project-image *{
    cursor: default !important;
}
.project-clone .project-meta,
.project-clone .project-details,
.project-clone .project-full,
.project-clone .project-full *{
    cursor: text !important;
}

.project-close{
    /* Default close button styling. When placed inside the clone meta
       this will be positioned absolutely using container positioning. */
    position: absolute;
    top: 8px;
    right: 12px;
    background: rgba(255,255,255,0.06);
    border: 0;
    color: #fff;
    font-size: 1.6rem;
    width: 40px;
    height: 40px;
    border-radius: 8px;
    cursor: pointer;
    z-index: 10002;
    opacity: 0; /* start hidden; JS will fade in */
    transition: opacity 200ms ease, background 160ms ease;
}

/* Theme toggle button shown on the cloned project (matches .project-close styling) */
.project-theme-toggle{
    position: fixed; /* will be repositioned by JS; default visual style */
    top: 12px;
    right: 64px; /* default offset; updated by JS */
    background: rgba(255,255,255,0.06);
    border: 0;
    color: #fff;
    font-size: 1.2rem;
    width: 40px;
    height: 40px;
    border-radius: 8px;
    cursor: pointer;
    z-index: 10002;
    opacity: 0;
    transition: opacity 200ms ease, background 160ms ease;
}
.project-theme-toggle{ display: inline-flex; align-items: center; justify-content: center; line-height: 0; }
.project-theme-toggle svg{ display: block; width: 18px; height: 18px; }
.project-theme-toggle:hover{ background: rgba(255,255,255,0.12); }
body.light-mode .project-theme-toggle{ color: #111 !important; background: rgba(0,0,0,0.06) !important; }

/* Overlay behind fullscreen clone */
.project-overlay{
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.64);
    transition: opacity 260ms ease;
}

/* Close button hover animation */
.project-close{
    transition: background 160ms ease, opacity 160ms ease;
}
.project-close:hover{
    background: rgba(255,255,255,0.12);
}

/* If the close button is appended to body as a fallback, ensure fixed
   placement looks reasonable by targeting the body-level placement. */
body > .project-close{ position: fixed !important; top: 42px !important; right: 12px !important; }

/* Make the whole card keyboard-focusable */
.project-card{ cursor: pointer; }
.project-card:hover{
    outline: 2px solid #aa8e1d6a;
    transition: 200ms ease;
}

/* Improve animation performance for cloned element and image */
.project-clone{
    will-change: top, left, width, height, transform, opacity;
    backface-visibility: hidden;
}
.project-clone .project-image{
    will-change: transform;
    transform: translateZ(0);
    transition: transform 480ms cubic-bezier(0.22, 0.1, 0.22, 1);
}

/* While a project modal is open, suppress focus outlines on cards and buttons */
body.project-modal-open .project-card:focus,
body.project-modal-open .project-card,
body.project-modal-open .project-card:focus-visible,
body.project-modal-open .project-close:focus,
body.project-modal-open .project-toggle:focus{
    outline: none !important;
    box-shadow: none !important;
}

/* When the user starts scrolling, visually fade out hover effects so
   hover-state highlights don't clash with scrolling. This keeps hover
   affordances available but quickly transitions them back to the
   non-hover appearance while scrolling. Class is toggled by JS. */
body.scrolling .project-card:not(.project-clone) .project-image{
    transform: none !important;
    transition: transform 260ms ease !important;
}
body.scrolling .project-card:not(.project-clone) .project-toggle::before{
    opacity: 0 !important; /* hide learn-more yellow overlay while scrolling */
    transition: opacity 220ms ease !important;
}
body.scrolling .project-card{
    outline: none !important;
}
body.scrolling .project-card:hover{ /* ensure hover outline fades */
    outline: none !important;
}
/* suppress small hover transforms on meme reveal and other buttons while scrolling */
body.scrolling .research-meme #meme-wrapper .reveal-btn,
body.scrolling .research-meme #meme-wrapper .reveal-btn:hover{
    transform: none !important;
    transition: transform 200ms ease !important;
}


/* Hide the in-card "Learn more" control when the card is cloned/open, and
   hide toggles on the page while a modal is active so the UI doesn't duplicate. */
.project-clone .project-toggle{ display: none !important; }

/* Sticky header inside cloned project
   Keep the project title/subtitle visible at the top of the cloned viewport
   while allowing the image and body content to scroll underneath. The
   .project-meta is made sticky inside the .project-clone scroll container.
*/
.project-clone .project-meta{
    position: -webkit-sticky;
    position: sticky;
    top: 0; /* stick flush to the top of the viewport */
    z-index: 10001;
    /* ensure the sticky bar covers underlying content for readability */
    background: rgba(11,11,11,0.9);
    padding-top: 15px;
    padding-bottom: 15px;
    padding-right: 112px; /* leave space for the close + theme buttons */
}

/* When in light-mode we want the sticky meta to be light as well */
body.light-mode .project-clone .project-meta{
    background: rgba(255,255,255,0.96) !important;
    color: #111 !important;
}

/* The close button is fixed via JS when a clone is created; ensure it
   looks appropriate in both themes. */
.project-close{
    /* keep existing visuals but make sure fixed placement transitions smoothly */
    transition: background 160ms ease, opacity 160ms ease, filter 160ms ease;
}
body.light-mode .project-close{
    background: rgba(0,0,0,0.06) !important;
    color: #111 !important;
}


/* MathJax / LaTeX color tuning for Research page
   Use slightly muted greys per theme so equations read well on both
   light and dark backgrounds. This page-scoped rule overrides any site-
   wide inversion or MathJax inline attributes. */
/* Light mode: medium-dark grey (good contrast on white) */
body.light-mode .MathJax_SVG,
body.light-mode .mjx-svg,
body.light-mode .mjx-chtml,
body.light-mode .MathJax{
    color: #ffffff !important;
    filter: none !important; /* ensure we don't double-invert */
}
body.light-mode .MathJax_SVG svg,
body.light-mode .mjx-svg svg,
body.light-mode .MathJax_SVG svg *{
    fill: #ffffff !important;
    stroke: #ffffff !important;
}

/* Dark mode: light-medium grey (good contrast on black) */
body:not(.light-mode) .MathJax_SVG,
body:not(.light-mode) .mjx-svg,
body:not(.light-mode) .mjx-chtml,
body:not(.light-mode) .MathJax{
    color: #ffffff !important;
    filter: none !important;
}
body:not(.light-mode) .MathJax_SVG svg,
body:not(.light-mode) .mjx-svg svg,
body:not(.light-mode) .MathJax_SVG svg *{
    fill: #ffffff !important;
    stroke: #ffffff !important;
}

body.project-modal-open .project-toggle{ visibility: hidden !important; pointer-events: none !important; }

/* Research-specific light-mode tweaks (kept minimal here). Global light-mode
    rules live in css/light_mode.css which can be included on other pages too. */
body.light-mode .timeline-main-heading-wrapper{ color: #111; }
body.light-mode .research-intro-text p{ color: #222; }

/* Research page: in light mode, make the divider line between the
   project subtitle and the "Learn more" control a light grey so it
   reads on a white card background. Scoped to #projects-grid to avoid
   changing other pages. */
body.light-mode #projects-grid .project-toggle{
    border-top-color: #e6e6e6 !important;
}

/* Mobile: nudge the expanded navigation panel a few pixels to the right
   on the Research page so it aligns visually with other pages that apply
   the same transform. Uses !important to override the global rule if
   necessary for this page's styles. */
@media (max-width: 768px){
    header.nav-open nav {
        transform: translateX(15px) !important;
    }
}


/* Desktop (PC) specific: fix light-mode 'Learn more' layout on Research page
   so it mirrors the dark-mode desktop layout (full-width toggle, top border,
   correct padding/alignment). Scoped to Research page using #projects-grid
   and body.light-mode so it only affects Research in light mode. */
@media (min-width: 769px){
    body.light-mode #projects-grid .project-toggle{
        display: block !important;
        width: 100% !important;
        box-sizing: border-box !important;
        /* Match dark-mode padding exactly for the learn-more control */
        padding: 12px 16px !important;
        text-align: left !important;
        border: none !important;
        border-top: 1px solid #e6e6e6 !important;
        background: transparent !important;
        margin: 0 !important;
        font-weight: 700 !important;
        cursor: pointer !important;
    }

    /* Ensure the project card has expected padding so the toggle lines up */
    /* Keep outer card padding 0 (matches dark-mode default) and put
       the interior spacing on .project-meta so title/subtitle match */
    body.light-mode #projects-grid .project-card{
        padding: 0 !important;
    }

    body.light-mode #projects-grid .project-meta{
        padding: 16px !important;
    }

    /* Ensure title/subtitle margins mirror dark-mode */
    body.light-mode #projects-grid .project-title{
        margin: 0 0 6px 0 !important;
        font-size: 2.4vh !important;
    }
    body.light-mode #projects-grid .project-subtitle{
        margin: 0 !important;
    }

    /* Desktop: keep heading centered via container centering (matches timeline)
       Do not use viewport transforms here to avoid asymmetric gutters. */
     h2.intro-heading{ display: block; margin-left: auto; margin-right: auto; }

     /* Remove the right padding used on smaller screens so desktop heading
         centering is symmetric like the Timeline page. Keep the padding on
         mobile so controls don't overlap the heading there. */
     .timeline-main-heading-wrapper{ padding-right: 0; }

     /* Desktop: force exactly 3 project cards per row for consistent layout */
     .projects-grid{
          grid-template-columns: repeat(3, 1fr);
          gap: 28px;
     }
}

/* Phone: ensure figures and any images inside the expanded/clone view
   occupy the full width of the viewport so illustrations and plots
   render edge-to-edge on small screens. Keep natural aspect ratio. */
@media (max-width: 780px){
    .project-clone .project-full figure,
    .project-clone .project-full figure img,
    .project-clone .project-full img{
        width: 100% !important;
        max-width: 100% !important;
        box-sizing: border-box !important;
    }
    .project-clone .project-full figure{ margin: 0 0 1rem 0 !important; }
    .project-clone .project-full figure img{ height: auto !important; display: block !important; object-fit: contain !important; }
}

/* Research: expanded/clone view image theme handling
   - Use PNGs (light-mode assets) as-is when `body.light-mode` is present.
   - When the site is in dark mode (no `light-mode` class), apply a filter to
     convert the light PNG into a dark-friendly variant. This keeps the image
     sources as single PNG files while presenting them appropriately in both
     themes. Use a selector specific to the cloned/expanded card so regular
     thumbnail/inline images are unaffected. */
.project-clone .project-full img{
    filter: none !important;
    transition: filter 220ms ease, opacity 160ms ease;
}

/* Dark mode: convert light PNGs to dark-ish appearance */
body:not(.light-mode) .project-clone .project-full img{
    /* Tuned to approximate a dark-mode look; adjust per-image if needed */
    filter: invert(1) hue-rotate(180deg) contrast(0.95) !important;
}

/* Light mode: ensure images render without the darkening filter */
body.light-mode .project-clone .project-full img{
    filter: none !important;
}

/* Meme image theme handling: allow you to provide a single light-mode PNG and
   automatically convert it for dark-mode using a CSS filter. Scoped to the
   research page meme image (`#meme-image` / `.timeline-hero-image`). */
.research-meme .timeline-hero-image,
#meme-image{
    filter: none !important;
    transition: filter 220ms ease, opacity 160ms ease;
}

body:not(.light-mode) .research-meme .timeline-hero-image,
body:not(.light-mode) #meme-image{
    /* Tuned to produce a dark-friendly visual; adjust if needed per image */
    filter: invert(1) hue-rotate(180deg) contrast(0.95) !important;
}

body.light-mode .research-meme .timeline-hero-image,
body.light-mode #meme-image{
    filter: none !important;
}

/* ------------------------------------------------------------------
   Do NOT invert Astrolore images in dark mode
   Some site rules convert light PNGs to dark-friendly variants using
   `filter: invert()`; explicitly exclude Astrolore screenshots so their
   colors remain as authored. We match filenames containing "astrolore".
 ------------------------------------------------------------------ */
body:not(.light-mode) img{
    filter: none !important;
}

/* Center Cubecraft GUI screenshots inside the expanded project card
   without modifying HTML. Select by filename segment so this only
   affects the intended images. */
.project-full img[src*="cubecraft_gui"]{
    display: block;
    margin-left: auto;
    margin-right: auto;
}


