/* Claude Monet, portfolio demo.
   Idea: a museum that lets you touch. Walls take each painting's colour (a curator's choice),
   labels follow museum wall-label form, and nothing competes with the paintings. */

:root {
  color-scheme: light;
  --gallery: #ededea;          /* gallery white, neutral, not cream */
  --gallery-2: #e3e3df;
  --band: #dcddd7;             /* the wall the collection hangs on */
  --ink: #1a1c1f;
  --ink-2: #555960;
  --line: rgba(26, 28, 31, .14);
  --warn: #9b3b26;
  --on-art: #f4f3ee;           /* text sitting on a painting */

  /* set by JS per painting; defaults are the gallery */
  --wall: var(--gallery);
  --wall-ink: var(--ink);
  --wall-muted: var(--ink-2);
  --nav-ink: var(--on-art);
  --nav-pill: var(--on-art);
  --nav-pill-ink: #1a1c1f;

  --font: "Switzer", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --fs-display: clamp(4rem, 9.6vw, 9.5rem);
  --fs-h2: clamp(2rem, 3vw, 2.75rem);
  --fs-body: 1.125rem;
  --fs-label: .875rem;

  --gutter: clamp(16px, 4vw, 56px);
  --section: 160px;
  --hero-bottom: 56px;
  --ease: cubic-bezier(.16, 1, .3, 1);
  --ease-io: cubic-bezier(.65, 0, .35, 1);

  --z-nav: 20;
  --z-wall: 30;
  --z-guide: 40;
  --z-detail: 50;
}

@media (prefers-color-scheme: dark) {
  :root {
    color-scheme: dark;
    --gallery: #17181a;
    --gallery-2: #202124;
    --band: #232427;
    --ink: #e8e8e4;
    --ink-2: #a4a7ac;
    --line: rgba(232, 232, 228, .16);
    --warn: #f08b6e;
  }
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scrollbar-gutter: stable; } /* no 15px jump when scrolling locks */
html.is-locked { overflow: hidden; }
body {
  margin: 0;
  background: var(--gallery);
  color: var(--ink);
  font-family: var(--font);
  font-size: var(--fs-body);
  font-weight: 400;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
img { display: block; max-width: 100%; height: auto; }
button { font: inherit; color: inherit; }
a { color: inherit; text-underline-offset: .18em; text-decoration-thickness: 1px; }
h1, h2, p, figure, ol { margin: 0; }
:focus-visible { outline: 2px solid currentColor; outline-offset: 3px; }

h2 {
  font-size: var(--fs-h2);
  font-weight: 500;
  letter-spacing: -.022em;
  line-height: 1.06;
  text-wrap: balance;
  max-width: 17ch;
}
.label { font-size: var(--fs-label); line-height: 1.45; }
.label i, .title-i { font-style: italic; }

.skip {
  position: absolute; left: -9999px; top: 16px; z-index: 100;
  padding: 8px 16px; border-radius: 999px; background: var(--ink); color: var(--gallery);
}
.skip:focus { left: 16px; }

/* Interactive things are pills; paintings and their frames are sharp. */
.pill {
  --h: 48px;
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  height: var(--h); padding: 0 24px;
  overflow: hidden;
  border: 0; border-radius: 999px;
  background: var(--ink); color: var(--gallery);
  font-size: var(--fs-body); font-weight: 500; line-height: var(--h); white-space: nowrap;
  text-decoration: none; cursor: pointer;
  transition: transform .16s var(--ease), background-color .3s var(--ease), color .3s var(--ease);
}
/* hover: the label rolls up and the same words roll in from below */
.pill > span { position: relative; display: block; transition: transform .5s var(--ease); }
.pill > span::after {
  content: attr(data-t);
  content: attr(data-t) / ""; /* the copy is decoration: screen readers hear the label once */
  position: absolute; left: 0; right: 0; top: 100%; text-align: center;
}
@media (hover: hover) { .pill:hover > span { transform: translateY(-100%); } }
.pill:active { transform: scale(.97); }
.pill--quiet { background: var(--ink-2); color: var(--gallery); }
.pill--wall { background: var(--wall-ink); color: var(--wall); }
.pill:focus-visible { outline: 2px solid var(--ink); }
.pill--wall:focus-visible { outline-color: var(--wall-ink); }
.nav__cta:focus-visible { outline-color: var(--nav-ink); }
.pill:disabled { opacity: .5; cursor: default; transform: none; }

/* ---------- nav ---------- */
.nav {
  position: fixed; inset: 0 0 auto 0; z-index: var(--z-nav);
  display: flex; align-items: center; justify-content: space-between;
  height: 72px; padding: 0 var(--gutter);
  color: var(--nav-ink);
  pointer-events: none;
  transition: color .4s var(--ease), transform .5s var(--ease), background-color .4s var(--ease);
}
.nav > * { pointer-events: auto; }
.nav.is-hidden { transform: translateY(-100%); }
.nav.is-solid { background: var(--nav-bg, var(--gallery)); }
.nav__name { font-weight: 500; text-decoration: none; letter-spacing: -.01em; transition: opacity .4s var(--ease), visibility .4s; }
/* over the hero the big name is the name; the small one comes back once it has scrolled away */
.nav.is-over-hero .nav__name { opacity: 0; visibility: hidden; }
.nav__cta { --h: 40px; padding: 0 20px; background: var(--nav-pill); color: var(--nav-pill-ink); }

/* ---------- hero: the touchable painting ---------- */
.hero {
  position: relative;
  height: 100svh; min-height: 560px;
  overflow: hidden;
  background: #2f3020;
  color: var(--on-art);
}
.hero__media { position: absolute; inset: 0; background-size: cover; background-position: center; }
.hero__img, .hero__canvas {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
}
.hero__img { object-fit: cover; }
.hero__canvas { opacity: 0; transition: opacity .8s var(--ease); touch-action: pan-y; }
.hero__canvas.is-on { opacity: 1; }
.hero.has-touch-ring .hero__canvas { cursor: none; }
/* shade for the text; once WebGL draws, the shader does this itself (under the painted name) */
.hero::after {
  content: ""; position: absolute; inset: auto 0 0 0; height: 50%;
  background: linear-gradient(to top, rgba(14, 16, 10, .58), rgba(14, 16, 10, 0));
  pointer-events: none;
  transition: opacity .8s var(--ease);
}
.hero.gl-on::after { opacity: 0; }
/* the name is painted by WebGL; the h1 keeps its place for readers and search */
.hero.has-gl .hero__name { color: transparent; }
.hero.has-gl .hero__name .line > span { transform: none !important; transition: none !important; }
.hero__ring {
  position: absolute; left: 0; top: 0; z-index: 3;
  width: 28px; height: 28px; margin: -14px 0 0 -14px;
  border: 1px solid rgba(244, 243, 238, .8); border-radius: 50%;
  pointer-events: none; opacity: 0;
  transition: opacity .3s var(--ease), scale .3s var(--ease);
}
.hero__ring.is-on { opacity: 1; }
.hero__ring.is-down { scale: 1.9; opacity: .5; }

.hero__text {
  position: absolute; z-index: 2;
  left: var(--gutter); bottom: var(--hero-bottom);
  pointer-events: none;
}
.hero__name {
  font-size: var(--fs-display);
  font-weight: 500;
  letter-spacing: -.045em;
  line-height: .9;
  margin-left: -.05em;
}
.hero__lede { margin-top: 24px; }
.hero__label {
  position: absolute; z-index: 2;
  right: var(--gutter); bottom: var(--hero-bottom);
  max-width: 280px;
  color: var(--on-art);
  pointer-events: none;
}
/* small text over a busy painting: a soft dark halo keeps every letter readable */
.hero__lede, .hero__label { text-shadow: 0 1px 2px rgba(10, 12, 8, .55), 0 0 18px rgba(10, 12, 8, .45); }
.hero__crop { display: none; }
@media (max-aspect-ratio: 6/5) { .hero__crop { display: inline; } }

/* line-by-line reveal on load (the one orchestrated moment) */
.line { display: inline-block; overflow: hidden; vertical-align: top; padding-bottom: .18em; margin-bottom: -.18em; }
.line > span { display: inline-block; }
.js .hero .line > span { transform: translateY(105%); }
.js .hero.is-ready .line > span { transform: none; transition: transform 1.1s var(--ease); }
.js .hero.is-ready .hero__name .line:nth-child(2) > span { transition-delay: .08s; }
.js .hero.is-ready .hero__lede .line > span { transition-delay: .24s; }
.js .hero__label { opacity: 0; }
.js .hero.is-ready .hero__label { opacity: 1; transition: opacity 1s var(--ease) .5s; }

/* ---------- series: the wall changes with each painting ---------- */
.series {
  position: relative;
  background: var(--wall);
  color: var(--wall-ink);
}
.series__intro { padding: var(--section) var(--gutter) 0; }
.series__intro p { margin-top: 24px; max-width: 34em; color: var(--wall-muted); }
.series__stage {
  position: relative;
  height: 100svh;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(220px, 300px);
  gap: 48px;
  align-items: center;
  padding: 88px var(--gutter) 56px;
}
.series__roller { position: absolute; inset: 0; visibility: hidden; pointer-events: none; }
.series__frames, .series__side { position: relative; z-index: 1; }
.series__frames { height: 100%; }
.series__frame {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  opacity: 0;
}
.series__frame:first-child { opacity: 1; }
.series__frame img {
  width: auto; height: auto; max-width: 100%; max-height: 100%;
  box-shadow: 0 40px 80px -40px color-mix(in srgb, var(--wall), #000 70%);
}
/* chips stay put at the top; the caption's last line sits on the painting's bottom edge */
.series__side { align-self: stretch; display: flex; flex-direction: column; justify-content: space-between; gap: 24px; }
.series__captions { position: relative; min-height: 220px; }
.series__caption { position: absolute; inset: auto 0 0 0; opacity: 0; }
.series__caption:first-child { opacity: 1; }
.series__caption h3 {
  margin: 0 0 16px;
  font-size: var(--fs-h2); font-weight: 400; font-style: italic;
  letter-spacing: -.02em; line-height: 1.08;
  padding-bottom: .08em;
}
.series__caption .label { color: var(--wall-muted); }
/* paint chips: each one is the wall colour of one painting */
.series__chips { display: flex; gap: 12px; }
.chip {
  width: 32px; height: 32px; padding: 0;
  background: var(--chip);
  border: 2px solid var(--wall-muted);
  border-radius: 50%;
  cursor: pointer;
  transition: transform .2s var(--ease), box-shadow .2s var(--ease);
}
.chip:hover { transform: scale(1.1); }
.chip[aria-pressed="true"] { box-shadow: 0 0 0 3px var(--wall), 0 0 0 5px var(--wall-ink); }

/* reduced motion: no pinning, every painting gets its own wall */
.series.is-static .series__stage { display: none; }
.series__static { display: none; }
.series.is-static .series__static { display: block; }
.series__static figure { padding: 64px var(--gutter); display: grid; gap: 24px; }
.series__static img { max-height: 76vh; width: auto; }

/* ---------- collection: the endless wall ---------- */
.collection { padding: var(--section) 0; }
.collection__head { padding: 0 var(--gutter); }
.collection__head p { margin-top: 24px; max-width: 34em; color: var(--ink-2); }
.collection__foot { padding: 32px var(--gutter) 0; }
.wallslot { position: relative; height: min(64svh, 600px); margin-top: 56px; }
.wallview {
  position: absolute; inset: 0;
  overflow: hidden;
  background: var(--band);
  touch-action: pan-y;
  cursor: grab;
  user-select: none; -webkit-user-select: none;
  transition: background-color .6s var(--ease);
}
.wallview.is-dragging { cursor: grabbing; }
.wallview.is-full {
  position: fixed; inset: 0; z-index: var(--z-wall);
  touch-action: none;
}
.wallview__layer { position: absolute; inset: 0; }
.tile {
  position: absolute; left: 0; top: 0;
  padding: 0; border: 0; background: none;
  cursor: inherit;
  transform-origin: 50% 50%;
  will-change: transform;
}
.tile img {
  width: 100%; height: 100%; object-fit: cover;
  box-shadow: 0 24px 48px -28px rgba(20, 22, 24, .55);
  transition: transform .3s var(--ease);
  pointer-events: none;
  -webkit-user-drag: none;
}
.tile:hover img, .tile:focus-visible img { transform: scale(1.03); }
.tile__cap {
  position: absolute; left: 0; top: calc(100% + 12px);
  width: max-content; max-width: 280px;
  opacity: 0; transform: translateY(-4px);
  transition: opacity .2s var(--ease), transform .3s var(--ease);
  pointer-events: none; text-align: left;
}
.tile:hover .tile__cap, .tile:focus-visible .tile__cap { opacity: 1; transform: none; }
/* in the page the wall is one hang; the other rows only appear in full screen */
.tile { transition: opacity .6s var(--ease); }
.wallview:not(.is-full) .tile.is-offrow { opacity: 0; pointer-events: none; }
/* full-screen controls; hidden (and out of the tab order) in the page */
.wallview__hint, .wallview__close { position: absolute; z-index: 2; opacity: 0; visibility: hidden; transition: opacity .3s var(--ease), visibility .3s; }
.wallview__hint { left: var(--gutter); bottom: 24px; padding: 12px 16px; background: var(--gallery); color: var(--ink); }
.wallview__close { right: var(--gutter); top: 16px; }
.wallview.is-full .wallview__hint,
.wallview.is-full .wallview__close { opacity: 1; visibility: visible; transition: opacity .3s var(--ease); } /* focusable at once */
.wallview.is-full.was-dragged .wallview__hint { opacity: 0; visibility: hidden; transition: opacity .3s var(--ease), visibility .3s; }

/* ---------- detail: the painting on its own wall ---------- */
.detail {
  position: fixed; inset: 0; z-index: var(--z-detail);
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(260px, 360px);
  gap: 64px;
  padding: 88px var(--gutter) 56px;
  color: var(--wall-ink);
}
.detail[hidden] { display: none; }
.detail__bg { position: absolute; inset: 0; background: var(--wall); z-index: -1; }
.detail__fig { position: relative; min-height: 0; touch-action: none; }
.detail__img {
  position: fixed; left: 0; top: 0;
  max-width: none;
  transform-origin: 0 0;
  box-shadow: 0 48px 96px -48px color-mix(in srgb, var(--wall), #000 72%);
  user-select: none; -webkit-user-drag: none;
}
.detail__img--next { opacity: 0; pointer-events: none; }
.detail.has-loupe .detail__fig { cursor: none; }
.detail__info { align-self: end; display: grid; gap: 16px; }
.detail__title { font-weight: 400; font-style: italic; max-width: none; padding-bottom: .06em; }
.detail__meta { color: var(--wall-muted); }
.detail__hint { color: var(--wall-muted); }
.detail__bar { position: absolute; right: var(--gutter); top: 16px; display: flex; gap: 8px; }

.loupe {
  position: fixed; left: 0; top: 0; z-index: 2;
  width: 0; height: 0;
  pointer-events: none;
}
.loupe__lens {
  position: absolute; left: -120px; top: -120px;
  width: 240px; height: 240px; border-radius: 50%;
  background-repeat: no-repeat;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .55), 0 24px 56px -16px rgba(0, 0, 0, .6);
  opacity: 0; transform: scale(.6);
  transition: opacity .16s var(--ease), transform .24s var(--ease);
}
.loupe.is-on .loupe__lens { opacity: 1; transform: none; }

/* ---------- phone photo fix ---------- */
.fix { padding: var(--section) var(--gutter); background: var(--gallery); }
.fix__head p { margin-top: 24px; max-width: 34em; color: var(--ink-2); }
.fix__ui {
  margin-top: 56px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(280px, 360px);
  gap: 48px;
  align-items: start;
}
.fix__stage {
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--gallery-2);
}
.fix__plane { position: absolute; left: 0; top: 0; transform-origin: 0 0; }
.fix__plane img { width: 100%; height: 100%; max-width: none; }
.fix__fixed, .fix__compare { position: absolute; left: 0; top: 0; max-width: none; opacity: 0; pointer-events: none; }
.fix__compare { width: 100%; height: 100%; object-fit: contain; transition: opacity .2s var(--ease); background: var(--gallery-2); }
.fix__stage.is-comparing .fix__compare { opacity: 1; }
.fix__outline { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; overflow: visible; }
.fix__outline polygon { fill: none; stroke: #f4f3ee; stroke-width: 2; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.fix__samples { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
.fix__sample {
  position: relative; aspect-ratio: 4 / 3;
  padding: 0; border: 0; background: var(--gallery-2);
  cursor: pointer; opacity: .55;
  transition: opacity .2s var(--ease);
}
.fix__sample img { width: 100%; height: 100%; object-fit: cover; }
.fix__sample:hover { opacity: .85; }
.fix__sample[aria-pressed="true"] { opacity: 1; box-shadow: 0 0 0 2px var(--gallery), 0 0 0 4px var(--ink); }
.fix__problem { margin-top: 24px; font-weight: 500; }
.fix__actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 16px; }
.fix__steps { list-style: none; padding: 0; margin-top: 32px; display: grid; gap: 12px; }
.fix__steps:empty { display: none; }
/* each finding appears when the fixer reaches it, not before */
.fix__steps li { display: grid; gap: 2px; animation: step-in .5s var(--ease) both; }
.fix__steps li span { color: var(--ink-2); font-size: var(--fs-label); }
.fix__idle { margin-top: 32px; color: var(--ink-2); }
@keyframes step-in { from { opacity: 0; transform: translateY(6px); } }
.fix__verdict { margin-top: 24px; font-weight: 500; min-height: 1.55em; }
.fix__verdict.is-warn { color: var(--warn); }
.fix__note { margin-top: 16px; color: var(--ink-2); }
.fix.is-pending .fix__ui { opacity: .4; pointer-events: none; }

/* ---------- footer ---------- */
.foot { padding: 48px var(--gutter) 96px; color: var(--ink-2); border-top: 1px solid var(--line); }
.foot p { max-width: 48em; }

/* ---------- try-out guide (for reviewing the demo; hide with ?clean) ---------- */
.guide {
  position: fixed; left: 50%; top: 16px; z-index: var(--z-guide);
  transform: translateX(-50%);
  font-family: "PingFang SC", "Microsoft YaHei", "Noto Sans SC", system-ui, sans-serif;
  font-size: 13px; line-height: 1.4;
  color: #f4f3ee;
}
.guide__toggle {
  height: 40px; padding: 0 16px;
  border: 0; border-radius: 999px;
  background: #1a1c1f; color: #f4f3ee;
  box-shadow: 0 8px 24px -10px rgba(0, 0, 0, .5);
  cursor: pointer;
}
.guide__toggle b { font-weight: 500; margin-left: 4px; }
.guide__list {
  position: absolute; left: 50%; top: 48px;
  transform: translateX(-50%);
  width: 268px; margin: 0; padding: 8px;
  list-style: none;
  background: #1a1c1f; border-radius: 16px;
  box-shadow: 0 16px 40px -16px rgba(0, 0, 0, .6);
}
.guide__list a { display: grid; gap: 2px; padding: 8px 12px; border-radius: 10px; text-decoration: none; }
.guide__list a span { opacity: .65; font-size: 12px; }
.guide__list a:hover, .guide__list a[aria-current="step"] { background: rgba(255, 255, 255, .1); }

/* ---------- small screens: designed, not shrunk ---------- */
@media (max-width: 719px) {
  :root { --fs-display: 21vw; --section: 96px; }
  .nav { height: 64px; }
  .nav__cta { --h: 36px; padding: 0 16px; font-size: var(--fs-label); }
  .hero__name .line { display: block; }
  .hero__text { bottom: 96px; right: var(--gutter); }
  .hero__lede { margin-top: 16px; }
  .hero__label { left: var(--gutter); right: auto; bottom: 24px; max-width: 60vw; }

  /* painting and caption as one centred group, no dead band under the painting */
  .series__stage {
    grid-template-columns: 1fr;
    grid-template-rows: auto auto;
    align-content: center;
    gap: 24px;
    padding: 64px var(--gutter) 32px;
  }
  .series__frames { height: min(52svh, calc((100vw - 32px) * .7)); }
  .series__side { align-self: start; justify-content: flex-start; gap: 16px; }
  .series__captions { min-height: 0; } /* set from the tallest caption in series.js */
  .series__caption { inset: 0 0 auto 0; }
  .series__caption h3 { margin-bottom: 8px; }

  .wallslot { height: min(56svh, 460px); margin-top: 40px; }
  .guide { left: auto; right: 16px; top: auto; bottom: 16px; transform: none; }
  .guide__list { left: auto; right: 0; top: auto; bottom: 48px; transform: none; }
  .guide__toggle b span { display: none; }
  .wallview__hint { right: var(--gutter); bottom: 72px; }

  .detail {
    grid-template-columns: 1fr;
    grid-template-rows: minmax(0, 1fr) auto;
    gap: 24px;
    padding: 72px var(--gutter) 24px;
  }
  .detail__info { gap: 8px; }
  .detail__bar .pill { padding: 0 18px; }

  /* photo fix on a phone: pick, see, act, verdict right under the photo, then the details */
  .fix__ui { display: flex; flex-direction: column; align-items: stretch; gap: 24px; }
  .fix__side { display: contents; }
  .fix__samples { order: 1; }
  .fix__problem { order: 2; margin-top: 0; }
  .fix__stage { order: 3; }
  .fix__actions { order: 4; margin-top: 0; flex-direction: column; }
  .fix__actions .pill { width: 100%; }
  .fix__verdict { order: 5; margin-top: 0; }
  .fix__steps, .fix__idle { order: 6; margin-top: 0; }
  .fix__note { order: 7; margin-top: 0; }
  .guide__toggle { height: 36px; padding: 0 14px; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: .01ms !important; animation-duration: .01ms !important; }
  .js .hero .line > span { transform: none; }
  .js .hero__label { opacity: 1; }
}
