/* Jess Fine — portfolio
   Palette carried over from her existing brand. The one structural idea:
   every portfolio still sits in a strict 9:16 frame, because vertical phone
   video is the thing she is actually selling. */

:root {
  --paper:  #F4F0EA;
  --ink:    #171512;
  --clay:   #B8825C;
  --muted:  #6E6459;
  --line:   #E2DACF;
  --white:  #FBF9F6;

  --gap:    clamp(1rem, 4vw, 2.5rem);
  --bleed:  clamp(1.25rem, 6vw, 6rem);
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font: 400 clamp(1rem, .55vw + .9rem, 1.0625rem)/1.65 'Inter', system-ui, sans-serif;
}

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

a { color: inherit; }

h1, h2 {
  font-family: 'Fraunces', Georgia, serif;
  font-weight: 600;
  letter-spacing: -.015em;
  line-height: 1.02;
  margin: 0;
}

h2 {
  font-size: clamp(1.85rem, 4vw, 3rem);
  margin-bottom: 1.5rem;
}

section { padding: clamp(3.5rem, 9vw, 8rem) var(--bleed); }

.skip {
  position: absolute; left: -9999px;
  background: var(--ink); color: var(--paper); padding: .75rem 1rem;
}
.skip:focus { left: 1rem; top: 1rem; z-index: 100; }

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

/* ───────── hero ───────── */

.hero {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: end;
  gap: var(--gap);
  min-height: 88vh;
  padding: clamp(3rem, 8vw, 6rem) var(--bleed) clamp(3rem, 7vw, 5rem);
}
.hero-text { padding-bottom: clamp(1rem, 4vw, 3rem); }
.hero h1 { font-size: clamp(3rem, 9vw, 6.5rem); }
.hero .role {
  font-family: 'Fraunces', Georgia, serif;
  font-size: clamp(1.6rem, 4.6vw, 3.25rem);
  color: var(--clay);
  margin: .1em 0 0;
  line-height: 1.05;
}
.jump {
  display: inline-block;
  margin-top: clamp(1.5rem, 4vw, 2.75rem);
  font-weight: 600;
  text-decoration: none;
  border-bottom: 2px solid var(--ink);
  padding-bottom: .2rem;
}
.jump:hover { color: var(--clay); border-color: var(--clay); }
.hero-img img { width: 100%; height: clamp(20rem, 62vh, 40rem); object-fit: cover; }

/* ───────── about ───────── */

.about {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: clamp(1.5rem, 5vw, 4.5rem);
  align-items: start;
  border-top: 1px solid var(--line);
}
.about-img img { width: 100%; height: clamp(18rem, 46vh, 30rem); object-fit: cover; }
.about-text p { max-width: 62ch; margin: 0 0 1.15em; }
.about-text p:last-child { margin-bottom: 0; }

/* ───────── clients ───────── */

.clients { border-top: 1px solid var(--line); }
.logos {
  list-style: none; margin: 0; padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(clamp(6rem, 14vw, 10rem), 1fr));
  gap: clamp(1.75rem, 5vw, 4rem);
  align-items: center;
}
.logos li { display: grid; place-items: center; }
/* Shown in full colour. Greyscale flattens the gradient marks and turns the
   illustrated ones to mud, and several of these logos come on a dark plate
   that greyscale cannot fix anyway. */
.logos img {
  max-height: 3.5rem; max-width: 100%; width: auto; object-fit: contain;
}

/* ───────── portfolio ───────── */

.work { border-top: 1px solid var(--line); }
.work-head p { max-width: 46ch; color: var(--muted); margin: -.5rem 0 0; }

.grid {
  list-style: none; margin: clamp(2rem, 5vw, 3.5rem) 0 0; padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  gap: clamp(1rem, 2.5vw, 2rem);
}

/* The frame is the whole idea: 9:16, always, no exceptions. */
.frame {
  display: block; width: 100%; padding: 0; border: 0; cursor: pointer;
  position: relative; aspect-ratio: 9 / 16; overflow: hidden;
  background: var(--white); border: 1px solid var(--line);
}
.frame img { width: 100%; height: 100%; object-fit: cover; }
.frame::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(180deg, transparent 55%, rgba(23,21,18,.28));
  opacity: 0; transition: opacity .2s ease;
}
.card:hover .frame::after, .frame:focus-visible::after { opacity: 1; }

.play {
  position: absolute; left: 50%; top: 50%; translate: -50% -50%;
  width: 3.5rem; height: 3.5rem; border-radius: 50%;
  background: rgba(251,249,246,.92);
  display: grid; place-items: center;
}
.play::before {
  content: ''; width: 0; height: 0; margin-left: .22rem;
  border-left: .85rem solid var(--ink);
  border-top: .55rem solid transparent;
  border-bottom: .55rem solid transparent;
}
/* Video plays inside the 9:16 frame, filling it exactly. */
.frame.playing { cursor: default; background: #000; }
.frame video, .frame iframe {
  width: 100%; height: 100%; border: 0; display: block; object-fit: cover;
}
.frame.playing::after { display: none; }

/* No video attached yet? Then it is a still, and it should not pretend. */
.card:not([data-video]):not([data-mp4]):not([data-vimeo]) .play,
.card[data-video=""]:not([data-mp4]):not([data-vimeo]) .play { display: none; }
.card[data-video=""]:not([data-mp4]):not([data-vimeo]) .frame { cursor: default; }

.cat {
  margin: .85rem 0 .1rem;
  font-size: .8125rem; font-weight: 600; color: var(--clay);
}
.name { margin: 0; font-family: 'Fraunces', Georgia, serif; font-size: 1.125rem; }

/* ───────── services ───────── */

/* Set as a plain list, not pills. Bordered rounded shapes read as buttons,
   and these are statements of fact -- there is nothing to press. */
.services { border-top: 1px solid var(--line); }
.services ul {
  list-style: none; margin: 0; padding: 0;
  columns: 2; column-gap: clamp(2rem, 6vw, 5rem);
  max-width: 52rem;
}
.services li {
  break-inside: avoid;
  font-family: 'Fraunces', Georgia, serif;
  font-size: clamp(1.0625rem, 1.4vw, 1.25rem);
  padding: .85rem 0;
  border-bottom: 1px solid var(--line);
}

/* ───────── contact ───────── */

.contact { border-top: 1px solid var(--line); }
.contact-grid {
  display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: clamp(1.5rem, 5vw, 4.5rem); align-items: start;
}
.contact-img img { width: 100%; height: clamp(20rem, 55vh, 34rem); object-fit: cover; }

.details {
  display: grid; grid-template-columns: auto 1fr;
  gap: 0; margin: 0 0 clamp(2rem, 5vw, 3rem);
}
.details dt {
  font-size: .8125rem; font-weight: 600; color: var(--clay);
  padding: .9rem 1.5rem .9rem 0; border-top: 1px solid var(--line);
}
.details dd {
  margin: 0; padding: .9rem 0; border-top: 1px solid var(--line);
  font-family: 'Fraunces', Georgia, serif; font-size: 1.0625rem;
}
.details a { text-decoration-thickness: 1px; text-underline-offset: 3px; }

.enquiry { display: grid; gap: .35rem; max-width: 34rem; }
.form-intro { margin: 0 0 .75rem; color: var(--muted); font-size: .9375rem; }
.enquiry label { font-size: .8125rem; font-weight: 600; margin-top: .6rem; }
.enquiry input, .enquiry textarea {
  font: inherit; font-size: .9375rem;
  padding: .7rem .8rem; border: 1px solid var(--line);
  background: var(--white); color: var(--ink); border-radius: 4px;
}
.enquiry textarea { resize: vertical; min-height: 7rem; }
.enquiry button {
  justify-self: start; margin-top: 1.25rem;
  font: 600 .9375rem 'Inter', sans-serif;
  background: var(--ink); color: var(--paper);
  border: 0; border-radius: 4px; padding: .85rem 1.6rem; cursor: pointer;
}
.enquiry button:hover { background: var(--clay); }
.trap { position: absolute; left: -9999px; }

footer {
  border-top: 1px solid var(--line);
  padding: 2rem var(--bleed) 3rem;
  color: var(--muted); font-size: .875rem;
}
footer p { margin: 0; }

/* ───────── narrow ───────── */

@media (max-width: 760px) {
  .services ul { columns: 1; }
  .hero { grid-template-columns: 1fr; min-height: 0; align-items: start; }
  .hero-img { order: -1; }
  .hero-img img { height: clamp(18rem, 52vh, 26rem); }
  .about, .contact-grid { grid-template-columns: 1fr; }
  .about-img { order: -1; }
  .grid { grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr)); }
  .details { grid-template-columns: 1fr; }
  .details dt { padding-bottom: 0; border-top: 1px solid var(--line); }
  .details dd { padding-top: .15rem; border-top: 0; }
}

/* ───────── per-logo optical sizing ─────────
   A single max-height makes these look wrong, because visual weight is not
   height. A solid dark plate at 56px reads far heavier than a hairline
   wordmark at 56px — HoneyLove measured 18% ink coverage against Garderoba's
   100%, a 4.7x difference in perceived size at identical heights.

   Each height below is derived from the logo's ink coverage and aspect ratio,
   normalised so every mark carries roughly the same optical weight. Recompute
   if a logo file is replaced. */

.l-arm-hammer  img { max-height: 4.09rem; }
.l-believe     img { max-height: 3.65rem; }
.l-epify       img { max-height: 3.62rem; }
.l-fgo         img { max-height: 4.40rem; }
.l-flintts     img { max-height: 3.74rem; }
.l-garderoba   img { max-height: 3.27rem; }
.l-honeylove   img { max-height: 4.40rem; }
.l-iconic      img { max-height: 2.83rem; }
.l-kimith      img { max-height: 2.87rem; }
.l-pancake     img { max-height: 3.44rem; }
.l-plurality   img { max-height: 2.35rem; }
.l-polo-sauces img { max-height: 4.40rem; }
.l-supply      img { max-height: 3.65rem; }
.l-totoritas   img { max-height: 3.65rem; }

/* Narrow screens: same relationships, scaled down together. */
@media (max-width: 640px) {
  .logos img { max-height: 2.9rem; }
  .l-honeylove img, .l-fgo img, .l-polo-sauces img { max-height: 3.5rem; }
  .l-arm-hammer img { max-height: 3.3rem; }
  .l-iconic img, .l-kimith img { max-height: 2.3rem; }
  .l-plurality img { max-height: 1.9rem; }
}
