/* ============================================================
   Chelsey Huang — personal homepage
   Structure: academic index. Surface: neutral, typographic.
   Colour appears only on things you can act on.
   ============================================================ */

/* ---------- tokens ---------- */
:root {
  --bg:      oklch(0.985 0     0);
  --surface: oklch(0.962 0.002 30);
  --ink:     oklch(0.205 0     0);
  --muted:   oklch(0.472 0     0);
  --rule:    oklch(0.898 0     0);
  --rule-sf: oklch(0.930 0     0);
  --accent:  oklch(0.545 0.185 30);
  --accent-q:oklch(0.545 0.185 30 / 0.10);
  --focus:   oklch(0.545 0.185 30);

  /* Latin fallbacks sit ahead of the CJK faces on purpose: during the
     font-display:swap window the Latin text must not be set in PingFang,
     whose ASCII punctuation is full-width and reflows the whole line. */
  --sans: "Schibsted Grotesk", -apple-system, "Helvetica Neue", Arial,
          "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
  --mono: "Spline Sans Mono", ui-monospace, "SF Mono", Menlo, monospace;

  --shell: 68rem;
  --prose: 66ch;

  /* The page grid. Left column carries the portrait, section headings and
     dates; the right column carries everything you read. Both the hero and
     every section run on it, so the page has one left edge, not six. */
  --col: 16.25rem;
  --gutter: 3rem;
  --sub: 8.5rem;      /* label column inside the right-hand column */

  --z-nav: 100;
  --z-menu: 200;

  --ease: cubic-bezier(0.16, 1, 0.3, 1);   /* ease-out-expo-ish */
  --bar: 3.25rem;

  color-scheme: light;
}

/* Dark comes from the system preference unless the toggle has pinned a
   theme, so both the media query and the explicit attribute are declared. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg:      oklch(0.172 0.004 285);
    --surface: oklch(0.215 0.005 285);
    --ink:     oklch(0.935 0     0);
    --muted:   oklch(0.702 0     0);
    --rule:    oklch(0.302 0.004 285);
    --rule-sf: oklch(0.345 0.004 285);
    --accent:  oklch(0.735 0.150 40);
    --accent-q:oklch(0.735 0.150 40 / 0.14);
    --focus:   oklch(0.735 0.150 40);
    color-scheme: dark;
  }
}

:root[data-theme="dark"] {
  --bg:      oklch(0.172 0.004 285);
  --surface: oklch(0.215 0.005 285);
  --ink:     oklch(0.935 0     0);
  --muted:   oklch(0.702 0     0);
  --rule:    oklch(0.302 0.004 285);
  --rule-sf: oklch(0.345 0.004 285);
  --accent:  oklch(0.735 0.150 40);
  --accent-q:oklch(0.735 0.150 40 / 0.14);
  --focus:   oklch(0.735 0.150 40);
  color-scheme: dark;
}

/* ---------- 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; } }

body {
  margin: 0;
  padding-top: var(--bar);
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 1.0625rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3 { margin: 0; font-weight: 700; text-wrap: balance; line-height: 1.15; }
p { margin: 0; text-wrap: pretty; }
ul, ol, dl, dd { margin: 0; padding: 0; }
li { list-style: none; }
img { max-width: 100%; height: auto; display: block; }

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 0.18em; }

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

::selection { background: var(--accent-q); }

.skip {
  position: absolute; left: 0.5rem; top: -4rem;
  z-index: calc(var(--z-menu) + 1);
  padding: 0.55rem 0.9rem;
  background: var(--ink); color: var(--bg);
  font-size: 0.875rem; font-weight: 600;
  transition: top 0.18s var(--ease);
}
.skip:focus { top: 0.5rem; text-decoration: none; }

/* ---------- top bar ---------- */
.topbar {
  position: fixed; inset: 0 0 auto 0;
  z-index: var(--z-nav);
  height: var(--bar);
  background: var(--bg);
  border-bottom: 1px solid var(--rule);
}

.topbar-inner {
  max-width: var(--shell);
  margin: 0 auto;
  padding: 0 1.5rem;
  height: 100%;
  display: flex; align-items: center; gap: 1.5rem;
}

.brand {
  color: var(--ink);
  font-weight: 700;
  font-size: 0.9375rem;
  letter-spacing: -0.012em;
  white-space: nowrap;
  display: flex; align-items: baseline; gap: 0.4rem;
}
.brand:hover { text-decoration: none; }

.navlist {
  display: flex; align-items: center; gap: 1.35rem;
  margin-left: auto;
  font-size: 0.875rem;
}
.navlist a {
  color: var(--muted);
  padding: 0.25rem 0;
  border-bottom: 1.5px solid transparent;
  transition: color 0.16s var(--ease), border-color 0.16s var(--ease);
}
.navlist a:hover { color: var(--ink); text-decoration: none; }
.navlist a[aria-current="true"] { color: var(--ink); border-bottom-color: var(--accent); }

.theme-btn {
  flex: none;
  width: 2rem; height: 2rem;
  display: grid; place-items: center;
  padding: 0; margin-left: 0.25rem;
  background: none; border: 1px solid var(--rule);
  color: var(--muted); cursor: pointer;
  transition: color 0.16s var(--ease), border-color 0.16s var(--ease);
}
.theme-btn:hover { color: var(--ink); border-color: var(--muted); }
.theme-btn svg { width: 1rem; height: 1rem; }
.ico-moon { display: none; }
:root[data-theme="dark"] .ico-sun { display: none; }
:root[data-theme="dark"] .ico-moon { display: block; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .ico-sun { display: none; }
  :root:not([data-theme="light"]) .ico-moon { display: block; }
}

.menu-btn { display: none; }

/* ---------- layout shell ---------- */
.hero, .sec {
  max-width: var(--shell);
  margin: 0 auto;
  padding-inline: 1.5rem;
}
.sec { scroll-margin-top: calc(var(--bar) + 1rem); }

/* ---------- hero ---------- */
.hero {
  display: grid;
  grid-template-columns: var(--col) 1fr;
  gap: var(--gutter);
  align-items: start;
  padding-block: clamp(3rem, 2rem + 4vw, 5.5rem) clamp(2.5rem, 2rem + 3vw, 4rem);
}

.hero-portrait img {
  width: 100%;
  aspect-ratio: 3 / 4;
  object-fit: cover;
}

.hero-id h1 {
  font-size: clamp(2.1rem, 1.4rem + 2.6vw, 3.1rem);
  letter-spacing: -0.032em;
  margin-bottom: 0.65rem;
}
/* The legal name, set smaller and quieter so it reads as a parenthetical
   rather than a second headline. */
.hero-id h1 .alt {
  display: block;
  margin-top: 0.3rem;
  font-size: 0.42em;
  font-weight: 500;
  color: var(--muted);
  letter-spacing: -0.012em;
}

.hero-role { font-size: 1.125rem; font-weight: 600; margin-bottom: 0.35rem; }
.hero-line {
  color: var(--muted);
  max-width: 46ch;
  margin-bottom: 1.75rem;
}

.idlist {
  display: grid;
  gap: 0.4rem 0;
  border-top: 1px solid var(--rule);
  padding-top: 1rem;
  margin-bottom: 1.65rem;
  font-size: 0.9375rem;
}
.idlist > div { display: grid; grid-template-columns: var(--sub) 1fr; gap: 1.5rem; }
.idlist dt { color: var(--muted); }
.idlist dd { margin: 0; }

.hero-links {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 1rem 1.25rem;
  font-size: 0.9375rem;
}
.socials { display: flex; flex-wrap: wrap; align-items: center; gap: 0.55rem 1.25rem; }
.socials a { white-space: nowrap; }

.hero-links .cta {
  font-weight: 600;
  margin-left: auto;
  border: 1px solid var(--accent);
  padding: 0.45rem 0.95rem;
  transition: background-color 0.18s var(--ease), color 0.18s var(--ease);
}
.hero-links .cta:hover { background: var(--accent); color: var(--bg); text-decoration: none; }

/* ---------- section frame ----------
   Every section runs on the same two-column grid as the hero: the portrait,
   the section headings and the dates all sit in the left column, everything
   you actually read sits in the right one. That gives the page one continuous
   left edge at each of two positions instead of a different indent per block. */
.sec {
  display: grid;
  /* minmax(0,1fr), not 1fr: a grid track's automatic minimum is its content's
     min-content size, and the nowrap install commands would otherwise blow the
     column past the viewport instead of scrolling inside their own box. */
  grid-template-columns: var(--col) minmax(0, 1fr);
  gap: 0 var(--gutter);
  align-content: start;
  padding-block: clamp(2.5rem, 2rem + 2vw, 3.75rem);
}
.sec + .sec { border-top: 1px solid var(--rule); }

.sec > h2 {
  grid-column: 1;
  font-size: clamp(1.4rem, 1.2rem + 0.7vw, 1.8rem);
  letter-spacing: -0.024em;
  margin-bottom: 1.5rem;
}
.sec > *:not(h2) { grid-column: 2; min-width: 0; }

.sec-note {
  color: var(--muted);
  max-width: var(--prose);
  font-size: 0.9375rem;
  margin-bottom: 2rem;
}

.sec-more { margin-top: 2rem; font-size: 0.9375rem; font-weight: 600; }

/* ---------- about ---------- */
.prose { max-width: var(--prose); display: grid; gap: 1rem; }
.prose strong { font-weight: 700; }

/* ---------- now / log ---------- */
.log { display: grid; }
.log li {
  display: grid;
  grid-template-columns: var(--sub) 1fr;
  gap: 1.5rem;
  padding-block: 0.9rem;
  border-top: 1px solid var(--rule);
}
.log li:last-child { border-bottom: 1px solid var(--rule); }
/* tnum only here, where a column of dates has to line up. Applying it
   globally also swaps in tabular comma/period glyphs, which are wide and
   centred, and they wreck ordinary prose and domain names. */
.log time {
  color: var(--muted);
  font-size: 0.875rem;
  font-variant-numeric: tabular-nums;
  padding-top: 0.15rem;
  white-space: nowrap;
}
.log p { max-width: 62ch; }

/* ---------- press / events ----------
   Both run the log's two-column rhythm: who and when on the left, what you
   read on the right. Their left column is the same shape either way — an
   identifying line (the publication, or the capacity you were there in) over
   a muted date — so the two lists share one set of rules and stay in step. */
.press li, .events li {
  display: grid;
  grid-template-columns: var(--sub) 1fr;
  gap: 1.5rem;
  padding-block: 1rem;
  border-top: 1px solid var(--rule);
}
.press li:last-child, .events li:last-child { border-bottom: 1px solid var(--rule); }

.pr-src, .ev-when {
  display: grid;
  align-content: start;   /* otherwise the two rows stretch to the headline's height */
  gap: 0.1rem;
  font-size: 0.875rem;
  padding-top: 0.1rem;
}
.pr-pub, .ev-role { font-weight: 600; }
.press time, .events time {
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.pr-title, .ev-name {
  display: block;
  font-weight: 600;
  letter-spacing: -0.014em;
  max-width: 56ch;
}
.pr-body p, .ev-body p {
  margin-top: 0.35rem;
  color: var(--muted);
  font-size: 0.9375rem;
  max-width: 62ch;
}

/* ---------- skills ---------- */
.grp {
  font-size: 0.9375rem;
  letter-spacing: 0.005em;
  margin: 2.5rem 0 0.25rem;
  padding-bottom: 0.6rem;
  border-bottom: 1px solid var(--ink);
}
.grp:first-of-type { margin-top: 0; }
.grp-note { display: block; font-weight: 400; color: var(--muted); font-size: 0.8125rem; margin-top: 0.2rem; }

.skills li {
  padding-block: 1.15rem;
  border-bottom: 1px solid var(--rule);
}

.sk-head {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.5rem 0.9rem;
  margin-bottom: 0.35rem;
}
.sk-name { font-weight: 700; font-size: 1.0625rem; letter-spacing: -0.014em; }
.sk-tags { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.sk-tags span {
  color: var(--muted);
  font-size: 0.75rem;
  line-height: 1.4;
  padding: 0.12rem 0.45rem;
  border: 1px solid var(--rule);
}
.sk-desc { color: var(--muted); max-width: 68ch; font-size: 0.9375rem; }
.sk-up { font-size: 0.8125rem; color: var(--muted); margin-top: 0.35rem; }

.cmd {
  display: flex; align-items: stretch;
  margin-top: 0.75rem;
  background: var(--surface);
  border: 1px solid var(--rule-sf);
  max-width: 100%;
}
.cmd code {
  flex: 1 1 auto;
  min-width: 0;
  overflow-x: auto;
  white-space: nowrap;
  padding: 0.5rem 0.7rem;
  font-family: var(--mono);
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--ink);
  scrollbar-width: thin;
}
.copy {
  flex: none;
  padding: 0 0.85rem;
  background: none;
  border: 0;
  border-left: 1px solid var(--rule-sf);
  color: var(--muted);
  font: inherit; font-size: 0.8125rem; font-weight: 600;
  cursor: pointer;
  transition: color 0.16s var(--ease), background-color 0.16s var(--ease);
}
.copy:hover { color: var(--ink); background: var(--accent-q); }
.copy[data-done="1"] { color: var(--accent); }

/* ---------- building / ventures ---------- */
.entries li {
  padding-block: 1.2rem;
  border-bottom: 1px solid var(--rule);
}
.entries li:first-child { border-top: 1px solid var(--rule); }

.ent-head {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.4rem 1rem;
  margin-bottom: 0.3rem;
}
.ent-name { font-weight: 700; font-size: 1.0625rem; letter-spacing: -0.014em; color: var(--ink); }
a.ent-name { color: var(--accent); }
.ent-role { color: var(--muted); font-size: 0.875rem; }
.entries p { color: var(--muted); max-width: var(--prose); font-size: 0.9375rem; }

.chips {
  display: flex; flex-wrap: wrap; gap: 0.4rem;
  margin-top: 0.85rem;
}
.chips li {
  padding: 0.28rem 0.6rem;
  border: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  font-size: 0.8125rem;
  line-height: 1.45;
}
.chips li span { color: var(--muted); }

/* ---------- contact ---------- */
.sec-contact { padding-bottom: clamp(3rem, 2rem + 3vw, 4.5rem); }
.contact-lead { max-width: 52ch; color: var(--muted); margin-bottom: 1.1rem; }
.contact-mail {
  font-size: clamp(1.2rem, 0.9rem + 1.4vw, 1.9rem);
  font-weight: 700;
  letter-spacing: -0.026em;
  margin-bottom: 1.4rem;
  overflow-wrap: anywhere;
}
.contact-links { display: flex; flex-wrap: wrap; gap: 1.25rem; font-size: 0.9375rem; }

/* ---------- footer ---------- */
.foot {
  max-width: var(--shell);
  margin: 0 auto;
  padding: 1.5rem;
  border-top: 1px solid var(--rule);
  display: flex; flex-wrap: wrap; justify-content: space-between; gap: 0.75rem;
  color: var(--muted);
  font-size: 0.875rem;
}

/* ---------- page load ---------- */
@media (prefers-reduced-motion: no-preference) {
  .hero-portrait { animation: rise 0.7s var(--ease) both; }
  .hero-id > *   { animation: rise 0.65s var(--ease) both; }
  .hero-id > :nth-child(1) { animation-delay: 0.04s; }
  .hero-id > :nth-child(2) { animation-delay: 0.08s; }
  .hero-id > :nth-child(3) { animation-delay: 0.12s; }
  .hero-id > :nth-child(4) { animation-delay: 0.16s; }
  .hero-id > :nth-child(5) { animation-delay: 0.20s; }
}
@keyframes rise {
  from { opacity: 0; transform: translateY(0.6rem); }
  to   { opacity: 1; transform: none; }
}

/* ============================================================
   responsive
   ============================================================ */

@media (max-width: 60rem) {
  .navlist { gap: 1rem; font-size: 0.8125rem; }
  .hero { grid-template-columns: 13rem 1fr; gap: 2.25rem; }
}

@media (max-width: 48rem) {
  .topbar-inner { padding-inline: 1.15rem; gap: 0.75rem; }

  .menu-btn {
    display: flex; align-items: center; gap: 0.45rem;
    margin-left: auto;
    padding: 0.35rem 0.6rem;
    background: none; border: 1px solid var(--rule);
    color: var(--ink); font: inherit; font-size: 0.8125rem; font-weight: 600;
    cursor: pointer;
  }
  .menu-bars {
    width: 0.9rem; height: 0.55rem;
    border-top: 1.5px solid currentColor;
    border-bottom: 1.5px solid currentColor;
  }

  .navlist {
    position: fixed; inset: var(--bar) 0 auto 0;
    z-index: var(--z-menu);
    display: none;
    flex-direction: column; align-items: stretch; gap: 0;
    margin: 0;
    background: var(--bg);
    border-bottom: 1px solid var(--rule);
    font-size: 1rem;
  }
  .navlist[data-open="1"] { display: flex; }
  .navlist li + li { border-top: 1px solid var(--rule); }
  .navlist a {
    display: block;
    padding: 0.8rem 1.15rem;
    border-bottom: 0;
    border-left: 2px solid transparent;
  }
  .navlist a[aria-current="true"] { border-left-color: var(--accent); }

  /* Below this width the left column can't hold a heading and a body column
     side by side, so the whole page grid collapses to one. */
  .hero, .sec {
    grid-template-columns: 1fr;
    gap: 1.6rem;
  }
  .hero { padding-block: 2.25rem 2rem; }
  .sec { gap: 0; }
  .sec > h2, .sec > *:not(h2) { grid-column: 1; }
  .hero-portrait { width: 10.5rem; }

  .idlist > div { grid-template-columns: 6.25rem 1fr; gap: 0.75rem; }
  .hero-links .cta { margin-left: 0; }

  .log li { grid-template-columns: 1fr; gap: 0.3rem; padding-block: 1rem; }
  .log time { padding-top: 0; }

  .press li, .events li { grid-template-columns: 1fr; gap: 0.35rem; }
  /* Source and date sit side by side once they no longer have a column of
     their own, so they read as one credit line above the headline. */
  .pr-src, .ev-when {
    display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.55rem;
    padding-top: 0;
  }
}

/* The RedNote wordmark is ~113px wider than a square glyph would be, which
   pushes the social row onto two lines below ~360px. Tighten rather than wrap:
   one line is the point of the row. */
@media (max-width: 30rem) {
  body { font-size: 1rem; }
  .hero, .sec, .foot { padding-inline: 1.15rem; }
  .idlist > div { grid-template-columns: 1fr; gap: 0; }
  .idlist dt { font-size: 0.8125rem; }
  .idlist { gap: 0.75rem 0; }
  .cmd { flex-direction: column; align-items: stretch; }
  .copy { border-left: 0; border-top: 1px solid var(--rule-sf); padding: 0.45rem; text-align: left; }
}

/* ---------- print ---------- */
@media print {
  .topbar, .theme-btn, .copy, .skip, .hero-links .cta { display: none !important; }
  body { padding-top: 0; font-size: 10.5pt; }
  .sec, .hero { padding-block: 0.75rem; max-width: none; }
  a { color: inherit; text-decoration: underline; }
  .sec + .sec { border-top: 1px solid #ccc; }
}
