:root {
  --bg-black: #000000;
  --bg-burgundy: #2A0009;
  --mint-light: #D0FFEA;
  --mint-dark: #AEEB87;
  --pink: #FF0093;
  --burgundy-accent: #A2084E;
  --text-light: #FDF2F2;
  --text-edge: 24px;
  /* How far the round controls sit below the top of the window. The shared
     artwork bar draws over everything, so the info button has to wait below
     where the bar lands once it is pulled down. That height is the bar's own
     padding (14px + 42px) plus its logo, which is clamp(46px, 5vw, 68px) wide
     and 0.945 as tall as it is wide — 120px on a laptop — and then 16px of
     air. The whole step is then lifted by a tenth, which is as high as the
     button can be asked to sit and still clear the bar: it lands a couple of
     pixels under it rather than a comfortable margin. */
  --nav-clearance: calc(0.9 * (56px + 0.945 * clamp(46px, 5vw, 68px) + 16px));
  background: var(--bg-black);
}

* { box-sizing: border-box; }

html, body { width: 100%; height: 100%; margin: 0; background: var(--bg-black); overflow: hidden; }

/* Locks page scrolling while the project info overlay is open */
html.overlay-locked, body.overlay-locked { overflow: hidden !important; }

body { display: grid; height: 100dvh; place-items: center; overflow: hidden; }


/* Canvas */
#canvas-holder {
  /* The holder is the window itself, so the garden runs to all four edges the
     way the other three artworks do. The sketch still draws a fixed 1920x1080
     frame; the canvas below is grown until that frame covers the window and
     whatever hangs over the long edge is cropped here. Cropped, never
     stretched: pulling the frame into the window's own shape squashed the
     garden on every screen that is not 16:9 — at 4:3 it was compressed to
     three quarters of its width. Nothing lives in the strips that are cut:
     the flowers sit inside the middle half of the frame. */
  width: 100vw;
  height: 100dvh;
  position: relative;
  overflow: hidden;
  container-type: inline-size;
}

/* Cover: keep the 16:9 shape, size it to fill both axes, and let the auto
   margins centre it — they go negative on the overflowing axis, which is what
   crops the frame evenly on both sides. The cap holds for every ordinary
   screen up to 21:9; past 1.35x the fitting size the frame stops growing, so a
   phone held upright or a doubled-up ultrawide falls back to bands at the
   edges rather than zooming so far in that the garden is lost. */
#canvas-holder canvas {
  display: block;
  position: absolute;
  inset: 0;
  margin: auto;
  z-index: 0;
  aspect-ratio: 16 / 9;
  width: min(
    max(100vw, calc(100dvh * 16 / 9)),
    calc(min(100vw, calc(100dvh * 16 / 9)) * 1.35)
  ) !important;
  height: auto !important;
  cursor: crosshair;
}


/* Typography grid (12x12) */

/* The words stay on the 16:9 frame *fitted* to the window rather than on the
   cropped one, so they keep the size and the corner placement they have always
   had and none of them can be cut off by the crop. */
#copy-layer {
  position: absolute; z-index: 1; inset: 0; margin: auto;
  width: min(100vw, calc(100dvh * 16 / 9));
  height: min(100dvh, calc(100vw * 9 / 16));
  container-type: inline-size;
  pointer-events: none; color: var(--text-light);
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  grid-template-rows: repeat(12, 1fr);
  padding: var(--text-edge);
}

.quote { font-family: "League Spartan", sans-serif; font-weight: 430; letter-spacing: -0.075em; line-height: 0.82; }
.quote__sans { display: block; font-size: 7.45cqw; white-space: nowrap; color: var(--text-light); }
.quote__question { display: flex; align-items: center; height: 8.5cqw; font-size: 7.15cqw; white-space: nowrap; color: #c9f3bd; }
.quote__script { display: inline-block; position: relative; z-index: 2; flex: 0 0 8cqw; margin-right: 0.4cqw; margin-top: -0.1cqw; font-family: "Mea Culpa", cursive; font-size: 7.15cqw; font-weight: 430; line-height: 0.68; letter-spacing: 0; color: #c9f3bd; }
.quote--when .quote__sans > span { display: block; line-height: 0.92; }
.quote--when .quote__question { margin-top: 0; }

.wave-letter {
  display: inline-block;
  animation: wave-letter-bob 1.8s ease-in-out infinite;
}

.quote__question > span:not(.quote__script) {
  position: relative;
  z-index: 1;
}
@keyframes wave-letter-bob {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-0.14em); }
}
@media (prefers-reduced-motion: reduce) {
  .wave-letter { animation: none; }
}

.cta { font-family: "League Spartan", sans-serif; font-size: 1.28cqw; font-weight: 500; line-height: 1.4; color: var(--text-light); }
.cta p { margin: 0; }
.cta__message span { display: block; white-space: nowrap; }
#trace-status { margin-bottom: 0.8cqw; color: #ec56ad; font-size: 0.88cqw; font-weight: 700; letter-spacing: 0.06em; text-shadow: 0 0 12px rgba(255, 0, 147, 0.45); }

/* "TRACE 0X" label */

/* The labels point at pollen drawn on the canvas, so they ride the canvas
   layer, not the typography one: sketch.js sets each one in pixels measured
   off the canvas box, which is the only layer that knows where the crop put
   the artwork. */
#trace-layer { position: absolute; inset: 0; z-index: 1; pointer-events: none; }

.trace-label { position: absolute; color: var(--mint-light); font-family: "League Spartan", sans-serif; font-size: 0.72cqw; font-weight: 700; letter-spacing: 0.08em; opacity: 0; transition: opacity 260ms ease; text-shadow: 0 0 8px rgba(208, 255, 234, 0.55); transform: translateX(-50%); text-align: center; white-space: nowrap; }
.trace-label.is-visible { opacity: 0.9; }
.trace-label.is-hidden { opacity: 0; }

/* Instruction + hint text */

.hint-text {
  position: absolute;
  left: 51%;
  bottom: 2cqw;
  margin: 0;
  transform: translateX(-50%);
  font-family: "League Spartan", sans-serif;
  font-weight: 500;
  font-size: 1cqw;
  letter-spacing: 0.05em;
  color: var(--text-light);
  text-shadow:
    0 0 8px rgba(208, 255, 234, 0.85),
    0 0 20px rgba(208, 255, 234, 0.5),
    0 0 40px rgba(208, 255, 234, 0.25);
  text-align: center;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity 320ms ease;
}
.hint-text.is-visible { animation: hint-blink 1.3s ease-in-out infinite; }

.evidence-complete {
  position: absolute;
  left: 53%;
  top: 50%;
  margin: 0;
  transform: translate(-50%, -50%);
  font-family: "League Spartan", sans-serif;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-size: 2.6cqw;
  color: var(--pink);
  text-shadow:
    0 0 14px rgba(255, 0, 147, 0.95),
    0 0 32px rgba(255, 0, 147, 0.65),
    0 0 60px rgba(255, 0, 147, 0.35);
  text-align: center;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
}
.evidence-complete.is-visible { animation: hint-blink 0.9s ease-in-out infinite; }

@keyframes hint-blink {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.3; }
}

/* Quote + CTA */

.quote--who { transform: translateY(1.4cqw); } 

#copy-layer[data-layout="right"] .quote--who { grid-column: 8 / 13; grid-row: 1 / 4; justify-self: end; align-self: start; text-align: right; }
#copy-layer[data-layout="right"] .quote--who .quote__question { justify-content: flex-end; }
#copy-layer[data-layout="right"] .quote--when { grid-column: 1 / 6; grid-row: 8 / 13; justify-self: start; align-self: end; transform: translateY(1.6cqw); }
#copy-layer[data-layout="right"] .cta { grid-column: 8 / 13; grid-row: 10 / 13; justify-self: end; align-self: end; text-align: right; }

#copy-layer[data-layout="left"] .quote--who { grid-column: 1 / 6; grid-row: 1 / 4; justify-self: start; align-self: start; text-align: left; }
#copy-layer[data-layout="left"] .quote--when { grid-column: 8 / 13; grid-row: 8 / 13; justify-self: end; align-self: end; text-align: right; transform: translateY(1.6cqw); }
#copy-layer[data-layout="left"] .quote--when .quote__sans { text-align: right; }
#copy-layer[data-layout="left"] .quote--when .quote__question { justify-content: flex-end; }
#copy-layer[data-layout="left"] .cta { grid-column: 1 / 6; grid-row: 10 / 13; justify-self: start; align-self: end; text-align: left; }


/* Info button + panel */
/* An open ring with an "i" inside, in the same yellow-green the other three
   artworks use for this control, so the four pages read as one set. The ring
   and the letter both carry a soft halo in their own colour, which lifts the
   mark off the black garden without a solid disc underneath. */
.project-logo-btn {
  --mark-ink: #cbe45c;
  position: absolute;
  top: var(--nav-clearance);
  z-index: 3;
  width: 2.3cqw;
  height: 2.3cqw;
  min-width: 29px;
  min-height: 29px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1.5px solid var(--mark-ink);
  border-radius: 50%;
  background: none;
  cursor: pointer;
  pointer-events: auto;
  box-shadow:
    0 0 10px rgba(203, 228, 92, 0.45),
    inset 0 0 7px rgba(203, 228, 92, 0.18);
  transition: color 200ms ease, background 200ms ease, transform 200ms ease,
    box-shadow 200ms ease;
  color: var(--mark-ink);
}

/* The letter is sized as the same fraction of the frame the ring is (0.42 of
   2.3cqw), with the same 29px floor, so it stays centred at every window
   width instead of being typed in at one fixed size. */
.project-logo-btn__glyph {
  font: 400 max(12px, 0.97cqw) / 1 Helvetica, Arial, sans-serif;
  /* Helvetica hangs a lowercase "i" high in its line box; this drops the
     letter back onto the ring's own centre. */
  transform: translateY(0.06em);
  text-shadow: 0 0 7px rgba(203, 228, 92, 0.55);
  transition: text-shadow 200ms ease;
}

/* On hover the ring fills in and the letter drops out of it in the black of
   the garden — the same two colours swapping places. */
.project-logo-btn:hover,
.project-logo-btn:focus-visible {
  background: var(--mark-ink);
  color: var(--bg-black);
  transform: scale(1.06);
  box-shadow: 0 0 15px rgba(203, 228, 92, 0.6);
}
.project-logo-btn:hover .project-logo-btn__glyph,
.project-logo-btn:focus-visible .project-logo-btn__glyph { text-shadow: none; }

/* A tab stop needs to be tellable from a hover, so keyboard focus adds a ring
   in the page's mint on top of the filled state. */
.project-logo-btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--mint-light);
}

/* Info button always on the opposite side from the typography layout */
body:has(#copy-layer[data-layout="right"]) .project-logo-btn { left: max(12px, 1.25cqw); right: auto; }
body:has(#copy-layer[data-layout="left"]) .project-logo-btn { right: max(12px, 1.25cqw); left: auto; }

.project-overlay {
  position: fixed;
  inset: 0;
  z-index: 9999;
  /* A pink wash rather than a dark one, with the garden still showing through
     it: this is the piece talking about itself, so the panel should read as a
     layer of the picture rather than a window cut out of it. The colour is the
     project burgundy and the weight is the one the other three artworks use, so
     all four panels sit at the same depth. */
  background: rgba(162, 8, 78, 0.8);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 420ms ease, visibility 0s linear 420ms;
}
.project-overlay.is-open {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transition: opacity 420ms ease, visibility 0s linear 0s;
}

.overlay-close-btn {
  position: fixed;
  top: var(--nav-clearance);
  z-index: 2;
  width: 2.3vw;
  height: 2.3vw;
  min-width: 29px;
  min-height: 29px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1.1px solid currentColor;
  border-radius: 50%;
  background: none;
  color: var(--mint-dark);
  font-family: "League Spartan", sans-serif;
  font-weight: 700;
  font-size: 1.1vw;
  cursor: pointer;
  transition: color 200ms ease, transform 200ms ease;
}
.overlay-close-btn:hover,
.overlay-close-btn:focus-visible { color: var(--pink); transform: scale(1.06); }
.overlay-close-btn:focus-visible { outline: 2px solid var(--pink); outline-offset: 3px; }

/* Close button in the exact same corner spot as the info button */
body:has(#copy-layer[data-layout="right"]) .overlay-close-btn { left: max(12px, 1.25vw); right: auto; }
body:has(#copy-layer[data-layout="left"]) .overlay-close-btn { right: max(12px, 1.25vw); left: auto; }

.project-overlay__scroll {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  outline: none;
}

.project-overlay__inner {
  margin: 0;
  padding: 6vw 5vw 8vw;
}

.overlay-masthead { margin-bottom: 4.2vw; }
/* 60vw is the width the wordmark has on the other pages in the set, so the
   four panels open on the same title at the same size. */
.overlay-masthead__img { display: block; max-width: 60vw; width: 100%; height: auto; }

.overlay-column {
  display: flex;
  flex-direction: column;
  gap: 3.6vw;
  max-width: 58vw;
}

.overlay-title {
  font-family: "League Spartan", sans-serif;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: -0.01em;
  font-size: 2.16vw;
  line-height: 1.05;
  color: var(--mint-light);
  margin: 0 0 1vw;
  padding-bottom: 0.6vw;
  border-bottom: 3px solid var(--mint-dark);
}

.overlay-subtitle {
  font-family: "League Spartan", sans-serif;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-size: 1.38vw;
  color: var(--mint-dark);
  margin: 1.4vw 0 0.35vw;
}
.overlay-subtitle:first-of-type { margin-top: 0; }

.overlay-body {
  font-family: "League Spartan", sans-serif;
  font-weight: 400;
  font-size: 1.26vw;
  line-height: 1.5;
  color: var(--mint-light);
  margin: 0;
}
.overlay-body + .overlay-body { margin-top: 1vw; }
.overlay-body--lead { font-size: 1.26vw; }

.overlay-list {
  margin: 1vw 0 0;
  padding-left: 1.3vw;
  display: flex;
  flex-direction: column;
  gap: 1vw;
}
.overlay-list li {
  font-family: "League Spartan", sans-serif;
  font-weight: 400;
  font-size: 1.26vw;
  line-height: 1.5;
  color: var(--mint-light);
  padding-left: 0.4vw;
}

@media (max-width: 720px) {
  .overlay-title { font-size: 5.5vw; }
  .overlay-subtitle { font-size: 4.1vw; }
  .overlay-body { font-size: 3.6vw; }
  .overlay-body--lead { font-size: 3.6vw; }
  .overlay-list li { font-size: 3.6vw; }
  .overlay-column { max-width: 100%; }
}


/* Story caption */
.story-caption {
  display: inline-block; 
  margin-bottom: 0.7cqw;
  padding: 0.7cqw 1cqw;
  max-width: 26cqw; 
  background: rgba(0, 0, 0, 0.72);
  border-left: 3px solid var(--pink);
  border-radius: 2px;
  font-family: "League Spartan", sans-serif;
  font-weight: 500;
  font-size: 1.28cqw; 
  line-height: 1.4;
  color: var(--mint-light);
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 320ms ease, transform 320ms ease;
}
.story-caption:empty { margin-bottom: 0; }
.story-caption.is-visible { opacity: 1; transform: translateY(0); }

#copy-layer[data-layout="right"] .story-caption { border-left: none; border-right: 3px solid var(--pink); }

@media (max-width: 720px) {
  .story-caption { font-size: 3.2vw; max-width: 70vw; }
}