@layer components {
  /* Sticky header. Full-bleed bar so the background spans the viewport,
     with the content held to the same container as the page. */
  .site-header{
    position:sticky;
    top:0;
    z-index:100;
    background:var(--bg);                    /* solid fallback */
    /* Visible by default so the header still reads as a bar without JS. */
    border-bottom:1px solid var(--line);
    transition:border-color var(--motion-fast) var(--ease-standard);
  }

  /* With JS the line is held back until the page actually moves, so the
     header sits flush with the page at rest. */
  .js .site-header{border-bottom-color:transparent}

  /* Translucency only where it can actually be blurred, so the header
     never becomes see-through without the blur backing it up. */
  @supports (backdrop-filter:blur(1px)) and (background:color-mix(in srgb,red 50%,transparent)){
    .site-header{
      background:color-mix(in srgb, var(--bg) 82%, transparent);
      backdrop-filter:blur(14px) saturate(1.08);
      -webkit-backdrop-filter:blur(14px) saturate(1.08);
    }
  }

  /* The hairline appears only once the page has moved, so the header
     reads as part of the page at rest and as a bar while scrolling. */
  .js .site-header.is-stuck{border-bottom-color:var(--line)}

  .site-header__inner{
    display:flex;
    justify-content:space-between;
    align-items:center;
    gap:var(--space-3);
    padding-block:1.05rem;
  }

  .brand-block{display:grid;gap:.15rem}
  .brand{font-family:var(--font-display);font-size:var(--text-lg);line-height:1.1}
  .brand-tagline{margin:0;font-size:var(--text-xs);letter-spacing:.14em;text-transform:uppercase;color:var(--muted)}

  /* Desktop: control is not needed. */
  .nav-toggle{
    display:none;
    background:0;
    border:0;
    padding:.45rem 0;
    margin:0;
    font:inherit;
    font-size:var(--text-xs);
    letter-spacing:.16em;
    text-transform:uppercase;
    color:var(--muted);
    cursor:pointer;
  }
  .nav-toggle:hover{color:var(--text)}

  .site-nav{display:flex;gap:clamp(1rem,3vw,2.75rem);font-size:var(--text-sm)}
  .site-nav a{position:relative}
  .site-nav a::after{content:"";position:absolute;left:0;right:100%;bottom:-.35rem;height:1px;background:currentColor;transition:right var(--motion-base) var(--ease-standard)}
  .site-nav a:hover::after{right:0}

  /* Homepage sequence: a curated run of works, not stacked full-screen slides. */
  .sequence{
    display:grid;
    grid-template-columns:repeat(12,1fr);
    column-gap:clamp(1rem,3vw,3rem);
    row-gap:clamp(3.5rem,8vw,7rem);
    padding-block:clamp(2rem,5vw,4rem) clamp(4rem,9vw,8rem);
  }

  /* The figure is sized from the artwork's own aspect ratio (--ar, set
     inline per work from the file's real dimensions), capped by the
     column width. That makes the box exactly the size the image will
     render at, before it loads: space is reserved, nothing shifts, and
     the caption rail always matches the artwork's width on any ratio. */
  .work-piece{
    margin:0;
    --ar:1.5;
    width:min(100%, calc(var(--piece-height,60svh) * var(--ar)));
    max-width:100%;
    min-width:0;
  }

  .work-piece img{
    display:block;
    width:100%;
    height:auto;
    aspect-ratio:var(--ar);
    object-fit:contain; /* safety net: letterbox rather than crop */
    transition:opacity var(--motion-base) var(--ease-standard);
  }

  /* One link per work. The anchor wraps only the image so figcaption stays
     a direct child of figure; this overlay extends the same link's hit area
     across the caption, keeping the whole work a single tab stop. */
  .work-piece{position:relative}
  .work-piece__link{display:block}
  .work-piece__link::after{content:"";position:absolute;inset:0}
  .work-piece:hover img{opacity:.88}
  .work-piece__link:focus-visible{outline:none}
  .work-piece__link:focus-visible::after{outline:2px solid var(--text);outline-offset:8px}

  @media(prefers-reduced-motion:reduce){
    .work-piece img{transition:none}
  }

  .work-piece__caption{
    display:flex;
    justify-content:space-between;
    align-items:baseline;
    gap:clamp(1rem,4vw,3rem);
    margin-top:.9rem;
    padding-top:.7rem;
    border-top:1px solid var(--line);
    font-size:var(--text-sm);
  }
  .work-piece__title{font-family:var(--font-display);letter-spacing:-.01em}
  .work-piece__year{color:var(--muted);font-variant-numeric:tabular-nums;white-space:nowrap}

  /* The rhythm: lead work, then alternating side and scale. */
  .work-piece--lead{grid-column:2 / span 10;justify-self:center;--piece-height:76svh}
  .work-piece--left{grid-column:1 / span 7;justify-self:start;--piece-height:62svh}
  .work-piece--right{grid-column:6 / span 7;justify-self:end;--piece-height:56svh}

  /* Portrait works are height-led: a width-based allowance would render
     them much smaller than their landscape neighbours. Declared after the
     placement rules so it wins on any of them. */
  .work-piece--portrait{--piece-height:78svh}

  .project-card a{display:block}
  /* Sized from the work's own ratio (--ar, set per card): the whole
     composition shows, matching how the homepage treats the same images. */
  .project-card img{
    width:100%;height:auto;
    aspect-ratio:var(--ar,1.5);
    object-fit:contain;
    background:var(--surface);
    transition:opacity var(--motion-base) var(--ease-standard);
  }
  .project-card:hover img{opacity:.88}
  .project-card__meta{display:flex;justify-content:space-between;gap:1rem;padding-top:.7rem;margin-top:.9rem;border-top:1px solid var(--line)}
  .project-card__meta h2{font-family:var(--font-display);font-size:var(--text-sm);letter-spacing:-.01em;line-height:1.3}
  .project-card__meta p{color:var(--muted);font-size:var(--text-sm);font-variant-numeric:tabular-nums}

  .eyebrow{text-transform:uppercase;letter-spacing:.14em;font-size:var(--text-xs);color:var(--muted)}
  .project-meta{display:grid;gap:1rem;font-size:var(--text-sm)}
  .project-meta div{display:grid;grid-template-columns:7rem 1fr;border-top:1px solid var(--line);padding-top:.65rem}
  .project-meta dt{color:var(--muted)}
  .prose{display:grid;gap:1rem;white-space:normal}
  .contact-channels{list-style:none;margin:var(--space-5) 0 0;padding:0;display:flex;flex-wrap:wrap;gap:var(--space-4);font-size:var(--text-sm)}
  .contact-channels a{border-bottom:1px solid var(--line);padding-bottom:.15rem}
  .contact-channels a:hover{border-bottom-color:currentColor}
  .contact-form{display:grid;gap:1rem;margin-top:var(--space-6)}
  .contact-form label{display:grid;gap:.5rem}
  .button{
    width:max-content;border:1px solid var(--text);background:var(--text);
    color:var(--bg);padding:.9rem 1.35rem;cursor:pointer;
    font-size:var(--text-sm);letter-spacing:.04em;
    transition:background var(--motion-fast) var(--ease-standard),
               color var(--motion-fast) var(--ease-standard);
  }
  .button:hover{background:transparent;color:var(--text)}

  .site-footer{
    /* Sections already carry generous bottom padding, so the rule only
       needs breathing room beneath it. */
    padding-block:var(--space-5);
    border-top:1px solid var(--line);
    font-size:var(--text-sm);color:var(--muted);
  }
  .empty-state{grid-column:1 / -1;padding-block:clamp(3.5rem,9vw,6.5rem);color:var(--muted)}

  /* Tablet: keep the alternation but widen the spans. */
  @media(min-width:861px) and (max-width:1180px){
    .work-piece--lead{grid-column:1 / span 12;--piece-height:66svh}
    .work-piece--left{grid-column:1 / span 9;--piece-height:56svh}
    .work-piece--right{grid-column:4 / span 9;--piece-height:52svh}
  }

  /* Mobile: one column, image-led, captions still attached. */
  @media(max-width:860px){
    .sequence{grid-template-columns:1fr;row-gap:clamp(2.75rem,9vw,4.5rem)}
    .work-piece--lead,
    .work-piece--left,
    .work-piece--right{grid-column:1 / -1;justify-self:start}
    .work-piece--lead{--piece-height:66svh}
    .work-piece--left,
    .work-piece--right{--piece-height:58svh}
    .work-piece--portrait{--piece-height:72svh}
  }

  /* Below this the four links no longer share a row with the brand, so
     they move behind a control instead of wrapping. */
  @media(max-width:760px){
    .nav-toggle{display:inline-flex;align-items:center}

    /* Only collapse when JS can reopen it. Without JS the links stay
       visible and simply wrap, which is a usable fallback. */
    .js .site-nav{
      display:none;
      position:absolute;
      top:100%;
      left:0;
      right:0;
      flex-direction:column;
      align-items:stretch;
      gap:0;
      padding:.25rem var(--page-gutter) 1rem;
      background:var(--bg);
      border-bottom:1px solid var(--line);
    }
    @supports (backdrop-filter:blur(1px)) and (background:color-mix(in srgb,red 50%,transparent)){
      .js .site-nav{
        background:color-mix(in srgb, var(--bg) 92%, transparent);
        backdrop-filter:blur(16px) saturate(1.08);
        -webkit-backdrop-filter:blur(16px) saturate(1.08);
      }
    }
    .js .site-header.is-open .site-nav{display:flex}
    .js .site-nav a{padding-block:.8rem;border-top:1px solid var(--line)}
    .js .site-nav a::after{content:none} /* hover underline is wrong in a stacked panel */
  }

  @media(max-width:640px){
    .site-nav{flex-wrap:wrap;justify-content:flex-end}
    .work-piece--lead{--piece-height:60svh}
    .work-piece--left,
    .work-piece--right{--piece-height:54svh}
    .work-piece--portrait{--piece-height:72svh}
  }
}
