/* ---------------------------------------------------------------
   Nicholas Kao — portfolio
   One stylesheet. No build step, no dependencies, no webfonts.
   --------------------------------------------------------------- */

/* Text ramps. Every value carries real text, so every value clears the
   4.5:1 WCAG floor against its own background — measured, not eyeballed.
   Light:  17.61 / 6.00 / 4.60    Dark: 16.47 / 7.10 / 5.29
   --rule is decorative hairline only and is exempt. Keep it that way:
   the moment a rule carries meaning it needs 3:1. */
:root {
  --bg:        #fdfdfc;
  --text:      #16171a;
  --secondary: #5f6269;
  --faint:     #71747b;
  --rule:      #e9e9e7;
  --measure:   37.5rem; /* 600px */
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg:        #0e0e0f;
    --text:      #ededec;
    --secondary: #9a9da4;
    --faint:     #83868d;
    --rule:      #232326;
  }
}

*,
*::before,
*::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  padding: 6rem 1.5rem 8rem;
  background: var(--bg);
  color: var(--text);
  font-family: ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI",
               Roboto, Helvetica, Arial, sans-serif;
  font-size: 15px;
  line-height: 1.6;
  font-feature-settings: "kern", "liga";
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

@media (max-width: 40rem) {
  body { padding-top: 3.5rem; }
}

main {
  max-width: var(--measure);
  margin: 0 auto;
}

/* ---------- Header ---------- */

header { margin-bottom: 3.5rem; }

.name,
article h1 {
  margin: 0;
  font-size: 15px;
  font-weight: 500;
  letter-spacing: -0.01em;
}

.role {
  margin: 0;
  color: var(--secondary);
}

.intro {
  margin: 1.5rem 0 0;
  max-width: 32rem;
  text-wrap: pretty;
}

/* The one piece of third-party validation on the page. Secondary weight, not
   full contrast — it supports the intro's claim rather than competing with it. */
.award {
  margin: 0.75rem 0 0;
  max-width: 32rem;
  color: var(--secondary);
  text-wrap: pretty;
}

/* ---------- Sections ---------- */

section { margin-bottom: 3rem; }

/* Section labels are structure, not metadata — on a two-screen page they
   are the only navigation. One weight step and full contrast, no size
   change, so they survive a squint without turning into headlines. */
h2 {
  margin: 0 0 0.875rem;
  font-size: 15px;
  font-weight: 500;
  color: var(--text);
}

/* ---------- Rows ---------- */

/* One row component for the whole site. A row is a block; .top is the
   optional title/year line and .desc the optional line beneath it. Rows with
   no year skip .top and put .title directly in the row.

   NOTE: no row on the page currently uses .top / .lead / .meta — Work dropped
   its years and Stack never had any. They are kept because the Projects and
   Writing restore snippets in README.md do use them. Verify against README
   before deleting them as dead code.

   Do not add a second row variant. There were two — .row (flex) and
   .stack-row (block) — and once every row on the page happened to use the
   block one, .row's flex properties sat there doing nothing, silently. */

.list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.list li + li { margin-top: 0.125rem; }

.row {
  display: block;
  padding: 0.4375rem 0;
  color: inherit;
  text-decoration: none;
}

.row .top {
  display: flex;
  align-items: baseline;
  gap: 1rem;
}

/* Titles wrap rather than truncate. The content outranks the decoration:
   at 390px an ellipsis was eating titles to protect the hairline. */
.row .title {
  flex: 0 1 auto;
  min-width: 0;
}

/* The hairline between title and year. It absorbs the leftover space and
   is the thing allowed to shrink. Baseline alignment keeps the year on the
   title's first line even when the title runs to two. */
.row .lead {
  flex: 1 1 auto;
  height: 1px;
  min-width: 1rem;
  background: var(--rule);
  transform: translateY(-0.2em);
}

.row .meta {
  flex: none;
  color: var(--faint);
  font-variant-numeric: tabular-nums;
  transition: color 120ms ease;
}

/* .desc is a <span> inside <a> in Stack and a <p> in Work, so it has to be
   told to be a block either way. */
.row .desc {
  display: block;
  margin: 0.0625rem 0 0;
  color: var(--secondary);
  text-wrap: pretty;
}

/* ---------- Links ---------- */

/* One underline recipe in three places. Prose links get --faint instead of
   --rule: a hairline that reads fine under a standalone row title vanishes
   mid-sentence. Links respond to hover; plain rows do not. */
a.row .title,
footer a,
article a {
  text-decoration: underline;
  text-decoration-color: var(--rule);
  text-underline-offset: 0.2em;
  text-decoration-thickness: 1px;
  transition: text-decoration-color 120ms ease;
}

footer a,
article a { color: inherit; }

article a { text-decoration-color: var(--faint); }

@media (hover: hover) {
  a.row:hover .title,
  footer a:hover { text-decoration-color: var(--secondary); }
  a.row:hover .meta { color: var(--secondary); }
}

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

/* ---------- Footer ---------- */

footer {
  margin-top: 4rem;
  color: var(--secondary);
}

/* ---------- Writing pages ---------- */

/* Dormant — there is no Writing section yet. These style
   writing/_template.html so that adding a post is a copy, not a redesign.
   Delete this block and the template together, or not at all. */

.back {
  display: inline-block;
  margin-bottom: 3rem;
  color: var(--secondary);
  text-decoration: none;
}

@media (hover: hover) {
  .back:hover { color: var(--text); }
}

.dateline {
  margin: 0 0 2.5rem;
  color: var(--faint);
  font-variant-numeric: tabular-nums;
}

article p { margin: 0 0 1.25rem; text-wrap: pretty; }

article h2 { margin: 2.5rem 0 0.75rem; }

article blockquote {
  margin: 0 0 1.25rem;
  padding-left: 1.25rem;
  border-left: 1px solid var(--rule);
  color: var(--secondary);
}

article code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.9em;
}
