/* ==========================================================================
   Fonts — self-hosted, Latin subset (woff2). Both families are SIL OFL 1.1.
   Lateef: https://github.com/silnrsi/font-lateef   Mona Sans: https://github.com/github/mona-sans
   Files come from the Fontsource packages (@fontsource/lateef, @fontsource-variable/mona-sans).
   ========================================================================== */

@font-face {
  font-family: "Lateef";
  font-style: normal; font-weight: 300; font-display: swap;
  src: url("../assets/fonts/lateef-latin-300-normal.woff2") format("woff2");
}
@font-face {
  font-family: "Lateef";
  font-style: normal; font-weight: 400; font-display: swap;
  src: url("../assets/fonts/lateef-latin-400-normal.woff2") format("woff2");
}
@font-face {
  font-family: "Mona Sans";
  font-style: normal; font-weight: 200 900; font-display: swap; /* variable weight */
  src: url("../assets/fonts/mona-sans-latin-wght-normal.woff2") format("woff2");
}

/* ==========================================================================
   Stefanie Chan — portfolio homepage
   Tokens come from the Figma "Visual ID Guidelines".
   Desktop baseline = 1280px. --u scales desktop measurements between
   900px and 1280px; below 900px the mobile layout takes over.
   ========================================================================== */

:root {
  --vh: 100vh;
  /* When the hero statement + contact lines (and the scroll arrow) start appearing, counted from the end of the hold (when the three words start fading out) */
  --statement-delay: 1.4s;
  /* Colour */
  --bg: #fcfff7;
  --primary: #2f9a67;
  --text-primary: #0d0d0d;
  --text-secondary: #1f6b45; /* philosophy headings */
  --heading: #444444;
  --nav-inactive: rgba(67, 67, 67, 0.5);
  --border-default: #a8d5ba;
  --tint-work: rgba(47, 154, 103, 0.15);
  --tint-philosophy: rgba(226, 240, 232, 0.4);
  --word-1: #087541;
  --word-2: #2f9a67;
  --word-3: #2fb977;
  --word-faint-opacity: 0.03;

  /* Effects */
  --shadow-tile: 0 4px 30px 10px rgba(0, 0, 0, 0.05);
  --shadow-tile-hover: 0 8px 36px 12px rgba(0, 0, 0, 0.09);

  /* Type */
  --font-display: "Lateef", Georgia, serif;
  --font-body: "Mona Sans", system-ui, sans-serif;

  /* Motion (hover/transition values are proposals — see notes) */
  --ease-out: cubic-bezier(0.22, 0.61, 0.36, 1);

  /* Desktop scale factor: 1px at >=1280px viewport */
  --u: calc(min(100vw, 1280px) / 1280);
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text-primary);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 32px;
  -webkit-font-smoothing: antialiased;
  min-height: 100vh;
  display: flex; flex-direction: column;
}
.page { flex: 1 0 auto; width: 100%; }
.footer { flex-shrink: 0; }

h1, h2, h3, p, ul { margin: 0; padding: 0; }
ul { list-style: none; }
img { display: block; max-width: none; }
a { color: inherit; text-decoration: none; }
[hidden] { display: none !important; }

:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 4px;
  border-radius: 4px;
}

.skip-link {
  position: absolute; left: 16px; top: -64px; z-index: 10;
  background: var(--primary); color: #fff; padding: 8px 16px; border-radius: 8px;
  transition: top 0.2s var(--ease-out);
}
.skip-link:focus { top: 16px; }

.page { position: relative; max-width: 1280px; margin: 0 auto; }

@supports (height: 100svh) { :root { --vh: 100svh; } }

/* ==========================================================================
   Hero (desktop)
   ========================================================================== */

/* The part above the divider fills the viewport, so on landing only the
   opening is visible; the nav + content start 122px (design) below the divider. */
.hero {
  --above: max(calc(var(--u) * 527), var(--vh));
  position: relative;
  height: calc(var(--above) + var(--u) * 122);
}
/* The 527px design composition, centred in whatever space the viewport gives */
.hero__canvas {
  position: absolute;
  left: 0; right: 0;
  top: calc((var(--above) - var(--u) * 527) / 2);
  height: calc(var(--u) * 527);
}

.hero__logo {
  position: absolute;
  left: calc(var(--u) * 36);
  top: calc(var(--u) * 34.5);
  width: calc(var(--u) * 32);
  height: calc(var(--u) * 44);
  transition: transform 0.25s var(--ease-out);
}
.hero__logo img { width: 100%; height: 100%; }
.hero__logo:hover { transform: scale(1.08) rotate(-4deg); }

/* Decorative role words */
.hero__words { position: absolute; left: 0; top: 0; pointer-events: none; }
.hero__word {
  position: absolute;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: calc(var(--u) * 150);
  line-height: calc(var(--u) * 120);
  white-space: nowrap;
}
.hero__word .punct { font-size: calc(var(--u) * 110); }
.hero__word--1 { left: calc(var(--u) * -51); top: calc(var(--u) * -50); color: var(--word-1); }
.hero__word--2 { left: calc(var(--u) * -7); top: calc(var(--u) * 43); color: var(--word-2); }
.hero__word--3 { left: calc(var(--u) * 54); top: calc(var(--u) * 135); color: var(--word-3); }

/* Greeting block */
.hero__intro {
  position: absolute;
  left: calc(var(--u) * 166);
  top: calc(var(--u) * 158);
  width: calc(var(--u) * 865);
  height: calc(var(--u) * 280);
}
.hero__greeting {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: calc(var(--u) * 150);
  line-height: calc(var(--u) * 120);
  color: var(--primary);
  white-space: nowrap;
}
.hero__statement {
  position: absolute;
  left: calc(var(--u) * 79);
  top: calc(var(--u) * 140);
  width: calc(var(--u) * 729);
  font-family: var(--font-display);
  font-weight: 300;
  font-size: calc(var(--u) * 40);
  line-height: calc(var(--u) * 40);
  color: var(--text-primary);
}

/* Contact icons (SVG: Lucide "mail" — ISC; Font Awesome "linkedin-in" — CC BY 4.0) */
.contact {
  position: absolute;
  left: calc(var(--u) * 79);
  top: calc(var(--u) * 239);
  display: flex;
  gap: calc(var(--u) * 0); /* space between the two icon boxes; each box also has built-in padding around its icon */
}
.contact__link {
  display: grid; place-items: center;
  width: calc(var(--u) * 48); height: calc(var(--u) * 41);
  border-radius: 8px;
  transition: background-color 0.2s var(--ease-out), transform 0.2s var(--ease-out);
}
.contact__link img { width: auto; height: calc(var(--u) * 25); } /* LinkedIn: its square fills its whole box, so it is smaller than the mail box to look the same height */
.contact__link:first-child img { height: calc(var(--u) * 34); }
.contact__link:hover { background-color: rgba(47, 154, 103, 0.12); transform: translateY(-2px); }
button.contact__link { appearance: none; border: 0; padding: 0; margin: 0; background: transparent; color: inherit; font: inherit; cursor: pointer; }
button.contact__link:hover { background-color: rgba(47, 154, 103, 0.12); }

/* Email line revealed by the mail icon (text is inserted by js/main.js) */
.contact-line {
  position: absolute;
  left: calc(var(--u) * 79);
  top: calc(var(--u) * 288);
  display: none;
  font-size: 16px; line-height: 32px;
  color: var(--text-primary);
}
.contact-line.is-open { display: block; animation: line-in 0.4s var(--ease-out) both; }
.contact-line__address {
  font-weight: 500;
  text-decoration: underline; text-decoration-color: var(--border-default); text-underline-offset: 4px;
  transition: color 0.2s var(--ease-out), text-decoration-color 0.2s var(--ease-out);
}
.contact-line__address:hover { color: var(--primary); text-decoration-color: var(--primary); }
.contact-line__copy {
  appearance: none; margin-left: 12px; padding: 0 12px;
  font: inherit; font-size: 13px; font-weight: 500; line-height: 24px; vertical-align: 1px;
  color: var(--text-secondary); background: transparent;
  border: 1px solid var(--border-default); border-radius: 999px; cursor: pointer;
  transition: background-color 0.2s var(--ease-out), border-color 0.2s var(--ease-out);
}
.contact-line__copy:hover { background: var(--tint-philosophy); border-color: var(--primary); }
@keyframes line-in { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: translateY(0); } }

.hero__divider {
  position: absolute;
  left: calc(var(--u) * 71);
  top: calc(var(--above) - 1px);
  width: calc(var(--u) * 1148);
  height: 1px;
  transform: rotate(-0.1deg);
}

/* ==========================================================================
   Stage: nav rail + content
   ========================================================================== */

.stage {
  display: grid;
  grid-template-columns: calc(var(--u) * 191) minmax(0, 1fr);
  column-gap: calc(var(--u) * 122);
  padding: 0 calc(var(--u) * 90) calc(var(--u) * 120) calc(var(--u) * 71);
  min-height: calc(var(--u) * 553 + var(--u) * 120);
  align-items: start;
}

.nav {
  display: flex; flex-direction: column;
  gap: calc(var(--u) * 35);
  font-family: var(--font-display);
  font-weight: 300;
  font-size: calc(var(--u) * 80);
  line-height: calc(var(--u) * 40);
  text-transform: uppercase;
  /* Follows the user once scrolled past its starting position, and settles back
     at that position when scrolling up. 48px is the gap kept from the top of the window. */
  position: sticky;
  top: 48px;
  align-self: start;
}
.nav__link {
  display: block;
  color: var(--nav-inactive);
  transition: color 0.25s var(--ease-out), transform 0.25s var(--ease-out);
}
.nav__link:hover { color: rgba(47, 154, 103, 0.75); transform: translateX(4px); }
.nav__link[aria-current="page"] { color: var(--primary); }
.nav__link[aria-current="page"]:hover { transform: none; }

/* ==========================================================================
   Work + Play tiles
   ========================================================================== */

.tiles {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 16px;
  align-items: start;
}
.tile--offset { margin-top: 40px; }

.tile__link { display: flex; flex-direction: column; gap: 16px; }

.tile__media {
  position: relative;
  aspect-ratio: 395 / 353;
  border-radius: 32px;
  overflow: hidden;
  box-shadow: var(--shadow-tile);
  transition: box-shadow 0.3s var(--ease-out), transform 0.3s var(--ease-out);
  /* keeps the rounded clip + shadow crisp while the image scales on hover */
  isolation: isolate;
}
.tile__media--tint  { background: var(--tint-work); }
.tile__media--white { background: #fff; }

.media { position: absolute; object-fit: cover; transition: transform 0.5s var(--ease-out); }
/* positions are percentages of the 395 × 353 panel (from Figma) */
.media--koin        { left: 19.49%; top: 6.80%;  width: 61.27%;  height: 132.01%; }
.media--knit-back   { left: 25.85%; top: 32.04%; width: 70.86%;  height: 55.55%; }
.media--knit-front  { left: 5.06%;  top: 10.20%; width: 70.86%;  height: 55.55%; }
.media--sketches    { left: 0;      top: -21.53%; width: 102.03%; height: 150.71%; }
.media--cover       { inset: 0; width: 100%; height: 100%; }

.tile__link:hover .tile__media { transform: translateY(-4px); box-shadow: var(--shadow-tile-hover); }
.tile__link:hover .media { transform: scale(1.02); }

.tile__copy { color: #000; }
.tile__eyebrow { font-family: var(--font-display); font-size: 24px; line-height: 40px; }
.tile__title   { font-family: var(--font-display); font-weight: 400; font-size: 40px; line-height: 40px; }
.tile__desc    { font-size: 16px; line-height: 32px; color: var(--text-primary); }

/* ==========================================================================
   About
   ========================================================================== */

.panel--about { display: flex; flex-direction: column; gap: 117px; }

.section-heading {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: 80px;
  line-height: 40px;
  color: var(--heading);
}

.about-bio__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 244px;
  column-gap: 32px;
  margin-top: 32px;
  align-items: start;
}
.about-bio__text { display: flex; flex-direction: column; gap: 40px; max-width: 582px; }
.portrait {
  width: 244px; height: 351px; margin-top: 8px;
  border-radius: 171px; overflow: hidden;
  box-shadow: var(--shadow-tile);
}
.portrait img {
  width: 107.38%; height: 107.72%;
  margin-left: -3.38%; margin-top: -3.96%;
  object-fit: cover;
}

.about-philosophies__intro { margin-top: 35px; }
.cards {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  column-gap: 17px;
  margin-top: 37px;
}
.card {
  min-height: 366px;
  padding: 20px 16px 16px 20px;
  border-radius: 16px;
  background: var(--tint-philosophy);
  display: flex; flex-direction: column;
}
.card__title { font-family: var(--font-display); font-weight: 400; font-size: 28px; line-height: 40px; color: var(--text-secondary); }
.card__strap { font-weight: 500; }
.card__body  { margin-top: 16px; }

/* ==========================================================================
   Footer
   ========================================================================== */

.footer {
  background: var(--primary);
  height: 86px;
  display: flex; align-items: center;
  padding-left: max(calc(var(--u) * 71), calc((100vw - 1280px) / 2 + 71px));
}
.footer__copy { font-family: var(--font-display); font-size: 24px; line-height: 16px; color: #fff; }

/* ==========================================================================
   Motion
   ========================================================================== */

@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
/* Slide distance for the three hero words: the -10px below */
@keyframes slide-in-left { from { translate: -10px 0; } to { translate: 0 0; } }
@keyframes fade-to-faint { from { opacity: 1; } to { opacity: var(--word-faint-opacity); } }
@keyframes rise-in {
  from { opacity: 0; transform: translateY(32px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Opening sequence — only when JS is available.
   Timeline (seconds from page load); js/main.js has the matching OPENING_HOLD:
     0.2 / 1.0 / 2.0   words 1, 2, 3 start fading in (1.0s fade) and sliding in from the left (1.2s slide)
     3.0               word 3 fully visible
     3.4               hold ends (OPENING_HOLD): the three words fade out over 1s, which starts "settled"
     +0.6 (4.0)        "Hey, I'm Stef!" starts rising in (1.5s)
     +1.4 (4.8)        statement + contact start rising in, and the scroll arrow appears (--statement-delay)
     +2.8 (6.2)        tiles / About sections fade up (set in js/main.js) */
.js .hero__word { opacity: 0; }
/* Each word runs two animations: [1] a fade, [2] a small slide in from the left.
   --d is the word's start delay. The slide keeps running (uninterrupted) if the
   opening settles while it is still moving, because only the fade entry changes name. */
.js .hero__word--1 { --d: 0.2s; }
.js .hero__word--2 { --d: 1.0s; }
.js .hero__word--3 { --d: 2.0s; }
.js .hero__word { animation-fill-mode: forwards, forwards; }

.js .hero[data-phase="opening"] .hero__word {
  animation-name: fade-in, slide-in-left;
  animation-duration: 1.0s, 1.2s;              /* [fade-in time, slide time] */
  animation-timing-function: ease-in-out, ease-out;
  animation-delay: var(--d), var(--d);
}

/* Fade-OUT of the three lines to ~3% — starts when the hold ends.
   [fade-out time, slide time]: keep the slide time equal to the opening one above,
   so a slide that is still moving at this point is not retimed. */
.js .hero[data-phase="settled"] .hero__word {
  animation-name: fade-to-faint, slide-in-left;
  animation-duration: 1s, 1.2s;
  animation-timing-function: ease-in-out, ease-out;
  animation-delay: 0s, var(--d);
}

.js .hero__greeting, .js .hero__statement, .js .contact { opacity: 0; }
.js .hero[data-phase="settled"] .hero__greeting,
.js .hero[data-phase="settled"] .hero__statement,
.js .hero[data-phase="settled"] .contact { animation: rise-in 1.5s var(--ease-out) forwards; }
.js .hero[data-phase="settled"] .hero__greeting  { animation-delay: 0.6s; }   /* after the fade-out starts */
.js .hero[data-phase="settled"] .hero__statement { animation-delay: var(--statement-delay); }
.js .hero[data-phase="settled"] .contact         { animation-delay: var(--statement-delay); }
/* "remains until refresh": settled state needs no further rules */

/* Tiles + sections: fade in upward, progressively */
.js .panel [data-reveal] { opacity: 0; }
.js .panel.is-revealed [data-reveal] { animation: rise-in 0.7s var(--ease-out) forwards; }
.js .panel.is-revealed [data-reveal]:nth-child(2) { animation-delay: 0.15s; }

/* Skipped opening (?skip-intro, or arriving from another page of the site): only the OPENING HERO is already in
   its final state, with no animation. The Work / Play / About tiles and sections still fade up as normal
   (.panel [data-reveal] above), for new and returning visitors alike. */
.skip-intro .hero__word { opacity: var(--word-faint-opacity) !important; animation: none !important; translate: none !important; }
.skip-intro .hero__greeting, .skip-intro .hero__statement, .skip-intro .contact { opacity: 1 !important; animation: none !important; transform: none !important; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
  .js .hero__word { opacity: var(--word-faint-opacity); }
  .js .hero__greeting, .js .hero__statement, .js .contact,
  .js .panel [data-reveal] { opacity: 1; }
}

/* ==========================================================================
   Scroll hint — floating arrow shown while more content sits below the fold
   (styling and hover bounce are proposals)
   ========================================================================== */

.scroll-hint {
  position: fixed;
  left: 50%; bottom: 24px;
  z-index: 5;
  width: 32px; height: 32px;
  margin-left: -16px;
  display: grid; place-items: center;
  border: 0; border-radius: 50%;
  background: var(--primary); color: #fff;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.18);
  cursor: pointer;
  opacity: 0; visibility: hidden; transform: translateY(12px);
  transition: opacity 0.3s var(--ease-out), transform 0.3s var(--ease-out), visibility 0s 0.3s, background-color 0.2s;
}
.scroll-hint.is-visible {
  opacity: 1; visibility: visible; transform: translateY(0);
  transition: opacity 0.3s var(--ease-out), transform 0.3s var(--ease-out), visibility 0s, background-color 0.2s;
}
.scroll-hint svg { width: 16px; height: 16px; }
.scroll-hint:hover { background: var(--word-1); }
.scroll-hint:hover svg { animation: hint-bounce 0.9s ease-in-out infinite; }
.scroll-hint:focus-visible { outline-offset: 4px; border-radius: 50%; }

@keyframes hint-bounce {
  0%, 100% { transform: translateY(-2px); }
  50%      { transform: translateY(5px); }
}

@media (prefers-reduced-motion: reduce) {
  .scroll-hint:hover svg { animation: none; }
}

/* ==========================================================================
   Mobile (<900px) — About is from Figma (390px); Work / Play adapted
   ========================================================================== */

@media (max-width: 899px) {
  .page { max-width: none; }

  .hero {
    height: auto; min-height: var(--vh);
    display: flex; flex-direction: column; gap: 32px;
    padding: 28px 24px 0;
    overflow: hidden; /* the decorative words may run past the screen edge */
  }
  .hero__logo { position: static; width: 32px; height: 44px; }
  .hero__logo img { width: 32px; height: 44px; }

  .hero__canvas {
    position: static; height: auto; flex: 1;
    display: flex; flex-direction: column; justify-content: center;
  }
  .hero__words { left: -5px; top: -5px; width: 347px; }
  body { overflow-x: clip; }
  .hero__word {
    position: static; display: block; left: auto; top: auto;
    font-size: 70px; line-height: 50px;
  }
  .hero__word .punct { font-size: 70px; }

  .hero__intro {
    position: relative; left: auto; top: auto; width: auto; height: auto;
    display: flex; flex-direction: column; gap: 16px; padding-top: 16px;
  }
  .hero__greeting { font-size: 68px; line-height: 64px; white-space: normal; }
  .hero__statement { position: static; width: auto; font-size: 30px; line-height: 32px; }
  .contact { position: relative; left: auto; top: auto; gap: 0; margin-left: -8px; }
  .contact__link { width: 40px; height: 36px; }
  .contact-line { position: static; }
  .contact__link img { height: 20px; }
  .contact__link:first-child img { height: 28px; }

  .hero__divider { position: static; width: 100%; height: 1px; transform: none; }

  .stage {
    display: block; padding: 16px 0 0; min-height: 0;
  }
  .nav {
    flex-direction: row; justify-content: space-between; align-items: center;
    padding: 16px 24px 12px;
    font-size: 36px; line-height: 36px;
    top: 0; z-index: 4;
    background: var(--bg); /* content scrolls underneath the pinned nav */
  }
  .nav__link:hover { transform: none; }

  .panels { padding: 28px 24px 64px; }

  .tiles { grid-template-columns: 1fr; row-gap: 40px; }
  .tile--offset { margin-top: 0; }
  .tile__media { border-radius: 32px; }

  .panel--about { gap: 64px; }
  .section-heading { font-size: 40px; font-weight: 400; }
  .about-bio__grid { display: flex; flex-direction: column; margin-top: 24px; gap: 32px; }
  .about-bio__text { gap: 24px; max-width: none; }
  .about-bio__text, .about-philosophies__intro, .card__strap, .card__body { line-height: 28px; }
  .portrait { align-self: center; width: 220px; height: 316.8px; margin-top: 0; order: 1; }
  .about-philosophies__intro { margin-top: 24px; }
  .cards { grid-template-columns: 1fr; row-gap: 16px; margin-top: 32px; }
  .card { min-height: 0; padding: 20px; gap: 16px; }
  .card__body { margin-top: 0; }
  .card__title { margin-bottom: -12px; } /* 4px gap to strapline, per Figma */

  .footer { height: 80px; padding-left: 24px; }
  .footer__copy { line-height: 24px; }
}
