/*
 * Your tweaks go here.
 *
 * This file is loaded after every Webflow stylesheet, so anything in it wins without
 * needing !important. Put changes here rather than editing asher-khan.webflow.css next to
 * it, which is machine-written and best left alone.
 *
 * Class names to target are in asher-khan.webflow.css. The ones the page actually uses:
 * .heading-1, .heading-3, .p2, .paragraph, .caption, .chip, .project, .project-image,
 * .footer-chip, .hero-content.
 */

:root {
  /* Mirrored by `layout` in scripts/config.mjs, which sizes the generated images. */
  --content-width: 780px;
  --content-gutter: 40px;
  /* Keep in step with logoHeight in content/logos.mjs, which sizes the img attributes. */
  --logo-height: 24px;
  --logo-gap: 64px;
  /* The display face and its weight. Neither self-hosted family is variable, so this may
   * only be a weight that exists as a real file: 400 or 500 for Libre Caslon Condensed,
   * 400 or 700 for Libre Caslon Text. Anything else makes the browser round to the nearest
   * cut, or fake one, while the CSS claims otherwise. Changing either line means updating
   * preloadFonts in scripts/config.mjs to match — npm run verify catches a mismatch. */
  --title-font: 'Libre Caslon Condensed';
  --title-weight: 400;
}

/*
 * Light text on a dark background gains weight under macOS subpixel antialiasing, which
 * is what made Inter look heavier here than on light-background sites. Grayscale
 * antialiasing renders it at its intended weight.
 */
body {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/*
 * Page background. Matched by the theme-color meta tag in scripts/patch-html.mjs, which
 * tints the browser chrome on mobile — leaving them different shows as a seam above the
 * page. The class selector is needed: the export sets this on .body, which would outrank a
 * plain `body` rule here no matter that this file loads later.
 */
.body {
  background-color: #141414;
}

/*
 * One measure for every section. The export sized each section by hard-coding side
 * padding instead of capping the column, which is why the footer sat 80px wider than
 * the hero and work sections (80px padding vs 160px). Capping the containers and
 * centring them keeps every section on the same measure.
 */
.hero-container,
.logo-container,
.work-container,
.footer-container {
  max-width: var(--content-width);
  margin-left: auto;
  margin-right: auto;
}

/*
 * Sizing now comes from the max-width above, so the side padding is only ever a gutter
 * for viewports narrower than the measure. The export instead used it to set the width,
 * at four different values (160px desktop, 80px footer, 40px tablet, 0 on the work
 * section), which is why the sections never quite lined up.
 */
.main-hero,
.work-section,
.footer-section,
.logo-section {
  padding-left: var(--content-gutter);
  padding-right: var(--content-gutter);
}

/*
 * The export hides the logo strip below 992px, where its fixed five-column grid had no
 * room, and insets it with side margins that match no other section. A marquee has
 * neither problem, so it runs at every width on the shared measure above.
 */
@media screen and (max-width: 991px) {
  .logo-section {
    display: block;
    margin-left: 0;
    margin-right: 0;
  }
}

/*
 * Below 992px the export gives .project its own side margin, because .work-section had
 * no padding there for it to sit inside. With the section gutter above that margin
 * insets projects a second time, leaving them narrower than the hero. Vertical margins
 * carry the rhythm between projects and are left alone.
 */
.project {
  margin-left: 0;
  margin-right: 0;
}

/*
 * Every project image ships width and height attributes so the browser can reserve its box
 * before the file arrives and the page stops jumping as images load. Those attributes are
 * also a presentational hint that fixes the height in pixels, which would squash the image
 * at every width but the one it was generated at, so hand the height back to the ratio.
 */
.project-image {
  height: auto;
}

/*
 * Various Works stacks its pictures at the full column width, exactly like the images in the
 * projects above it, so the page reads as one column all the way down. The title and the
 * 24px between images come from .project-title and .project-image already.
 *
 * Only the bottom of the block needs a word: a normal project ends on its .p2 paragraph,
 * which sits flush, so the 80px on .project is the whole gap to the next entry. A gallery
 * ends on an image and would otherwise add its 24px on top. Matching the last visible image
 * rather than :last-child keeps that true when a picture is parked with hidden.
 */
.various-works .project-image:not(:has(~ .project-image:not([hidden]))) {
  margin-bottom: 0;
}

/*
 * Work parked with the hidden attribute rather than deleted. The UA sheet already does this,
 * but it loses to any author rule that sets display, so state it here at author level.
 */
[hidden] {
  display: none !important;
}

/*
 * The export closes the list by hanging a .last class on one project to drop its bottom
 * margin, which goes wrong the moment that project is parked: the 80px gap reappears above
 * the footer. Match the last project with no visible project after it instead, so hiding
 * or restoring work needs no bookkeeping in the markup.
 */
.project:not(:has(~ .project:not([hidden]))) {
  margin-bottom: 0;
}

@media screen and (max-width: 479px) {
  :root {
    --content-gutter: 16px;
  }
}

/*
 * Display sizes: 36 hero, 32 project title, 28 descriptor. All three are Libre Caslon
 * Display, so 4px between levels is enough separation — the gaps only needed to be wider
 * back when the descriptor was set in Inter and its larger x-height shouted over the title.
 *
 * Every one resolves its leading from a 125% ratio rather than a fixed pixel value, so
 * changing a size here does not need a matching line-height correction.
 */
.heading-1 {
  font-size: 36px; /* line-height is already a 125% ratio on this class */
}

.heading-3 {
  font-size: 32px;
  line-height: 125%;
}

.paragraph {
  font-size: 28px; /* line-height is a 125% ratio, so it follows on its own */
  /*
   * Between 480px and 991px the export insets the descriptor by 120px on the right, so it
   * wraps well short of the column while everything around it runs full width. Nothing
   * else on the page is inset that way, and the gutter already handles the edge.
   */
  margin-right: 0;
}

/*
 * A ~358px column cannot carry 28px display type: the longest descriptor runs to five lines
 * and its ragged edge falls well short of the measure. 26px pulls that back and fills the
 * line better than either 28 or the 20 the export dropped to. This has to sit after the rule
 * above, since a media query carries no specificity of its own.
 *
 * Size was only half the problem, though — four lines of display type is a wall however it is
 * set. So a project may carry a second, shorter descriptor (`summaryMobile` in content/work.mjs,
 * roughly half the words), and scripts/work.mjs writes both into the page for this breakpoint
 * to choose between. Two lines of the same face say the same thing in the space the column has.
 *
 * The pair is only ever written together, and a project with one descriptor gets neither class,
 * so nothing here can leave a project with no visible line.
 */
.narrow-only {
  display: none;
}

@media screen and (max-width: 479px) {
  .paragraph {
    font-size: 26px;
  }

  .wide-only {
    display: none;
  }

  .narrow-only {
    display: block;
  }
}

/*
 * Libre Caslon Text carries the display voice: headings and the one-line project description
 * that sits under each project as a subtitle. Inter takes the running body copy, JetBrains
 * Mono the tags and captions.
 *
 * Setting the weight here is not optional. The export declares font-weight: 300 on
 * .heading-1, left over from Newsreader, and the family has no light cut to answer it —
 * the titles would render at 400 while the CSS claimed 300.
 */
.heading-1,
.heading-3,
.paragraph {
  font-family: var(--title-font), Georgia, serif;
  font-weight: var(--title-weight);
}

.p2 {
  font-family: Inter, system-ui, sans-serif;
}

/*
 * Below 480px the export drops body copy to 13px with 32px leading. Keep the desktop
 * 16/24 instead — small enough for the column, large enough to read.
 */
@media screen and (max-width: 479px) {
  .p2 {
    font-size: 16px;
    line-height: 24px;
  }
}

/*
 * Chips take the 13px text and 4px/12px padding the design already uses for them at its
 * narrowest breakpoint. Scoped inside the pill so the standalone year caption beside each
 * project title keeps its 16px — it shares the .caption class but is not a chip.
 */
.chip,
.footer-chip {
  padding: 4px 12px;
}

.chip .caption,
.footer-chip .caption {
  font-size: 13px;
  line-height: 20px;
}

/*
 * A pill must stay one line; if it cannot fit on the row it wraps, and the row is capped
 * at one chip tall (4px + 20px + 4px) so that whole pill is hidden rather than stacking
 * or letting its label break onto two lines inside the chip.
 */
@media screen and (max-width: 479px) {
  .project-tags {
    flex-wrap: wrap;
    max-height: 28px;
    overflow: hidden;
  }

  .chip {
    flex-shrink: 0;
    white-space: nowrap;
  }
}

/*
 * The footer copyright. `.div-block` is Webflow's auto-generated name for the footer row,
 * and the child combinator is what keeps this off the chip labels beside it, which are
 * captions too but sit a level deeper inside .footer-chip.
 */
.div-block > .caption {
  font-family: Inter, system-ui, sans-serif;
}

/*
 * Looping logo strip, generated by scripts/logos.mjs. The track holds the logo set twice,
 * so translating it exactly -50% puts the copy where the original started and the loop has
 * no seam. Spacing comes from a margin on each logo rather than flex `gap`: a gap only
 * falls between items, which would leave the two passes half a gap out of step.
 */
.logo-marquee {
  overflow: hidden;
  /* Fade both edges so logos arrive and leave instead of clipping at a hard border. */
  -webkit-mask-image: linear-gradient(to right, transparent, #000 8%, #000 92%, transparent);
  mask-image: linear-gradient(to right, transparent, #000 8%, #000 92%, transparent);
}

.logo-track {
  display: flex;
  align-items: center;
  width: max-content;
  /* Tied to the logo count so the strip keeps its pace as logos are added or removed. */
  animation: logo-marquee calc(var(--logo-count, 8) * 4s) linear infinite;
}

.logo-track img {
  height: var(--logo-height);
  width: auto;
  margin-right: var(--logo-gap);
}

@keyframes logo-marquee {
  to {
    transform: translateX(-50%);
  }
}

/*
 * The strip is decorative, so honour a reduced-motion preference by holding it still
 * rather than offering a slower version of the same movement.
 */
@media (prefers-reduced-motion: reduce) {
  .logo-track {
    animation: none;
  }
}
