/**
 * Project page styles: the studio
 * One stylesheet for the project pages. The home page's studio on one screen:
 * the nav, the masthead and role row, the shot under the lamp where the figure
 * stands, the two columns, the closing line, the entrance. A page sets its own
 * colours as tokens on its own class (.pj-psnppp, .pj-window) and keeps
 * anything else of its own in its own sheet. Under 960px it all stacks.
 * Author: Trippixn · trippixn.com · discord.gg/syria
 */

.pj {
  /* Defaults, the home's greys: a page that set nothing would still read. Each page overrides them. */
  --cyc: #454341;
  --cyc-dark: #201f1d;
  --paper: #ede9e2;
  --paper-dim: #c6bfb6;
  --accent: #d29c6e;
  --on-accent: #121110;
  /* The lamp's colour as an rgb triplet, and its peak alpha. */
  --lamp: 255, 244, 228;
  --lamp-a: .22;
  /* The glint the lamp puts on the filled button. */
  --glint: rgba(255, 255, 255, .28);
  --hairline: rgba(237, 233, 226, .3);
  --status-up: #6fbf73;
  --status-down: #ba4b47;
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  /* The masthead's box, so the role row, the columns and the shot hang from it at any viewport. */
  --mast-top: max(8vh, 66px);
  --mast-size: min(17vw, 30vh);
  --mast-bottom: calc(var(--mast-top) + 0.9 * var(--mast-size));
  /* The shot's box: from under the role row to above the closing line, capped by width. */
  --shot-ratio: 1.545;
  --shot-top: calc(var(--mast-bottom) + 6vh);
  --end-h: calc(6vh + 44px);
  /* Narrower on a narrower desktop, so the columns keep their measure beside it. */
  --shot-cap: 48vw;
  --shot-h: min(calc(100svh - var(--shot-top) - var(--end-h)), calc(var(--shot-cap) / var(--shot-ratio)));

  position: relative;
  min-height: 100svh;
  overflow-x: clip;
  background: radial-gradient(ellipse 95% 85% at 50% 42%, var(--cyc) 28%, var(--cyc-dark) 100%);
  color: var(--paper);
  font-family: 'Archivo', 'Helvetica Neue', Arial, sans-serif;
  font-size: 17px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
}
.pj a { color: inherit; text-decoration: none; }
.pj :focus-visible { outline: 2px solid var(--paper); outline-offset: 4px; border-radius: 2px; }
/* Selected text is a print: the type's colour as the ground, the ground's as the type. */
.pj ::selection { background: var(--paper); color: var(--cyc-dark); }

/* ---------- the stage: one screen ---------- */
.pj-stage { position: relative; height: 100svh; }

/* The lamp: fixed to the viewport, moved by transform, the same disc as the home page. */
.pj-light {
  position: fixed;
  left: 0;
  top: 0;
  width: 0;
  height: 0;
  pointer-events: none;
  will-change: transform;
  transform: translate3d(50vw, 42vh, 0);
  animation: pj-lamp-on 1.4s var(--ease-out) both;
}
.pj-light::before {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  width: max(1700px, 115vw);
  aspect-ratio: 1;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  background: radial-gradient(circle,
    rgba(var(--lamp), var(--lamp-a)) 0%,
    rgba(var(--lamp), calc(var(--lamp-a) * .45)) 20%,
    rgba(var(--lamp), calc(var(--lamp-a) * .18)) 40%,
    rgba(var(--lamp), 0) 60%);
}

.pj-words {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
}

/* ---------- nav ---------- */
.pj-nav {
  position: fixed;
  left: 0;
  right: 0;
  top: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 26px 5vw 0;
  font-stretch: 112%;
  font-weight: 500;
  font-size: 14px;
  letter-spacing: .01em;
}
.pj-nav a { padding: 12px 6px; margin: -12px -6px; color: var(--paper-dim); transition: color 150ms ease; }
.pj-nav a:hover { color: var(--paper); }
.pj-nav .pj-brand {
  font-family: 'Judas Caps', 'Archivo', 'Helvetica Neue', Arial, sans-serif;
  font-weight: 400;
  font-stretch: 100%;
  font-size: 30px;
  line-height: 1;
  letter-spacing: 0;
  color: var(--paper);
  padding: 8px 14px;
  margin: -8px -14px;
  /* The same name the home's mark carries, so it holds still across the cross-document transition. */
  view-transition-name: mark;
}
.pj-nav .pj-brand:hover { color: var(--paper-dim); }
/* The repository: its glyph and its name, in Pause's slot. */
.pj-nav .pj-repo { display: inline-flex; align-items: center; gap: 8px; }
.pj-nav .pj-repo svg { display: block; }

/* ---------- masthead and role row ---------- */
.pj-masthead {
  position: absolute;
  left: 0;
  right: 0;
  top: var(--mast-top);
  display: flex;
  justify-content: center;
  align-items: center;
  gap: .1em;
  margin: 0;
  font-family: 'Judas Caps', 'Archivo', 'Helvetica Neue', Arial, sans-serif;
  font-weight: 400;
  font-size: var(--mast-size);
  line-height: .9;
  letter-spacing: .02em;
  color: var(--paper);
  pointer-events: none;
  user-select: none;
  z-index: 1;
}

.pj-role {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(var(--mast-bottom) + 1.6vh);
  display: flex;
  align-items: center;
  gap: 2.2vw;
  margin: 0;
  padding: 0 5vw;
  font-stretch: 118%;
  font-weight: 600;
  font-size: clamp(13px, 1.15vw, 18px);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--paper);
  z-index: 1;
  pointer-events: none;
}
.pj-role::before {
  content: '';
  order: 1;
  flex: 1;
  height: 1px;
  background: var(--hairline);
}
.pj-role span:last-child { order: 2; }

/* ---------- the shot: where the figure stands on the home page ---------- */
.pj-shot {
  position: absolute;
  left: 50%;
  /* Centred in the room between the role row and the closing line, so a tall
     screen does not leave it hanging under the masthead over an empty floor. */
  top: calc(var(--shot-top) + (100svh - var(--shot-top) - var(--end-h) - var(--shot-h)) / 2);
  height: var(--shot-h);
  width: calc(var(--shot-h) * var(--shot-ratio));
  margin: 0;
  transform: translateX(-50%);
  perspective: 1400px;
  z-index: 2;
}
/* The object: turns a few degrees toward the lamp (studio/lamp.ts). */
.pj-shot-card {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  will-change: transform, opacity;
}
.pj-shot-card picture { display: block; height: 100%; }
.pj-shot-card img {
  display: block;
  width: 100%;
  height: 100%;
}
/* The whole card fades in when its image has decoded, rather than popping
   mid-entrance: on the card, not the image, so anything a page layers over the
   image (the Window's shade and bezels) arrives with it and can carry
   opacities of its own without a transition dragging on them. */
.pj-shot-card { opacity: 0; transition: opacity 500ms ease; }
.pj-shot-card.is-loaded { opacity: 1; }
/* Its shadow on the wall: the shot drawn black into a quarter-size canvas
   with the blur baked in (studio/shadow.ts), sliding away from the lamp. The
   CSS filter is only the fallback for browsers without canvas filters. */
.pj-shot-shadow {
  position: absolute;
  /* Oversized by the canvas's own margin (studio/shadow.ts MARGIN), so the
     blur is never cut off in a straight line at the image's edge. */
  inset: -8%;
  width: 116%;
  height: 116%;
  opacity: 0;
  transform: translate3d(0, 14px, 0) scale(1.03);
  will-change: transform;
  pointer-events: none;
  transition: opacity 600ms ease;
}
.pj-shot-shadow.is-drawn { opacity: .7; }
.pj-shot-shadow.css-filter { filter: blur(16px); }
/* The light on its face: a soft spot the rig positions in the shot's own
   pixels, confined to the object by the image's own alpha (the mask is set
   from whichever source loaded). Off the box it draws nothing. */
.pj-shot-shine {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(240px circle at var(--sx, -999px) var(--sy, -999px), rgba(255, 244, 214, .2), transparent 70%);
  mix-blend-mode: screen;
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
}

/* ---------- the columns, either side of the shot's top ---------- */
.pj-fold {
  position: relative;
  z-index: 3;
  pointer-events: none;
}
.pj-fold > * { pointer-events: auto; }
.pj-copy,
.pj-spec {
  position: absolute;
  top: calc(var(--mast-bottom) + 8vh);
}
/* The column's width is the free side of the shot less the gutter. */
.pj-copy { left: 5vw; max-width: min(32ch, 27vw); }
.pj-copy p { margin: 0; }
.pj-copy .pj-claim {
  font-size: clamp(17px, 1.3vw, 21px);
  line-height: 1.4;
  text-wrap: pretty;
}
.pj-copy .pj-lines {
  margin-top: 12px;
  font-size: 14px;
  line-height: 1.5;
  color: var(--paper-dim);
  text-wrap: pretty;
}
.pj-cta { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 22px; margin-top: 22px; }
/* `.pj .pj-btn`, not `.pj-btn`: the page-wide `.pj a` reset outranks a lone
   class and would have the button's text inheriting the page's. */
.pj .pj-btn {
  display: inline-block;
  padding: 12px 20px 13px;
  border-radius: 999px;
  white-space: nowrap;
  /* The lamp's glint, positioned by studio/lamp.ts from where the light is. Off the box it draws nothing. */
  background:
    radial-gradient(170px circle at var(--sx, -999px) var(--sy, -999px), var(--glint), transparent 70%),
    var(--accent);
  color: var(--on-accent);
  font-size: 15px;
  font-weight: 600;
  font-stretch: 105%;
  transition: transform 120ms var(--ease-out);
}
.pj .pj-btn:active { transform: scale(.97); }
.pj .pj-link {
  padding: 12px 0;
  margin: -12px 0;
  color: var(--paper-dim);
  font-size: 15px;
  font-weight: 500;
  white-space: nowrap;
  text-decoration: underline;
  text-decoration-color: var(--paper-dim);
  text-underline-offset: 5px;
  text-decoration-thickness: 1.5px;
  transition: color 150ms ease;
}
.pj .pj-link:hover { color: var(--paper); }
.pj-copy .pj-note {
  margin-top: 22px;
  font-size: 13px;
  line-height: 1.6;
  font-stretch: 118%;
  font-weight: 500;
  color: var(--paper-dim);
}

.pj-spec {
  right: 5vw;
  max-width: min(24ch, 26vw);
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  text-align: right;
  font-size: 13px;
  line-height: 1.75;
  font-stretch: 118%;
  font-weight: 500;
  color: var(--paper-dim);
}
.pj-spec b { color: var(--paper); font-weight: 600; }
/* A live figure beside a fact: the home's live-figure tone. */
.pj-ms { color: var(--paper-dim); font-weight: 500; font-variant-numeric: tabular-nums; }
.pj-spec-in { animation: pj-fade 350ms ease-out both; }
.pj-status {
  display: inline-block;
  width: 8px;
  height: 8px;
  margin-right: 9px;
  vertical-align: 1px;
  background: var(--status-down);
}
.pj-status.is-up { background: var(--status-up); }
/* A state that changes while you watch pulses once, so a live change reads as one. */
.pj-status.is-pulse { animation: pj-pulse 700ms ease-out; }
@keyframes pj-pulse {
  from { box-shadow: 0 0 0 0 rgba(var(--pulse, 224, 224, 224), .55); }
  to   { box-shadow: 0 0 0 10px rgba(var(--pulse, 224, 224, 224), 0); }
}
.pj-stack {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 2px 18px;
  margin-top: 10px;
  font-size: 12px;
  opacity: .8;
}

/* ---------- the closing line ---------- */
.pj-end {
  position: absolute;
  left: 5vw;
  right: 5vw;
  bottom: 3vh;
  z-index: 3;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 18px;
  margin: 0;
  font-size: 12px;
  font-stretch: 118%;
  font-weight: 500;
  line-height: 1.5;
  color: var(--paper-dim);
}
.pj .pj-end a { color: var(--paper); transition: color 150ms ease; padding: 14px 4px; margin: -14px -4px; }
.pj .pj-end a:hover { color: var(--paper-dim); }
.pj .pj-end-mark {
  font-family: 'Judas Caps', 'Archivo', 'Helvetica Neue', Arial, sans-serif;
  font-size: 22px;
  font-stretch: 100%;
  line-height: 1;
  padding: 11px 13px;
  margin: -11px -13px;
}
.pj-end-credit { text-align: right; }

/* ---------- entrance: one sequence on load ---------- */
.pj .rise { animation: pj-rise 800ms var(--ease-out) both; animation-delay: var(--d, 0ms); }
@keyframes pj-rise {
  from { opacity: 0; transform: translate3d(0, 18px, 0); }
  to   { opacity: 1; transform: translate3d(0, 0, 0); }
}
/* The masthead rises without fading, so it is painted from the first frame. */
.pj .rise-still { animation-name: pj-rise-still; }
@keyframes pj-rise-still {
  from { transform: translate3d(0, 18px, 0); }
  to   { transform: translate3d(0, 0, 0); }
}
/* The shot keeps its centring transform through its rise. */
.pj .pj-shot.rise { animation-name: pj-rise-shot; }
@keyframes pj-rise-shot {
  from { opacity: 0; transform: translate3d(-50%, 18px, 0); }
  to   { opacity: 1; transform: translate3d(-50%, 0, 0); }
}
@keyframes pj-lamp-on { from { opacity: 0; } to { opacity: 1; } }
@keyframes pj-fade { from { opacity: 0; } to { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  .pj .rise { animation-name: pj-fade; animation-duration: 400ms; }
  .pj .rise-still { animation: none; }
  .pj .pj-shot.rise { animation-name: pj-fade; }
  .pj .pj-btn,
  .pj-nav a,
  .pj .pj-link,
  .pj-shot-shadow,
  .pj .pj-end a { transition: none; }
}

@media (max-width: 1280px) {
  .pj { --shot-cap: 40vw; }
}

/* ---------- narrow: stack it ---------- */
@media (max-width: 960px) {
  .pj { background: radial-gradient(ellipse 120% 60% at 50% 30%, var(--cyc) 30%, var(--cyc-dark) 100%) fixed; }
  .pj-nav { position: relative; padding: 20px 6vw 0; }
  .pj-nav a { padding: 12px 8px; margin: -12px -8px; }
  .pj-stage { height: auto; display: flex; flex-direction: column; padding-bottom: 6vh; }
  .pj-words,
  .pj-fold { display: contents; }
  .pj-masthead { order: 1; position: relative; top: auto; margin: 5vh 0 0; font-size: min(24vw, 26vh); }
  .pj-role { order: 2; position: static; padding: 0 6vw; margin-top: 2vw; gap: 4vw; font-size: 12px; letter-spacing: .14em; }
  .pj-copy,
  .pj-spec {
    position: static;
    padding: 0 6vw;
    max-width: none;
  }
  .pj-copy { order: 3; margin-top: 5vh; }
  .pj-copy > * { max-width: 34ch; }
  .pj-spec { order: 4; align-items: flex-start; text-align: left; margin-top: 26px; }
  .pj-stack { justify-content: flex-start; }
  .pj-shot {
    order: 5;
    position: relative;
    left: auto;
    top: auto;
    width: 100%;
    height: auto;
    margin: 5vh 0 0;
    transform: none;
  }
  /* In the column the card gives the figure its height; the shadow keeps its place under it. */
  .pj-shot-card { position: relative; inset: auto; }
  .pj-shot-card picture { height: auto; }
  .pj-shot-card img { height: auto; }
  .pj .pj-shot.rise { animation-name: pj-rise; }
  .pj-end { order: 6; position: static; flex-wrap: wrap; margin: 6vh 6vw 0; }
  .pj-end-credit { text-align: left; }
}
