/* ==========================================================================
   Eric C. W. FUNG — CV website
   Rebuilt from the Figma file, canvas "ver_3 (Final Version)".

   HOW THIS FILE IS ORGANISED
   1. Design tokens   — the colours / sizes lifted straight out of Figma
   2. Reset + base    — sane defaults
   3. Page shell      — background glow, outer padding, vertical rhythm
   4. Sections        — hero, about, cards, projects, connect
   5. Desktop         — everything above is the 402px mobile frame;
                        the @media block at the end is the 1440px frame
   6. Print           — so Cmd/Ctrl+P gives a clean PDF resume
   ========================================================================== */

/* ── 1. Design tokens ───────────────────────────────────────────────────── */
:root {
  /* Colours, exactly as in the Figma file */
  --ink:    #1E1E1E;          /* all body copy and the card borders   */
  --bg:     #EAEAEA;          /* page background                      */
  --accent: #385C6B;          /* the "Connect" wordmark + arrow       */

  /* The background ellipse in Figma is this colour at 73% alpha, on a paint
     set to 55% opacity → 0.73 × 0.55 ≈ 0.40 effective. Turn this down if the
     spotlight feels too strong. */
  --glow: rgba(56, 92, 110, 0.40);

  /* Diameter of the glow, and where its centre sits. assets/js/glow.js
     overwrites the two positions to follow the mouse; these defaults centre
     it, which is what touch devices and reduced-motion users get. */
  --glow-size: clamp(340px, 55vmin, 660px);
  --glow-x: 50vw;
  --glow-y: 50vh;

  /* Type scale: base 16, ratio 1.2 — the scale on the Typescale frame.
     11 · 13 · 16 · 19 · 23 · 28 · 33 · 40 · 48 · 57 · 69 · 83 · 99 */
  --fs-body:    1rem;         /* 16px */
  --fs-heading: 1.438rem;     /* 23px */

  /* Connect interpolates between the mobile (402px) and desktop (1440px)
     frames — 57px → 99px — so it never jumps at the breakpoint. */
  --fs-connect: clamp(2.5rem,  calc(2.544rem + 4.046vw), 6.188rem);

  /* The name must sit on ONE line at every width. "Eric C. W. FUNG" renders
     7.5x the font size wide, so the size is tied to the available width
     rather than the design's fixed 83px. It reaches 83px — the Figma value —
     at 671px and holds there, so desktop is unchanged; narrower screens step
     down instead of wrapping. */
  --fs-name:    clamp(1.75rem, calc(12.7vw - 4.16px), 5.188rem);

  /* The role is sized separately because "INTERACTION" is the longest word on
     the page that cannot wrap: it renders 6.5x the font size wide, against
     4.75x for "DESIGNER". These values are solved from that ratio so the word
     always fits its column — here, the full content width. See the desktop
     block for the wider case, where the 265px tag column eats into it. */
  --fs-role:    clamp(2.25rem, 13.2vw, 3.4375rem);   /* 36px … 55px */

  --lh-tight:   1;            /* Figma "1.0 RAW" — the big display type   */
  --lh-body:    1.5;          /* Figma "100%"    — Poppins' natural lead  */
  --lh-connect: 1.05;         /* Figma 57px type on a 60px line           */

  --w-light:  300;
  --w-medium: 500;
  --w-semi:   600;

  /* Mobile frame spacing */
  --pad-x:    16px;
  --pad-y:    40px;
  --gap-body: 72px;           /* between the main blocks */
  --gap-card: 40px;           /* between cards          */
  --card-pad: 8px;
}

/* ── 2. Reset + base ────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

html, body { overflow-x: clip; }   /* the glow is wider than the viewport */

body {
  margin: 0;
  position: relative;
  background: var(--bg);
  color: var(--ink);
  font-family: "Poppins", system-ui, -apple-system, "Segoe UI", sans-serif;
  font-weight: var(--w-light);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, p, ul, figure, address { margin: 0; }
ul { padding: 0; list-style: none; }
address { font-style: normal; }
img { display: block; max-width: 100%; height: auto; }

a { color: inherit; text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 3px; }
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

/* Keyboard-only shortcut past the hero */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 10;
  padding: 12px 16px;
  background: var(--ink);
  color: var(--bg);
  font-weight: var(--w-semi);
}
.skip-link:focus { left: 0; }

/* ── 3. Page shell ──────────────────────────────────────────────────────── */

/* The soft teal spotlight, derived from the blurred ellipse in the Figma file
   but reproduced as a radial gradient — no image to download.

   `fixed` pins the layer to the viewport rather than the document, which is
   what lets it track the cursor (pointer coordinates are viewport-relative)
   and also means it can never add to the page's scroll size. `overflow: clip`
   keeps the circle from spilling out and creating a horizontal scrollbar. */
.page-glow {
  position: fixed;
  inset: 0;
  overflow: clip;
  pointer-events: none;   /* never intercepts clicks or text selection */
  z-index: 0;
}
.page-glow::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: var(--glow-size);
  height: var(--glow-size);
  background: radial-gradient(circle closest-side,
              var(--glow), rgba(56, 92, 110, 0) 100%);
  /* First translate moves the circle's top-left corner to the tracked point,
     the second re-centres the circle on it (percentages here are of the
     element's own size). */
  transform: translate(var(--glow-x), var(--glow-y)) translate(-50%, -50%);
  will-change: transform;
}

/* Belt and braces: if the OS asks for reduced motion the script bails out, but
   pin the glow anyway in case it was already moving. */
@media (prefers-reduced-motion: reduce) {
  .page-glow::before { transition: none; }
}

.page {
  position: relative;         /* sits above the glow */
  z-index: 1;
  max-width: 1440px;
  margin-inline: auto;
  padding: var(--pad-y) var(--pad-x);
}

/* Top bar: "RESUME" left, "Hong Kong" right */
.topbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  margin-bottom: 56px;
}
.topbar__label {
  font-weight: var(--w-semi);
  line-height: var(--lh-body);
}
.topbar__label--end { text-align: right; }

/* The main vertical rhythm */
.body-txt {
  display: flex;
  flex-direction: column;
  gap: var(--gap-body);
}

/* ── 4. Sections ────────────────────────────────────────────────────────── */

/* -- hero ---------------------------------------------------------------- */
.hero {
  display: flex;
  flex-direction: column;
  gap: var(--gap-body);
}
.hero__intro {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.hero__name {
  font-size: var(--fs-name);
  font-weight: var(--w-medium);
  line-height: var(--lh-tight);
  letter-spacing: 0;
}
.hero__media {
  display: flex;
  flex-direction: column;
  gap: 24px;
}
.hero__img img {
  width: 100%;
  height: 248px;
  object-fit: cover;
}
.contact {
  display: flex;
  flex-direction: column;
  gap: 8px;
  text-align: right;
}
.contact__line { line-height: var(--lh-tight); }

.hero__title-row {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 24px;
}
.hero__role {
  order: -1;                  /* mobile puts the role above the tags */
  font-size: var(--fs-role);
  font-weight: var(--w-medium);
  line-height: var(--lh-tight);
  text-align: right;
}
.tags {
  display: flex;
  flex-direction: column;
  gap: 8px;
  text-align: right;
}
.tags li { line-height: var(--lh-tight); }

/* -- scroll cue --------------------------------------------------------- */
.arrow-row {
  display: flex;
  justify-content: center;
}
.arrow-link {
  display: block;
  padding: 14px;
  line-height: 0;
}
.arrow-link:hover { text-decoration: none; }
.arrow {
  display: block;
  width: 56px;
  height: 56px;
  fill: var(--ink);
}
/* Sized to the rotated bounding box (the arrow itself is 58px on its own
   axis, matching Figma; 58 × √2 ≈ 83 across the box). */
.arrow--diag {
  width: 83px;
  height: 83px;
  flex: none;
  fill: var(--accent);
  opacity: 0.74;
}

/* -- about ------------------------------------------------------------- */
.about {
  display: flex;
  flex-direction: column;
  gap: 24px;
  scroll-margin-top: 24px;
}
.section-heading {
  font-size: var(--fs-heading);
  font-weight: var(--w-semi);
  line-height: var(--lh-body);
}
.about__txt {
  display: flex;
  flex-direction: column;
  gap: 1.5em;
}

/* -- cards ------------------------------------------------------------- */
.cards {
  display: flex;
  flex-direction: column;
  gap: var(--gap-card);
}
.cards__row {
  display: flex;
  flex-direction: column;
  gap: var(--gap-card);
}
.card {
  display: flex;
  flex-direction: column;
  gap: 24px;
  border: 1px solid var(--ink);
  padding: var(--card-pad);
}
.card__body {
  display: flex;
  flex-direction: column;
  gap: 56px;
}
.entry {
  display: flex;
  flex-direction: column;
}
.entry__role,
.entry__meta,
.entry__lead,
.entry__rule {
  font-size: var(--fs-body);
  font-weight: var(--w-light);
  line-height: var(--lh-body);
}
.entry__role--strong { font-weight: var(--w-semi); }
.entry__lead { margin-top: 8px; }

/* Award project names link out to the UX Design Awards entry. Body links are
   otherwise underline-on-hover only, which would leave these undiscoverable,
   so they carry a permanent underline. */
.proj-link {
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}
.proj-link:hover {
  color: var(--accent);
  text-decoration-thickness: 2px;
}
/* The literal "-" divider the design uses inside the Education entries */
.entry__rule { margin-block: 8px; }

.bullets,
.plain {
  display: flex;
  flex-direction: column;
  gap: 24px;
}
.bullets { margin-top: 24px; }
.plain   { margin-top: 0; }
.skills  { font-weight: var(--w-light); }

/* -- projects ---------------------------------------------------------- */
.rule {
  border: 0;
  border-top: 1px solid var(--ink);
  margin: 0;
}
.projects,
.cta {
  display: flex;
  flex-direction: column;
  gap: 24px;
}
.projects__inner {
  display: flex;
  flex-direction: column;
  gap: 24px;
}
/* The thumbnails butt up against each other — no gaps, exactly as designed. */
.proj-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0;
}
.proj-grid img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
}

/* -- connect ----------------------------------------------------------- */
.cta { gap: 8px; }
.cta__link {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
}
.cta__link:hover { text-decoration: none; }
.cta__link:hover .cta__word { text-decoration: underline; text-underline-offset: 6px; }
.cta__word {
  font-size: var(--fs-connect);
  font-weight: var(--w-semi);
  line-height: var(--lh-connect);
  color: var(--accent);
  opacity: 0.74;
}

/* ── 4b. Below the 402px design frame ───────────────────────────────────── */
/* "PRODUCT", "DESIGNER" and "Connect" are single words that cannot wrap, so
   on phones narrower than the Figma frame they have to shrink with the
   viewport or they would spill off the edge. Sizes above 402px are untouched,
   which keeps both reference frames pixel-accurate. */
@media (max-width: 401px) {
  :root {
    --fs-connect: 12vw;
  }
  .arrow--diag {
    width: 17vw;
    height: 17vw;
  }
}

/* ── 5. Desktop — the 1440px Figma frame ────────────────────────────────── */
@media (min-width: 900px) {
  :root {
    --pad-x:    80px;
    --pad-y:    32px;
    --gap-body: 96px;
    --gap-card: 56px;
    --card-pad: 16px;
    --lh-connect: 1.515;      /* Figma 99px type on a 150px line */

    /* Here the role shares its row with the 265px tag column, so it only has
       (page width - 441px) to play with. Solved so "INTERACTION" fits at the
       900px breakpoint, reaching the design's 99px at 1440 and stopping there
       (the page itself stops growing at 1440). */
    --fs-role: clamp(4.125rem, calc(0.769rem + 6.02vw), 6.188rem);  /* 66px … 99px */
  }

  .topbar { margin-bottom: 32px; }

  /* Name, then portrait + contact side by side */
  .hero__intro { gap: 24px; }
  .hero__media {
    flex-direction: row;
    gap: 24px;
  }
  .hero__img,
  .contact { flex: 1 1 0; }
  .contact {
    display: flex;
    justify-content: flex-end;   /* contact details sit on the baseline
                                    of the portrait, as in the design */
    min-height: 248px;
  }

  /* Tags top-left, role on the right — both children sit at y=0 in Figma,
     so the tag list lines up with the first line of the role. */
  .hero__title-row {
    flex-direction: row;
    align-items: flex-start;
    gap: 16px;
  }
  .hero__role {
    order: 0;
    flex: 1 1 auto;
  }
  .tags {
    flex: 0 0 265px;
    text-align: left;
    padding-block: 10px;
  }

  /* Heading left, paragraph right — and right-aligned, per the design */
  .about {
    flex-direction: row;
    gap: 24px;
  }
  .about .section-heading,
  .about__txt { flex: 1 1 0; }
  .about__txt { text-align: right; }

  /* Experience | Education, then Awards | Certifications | Skills.
     Cards keep their natural height and hang from the top, as in Figma. */
  .cards__row--2,
  .cards__row--3 {
    flex-direction: row;
    align-items: flex-start;
  }
  .cards__row--2 > .card { flex: 1 1 0; }
  .cards__row--3 > .card { flex: 1 1 0; }

  /* Heading on the left, thumbnails flush right */
  .projects__inner {
    flex-direction: row;
    gap: 16px;
  }
  .projects__inner .section-heading { flex: 0 0 94px; }
  /* Six across, 160px each at 1440 as designed, but allowed to shrink so the
     row still fits between the breakpoint and ~1280px. */
  .proj-grid {
    flex: 1 1 auto;
    min-width: 0;
    grid-template-columns: repeat(6, minmax(0, 160px));
    justify-content: end;
  }

  .arrow--diag {          /* 91px arrow → 91 × √2 ≈ 129px box */
    width: 129px;
    height: 129px;
  }
}

/* ── 6. Print — Ctrl/Cmd+P gives a clean PDF resume ─────────────────────── */
@media print {
  :root {
    --pad-x: 0;
    --pad-y: 0;
    --gap-body: 24pt;
    --gap-card: 12pt;
  }
  @page { margin: 14mm; }

  html, body {
    background: #fff;
    color: #000;
    font-size: 10pt;
  }
  .page-glow,
  .arrow-row,
  .skip-link { display: none; }

  .page { max-width: none; }

  /* Keep a card from being split across two sheets */
  .card, .entry, .proj-grid { break-inside: avoid; }

  .hero__name    { font-size: 26pt; }
  .hero__role    { font-size: 22pt; }
  .cta__word     { font-size: 20pt; color: #000; opacity: 1; }
  .arrow--diag   { display: none; }
  .section-heading { font-size: 13pt; }

  /* On paper "Connect" is not clickable, so name the address */
  .cta__link::after { content: " — ericfcw@gmail.com"; font-size: 10pt; }
}
