/* ==========================================================================
   Yuhan Liu — personal site  ·  Concept "Plein air"
   --------------------------------------------------------------------------
   A centered portrait and intro over a wide, compact publication list.
   One sans-serif (Inter) for all text. Every paper gets one picture or looping
   video on its left, all in the same frame; papers are grouped by year.
   The color set is chosen by `data-palette` on <html> (see index.html).

   STRUCTURE
     1. Design tokens   (:root + palettes)   <- change colors / fonts / sizes here
     2. Base, background wash & grain
     3. Hero / bio (+ name seal)
     4. Section scaffolding
     5. Publications (+ year labels, media frame, TL;DR)
     6. Timeline (education / experience)
     7. News
     8. Footer & utilities
     9. Responsive
   ========================================================================== */

/* 1. ---------- DESIGN TOKENS --------------------------------------------- */
:root {
  /* Type — one sans for everything */
  --sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, sans-serif;
  --cjk:  "Noto Sans SC", "PingFang SC", sans-serif;          /* the name seal */

  /* Type scale */
  --fs-name:  clamp(2.1rem, 5vw, 2.6rem);
  --fs-h2:    1.3rem;
  --fs-title: 1.02rem;
  --fs-body:  1rem;
  --fs-small: 0.875rem;
  --fs-tiny:  0.8rem;
  --leading:  1.65;

  /* Layout */
  --maxw:      1000px;       /* page width (the publication list uses all of it) */
  --measure:   680px;        /* width of the intro, research and education text  */
  --radius:    14px;
  --radius-sm: 8px;
  --thumb-w:   220px;        /* publication picture/video width                  */
  --thumb-ar:  16 / 9;       /* the one frame shape every picture/video sits in  */
  --photo-w:   132px;        /* profile photo (round)                            */
  --speed:     0.4s;
}

/* Palettes. Each sets the same tokens; pick one with <html data-palette="…">.
   --mat is the color behind a `fit: "whole"` picture (white matches figures
   drawn on white, so the padding is invisible). */
:root,
[data-palette="plein-air"] {          /* warm light vs. cool shadow (original) */
  --bg-top:        #fdeede;   /* warm peach, top of the daylight wash  */
  --bg-bottom:     #fbf6ee;   /* settles into warm ivory               */
  --surface:       #f6ede1;   /* placeholder swatch                    */
  --ink:           #322a23;   /* primary text (warm near-black)        */
  --body:          #5f574c;   /* paragraph text, a touch softer        */
  --muted:         #8a7e6e;   /* author lists, captions                */
  --faint:         #b3a796;   /* TL;DR at rest (a pencil note)         */
  --accent:        #e8834e;   /* THE accent — golden-hour coral        */
  --accent-strong: #d8702f;   /* accent on hover                       */
  --accent-soft:   rgba(232, 131, 78, 0.14);
  --cool:          #8aa0c0;   /* the cool counterpoint (venue, years)  */
  --seal:          #e8834e;
  --line:          rgba(50, 42, 35, 0.10);
  --shadow:        rgba(50, 42, 35, 0.13);
  --glow:          rgba(232, 131, 78, 0.30);   /* portrait shadow      */
  --card:          rgba(255, 255, 255, 0.55);  /* hover highlight      */
  --chip:          #fffdf9;                    /* icon buttons, photo ring */
  --mat:           #ffffff;
  --grain:         0.5;
}
[data-palette="greyblue"] {           /* Morandi: grey-blue */
  --bg-top: #eeece8; --bg-bottom: #eeece8; --surface: #e2dfd9;
  --ink: #2f3337; --body: #4a4f55; --muted: #666b70; --faint: #7d8287;
  --accent: #4a6275; --accent-strong: #3a4e5e; --accent-soft: rgba(74, 98, 117, 0.12);
  --cool: #5a6c7b; --seal: #a05a50;
  --line: rgba(47, 51, 55, 0.13); --shadow: rgba(47, 51, 55, 0.12); --glow: rgba(47, 51, 55, 0.16);
  --card: rgba(255, 255, 255, 0.4); --chip: #f6f5f2; --mat: #ffffff; --grain: 0.35;
}
[data-palette="sage"] {               /* Morandi: sage green */
  --bg-top: #ecebe4; --bg-bottom: #ecebe4; --surface: #e0dfd5;
  --ink: #30342c; --body: #4a4f44; --muted: #666a5f; --faint: #7c8075;
  --accent: #566650; --accent-strong: #44523f; --accent-soft: rgba(86, 102, 80, 0.12);
  --cool: #5e6b6e; --seal: #a05a50;
  --line: rgba(48, 52, 44, 0.13); --shadow: rgba(48, 52, 44, 0.12); --glow: rgba(48, 52, 44, 0.16);
  --card: rgba(255, 255, 255, 0.4); --chip: #f5f4ef; --mat: #ffffff; --grain: 0.35;
}
[data-palette="rose"] {               /* Morandi: dusty rose */
  --bg-top: #efe9e5; --bg-bottom: #efe9e5; --surface: #e4dbd5;
  --ink: #37302d; --body: #524945; --muted: #6e645e; --faint: #857a74;
  --accent: #87574f; --accent-strong: #6f463f; --accent-soft: rgba(135, 87, 79, 0.12);
  --cool: #6e6672; --seal: #9c5248;
  --line: rgba(55, 48, 45, 0.13); --shadow: rgba(55, 48, 45, 0.12); --glow: rgba(55, 48, 45, 0.16);
  --card: rgba(255, 255, 255, 0.4); --chip: #f7f3f0; --mat: #ffffff; --grain: 0.35;
}
[data-palette="sand"] {               /* Morandi: sand */
  --bg-top: #eeeae1; --bg-bottom: #eeeae1; --surface: #e2dccf;
  --ink: #36322a; --body: #4f493f; --muted: #6c655a; --faint: #837b6f;
  --accent: #75613f; --accent-strong: #5f4e31; --accent-soft: rgba(117, 97, 63, 0.12);
  --cool: #5f6a6b; --seal: #a05a50;
  --line: rgba(54, 50, 42, 0.13); --shadow: rgba(54, 50, 42, 0.12); --glow: rgba(54, 50, 42, 0.16);
  --card: rgba(255, 255, 255, 0.4); --chip: #f6f3ec; --mat: #ffffff; --grain: 0.35;
}

/* 2. ---------- BASE, BACKGROUND WASH & GRAIN ----------------------------- */
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100vh;
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--fs-body);
  line-height: var(--leading);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* the daylight wash — fixed so it stays put while scrolling */
  background: linear-gradient(180deg, var(--bg-top) 0%, var(--bg-bottom) 40%) fixed;
  background-color: var(--bg-bottom);
}

/* a faint canvas grain over everything (tactile, hand-made warmth) */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: var(--grain);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.035'/%3E%3C/svg%3E");
}

.page, .footer { position: relative; z-index: 1; }

.page {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: clamp(3rem, 8vw, 4.6rem) clamp(1rem, 4vw, 1.75rem) 1rem;
}

a { color: var(--accent); text-decoration: none; transition: color var(--speed) ease; }
a:hover, a:focus-visible { color: var(--accent-strong); }
p { margin: 0 0 0.9em; }
img, video { display: block; max-width: 100%; }
strong { font-weight: 600; }
em { font-style: italic; }

/* 3. ---------- HERO / BIO ------------------------------------------------ */
.hero { text-align: center; margin-bottom: 3.4rem; }

.hero__photo {
  position: relative;
  overflow: hidden;
  width: var(--photo-w);
  height: var(--photo-w);
  margin: 0 auto;
  border-radius: 50%;
  outline: 5px solid var(--chip);
  outline-offset: -1px;
  box-shadow: 0 12px 34px var(--glow);
}

.hero__name {
  font-size: var(--fs-name);
  font-weight: 600;
  letter-spacing: -0.025em;
  line-height: 1.1;
  margin: 1.1rem 0 0;
}
.hero__name .seal {
  display: inline-block;
  margin-left: 0.5rem;
  padding: 3px 7px;
  font-family: var(--cjk);
  font-size: 0.9rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  line-height: 1.5;
  color: #fff7f0;
  background: var(--seal);
  border-radius: 6px;
  vertical-align: 0.5em;
}
.hero__lede {
  font-size: 1.05rem;
  color: var(--muted);
  margin: 0.55rem 0 0;
}

/* The intro is a centered block, but its lines are justified (both edges
   straight) so every line starts at the same place and reads easily. */
.hero__bio {
  max-width: var(--measure);
  margin: 1.3rem auto 0;
  color: var(--body);
  text-align: justify;
  hyphens: auto;                  /* split only long words, to keep word gaps even */
  -webkit-hyphens: auto;
  hyphenate-limit-chars: 10 4 4;
}
.hero__bio p { margin-bottom: 0.7em; }
.hero__bio p:last-child { margin-bottom: 0; }
.hero__bio a { border-bottom: 1px solid var(--accent-soft); }
.hero__bio a:hover { border-color: var(--accent-strong); }

/* social icon buttons, centered under the intro */
.linkbar {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.7rem;
  margin-top: 1.4rem;
}
.linkbar a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.4rem;
  height: 2.4rem;
  color: var(--muted);
  background: var(--chip);
  border: 1px solid var(--line);
  border-radius: 50%;
  transition: color var(--speed) ease, background var(--speed) ease,
              border-color var(--speed) ease, transform var(--speed) ease;
}
.linkbar a:hover, .linkbar a:focus-visible {
  color: #fff;
  background: var(--accent);
  border-color: var(--accent);
  transform: translateY(-2px);
}
.linkbar svg { width: 1.15rem; height: 1.15rem; display: block; fill: currentColor; }

/* 4. ---------- SECTION SCAFFOLDING --------------------------------------- */
.section { max-width: var(--measure); margin: 0 auto 3rem; }
.section--wide { max-width: none; }         /* publications use the full page width */
.section__title {
  font-size: var(--fs-h2);
  font-weight: 600;
  letter-spacing: -0.01em;
  text-align: center;
  margin: 0;
}
.section__title::after {
  content: "";
  display: block;
  width: 42px;
  height: 3px;
  margin: 0.7rem auto 1.6rem;
  border-radius: 3px;
  background: var(--accent);
}
.prose {
  color: var(--body);
  text-align: justify;          /* same treatment as the intro */
  hyphens: auto;                  /* split only long words, to keep word gaps even */
  -webkit-hyphens: auto;
  hyphenate-limit-chars: 10 4 4;
}
.prose :last-child { margin-bottom: 0; }

/* 5. ---------- PUBLICATIONS ---------------------------------------------- */
.pubs { display: flex; flex-direction: column; gap: 0.3rem; }

/* year label: a cool-toned number with a hairline running to the right */
.pubs__year {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  margin: 1.4rem 0 0.3rem;
  font-size: var(--fs-small);
  font-weight: 600;
  letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums;
  color: var(--cool);
}
.pubs__year:first-child { margin-top: 0; }
.pubs__year::after { content: ""; flex: 1; height: 1px; background: var(--line); }

.pub {
  position: relative;
  display: flex;
  gap: 1.4rem;
  align-items: center;          /* picture centered to its text */
  padding: 0.8rem 0.9rem;
  border-radius: var(--radius);
  transition: background var(--speed) ease;
}
.pub:hover { background: var(--card); }

/* accent bar that slides in on hover */
.pub::before {
  content: "";
  position: absolute;
  left: 2px;
  top: 16px;
  bottom: 16px;
  width: 3px;
  border-radius: 3px;
  background: var(--accent);
  opacity: 0;
  transition: opacity var(--speed) ease;
}
.pub:hover::before { opacity: 1; }

/* --- the frame: same width and shape for every paper --- */
.pub__media {
  flex: 0 0 var(--thumb-w);
  width: var(--thumb-w);
  aspect-ratio: var(--thumb-ar);
  position: relative;
  overflow: hidden;
  border-radius: var(--radius-sm);
  box-shadow: 0 6px 18px var(--shadow);
  background: var(--mat);
}
/* Pictures/videos in a frame are sized and placed by main.js (fit, center, zoom
   in config.js). Until then they simply fill the frame. */
.pub__media > img,
.pub__media > video,
.hero__photo > img {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: cover;
}

/* placeholder (no media yet) — a soft swatch with the venue */
.pub__media.is-placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: none;
  background: linear-gradient(135deg, var(--accent-soft), transparent), var(--surface);
}
.pub__media.is-placeholder span {
  font-size: var(--fs-tiny);
  font-weight: 500;
  color: var(--accent);
  text-align: center;
  padding: 0.5em;
}

/* --- details --- */
.pub__info { flex: 1 1 auto; min-width: 0; }
.pub__title {
  font-size: var(--fs-title);
  font-weight: 600;
  line-height: 1.35;
  margin: 0;
}
.pub__title a { color: var(--ink); }
.pub__title a:hover { color: var(--accent); }
.pub__authors { font-size: var(--fs-small); color: var(--muted); margin: 0.25em 0 0; line-height: 1.5; }
.pub__authors strong { color: var(--ink); font-weight: 700; }
.pub__venue { font-size: var(--fs-tiny); color: var(--cool); font-style: italic; margin: 0.2em 0 0; }
.badge {
  display: inline-block;
  margin-left: 0.5em;
  padding: 0.05em 0.5em;
  font-size: var(--fs-tiny);
  font-style: normal;
  font-weight: 600;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: 999px;
  vertical-align: 1px;
}
.pub__links { font-size: var(--fs-tiny); margin: 0.35em 0 0; }
.pub__links a { font-weight: 500; }
.pub__links .sep { color: var(--faint); margin: 0 0.4em; }

/* the TL;DR: one quiet line under the links */
.pub__tldr {
  font-size: var(--fs-small);
  line-height: 1.55;
  color: var(--muted);
  max-width: 72ch;
  margin: 0.45em 0 0;
}

/* 6. ---------- TIMELINE (education / experience) ------------------------- */
.timeline { display: flex; flex-direction: column; gap: 1.05rem; }
.tl-row { display: flex; gap: 1.2rem; align-items: baseline; }
.tl-row__when { flex: 0 0 8.5rem; font-size: var(--fs-tiny); font-style: italic; color: var(--cool); }
.tl-row__body { flex: 1 1 auto; min-width: 0; }
.tl-row__what { font-weight: 600; margin: 0; }
.tl-row__where { font-size: var(--fs-small); color: var(--muted); margin: 0.1em 0 0; }
.tl-row__where img { display: inline-block; height: 1em; width: auto; vertical-align: -0.15em; margin-right: 0.4em; border-radius: 2px; }
.tl-row__note { font-size: var(--fs-small); color: var(--muted); margin: 0.25em 0 0; }

/* 7. ---------- NEWS ------------------------------------------------------ */
.news { display: flex; flex-direction: column; gap: 0.75rem; }
.news__item { display: flex; gap: 1rem; align-items: baseline; font-size: var(--fs-small); }
.news__date { flex: 0 0 5.5rem; font-size: var(--fs-small); font-weight: 500; color: var(--accent); }
.news__text { flex: 1 1 auto; min-width: 0; margin: 0; color: var(--body); }
.news__item.is-hidden { display: none; }
.news__more {
  align-self: center;
  margin-top: 0.3rem;
  padding: 0;
  font: inherit;
  font-size: var(--fs-small);
  color: var(--accent);
  background: none;
  border: none;
  cursor: pointer;
}
.news__more:hover { text-decoration: underline; }

/* 8. ---------- FOOTER & UTILITIES ---------------------------------------- */
.footer {
  max-width: var(--maxw);
  margin: 2rem auto 0;
  padding: 1.6rem clamp(1rem, 4vw, 1.75rem) 3rem;
  border-top: 1px solid var(--line);
  color: var(--muted);
  font-size: var(--fs-tiny);
  text-align: center;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  padding: 0.6em 1em;
  background: var(--accent);
  color: #fff;
  border-radius: 0 0 var(--radius-sm) 0;
  z-index: 20;
}
.skip-link:focus { left: 0; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px; }

/* 9. ---------- RESPONSIVE ------------------------------------------------ */
/* Phones keep the picture on the LEFT of the text (just smaller). */
@media (max-width: 720px) {
  :root {
    --thumb-w:   clamp(104px, 34vw, 180px);
    --photo-w:   112px;
    --fs-title:  0.95rem;
    --fs-small:  0.8rem;
    --fs-tiny:   0.75rem;
  }
  .hero__bio, .prose { text-align: left; hyphens: manual; -webkit-hyphens: manual; }
  .pub { gap: 0.85rem; align-items: flex-start; padding: 0.7rem 0; }
  .pub:hover { background: none; }
  .pub::before { display: none; }
  .pub__media { margin-top: 0.2rem; border-radius: 6px; }
  .tl-row { flex-direction: column; gap: 0.15rem; }
  .tl-row__when { flex-basis: auto; }
  .news__item { flex-direction: column; gap: 0.1rem; }
  .news__date { flex-basis: auto; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; }
}
