/* ==========================================================
   Joanne Panicker — portfolio
   Palette pulled from her main original ("main1"):
   acid green, sun yellow, tangerine, plum and electric blue.
   ========================================================== */

:root {
  --ink: #0e0c12;
  --ink-2: #17141d;
  --paper: #fbfaf6;
  --green: #8be13c;
  --yellow: #ffe04a;
  --orange: #ff8a1f;
  --plum: #6e2b7f;
  --blue: #2f6fe4;
  --teal: #3fd0c9;
  --accent: var(--green);

  --display: "Big Shoulders Stencil Display", "Big Shoulders Stencil", "Big Shoulders Display", "Oswald", sans-serif;
  --sans: "Poppins", system-ui, -apple-system, "Segoe UI", sans-serif;

  --topbar-h: 64px;
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--sans);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }

/* ---------- Top bar ---------- */

.topbar {
  position: fixed;
  inset: 0 0 auto 0;
  height: var(--topbar-h);
  padding: 0 clamp(16px, 3vw, 40px);
  display: flex;
  align-items: center;
  justify-content: space-between;
  z-index: 50;
  transition: background .35s ease, backdrop-filter .35s ease;
}
.topbar.scrolled {
  background: rgba(14, 12, 18, .78);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}

.nav-links { display: flex; gap: clamp(16px, 2.4vw, 32px); }
.nav-links a {
  position: relative;
  font-size: 15px;
  font-weight: 500;
  letter-spacing: .02em;
  padding: 6px 0;
}
.nav-links a::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 2px;
  background: linear-gradient(90deg, var(--green), var(--yellow), var(--orange));
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .3s ease;
}
.nav-links a:hover::after,
.nav-links a[aria-current="page"]::after { transform: scaleX(1); }

/* Line the links up with the white bar on the home hero */
.home .topbar { padding-left: calc(4vw + clamp(16px, 2vw, 32px)); }

/* On the home hero the links sit on the white bar, so they're dark until you scroll */
.home .topbar:not(.scrolled) .nav-links a { color: var(--ink); }

.socials { display: flex; gap: 18px; align-items: center; }
.socials a { display: grid; place-items: center; width: 22px; height: 22px; transition: color .2s, transform .2s; }
.socials a:hover { color: var(--accent); transform: translateY(-2px); }
.socials svg { width: 20px; height: 20px; }

/* ---------- Hero ---------- */

.hero {
  /* Geometry shared by the white bar and the split title */
  --bar-l: 4vw;
  --bar-w: 27vw;
  --title-l: 7vw;
  --split: calc(var(--bar-l) + var(--bar-w) - var(--title-l));

  position: relative;
  height: 100vh;
  height: 100svh;
  min-height: 560px;
  overflow: hidden;
  isolation: isolate;
}

.bar {
  position: absolute;
  top: 0; bottom: 0;
  left: var(--bar-l);
  width: var(--bar-w);
  background: var(--paper);
  z-index: 1;
  box-shadow: 0 0 80px rgba(0, 0, 0, .35);
}

/* The painting, floating in 3D on the right */
.art-stage {
  position: absolute;
  right: 5vw;
  top: 50%;
  width: min(74vh, 54vw);
  aspect-ratio: 1;
  transform: translateY(-46%);
  perspective: 1200px;
  z-index: 2;
}
.art {
  position: relative;
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  transform: rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
  transition: transform .5s cubic-bezier(.2, .7, .2, 1);
}
.art img,
.art .echo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 4px;
}
.art img {
  transform: translateZ(40px);
  box-shadow: 0 40px 90px -20px rgba(0, 0, 0, .7);
}
/* Coloured "echo" slabs behind the canvas give it physical depth */
.art .echo { filter: blur(2px) saturate(1.4); opacity: .55; }
.art .echo-1 { transform: translateZ(0)     translate(14px, 14px);  background: var(--green); }
.art .echo-2 { transform: translateZ(-40px) translate(28px, 28px);  background: var(--plum); }
.art .echo-3 { transform: translateZ(-80px) translate(42px, 42px);  background: var(--blue); opacity: .4; }
/* Colour flow (colourflow.js): the painting redrawn with its colours turning,
   on a layer just in front of it so it tilts with it. Hidden until it's running;
   the slabs behind then change colour along with it. */
.art .flow {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border-radius: 4px;
  pointer-events: none;
  transform: translateZ(40.5px);
  display: none;
}
.art.flowing .flow { display: block; }
.art.flowing { cursor: pointer; } /* clicking sends a ripple of colour */
.art .glare {
  position: absolute;
  inset: 0;
  transform: translateZ(41px);
  border-radius: 4px;
  pointer-events: none;
  background: radial-gradient(circle at var(--gx, 50%) var(--gy, 30%), rgba(255, 255, 255, .28), transparent 55%);
  mix-blend-mode: soft-light;
}

/* PORTFOLIO — two stacked copies, clipped at the bar edge */
.title {
  position: absolute;
  left: var(--title-l);
  top: 50%;
  margin: 0;
  z-index: 3;
  font-family: var(--display);
  font-weight: 500;
  font-size: clamp(90px, 26vh, 300px);
  line-height: .82;
  letter-spacing: .02em;
  text-transform: uppercase;
  white-space: nowrap;
  pointer-events: none;
  transform: translateY(-35%);
}
.title .layer { display: block; }
.title .layer + .layer { position: absolute; inset: 0; }
.title .on-paint {
  color: var(--paper);
  text-shadow: 0 6px 40px rgba(0, 0, 0, .35);
  clip-path: inset(-20% -20% -20% var(--split));
}
.title .on-bar {
  /* the green shows in the letters until the picture has loaded */
  background: #5dc255 url("../assets/originals/main1.jpg") 30% 40% / 260% auto;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  clip-path: inset(-20% calc(100% - var(--split)) -20% -20%);
  animation: drift 18s ease-in-out infinite alternate;
}
@keyframes drift {
  from { background-position: 10% 30%; }
  to   { background-position: 90% 70%; }
}

/* The drift above repaints the whole word on every frame. Where the browser can,
   the same picture is built from layers instead, so only a transform moves and
   the graphics chip does the rest:
   - .title-cut: the word in black, cut into whatever is behind it (the bar, or the
     hero painting where they overlap on narrow screens)
   - .title-fill: the painting, drifting, multiplied by the word in white on black,
     so it's the painting inside the letters and black everywhere else; added on
     top with plus-lighter, black adds nothing and the letters fill back in.
   The result matches the original exactly, soft letter edges included. */
.title-cut, .title-fill { display: none; }
@supports (mix-blend-mode: plus-lighter) {
  .title .on-bar { display: none; }
  /* Only the right-hand edge (where the bar ends) needs cutting; the other edges sit
     off screen, because a cut edge across the painting drew a faint line */
  .title-cut,
  .title-fill { display: block; clip-path: inset(-100vmax calc(100% - var(--split)) -100vmax -100vmax); }
  .title-cut { color: #000; }
  .title-fill { color: #fff; mix-blend-mode: plus-lighter; }
  /* Under the drifting copy: the painting standing still, and under that its
     green. The drifting copy is a huge layer, and the browser sometimes skips
     drawing it for a moment (before the picture has loaded, while it catches up
     with the movement, or on coming back to the tab). With nothing beneath it the
     letters came out plain white on the white bar; now they still show paint. */
  .title-fill .paint {
    position: absolute;
    inset: 0;
    container-type: size;
    background: #5dc255 url("../assets/originals/main1.jpg") 30% 40% / 260% auto;
  }
  .title-fill .paint::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    width: 260%;
    aspect-ratio: 1595 / 1600; /* main1.jpg */
    background: url("../assets/originals/main1.jpg") 0 0 / 100% 100%;
    /* where background-position 30% 40% would put it, for reduced motion */
    translate: calc(30cqw - 30%) calc(40cqh - 40%);
    animation: drift-move 18s ease-in-out infinite alternate;
  }
  .title-fill .ink {
    display: block;
    position: relative;
    background: #000;
    box-shadow: 0 0 0 100vmax #000;
    mix-blend-mode: multiply;
  }
}
/* Same path as the drift above: background-position p% = p% of (box − picture) */
@keyframes drift-move {
  from { translate: calc(10cqw - 10%) calc(30cqh - 30%); }
  to   { translate: calc(90cqw - 90%) calc(70cqh - 70%); }
}

.year {
  position: absolute;
  z-index: 3;
  left: calc(var(--bar-l) + var(--bar-w) + 2vw);
  top: calc(50% + 14vh);
  font-family: var(--display);
  font-weight: 500;
  font-size: clamp(80px, 22vh, 260px);
  line-height: 1;
  color: var(--paper);
  text-shadow: 0 6px 40px rgba(0, 0, 0, .35);
  pointer-events: none;
}

.byline {
  position: absolute;
  z-index: 3;
  left: var(--bar-l);
  width: var(--bar-w);
  top: calc(50% + 19vh);
  padding: 0 2vw;
  color: var(--ink);
  text-align: right;
}
.byline .name {
  margin: 0;
  font-weight: 700;
  font-size: clamp(22px, 2.3vw, 36px);
  letter-spacing: -.01em;
  text-transform: lowercase;
  line-height: 1.1;
}
.byline .role {
  margin: 12px 0 0;
  font-size: clamp(11px, .9vw, 14px);
  letter-spacing: .14em;
  line-height: 1.6;
}

.scroll-cue {
  position: absolute;
  z-index: 3;
  left: calc(var(--bar-l) + var(--bar-w) / 2);
  bottom: 28px;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  color: var(--ink);
  font-size: 11px;
  letter-spacing: .25em;
  text-transform: uppercase;
}
.scroll-cue span {
  width: 1px;
  height: 36px;
  background: currentColor;
  transform-origin: top;
  animation: cue 1.8s ease-in-out infinite;
}
@keyframes cue {
  0%   { transform: scaleY(0); }
  50%  { transform: scaleY(1); transform-origin: top; }
  51%  { transform-origin: bottom; }
  100% { transform: scaleY(0); transform-origin: bottom; }
}

/* Entrance */
.hero .bar       { animation: barIn 1s cubic-bezier(.7, 0, .2, 1) both; }
.hero .art-stage { animation: fadeUp 1.2s .35s cubic-bezier(.2, .7, .2, 1) both; }
.hero .title,
.hero .year,
.hero .byline    { animation: fadeIn 1s .7s both; }
@keyframes barIn  { from { transform: scaleY(0); transform-origin: top; } }
@keyframes fadeUp { from { opacity: 0; translate: 0 40px; } }
@keyframes fadeIn { from { opacity: 0; } }

/* ---------- Work grid ---------- */

.work {
  position: relative;
  padding: clamp(64px, 10vw, 120px) clamp(16px, 3vw, 40px) 80px;
}
.section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  margin: 0 0 28px;
}
.section-head h2 {
  margin: 0;
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(48px, 7vw, 96px);
  line-height: .9;
  text-transform: uppercase;
}
.section-head p { margin: 0; color: rgba(251, 250, 246, .6); font-size: 14px; }

.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0;
  border: 2px solid var(--ink);
}

.tile {
  display: flex;
  flex-direction: column;
  border: 2px solid var(--ink);
  background: var(--ink-2);
  overflow: hidden;
  opacity: 0;
  transform: translateY(30px);
  transition: opacity .7s ease, transform .7s cubic-bezier(.2, .7, .2, 1);
}
.tile.in { opacity: 1; transform: none; }

.tile-title {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 12px;
  background: var(--tile-c, var(--green));
  color: var(--ink);
  font-weight: 600;
  font-size: 15px;
  border-bottom: 2px solid var(--ink);
}
.tile-title .count { font-weight: 400; font-size: 12px; opacity: .7; }

.tile-img { aspect-ratio: 4 / 5; overflow: hidden; }
.tile-img img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform .8s cubic-bezier(.2, .7, .2, 1), filter .5s;
}
.tile:hover .tile-img img { transform: scale(1.06) rotate(-.6deg); }
.tile:hover .tile-title { filter: brightness(1.08); }

.tile:nth-child(5n+1) { --tile-c: var(--green); }
.tile:nth-child(5n+2) { --tile-c: var(--yellow); }
.tile:nth-child(5n+3) { --tile-c: var(--orange); }
.tile:nth-child(5n+4) { --tile-c: var(--teal); }
.tile:nth-child(5n+5) { --tile-c: #c58bff; }

/* Sketches cover: a pile of cut-outs on paper */
.tile-img.scatter {
  position: relative;
  background:
    radial-gradient(circle at 30% 20%, rgba(0, 0, 0, .04), transparent 60%),
    #f2efe8;
}
/* The wrapper moves (on the GPU); the shadowed image inside never changes,
   so its drop-shadow is only painted once. */
.scrap {
  position: absolute;
  display: block;
  transition: transform .6s cubic-bezier(.2, .8, .2, 1);
  will-change: transform;
  animation: bob 6s ease-in-out infinite alternate;
}
.scrap img {
  width: 100%;
  height: auto;
  filter: drop-shadow(0 3px 5px rgba(0, 0, 0, .18));
}
@keyframes bob {
  from { translate: 0 -4px; rotate: -1.5deg; }
  to   { translate: 0 4px;  rotate: 1.5deg; }
}
.tile:hover .tile-img.scatter img { transform: none; }
.tile .tile-img.scatter img { transition: none; }

/* Gouache cover: glows that pulse over the painted fireflies */
.ff-box { position: relative; }
.ff-layer {
  position: absolute;
  left: 0;
  top: 50%;
  width: 100%;
  translate: 0 -50%; /* centred like the object-fit: cover image underneath */
  pointer-events: none;
  transition: transform .8s cubic-bezier(.2, .7, .2, 1);
}
.tile:hover .ff-layer { transform: scale(1.06) rotate(-.6deg); } /* follows the image's hover zoom */
.ff-layer canvas { display: block; width: 100%; height: 100%; }

/* Watercolours cover: painted in with the cursor (canvas drawn by watercolour.js) */
.tile-img.wc { position: relative; }
.tile-img.wc img { visibility: hidden; }
.wc-canvas { position: absolute; inset: 0; width: 100%; height: 100%; cursor: crosshair; }
.wc-hint {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 18px;
  text-align: center;
  font-family: "Patrick Hand", cursive;
  font-size: 20px;
  color: rgba(60, 50, 40, .55);
  pointer-events: none;
  transition: opacity .6s ease;
}
.wc-hint.gone { opacity: 0; }

/* ---------- Collage (Sketches page) ---------- */

.no-scroll, .no-scroll body { overflow: hidden; }

.collage-overlay {
  position: fixed;
  inset: 0;
  z-index: 200;
  overflow-y: auto;
  background: transparent;
  transition: background .6s ease;
}
.collage-overlay.in { background: #5e5c5f; }
.collage-overlay.leaving { opacity: 0; transition: opacity .35s ease; }
.collage-overlay .sheet { opacity: 0; transition: opacity .5s ease .2s; }
.collage-overlay.in .sheet { opacity: 1; }
.collage-overlay.building .piece:not(.landed) { background: transparent; box-shadow: none; }
.collage-overlay.building .piece:not(.landed) img { opacity: 0; }
.collage-overlay.building .text-card { opacity: 0; transform: translateY(24px); }

.collage-page { background: #5e5c5f; }
.collage-page .topbar.scrolled,
.collage-overlay .topbar.scrolled { background: rgba(60, 58, 62, .85); }

/* The menu copied into the overlay drops the home hero's dark-on-white styling */
.collage-overlay .topbar { padding-left: clamp(16px, 3vw, 40px); }
.home .collage-overlay .topbar .nav-links a { color: var(--paper); }

.board {
  max-width: 1180px;
  margin: 0 auto;
  padding: 24px clamp(12px, 3vw, 32px) 80px;
}
.collage-page .board,
.collage-overlay .board { padding-top: calc(var(--topbar-h) + 16px); }
.board-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin: 0 0 14px;
  font-size: 14px;
  color: rgba(255, 255, 255, .75);
}
.board-bar .back { color: #fff; }
.board-hint { font-family: "Patrick Hand", cursive; font-size: 17px; }

.sheet {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  grid-auto-rows: 8px;
  grid-auto-flow: dense;
  gap: 10px;
  padding: 18px;
  background: #4e4c50;
  box-shadow: 0 30px 80px -30px rgba(0, 0, 0, .6);
}

.card {
  position: relative;
  background: #fbfaf7;
  overflow: hidden;
}
.piece {
  display: block;
  transition: background .25s ease, box-shadow .25s ease;
  padding: 10px;
  border: 0;
  cursor: zoom-in;
}
.piece img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  transition: transform .5s cubic-bezier(.2, .8, .2, 1), opacity .25s;
}
.piece:hover img { transform: scale(1.04) rotate(-.8deg); }
.piece.framed { box-shadow: inset 0 0 0 3px #4a1515; }

.text-card {
  transition: opacity .6s ease, transform .6s cubic-bezier(.2, .8, .2, 1);
  color: #2a2627;
}
.text-card:nth-of-type(odd)  { transition-delay: .05s; }
.text-card:nth-of-type(even) { transition-delay: .2s; }
.text-card { container-type: inline-size; }
.text-card .inner { padding: 18px 22px; }
.text-card.title h2 {
  margin: 0;
  font-family: "Londrina Outline", cursive;
  font-weight: 400;
  font-size: min(19cqi, 120px); /* sized to the card so the full word fits */
  line-height: .95;
  white-space: nowrap;
  letter-spacing: .02em;
  text-transform: uppercase;
}
.text-card.note p {
  margin: 0;
  font-family: "Patrick Hand", cursive;
  font-size: clamp(18px, 1.5vw, 21px);
  line-height: 1.75;
  /* faint ruled lines, like the reference page */
  background-image: linear-gradient(transparent calc(1.75em - 1px), rgba(74, 21, 21, .12) 1px);
  background-size: 100% 1.75em;
}

.flying {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 300;
  pointer-events: none;
  will-change: transform;
}
.flying img {
  display: block;
  width: 100%;
  height: 100%;
  filter: drop-shadow(0 10px 14px rgba(0, 0, 0, .3));
}

/* ---------- Sketchbook (flip-through book) ---------- */

.book-page { background: #6b6e8c; }
.book-page .topbar.scrolled { background: rgba(80, 82, 108, .85); }

.sketchbook {
  min-height: 100vh;
  padding: calc(var(--topbar-h) + 16px) clamp(12px, 3vw, 32px) 40px;
  display: flex;
  flex-direction: column;
  align-items: center;
  overflow: hidden;
}
.sb-head { width: 100%; max-width: 1180px; text-align: center; position: relative; }
.sb-head .back { position: absolute; left: 0; top: 4px; color: #fff; }
.sb-head h1 { margin: 0; font-weight: 700; font-size: clamp(24px, 3vw, 34px); letter-spacing: -.01em; }
.sb-count { margin: 4px 0 0; font-size: 13px; color: rgba(255, 255, 255, .7); }

.sb-stage {
  width: 100%;
  display: grid;
  place-items: center;
  perspective: 2400px;
  margin-top: 12px;
  transition: height .6s ease;
}
.sb-turn { transition: transform .7s cubic-bezier(.45, .05, .25, 1); transform-style: preserve-3d; }
.sb-turn.rotated { transform: rotate(-90deg) scale(var(--rs, 1)); }

.sb-book {
  --shift: 0px;
  position: relative;
  width: calc(var(--pw) * 2);
  height: var(--ph);
  transform-style: preserve-3d;
  transform: rotateX(10deg) translateX(var(--shift)) translateY(var(--shift-y, 0px));
  transition: transform .9s cubic-bezier(.45, .05, .25, 1);
  cursor: pointer;
  animation: book-in .9s cubic-bezier(.2, .8, .2, 1) both;
}
.sb-book[data-state="closed"] { --shift: calc(var(--pw) * -.5); }
.sb-book[data-state="ended"]  { --shift: calc(var(--pw) * .5); }
@keyframes book-in { from { opacity: 0; translate: 0 40px; } }

.sb-leaf {
  position: absolute;
  left: 50%;
  top: 0;
  width: var(--pw);
  height: var(--ph);
  transform-origin: left center;
  transform-style: preserve-3d;
  transition: transform .9s cubic-bezier(.45, .05, .25, 1);
}
.sb-leaf.turned { transform: rotateY(-180deg); }
.sb-leaf.away { display: none; } /* buried well under the open page */
/* a little lift while the page is in the air */
.sb-leaf.flipping .sb-face { box-shadow: 0 30px 50px rgba(0, 0, 0, .3); }

.sb-face {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  overflow: hidden;
  box-shadow: 0 18px 30px -12px rgba(0, 0, 0, .35);
}
.sb-face.back { transform: rotateY(180deg); }
.sb-face img { width: 100%; height: 100%; object-fit: cover; display: block; }
.sb-face.paper { background: #f5f2ea; }
/* shading into the spine */
.sb-face.paper::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(to right, rgba(0, 0, 0, .22), rgba(0, 0, 0, .06) 5%, transparent 12%);
}
.sb-face.back.paper::after { background: linear-gradient(to left, rgba(0, 0, 0, .22), rgba(0, 0, 0, .06) 5%, transparent 12%); }
.sb-face.cover { border-radius: 2px 7px 7px 2px; background: #1c1c1f; }
.sb-face.backcover {
  border-radius: 7px 2px 2px 7px;
  background:
    repeating-linear-gradient(45deg, rgba(255, 255, 255, .025) 0 2px, transparent 2px 4px),
    #1c1c1f;
}

/* stacked page edges either side, thicker on the side with more pages */
.sb-edges {
  position: absolute;
  top: 4px;
  bottom: 4px;
  background: repeating-linear-gradient(to right, #ece7db 0 1px, #c9c1b0 1px 2px);
  border-radius: 2px;
  transform: translateZ(-2px);
}
.sb-edges.right { left: calc(50% + var(--pw) - 2px); width: calc(var(--right) * var(--edge, 1.3px)); }
.sb-edges.left  { right: calc(50% + var(--pw) - 2px); width: calc(var(--left) * var(--edge, 1.3px)); }
.sb-book[data-state="closed"] .sb-edges.left,
.sb-book[data-state="ended"] .sb-edges.right { display: none; }

/* Portrait book: paper shows a ghost of the drawing on the other side */
.sb-face img.through {
  transform: scaleX(-1);
  opacity: .045;
  filter: grayscale(.4) blur(2px);
}
.sb-book.tall .sb-face.paper { background: #f8f6f1; }
/* Cloth cover with a pasted-on label, for books without a cover photo */
.sb-face.cover.cloth {
  display: grid;
  place-items: center;
  background:
    repeating-linear-gradient(0deg, rgba(255, 255, 255, .035) 0 1px, transparent 1px 3px),
    repeating-linear-gradient(90deg, rgba(0, 0, 0, .08) 0 1px, transparent 1px 3px),
    linear-gradient(135deg, #5b5550, #3f3a37);
}
.sb-label-plate {
  width: 62%;
  padding: 7% 6%;
  background: #f4efe4;
  border: 1px solid rgba(0, 0, 0, .25);
  box-shadow: inset 0 0 0 4px #f4efe4, inset 0 0 0 5px rgba(90, 60, 40, .35), 0 2px 4px rgba(0, 0, 0, .3);
  text-align: center;
  color: #3a2f2a;
}
.sb-label-plate span { display: block; font-family: "Patrick Hand", cursive; font-size: calc(var(--pw) * .12); line-height: 1; }
.sb-label-plate small { display: block; margin-top: 6%; font-size: calc(var(--pw) * .042); letter-spacing: .18em; text-transform: uppercase; opacity: .7; }
/* Orange ribbon bookmark, like the real portrait book */
.sb-book.tall::after {
  content: "";
  position: absolute;
  left: calc(50% + var(--pw) * .62);
  top: calc(var(--ph) - 6px);
  width: 9px;
  height: 46px;
  background: linear-gradient(90deg, #d9531e, #f2742f 50%, #c94a18);
  clip-path: polygon(0 0, 100% 0, 100% 100%, 50% 82%, 0 100%);
  transform: translateZ(-1px);
}
.sb-book.tall[data-state="ended"]::after { left: calc(50% - var(--pw) * .62); }

/* Flip pad (portraits): bound along the top with wire; pages swing out towards
   you, over the binding and fold down behind the pad */
.sb-book.up {
  width: var(--pw);
  height: var(--ph);
  touch-action: none;
  transform: rotateX(6deg); /* tipped back slightly, like a pad held up */
}
.sb-book.up .sb-leaf { left: 0; top: 0; transform-origin: 50% -10px; } /* hinge on the wire */
/* Forward: the page folds all the way round the wire to hang behind the pad,
   then is hidden (browsers don't reliably draw it behind the board). */
.sb-book.up .sb-leaf.turned { transform: rotateX(352deg) translateZ(-18px); }
.sb-book.up .sb-leaf.turned:not(.flipping) { visibility: hidden; }
/* Back: rather than coming out from behind the pad, the page starts just behind
   the top edge, invisible, and fades in as it swings over the wire and down */
.sb-book.up .sb-leaf .sb-face { transition: opacity .18s ease-out; }
.sb-book.up .sb-leaf.rewind { transition: none; transform: rotateX(235deg); }
.sb-book.up .sb-leaf.rewind .sb-face { opacity: 0; transition: none; }
.sb-book.up .sb-face { box-shadow: 0 8px 14px -10px rgba(0, 0, 0, .3); border-radius: 3px 3px 6px 6px; }
.sb-book.up .sb-leaf.flipping .sb-face { box-shadow: 0 10px 20px rgba(0, 0, 0, .18); }
.sb-book.up .sb-face.back { transform: rotateX(180deg); }
.sb-book.up .sb-face.paper::after { background: linear-gradient(to bottom, rgba(0, 0, 0, .12), transparent 6%); }
.sb-book.up .sb-face.back.paper::after { background: linear-gradient(to top, rgba(0, 0, 0, .12), transparent 6%); }
/* punched holes along the top of every sheet */
.sb-book.up .sb-face::before {
  content: "";
  position: absolute;
  z-index: 2;
  left: 7%;
  right: 7%;
  top: 5px;
  height: 9px;
  background: radial-gradient(circle, #3b3d52 0 3px, transparent 3.5px) 0 0 / 16px 9px repeat-x;
  opacity: .85;
}
.sb-book.up .sb-face.back::before { top: auto; bottom: 5px; }
/* the cardboard back of the pad, seen once every page is folded away */
.sb-board {
  position: absolute;
  inset: 0;
  border-radius: 3px 3px 6px 6px;
  transform: translateZ(-8px);
  background:
    repeating-linear-gradient(115deg, rgba(255, 255, 255, .025) 0 2px, transparent 2px 5px),
    linear-gradient(160deg, #1d1d20, #0f0f11);
  box-shadow: 0 18px 30px -12px rgba(0, 0, 0, .4);
}
/* wire binding: a row of loops across the top */
.sb-wire {
  position: absolute;
  left: 7%;
  right: 7%;
  top: -13px;
  height: 26px;
  display: flex;
  justify-content: space-between;
  transform: translateZ(6px);
  pointer-events: none;
  z-index: 200;
}
.sb-wire i {
  width: 5px;
  height: 100%;
  border-radius: 3px;
  background: linear-gradient(90deg, #4a4b52, #d9dbe2 45%, #8a8c94 70%, #3e3f45);
  box-shadow: 1px 2px 2px rgba(0, 0, 0, .35);
  transform: rotate(8deg);
}
/* black card cover with a label */
.sb-book.up .sb-face.cover.cloth {
  background:
    radial-gradient(circle at 20% 15%, rgba(255, 255, 255, .08), transparent 55%),
    repeating-linear-gradient(115deg, rgba(255, 255, 255, .025) 0 1px, transparent 1px 4px),
    repeating-linear-gradient(25deg, rgba(255, 255, 255, .02) 0 1px, transparent 1px 6px),
    linear-gradient(160deg, #222225, #121214);
}
.sb-book.up .sb-label-plate { width: 70%; transform: rotate(-1.5deg); }
.sb-cover-foot {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 6%;
  text-align: center;
  font-size: calc(var(--pw) * .036);
  letter-spacing: .22em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .5);
}
.sb-book.up .sb-edges.left,
.sb-book.up::after { display: none; }
.sb-book.up .sb-edges.right {
  left: 4px;
  right: 4px;
  width: auto;
  top: calc(var(--ph) - 2px);
  bottom: auto;
  height: calc(var(--right) * var(--edge, 1.3px));
  background: repeating-linear-gradient(to bottom, #ece7db 0 1px, #c9c1b0 1px 2px);
}

.sb-controls {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 8px;
}
.sb-btn {
  width: 42px;
  height: 42px;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, .88);
  color: #2b2b35;
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  box-shadow: 0 6px 16px -6px rgba(0, 0, 0, .4);
  transition: transform .2s, background .2s, opacity .2s;
}
.sb-btn:hover { transform: translateY(-2px); background: #fff; }
.sb-btn:disabled { opacity: .35; cursor: default; transform: none; }
.sb-label { min-width: 110px; text-align: center; font-size: 14px; color: rgba(255, 255, 255, .9); }
.sb-hint { margin: 14px 0 0; font-size: 12px; color: rgba(255, 255, 255, .55); }

@media (max-width: 560px) {
  .sb-head .back { position: static; display: inline-block; margin-bottom: 8px; }
}

/* ---------- Footer ---------- */

.footer {
  padding: 40px clamp(16px, 3vw, 40px);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  font-size: 13px;
  color: rgba(251, 250, 246, .55);
  border-top: 1px solid rgba(251, 250, 246, .08);
}

/* ---------- About ---------- */

.about-page { background: var(--ink); }
#specks { position: fixed; inset: 0; width: 100%; height: 100%; z-index: 0; pointer-events: none; }

.about {
  position: relative;
  z-index: 1;
  min-height: 100vh;
  max-width: 1100px;
  margin: 0 auto;
  padding: calc(var(--topbar-h) + 60px) clamp(16px, 4vw, 48px) 80px;
  display: grid;
  grid-template-columns: minmax(240px, 360px) 1fr;
  gap: clamp(32px, 6vw, 90px);
  align-items: center;
}

/* One frame; the photos swap like a GIF. Each photo is scaled and
   shifted (via --s, --ex, --ey: zoom and eye-midpoint as fractions of the
   image) so her eyes always land on the same spot in the frame. */
.photo-frame {
  --tx: .5;   /* where the eyes sit in the frame, x */
  --ty: .45;  /* ... and y */
  position: relative;
  aspect-ratio: 9 / 16;
  margin: 0 auto;
  width: min(100%, calc(70vh * 9 / 16));
  overflow: hidden;
  box-shadow: 0 30px 60px -20px rgba(0, 0, 0, .8);
  background: var(--ink-2);
}
.photo-frame img {
  position: absolute;
  max-width: none;
  width: calc(var(--s) * 100%);
  height: calc(var(--s) * 100%);
  left: calc((var(--tx) - var(--ex) * var(--s)) * 100%);
  top: calc((var(--ty) - var(--ey) * var(--s)) * 100%);
  visibility: hidden;
}
.photo-frame img.on { visibility: visible; }

.about-copy h1 {
  margin: 0 0 24px;
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(56px, 8vw, 110px);
  line-height: .85;
  text-transform: uppercase;
}
.about-copy h1 em {
  font-style: normal;
  background: linear-gradient(90deg, var(--green), var(--yellow), var(--orange));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.about-copy p {
  max-width: 56ch;
  margin: 0 0 22px;
  font-size: clamp(15px, 1.15vw, 17px);
  line-height: 1.75;
  color: rgba(251, 250, 246, .85);
}
.about-copy a.inline { color: var(--green); border-bottom: 1px solid currentColor; }

/* ---------- Category gallery ---------- */

.gallery-head {
  padding: calc(var(--topbar-h) + 48px) clamp(16px, 3vw, 40px) 24px;
}
.back { font-size: 14px; color: rgba(251, 250, 246, .6); }
.back:hover { color: var(--accent); }
.gallery-head h1 {
  margin: 12px 0 0;
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(56px, 10vw, 140px);
  line-height: .85;
  text-transform: uppercase;
}

.masonry {
  columns: 4 260px;
  column-gap: 14px;
  padding: 0 clamp(16px, 3vw, 40px) 80px;
}
.masonry button {
  display: block;
  width: 100%;
  margin: 0 0 14px;
  padding: 0;
  border: 0;
  background: var(--ink-2);
  cursor: zoom-in;
  break-inside: avoid;
  overflow: hidden;
}
.masonry img { width: 100%; height: auto; transition: transform .6s cubic-bezier(.2, .7, .2, 1); }
.masonry button:hover img { transform: scale(1.03); }
/* Gouache paintings are all tall and detailed: 3 columns (2 on tablets, 1 on
   phones) makes each as big as it can be while still fitting on a laptop screen */
[data-cat="gouache"] .masonry { columns: 3 340px; }

/* Editorial layout (commissions): two columns of paintings */
.ed-grid {
  max-width: 1100px;
  margin: 0 auto;
  padding: clamp(8px, 2vw, 24px) clamp(16px, 4vw, 48px) 96px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(14px, 3vw, 40px);
  align-items: start;
}
.ed-col { display: flex; flex-direction: column; gap: clamp(14px, 3vw, 40px); }
.ed-col button {
  display: block;
  padding: 0;
  border: 0;
  background: var(--ink-2);
  cursor: zoom-in;
  overflow: hidden;
}
.ed-col img { width: 100%; height: auto; transition: transform .6s cubic-bezier(.2, .7, .2, 1); }
.ed-col button:hover img { transform: scale(1.03); }

/* Story layout (originals): each painting gets a screen, laid out like a page
   in a printed catalogue. A paper card floats on a huge close-up of the
   painting; a banner cut from the painting carries the title, and under it sit
   the full painting, the write-up and any other views. The page snaps from
   painting to painting; a screen too short for a long write-up scrolls
   through it first, then snaps on. story.js sets --img (the painting, once it's
   near), --banner-y (which strip of it the banner shows, from writeups.md) and
   --close-up (where the background close-up is taken from). */
html.story-snap { scroll-snap-type: y mandatory; }
.story-snap .footer { scroll-snap-align: end; }

/* Read out by screen readers, not shown */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.st {
  --card-ink: #2b2520;
  --card-paper: #fbf8f3;
  --card-panel: #eee7dd;
  --catalogue-serif: "Iowan Old Style", "Palatino Linotype", Palatino, "Book Antiqua", Georgia, serif;
  position: relative;
  isolation: isolate;
  overflow: hidden;
  min-height: 100svh;
  padding: calc(var(--topbar-h) + 4px) clamp(12px, 4vw, 56px) 20px;
  display: grid;
  place-items: center;
  scroll-snap-align: start;
}
/* The close-up of the painting behind the card, darkened to sit with the site */
.st::before,
.st::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
}
.st::before {
  background: var(--img, none) var(--close-up, 50% 50%) / 420% auto no-repeat, var(--ink-2);
  transition: transform 1.6s cubic-bezier(.2, .7, .2, 1);
}
.st::after { background: linear-gradient(rgba(14, 12, 18, .3), rgba(14, 12, 18, .55)); }

.oc-card {
  --banner-h: clamp(120px, 19svh, 220px);
  width: min(1240px, 100%);
  min-height: calc(100svh - var(--topbar-h) - 24px);
  padding: clamp(10px, 1.4vw, 20px);
  display: flex;
  flex-direction: column;
  background: var(--card-paper);
  color: var(--card-ink);
  box-shadow: 0 50px 100px -30px rgba(0, 0, 0, .9);
}

/* Banner: a strip through the painting, with the title across it */
.oc-banner {
  position: relative;
  flex: 0 0 var(--banner-h);
  display: grid;
  place-items: center;
  overflow: hidden;
  text-align: center;
  background: var(--img, none) 50% var(--banner-y, 50%) / cover no-repeat, #3a3330;
}
.oc-banner::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 60% 90% at center, rgba(10, 8, 12, .5), rgba(10, 8, 12, .08));
}
.oc-banner-in { position: relative; padding: 0 24px; color: #fff; }
.oc-banner h2 {
  margin: 0;
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(40px, 5.4vw, 92px);
  line-height: .88;
  letter-spacing: .02em;
  text-transform: uppercase;
  text-shadow: 0 4px 30px rgba(0, 0, 0, .45);
}
.oc-details {
  margin: 12px 0 0;
  font-size: 11px;
  letter-spacing: .32em;
  text-transform: uppercase;
  text-shadow: 0 1px 8px rgba(0, 0, 0, .6);
}

/* The thin line under the banner, like a page header */
.oc-strip {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  padding: 14px clamp(16px, 2.4vw, 32px);
  background: var(--card-panel);
  border-bottom: 1px solid rgba(43, 37, 32, .1);
}
.oc-artist span { color: rgba(43, 37, 32, .5); }
.oc-artist {
  font-family: var(--display);
  font-weight: 600;
  font-size: 15px;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.oc-num {
  font-size: 11px;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: rgba(43, 37, 32, .55);
}
.oc-num b { font-weight: 600; color: var(--card-ink); }

/* The painting and its story */
.oc-body {
  flex: 1;
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
  gap: clamp(20px, 3vw, 48px);
  padding: clamp(16px, 1.8vw, 24px) clamp(16px, 2.4vw, 32px);
  background: var(--card-panel);
}
.st.flip .oc-body { grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr); }
.st.flip .oc-main { order: 2; }
.oc-main {
  position: relative;
  min-height: 240px;
  padding: 0;
  border: 0;
  background: none;
  cursor: zoom-in;
}
/* Fills whatever room the card has, whole painting always showing */
.oc-main img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  filter: drop-shadow(0 18px 22px rgba(43, 37, 32, .28));
  transition: transform .6s cubic-bezier(.2, .7, .2, 1);
}
.oc-main:hover img { transform: scale(1.015); }

.oc-copy {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-width: 0;
}
.oc-text {
  max-width: 52ch;
  margin: 0 0 14px;
  font-family: var(--catalogue-serif);
  font-style: italic;
  font-size: clamp(15px, 1.12vw, 17px);
  line-height: 1.65;
  color: #3d342d;
}
/* A stencil drop capital to open each story */
.oc-text:first-child::first-letter {
  float: left;
  margin: .06em .12em 0 0;
  font-family: var(--display);
  font-style: normal;
  font-weight: 600;
  font-size: 3.7em;
  line-height: .8;
  color: var(--card-ink);
}
.oc-views { margin-top: 10px; }
.oc-label {
  margin: 0 0 10px;
  font-size: 10.5px;
  letter-spacing: .24em;
  text-transform: uppercase;
  color: rgba(43, 37, 32, .55);
}
.oc-thumbs { display: flex; flex-wrap: wrap; gap: 12px; }
.oc-thumbs button {
  height: clamp(64px, 9svh, 110px);
  padding: 0;
  border: 0;
  background: none;
  cursor: zoom-in;
}
.oc-thumbs img {
  height: 100%;
  width: auto;
  aspect-ratio: var(--r, 1);
  object-fit: cover;
  box-shadow: 0 10px 20px -10px rgba(43, 37, 32, .55);
  transition: transform .3s ease;
}
.oc-thumbs button:hover img { transform: translateY(-3px); }

/* Each card settles into place as it arrives, the close-up easing back behind it */
.st-animate .oc-card {
  opacity: 0;
  transform: translateY(36px) scale(.985);
  transition: opacity .8s ease, transform .9s cubic-bezier(.2, .7, .2, 1);
}
.st-animate .st.in .oc-card { opacity: 1; transform: none; }
.st-animate .st::before { transform: scale(1.08); }
.st-animate .st.in::before { transform: none; }

/* Tablets and phones: banner, then the story and other views, then the painting */
@media (max-width: 900px) {
  .st { padding: calc(var(--topbar-h) + 4px) 10px 16px; }
  .oc-card { min-height: 0; --banner-h: 30svh; }
  .oc-body,
  .st.flip .oc-body { grid-template-columns: minmax(0, 1fr); }
  .oc-main,
  .st.flip .oc-main { order: 2; min-height: 0; }
  .oc-main img {
    position: static;
    height: auto;
    aspect-ratio: var(--r, auto);
  }
  .oc-artist { font-size: 13px; }
  .oc-num { font-size: 10px; letter-spacing: .14em; }
}

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: none;
  place-items: center;
  background: rgba(8, 7, 10, .94);
}
.lightbox.open { display: grid; }
.lightbox img { max-width: 92vw; max-height: 88vh; object-fit: contain; }
.lightbox button {
  position: absolute;
  background: none;
  border: 0;
  color: var(--paper);
  font-size: 34px;
  cursor: pointer;
  padding: 16px;
  font-family: var(--sans);
}
.lightbox .lb-close { top: 8px; right: 12px; }
.lightbox .lb-prev  { left: 8px; top: 50%; transform: translateY(-50%); }
.lightbox .lb-next  { right: 8px; top: 50%; transform: translateY(-50%); }
.lightbox button:hover { color: var(--accent); }

/* ---------- Shop placeholder ---------- */

.placeholder {
  min-height: 100vh;
  display: grid;
  place-items: center;
  text-align: center;
  padding: 0 16px;
}
.placeholder h1 {
  margin: 0;
  font-family: var(--display);
  font-size: clamp(64px, 14vw, 180px);
  line-height: .85;
  text-transform: uppercase;
}
.placeholder p { color: rgba(251, 250, 246, .6); }

/* ---------- Responsive ---------- */

@media (max-width: 1000px) {
  .grid { grid-template-columns: repeat(2, 1fr); }
  .sheet { grid-template-columns: repeat(6, 1fr); }
}

@media (max-width: 560px) {
  .grid { grid-template-columns: 1fr; }
  .sheet { grid-template-columns: repeat(2, 1fr); padding: 12px; }
}

@media (max-width: 760px) {
  .hero {
    --bar-l: 0vw;
    --bar-w: 44vw;
    --title-l: 5vw;
  }
  .art-stage {
    right: 5vw;
    top: calc(var(--topbar-h) + 12px);
    width: 74vw;
    transform: none;
  }
  .title { font-size: 21vw; top: auto; bottom: 30%; transform: none; }
  .year  { font-size: 19vw; top: auto; bottom: 12%; left: calc(var(--bar-w) + 4vw); }
  .byline { top: auto; bottom: 13%; padding: 0 4vw; }
  .byline .name { font-size: 20px; }
  .byline .role { font-size: 10px; }
  .scroll-cue { bottom: 16px; }
  .home .topbar { padding-left: 16px; }

  .about { grid-template-columns: 1fr; padding-top: calc(var(--topbar-h) + 32px); }
  .photo-frame { width: min(70%, calc(62vh * 9 / 16)); }

  .footer { flex-direction: column; text-align: center; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
  .tile { opacity: 1; transform: none; }
  .ff-layer { display: none; }
}
