/* ---------------------------------------------------------------
   Andrew Moore — resume site
   Single stylesheet, no build step. Edit the tokens below to retune.
--------------------------------------------------------------- */

/* Montserrat — geometric sans, self-hosted, and the whole page: headings on
   the heavy end of the variable range, copy on the light end. Latin subset,
   roman + a real drawn italic. */
@font-face {
  font-family: "Montserrat Variable";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/fonts/montserrat-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+2074, U+20AC, U+2122, U+2191,
    U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Never let the browser slant the roman for this. */
@font-face {
  font-family: "Montserrat Variable";
  font-style: italic;
  font-weight: 100 900;
  font-display: swap;
  src: url("/fonts/montserrat-latin-wght-italic.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+2074, U+20AC, U+2122, U+2191,
    U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  --bg: #ffffff;
  --text: #17171a;
  --text-2: #3f3f48;
  /* body copy that matters but isn't a heading */
  --muted: #6e6e78;
  --faint: #9a9aa4;
  --rule: #ebebef;
  --link-underline: #d4d4dc;

  /* Paper grain. One number to tune — past about 0.2 it stops reading as
     texture and starts reading as a dirty screen. */
  --grain: 0.055;

  --font: "Montserrat Variable", "Montserrat", -apple-system, BlinkMacSystemFont,
    "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  /* Headings run on the same face — point this elsewhere to reintroduce a
     second one. */
  --font-display: var(--font);

  /* Type scale — four steps, nothing in between.
     name → heading → copy → meta                        */
  --fs-name: 1.375rem;
  /* 22px   — one step over the company headings, not a whole register */
  --fs-head: 1.125rem;
  /* 18px   — company names, in the display face */
  --fs-label: 0.8125rem;
  /* 13px   — section marks */
  --fs-copy: 0.9375rem;
  /* 15px   — bio, descriptions; Montserrat is wide and even, so it holds
                 the measure at a step down from the old 16px */
  --fs-meta: 0.875rem;
  /* 14px   — dates, scope */

  --measure: 37rem;
  /* content width */
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #0e0e10;
    --text: #ededf0;
    --text-2: #c6c6d0;
    --muted: #9494a0;
    --faint: #6c6c78;
    --rule: #232328;
    --link-underline: #3a3a42;

    /* Light grain on a dark ground reads stronger, so it comes down. */
    --grain: 0.035;
  }
}

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

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: var(--fs-copy);
  line-height: 1.7;
  letter-spacing: 0.002em;
  font-feature-settings: "kern", "liga", "calt";
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

/* Paper grain: one tiled SVG of fractal noise, fixed behind the text so it
   sits still while the page scrolls — grain that moves reads as a bug.
   Inline data URI, so it stays a zero-request page. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  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='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.5' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23g)'/%3E%3C/svg%3E");
  /* The tile renders at 2x its own size, so the speckle lands at roughly two
     device pixels on a retina screen. At 1x it disappeared into the panel. */
  background-size: 320px 320px;
}

main {
  max-width: var(--measure);
  margin: 0 auto;
  padding: 4.5rem 1.5rem 5.5rem;
}

/* Sit the column in the left half of the page, tucked up against the centre
   line, once the viewport is wide enough to hold it there without cramping
   the left edge. Below this it stays centred. */
@media (min-width: 80rem) {
  main {
    margin-left: auto;
    margin-right: 50%;
  }
}

/* --- Type ------------------------------------------------------ */

/* One face, one weight, top to bottom. Headings separate from copy by
   colour and size — they sit at full --text while the paragraphs run at
   --text-2, and that's contrast enough without a bold. */
h1,
h2,
h3 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 400;
  letter-spacing: -0.005em;
}

/* The name runs one step over the company headings — enough to lead the
   page, not so much that it becomes a masthead. */
h1 {
  font-size: var(--fs-name);
  letter-spacing: -0.01em;
  line-height: 1.3;
}

h3 {
  font-size: var(--fs-head);
  line-height: 1.4;
}

/* The role after the company name is context, not title — same face, same
   weight, one step lighter in colour. */
h3 .muted {
  font-size: var(--fs-copy);
  letter-spacing: 0;
}

p {
  margin: 0;
}

a {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: var(--link-underline);
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  transition: text-decoration-color 120ms ease, color 120ms ease;
}

a:hover {
  text-decoration-color: currentColor;
}

a:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 3px;
  border-radius: 2px;
}

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

.sep {
  color: var(--faint);
  padding: 0 0.15em;
}

/* --- Intro ----------------------------------------------------- */

.intro {
  margin-bottom: 3.25rem;
}

.intro .role {
  color: var(--muted);
  margin-top: 0.45rem;
}

.intro .bio {
  margin-top: 1.15rem;
  max-width: 33rem;
  color: var(--text-2);
}

.links {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.35rem;
  margin: 1.35rem 0 0;
  padding: 0;
  list-style: none;
  font-size: 0.9375rem;
  color: var(--muted);
}

.links a {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  color: var(--muted);
  text-decoration: none;
}

.links a:hover {
  color: var(--text);
}

/* Underline the label only, so the icon never picks up a rule under it. */
.links a:hover span {
  text-decoration: underline;
  text-decoration-color: currentColor;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

.links svg {
  width: 15px;
  height: 15px;
  flex: none;
  fill: currentColor;
  opacity: 0.7;
  transition: opacity 120ms ease;
}

.links a:hover svg {
  opacity: 1;
}

.links a span {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.links svg {
  width: 17px;
  height: 17px;
}

.links {
  gap: 1.15rem;
}


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

section {
  margin-bottom: 2.75rem;
}

section>h2 {
  font-size: var(--fs-label);
  color: var(--faint);
  letter-spacing: 0.05em;
  padding-bottom: 0.7rem;
  margin-bottom: 1.45rem;
  border-bottom: 1px solid var(--rule);
}

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

/* Everything hangs off the left margin — no date gutter. */
.entry {
  margin-bottom: 1.75rem;
}

/* Older roles and one-line items sit tighter — recency gets the space. */
.entry--brief {
  margin-bottom: 1.1rem;
}

.entry:last-child {
  margin-bottom: 0;
}

/* Dates and scope on one subdued line under the heading. */
.meta {
  color: var(--faint);
  font-style: italic;
  font-size: var(--fs-meta);
  margin-top: 0.2rem;
  font-variant-numeric: tabular-nums;
}

.entry>p {
  color: var(--text-2);
  margin-top: 0.5rem;
  max-width: 33rem;
}

/* Focus rows read as term → definition, so the label sits above. */
.entry--term>.meta {
  margin-top: 0;
}

.entry--term>.meta+p {
  margin-top: 0.1rem;
}

/* Earlier title at the same company — keeps one tenure as one entry. */
.entry>p.prior {
  color: var(--faint);
  font-size: var(--fs-meta);
  margin-top: 0.55rem;
}

/* Stacked prior titles read as one list, not two separate notes. */
.entry>p.prior+p.prior {
  margin-top: 0.1rem;
}

/* Unused as written — kept for any role that genuinely needs a list. */
.entry ul {
  margin: 0.8rem 0 0;
  padding: 0;
  list-style: none;
  max-width: 33rem;
}

.entry ul li {
  position: relative;
  padding-left: 1.05rem;
  color: var(--text-2);
  line-height: 1.55;
  margin-bottom: 0.5rem;
}

/* Colour does the work here, not weight — any bold at this size speckles
   the paragraph. */
.entry strong {
  font-weight: inherit;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

.entry ul li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.7em;
  width: 4px;
  height: 1px;
  background: var(--faint);
}

.entry ul li:last-child {
  margin-bottom: 0;
}

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

footer {
  margin-top: 3.5rem;
  padding-top: 1.4rem;
  border-top: 1px solid var(--rule);
  color: var(--muted);
  font-size: var(--fs-copy);
}

footer .muted {
  margin-top: 0.35rem;
  color: var(--faint);
}

/* --- Small screens --------------------------------------------- */

@media (max-width: 34rem) {
  main {
    padding: 3rem 1.35rem 4rem;
  }

  .intro {
    margin-bottom: 3.5rem;
  }
}

/* --- Print ------------------------------------------------------ */

@media print {
  :root {
    --bg: #fff;
    --text: #000;
    --muted: #333;
    --faint: #666;
    --rule: #ddd;
  }

  /* Grain is a screen effect — on paper it's just toner. */
  body::before {
    display: none;
  }

  main {
    padding: 0;
    max-width: none;
  }

  a {
    text-decoration: none;
  }

  section {
    break-inside: avoid;
  }
}