/* zifuwang.com: one stylesheet for every page.
   Most lengths are in vw, so the whole page scales with the window. */

:root {
  --paper: #fbfbfb;    /* page background */
  --ink: #5e5858;      /* icons, the phone menu */
  --dark: #333;        /* site title, navigation, headings, bold text */
  --body: #555;        /* running text */
  --gutter: 2vw;       /* side margin of the page; phones use 6vw (see the header and .grid) */
  --page-max: 2560px;  /* the layout stops growing at this width */
}

html {
  font-size: 16px;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-behavior: smooth;
  overscroll-behavior-y: none;  /* pulled past its top or bottom, a page stays put instead of bouncing */
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: "PT Serif";
  overflow-wrap: break-word;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

a {
  color: inherit;
  text-decoration: none;
}

/* ---------- header ---------- */

.header {
  --title-size: min(calc(.6vw + 1rem), calc(15.36px + 1rem));
  position: relative;
  z-index: 10;
  padding: 1vw var(--gutter);
  line-height: 1;
  -webkit-tap-highlight-color: transparent;
}

/* The title and the links stand on one line, whatever their sizes. The header keeps the height it had when
   they were centred instead: that of the links, or on very wide screens 1.2 times the title's size. */
.header-bar {
  position: relative;
  z-index: 2;
  display: flex;
  align-items: baseline;
  min-height: calc(1.2 * var(--title-size));
}

.site-title {
  font-family: "Gilda Display";
  font-size: var(--title-size);
  line-height: 1;  /* no taller than its letters, so it never pushes the links down */
  letter-spacing: -.02em;
  color: var(--dark);
}

.nav {
  display: flex;
  flex: 1 1 auto;
  flex-wrap: wrap;
  justify-content: flex-end;
  margin-left: auto;
  padding-left: 2.5vw;
  line-height: 2em;
}

.nav a {
  padding: .1em 0;
  color: var(--dark);
}

.nav a + a {
  margin-left: 2.5vw;
}

/* The page you are on is underlined. */
.nav a[aria-current="page"] {
  background: linear-gradient(currentColor, currentColor) 0 calc(100% - .1em) / 1px 1px repeat-x;
}

/* Over the home photo the title and the links are white. */
.home .site-title,
.home .nav a {
  color: #fff;
}

/* Keyboard users can jump past the header; the link shows only when focused. */
.skip {
  position: absolute;
  top: 1.5em;
  left: -1000em;
  z-index: 3;
  padding: 1.3em 2.171em;
  background: var(--ink);
  color: var(--paper);
  text-decoration: underline;
}

.skip:focus {
  left: 1.3em;
}

/* ---------- phone header and menu ---------- */

/* The button keeps the browser's own padding: with the 35px icon inside, that is what sets the phone header's height. */
.burger {
  display: none;
  flex: none;
  margin: 0 0 0 auto;
  border: 0;
  background: none;
  cursor: pointer;
}

.burger span {
  position: relative;
  display: block;
  width: 35px;
  height: 35px;
}

.burger span::before,
.burger span::after {
  content: "";
  position: absolute;
  top: 17px;
  left: 0;
  width: 35px;
  height: 1px;
  background: var(--dark);
  transition: transform .25s cubic-bezier(.2, .6, .3, 1), width .25s cubic-bezier(.2, .6, .3, 1);
  will-change: transform, width;  /* keeps the hairlines sharp on high-density screens */
}

.burger span::before {
  transform: translateY(-5.5px);
}

.burger span::after {
  transform: translateY(5.5px);
}

/* Over the home photo the button is white, like the title. */
.home .burger span::before,
.home .burger span::after {
  background: #fff;
}

/* Touch screens up to tablet size, and any narrow window: the links move into a full-screen menu
   that the two-line button opens and closes (site.js puts .menu-open on the html element). */
@media only screen and (pointer: coarse) and (max-width: 1024px), screen and (max-width: 799px) {
  .header {
    padding: 6vw;
  }

  .header-bar {
    align-items: center;  /* the button has no text to line up with */
  }

  .site-title {
    font-size: 1rem;
    line-height: 1.2em;
  }

  .burger {
    display: block;
  }

  .nav {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: -1;  /* behind the title and the button, in front of the page */
    flex-flow: column nowrap;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    margin: 0;
    padding: var(--header-height, calc(12vw + 37px)) 2vw 0;  /* the top clears the header; site.js measures it */
    overflow-y: auto;
    background: var(--paper);
    box-shadow: 0 50vh var(--paper);  /* also covers what lies under a phone browser's bottom bar */
    line-height: 1;
    opacity: 0;
    visibility: hidden;
    user-select: none;
    transition: visibility .6s cubic-bezier(.4, 0, .2, 1), opacity .4s cubic-bezier(.4, 0, .2, 1);
  }

  .header .nav a {
    margin: 3vw 5vw;
    padding: 0;
    background: none;
    font-size: 8.5vmin;
    color: var(--ink);
    transform: translateY(20px);
    transition: transform .6s cubic-bezier(.4, 0, .2, 1), opacity .25s cubic-bezier(.4, 0, .2, 1);
  }

  @media (min-width: 576px) {
    .header .nav a {
      font-size: 6.6vmin;
    }
  }

  @media (min-width: 768px) {
    .header .nav a {
      font-size: 6vmin;
    }
  }

  @media (hover: hover) {
    .header .nav a:hover {
      opacity: .9;
    }
  }

  .menu-open body {
    overflow: hidden;
  }

  .menu-open .nav {
    opacity: 1;
    visibility: visible;
  }

  .menu-open .nav a {
    transform: none;
  }

  .menu-open .site-title {
    color: var(--ink);
  }

  .menu-open .burger span::before,
  .menu-open .burger span::after {
    width: 28px;
    background: var(--ink);
  }

  .menu-open .burger span::before {
    transform: translateX(3.5px) rotate(-135deg);
  }

  .menu-open .burger span::after {
    transform: translateX(3.5px) rotate(135deg);
  }
}

/* ---------- page grid ---------- */

/* Every page is laid out on a grid: 8 columns on phones, 24 on wider screens, with a margin column on each side.
   Rows have a minimum height and grow with what is in them. */
.grid {
  --side: 6vw;
  --row: 24px;  /* the least height of a row */
  display: grid;
  grid-template-columns:
    minmax(var(--side), 1fr)
    repeat(8, minmax(0, calc(var(--page-max) / 8)))
    minmax(var(--side), 1fr);
  grid-template-rows: repeat(var(--rows), minmax(var(--row), auto));
  overflow-x: hidden;
  overflow-x: clip;
}

.grid > * {
  min-width: 0;
}

@media (min-width: 768px) {
  .grid {
    --side: var(--gutter);
    --row: calc(min(var(--page-max), 100vw - 2 * var(--gutter)) * .0215);
    grid-template-columns:
      minmax(var(--side), 1fr)
      repeat(24, minmax(0, calc(var(--page-max) / 24)))
      minmax(var(--side), 1fr);
  }
}

/* Where each block sits: row start / column start / row end / column end. */
.about .text { grid-area: 2 / 2 / 3 / -2; }
.about .social { grid-area: 4 / 2 / 5 / -2; }

.experience .grid { --rows: 32; }
.experience .text { grid-area: 4 / 2 / 30 / -2; }

.publication .grid { --rows: 85; }
.publication .text { grid-area: 4 / 2 / 83 / 10; }

@media (min-width: 768px) {
  .experience .grid { --rows: 26; }
  .experience .text { grid-area: 3 / 2 / 26 / -2; }

  .publication .grid { --rows: 79; }
  .publication .text { grid-area: 4 / 3 / 77 / 25; }
}

/* About is short, and its icons have to stay in the window. The text starts a fixed number of rows down
   (--lead). The room left under it is shared out by the window's height: five parts between the text and
   the icons, two below the icons. In a window too short for the smallest shares, the page scrolls. */
.about body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100svh;  /* on phones, the height with the browser's bars showing */
}

.about main {
  display: flex;
  flex: 1;
  flex-direction: column;
}

.about .grid {
  --lead: 5;
  flex: 1;
  grid-template-rows: calc(var(--lead) * var(--row)) auto minmax(7.5rem, 5fr) auto minmax(3rem, 2fr);
}

@media (min-width: 768px) {
  .about .grid {
    --lead: 6;
  }
}

/* ---------- text ---------- */

.text h1,
.text h2 {
  margin: 0 0 2rem;
  font-family: "Gilda Display";
  font-weight: 400;  /* the typeface has one weight; asked for bold, some browsers fake it and some do not */
  letter-spacing: -.02em;
  color: var(--dark);
}

.text h1 {
  font-size: min(calc(1.44vw + 1rem), calc(36.864px + 1rem));
  line-height: 1.1424em;
}

.text h2 {
  font-size: min(calc(.72vw + 1rem), calc(18.432px + 1rem));
  line-height: 1.1712em;
}

/* A new section starts well below the one before it. */
.text h2:not(:first-child) {
  margin-top: 8rem;
}

/* Upright phones size headings by the screen's height. */
@media screen and (max-width: 767px) and (orientation: portrait) {
  .text h1 {
    font-size: calc(.0144 * min(100vh, 900px) + 1rem);
  }

  .text h2 {
    font-size: calc(.0072 * min(100vh, 900px) + 1rem);
  }
}

/* Spaces are kept as typed: the gap between Paper and Code on the Publication page is four of them. */
.text p {
  margin: 1rem 0;
  font-size: 1rem;
  line-height: 2em;
  color: var(--body);
  white-space: pre-wrap;
}

.text > :first-child,
.text article > :first-child {
  margin-top: 0;
}

.text > :last-child,
.text article > :last-child {
  margin-bottom: 0;
}

/* One publication. */
.text article + article {
  margin-top: 4rem;
}

.text strong {
  color: var(--dark);
}

.text a {
  text-decoration-line: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: .2em;
  text-decoration-skip: auto;
  text-decoration-skip-ink: auto;
}

/* A word wrapped in this stays on one line. It is for words with a hyphen, which may otherwise break after it. */
.nb {
  white-space: nowrap;
}

/* The Experience column is as wide as its longest line and sits in the middle of the page. */
.experience .text {
  justify-self: center;
  width: max-content;
  max-width: 100%;
}

/* A role on the left and its years on the right, so every range starts and ends at the same place:
   the right edge of the column, which is where the longest line ends. */
.role {
  display: flex;
  flex-wrap: wrap;
  column-gap: 1em;  /* on a phone too narrow for both, the years drop to the next line, still at the right */
}

.role span:last-child {
  margin-left: auto;
  white-space: nowrap;
}

/* The About column stops widening at a comfortable line length and stays in the middle of the page. */
.about .text {
  justify-self: center;
  width: 100%;
  max-width: 36rem;
}

/* So does the Publications column, wide enough that only the longest list of authors runs over a line. */
.publication .text {
  justify-self: center;
  width: 100%;
  max-width: 64rem;
}

.about .text h1 {
  margin-bottom: 5rem;
  text-align: center;
}

.about .text p {
  text-align: justify;
}

/* ---------- contact icons ---------- */

.social {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  align-self: start;
  justify-content: center;
  gap: 14px;
}

/* Each icon is 24px; the padding makes it easier to hit with a finger, and the margin takes back the room. */
.social a {
  width: 24px;
  height: 24px;
  margin: -10px -7px;
  padding: 10px 7px;
  transition: opacity .17s ease-in-out;
}

.social a:hover {
  opacity: .8;
}

.social svg {
  display: block;
  width: 24px;
  height: 24px;
  fill: var(--ink);
}

/* ---------- home ---------- */

/* The home page is one photo that fills the window and stays put. The colour behind it is that of the photo's
   top edge under its shade: iPhone Safari paints the strip behind the clock with it, so the two run together. */
.home {
  background: #3e6e7f;
}

/* Behind its bottom bar, iPhone Safari (from version 26) uses the colour of whatever is fixed to the bottom of
   the window, if it is a few pixels tall and can be seen. This strip is the average colour of the photo's
   bottom edge on a phone; the two conditions pick out that browser, and nothing else shows the strip. */
.tint {
  display: none;
}

@supports (-webkit-touch-callout: none) and (anchor-name: --a) {
  @media (max-width: 767px) {
    .tint {
      display: block;
      position: fixed;
      right: 0;
      bottom: 0;
      left: 0;
      height: 6px;
      background: #a9b9c2;
    }
  }
}

/* Behind the open menu both bars take the menu's colour. */
.home.menu-open {
  background: var(--paper);
}

.home body {
  background: none;
}

.backdrop {
  position: fixed;
  top: 0;
  left: 0;
  z-index: -1;
  width: 100%;
  height: 100vh;  /* on phones this reaches under the browser's own bars */
}

.backdrop img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* A light veil over the photo. */
.backdrop::before {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background: var(--paper);
  opacity: .3;
}

/* Over the veil, a shade the colour of deep water: strongest at the top, gone by the middle.
   It is what the white title and menu are read against. */
.backdrop::after {
  --sea: 8, 70, 92;
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  left: 0;
  height: 50%;
  background: linear-gradient(
    rgba(var(--sea), .72),
    rgba(var(--sea), .49) 12%,
    rgba(var(--sea), .3) 25%,
    rgba(var(--sea), .155) 40%,
    rgba(var(--sea), .046) 60%,
    rgba(var(--sea), .006) 80%,
    rgba(var(--sea), 0));
}

/* ---------- page not found ---------- */

.message {
  padding: calc(var(--gutter) + 1rem) var(--gutter) var(--gutter);
}

@media only screen and (pointer: coarse) and (max-width: 1024px), screen and (max-width: 799px) {
  .message {
    padding: 1rem 6vw 6vw;
  }
}

/* ---------- fonts ---------- */

/* Keep this order. For regular text the Latin file is declared last, which makes it the family's main file;
   with another file last, Safari stops breaking link underlines around letters like p and g. */
@font-face { font-family: "PT Serif"; font-style: normal; font-weight: 400; font-display: swap; src: url("fonts/pt-serif-400-cyrillic.woff2") format("woff2"); unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; }
@font-face { font-family: "PT Serif"; font-style: normal; font-weight: 400; font-display: swap; src: url("fonts/pt-serif-400-latin-ext.woff2") format("woff2"); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "PT Serif"; font-style: normal; font-weight: 400; font-display: swap; src: url("fonts/pt-serif-400-cyrillic-ext.woff2") format("woff2"); unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; }
@font-face { font-family: "PT Serif"; font-style: normal; font-weight: 400; font-display: swap; src: url("fonts/pt-serif-400-latin.woff2") format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "PT Serif"; font-style: italic; font-weight: 700; font-display: swap; src: url("fonts/pt-serif-700-italic-latin-ext.woff2") format("woff2"); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "PT Serif"; font-style: italic; font-weight: 700; font-display: swap; src: url("fonts/pt-serif-700-italic-cyrillic-ext.woff2") format("woff2"); unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; }
@font-face { font-family: "PT Serif"; font-style: italic; font-weight: 700; font-display: swap; src: url("fonts/pt-serif-700-italic-cyrillic.woff2") format("woff2"); unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; }
@font-face { font-family: "PT Serif"; font-style: italic; font-weight: 700; font-display: swap; src: url("fonts/pt-serif-700-italic-latin.woff2") format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "PT Serif"; font-style: normal; font-weight: 700; font-display: swap; src: url("fonts/pt-serif-700-cyrillic-ext.woff2") format("woff2"); unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; }
@font-face { font-family: "PT Serif"; font-style: normal; font-weight: 700; font-display: swap; src: url("fonts/pt-serif-700-latin.woff2") format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "PT Serif"; font-style: normal; font-weight: 700; font-display: swap; src: url("fonts/pt-serif-700-latin-ext.woff2") format("woff2"); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "PT Serif"; font-style: normal; font-weight: 700; font-display: swap; src: url("fonts/pt-serif-700-cyrillic.woff2") format("woff2"); unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; }
@font-face { font-family: "PT Serif"; font-style: italic; font-weight: 400; font-display: swap; src: url("fonts/pt-serif-400-italic-cyrillic.woff2") format("woff2"); unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; }
@font-face { font-family: "PT Serif"; font-style: italic; font-weight: 400; font-display: swap; src: url("fonts/pt-serif-400-italic-latin-ext.woff2") format("woff2"); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "PT Serif"; font-style: italic; font-weight: 400; font-display: swap; src: url("fonts/pt-serif-400-italic-cyrillic-ext.woff2") format("woff2"); unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; }
@font-face { font-family: "PT Serif"; font-style: italic; font-weight: 400; font-display: swap; src: url("fonts/pt-serif-400-italic-latin.woff2") format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "Gilda Display"; font-style: normal; font-weight: 400; font-display: swap; src: url("fonts/gilda-display-400-latin-ext.woff2") format("woff2"); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "Gilda Display"; font-style: normal; font-weight: 400; font-display: swap; src: url("fonts/gilda-display-400-latin.woff2") format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
