/* ==========================================================================
   site.css — custom layer on top of the Webflow export
   --------------------------------------------------------------------------
   Loaded AFTER normalize.css, webflow.css and the generated
   shyams-portfolio CSS on every page. All hand-written customisations
   live here (previously duplicated as inline <style>/<script> blocks
   on each page).

   Contents
   1. Theme transition        — smooth dark/light cross-fade
   2. Tools marquee           — continuous logo strip, pause on hover
   3. Project-card carousel   — seamless infinite image drift, pause on hover
   4. Accessibility           — reduced-motion guard
   ========================================================================== */


/* 1. Theme transition ---------------------------------------------------- */
/* Cross-fades colours when .light-theme is toggled on <body>. */

body,
body * {
  transition:
    background-color 500ms cubic-bezier(0.65, 0, 0.35, 1),
    color 500ms cubic-bezier(0.65, 0, 0.35, 1),
    border-color 500ms cubic-bezier(0.65, 0, 0.35, 1),
    fill 500ms cubic-bezier(0.65, 0, 0.35, 1),
    stroke 500ms cubic-bezier(0.65, 0, 0.35, 1);
}

/* Glass / bordered elements: their own `transition` in the Webflow CSS
   (border-only, 200ms) overrides the global rule above, which made the
   glass background snap instantly on theme change. Restore the 500ms
   theme fade while keeping the 200ms border hover. */
.glass-effect,
.border-effect {
  transition:
    background-color 500ms cubic-bezier(0.65, 0, 0.35, 1),
    color 500ms cubic-bezier(0.65, 0, 0.35, 1),
    fill 500ms cubic-bezier(0.65, 0, 0.35, 1),
    stroke 500ms cubic-bezier(0.65, 0, 0.35, 1),
    border-color 200ms cubic-bezier(0.645, 0.045, 0.355, 1),
    border 200ms cubic-bezier(0.645, 0.045, 0.355, 1);
}

/* Theme toggle: the Webflow rule .links-switch-wrapper.glass-effect.border-effect
   (higher specificity) redefines `transition` without background-color,
   which made its glass background snap on theme change. Same fix, matched
   specificity: 500ms theme fade + the original 200ms transform/border. */
.links-switch-wrapper.glass-effect.border-effect {
  transition:
    background-color 500ms cubic-bezier(0.65, 0, 0.35, 1),
    color 500ms cubic-bezier(0.65, 0, 0.35, 1),
    fill 500ms cubic-bezier(0.65, 0, 0.35, 1),
    stroke 500ms cubic-bezier(0.65, 0, 0.35, 1),
    transform 200ms cubic-bezier(0.645, 0.045, 0.355, 1),
    border-color 200ms cubic-bezier(0.645, 0.045, 0.355, 1),
    border 200ms cubic-bezier(0.645, 0.045, 0.355, 1);
}

/* Card hover interactions (migrated from Webflow IX2 to pure CSS) --------
   Formerly IX2 interactions a-10/a-11 (project cards) and a-14/a-15
   (resume rows). The project cards' trigger `data-w-id`s were removed from
   the HTML; the resume rows share their trigger with the dropdown
   open/close, so a-14/a-15 were instead pointed at dead selectors inside
   webflow.js (search ".ix2-migrated-" there).
   Everything runs at 200ms with the same easing as the .border-effect
   border hover, so the whole card hover starts and ends as one motion.
   Resting colours are the literals IX2 used to write inline (they're the
   same in both themes), so the look is unchanged. */

/* Project cards: "More Information" text slides in from the right (the
   wrapper is overflow:hidden) while text + arrow tint to the highlight. */
.card-button-static-link-text {
  color: rgb(158, 158, 158);
  transform: translateX(100%);
  transition:
    transform 200ms cubic-bezier(0.645, 0.045, 0.355, 1),
    color 200ms cubic-bezier(0.645, 0.045, 0.355, 1);
}

.card-button-static-link-arrow {
  color: rgb(158, 158, 158);
  transition: color 200ms cubic-bezier(0.645, 0.045, 0.355, 1);
}

.card-project:hover .card-button-static-link-text {
  transform: translateX(0);
  color: var(--_theme---text--highlight);
}

.card-project:hover .card-button-static-link-arrow {
  color: var(--_theme---text--highlight);
}

/* Resume rows: arrow + vertical line tint to the highlight on hover.
   The dropdown open/close (rotation, line growth, dates) stays in IX2. */
.card-button-rotate-arrow {
  color: rgb(158, 158, 158);
  transition:
    color 200ms cubic-bezier(0.645, 0.045, 0.355, 1),
    background-color 200ms cubic-bezier(0.645, 0.045, 0.355, 1);
}

.vertical-line {
  background-color: var(--greyscale--light-grey); /* #9a9183, as IX2 set it */
  transition:
    color 200ms cubic-bezier(0.645, 0.045, 0.355, 1),
    background-color 200ms cubic-bezier(0.645, 0.045, 0.355, 1);
}

.card-resume-dropdown:hover .card-button-rotate-arrow {
  color: var(--_theme---text--highlight);
}

.card-resume-dropdown:hover .vertical-line {
  background-color: var(--_theme---text--highlight);
}

/* Theme-aware logos (inlined SVGs on Backroom): black in light mode,
   white in dark mode, via currentColor. */
.card-project-logo-01,
.card-project-logo-04 {
  color: var(--_theme---text--normal);
}

/* Keep those logos in sync with the rest of the theme fade. Their shapes
   paint with `currentColor`, so they already follow the 500ms `color`
   transition on the <svg> root. The global `body *` rule, though, also gives
   every inner <rect>/<path> its OWN 500ms fill/stroke transition — a second
   ease chasing the already-easing currentColor — which makes the mark land a
   beat after the background and text. Switching the inner shapes' transition
   off lets them track `color` directly, so the logo changes with the theme,
   not after it. */
.card-project-logo-01 *,
.card-project-logo-04 * {
  transition: none;
}


/* 2. Tools marquee ("My Tools" section) ---------------------------------- */

.marquee-wrapper {
  overflow: hidden;
}

.marquee-container {
  animation: marquee-scroll 24s linear infinite;
}

.marquee-wrapper:hover .marquee-container {
  animation-play-state: paused;
}

@keyframes marquee-scroll {
  from { transform: translateX(0); }
  to   { transform: translateX(-100%); }
}


/* 3. Project-card image carousel ----------------------------------------- */
/* Replaces the old Webflow w-slider inside .card-project.
   Markup:
     <div class="card-project-slider" style="--carousel-duration: 32s">
       <div class="card-carousel-track">
         <img class="card-project-image" …>  (one full set)
         <img class="card-project-image" …>  (identical duplicate set,
                                              aria-hidden="true")
       </div>
     </div>
   The track holds exactly two identical sets of images, each image
   carrying the same right-hand margin, so translateX(-50%) lands
   precisely on the start of the duplicate set → a seamless loop with
   no blank space. Speed stays constant across cards because
   --carousel-duration is set per card at 11s per unique image. */

.card-project-slider {
  height: 300px;                 /* same height the w-slider used */
  overflow: hidden;
  position: relative;
  background-color: transparent;
}

.card-carousel-track {
  display: flex;
  width: max-content;
  height: 100%;
  animation: card-carousel-scroll var(--carousel-duration, 44s) linear infinite;
  will-change: transform;
}

.card-carousel-track .card-project-image {
  height: 100%;
  width: auto;
  flex: none;
  margin-right: var(--_responsive---general-spacing--margin-x);
  object-fit: cover;
}

.card-project-slider:hover .card-carousel-track {
  animation-play-state: paused;
}

@keyframes card-carousel-scroll {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}


/* 4. Motion-design gallery (Backroom) ------------------------------------- */
/* Video cards are no longer cropped to the fixed 500px w-background-video
   height at any breakpoint: each card keeps its width behaviour but takes
   its height from the video's real aspect ratio, set per card via
   --video-ar inline (1280/720, 720/404, 520/292). All six videos are
   within 0.3% of 16:9, so the desktop 2-column grid rows stay aligned;
   the sub-pixel difference is absorbed by object-fit: cover. */

.card-project-motion-video {
  height: auto;
  aspect-ratio: var(--video-ar, 16 / 9);
}


/* 5. Page crossfade ------------------------------------------------------- */
/* Site-wide fade between pages, using the theme background colour as the
   fade target. Enter: <html> starts with `.is-loading` (set pre-paint in
   each page's <head>), removed on load to fade the body up from the
   background. Leave: site.js adds `.is-leaving` on internal navigation to
   fade the body down before the browser follows the link.

   The rule below re-declares body's transition so the opacity fade sits
   ALONGSIDE the existing 500ms theme colour fade (a bare `transition:
   opacity` rule would clobber it). Only `body` fades — never `body *` —
   so the Webflow IX2 opacity animations on the hero/cards are untouched. */
html body {
  transition:
    background-color 500ms cubic-bezier(0.65, 0, 0.35, 1),
    color 500ms cubic-bezier(0.65, 0, 0.35, 1),
    border-color 500ms cubic-bezier(0.65, 0, 0.35, 1),
    fill 500ms cubic-bezier(0.65, 0, 0.35, 1),
    stroke 500ms cubic-bezier(0.65, 0, 0.35, 1),
    opacity 350ms ease;
}

html.is-loading body,
html.is-leaving body {
  opacity: 0;
}

/* No fade at all when the visitor prefers reduced motion. */
@media (prefers-reduced-motion: reduce) {
  html.is-loading body,
  html.is-leaving body {
    opacity: 1;
  }
}


/* 5b. Directional page slide (Home <-> Backroom) -------------------------- */
/* Codrops-style "move to left / from right". The whole page (<body>) slides:
   going Home -> Backroom the old page exits to the LEFT and the new one
   enters FROM THE RIGHT; Backroom -> Home is the mirror image. site.js adds
   the leaving class before navigating and stashes the entry direction; the
   destination's pre-paint <head> snippet adds the matching entering class.
   Only Home <-> Backroom use this; every other link keeps the crossfade. */
html.pt-leaving-left,
html.pt-leaving-right,
html.pt-from-right,
html.pt-from-left {
  overflow-x: hidden; /* hide the off-screen half mid-slide (no scrollbar) */
}

/* The slide is applied to the body's content children, NOT to <body> itself,
   and the header + floating theme-switch wrapper are excluded — so those two
   stay pinned to the viewport while the rest of the page slides underneath. */
@media (prefers-reduced-motion: no-preference) {
  html.pt-leaving-left body > :not(.header):not(#theme-toggle) {
    animation: pt-to-left 600ms cubic-bezier(0.77, 0, 0.175, 1) both;
  }
  html.pt-leaving-right body > :not(.header):not(#theme-toggle) {
    animation: pt-to-right 600ms cubic-bezier(0.77, 0, 0.175, 1) both;
  }
  html.pt-from-right body > :not(.header):not(#theme-toggle) {
    animation: pt-from-right 600ms cubic-bezier(0.77, 0, 0.175, 1) both;
  }
  html.pt-from-left body > :not(.header):not(#theme-toggle) {
    animation: pt-from-left 600ms cubic-bezier(0.77, 0, 0.175, 1) both;
  }
}

@keyframes pt-to-left {
  from { transform: translateX(0); }
  to   { transform: translateX(-100%); }
}
@keyframes pt-to-right {
  from { transform: translateX(0); }
  to   { transform: translateX(100%); }
}
@keyframes pt-from-right {
  from { transform: translateX(100%); }
  to   { transform: translateX(0); }
}
@keyframes pt-from-left {
  from { transform: translateX(-100%); }
  to   { transform: translateX(0); }
}

/* Header stays put — like the theme-switch wrapper. Webflow's page-load
   interaction (IX2) slides the header down from translateY(-150%) on every
   load, so it re-drops after each page transition. Forcing the transform off
   with !important overrides the inline transform IX2 writes each frame, and
   also keeps the header visible despite its exported off-screen start state.
   The header is already excluded from the page slide, so this makes it truly
   static throughout. */
.header {
  transform: none !important;
}

/* Hero intro: each block slides in from OUTSIDE its own wrapper and is clipped
   by it (both .hero-text and .hero-image-wrapper already have overflow:hidden)
   — the text slides in from the left (left-to-right), the image from the right
   (right-to-left). No opacity change on the slide. The Webflow fly-ins are
   neutralised in the interaction data, and these start once the page slide has
   finished (600ms). */
@media (prefers-reduced-motion: no-preference) {
  .hero-text > * {
    animation: hero-text-in 700ms cubic-bezier(0.65, 0, 0.35, 1) 600ms both;
  }
  .hero-image {
    animation: hero-image-in 700ms cubic-bezier(0.65, 0, 0.35, 1) 600ms both;
  }
}

@keyframes hero-text-in {
  from { opacity: 0; transform: translateX(-100%); }
  to   { opacity: 1; transform: translateX(0); }
}

@keyframes hero-image-in {
  from { opacity: 0; transform: translateX(100%); }
  to   { opacity: 1; transform: translateX(0); }
}


/* 6. Utility pages (404 / 401) -------------------------------------------- */
/* Brand-matched layout: fixed header (as on the main pages), centred
   message, footer pinned to the bottom. The generated `.utility-page-wrap`
   rule hard-codes height:100vh; here it becomes the flexible middle row so
   the footer sits at the foot of the viewport rather than below the fold. */
body.utility-page {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100svh;
}

body.utility-page .utility-page-wrap {
  flex: 1 0 auto;
  height: auto;
  min-height: 0;
  padding: var(--_responsive---page-spacing--page-gutter);
}

body.utility-page .utility-page-content {
  width: min(440px, 86vw);
  text-align: center;
  grid-row-gap: var(--_responsive---general-spacing--margin-x-5);
}

/* Big status code — centred, in the heading typeface and highlight colour. */
.utility-code {
  margin: 0 0 var(--_responsive---general-spacing--margin-x-25);
  font-family: var(--font-family--heading);
  color: var(--_theme---text--highlight);
  font-size: var(--_responsive---font-size--4x);
  line-height: 1;
  text-align: center;
}

/* Headings and body copy on these pages use the normal text colour. */
body.utility-page .utility-page-content h2 {
  color: var(--_theme---text--normal);
}

.utility-message {
  margin-top: var(--_responsive---general-spacing--margin-x-25);
  color: var(--_theme---text--normal);
  text-align: center;
}

/* "Back to home" link. Borders come from the `.border-effect` class (dashed
   → solid highlight on hover); here we only add the pill shape, spacing and
   text colour. */
.utility-home-button {
  align-self: center;
  margin-top: var(--_responsive---general-spacing--margin-x);
  padding: var(--_responsive---general-spacing--margin-x-5)
           var(--_responsive---general-spacing--margin-2x);
  border-radius: var(--_responsive---border-styles--radius-round);
  font-family: var(--font-family--paragraph);
  color: var(--_theme---text--normal);
  text-decoration: none;
  transition: color 200ms cubic-bezier(0.645, 0.045, 0.355, 1);
}

.utility-home-button:hover {
  color: var(--_theme---text--highlight);
}

/* 401 password form, matched to the theme. */
body.utility-page .utility-page-form label {
  margin-top: var(--_responsive---general-spacing--margin-x-5);
  color: var(--_theme---text--normal);
  font-family: var(--font-family--paragraph);
  text-align: left;
}

/* Field border comes from the `.border-effect` class; keep it transparent,
   rounded and themed, and warm the border to highlight on focus. */
body.utility-page .utility-page-form .w-input {
  margin-bottom: var(--_responsive---general-spacing--margin-x-5);
  background-color: #0000;
  border-radius: var(--_responsive---border-styles--radius-round);
  color: var(--_theme---text--normal);
  font-family: var(--font-family--paragraph);
}

body.utility-page .utility-page-form .w-input::placeholder {
  color: var(--_theme---text--mono-04);
}

body.utility-page .utility-page-form .w-input:focus {
  border-style: solid;
  border-color: var(--_theme---text--highlight);
  outline: none;
}

/* Submit button. Borders come from `.border-effect`; pill shape + text
   colour only. */
body.utility-page .utility-page-form .w-button {
  align-self: center;
  margin-top: var(--_responsive---general-spacing--margin-x-5);
  padding: var(--_responsive---general-spacing--margin-x-5)
           var(--_responsive---general-spacing--margin-2x);
  background-color: #0000;
  border-radius: var(--_responsive---border-styles--radius-round);
  font-family: var(--font-family--paragraph);
  color: var(--_theme---text--normal);
  transition: color 200ms cubic-bezier(0.645, 0.045, 0.355, 1);
}

body.utility-page .utility-page-form .w-button:hover {
  color: var(--_theme---text--highlight);
}

body.utility-page .utility-page-form .w-form-fail {
  margin-top: var(--_responsive---general-spacing--margin-x-5);
  color: var(--_theme---text--highlight);
}


/* 7. Accessibility -------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .marquee-container,
  .card-carousel-track {
    animation-play-state: paused;
  }
}
