/*
 * Shared fonts, element defaults and components for the static pages.
 *
 * Load order, one <link rel="stylesheet"> each:
 *   /vendor/modern-normalize.css → /theme.css → /site.css → page CSS
 * Every value here is a token from theme.css. Rules sit in @layer base and
 * @layer components; page CSS is unlayered, so it always wins and a page can
 * migrate one rule at a time. modern-normalize is unlayered too, so the few
 * properties it sets on the same elements are restated outside the layers at
 * the end of this file. Pages leave scroll-behavior to base, which turns it
 * off under reduced motion.
 *
 * Components, and the markup each expects:
 *
 *   .skip-link       <a class="skip-link" href="#content">Skip to content</a>,
 *                    first in <body>, on every page with the header.
 *   .site-header     <header class="site-header">: .lockup · .site-tagline ·
 *                    .site-nav, on a 1px --rule. It sizes itself to the gutter
 *                    and --wide, so it sits straight in <body>.
 *   .lockup          <a class="lockup" href="/" aria-label="Mingyang Jin, home">
 *                    wrapping .mark and <span>Mingyang Jin</span>.
 *   .mark            The 28px vermilion MJ disc: <svg class="mark"
 *                    viewBox="0 0 64 64" width="28" height="28"
 *                    aria-hidden="true"> with public/icon.svg's outlined paths.
 *   .site-tagline    <p class="site-tagline">Software engineer · Agent-native
 *                    builder</p>, hidden at 620px and below.
 *   .site-nav        <nav class="site-nav" aria-label="Primary">: Photography,
 *                    Writing, Explainers, in that order, no arrows. The
 *                    current section's link carries aria-current="page" and
 *                    gets the 2px --current underline, in the header only.
 *   .site-footer     <footer class="site-footer">: a 1px --rule on top, then
 *                    .lockup · <p class="site-place">San Francisco Bay Area</p>
 *                    · <nav class="site-nav" aria-label="Footer"> with the
 *                    same three links.
 *   .back-link       "← " plus the destination's own title: "← Mingyang Jin".
 *   .button          Document pill, 44px tall; the secondary look by default.
 *     --primary      Filled with the action role.
 *     --secondary    Names the default: transparent on a --line-strong edge.
 *                    aria-pressed or aria-checked "true" takes the action
 *                    fill; :disabled and aria-disabled="true" go --muted.
 *   .eyebrow         12px label in --eyebrow, typed in sentence case.
 *   .section-label   "Name / 01" in --muted.
 *   .callout         Neutral: --tint with a 3px --ink rule.
 *     --critical, --caution, --positive
 *                    The status tint and rule. The status word goes in a
 *                    .callout-status element, never color alone.
 *   .table-wrap      <div class="table-wrap" role="region" tabindex="0"
 *                    aria-label="…"> around every table.
 */

@layer base, components;

/* Inter reaches only visitors without Helvetica Neue, and is never preloaded. */
@font-face {
  font-family: "Inter Variable";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(/fonts/inter-latin-wght-normal.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;
}

/* Arial stretched to Inter's metrics (next/font's numbers), so the swap to
   Inter does not reflow the page. */
@font-face {
  font-family: "Inter Fallback";
  src: local("Arial");
  size-adjust: 107.89%;
  ascent-override: 89.79%;
  descent-override: 22.36%;
  line-gap-override: 0%;
}

@layer base {
  body {
    min-width: 320px;
    background: var(--bg);
    color: var(--ink);
    font-family: var(--font-sans);
    font-size: var(--text-base);
    line-height: var(--leading-ui);
  }

  /* color inherits as a resolved value, so an island resolves its own. */
  [data-theme] {
    color: var(--ink);
  }

  h1,
  h2,
  h3 {
    line-height: var(--leading-heading);
  }

  h1 {
    font-size: var(--text-3xl);
    letter-spacing: var(--tracking-heading);
  }

  h2 {
    font-size: var(--text-2xl);
    letter-spacing: var(--tracking-heading);
  }

  h3 {
    font-size: var(--text-xl);
  }

  /* Prose links: ink on a 1px underline that turns 2px vermilion on hover.
     Chrome links (nav, lockup, back link) drop the underline at rest. A quiet
     page leaves vermilion to the MJ disc, so its hover underline stays ink. */
  a {
    color: var(--ink);
    text-decoration-thickness: 1px;
    text-underline-offset: 0.18em;
  }

  a:hover {
    text-decoration-color: var(--accent);
    text-decoration-thickness: 2px;
  }

  [data-accent="quiet"] a:hover {
    text-decoration-color: currentcolor;
  }

  ::selection {
    background: var(--selection-bg);
    color: var(--selection-ink);
  }

  /* One ring, always ink, never removed. The radio-label rule stays separate
     so a browser without :has() still draws the ring everywhere else. */
  :focus-visible {
    outline: 2px solid var(--focus);
    outline-offset: 3px;
  }

  label:has(input[type="radio"]:focus-visible) {
    outline: 2px solid var(--focus);
    outline-offset: 3px;
  }

  @media (prefers-reduced-motion: no-preference) {
    html {
      scroll-behavior: smooth;
    }
  }

  /* A layered !important outranks unlayered page CSS. theme.css zeroes the
     durations and the lift. */
  @media (prefers-reduced-motion: reduce) {
    html {
      scroll-behavior: auto !important;
    }
  }

  /* Matches zh-CN and zh-Hans. The CJK families come ahead of the generic,
     which would otherwise always match first. */
  :lang(zh) {
    --font-sans:
      "Helvetica Neue", "Inter Variable", "PingFang SC", "Hiragino Sans GB",
      "Noto Sans CJK SC", "Source Han Sans SC", "Microsoft YaHei", sans-serif;
    --leading-prose: 1.8;
    --tracking-display: 0;
    --tracking-heading: 0;
    --tracking-label: 0;
    --label-case: none;
    --weight-bold: 500;
    letter-spacing: 0;
    text-transform: none;
    font-synthesis: none;
  }

  /* The element carrying lang re-resolves the family; its children inherit. */
  [lang|="zh"] {
    font-family: var(--font-sans);
  }

  /* Han weights stop at 500, whatever the page (or normalize's bolder) asks. */
  :is(h1, h2, h3, h4, h5, h6, b, strong, th):lang(zh) {
    font-weight: var(--weight-bold) !important;
  }
}

@layer components {
  .skip-link {
    position: absolute;
    z-index: 10;
    top: var(--space-2);
    left: var(--gutter);
    padding: var(--space-2) var(--space-4);
    background: var(--action-bg);
    color: var(--action-ink);
    font-size: var(--text-sm);
    font-weight: var(--weight-bold);
    text-decoration: none;
    transform: translateY(-200%);
  }

  .skip-link:focus {
    transform: none;
  }

  .site-header,
  .site-footer {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: var(--space-4);
    width: min(100% - 2 * var(--gutter), var(--wide));
    margin-inline: auto;
    font-size: var(--text-xs);
    font-weight: var(--weight-bold);
    letter-spacing: var(--tracking-label);
    text-transform: var(--label-case);
  }

  .site-header {
    padding-block: var(--space-5) var(--space-4);
    border-bottom: 1px solid var(--rule);
  }

  .site-footer {
    padding-block: var(--space-6);
    border-top: 1px solid var(--rule);
  }

  .site-tagline,
  .site-place {
    margin: 0;
    color: var(--muted);
  }

  .lockup {
    display: inline-flex;
    align-items: center;
    gap: var(--space-3);
    width: fit-content;
    color: var(--ink);
    font-size: var(--text-xs);
    font-weight: var(--weight-bold);
    letter-spacing: var(--tracking-label);
    text-transform: var(--label-case);
    text-decoration: none;
    text-underline-offset: 0.4em;
    white-space: nowrap;
  }

  .mark {
    display: block;
    flex: none;
    width: 28px;
    height: 28px;
  }

  .site-nav {
    justify-self: end;
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    column-gap: var(--space-5);
    font-size: var(--text-sm);
  }

  .site-footer .site-nav {
    font-size: inherit;
  }

  .site-nav a,
  .back-link {
    display: inline-block;
    padding-block: var(--space-1);
    text-decoration: none;
    text-underline-offset: 0.4em;
  }

  .lockup:hover,
  .site-nav a:hover,
  .back-link:hover {
    text-decoration-line: underline;
  }

  .site-nav a[aria-current]:not([aria-current="false"]) {
    text-decoration: underline 2px var(--current);
  }

  .back-link {
    color: var(--ink);
    font-size: var(--text-sm);
    text-underline-offset: 0.18em;
  }

  .button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    min-height: 44px;
    padding: 0 20px;
    border: 1px solid var(--line-strong);
    border-radius: var(--radius-pill);
    background: transparent;
    color: var(--ink);
    font-weight: var(--weight-bold);
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    transition: transform var(--dur) var(--ease);
  }

  .button:hover {
    transform: translateY(var(--lift));
  }

  .button--secondary {
    border-color: var(--line-strong);
    background: transparent;
    color: var(--ink);
  }

  .button--primary,
  .button[aria-pressed="true"],
  .button[aria-checked="true"] {
    border-color: var(--action-bg);
    background: var(--action-bg);
    color: var(--action-ink);
  }

  .button:disabled,
  .button[aria-disabled="true"] {
    border-color: var(--line);
    background: transparent;
    color: var(--muted);
    cursor: not-allowed;
    transform: none;
  }

  .eyebrow,
  .section-label {
    margin: 0;
    font-size: var(--text-xs);
    font-weight: var(--weight-bold);
    line-height: 1.2;
    letter-spacing: var(--tracking-label);
    text-transform: var(--label-case);
  }

  .eyebrow {
    color: var(--eyebrow);
  }

  .section-label {
    color: var(--muted);
    font-variant-numeric: tabular-nums;
  }

  .callout {
    --callout-tone: var(--ink);
    margin-block: var(--space-5);
    padding: var(--space-4) var(--space-5);
    border-left: 3px solid var(--callout-tone);
    background: var(--tint);
  }

  .callout > :first-child {
    margin-top: 0;
  }

  .callout > :last-child {
    margin-bottom: 0;
  }

  .callout--critical {
    --callout-tone: var(--critical);
    background: var(--critical-tint);
  }

  .callout--caution {
    --callout-tone: var(--caution);
    background: var(--caution-tint);
  }

  .callout--positive {
    --callout-tone: var(--positive);
    background: var(--positive-tint);
  }

  .callout-status {
    color: var(--callout-tone);
    font-weight: var(--weight-bold);
  }

  .table-wrap {
    overflow-x: auto;
    margin-block: var(--space-5);
  }

  .table-wrap table {
    width: 100%;
    border-collapse: collapse;
    border-top: 1px solid var(--rule);
    font-size: var(--text-sm);
    font-variant-numeric: tabular-nums;
  }

  .table-wrap th,
  .table-wrap td {
    padding: var(--space-2) var(--space-3);
    border-bottom: 1px solid var(--line);
    text-align: left;
    vertical-align: top;
  }

  .table-wrap thead th {
    color: var(--muted);
    font-size: var(--text-xs);
    font-weight: var(--weight-bold);
    letter-spacing: var(--tracking-label);
    text-transform: var(--label-case);
  }

  @media (max-width: 620px) {
    .site-header {
      grid-template-columns: auto 1fr;
    }

    .site-tagline {
      display: none;
    }

    .site-footer {
      grid-template-columns: 1fr;
      justify-items: start;
    }

    .site-footer .site-nav {
      justify-self: start;
      justify-content: flex-start;
    }
  }
}

/*
 * Outside the layers. modern-normalize is unlayered, so on the elements it
 * styles it outranks both layers whatever their specificity: font-size: 100%
 * and line-height: 1.15 on <button>, outline-offset: -2px on search inputs,
 * border-color: currentcolor on <table>. These restate the component values
 * with higher specificity; page CSS, loaded later, still overrides them.
 */
.button {
  font-size: var(--text-sm);
  line-height: 1.2;
}

[type="search"]:focus-visible {
  outline-offset: 3px;
}

.table-wrap table {
  border-top-color: var(--rule);
}
