/* ==========================================================================
   zunaid.kazi.net — one stylesheet for the whole site.
   Plain CSS, no build step. Edit this file directly.

   Contents:
     1. Tokens (colors, type, spacing)
     2. Reset & base
     3. Layout helpers
     4. Header & navigation
     5. Home / bio page
     6. List pages (publications, patents, press, articles, books)
     7. List controls (search / filter / sort)
     8. Footer
     9. Motion & reveal-on-scroll
   ========================================================================== */

/* -- 1. Tokens ----------------------------------------------------------- */

/* One neutral hue axis (OKLCH H≈85, the warm note the paper surfaces
   already had) with a single deliberate departure: oxblood at H≈25.
   Text used to sit at H≈250 while the paper sat at H≈85, so ink and
   paper disagreed; they now share an axis and the accent is the only
   thing in the palette allowed to be chromatic. */
:root {
  --ink:          #1c1b18;
  --ink-soft:     #504c44;
  --ink-faint:    #676359;
  --bg:           #fcfbf9;
  --bg-panel:     #f2efe9;
  --bg-raised:    #ffffff;
  --rule:         #e3ded4;
  --rule-strong:  #cdc6b8;
  --accent:       #7d2e2c;
  --accent-hover: #5d1c1b;
  --accent-wash:  #fbe9e7;
  --focus:        #a25b00;

  --serif: "Iowan Old Style", "Palatino Linotype", Palatino, "Book Antiqua", Georgia, "Times New Roman", serif;
  --sans:  -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;

  /* 36rem = 576px. At the body size that lands at 70ch on macOS, 73ch on
     Windows and 64ch on Android — inside the 45-75ch band on every platform
     the font stack can resolve to. 40rem put Windows at 81ch. */
  --measure: 36rem;   /* comfortable reading width for prose  */
  --wide:    62rem;   /* page frame                            */

  --step-0: 1.0625rem;
  --step-1: 1.25rem;
  --step-2: 1.5rem;
  --step-3: 2rem;
  --step-4: 2.75rem;

  --radius: 4px;
  --shadow: 0 1px 2px rgba(25, 27, 29, .05), 0 6px 20px rgba(25, 27, 29, .05);
}

@media (prefers-color-scheme: dark) {
  :root {
    --ink:          #e8e4dc;
    --ink-soft:     #b3ada2;
    --ink-faint:    #9d9586;
    --bg:           #191815;
    --bg-panel:     #22201c;
    --bg-raised:    #24221e;
    --rule:         #34312c;
    --rule-strong:  #4e4a42;
    --accent:       #e79993;
    --accent-hover: #f5b9b4;
    --accent-wash:  #3b2422;
    --focus:        #f0a94b;
    --shadow: 0 1px 2px rgba(0, 0, 0, .4), 0 6px 20px rgba(0, 0, 0, .3);
  }
}

/* Manual theme override — wins over the OS preference above once the
   visitor has clicked the toggle. Set on <html> by js/site.js. */
:root[data-theme="light"] {
  --ink:          #1c1b18;
  --ink-soft:     #504c44;
  --ink-faint:    #676359;
  --bg:           #fcfbf9;
  --bg-panel:     #f2efe9;
  --bg-raised:    #ffffff;
  --rule:         #e3ded4;
  --rule-strong:  #cdc6b8;
  --accent:       #7d2e2c;
  --accent-hover: #5d1c1b;
  --accent-wash:  #fbe9e7;
  --focus:        #a25b00;
  --shadow: 0 1px 2px rgba(25, 27, 29, .05), 0 6px 20px rgba(25, 27, 29, .05);
}
:root[data-theme="dark"] {
  --ink:          #e8e4dc;
  --ink-soft:     #b3ada2;
  --ink-faint:    #9d9586;
  --bg:           #191815;
  --bg-panel:     #22201c;
  --bg-raised:    #24221e;
  --rule:         #34312c;
  --rule-strong:  #4e4a42;
  --accent:       #e79993;
  --accent-hover: #f5b9b4;
  --accent-wash:  #3b2422;
  --focus:        #f0a94b;
  --shadow: 0 1px 2px rgba(0, 0, 0, .4), 0 6px 20px rgba(0, 0, 0, .3);
}

/* Dark mode is not only a color swap. Light text on a dark ground blooms:
   the thick stems spread and the hairlines get eaten, which flattens exactly
   the stroke modulation that makes an oldstyle serif worth setting. Both
   faces this stack resolves to (Iowan Old Style, Palatino Linotype) are
   high-contrast, so they need the compensation more than a sans would.
   A little extra leading and tracking buys the strokes room back.
   Guarded like the tokens above, so a forced light theme never gets it. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) body { line-height: 1.7; letter-spacing: .004em; }
  :root:not([data-theme="light"]) .bio { line-height: 1.78; }
}
:root[data-theme="dark"] body { line-height: 1.7; letter-spacing: .004em; }
:root[data-theme="dark"] .bio  { line-height: 1.78; }

/* -- 2. Reset & base ----------------------------------------------------- */

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

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
  /* Surfaces the browser draws for us still belong to the palette:
     the search caret, the select's own control chrome, and the
     scrollbar all default to a blue that is no longer in this site. */
  accent-color: var(--accent);
  caret-color: var(--accent);
  scrollbar-color: var(--rule-strong) transparent;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--serif);
  font-size: var(--step-0);
  line-height: 1.65;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 {
  font-family: var(--serif);
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.012em;
  color: var(--ink);
  margin: 0 0 .5em;
  text-wrap: balance;
}

h1 { font-size: var(--step-4); }
h2 { font-size: var(--step-2); }
h3 { font-size: var(--step-1); }

p { margin: 0 0 1.15em; }

a {
  color: var(--accent);
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
  transition: color .15s ease;
}
a:hover { color: var(--accent-hover); }

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

img { max-width: 100%; height: auto; }

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

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: .6rem 1rem;
  background: var(--bg-raised);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius);
  font-family: var(--sans);
  font-size: .9rem;
}
.skip-link:focus { left: 1rem; top: 1rem; }

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* -- 3. Layout helpers --------------------------------------------------- */

.wrap {
  width: 100%;
  max-width: var(--wide);
  margin-inline: auto;
  padding-inline: 1.25rem;
}

main { display: block; }

.page-head {
  padding: 3rem 0 1.5rem;
  border-bottom: 1px solid var(--rule);
  margin-bottom: 2rem;
}
.page-head p {
  font-family: var(--sans);
  font-size: .95rem;
  color: var(--ink-soft);
  max-width: var(--measure);
  margin-bottom: 0;
}

/* -- 4. Header & navigation ---------------------------------------------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: saturate(180%) blur(10px);
  border-bottom: 1px solid var(--rule);
}
@supports not (backdrop-filter: blur(1px)) {
  .site-header { background: var(--bg); }
}

.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-height: 3.75rem;
  flex-wrap: wrap;
}

.brand {
  font-family: var(--serif);
  font-size: 1.05rem;
  font-weight: 600;
  letter-spacing: .01em;
  color: var(--ink);
  text-decoration: none;
  white-space: nowrap;
}
.brand:hover { color: var(--accent); }
.brand-suffix { color: var(--ink-faint); font-weight: 400; }

.header-actions {
  display: flex;
  align-items: center;
  gap: .5rem;
}

.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.1rem;
  height: 2.1rem;
  background: none;
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius);
  color: var(--ink-soft);
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
}
.theme-toggle:hover { color: var(--accent); border-color: var(--accent); }
/* Inline SVG rather than U+2600/U+263E: those depend on font fallback and
   degrade to a box glyph on systems that lack them. */
.theme-toggle svg { display: block; }
.theme-toggle .icon-dark { display: none; }
:root[data-theme="dark"] .theme-toggle .icon-light { display: none; }
:root[data-theme="dark"] .theme-toggle .icon-dark { display: block; }
/* No manual choice yet: follow the OS preference for which icon shows. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) .theme-toggle .icon-light { display: none; }
  :root:not([data-theme]) .theme-toggle .icon-dark { display: block; }
}

.site-nav ul {
  display: flex;
  gap: 1.4rem;
  list-style: none;
  margin: 0;
  padding: 0;
}
.site-nav a {
  font-family: var(--sans);
  font-size: .875rem;
  letter-spacing: .01em;
  color: var(--ink-soft);
  text-decoration: none;
  padding: .35rem 0;
  border-bottom: 2px solid transparent;
  display: inline-block;
}
.site-nav a:hover { color: var(--accent); border-bottom-color: var(--rule-strong); }
.site-nav a[aria-current="page"] {
  color: var(--ink);
  font-weight: 600;
  border-bottom-color: var(--accent);
}

.nav-toggle {
  display: none;
  align-items: center;
  gap: .5rem;
  background: none;
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius);
  color: var(--ink-soft);
  font-family: var(--sans);
  font-size: .8rem;
  padding: .4rem .7rem;
  cursor: pointer;
}
.nav-toggle-bars,
.nav-toggle-bars::before,
.nav-toggle-bars::after {
  display: block;
  width: 15px;
  height: 1.5px;
  background: currentColor;
  content: "";
}
.nav-toggle-bars { position: relative; }
.nav-toggle-bars::before { position: absolute; top: -5px; }
.nav-toggle-bars::after  { position: absolute; top:  5px; }

@media (max-width: 40rem) {
  .nav-toggle { display: inline-flex; }
  .site-nav {
    flex-basis: 100%;
    display: none;
    padding-bottom: .75rem;
  }
  .site-nav.is-open { display: block; }
  .site-nav ul { flex-direction: column; gap: 0; }
  .site-nav a {
    padding: .6rem .25rem;
    border-bottom: 1px solid var(--rule);
    width: 100%;
  }
  .site-nav a[aria-current="page"] { border-bottom-color: var(--accent); }
}

/* Without JS the toggle is useless, so hide it and always show the nav. */
.no-js .nav-toggle { display: none; }
@media (max-width: 40rem) {
  .no-js .site-nav { display: block; }
}

/* -- 5. Home / bio page -------------------------------------------------- */

.hero {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 2rem;
  align-items: start;
  padding: 3.5rem 0 2rem;
}
.hero-portrait {
  width: 168px;
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  display: block;
}
.hero h1 { margin-bottom: .25rem; }
.hero-tagline {
  font-family: var(--sans);
  font-size: 1rem;
  color: var(--ink-soft);
  margin-bottom: 0;
  max-width: var(--measure);
}

@media (max-width: 40rem) {
  .hero { grid-template-columns: 1fr; gap: 1.25rem; padding-top: 2rem; }
  .hero-portrait { width: 132px; }
  h1 { font-size: var(--step-3); }
}

/* Leading rises with measure: at 70ch the eye needs a stronger horizontal
   track to find the next line start than the global 1.65 provides. The
   paragraph gap is close to one full line, so breaks read as breaks. */
.bio {
  max-width: var(--measure);
  padding-bottom: 1rem;
  line-height: 1.72;
}
.bio p { margin-bottom: 1.45em; }
.bio p:first-of-type { font-size: 1.2rem; color: var(--ink); }

/* Not prose, so it is not bound to --measure: the reading width is tuned
   for the bio, and squeezing the card grid to it would cost a column. */
.home-links {
  max-width: 46rem;
  margin: 1rem 0 4rem;
  padding-top: 2rem;
  border-top: 1px solid var(--rule);
}

.home-group + .home-group { margin-top: 2.25rem; }

/* The group label, not the block label, is what the reader needs; the
   block's own <h2> is there for screen readers and is hidden. */
.home-group-label {
  font-family: var(--sans);
  font-size: .75rem;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 0 0 .75rem;
}
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(13rem, 100%), 1fr));
  gap: .75rem;
  list-style: none;
  margin: 0;
  padding: 0;
}
/* The two largest bodies of work get more room than the one-item sections,
   so the grid stops implying that 78 essays and 1 book weigh the same. */
.card-lead { grid-column: span 2; }
@media (max-width: 34rem) {
  .card-lead { grid-column: auto; }
}
/* Title and count share the first row, the note spans beneath. min() on the
   track keeps a card from outgrowing a narrow screen. */
.card {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  column-gap: .75rem;
  padding: .9rem 1rem;
  background: var(--bg-raised);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  text-decoration: none;
  color: var(--ink);
  transition: border-color .15s ease, transform .15s ease, box-shadow .15s ease;
}
.card:hover {
  border-color: var(--rule-strong);
  transform: translateY(-2px);
  box-shadow: var(--shadow);
  color: var(--ink);
}
.card-title { font-weight: 600; display: block; }

/* How much is behind the link. Tabular so the digits line up down the
   column, and quiet enough that it reads as scale, not as a badge. */
.card-count {
  font-family: var(--sans);
  font-size: .8rem;
  font-variant-numeric: tabular-nums;
  color: var(--ink-faint);
  justify-self: end;
}
.card-note {
  display: block;
  grid-column: 1 / -1;
  font-family: var(--sans);
  font-size: .8rem;
  color: var(--ink-faint);
  margin-top: .15rem;
}

/* -- 6. List pages ------------------------------------------------------- */

.entry-list {
  list-style: none;
  margin: 0 0 3rem;
  padding: 0;
  max-width: 46rem;
}

.entry {
  padding: 1.15rem 0;
  border-bottom: 1px solid var(--rule);
}
.entry:first-child { border-top: 1px solid var(--rule); }

/* The primary object on four pages. At 1.08rem it sat 0.28px above body
   text and carried its whole job on weight; 1.15rem makes the size step
   visible. <cite> is not a heading, so it needs balance set explicitly. */
.entry-title {
  font-style: normal;
  font-weight: 600;
  font-size: 1.15rem;
  line-height: 1.35;
  display: block;
  margin-bottom: .35rem;
  text-wrap: balance;
}
.entry-title a { text-decoration-color: var(--rule-strong); }

/* This class carries two kinds of content: citation strings on papers.html,
   which scan fine wide, and article standfirsts on articles.html, which are
   real prose. At the list's 46rem the prose ran to ~105ch. Cap it. */
.entry-meta {
  font-family: var(--sans);
  font-size: .875rem;
  line-height: 1.6;
  color: var(--ink-soft);
  margin: 0;
  max-width: 34rem;
}
.entry-meta .self { color: var(--ink); font-weight: 600; }

.entry-tags {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .5rem;
  margin-top: .5rem;
}

.tag {
  font-family: var(--sans);
  font-size: .75rem;
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--ink-faint);
  background: var(--bg-panel);
  border: 1px solid var(--rule);
  border-radius: 999px;
  padding: .2rem .6rem;
  white-space: nowrap;
}
.tag-year { font-variant-numeric: tabular-nums; }

/* Patent numbers read as registry entries, not prose. */
.tag-patent {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  letter-spacing: 0;
  text-transform: none;
}

/* Media: a speaking engagement is a different fact from press coverage.
   Driven off data-type, so entries need no extra markup. */
.entry[data-type="speaking"] .entry-tags .tag:last-of-type {
  color: var(--accent);
  background: var(--accent-wash);
  border-color: transparent;
}

/* A PDF link and a tag sat in the same row as the same pill, at the same
   size and tracking: one clickable, one not, and no way to tell without
   reading. The link keeps the accent but takes a squared corner and an
   underline, so shape and decoration both say "control" before the eye
   reaches the word. Tags stay pills. */
.pdf-link {
  font-family: var(--sans);
  font-size: .75rem;
  font-weight: 700;
  letter-spacing: .07em;
  color: var(--accent);
  background: var(--accent-wash);
  border: 1px solid var(--accent-wash);
  border-radius: var(--radius);
  padding: .2rem .6rem;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
  white-space: nowrap;
}
.pdf-link:hover { border-color: var(--accent); color: var(--accent-hover); }

.back-link {
  font-family: var(--sans);
  font-size: .875rem;
  padding-bottom: 3rem;
}

/* -- 7. List controls ---------------------------------------------------- */

.controls {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 1rem;
  margin-bottom: 1.75rem;
  padding: 1rem 1.1rem;
  background: var(--bg-panel);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  max-width: 46rem;
}
.no-js .controls { display: none; }

.ctl { display: flex; flex-direction: column; gap: .3rem; }
.ctl-search { flex: 1 1 15rem; }

.ctl-label {
  font-family: var(--sans);
  font-size: .7rem;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.ctl input,
.ctl select {
  font-family: var(--sans);
  font-size: .9rem;
  color: var(--ink);
  background: var(--bg-raised);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius);
  padding: .45rem .6rem;
  width: 100%;
  min-height: 2.25rem;
}
.ctl input:focus, .ctl select:focus { border-color: var(--accent); }

.result-count {
  font-family: var(--sans);
  font-size: .8rem;
  color: var(--ink-faint);
  margin: 0 0 .25rem auto;
  font-variant-numeric: tabular-nums;
}

.entry[hidden] { display: none; }

.empty-state {
  font-family: var(--sans);
  font-size: .95rem;
  color: var(--ink-faint);
  padding: 2rem 0;
  margin: 0;
}

@media (max-width: 40rem) {
  .controls { gap: .75rem; }
  .result-count { margin-left: 0; }
}

/* -- 8. Footer ----------------------------------------------------------- */

.site-footer {
  border-top: 1px solid var(--rule);
  padding: 2rem 0 3rem;
  margin-top: auto;
}
/* Three small groups rather than one flat row: a recruiter, a journalist,
   and an academic peer are each looking for a different one of these. */
.footer-groups {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem 3rem;
  margin-bottom: 1.5rem;
}
.footer-group-label {
  display: block;
  font-family: var(--sans);
  font-size: .7rem;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: .5rem;
}
.footer-links {
  display: flex;
  flex-wrap: wrap;
  gap: .3rem 1.25rem;
  list-style: none;
  margin: 0;
  padding: 0;
}
.footer-links a {
  font-family: var(--sans);
  font-size: .875rem;
  text-decoration: none;
}
.footer-links a:hover { text-decoration: underline; }

@media (max-width: 40rem) {
  .footer-groups { gap: 1.25rem 2rem; }
  .footer-links { flex-direction: column; gap: .35rem; }
}
.footer-note {
  font-family: var(--sans);
  font-size: .8rem;
  color: var(--ink-faint);
  margin: 0;
}

/* -- 9. Motion & reveal-on-scroll ---------------------------------------- */

.reveal {
  opacity: 0;
  transform: translateY(12px);
  transition: opacity .5s ease, transform .5s ease;
}
.reveal.is-visible { opacity: 1; transform: none; }

/* No JS, or user prefers less motion: show everything immediately. */
.no-js .reveal { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal { opacity: 1; transform: none; transition: none; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}
