/* ============================================================
   Kaleb Poulsen — portfolio
   Tokens first, then layout. Everything is flat and low
   specificity: one class does one job, nothing overrides.
   ============================================================ */

:root {
  /* Mostly white, some black. The page is white; black is spent
     on type and edges only. No cast in the neutrals — any colour
     here belongs to the work, not to the chrome. */
  --daylight:  #FFFFFF;   /* page ground        */
  --plaster:   #F4F4F4;   /* image ground       */
  --graphite:  #000000;   /* ink — the black    */
  --slate:     #6B6B6B;   /* metadata           */
  --hairline:  #E2E2E2;   /* rules              */
  --mark:      #000000;   /* emphasis, focus    */

  --display: "Familjen Grotesk", ui-sans-serif, system-ui, sans-serif;
  --read:    "Newsreader", Georgia, "Times New Roman", serif;
  --label:   "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;

  /* The hang scale: px of screen per cm of real artwork.
     This is what makes a drawing read small next to a painting.
     Each work sets --cm (its real width in cm) for size, and
     --w / --h (the file's pixel dimensions) for shape. Keeping
     the two apart means a photo never gets stretched to fit. */
  --hang: 0.26vw;   /* px of screen per cm of artwork */

  --gutter: clamp(1.5rem, 5vw, 6rem);
  --rule: 1px solid var(--hairline);
}

/* This design is committed to one look: white ground, black type.
   There is deliberately no prefers-color-scheme inversion — a full-black
   dark mode would invert the brief. See the README before adding one. */

@media (max-width: 900px) { :root { --hang: 0.36vw; } }

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

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

body {
  margin: 0;
  background: var(--daylight);
  color: var(--graphite);
  font-family: var(--read);
  font-size: 1.0625rem;
  line-height: 1.65;
  font-synthesis: none;
  -webkit-font-smoothing: antialiased;
}

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

a { color: inherit; text-decoration: none; }

:focus-visible {
  outline: 2px solid var(--mark);
  outline-offset: 3px;
}

.skip {
  position: absolute; left: -9999px;
  background: var(--graphite); color: var(--daylight);
  padding: 0.6rem 1rem;
}
.skip:focus { left: var(--gutter); top: 0.75rem; z-index: 20; }

/* ---------- the label voice: mono, small, letterspaced ---------- */

.mono {
  font-family: var(--label);
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--slate);
  font-weight: 400;
}

/* ---------- shell ---------- */

.wrap { max-width: 84rem; margin: 0 auto; padding: 0 var(--gutter); }

.masthead {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 2rem;
  flex-wrap: wrap;
  padding: 1.75rem 0;
  border-bottom: var(--rule);
}

.masthead-name {
  font-family: var(--display);
  font-size: 0.9375rem;
  font-weight: 500;
  letter-spacing: 0.02em;
  margin: 0;
}

.nav { display: flex; gap: 1.75rem; }

.nav a { position: relative; padding-bottom: 2px; }

.nav a:hover,
.nav a[aria-current="page"] { color: var(--graphite); }

.nav a[aria-current="page"]::after {
  content: "";
  position: absolute; inset: auto 0 -1px 0;
  border-bottom: 1px solid var(--mark);
}

/* ---------- banner ---------- */

/* A wide crop across the top of the index. It is not a work, so it carries
   no label and does not link anywhere. */
.banner {
  margin: 0 0 clamp(1rem, 2.5vh, 2rem);
}

.banner img {
  width: 100%;
  height: clamp(220px, 46vh, 580px);
  object-fit: cover;
  object-position: center 45%;
  outline: 1px solid var(--hairline);
  outline-offset: -1px;
}

/* ---------- hero ---------- */

/* After a banner the hero needs less breathing room above it, so that the
   banner, the name and the line under it all land on the first screen. */
.banner + .hero { padding-top: clamp(0.5rem, 1.5vh, 1.5rem); }

.hero { padding: clamp(4rem, 14vh, 9rem) 0 clamp(3rem, 9vh, 6rem); }

.hero-name {
  font-family: var(--display);
  font-weight: 500;
  font-size: clamp(2.4rem, 7.4vw, 5.75rem);
  line-height: 0.92;
  letter-spacing: -0.035em;
  margin: 0 0 1.75rem;
  max-width: 14ch;
}

.hero-line {
  font-size: clamp(1.125rem, 2vw, 1.5rem);
  line-height: 1.45;
  max-width: 32ch;
  margin: 0;
  color: var(--graphite);
}

.hero-meta { margin-top: 2.5rem; }

/* The one button on the site. Mono and uppercase like the labels, a hairline
   box rather than a filled shape, inverting on hover. */
.cta {
  display: inline-block;
  margin-top: clamp(1.75rem, 4vh, 2.75rem);
  padding: 0.8rem 1.5rem;
  border: 1px solid var(--graphite);
  font-family: var(--label);
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--graphite);
  transition: background-color 200ms ease, color 200ms ease;
}

.cta:hover {
  background: var(--graphite);
  color: var(--daylight);
}

/* ---------- the wall ---------- */

.wall {
  list-style: none;
  margin: 0;
  padding: 0 0 clamp(4rem, 12vh, 8rem);
}

.work {
  display: flex;
  align-items: center;          /* the hang line: labels centre on the work */
  gap: clamp(1.5rem, 4vw, 4rem);
  padding: clamp(3rem, 9vh, 7rem) 0;
  border-top: var(--rule);
}

.work:nth-child(even) { flex-direction: row-reverse; }

/* Width comes from --cm, the work's real width in centimetres, so a 28cm
   drawing is genuinely smaller than a 200cm painting. Shape comes from
   --w/--h, the file's own pixel dimensions, so nothing gets stretched. */
.work-figure {
  margin: 0;
  flex: 0 1 auto;
  min-width: 0;
  max-width: 100%;
  width: clamp(7.5rem, calc(var(--cm) * var(--hang)), 52rem);
}

.work-figure img {
  width: 100%;
  aspect-ratio: var(--w) / var(--h);
  background: var(--plaster);
  outline: 1px solid var(--hairline);
  outline-offset: -1px;
}

.work-link { display: block; }
.work-link img { transition: opacity 220ms ease; }
.work-link:hover img { opacity: 0.86; }

.work-label { flex: 0 1 16rem; }

.work-title {
  font-family: var(--read);
  font-style: italic;
  font-weight: 400;
  font-size: 1.25rem;
  line-height: 1.25;
  margin: 0 0 0.4rem;
}

.work-link:hover .work-title {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.16em;
}

.work-medium {
  margin: 0 0 0.75rem;
  color: var(--slate);
  font-size: 1rem;
  line-height: 1.45;
}

.work-dims { display: block; }

@media (max-width: 760px) {
  .work,
  .work:nth-child(even) {
    flex-direction: column;
    align-items: flex-start;
    gap: 1.25rem;
  }
  .work-label { flex: 1 1 auto; max-width: 30rem; }
}

/* ---------- single work ---------- */

/* A way out, at the top where it is reachable without scrolling past the
   whole work. The pager at the foot of the page does the same job for
   anyone who has already read to the bottom. */
.plate-back { padding: 1.25rem 0 0; }

.plate-back a:hover {
  color: var(--graphite);
  text-decoration: underline;
  text-underline-offset: 0.3em;
}

.plate { padding: clamp(2.5rem, 7vh, 5rem) 0; }

.plate-figure {
  margin: 0 auto;
  max-width: 100%;
  width: clamp(12rem, calc(var(--cm) * var(--hang) * 1.55), 52rem);
}

.plate-figure img {
  width: 100%;
  aspect-ratio: var(--w) / var(--h);
  background: var(--plaster);
  outline: 1px solid var(--hairline);
  outline-offset: -1px;
}

.plate-label {
  margin: clamp(2rem, 5vh, 3.5rem) 0 0;
  padding-top: 1.5rem;
  border-top: var(--rule);
  display: grid;
  grid-template-columns: minmax(0, 22rem) minmax(0, 30rem);
  gap: clamp(1.5rem, 5vw, 5rem);
  align-items: start;
}

@media (max-width: 760px) { .plate-label { grid-template-columns: 1fr; } }

.plate-title {
  font-family: var(--read);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(1.5rem, 3vw, 2rem);
  line-height: 1.2;
  margin: 0 0 0.5rem;
}

.plate-note { margin: 0; color: var(--slate); }
.plate-note + .plate-note { margin-top: 1rem; }

.pager {
  display: flex;
  justify-content: space-between;
  gap: 2rem;
  padding: 2rem 0 clamp(4rem, 10vh, 7rem);
  border-top: var(--rule);
}

.pager a:hover { color: var(--graphite); text-decoration: underline; text-underline-offset: 0.3em; }

/* ---------- info ---------- */

.lede {
  font-size: clamp(1.375rem, 2.6vw, 1.875rem);
  line-height: 1.35;
  max-width: 26ch;
  margin: 0;
  font-family: var(--display);
  font-weight: 400;
  letter-spacing: -0.015em;
}

.section {
  display: grid;
  grid-template-columns: minmax(0, 11rem) minmax(0, 44rem);
  gap: clamp(1rem, 4vw, 4rem);
  padding: clamp(2.5rem, 6vh, 4rem) 0;
  border-top: var(--rule);
}

@media (max-width: 760px) {
  .section { grid-template-columns: 1fr; gap: 1.25rem; }
}

.section-body > :first-child { margin-top: 0; }
.section-body > :last-child { margin-bottom: 0; }
.section-body p { max-width: 62ch; }

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

.entries li {
  display: grid;
  grid-template-columns: 4.5rem 1fr;
  gap: 1rem;
  padding: 0.7rem 0;
  border-bottom: var(--rule);
}

.entries li:last-child { border-bottom: 0; }

.entries .mono { padding-top: 0.35rem; }

.entry-name { font-style: italic; }
.entry-where { color: var(--slate); }

.inline-link {
  color: var(--mark);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}

.inline-link:hover { text-decoration-thickness: 2px; }

/* ---------- footer ---------- */

.foot {
  display: flex;
  justify-content: space-between;
  gap: 2rem;
  flex-wrap: wrap;
  padding: 2rem 0 3rem;
  border-top: var(--rule);
}

.foot a:hover { color: var(--graphite); text-decoration: underline; text-underline-offset: 0.3em; }

/* Show the address exactly as it is typed — the mono style uppercases
   everything else in the footer, which would misrepresent it. */
.foot a[href^="mailto:"] { text-transform: none; letter-spacing: 0.06em; }

/* ---------- motion ---------- */

.reveal { opacity: 0; transform: translateY(12px); }

.reveal-in {
  opacity: 1;
  transform: none;
  transition: opacity 700ms ease, transform 700ms cubic-bezier(0.2, 0.7, 0.3, 1);
}

@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; }
  * {
    animation-duration: 0.01ms !important;
    animation-delay: 0ms !important;
    transition-duration: 0.01ms !important;
  }
}
