/* ==========================================================================
   Shashwat's portfolio — base.css
   Tokens, reset, type scale, container and components shared by every page.
   ========================================================================== */

:root {
  /* Colour */
  --ink: #10284a;
  --green-900: #295538;
  --green-800: #225b44;
  --olive-800: #3c5d1f;
  --olive-900: #30580a;
  --surface: #f3ffeb;
  --card: #f2fce9;
  --card-border: #a2b294;
  --grad-light: #d9f795;
  --grad-deep: #50c192;
  --desk: #745b47;
  --page: #fff;

  /* Fonts */
  --font-display: "Bricolage Grotesque", "Arial Black", system-ui, sans-serif;
  --font-body: "Golos Text", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-accent: "Fredoka", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-ui: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;

  /* Layout */
  --container: 960px;
  --gutter: clamp(16px, 5vw, 32px);
  --section-gap: clamp(64px, 12.5vw, 120px);

  /* Type scale.
     One fluid factor (0 at 320px wide, 1 at 960px) drives every step, so the
     sizes shrink together on small screens and the hierarchy never reorders.
     Each token is: mobile size + (desktop size - mobile size) * factor.
     Desktop sizes are the Figma sizes. */
  --fluid: clamp(0px, (100vw - 320px) / 640, 1px); /* 0px .. 1px */

  --text-eyebrow: calc(12px + 2 * var(--fluid));   /* 12 -> 14 */
  --text-body:    calc(15px + 1 * var(--fluid));   /* 15 -> 16 */
  --text-body-lg: calc(16px + 2 * var(--fluid));   /* 16 -> 18 */
  --text-subhead: calc(17px + 3 * var(--fluid));   /* 17 -> 20 */
  --text-title:   calc(20px + 4 * var(--fluid));   /* 20 -> 24 */
  --text-lead:    calc(20px + 4 * var(--fluid));   /* 20 -> 24 */
  --text-logo:    calc(20px + 12 * var(--fluid));  /* 20 -> 32 */
  --text-display: calc(26px + 18 * var(--fluid));  /* 26 -> 44 */

  /* Line heights, as ratios so they follow the size */
  --lh-eyebrow: 1.43;  /* 20 / 14 */
  --lh-body: 1.5;      /* 24 / 16 */
  --lh-body-loose: 1.8;/* 29 / 16 */
  --lh-body-lg: 1.56;  /* 28 / 18 */
  --lh-subhead: 1.4;   /* 28 / 20 */
  --lh-title: 1.5;     /* 36 / 24 */
  --lh-lead: 1.67;     /* 40 / 24 */
  --lh-display: 1;     /* Figma is 36 / 44; 1 keeps wrapped lines apart on phones */
}

/* Reset ------------------------------------------------------------------ */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--page);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--text-body);
  line-height: var(--lh-body);
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3, p, ul, figure { margin: 0; }
ul { padding: 0; list-style: none; }
img { display: block; max-width: 100%; height: auto; }
a { color: inherit; }

/* Layout ------------------------------------------------------------------ */
/* Everything except the hero sits in this. Content never exceeds 960px. */
.container {
  width: 100%;
  max-width: calc(var(--container) + 2 * var(--gutter));
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* Type -------------------------------------------------------------------- */
.eyebrow {
  font-family: var(--font-accent);
  font-weight: 500;
  font-size: var(--text-eyebrow);
  line-height: var(--lh-eyebrow);
  text-transform: uppercase;
  color: var(--green-800);
}
.title {
  font-weight: 600;
  font-size: var(--text-title);
  line-height: var(--lh-title);
}
.subhead {
  font-weight: 700;
  font-size: var(--text-subhead);
  line-height: var(--lh-subhead);
}
.display {
  font-weight: 900;
  font-size: var(--text-display);
  line-height: var(--lh-display);
}
.lead {
  font-size: var(--text-lead);
  line-height: var(--lh-lead);
}
.body { font-size: var(--text-body); line-height: var(--lh-body); }
.body-loose { font-size: var(--text-body); line-height: var(--lh-body-loose); }
.body-lg { font-size: var(--text-body-lg); line-height: var(--lh-body-lg); }
.prose > p + p { margin-top: 1.5em; }

/* Components -------------------------------------------------------------- */
.card {
  background: linear-gradient(to bottom, var(--card), rgba(242, 252, 233, 0));
  border-radius: 16px;
  padding: clamp(20px, 4.2vw, 40px);
}

.chips { display: flex; flex-wrap: wrap; gap: 8px 12px; }
.chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 40px;
  padding: 8px 16px;
  border-radius: 24px;
  background: linear-gradient(to right, rgba(168, 255, 149, .4), rgba(200, 240, 161, .4));
  color: var(--olive-900);
  font-weight: 600;
  font-size: var(--text-eyebrow);
  line-height: var(--lh-eyebrow);
  text-transform: uppercase;
  white-space: nowrap;
}

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 20px;
  padding-top: clamp(8px, 3.3vw, 32px);
}
.chip__icon { width: 24px; height: 24px; flex: none; }
.button {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 16px 20px 18px;
  border: 2px solid var(--ink);
  border-radius: 20px;
  background: #fff;
  box-shadow: inset 0 -4px 0 var(--ink);
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: var(--text-body);
  line-height: 1.5;
  letter-spacing: .02em;
  text-decoration: none;
  transition: translate .12s, box-shadow .12s;
}
.button:hover, .button:focus-visible { translate: 0 2px; box-shadow: inset 0 -2px 0 var(--ink); }
.button__icon { width: 24px; height: 24px; flex: none; }

/* Header and footer bar: avatar, logo, then links or a note. Shared by every
   page. It has no background of its own. */
.site-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 16px;
  padding: 16px;
  border-radius: 72px;
}
.site-bar__avatar {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  flex: none;
  border: 2px solid #fff;
  border-radius: 50%;
  background: #e6d6ff;
}
.site-bar__avatar img { width: 31px; }
.site-bar__logo {
  flex: 1 0 auto;
  font-family: var(--font-accent);
  font-weight: 700;
  font-stretch: 118%;
  font-variation-settings: "wdth" 118;
  font-size: var(--text-logo);
  line-height: 1.25;
}
.site-bar__nav { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; }
.site-bar__note {
  font-family: var(--font-accent);
  font-weight: 500;
  font-size: var(--text-body);
  line-height: var(--lh-body);
}
.pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 56px;
  padding: 7px 24px;
  border: 1px solid var(--ink);
  border-radius: 36px;
  font-family: var(--font-accent);
  font-weight: 500;
  font-size: var(--text-body);
  line-height: var(--lh-body);
  text-decoration: none;
  white-space: nowrap;
  transition: background-color .2s;
}
/* Links only pick up colour when hovered or focused. */
.pill:hover, .pill:focus-visible { background-color: #f9f5ff; }
/* The page you are on. The gradient is drawn twice as wide as the pill, with
   its mirror image in the second half; hovering slides it across, so the
   colours travel smoothly inside the pill and slide back on leaving. */
.pill--accent,
.pill--accent:hover,
.pill--accent:focus-visible {
  border-color: transparent;
  background: linear-gradient(to right, #fbecda, #fbd3fd 25.2%, #e8cdff 50%, #fbd3fd 74.8%, #fbecda) 0% 0 / 200% 100%;
  color: #430465;
}
.pill--accent { transition: background-position .7s ease; }
.pill--accent:hover, .pill--accent:focus-visible { background-position: 100% 0; }
.pill--accent strong { font-weight: 600; }
.pill__icon { width: 20px; height: 20px; flex: none; }

/* The menu button and the checkbox behind it only exist on phones. On wider
   screens the tray wrapper steps aside and the links sit in the bar. */
.site-bar__menu { display: none; }
.site-bar__tray { display: contents; }

@media (max-width: 719px) {
  .site-bar { padding: 0; border-radius: 0; }
  .pill { min-height: 44px; padding: 4px 14px; }

  /* Phone header: avatar, logo and a menu button. The links drop down
     underneath as a white tray when the button is tapped. It is a checkbox
     and its label, so it works without any script. */
  .site-bar--menu { padding: 16px 16px 0; }
  .site-bar--menu .site-bar__avatar img { width: 24px; }
  .site-bar__menu {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    flex: none;
    border: 1px solid var(--ink);
    border-radius: 50%;
    cursor: pointer;
  }
  .site-bar__menu img { width: 19px; height: 16px; }
  .site-bar__menu .icon-close { display: none; }
  .site-menu-toggle:checked ~ .site-bar .icon-open { display: none; }
  .site-menu-toggle:checked ~ .site-bar .icon-close { display: block; animation: menu-icon .25s ease-out; }
  .site-menu-toggle:focus-visible ~ .site-bar .site-bar__menu { outline: 2px solid var(--ink); outline-offset: 3px; }

  /* The tray is always in the page but folded to zero height. Opening it
     grows the row from 0fr to 1fr, so the tray unfolds and everything below
     it slides down smoothly instead of jumping. Closing runs in reverse. */
  .site-bar__tray {
    display: grid;
    grid-template-rows: 0fr;
    flex: 1 0 100%;
    margin: 0 -16px;
    border-radius: 20px;
    background: #fff;
    opacity: 0;
    visibility: hidden;            /* keeps the hidden links out of the tab order */
    transition:
      grid-template-rows .35s cubic-bezier(.3, .7, .2, 1),
      margin-top .35s cubic-bezier(.3, .7, .2, 1),
      opacity .25s ease,
      visibility 0s linear .35s;
  }
  .site-menu-toggle:checked ~ .site-bar .site-bar__tray {
    grid-template-rows: 1fr;
    margin-top: 8px;               /* 16px to the bottom of the bar, then a 4px gap */
    opacity: 1;
    visibility: visible;
    transition-delay: 0s;
  }
  .site-bar--menu .site-bar__nav {
    flex-direction: column;
    flex-wrap: nowrap;
    align-items: stretch;
    gap: 4px;
    min-height: 0;                 /* lets the row fold all the way shut */
    overflow: hidden;
    padding: 0 24px;
  }
  /* the tray's 16px top and bottom padding, as margins so it can fold flat */
  .site-bar--menu .pill:first-child { margin-top: 16px; }
  .site-bar--menu .pill--end { margin-bottom: 16px; }

  /* The links follow one after another as it opens. */
  .site-menu-toggle:checked ~ .site-bar .pill { animation: menu-link .3s ease-out backwards; }
  .site-menu-toggle:checked ~ .site-bar .pill:nth-child(2) { animation-delay: .04s; }
  .site-menu-toggle:checked ~ .site-bar .pill--accent { animation-delay: .08s; }
  .site-menu-toggle:checked ~ .site-bar .pill--end { animation-delay: .12s; }

  .site-bar--menu .pill {
    flex: none;
    min-height: 48px;
    padding: 7px 24px;
    border: 0;
    border-radius: 8px;
  }
  .site-bar--menu .pill:first-child { border-radius: 20px 20px 8px 8px; }
  /* the resume link always closes the list */
  .site-bar--menu .pill--end { order: 1; border-radius: 8px 8px 20px 20px; }
  .site-bar--menu .pill--accent { border-radius: 30px; color: var(--ink); }
  .site-bar--menu .pill--accent strong { font-weight: 500; }
}

@keyframes menu-link {
  from { opacity: 0; transform: translateY(-6px); }
}
@keyframes menu-icon {
  from { opacity: 0; transform: rotate(-45deg); }
}

.media {
  display: block;
  width: 100%;
  border-radius: 12px;
}
.media--bordered { border: 1px solid var(--card-border); }

/* Zoom -----------------------------------------------------------------------
   Any image or video with data-zoom="<HD file>" opens in a full-screen viewer
   when clicked (js/parallax.js builds the <dialog>). The page shows the light
   file; the HD file is only fetched when someone zooms. */
.zoom-on [data-zoom] { cursor: zoom-in; transition: filter .2s ease, box-shadow .2s ease; }
.zoom-on [data-zoom]:hover { filter: brightness(.96); }
.zoom-on [data-zoom]:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
html:has(.zoom[open]) { overflow: hidden; }

.zoom {
  position: fixed;
  inset: 0;
  width: 100vw;
  height: 100vh;
  height: 100dvh;
  max-width: none;
  max-height: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: rgba(0, 0, 0, .8);   /* #000000 at 80%, as Shashwat asked */
  overflow: hidden;
}
.zoom::backdrop { background: transparent; }
.zoom[open] { animation: zoom-fade .2s ease-out; }
.zoom[open] .zoom__media { animation: zoom-pop .25s ease-out; }
/* The stage scrolls when the picture is shown at full size. margin: auto on
   the picture centres it without cutting off the start when it overflows. */
.zoom__stage {
  display: flex;
  width: 100%;
  height: 100%;
  padding: 16px;
  overflow: auto;
  overscroll-behavior: contain;
}
.zoom__media {
  display: block;
  flex: none;
  margin: auto;
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  border-radius: 12px;
  background: var(--surface);
  box-shadow: 0 16px 64px rgba(0, 0, 0, .35);
}
img.zoom__media { cursor: zoom-in; }
video.zoom__media { background: #1a100c; }
/* Second step for pictures: actual size, scroll or drag to look around. */
.zoom.is-full img.zoom__media {
  max-width: none;
  max-height: none;
  width: var(--zoom-w);
  cursor: zoom-out;
}
.zoom__close {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--surface);
  box-shadow: 0 2px 12px rgba(0, 0, 0, .25);
  cursor: pointer;
}
.zoom__close img { width: 16px; height: 16px; }
.zoom__close:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }
@keyframes zoom-fade { from { opacity: 0; } }
@keyframes zoom-pop { from { scale: .96; opacity: 0; } }

/* Parallax ----------------------------------------------------------------
   js/parallax.js writes --py on every [data-parallax] element. Using the
   individual `translate` property keeps it independent of any `transform`. */
[data-parallax] { translate: 0 var(--py, 0px); will-change: translate; }

/* Fade-in on scroll ---------------------------------------------------------
   js/parallax.js adds .reveal-on to <html>, then .is-visible to each
   [data-reveal] section the first time it scrolls into view. */
.reveal-on [data-reveal] {
  opacity: 0;
  transform: translateY(16px);
}
/* The transition lives here so sections never animate while being hidden. */
.reveal-on [data-reveal].is-visible {
  opacity: 1;
  transform: none;
  transition: opacity .7s ease-out, transform .7s ease-out;
}

@media (prefers-reduced-motion: reduce) {
  .reveal-on [data-reveal] { opacity: 1; transform: none; }
  [data-parallax] { translate: none; }
  *, *::before, *::after { animation: none !important; transition: none !important; }
}

.visually-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}
