@import url("https://fonts.googleapis.com/css2?family=Anton&family=Archivo:wght@500&family=Archivo+Black&family=Space+Mono:wght@400;700&display=swap");

:root {
  --ink: #5f7899;
  --ink-deep: #34455f;
  --tint: #e3e9f2;
  --paper: #fbfcfe;
  --dot-light: radial-gradient(circle, rgba(255,255,255,.9) 0.7px, transparent 1.1px);
  --dot-dark: radial-gradient(circle, rgba(52,69,95,.55) 0.7px, transparent 1.2px);
}

* { box-sizing: border-box; margin: 0; padding: 0; }

body {
  background: #e4e9f1;
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 12px;
  overflow-x: hidden;
}
a { color: inherit; text-decoration: none; }

/* ---------- poster: fixed aspect, everything sized in cqw ---------- */
.poster {
  container-type: inline-size;
  position: relative;
  width: min(calc(100vw - 24px), calc((100vh - 24px) * 1.274), 1400px);
  aspect-ratio: 100 / 78.5;
  background: var(--paper);
  box-shadow: 0 0 0 1px #d3dae6, 0 24px 60px rgba(52,69,95,.18);
  overflow: hidden;
  color: var(--ink-deep);
}
/* faint paper grain */
.poster::before {
  content: ""; position: absolute; inset: 0; z-index: 9; pointer-events: none;
  background: var(--dot-dark) 0 0 / 6px 6px; opacity: .06;
}
.abs { position: absolute; }

/* crop marks */
.crop { position: absolute; width: 4cqw; height: 4cqw; border: .38cqw solid var(--ink); z-index: 8; }
.crop.tl { top: 1.2cqw; left: 1.2cqw; border-right: 0; border-bottom: 0; }
.crop.br { bottom: 1.2cqw; right: 1.2cqw; border-left: 0; border-top: 0; }

/* ---------- name ---------- */
.name {
  position: absolute; z-index: 4;
  left: 3cqw; top: 3.2cqw; width: 94cqw; height: auto;
  overflow: visible;
}

/* title halftone: only the white dots are softened; the letter blue is untouched.
   Original dot opacity was .55. Lower = fainter dots, 0 = no dots. */
.name #ht circle { opacity: .25; }

/* ---------- image panels ---------- */
.panel { position: absolute; display: block; transition: transform .35s cubic-bezier(.2,.8,.2,1); }
.shot {
  position: absolute; inset: 0; overflow: hidden;
  background: var(--ink);
  border: .4cqw solid var(--ink);
  box-shadow: 0 0 0 .75cqw var(--paper), 0 0 0 1cqw var(--ink);
  clip-path: inset(-1.2cqw);   /* clips the tilted, fading images as one group (no hairline while un-hovering); outset keeps the frame rings */
}
.shot img {
  position: absolute; inset: -1px; width: calc(100% + 2px); height: calc(100% + 2px); object-fit: cover;   /* 1px overfill: no ink gap at the edge while fading */
  filter: grayscale(1) contrast(1.35) brightness(.95);
  mix-blend-mode: screen;               /* ink-coloured duotone */
  transition: transform .6s cubic-bezier(.2,.8,.2,1);
}
.shot::after {                          /* halftone dots */
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: var(--dot-light) 0 0 / 4px 4px; opacity: .55;
  mix-blend-mode: screen;
}

/* default: tilted rectangle */
.strip   { left: 67cqw; top: 2.6cqw; width: 29cqw; height: 7.4cqw; z-index: 3; transform: rotate(-1.6deg); }
.strip img { object-position: 50% 36%; }
.strip .edge { display: none; }

/* variant: right triangle (flat top, vertical left edge, hypotenuse parallel to the title's slash) */
.strip.tri   { left: 68.8cqw; top: 4.5cqw; width: 28.2cqw; height: 6.9cqw; transform: none; }
.strip.tri .shot { border: 0; box-shadow: none; clip-path: polygon(0 0, 100% 0, 0 100%); }
.strip.tri .edge { display: block; position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
.strip .edge polygon { fill: none; vector-effect: non-scaling-stroke; stroke-linejoin: round; }
.strip .e-paper { stroke: var(--paper); stroke-width: 12px; }
.strip .e-ink   { stroke: var(--ink);   stroke-width: 4px; }

.work    { left: 3.6cqw; top: 47.5cqw; width: 57cqw; height: 25cqw; z-index: 5; transform: rotate(-1.4deg); }
.work img { object-position: 50% 40%; }

.about   { left: 64cqw; top: 26cqw; width: 32cqw; height: 46.5cqw; z-index: 2; transform: rotate(1.8deg); }
.about img { object-position: 38% 50%; }

/* hover: fade in the full-colour image and drop the halftone */
.link .shot img.color { mix-blend-mode: normal; filter: none; opacity: 0; transition: opacity .45s ease, transform .6s cubic-bezier(.2,.8,.2,1); }
.link .shot::after { transition: opacity .45s ease; }
.link:hover img.color, .link:focus-visible img.color { opacity: 1; }
.link:hover .shot::after, .link:focus-visible .shot::after { opacity: 0; }

.panel.link:hover { transform: rotate(0deg) translateY(-.6cqw) scale(1.012); z-index: 6; }
.panel.link:hover img { transform: scale(1.06); }

/* labels hanging off the panels */
.tag {
  position: absolute; z-index: 3;
  display: flex; align-items: baseline; gap: 1.2cqw;
  background: var(--ink-deep); color: var(--paper);
  padding: .9cqw 2cqw .7cqw 1.6cqw;
  font-family: "Anton", sans-serif; text-transform: uppercase; letter-spacing: .05em;
  font-size: 5.6cqw; line-height: 1;
  transition: background .25s, color .25s, transform .35s cubic-bezier(.2,.8,.2,1);
}
.tag small { font-family: "Space Mono", monospace; font-size: 1.15cqw; letter-spacing: .18em; opacity: .85; }
.tag .arrow { font-family: "Space Mono", monospace; font-size: 3.2cqw; transition: transform .25s; }
.link:hover .tag { background: var(--paper); color: var(--ink-deep); transform: translateX(.8cqw); }
.link:hover .tag .arrow { transform: translateX(.6cqw); }

.work  .tag { left: -1.8cqw; bottom: 2.6cqw; transform: rotate(-2deg); clip-path: polygon(0 0, 100% 0, 96% 100%, 0 100%); }
.about .tag { right: -2cqw; bottom: 3cqw; transform: rotate(2deg); clip-path: polygon(4% 0, 100% 0, 100% 100%, 0 100%); }

/* ---------- role line (under the name) ---------- */
.rule {
  position: absolute; z-index: 3; left: 3cqw; top: 42.2cqw; width: 55cqw;
  display: flex; align-items: center; gap: 2cqw;
}
.rule i { height: .4cqw; background: var(--ink); flex: 1; }
.rule span {
  font-family: "Anton", sans-serif; text-transform: uppercase; white-space: nowrap;
  font-size: 2.4cqw; letter-spacing: .22em; color: var(--ink);
}

/* ---------- small marks ---------- */
.mono {
  position: absolute; z-index: 6;
  font-family: "Space Mono", monospace; font-size: 1.15cqw; letter-spacing: .2em;
  text-transform: uppercase; color: var(--ink);
}
.mono.n1 { display: none; }
.mono.n2 { left: 5cqw; bottom: 1.5cqw; display: flex; align-items: center; gap: .6em; }
.cc {                       /* drawn © so it matches the text size and baseline */
  display: grid; place-items: center; flex: none;
  width: 1.35em; height: 1.35em; border: .09em solid currentColor; border-radius: 50%;
  font-style: normal; font-size: .58em; font-weight: 400; letter-spacing: 0; line-height: 1;
  padding-bottom: .04em;
}
.mono.n3 { right: 7cqw; bottom: 1.5cqw; }
/* footer email (replaces the name mark) */
.mono.email { transition: transform .25s, color .25s; }
.mono.email .at { font-family: "Archivo", sans-serif; font-weight: 500; letter-spacing: 0; margin: 0 .35em; }
.mono.email:hover { transform: translateX(-.6cqw); color: var(--ink-deep); }

.hatch { position: absolute; z-index: 3; width: 7cqw; height: .9cqw; left: 31cqw; bottom: 1.4cqw;
  background: repeating-linear-gradient(115deg, var(--ink) 0 .45cqw, transparent .45cqw 1cqw); }

.orbit { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 7; pointer-events: none; }
.orbit .o-ink   { fill: var(--ink-deep); opacity: .72; }
.orbit .o-edge  { fill: var(--paper); stroke: none; }
.orbit.m { display: none; }
.orbit .o-reveal { fill: none; stroke: #fff; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.orbit .spark   { fill: var(--paper); stroke: var(--ink-deep); stroke-width: .25; }

/* entrance */
@media (prefers-reduced-motion: no-preference) {
  .panel, .rule, .name { animation: rise .9s cubic-bezier(.2,.8,.2,1) both; }
  .strip { animation-delay: .1s; } .work { animation-delay: .25s; } .about { animation-delay: .4s; } .rule { animation-delay: .2s; }
  /* the loop is drawn in like a pen stroke; the sparkle pops in as it starts */
  .orbit .o-reveal { stroke-dasharray: 1; stroke-dashoffset: 1; animation: draw .36s steps(7, end) .3s forwards; }
  .orbit .o-ink, .orbit .o-edge { transform-box: fill-box; transform-origin: center; animation: shake .36s steps(2, end) .3s; }
  .orbit .spark { transform-box: fill-box; transform-origin: center; animation: pop .42s step-end .62s both; }
  @keyframes shake { 0% { transform: translate(.25px,-.2px) rotate(.4deg); } 50% { transform: translate(-.3px,.25px) rotate(-.5deg); } 100% { transform: none; } }
  @keyframes draw { to { stroke-dashoffset: 0; } }
  /* back-ease overshoot, held on each keyframe so it keeps the low-frame look */
  @keyframes pop { 0% { opacity: 0; transform: scale(.5) rotate(-70deg); } 30% { opacity: 1; transform: scale(1.9) rotate(25deg); } 55% { transform: scale(.7) rotate(-10deg); } 80% { transform: scale(1.2) rotate(4deg); } 100% { transform: none; } }
  @keyframes rise { from { opacity: 0; translate: 0 2cqw; } to { opacity: 1; translate: 0 0; } }
}

/* ---------- portrait / phone ---------- */
@media (max-width: 720px) {
  body { padding: 0; min-height: 100svh; background: var(--paper); place-items: start center; }
  /* The poster is always full width and exactly the visible height (no scroll, nothing under the browser bar).
     Above the buttons everything is sized by width (cqw). The buttons zone uses --v, which equals 1cqw on tall
     phones and shrinks on shorter ones so the whole layout still fits. Spare height on tall phones is split by --shift. */
  .poster { width: 100vw; aspect-ratio: auto; height: 100svh; box-shadow: none;
    --v: min(1cqw, calc((100svh - 57cqw) / 147));
    --shift: max(0px, calc((100svh - 57cqw - 147 * var(--v)) / 2)); }
  .name { left: 4cqw; width: 92cqw; top: calc(6cqw + var(--shift)); }
  .strip { left: 60cqw; top: calc(3cqw + var(--shift)); width: 36cqw; height: 7cqw; }
  .strip.tri { left: 68.4cqw; top: calc(7.3cqw + var(--shift)); width: 27.6cqw; height: 6.7cqw; }
  .rule { top: calc(45cqw + var(--shift)); left: 4cqw; width: 92cqw; }
  .rule span { font-size: 4.4cqw; }
  .mono.n1 { left: 5cqw; top: calc(51cqw + var(--shift)); font-size: 2.6cqw; }
  .work  { left: 6cqw; top: calc(57cqw + 3 * var(--v) + var(--shift)); width: 80cqw; height: calc(48 * var(--v)); }
  .about { left: 28cqw; top: calc(57cqw + 59 * var(--v) + var(--shift)); width: 66cqw; height: calc(76 * var(--v)); }
  .tag { font-size: 9cqw; }
  .tag small { font-size: 2.3cqw; }
  .tag .arrow { font-size: 6cqw; }
  .mono { font-size: 2.4cqw; }
  .mono.n3 { right: 8cqw; bottom: 3cqw; } .mono.n2 { bottom: 3cqw; left: 6cqw; }
  .hatch { display: none; }
  .orbit.d { display: none; }
  .orbit.m { display: block; inset: calc(57cqw - 57 * var(--v) + var(--shift)) auto auto 0; height: calc(204 * var(--v)); }   /* "meet" scaling keeps the sparkle undistorted */
  .crop { width: 8cqw; height: 8cqw; border-width: 1cqw; }
  .strip .e-paper { stroke-width: 7px; } .strip .e-ink { stroke-width: 2.5px; }   /* fixed-px strokes read too heavy on the smaller phone triangle */
}
