/* Landing collage ---------------------------------------------------------- */

/* The sketches overlap like a pinned-up studio wall, joined by fine threads
   (layout.js places them, sketches.js draws them), with the description in a
   column to their left on wide screens and above them on narrow ones. On wide
   screens the collage is sized to fit the window, nav and footer included, so
   it reads as one page. */
body:has(> .ps-main) {
  background-color: #fff;
}

.ps-main {
  --ps-fit: calc(100svh - 180px); /* the height left for the collage */
  box-sizing: border-box;
  width: 100%;
  margin: 90px auto 1.5rem; /* clear the fixed nav */
  padding: 0 24px;
}

.ps-intro {
  position: relative;
  z-index: 1002; /* its line can run out over the pieces, so above them */
  max-width: 340px;
  margin-bottom: 2rem;
  font-family: var(--font-sans);
  color: #111;
}

@media (min-width: 1100px) {
  /* The description sits near the left edge, a little in from the nav and
     footer, and the collage centres in the space beside it. */
  .ps-main {
    display: grid;
    grid-template-columns: 300px minmax(0, 1fr);
    column-gap: 40px;
    align-items: start;
    padding-left: clamp(32px, 4vw, 80px);
  }

  .ps-board {
    justify-self: center;
    width: 100%;
    max-width: calc(var(--ps-fit) * 1180 / 870);
  }

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

@media (max-width: 1099px) {
  .ps-board {
    max-width: calc(var(--ps-fit) * 1080 / 1180);
    margin: 0 auto;
  }
}

.ps-intro h1 {
  margin: 0 0 6px;
  font-size: 22px;
  font-weight: 500;
  letter-spacing: -0.01em;
}

.ps-intro .ps-years {
  margin: 0 0 14px;
  font-size: var(--text-caption);
  letter-spacing: 0.02em;
  color: #888;
}

.ps-intro .ps-subtitle {
  margin: 0 0 14px;
  font-size: 13.5px;
  font-style: italic;
  font-weight: 400;
}

/* One line wherever there's room for it, running past the column if need be;
   phones wrap it. */
@media (min-width: 600px) {
  .ps-intro .ps-subtitle {
    white-space: nowrap;
  }
}

.ps-intro p {
  margin: 0 0 12px;
  font-size: 12.5px;
  font-weight: 300;
  line-height: 1.45;
}

.ps-board {
  position: relative;
}

.ps-piece {
  position: absolute;
  display: block;
  color: inherit;
  text-decoration: none;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.08), 0 1px 6px rgba(0, 0, 0, 0.06);
  transition: box-shadow 0.2s;
}

/* Hovered, a piece comes to the front, over the lines and captions. */
.ps-board:not(.ps-arranging) .ps-piece:hover,
.ps-piece:focus-visible {
  z-index: 2000 !important;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25), 0 6px 24px rgba(0, 0, 0, 0.12);
}

.ps-photo img {
  display: block;
  width: 100%;
  height: auto;
}

/* A caption under each piece, like a plate in a catalogue: a large, light
   number in brackets and the title beside it, both in grey, set straight on
   the page with no box. A soft halo of the page's colour keeps one legible
   where it crosses another piece. In a layer above the pieces and lines
   (sketches.js); a hovered piece still comes in front of it. */
.ps-captions {
  position: absolute;
  inset: 0;
  z-index: 1001; /* over every piece, however high arranging has stacked it */
  pointer-events: none;
}

.ps-caption {
  --ps-halo: #fff;
  position: absolute;
  display: flex;
  align-items: baseline;
  gap: 6px;
  margin-top: 5px;
  font-family: var(--font-sans);
  font-weight: 300;
  line-height: 1;
  color: #8a8a8a;
  white-space: nowrap;
  text-shadow: 0 0 2px var(--ps-halo), 0 0 4px var(--ps-halo), 0 0 6px var(--ps-halo);
  transition: color 0.2s;
}

.ps-num {
  font-size: 17px;
  letter-spacing: -0.02em;
}

.ps-name {
  font-size: 12px;
  letter-spacing: 0.01em;
}

.ps-caption.ps-hot {
  color: #111;
}

.ps-lines {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 1000; /* over every piece, however high arranging has stacked it */
  overflow: visible;
  pointer-events: none;
}

.ps-lines path,
.ps-lines line {
  fill: none;
  vector-effect: non-scaling-stroke;
}

/* Fineliner ink: thin, even and nearly black. */
.ps-lines .ps-thread {
  stroke: #1c1c1c;
  stroke-width: 0.8;
  stroke-linecap: round;
  stroke-opacity: 0.9;
}

.ps-lines .ps-dot {
  fill: #1c1c1c;
}

.ps-lines .ps-mark {
  stroke: #555;
  stroke-width: 0.6;
  stroke-dasharray: 3 3;
}

.ps-canvas {
  aspect-ratio: 1;
  background: #fff;
  overflow: hidden;
}

.ps-canvas canvas,
.ps-stage > canvas {
  display: block;
  width: 100% !important;
  height: 100% !important;
}

/* Type view ----------------------------------------------------------------
   The collage again, with the title set huge among the pieces instead of in
   the description column: the words sit at a depth in the stack (TYPE in
   layout.js), so some pieces cover the letters and the letters cover others.
   html.ps-type-view switches it on. */
.ps-type {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
  display: none;
}

.ps-type-view .ps-type {
  display: block;
}

.ps-type text {
  font-family: var(--font-sans);
  font-weight: 500;
  letter-spacing: -0.045em;
  fill: #111;
}

.ps-dark .ps-type text {
  fill: #f2f2ee;
}

/* The title is in the picture, so out of the column (but still read out). */
.ps-type-view .ps-intro h1 {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.ps-type-view .ps-intro .ps-years {
  margin-top: 0;
}

/* Index view ---------------------------------------------------------------
   The second view, like the index of plates at the back of a catalogue: a
   tight grid of the same pieces, each under a small #number, between two thin
   rules carrying small running text. It's square, four tiles by four, and
   sized to fit the window, so it screenshots straight into a square post. It
   takes the collage's place, so the description stays in its column.
   html.ps-index-view switches it on (set by the head include and
   sketches.js). */
.ps-index {
  display: none;
  flex-direction: column;
  box-sizing: border-box;
  width: min(100%, var(--ps-fit));
  aspect-ratio: 1;
  font-family: var(--font-sans);
  color: #111;
}

.ps-index-view .ps-board {
  display: none;
}

.ps-index-view .ps-index {
  display: flex;
}

@media (min-width: 1100px) {
  .ps-index {
    grid-column: 2;
  }
}

.ps-index-rule {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding-bottom: 5px;
  border-bottom: 1px solid #111;
  font-size: 10px;
  letter-spacing: 0.02em;
}

.ps-index-foot {
  margin-top: 12px;
  padding: 5px 0 0;
  border-bottom: none;
  border-top: 1px solid #111;
  color: #777;
}

.ps-index-grid {
  flex: 1;
  min-height: 0;
  list-style: none;
  margin: 10px 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  grid-template-rows: repeat(4, minmax(0, 1fr));
  gap: 12px 8px;
}

.ps-cell {
  display: flex;
  flex-direction: column;
  min-height: 0;
}

/* Each tile fits its cell whole, from the top-left, whatever its shape. */
.ps-cell-frame {
  flex: 1;
  min-height: 0;
  container-type: size;
}

.ps-tag {
  display: block;
  margin-bottom: 3px;
  font-size: 10px;
  letter-spacing: 0.02em;
  color: #111;
}

/* The pieces arrive with the collage's placement set inline; here they just
   fit their cell (--a is the piece's aspect, set in sketches.js). */
.ps-index .ps-piece {
  position: relative !important;
  left: auto !important;
  top: auto !important;
  width: min(100cqw, calc(100cqh * var(--a))) !important;
  z-index: auto !important;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.06);
}

.ps-index .ps-piece:hover {
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.35);
}

.ps-index-view .ps-arrange-bar {
  display: none;
}

/* collage · type · index, in the corner. */
.ps-views {
  display: flex;
  gap: 0;
}

.ps-corner .ps-views button {
  border-radius: 0;
  margin-left: -1px;
}

.ps-corner .ps-views button:first-child {
  margin-left: 0;
  border-radius: 4px 0 0 4px;
}

.ps-corner .ps-views button:last-child {
  border-radius: 0 4px 4px 0;
}

.ps-corner .ps-views button[aria-pressed="true"] {
  position: relative;
  color: #fff;
  background: #111;
  border-color: #111;
}

.ps-dark .ps-corner .ps-views button[aria-pressed="true"] {
  color: #111;
  background: #f2f2ee;
  border-color: #f2f2ee;
}

.ps-dark .ps-index {
  color: #f2f2ee;
}

.ps-dark .ps-index-rule {
  border-color: rgba(255, 255, 255, 0.8);
}

.ps-dark .ps-index-foot {
  color: rgba(255, 255, 255, 0.5);
}

.ps-dark .ps-tag {
  color: rgba(255, 255, 255, 0.8);
}

.ps-dark .ps-index .ps-piece {
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.08);
}

.ps-dark .ps-index .ps-piece:hover {
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.4);
}

/* The bottom-right corner: dev tools, on localhost only (sketches.js): the
   view and light/dark switches, and the arrange tool (arrange.js). */
.ps-corner {
  position: fixed;
  right: 16px;
  bottom: 16px;
  z-index: 1001;
  display: flex;
  gap: 6px;
  align-items: center;
  font: var(--text-caption) var(--font-sans);
  color: #777;
}

.ps-corner[hidden] {
  display: none;
}

.ps-corner button {
  padding: 4px 10px;
  font: inherit;
  color: #333;
  background: #fff;
  border: 1px solid #ccc;
  border-radius: 4px;
  cursor: pointer;
}

.ps-corner button:hover {
  border-color: #000;
}

.ps-corner button:disabled {
  color: #aaa;
  border-color: #e3e3e3;
  cursor: default;
}

/* Dark version ---------------------------------------------------------------
   Black page, white and grey text, grey threads; the sketches keep their own
   paper. The nav and links take the sketchbook's dark tones
   (sketchbook/gallery-theme.css). Set on <html> by the head include. */
html.ps-dark,
html.ps-dark body {
  color-scheme: dark;
  background-color: #0b0b0b;
}

.ps-dark a:link,
.ps-dark a:visited {
  color: #f2f2ee;
}

.ps-dark a:hover:not([data-frame]) {
  color: rgba(255, 255, 255, 0.52);
}

.ps-dark .header-nav {
  background: rgba(23, 23, 22, 0.72);
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
}

@media (prefers-reduced-transparency: reduce) {
  .ps-dark .header-nav {
    background: #0b0b0b;
    border-bottom: 1px solid rgba(255, 255, 255, 0.12);
  }
}

.ps-dark .ps-intro {
  color: #f2f2ee;
}

.ps-dark .ps-intro .ps-years {
  color: rgba(255, 255, 255, 0.45);
}

.ps-dark .ps-intro .ps-subtitle {
  color: rgba(255, 255, 255, 0.82);
}

.ps-dark .ps-intro p {
  color: rgba(255, 255, 255, 0.6);
}

.ps-dark .ps-corner {
  color: rgba(255, 255, 255, 0.45);
}

.ps-dark .ps-corner button {
  color: #e6e6e3;
  background: #161616;
  border-color: rgba(255, 255, 255, 0.2);
}

.ps-dark .ps-corner button:hover {
  border-color: rgba(255, 255, 255, 0.6);
}

.ps-dark .ps-corner button:disabled {
  color: rgba(255, 255, 255, 0.3);
  border-color: rgba(255, 255, 255, 0.1);
}

.ps-dark .ps-piece {
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.1), 0 8px 24px rgba(0, 0, 0, 0.45);
}

.ps-dark .ps-board:not(.ps-arranging) .ps-piece:hover,
.ps-dark .ps-piece:focus-visible {
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.3), 0 14px 34px rgba(0, 0, 0, 0.55);
}

.ps-dark .ps-caption {
  --ps-halo: #0b0b0b;
  color: rgba(255, 255, 255, 0.5);
}

.ps-dark .ps-caption.ps-hot {
  color: #f2f2ee;
}

.ps-dark .ps-lines .ps-thread {
  stroke: #8a8a8a;
  stroke-opacity: 1;
}

.ps-dark .ps-lines .ps-dot {
  fill: #8a8a8a;
}

.ps-dark .ps-lines .ps-mark {
  stroke: #6a6a6a;
}

.ps-dark .ps-card-link .ps-canvas {
  border-color: rgba(255, 255, 255, 0.1);
}

/* Arranging the collage on localhost (arrange.js): pieces outlined, a corner
   handle on each for resizing, and the tool's buttons in the corner beside
   the light/dark switch. */
.ps-arranging .ps-piece {
  cursor: move;
  outline: 1px dashed rgba(0, 0, 0, 0.35);
  outline-offset: 2px;
}

.ps-arranging .ps-piece.ps-moving {
  outline-color: #000;
}

.ps-handle {
  display: none;
  position: absolute;
  right: -6px;
  bottom: -6px;
  width: 11px;
  height: 11px;
  background: #fff;
  border: 1px solid #000;
  cursor: nwse-resize;
  z-index: 1;
}

.ps-arranging .ps-handle {
  display: block;
}

.ps-arrange-bar {
  display: flex;
  gap: 6px;
  align-items: center;
}

/* The title's depth, only while arranging the type view. */
.ps-corner .ps-text-z {
  display: none;
}

.ps-type-view .ps-arranging-on .ps-text-z {
  display: inline-block;
}

/* Arranging the type view: the title's words take the pointer too. */
.ps-type-view .ps-arranging .ps-type text {
  pointer-events: auto;
  cursor: move;
}

.ps-type-view .ps-arranging .ps-type text:hover {
  opacity: 0.75;
}

.ps-arrange-hint {
  display: none;
}

.ps-arranging-on .ps-arrange-hint {
  display: inline;
}

/* Sketches not yet placed in the collage. */
.ps-grid {
  list-style: none;
  margin: 4rem 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 2rem 1.5rem;
  font-family: var(--font-sans);
}

.ps-grid:empty {
  display: none;
}

.ps-card-link {
  display: block;
  color: inherit;
  text-decoration: none;
}

.ps-card-link .ps-canvas {
  border: 1px solid #e6e6e6;
}

.ps-card-link .ps-title {
  display: block;
  margin-top: 0.5rem;
  font-size: var(--text-caption);
}

/* Copies the sketch as a standalone script for OpenProcessing (export.js,
   localhost only). */
.ps-export {
  padding: 0;
  font: inherit;
  color: #bbb;
  background: none;
  border: none;
  cursor: pointer;
}

.ps-export:hover {
  color: #000;
}


/* Local reordering (localhost only, see reorder.js) ----------------------- */

.ps-card[draggable="true"] {
  cursor: grab;
}

.ps-dragging {
  opacity: 0.35;
}

.ps-save-order {
  position: fixed;
  right: 16px;
  bottom: 16px;
  padding: 4px 10px;
  font: var(--text-caption) var(--font-sans);
  color: #555;
  background: #fff;
  border: 1px solid #ddd;
  border-radius: 4px;
  cursor: pointer;
}

.ps-save-order:disabled {
  color: #aaa;
  cursor: default;
}

/* Single-sketch view ------------------------------------------------------ */

body.ps-view {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-family: var(--font-sans);
}

.ps-back {
  position: fixed;
  top: 16px;
  left: 16px;
  font-size: var(--text-caption);
  color: #777;
  text-decoration: none;
}

.ps-back:hover {
  color: #000;
}

.ps-stage {
  width: min(92vw, calc(82vh * var(--aspect, 1)));
  aspect-ratio: var(--aspect, 1);
  background: #fff;
  cursor: pointer;
}

.ps-caption {
  font-size: var(--text-caption);
  color: #999;
  margin: 1rem 0 0;
}

/* Webcam window for camera pieces (lib/camera-window.js): sits just right of
   the stage, or in the screen's corner when there's no room beside it. */
.ps-stage {
  position: relative;
}

.ps-cam {
  position: absolute;
  left: calc(100% + 32px);
  top: 50%;
  transform: translateY(-50%);
  width: 280px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  cursor: default;
}

.ps-cam canvas {
  width: 100%;
  background: #eee;
  border-radius: 14px;
}

.ps-cam-off canvas {
  display: none;
}

.ps-cam button {
  align-self: flex-start;
  padding: 0;
  font: var(--text-caption) var(--font-sans);
  color: #999;
  background: none;
  border: none;
  cursor: pointer;
}

.ps-cam button:hover {
  color: #000;
}

/* With the camera off, the button is all there is: make it findable. */
.ps-cam-off button {
  padding: 6px 14px;
  color: #333;
  border: 1px solid #ccc;
  border-radius: 999px;
}

.ps-cam-off button:hover {
  border-color: #000;
}

.ps-cam-corner {
  position: fixed;
  left: auto;
  top: auto;
  right: 16px;
  bottom: 16px;
  transform: none;
  width: 160px;
}

.ps-cam-corner canvas {
  border-radius: 10px;
}

.ps-cam-corner button {
  align-self: flex-end;
}
