/* mostlywork.ing */

@font-face {
  font-family: "Instrument Sans";
  src: url("/fonts/instrument-sans.woff2") format("woff2");
  font-weight: 400 700;
  font-stretch: 75% 100%;
  font-style: normal;
  font-display: swap;
}

/* TRIAL licence only: replace with licensed files before this goes live. */
@font-face {
  font-family: "TRJN DaVinci";
  src: url("/fonts/trjn-davinci-semibold-trial.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "TRJN DaVinci";
  src: url("/fonts/trjn-davinci-italic-trial.woff2") format("woff2");
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}

:root {
  color-scheme: light;

  --paper: #ffffff;
  --ink: #141413;

  /* Characters the display face lacks (e.g. ’) fall back to the sans. */
  --display: "TRJN DaVinci", var(--sans);
  --sans: "Instrument Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;

  --body-size: clamp(18px, 1.6vw, 22px);

  --gutter: clamp(16px, 4vw, 48px);
  --bleed: 12px;

  /* Space under the ✱ logo, in proportion to the heading below it. On one
     line (the heading's size is about the content width / 6.55) its
     ascenders rise about 0.11em above the line box, so the gap allows for
     that plus about 0.1em of clear space. */
  --logo-gap: calc(min((100vw - 2 * var(--gutter)) / 6.55, 300px) * 0.21);
  --ease-out: cubic-bezier(0.2, 0.7, 0.2, 1);
}

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

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

body {
  margin: 0;
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  padding: 0 var(--gutter);
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--body-size);
  line-height: 1.3;
  letter-spacing: -0.01em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-kerning: normal;
}

main {
  flex: 1;
}

h1,
h2,
p,
ol {
  margin: 0;
}

h2 {
  font: inherit;
}

a {
  color: inherit;
}

::selection {
  background: var(--ink);
  color: var(--paper);
}

:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 4px;
}

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

/*
  Type: three styles, used everywhere, all in ink.
  1. Display  TRJN DaVinci Semibold  the page heading  (.intro h1)
  2. Title    TRJN DaVinci Italic    project names     (.project-name)
  3. Body     Instrument Sans        everything else   (body)
*/

/* Masthead */

/* The page's top space sits above the logo, so the ✱ rests just over
   the heading. */
.masthead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: clamp(56px, 16vh, 184px) 0 var(--logo-gap, 24px);
}

.home {
  display: block;
  margin: -6px;
  padding: 6px;
}

/* The ✱ logo (482 × 502) */
.logo {
  display: block;
  height: clamp(40px, 4.5vw, 72px);
  width: auto;
  aspect-ratio: 482 / 502;
  fill: currentColor;
  /* Rises in with the heading it sits on, first thing on load */
  animation: rise 0.9s var(--ease-out) backwards;
}

/* Intro */

.intro {
  container-type: inline-size;
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: 24px;
  align-items: baseline;
  padding: 0 0 clamp(72px, 14vh, 152px);
}

.intro h1 {
  grid-column: 1 / -1;
  font-family: var(--display);
  /* One line that fills the column: "mostlywork.ing" is 6.45em wide. */
  font-size: min(calc((100vw - 2 * var(--gutter)) / 6.55), 300px);
  font-size: min(calc(100cqi / 6.55), 300px);
  font-weight: 600;
  line-height: 0.82;
  letter-spacing: -0.05em;
}

/* On narrow screens one line would be small, so it breaks after "mostly"
   (at the <wbr>) and "work.ing", 3.68em wide, fills the column. */
@container (max-width: 520px) {
  .intro h1 {
    font-size: calc(100cqi / 3.74);
    /* Just enough to keep the y of "mostly" off the dot of the i */
    line-height: 1;
  }
}

/* 404: a sentence, so it wraps naturally at a more modest size */
.statement h1 {
  max-width: 14ch;
  font-size: min(15.2cqi, calc(20px + 9.5cqi), 184px);
  line-height: 0.82;
  text-wrap: balance;
}

.lede {
  /* Eight columns: room for the lede on one line on desktop, stopping
     just short of the contact block at column 9. */
  grid-column: 1 / span 8;
  margin-top: clamp(24px, 4vw, 48px);
  text-wrap: pretty;
}

.lede a {
  text-decoration-thickness: 1px;
  text-underline-offset: 0.15em;
}

.lede a:hover {
  text-decoration-thickness: 2px;
}

/* Homepage: main is the grid. The intro's children join it, so the
   contact block (after the projects in the HTML) can sit beside the lede
   on wider screens and follow the projects on phones. */

.homepage {
  container-type: inline-size;
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: 24px;
  align-items: baseline;
  align-content: start;
}

.homepage > .intro {
  display: contents;
  /* main is the size container here, not the intro */
  container-type: normal;
}

.homepage .contact {
  grid-row: 2;
}

.homepage > .projects {
  grid-column: 1 / -1;
  grid-row: 3;
  align-self: start;
  margin-top: clamp(72px, 14vh, 152px);
}

/* Contact */

.contact {
  grid-column: 9 / -1;
  margin-top: clamp(24px, 4vw, 48px);
  font-style: normal;
}

.contact dl,
.contact dd {
  margin: 0;
}

.contact dd + dt {
  margin-top: 1.3em;
}

.contact a {
  text-decoration: none;
}

.contact a:hover,
.contact a:focus-visible {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.15em;
}

.intro > * {
  animation: rise 0.9s var(--ease-out) backwards;
}

.intro > :nth-child(2) {
  animation-delay: 0.08s;
}

/* The contact block lives outside the intro (so it can follow the projects
   on phones) but rises in with it, just after the lede. */
.contact {
  animation: rise 0.9s var(--ease-out) 0.16s backwards;
}

/* Projects */

.projects {
  padding-bottom: clamp(72px, 12vh, 128px);
}

.projects h2 {
  padding-bottom: 14px;
  animation: rise 0.9s var(--ease-out) 0.16s backwards;
}

/* The rules are drawn with pseudo-elements rather than borders so they
   can draw in from the left on load, each just after its row rises. */

.index {
  position: relative;
  list-style: none;
  margin: 0 calc(-1 * var(--bleed));
  padding: 1px 0 0;
}

.index li {
  position: relative;
  padding-bottom: 1px;
}

.index::before,
.index li::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--ink);
  transform-origin: 0 50%;
  animation: draw 1.1s var(--ease-out) backwards;
  pointer-events: none;
}

.index::before {
  top: 0;
  animation-delay: 0.2s;
}

.index li::after {
  bottom: 0;
  animation-delay: calc(0.3s + var(--i, 0) * 0.08s);
}

/* Each row's link reaches 1px down under its rule (which lets the pointer
   through), so neighbouring rows touch: moving between them never passes
   over a gap where neither is hovered, which made the fill flicker. */
.project {
  margin-bottom: -1px;
}

/* On load the row's contents rise, not the link itself, so its hover area
   never moves under a still pointer (which could hand the hover to the
   next row). */
.project > * {
  animation: rise 0.9s var(--ease-out) backwards;
  animation-delay: calc(0.24s + var(--i, 0) * 0.08s);
}

.project {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  align-items: baseline;
  column-gap: 24px;
  padding: clamp(18px, 2.4vw, 30px) var(--bleed) calc(clamp(18px, 2.4vw, 30px) + 1px);
  text-decoration: none;
}

/* Hover is a plain instant switch. Nothing about the hovered state moves,
   fades or changes the row's shape, so there is no half-state, no restarted
   fade and no hover-dependent hit-testing that could flicker. Only on
   devices that really hover, so a tapped row on a phone doesn't stick. */
@media (hover: hover) {
  .project:hover {
    background: var(--ink);
    color: var(--paper);
  }

  .project:hover .arrow {
    transform: translate(3px, -3px);
  }
}

/* Keyboard focus is a ring, not the black fill. A clicked row keeps focus
   (its link opens a new tab), and after any key press browsers show that
   focus, so a fill here lit up a second row while another was hovered. */
.project:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: -2px;
}

.project-num {
  grid-column: span 1;
}

.project-name {
  font-family: var(--display);
  font-size: clamp(36px, 5vw, 76px);
  font-style: italic;
  font-weight: 400;
  line-height: 1;
  letter-spacing: -0.03em;
  grid-column: span 4;
}

.project-desc {
  grid-column: span 4;
  text-wrap: pretty;
}

.project-url {
  display: flex;
  align-items: baseline;
  gap: 0.3em;
  grid-column: span 3;
  justify-self: end;
  white-space: nowrap;
}

/* ↗ drawn to Instrument Sans's metrics: 0.72em cap height, 0.08em stems.
   It sits on the baseline, so it lines up with the text on every device
   (the font has no ↗ glyph, so a text arrow would come from a fallback). */
.arrow {
  flex: none;
  width: 0.72em;
  height: 0.72em;
  fill: none;
  stroke: currentColor;
  stroke-width: 8;
  overflow: visible;
}

.project:focus-visible .arrow {
  transform: translate(3px, -3px);
}

/* Colophon */

.colophon {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 8px 24px;
  padding: 24px 0 28px;
}

/* Two-line heading (content under 520px wide, so viewport under ~565px):
   size the logo gap from that larger size. Its line height is 1, so the
   ascenders barely overhang. */
@media (max-width: 565px) {
  :root {
    --logo-gap: calc((100vw - 2 * var(--gutter)) / 3.74 * 0.16);
  }
}

/* Small screens */

@media (max-width: 860px) {
  :root {
    --bleed: 8px;
  }

  .intro {
    grid-template-columns: minmax(0, 1fr);
  }

  .homepage {
    grid-template-columns: minmax(0, 1fr);
  }

  .lede,
  .contact {
    grid-column: 1 / -1;
  }

  /* Phones: the contact block follows the projects */
  .homepage .contact,
  .homepage > .projects {
    grid-row: auto;
  }

  .homepage .contact {
    margin-top: 0;
    padding-bottom: 24px;
  }

  .project {
    grid-template-columns: auto 1fr;
    grid-template-areas:
      "num url"
      "name name"
      "desc desc";
    row-gap: 10px;
  }

  .project-num {
    grid-area: num;
  }

  .project-name {
    grid-area: name;
    margin-top: 6px;
  }

  .project-desc {
    grid-area: desc;
  }

  .project-url {
    grid-area: url;
  }
}

/* Motion */

@keyframes rise {
  from {
    opacity: 0;
    transform: translateY(16px);
  }
}

@keyframes draw {
  from {
    transform: scaleX(0);
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation: none !important;
    transition: none !important;
  }
}
