/* =====================================================================
   VAL STUDIO — Works, in the Resn visual language
   ---------------------------------------------------------------------
   Loaded by works.html, project.html and works/*.html ONLY, on top of core/site.css.
   Everything here is scoped under .resn so the Labs/Info pages keep the
   original monochrome-mono language untouched.

   Tokens below are the ones captured from resn.co.nz (see the
   resn-design skill package): a near-black value-driven palette with a
   single warm accent, wide-tracked uppercase micro-labels against very
   light oversized display type, and one easing curve — easeOutQuart —
   carrying every interactive transition.

   Note on fidelity: resn's own Work grid never finished rendering
   during capture (it stalls loading a heavy WebGL payload), so the grid
   LAYOUT here is not a copy of theirs — it is built from the design
   language the capture did establish. The palette, type treatment,
   easing and transition pattern are the measured parts.
===================================================================== */

.resn{
  /* ---- backgrounds: near-black spectrum, no pure white anywhere ---- */
  --r-bg:      #0a0a0b;
  --r-bg-1:    #141214;
  --r-bg-2:    #171719;
  --r-bg-3:    #1c1a1c;
  --r-bg-4:    #1e1c20;

  /* ---- text ---- */
  --r-white:   #ffffff;
  --r-text:    #e3e3e3;
  --r-text-2:  #e0e0e0;

  /* ---- grays ---- */
  --r-gray:    #898989;
  --r-gray-2:  #a8a8a8;
  --r-gray-3:  #717171;
  --r-gray-4:  #666666;
  --r-line:    #333333;

  /* ---- the single saturated color in the whole system ---- */
  --r-accent:  #ffda93;

  /* ---- alpha overlays ---- */
  --r-glass-12: rgba(255,255,255,.12);
  --r-glass-20: rgba(255,255,255,.2);
  --r-glass-30: rgba(255,255,255,.3);
  --r-scrim:    rgba(0,0,0,.2);

  /* ---- type ----
     Fort (resn's display face) is commercial and not redistributable;
     Work Sans is what resn actually uses for UI chrome and is open —
     so it carries both roles here, at very light weights for display. */
  --r-font: 'Syne', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
  --r-fs-display: clamp(44px, 9vw, 132px);
  --r-fs-title:   clamp(22px, 2.6vw, 38px);
  --r-fs-lede:    clamp(15px, 1.5vw, 19px);
  --r-fs-body:    16px;
  --r-fs-label:   11px;
  --r-track-label: .1rem;   /* wide tracking on small caps — core to the look */
  --r-track-tight: -.02em;  /* negative tracking on large display type */

  /* ---- motion: one curve everywhere ---- */
  --r-ease: cubic-bezier(0.165, 0.84, 0.44, 1);
  --r-fast: 200ms;
  --r-mid:  300ms;
  --r-slow: 800ms;
}

/* ---------- page shell ------------------------------------------------ */
body.resn{
  background:var(--r-bg);
  color:var(--r-text);
  font-family:var(--r-font);
  font-size:var(--r-fs-body);
  letter-spacing:normal;
}
.resn .page{max-width:1440px;
  padding:max(clamp(28px,6vw,72px), var(--chrome-clear)) clamp(20px,5vw,64px) clamp(72px,12vw,160px)}

/* micro-label: uppercase, thin, widely tracked — used for every piece of
   supporting metadata on these pages */
.resn .r-label{
  font-size:var(--r-fs-label);font-weight:400;
  letter-spacing:var(--r-track-label);text-transform:uppercase;
  color:var(--r-gray);
}

/* ---------- shared header, retuned to this palette --------------------
   core/site.js injects the same header on every interior page; these
   overrides only bite on the Resn pages. */
body.resn .site-header{
  background:rgba(10,10,11,.82);
  border-bottom-color:var(--r-line);
  font-family:var(--r-font);
}
body.resn .site-logo{color:var(--r-gray-2)}
body.resn .site-logo:hover,body.resn .site-logo:focus-visible{color:var(--r-white)}
body.resn .site-logo .wordmark,
body.resn .site-nav a{
  font-size:var(--r-fs-label);letter-spacing:var(--r-track-label);font-weight:400;
}
body.resn .site-nav a{color:var(--r-gray-4);transition:color var(--r-fast) var(--r-ease)}
body.resn .site-nav a:hover,body.resn .site-nav a:focus-visible{color:var(--r-white)}
body.resn .site-nav a[aria-current="page"]{color:var(--r-white);border-bottom-color:var(--r-accent)}
body.resn :focus-visible{outline:1px solid var(--r-accent);outline-offset:4px}

/* ---------- the work index — REMOVED ----------------------------------
   /works is the reel (core/reel.js + core/reel.css) and nothing else,
   so the staggered two-column index that used to sit behind a "View all
   projects" switch, and the masthead above it, are gone. Nothing renders
   .r-index, .r-item, .r-shot, .r-num, .r-caption, .r-name or
   .r-masthead any more; their rules went with them.

   What is still used from this file is the .resn token block above, the
   .r-label micro-label, and everything below — which is the project
   DETAIL page, /works/<slug>.
======================================================================= */

/* ---------- project detail --------------------------------------------
   The way back is not in the page: on a single work it is in the mark's
   corner (#back, core/site.css). */
.resn .r-hero{
  position:relative;overflow:hidden;
  aspect-ratio:16/9;background:var(--r-bg-2);
  margin-bottom:clamp(36px,6vw,80px);
}
.resn .r-hero img,.resn .r-hero video{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  opacity:0;transition:opacity var(--r-slow) ease-out;
}
.resn .r-hero img.is-loaded,.resn .r-hero video.is-loaded{opacity:1}

/* Set the way the reel sets a project's name and the way the Studio page
   sets its heading — Outfit extralight, in capitals, tracking opened.
   Arriving here from the reel should not be a change of voice. */
.resn .r-title{
  font-family:var(--font-title);
  font-size:clamp(30px,5vw,68px);font-weight:var(--wt-title);line-height:1.04;
  letter-spacing:.055em;text-transform:uppercase;color:var(--r-white);
}
.resn .r-meta{
  display:flex;flex-wrap:wrap;gap:clamp(14px,2.4vw,32px);
  margin-top:clamp(18px,2.4vw,28px);
  padding-bottom:clamp(20px,3vw,32px);
  border-bottom:1px solid var(--r-line);
}
.resn .r-summary{
  margin-top:clamp(28px,4vw,48px);max-width:56ch;
  font-size:var(--r-fs-lede);font-weight:300;line-height:1.6;color:var(--r-text-2);
}
.resn .r-body{margin-top:clamp(20px,2.6vw,32px);max-width:68ch}
.resn .r-body p{
  margin-top:1.15em;font-size:var(--r-fs-body);font-weight:300;
  line-height:1.78;color:var(--r-gray-2);
}
.resn .r-body p:first-child{margin-top:0}

/* full-bleed-ish stack: detail media reads as a sequence, one per row,
   which suits documentation shots better than a dense thumbnail grid */
.resn .r-plates{margin-top:clamp(48px,8vw,110px);display:flex;flex-direction:column;gap:clamp(24px,4vw,64px)}
.resn .r-plate{position:relative;overflow:hidden;background:var(--r-bg-2)}
.resn .r-plate img,.resn .r-plate video{
  width:100%;height:auto;display:block;
  opacity:0;transition:opacity var(--r-slow) ease-out;
}
.resn .r-plate img.is-loaded,.resn .r-plate video.is-loaded{opacity:1}

.resn .r-specs{
  margin-top:clamp(48px,8vw,100px);padding-top:clamp(24px,3vw,36px);
  border-top:1px solid var(--r-line);
  display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));
  gap:clamp(20px,3vw,36px);
}
.resn .r-specs dd{margin-top:8px;font-size:15px;font-weight:300;color:var(--r-text)}

/* the way out — Patreon and the browser version, at the foot (core/render.js) */
.resn .r-out{
  display:flex;flex-wrap:wrap;gap:12px clamp(24px,3.4vw,44px);
  margin-top:clamp(40px,6vw,72px);
}
.resn .r-external{
  display:inline-flex;align-items:center;gap:.9em;
  padding-bottom:6px;
  border-bottom:1px solid var(--r-gray-4);
  color:var(--r-white);
  transition:border-color var(--r-fast) ease-in-out,color var(--r-fast) var(--r-ease);
}
.resn .r-external:hover,.resn .r-external:focus-visible{color:var(--r-accent);border-color:var(--r-accent)}
.resn .r-external .r-arrow{
  width:20px;height:1px;background:currentColor;
  transition:width var(--r-fast) var(--r-ease);
}
.resn .r-external:hover .r-arrow{width:30px}

/* ---------- pager between projects ------------------------------------ */
.resn .r-pager{
  margin-top:clamp(56px,9vw,120px);padding-top:clamp(24px,3vw,36px);
  border-top:1px solid var(--r-line);
  display:flex;justify-content:space-between;gap:var(--r-fs-body);
}
.resn .r-pager a{color:var(--r-gray);transition:color var(--r-fast) var(--r-ease)}
.resn .r-pager a:hover,.resn .r-pager a:focus-visible{color:var(--r-white)}

/* The split-curtain that used to live here was retired: the site now has
   one arrival (the VAL loader, core/loader.js) and one departure (the
   veil in core/site.js) on every page, rather than a second transition
   with a different mark on this route only. */

@media (prefers-reduced-motion:reduce){
  .resn *{transition-duration:.01ms!important;animation-duration:.01ms!important}
}

/* ---------- a collection: Fragments (renderCollection, core/render.js) ----
   A long page that introduces other work, not a contact sheet. The page's
   own title and one paragraph, then one project after another: its title,
   what I did on it, a short description, and its pictures at their own
   size. A hairline between projects is the only divider — the same line
   this site draws everywhere it means "a boundary".

   NOTHING IS CROPPED HERE. The old grid cut every frame to 4:3, which is
   right for a set and wrong for these: they are separate pieces of work,
   each needing a sentence, and a photograph cut to a common shape cannot
   carry one. A picture keeps its own aspect ratio; the layout reserves
   its box from the file's own width and height so nothing jumps as it
   loads. */
.resn .r-coll-head .r-summary{margin-top:clamp(18px,2.4vw,28px)}
/* THE SHOWREEL, above the list. It is the page's opening rather than its
   first entry, so it takes the hero's shape and the hero's silence — one
   16:9 plate, fading in as it loads, and no label on it. A reel that had
   to be introduced would not be a reel. */
.resn .r-coll-reel{
  position:relative;overflow:hidden;
  aspect-ratio:16/9;background:var(--r-bg-2);
  margin-top:clamp(36px,5vw,64px);
}
.resn .r-coll-reel img,.resn .r-coll-reel video{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  opacity:0;transition:opacity var(--r-slow) ease-out;
}
.resn .r-coll-reel img.is-loaded,.resn .r-coll-reel video.is-loaded{opacity:1}

.resn .r-coll{
  margin-top:clamp(48px,7vw,96px);
  display:flex;flex-direction:column;
}

/* WHAT IT WAS BUILT WITH, INSIDE AN ENTRY. The same <dl> a case study
   ends on, so the two answer the same questions in the same shape — but
   the page-foot version opens with a rule and a hundred pixels of air,
   and a block that closes a page cannot also sit in the middle of one.
   The rule goes: the hairline between projects is already the boundary
   here, and a second one inside an entry would contradict it. */
.resn .r-proj-specs{
  margin-top:clamp(18px,2.4vw,28px);padding-top:0;border-top:0;
  grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
  gap:clamp(14px,2vw,24px);
}
.resn .r-proj-specs dd{font-size:14px}

/* The cover as the way into a project. It is an <a> rather than a button,
   so it takes the waterline the picture frames already carry and nothing
   else — the underline a link would otherwise get is wrong on a
   photograph. Its shape is the picture's own, because this page does not
   crop: a cover made for the reel's fixed plate is still that cover, and
   cutting it again here would be the second crop the page refuses.

   IT IS HELD BACK FROM THE FULL MEASURE, and that is the one thing that
   makes this page an index rather than a slideshow. A cover here is a
   DOOR — the invitation to go and read the project — while the pictures
   below a project are the work itself and take the whole width they ask
   for. Nine full-bleed plates in a row would say the opposite, and the
   page would be scrolled past rather than read. On a phone there is only
   one measure, so the cap lifts. */
.resn .r-proj-media .r-proj-cover{max-width:min(520px,52%)}
.resn .r-proj-cover{text-decoration:none}
@media (max-width:760px){
  .resn .r-proj-media .r-proj-cover{max-width:none}
}
/* The boundary between two projects. Not on the first — a rule above the
   first project would read as a divider from the intro, which is not a
   boundary of the same kind. */
.resn .r-proj{
  padding-block:clamp(36px,5vw,64px);
  border-top:1px solid var(--r-line);
}
.resn .r-proj:first-child{padding-top:0;border-top:0}
.resn .r-proj:last-child{padding-bottom:0}

.resn .r-proj-title{
  margin:0;
  font-size:var(--r-fs-title);font-weight:500;
  letter-spacing:var(--r-track-tight);line-height:1.1;
  color:var(--r-white);text-wrap:balance;
}
/* place and date, in the page's micro-label */
.resn .r-proj-meta{margin:14px 0 0}
/* what I did on it — the one line that is not prose */
.resn .r-proj-role{
  margin:10px 0 0;
  font-size:var(--r-fs-body);font-weight:400;
  letter-spacing:.02em;color:var(--r-gray-2);
}
.resn .r-proj-body{
  margin-top:clamp(16px,2vw,24px);
  max-width:62ch;
  display:flex;flex-direction:column;gap:1em;
}
.resn .r-proj-body p{
  margin:0;
  font-size:var(--r-fs-lede);font-weight:300;line-height:1.6;
  color:var(--r-gray-2);
}

/* THE PICTURES. Two columns on a desktop, one on a phone; a project with
   a single item gives it the full measure instead of leaving half the
   row empty. `align-items:start` so two pictures of different heights sit
   on the same top line rather than being stretched to match. */
.resn .r-proj-media{
  margin-top:clamp(24px,3vw,40px);
  display:grid;align-items:start;
  grid-template-columns:repeat(2,minmax(0,1fr));
  gap:clamp(16px,2.2vw,28px);
}
.resn .r-proj-media.is-single{grid-template-columns:minmax(0,1fr)}
@media (max-width:760px){
  .resn .r-proj-media{grid-template-columns:minmax(0,1fr)}
}

.resn .r-proj-hit{
  display:block;width:100%;
  margin:0;padding:0;border:0;background:none;
  color:inherit;font:inherit;text-align:left;cursor:pointer;
}
.resn .r-proj-frame{
  position:relative;display:block;overflow:hidden;
  background:var(--r-bg-2);
}
/* the waterline: a hairline of the accent wipes in along the top edge —
   the same gesture the rest of the site's panels make */
.resn .r-proj-frame::before{
  content:"";position:absolute;left:0;right:0;top:0;height:1px;z-index:2;
  background:var(--r-accent);
  transform:scaleX(0);transform-origin:left center;
  transition:transform var(--r-mid) var(--r-ease);
}
.resn .r-proj-hit:hover .r-proj-frame::before,
.resn .r-proj-hit:focus-visible .r-proj-frame::before{transform:scaleX(1)}
.resn .r-proj-hit:focus-visible{outline:1px solid var(--r-accent);outline-offset:4px}

/* AT ITS OWN SHAPE. width:100% and height:auto, no aspect-ratio and no
   object-fit — the box is whatever the file is. */
.resn .r-proj-frame img,
.resn .r-proj-frame video{
  display:block;width:100%;height:auto;
  opacity:0;transition:opacity var(--r-slow) ease-out,scale var(--r-slow) var(--r-ease);
}
.resn .r-proj-frame img.is-loaded{opacity:.9}
/* a clip shows its poster and is never loaded on this page, so it has no
   load event to wait for — it is up from the start */
.resn .r-proj-frame video{opacity:.9}
.resn .r-proj-hit:hover .r-proj-frame img.is-loaded,
.resn .r-proj-hit:hover .r-proj-frame video{opacity:1;scale:1.01}
/* the picture is away in the closer look; its frame keeps its place */
.resn .r-proj-frame.is-zoomed img,
.resn .r-proj-frame.is-zoomed video{visibility:hidden}

.resn .r-proj-clip{
  position:absolute;left:12px;bottom:10px;z-index:1;color:var(--r-gray-2);
  transition:color var(--r-fast) var(--r-ease);
}
.resn .r-proj-hit:hover .r-proj-clip,
.resn .r-proj-hit:focus-visible .r-proj-clip{color:var(--r-accent)}

.resn .r-proj-link{
  display:inline-block;align-self:flex-start;
  margin-top:clamp(18px,2.4vw,28px);padding-block:8px;
  color:var(--r-gray);
  transition:color var(--r-fast) var(--r-ease);
}
.resn .r-proj-link:hover,.resn .r-proj-link:focus-visible{color:var(--r-accent)}

@media (prefers-reduced-motion:reduce){
  .resn .r-proj-frame img,.resn .r-proj-frame video,
  .resn .r-proj-frame::before{transition:none}
  .resn .r-proj-hit:hover .r-proj-frame img.is-loaded,
  .resn .r-proj-hit:hover .r-proj-frame video{scale:1}
}
