/* dirty girl glass: the black velvet backdrop from the photographs, with the
   blush of the pink backdrop carried over as the type colour */

:root {
  --ink: #110c0e;
  --panel: #1a1317;
  --stage: #060405;
  --blush: #f3dbda;
  --blush-dim: #b39ca1;
  --amber: #e7ad62;
  --line: rgb(243 219 218 / 0.14);
  --field-line: #7f6b70;
  --error: #ff8fa3;

  --display: "Bodoni Moda", "Bodoni 72", Didot, Georgia, serif;
  --text: "Atkinson Hyperlegible Next", "Atkinson Hyperlegible", system-ui, sans-serif;

  --page: 90rem;
  --gutter: clamp(1.25rem, 4vw, 3.5rem);
  --col-gap: clamp(1rem, 3vw, 3rem);
  --bar: 4.25rem;
  --ease: cubic-bezier(0.16, 1, 0.3, 1);

  color-scheme: dark;
}

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

html {
  background: var(--ink);
  scroll-padding-top: calc(var(--bar) + 1rem);
  scrollbar-gutter: stable;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--ink);
  color: var(--blush);
  font: 400 1.0625rem/1.6 var(--text);
}

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

h1,
h2,
h3 {
  margin: 0;
  font-family: var(--display);
  font-weight: 400;
  line-height: 1;
}

p {
  margin: 0;
}

a {
  color: inherit;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
}

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

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

#main:focus {
  outline: none;
}

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

.skip {
  position: fixed;
  top: 0.75rem;
  left: 0.75rem;
  z-index: 100;
  padding: 0.75rem 1rem;
  border-radius: 0.5rem;
  background: var(--blush);
  color: var(--ink);
  translate: 0 -200%;
}

.skip:focus {
  translate: none;
}

/* Bar: empty at the top of the page; it picks up a background and the
   wordmark once the masthead starts to slide underneath it. */

.bar {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  min-height: var(--bar);
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding-inline: max(var(--gutter), calc((100% - var(--page)) / 2 + var(--gutter)));
  transition:
    background-color 0.3s ease,
    box-shadow 0.3s ease;
}

.bar--scrolled {
  background: rgb(17 12 14 / 0.86);
  box-shadow: 0 1px 0 var(--line);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
}

.bar__brand {
  font: 400 1.5rem/1 var(--display);
  letter-spacing: -0.01em;
  text-decoration: none;
  white-space: nowrap;
  transition:
    opacity 0.4s ease,
    visibility 0.4s ease,
    translate 0.5s var(--ease);
}

@media (scripting: enabled) {
  .bar:not(.bar--scrolled) .bar__brand {
    opacity: 0;
    visibility: hidden;
    translate: 0 0.4rem;
  }
}

.bar__links {
  display: flex;
  gap: clamp(0.75rem, 3vw, 2.25rem);
  margin: 0;
  padding: 0;
  list-style: none;
}

.bar__links a {
  display: inline-flex;
  min-height: 2.75rem;
  align-items: center;
  text-decoration: none;
}

.bar__links a:hover {
  text-decoration: underline;
}

/* On the narrowest phones the masthead names the site; the bar keeps the links. */
@media (max-width: 22.5rem) {
  .bar {
    justify-content: flex-end;
  }

  .bar__brand {
    display: none;
  }
}

/* Hero: the first screen belongs to the wordmark alone. Its second line
   steps in to the same column the gallery's centred pieces start on. */

.hero {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--col-gap);
  align-content: center;
  min-height: calc(100svh - var(--bar));
  max-width: var(--page);
  margin-inline: auto;
  padding: clamp(3rem, 8vh, 6rem) var(--gutter) clamp(4rem, 14vh, 9rem);
}

.masthead {
  position: relative;
  display: grid;
  grid-column: 1 / -1;
  grid-template-columns: subgrid;
  font-size: clamp(4rem, 8vw + 1.5rem, 10.5rem);
  line-height: 1.08;
  letter-spacing: -0.03em;
}

@media (max-width: 760px) {
  .masthead {
    font-size: min(19vw, 6rem);
  }
}

.masthead__line {
  position: relative;
  display: block;
  grid-column: 1 / -1;
  justify-self: start;
}

.masthead__line > span {
  display: block;
}

.masthead__line + .masthead__line {
  grid-column: 3 / -1;
}

.hero__lede {
  grid-column: 3 / -1;
  max-width: 26ch;
  margin-top: clamp(1.75rem, 3vw, 2.75rem);
  color: var(--blush-dim);
  font-size: clamp(1.125rem, 0.6vw + 0.95rem, 1.375rem);
  line-height: 1.45;
}

/* Collections */

.collection {
  max-width: var(--page);
  margin-inline: auto;
  padding: clamp(3rem, 8vw, 7rem) var(--gutter);
}

.collection__head {
  display: grid;
  gap: 1rem;
  margin-bottom: clamp(2.5rem, 5vw, 4.5rem);
}

.collection__head h2,
.contact__intro h2 {
  font-size: clamp(2.5rem, 5vw, 4.5rem);
  letter-spacing: -0.02em;
}

.collection__head p {
  max-width: 44ch;
  color: var(--blush-dim);
}

.status {
  color: var(--blush-dim);
}

.status:empty {
  display: none;
}

/* Gallery: the staggered arrangement from the original site */

.gallery {
  display: flex;
  flex-direction: column;
  gap: 3.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.piece {
  position: relative;
}

.piece__figure {
  margin: 0;
}

.piece__frame {
  position: relative;
  overflow: hidden;
  background: var(--panel);
}

.piece__frame img {
  width: 100%;
  outline: 1px solid rgb(243 219 218 / 0.08);
  outline-offset: -1px;
  transition: scale 1.2s var(--ease);
}

.piece__frame::after {
  position: absolute;
  inset: 0;
  content: "";
  pointer-events: none;
  background: linear-gradient(
    105deg,
    transparent 30%,
    rgb(255 255 255 / 0.55) 47%,
    rgb(255 255 255 / 0.2) 53%,
    transparent 70%
  );
  mix-blend-mode: soft-light;
  translate: -100% 0;
}

.piece__caption {
  display: grid;
  gap: 0.15rem;
  padding-top: 1rem;
}

.piece__open {
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  cursor: pointer;
  font: italic 400 1.5rem/1.15 var(--display);
  text-align: left;
  text-decoration: none;
}

/* The whole piece links to its page; the title link carries the name. */
.piece__open::after {
  position: absolute;
  inset: 0;
  content: "";
}

.piece__open:focus-visible {
  outline: none;
}

.piece__open:focus-visible::after {
  outline: 3px solid var(--amber);
  outline-offset: 6px;
}

.piece__meta {
  color: var(--blush-dim);
  font-size: 0.9375rem;
}

@media (min-width: 761px) {
  .gallery {
    display: grid;
    grid-template-columns: repeat(12, minmax(0, 1fr));
    gap: clamp(2rem, 6vw, 7rem) var(--col-gap);
  }

  .piece:nth-child(3n + 1) {
    grid-column: 1 / span 7;
  }

  .piece:nth-child(3n + 2) {
    grid-column: 8 / span 5;
    margin-top: 8rem;
  }

  .piece:nth-child(3n) {
    grid-column: 3 / span 6;
  }

  .piece__caption {
    grid-template-columns: 1fr auto;
    gap: 1.5rem;
    align-items: baseline;
  }

  .piece__meta {
    text-align: right;
  }
}

/* Questions: plain answers, so people and search engines can both find
   them. Each question sits beside its answer on wider screens. */

.questions__list {
  max-width: 60rem;
  margin: 0;
}

.questions__item {
  display: grid;
  gap: 0.5rem;
  padding-block: 1.5rem;
  border-top: 1px solid var(--line);
}

.questions__item:last-child {
  border-bottom: 1px solid var(--line);
}

.questions__item dt {
  font: italic 400 1.5rem/1.15 var(--display);
}

.questions__item dd {
  max-width: 52ch;
  margin: 0;
  color: var(--blush-dim);
}

@media (min-width: 761px) {
  .questions__item {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    column-gap: var(--col-gap);
  }
}

/* Contact */

.contact {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--col-gap);
  row-gap: 2.5rem;
  max-width: var(--page);
  margin-inline: auto;
  padding: clamp(4rem, 10vw, 8rem) var(--gutter);
}

.contact__intro {
  grid-column: 1 / -1;
}

.contact__intro h2 {
  margin-bottom: 1.5rem;
}

.contact__intro p {
  max-width: 38ch;
  color: var(--blush-dim);
}

.contact__intro p + p {
  margin-top: 1rem;
}

.contact__intro a {
  color: var(--blush);
}

.form {
  display: grid;
  grid-column: 1 / -1;
  gap: 1.25rem;
}

.field {
  display: grid;
  gap: 0.4rem;
}

.field label {
  font-size: 0.9375rem;
  font-weight: 700;
}

input,
select,
textarea {
  width: 100%;
  min-height: 3rem;
  padding: 0.7rem 0.9rem;
  border: 1px solid var(--field-line);
  border-radius: 0.5rem;
  background: var(--panel);
  color: var(--blush);
  font: inherit;
}

textarea {
  min-height: 10rem;
  resize: vertical;
}

input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  border-color: var(--blush);
  outline-offset: 1px;
}

input:user-invalid,
select:user-invalid,
textarea:user-invalid {
  border-color: var(--error);
  border-width: 2px;
}

.form__submit {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem 1.5rem;
}

.form__status {
  max-width: 40ch;
  color: var(--blush-dim);
  font-size: 0.9375rem;
}

.button {
  display: inline-flex;
  min-height: 3rem;
  align-items: center;
  justify-content: center;
  padding: 0.75rem 1.5rem;
  border: 0;
  border-radius: 999px;
  background: var(--blush);
  color: var(--ink);
  cursor: pointer;
  font: 700 1rem/1.2 var(--text);
  text-decoration: none;
  transition: background-color 0.2s ease;
}

.button:hover {
  background: var(--amber);
}

@media (min-width: 761px) {
  .form {
    grid-template-columns: 1fr 1fr;
  }

  .field--wide,
  .form__submit {
    grid-column: 1 / -1;
  }
}

@media (min-width: 1000px) {
  .contact__intro {
    grid-column: 1 / span 5;
  }

  .form {
    grid-column: 7 / -1;
  }
}

/* Footer */

.foot {
  padding: clamp(3rem, 8vw, 5rem) var(--gutter);
  border-top: 1px solid var(--line);
  color: var(--blush-dim);
}

.foot__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  justify-content: space-between;
  gap: 1.5rem 3rem;
  max-width: var(--page);
  margin-inline: auto;
}

.foot__brand {
  color: var(--blush);
  font: 400 clamp(2rem, 5vw, 3.5rem)/1 var(--display);
  letter-spacing: -0.02em;
}

.foot__notes {
  display: grid;
  gap: 0.35rem;
}

.foot a {
  color: var(--blush);
}

/* Piece pages: every piece has a page of its own. Photos sit on a darker
   stage; the details stay beside them on wide screens, and on phones the
   photos become a swipeable strip so the price and the inquiry button stay
   near the top. */

.item {
  display: grid;
  gap: 2rem;
  max-width: var(--page);
  margin-inline: auto;
  padding: clamp(1.5rem, 4vw, 3rem) var(--gutter) clamp(3rem, 8vw, 6rem);
}

.item__photos {
  display: grid;
  gap: var(--col-gap);
}

.item__photos:focus-visible {
  outline-offset: -3px;
}

.item__photo {
  display: grid;
  place-items: center;
  margin: 0;
  padding: clamp(1rem, 3vw, 2.5rem);
  background: var(--stage);
}

/* Full width keeps the space reserved before the photo arrives; contain
   letterboxes tall pieces inside the height cap instead of cropping them. */
.item__photo img {
  width: 100%;
  max-height: 80svh;
  object-fit: contain;
}

.item__info {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1.5rem;
}

.item__back {
  color: var(--blush-dim);
}

.item__title {
  font: italic 400 clamp(2.5rem, 5vw, 4rem)/1.05 var(--display);
  letter-spacing: -0.01em;
}

.item__meta {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.35rem 1.5rem;
  margin: 0;
}

.item__meta dt {
  color: var(--blush-dim);
}

.item__meta dd {
  margin: 0;
}

.item__description {
  max-width: 60ch;
}

.item__note {
  color: var(--blush-dim);
  font-size: 0.9375rem;
}

.more {
  max-width: var(--page);
  margin-inline: auto;
  padding: 0 var(--gutter) clamp(4rem, 10vw, 7rem);
}

.more h2 {
  margin-bottom: 1.25rem;
  font-size: clamp(2rem, 4vw, 3rem);
  letter-spacing: -0.02em;
}

.more__list {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 2rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.more__list a {
  font: italic 400 1.5rem/1.4 var(--display);
  text-decoration: none;
}

.more__list a:hover {
  text-decoration: underline;
}

@media (max-width: 760px) {
  .item__photos {
    grid-auto-columns: 88%;
    grid-auto-flow: column;
    gap: 0.75rem;
    margin-inline: calc(var(--gutter) * -1);
    padding-inline: var(--gutter);
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-padding-inline: var(--gutter);
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
  }

  .item__photos::-webkit-scrollbar {
    display: none;
  }

  .item__photo {
    scroll-snap-align: start;
  }

  .item__photo img {
    max-height: 60svh;
  }
}

@media (min-width: 761px) {
  .item {
    grid-template-columns: minmax(0, 1.6fr) minmax(19rem, 1fr);
    column-gap: clamp(2rem, 5vw, 5rem);
    align-items: start;
  }

  .item__info {
    position: sticky;
    top: calc(var(--bar) + 2rem);
  }
}

/* Motion: one language throughout. Things arrive like panes of glass
   sliding into place, and catch a single glint of light. */

@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }

  /* Page load: the masthead rises out of its lines, then catches the light. */

  .masthead__line {
    overflow: clip;
    margin-block: -0.08em -0.24em;
    padding-block: 0.08em 0.24em;
  }

  .masthead__line > span {
    animation: rise 1.2s var(--ease) both;
  }

  .masthead__line + .masthead__line > span {
    animation-delay: 0.14s;
  }

  /* Each line gets its own glint, sized to the words and clipped by the
     line's mask. It hangs off the line wrapper rather than the rising span,
     because the span's animation isolates it and the soft-light blend would
     turn into a flat white blob. The band slides as its own layer (transform
     only), so the compositor keeps it smooth while the page is busy loading
     the gallery, and it starts off the left edge so its ease-in never
     lingers on a letter. */

  .masthead__line::after {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    width: 40%;
    content: "";
    pointer-events: none;
    background: linear-gradient(
      105deg,
      transparent 20%,
      rgb(255 255 255 / 0.85) 46%,
      rgb(255 255 255 / 0.3) 54%,
      transparent 80%
    );
    mix-blend-mode: soft-light;
    -webkit-mask-image: linear-gradient(transparent, #000 30%, #000 70%, transparent);
    mask-image: linear-gradient(transparent, #000 30%, #000 70%, transparent);
    animation: glint-across 1.3s 1s cubic-bezier(0.45, 0.05, 0.55, 0.95) both;
  }

  .masthead__line + .masthead__line::after {
    animation-delay: 1.18s;
  }

  .hero__lede {
    animation: settle 1s 0.45s var(--ease) both;
  }

  /* Scroll reveals, added by main.js only when this media query matches. */

  .reveal {
    opacity: 0;
    translate: var(--from-x, 0) var(--from-y, 2rem);
    transition:
      opacity 0.9s ease,
      translate 1.2s var(--ease);
  }

  .reveal.is-in {
    opacity: 1;
    translate: none;
  }

  .piece.reveal .piece__frame {
    clip-path: var(--wipe, inset(100% 0 0 0));
    transition: clip-path 1.2s var(--ease);
  }

  .piece.reveal .piece__frame img {
    scale: 1.12;
    transition: scale 1.6s var(--ease);
  }

  /* The caption only fades: moving it would make it the containing block
     for the title link's overlay, shrinking the piece's click target to
     the caption until the reveal finished. */
  .piece.reveal .piece__caption {
    opacity: 0;
    transition: opacity 0.8s 0.35s ease;
  }

  .piece.reveal.is-in .piece__frame {
    clip-path: inset(0);
  }

  .piece.reveal.is-in .piece__frame img {
    scale: 1;
  }

  .piece.reveal.is-in .piece__caption {
    opacity: 1;
  }

  .piece.reveal.is-in .piece__frame::after {
    animation: glint 1.3s 0.55s ease-in-out;
  }

  /* Each piece slides in from the side of the grid it sits on. */
  @media (min-width: 761px) {
    .piece:nth-child(3n + 1) {
      --from-x: -3rem;
      --from-y: 0;
      --wipe: inset(0 100% 0 0);
    }

    .piece:nth-child(3n + 2) {
      --from-x: 3rem;
      --from-y: 0;
      --wipe: inset(0 0 0 100%);
    }

    .piece:nth-child(3n) {
      --from-x: 0;
      --from-y: 3rem;
      --wipe: inset(100% 0 0 0);
    }
  }

  @media (hover: hover) {
    .piece:hover .piece__frame img {
      scale: 1.03;
    }

    .piece:hover .piece__frame::after {
      animation: glint 1.1s ease-in-out;
    }
  }
}

@media (prefers-reduced-motion: reduce) {
  .bar__brand {
    translate: none !important;
  }
}

@keyframes rise {
  from {
    translate: 0 105%;
  }
}

@keyframes settle {
  from {
    opacity: 0;
    translate: 0 1rem;
  }
}

@keyframes glint {
  from {
    translate: -100% 0;
  }

  to {
    translate: 100% 0;
  }
}

@keyframes glint-across {
  from {
    transform: translateX(-100%);
  }

  to {
    transform: translateX(250%);
  }
}

@media (forced-colors: active) {
  .piece__frame::after,
  .masthead__line::after {
    display: none;
  }

  .button {
    border: 1px solid ButtonText;
  }
}

@media print {
  html,
  body {
    background: #fff;
    color: #000;
  }

  .bar,
  .contact {
    display: none;
  }

  .reveal,
  .piece.reveal .piece__frame,
  .piece.reveal .piece__caption {
    opacity: 1;
    clip-path: none;
    translate: none;
  }
}
