/* ==========================================================================
   Design tokens — edit here to retune the whole site.
   ========================================================================== */

:root {
  /* Palette */
  --paper:        #ffffff;
  --ink:          #253340;   /* body text */
  --muted:        #7a7a7a;   /* section labels */
  --nav-ink:      #8c8c8c;   /* nav links, project dates, corner mark */
  --orange:       #f1600d;   /* display headings */
  --green:        #8cc63e;   /* nav active state */

  /* Media panel backgrounds (also baked into the placeholder images) */
  --panel-super:  #dceefc;
  --panel-role:   #14403e;
  --panel-empty:  #c4c4c4;

  /* Type */
  --font-display: "p22-mackinac-pro", "P22 Mackinac", Georgia, "Times New Roman", serif;
  --font-body:    "Google Sans Code", ui-monospace, SFMono-Regular, Menlo, monospace;

  --display-tracking: -0.04em;   /* Mackinac runs loose at display sizes */

  --fs-h1:        80px;
  --fs-h2:        56px;
  --fs-body:      16px;
  --fs-nav:       16px;
  --lh-body:      1.8;       /* multiplier on --fs-body */

  /* Layout */
  --content-width: 704px;
  --column-shift:  0px;      /* negative nudges the column left of centre */
  --radius:        6px;      /* corner rounding on image containers */
  --image-stroke:  rgba(0, 0, 0, 0.1);
  --nav-inset:     72px;
  --nav-gap:       13.5px;   /* gap between nav items, on top of the line box */

  /* Vertical rhythm — tuned to the Figma's baselines */
  --space-page-top:     168px;   /* 210 - 20% */
  --space-h1:           35px;
  --space-section:      64px;   /* above the label */
  --space-label:        64px;   /* below it — deliberately equal, so the label
                                   sits centred in the gap between sections */
  --space-heading:      19px;
  --space-before-media: 43px;
  --space-after-media:  30px;
  --space-paragraph:    40px;
  --space-project:      90px;
}

/* ==========================================================================
   Reset
   ========================================================================== */

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

body, h1, h2, h3, p, figure { margin: 0; }

html {
  /* The design is light-only. Without this the browser paints dark scrollbars
     and form controls for visitors whose OS is set to dark mode. */
  color-scheme: light;
  background: var(--paper);

  scroll-behavior: smooth;
  /* Reserve the scrollbar so the fixed navs don't shift when it appears. */
  scrollbar-gutter: stable;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

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

body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
}

/* ==========================================================================
   Layout — the page scrolls natively; the column just sits in normal flow.
   ========================================================================== */

main {
  /* Exactly --content-width when there's room, with 24px gutters when there isn't. */
  width: min(100% - 48px, var(--content-width));
  margin-inline: auto;
  padding: var(--space-page-top) 0 120px;
  transform: translateX(var(--column-shift));
}

/* ==========================================================================
   Fixed navs
   ========================================================================== */

/* Fixed column on the page's horizontal centreline. */
.nav {
  position: fixed;
  top: 50%;
  left: var(--nav-inset);
  transform: translateY(-50%);
  display: flex;
  flex-direction: column;
  gap: var(--nav-gap);
  z-index: 10;
}

/* Nav links and project dates share one type treatment, so they stay in sync. */
.nav a,
.project-dates {
  font-family: var(--font-body);
  font-size: var(--fs-nav);
  font-weight: 400;
}

.nav a {
  color: var(--nav-ink);
  text-decoration: none;
  /* Fixed, so nav spacing stays tight rather than inheriting body leading. */
  line-height: 24px;
}

.nav a:hover,
.nav a:focus-visible { color: var(--orange); }

/* Set by main.js as you scroll. */
.nav a[aria-current="true"] {
  color: var(--orange);
}

/* Decorative mark, pinned to the bottom-left corner. */
.footer-mark {
  position: fixed;
  left: var(--nav-inset);
  bottom: var(--nav-inset);
  font-size: 20px;
  line-height: 1;
  color: var(--nav-ink);
  z-index: 10;
  pointer-events: none;
}

/* ==========================================================================
   Intro
   ========================================================================== */

/* The headline treatment, shared so the two can't drift apart. */
h1,
.display {
  font-family: var(--font-display);
  font-size: var(--fs-h1);
  font-weight: 400;
  line-height: 1.05;
  letter-spacing: var(--display-tracking);
  color: var(--orange);
}

h1 { margin-bottom: var(--space-h1); }

/* Decorative glyph closing the sign-off. line-height: 0 keeps it from
   stretching the line box whatever size it's set to. */
.flourish {
  font-size: 1em;
  line-height: 0;
}

/* .display carries no bottom margin; the space before the contact links
   lives on the links themselves. */



/* Decorative mark in the headline. */
.glyph {
  font-size: 0.45em;
  vertical-align: 0.5em;
  margin-left: 0.39em;       /* ~14px; on top of the word space before it */
  white-space: nowrap;
}

/* ==========================================================================
   Sections
   ========================================================================== */

section { scroll-margin-top: 120px; }

/* "Hi" lands at the very top of the page rather than at the headline. The
   intro sits exactly --space-page-top from the top, so cancelling that much
   scroll margin puts the target at 0 — and it stays right if the padding changes. */
#intro { scroll-margin-top: var(--space-page-top); }

.section-label {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-body);
  font-size: var(--fs-body);
  font-weight: 400;
  line-height: var(--lh-body);
  color: var(--nav-ink);
  /* Guarantees the leading capital whatever case the markup is typed in. */
  text-transform: capitalize;
  -webkit-user-select: none;
  user-select: none;
  margin-top: var(--space-section);
  margin-bottom: var(--space-label);
}

/* Leading marker. */
.section-label::before {
  content: "+";
  flex: none;
}

/* ==========================================================================
   Projects — <article class="project"> is the repeating unit.
   ========================================================================== */

.project + .project { margin-top: var(--space-project); }

.project h3 {
  /* Flex so the dates sit on the project name's centre line rather than
     riding above its baseline. */
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 19px;
  font-weight: 400;
  line-height: 1.05;
  margin-bottom: var(--space-heading);
}

.project-name {
  font-family: var(--font-display);
  font-size: var(--fs-h2);
  letter-spacing: var(--display-tracking);
  color: var(--orange);
}

.project-dates {
  color: var(--nav-ink);
  /* Optical correction. align-items: center lines up the two boxes, but the
     name's box carries a big descender, so its letterforms sit higher than the
     box centre. Nudging the dates down puts the x-heights on one line. */
  transform: translateY(0.2em);
}

main p + p { margin-top: var(--space-paragraph); }

/* Links in prose: bold + underline. Emphasis: bold only. */
main p a {
  color: inherit;
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 3px;
}

main p a:hover,
main p a:focus-visible { color: var(--orange); }

main p em { font-weight: 700; font-style: normal; }

.contact-links {
  margin-top: 48px;
  display: flex;
  flex-wrap: wrap;
  gap: 24px;
}

.contact-links a {
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.contact-links a:hover,
.contact-links a:focus-visible { color: var(--orange); }

/* ==========================================================================
   Media
   ========================================================================== */

.project-media {
  position: relative;
  margin: var(--space-before-media) 0 var(--space-after-media);
  aspect-ratio: 16 / 9;      /* matches the exports exactly, so nothing is cropped */
  border-radius: var(--radius);
  background: var(--panel-empty);
  overflow: hidden;
}

.project-media img { width: 100%; height: 100%; object-fit: cover; }

/* 1px inner stroke. Drawn as a pseudo-element rather than an inset shadow on
   the figure itself, because an inset shadow paints beneath child content and
   the image would cover it. */
.project-media::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: inset 0 0 0 1px var(--image-stroke);
  pointer-events: none;
}

/* ==========================================================================
   Load-in

   Everything on first screen fades up, ordered top to bottom. main.js assigns
   each element its --fade-delay; anything below the fold keeps 0 and is simply
   there by the time you scroll to it.

   Wrapped in no-preference so that visitors who ask for reduced motion never
   get the opacity: 0 in the first place.
   ========================================================================== */

@media (prefers-reduced-motion: no-preference) {
  .js .nav a,
  .js .intro h1,
  .js .intro p,
  .js .section-label,
  .js .project h3,
  .js .project p,
  .js .project-media,
  .js .display,
  .js .contact-links,
  .js .footer-mark {
    opacity: 0;
    animation: fade-in 0.7s cubic-bezier(0.2, 0.6, 0.2, 1) var(--fade-delay, 0ms) forwards;
  }

  /* Anything below the fold is held here until it scrolls into view, so the
     page keeps fading in as you go rather than being pre-revealed. */
  .js .fade-wait { animation-play-state: paused; }

  @keyframes fade-in {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: none; }
  }
}

/* ==========================================================================
   Narrow screens.

   Two breakpoints doing two different jobs:
   1250px is where the column (800px) plus both navs plus their 72px insets
   stop fitting side by side, so the navs rejoin the document flow.
   900px is where the display type stops being appropriate and scales down.
   ========================================================================== */

@media (max-width: 1250px) {
  /* The bar's own padding-bottom carries most of the gap to the headline now,
     so this is smaller. Applies to every width below 1250. */
  :root { --space-page-top: 16px; }

  /* The wrapper becomes the sticky top bar. It needs an opaque background,
     or content would show through as it scrolls underneath. */
  .chrome {
    position: sticky;
    top: 0;
    z-index: 10;
    /* Eased fade rather than a plain two-stop ramp: a linear alpha ramp reads
       as a visible band, because perceived brightness isn't linear. These stops
       follow a smooth curve so the edge disappears. */
    background: linear-gradient(
      to bottom,
      rgba(255, 255, 255, 1)     0%,
      rgba(255, 255, 255, 1)     50%,
      rgba(255, 255, 255, 0.987) 54%,
      rgba(255, 255, 255, 0.951) 57.8%,
      rgba(255, 255, 255, 0.896) 61.3%,
      rgba(255, 255, 255, 0.825) 64.5%,
      rgba(255, 255, 255, 0.741) 67.7%,
      rgba(255, 255, 255, 0.648) 70.6%,
      rgba(255, 255, 255, 0.55)  73.7%,
      rgba(255, 255, 255, 0.45)  76.3%,
      rgba(255, 255, 255, 0.352) 79.4%,
      rgba(255, 255, 255, 0.259) 82.4%,
      rgba(255, 255, 255, 0.175) 85.1%,
      rgba(255, 255, 255, 0.104) 88.8%,
      rgba(255, 255, 255, 0.049) 92.3%,
      rgba(255, 255, 255, 0.013) 96%,
      rgba(255, 255, 255, 0)     100%
    );
    width: min(100% - 48px, var(--content-width));
    margin-inline: auto;
    padding: 40px 0 96px;
    display: flex;
    justify-content: space-between;   /* nav left, mark right */
    align-items: center;
    /* The faded lower half still sits over the content, so let clicks through
       and re-enable them on the bar's own contents. */
    pointer-events: none;
  }

  .nav { pointer-events: auto; }

  .nav {
    position: static;
    transform: none;
    flex-direction: row;
    flex-wrap: wrap;
    gap: 24px;
  }

  /* The mark joins the bar as its second item, so it sits at the right end. */
  .footer-mark {
    position: static;
    transform: none;
  }

  main {
    transform: none;
    padding-bottom: 80px;
  }
}

@media (max-width: 900px) {
  .footer-mark { display: none; }

  :root {
    --fs-h1:   46px;
    --fs-h2:   38px;
    --fs-body: 16px;

    --space-h1:           24px;
    --space-heading:      12px;
    --space-before-media: 28px;
    --space-after-media:  24px;
    --space-paragraph:    28px;
    --space-project:      56px;
    }
}
