/* ==========================================================================
   FIGURES — art-directed placeholder "photography"
   Black-and-white editorial campaign prints, built entirely from CSS
   gradients + inline-SVG grain. No external images, no libraries, no colour.

   These stand in for a founder photoshoot that does not exist yet. They are
   deliberately NOT gray boxes and NOT stock people: each one is a lit,
   volumetric massing study — the kind of frame a photographer contact-sheets
   before the real day. Read as intentional print artifacts.

   LAYER STACK (per print, bottom to top)
     0  element background ....... seamless ground, subtle vertical falloff
     1  ::before ................. silhouette massing (>= 3 layered gradients)
     2  ::after .................. film grain + 45deg halftone screen
     3  .figure-caption / .figure-frame-tag ......... slate + corner brackets

   API
     .figure-print                 base print block
     .figure-print--portrait       head & shoulders, rim-lit
     .figure-print--standing       full length, low key, floor shadow
     .figure-print--profile        side profile, pushed right
     .figure-print--detail         abstract crop, light + grain only
     .figure-print--light          paper-white inversion for white sections
     .figure-print--tall           3 / 4
     .figure-print--wide           16 / 10
     .figure-print--square         1 / 1
     .figure-caption               typographic slate, bottom-left
     .figure-frame-tag             thin corner brackets, TL + BR
   ========================================================================== */


/* --------------------------------------------------------------------------
   1. BASE PRINT
   Ground is a near-black seamless: a shallow vertical gradient centred on
   #111 rather than a flat fill, so the frame has a top-to-bottom falloff like
   paper under a single overhead source. The grain layer above it also does
   real work — it dithers the gradients, which is what keeps 800px-wide
   full-bleed renders free of visible banding.
   -------------------------------------------------------------------------- */

.figure-print {
  /* ---- tonal tokens: the light variant only rewrites these ---- */
  --fig-ground-top: #161616;
  --fig-ground-bottom: #0c0c0c;
  --fig-lit: 255, 255, 255;   /* everything the light touches   */
  --fig-mass: 4, 4, 4;        /* everything the light misses    */
  --fig-vig: 0, 0, 0;         /* corner falloff                 */
  --fig-vig-alpha: 0.55;
  --fig-halftone: rgba(255, 255, 255, 0.5);
  --fig-grain-alpha: 0.09;
  --fig-grain-hover-alpha: 0.13;
  --fig-grain-blend: normal;
  --fig-grain-size: 200px;
  --fig-grain-offset: 0 0;
  --fig-rule: rgba(255, 255, 255, 0.55);
  --fig-caption: rgba(255, 255, 255, 0.74);
  --fig-caption-shadow: rgba(0, 0, 0, 0.55);

  /* default grain plate — seed 2 (overridden per variant) */
  --fig-grain: url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20width%3D'200'%20height%3D'200'%3E%3Cfilter%20id%3D'n'%3E%3CfeTurbulence%20type%3D'fractalNoise'%20baseFrequency%3D'0.9'%20numOctaves%3D'3'%20seed%3D'2'%20stitchTiles%3D'stitch'%2F%3E%3CfeColorMatrix%20type%3D'saturate'%20values%3D'0'%2F%3E%3C%2Ffilter%3E%3Crect%20width%3D'200'%20height%3D'200'%20filter%3D'url(%23n)'%2F%3E%3C%2Fsvg%3E");

  position: relative;
  overflow: hidden;
  isolation: isolate;           /* keeps the grain blend inside the print */
  display: block;
  margin: 0;                    /* <figure> default margin, killed */
  width: 100%;
  aspect-ratio: 3 / 4;          /* sane default; sizing modifiers override */
  border-radius: 0;             /* corners stay square, always */
  background-color: var(--fig-ground-bottom);
  background-image: linear-gradient(
    180deg,
    var(--fig-ground-top) 0%,
    var(--fig-ground-top) 22%,
    var(--fig-ground-bottom) 100%
  );
}

/* silhouette plate — the only layer that moves */
.figure-print::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  transform: scale(1);
  transform-origin: 50% 50%;
  transition: transform 0.8s ease-out;
}

/* film grain + halftone screen — the "printed in a magazine" layer.
   Two dot lattices offset by half a pitch make a 45deg screen at ~3px. */
.figure-print::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  opacity: var(--fig-grain-alpha);
  mix-blend-mode: var(--fig-grain-blend);
  background-image:
    var(--fig-grain),
    radial-gradient(circle, var(--fig-halftone) 0.5px, transparent 0.6px),
    radial-gradient(circle, var(--fig-halftone) 0.5px, transparent 0.6px);
  background-size:
    var(--fig-grain-size) var(--fig-grain-size),
    3px 3px,
    3px 3px;
  background-position:
    var(--fig-grain-offset),
    0 0,
    1.5px 1.5px;
  background-repeat: repeat;
  transition: opacity 0.8s ease-out;
}


/* --------------------------------------------------------------------------
   2. SILHOUETTE VARIANTS
   Each is a lighting setup, not a shape. Masses are stacked ABOVE the
   backdrop glow so the figure always reads darker than the air behind it.
   Every variant carries its own grain seed and tile pitch so two prints set
   side by side never repeat the same speckle.
   -------------------------------------------------------------------------- */

/* --- PORTRAIT :: rim-lit head, key at 10 o'clock, bare seamless behind ---- */
.figure-print--portrait {
  --fig-grain-size: 190px;
  --fig-grain-offset: 0 0;
  --fig-grain: url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20width%3D'190'%20height%3D'190'%3E%3Cfilter%20id%3D'n'%3E%3CfeTurbulence%20type%3D'fractalNoise'%20baseFrequency%3D'0.86'%20numOctaves%3D'3'%20seed%3D'17'%20stitchTiles%3D'stitch'%2F%3E%3CfeColorMatrix%20type%3D'saturate'%20values%3D'0'%2F%3E%3C%2Ffilter%3E%3Crect%20width%3D'190'%20height%3D'190'%20filter%3D'url(%23n)'%2F%3E%3C%2Fsvg%3E");
}

.figure-print--portrait::before {
  background-image:
    /* key spill entering top-left */
    radial-gradient(ellipse 64% 54% at 10% 2%,
      rgba(var(--fig-lit), 0.155),
      rgba(var(--fig-lit), 0) 62%),
    /* rim: halo offset up-left of the skull so the edge lights at 10 o'clock */
    radial-gradient(ellipse 25% 23% at 47% 27%,
      rgba(var(--fig-lit), 0) 60%,
      rgba(var(--fig-lit), 0.46) 73%,
      rgba(var(--fig-lit), 0) 89%),
    /* skull mass */
    radial-gradient(ellipse 23% 21% at 50% 29%,
      rgba(var(--fig-mass), 0.97) 52%,
      rgba(var(--fig-mass), 0.55) 74%,
      rgba(var(--fig-mass), 0) 92%),
    /* neck wedge */
    radial-gradient(ellipse 9% 14% at 50.5% 52%,
      rgba(var(--fig-mass), 0.9) 40%,
      rgba(var(--fig-mass), 0) 90%),
    /* shoulder line running off the bottom of the frame */
    radial-gradient(ellipse 45% 33% at 50% 96%,
      rgba(var(--fig-mass), 0.98) 42%,
      rgba(var(--fig-mass), 0.6) 68%,
      rgba(var(--fig-mass), 0) 90%),
    /* backdrop glow — the air the head is cut out of */
    radial-gradient(ellipse 47% 41% at 50% 33%,
      rgba(var(--fig-lit), 0.225),
      rgba(var(--fig-lit), 0.07) 55%,
      rgba(var(--fig-lit), 0) 80%),
    /* vignette */
    radial-gradient(ellipse 78% 74% at 50% 44%,
      rgba(var(--fig-vig), 0) 44%,
      rgba(var(--fig-vig), var(--fig-vig-alpha)) 100%);
}

/* --- STANDING :: soft top-back source, low key, hard floor shadow --------- */
.figure-print--standing {
  --fig-grain-size: 215px;
  --fig-grain-offset: 40px 22px;
  --fig-grain: url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20width%3D'215'%20height%3D'215'%3E%3Cfilter%20id%3D'n'%3E%3CfeTurbulence%20type%3D'fractalNoise'%20baseFrequency%3D'0.92'%20numOctaves%3D'3'%20seed%3D'41'%20stitchTiles%3D'stitch'%2F%3E%3CfeColorMatrix%20type%3D'saturate'%20values%3D'0'%2F%3E%3C%2Ffilter%3E%3Crect%20width%3D'215'%20height%3D'215'%20filter%3D'url(%23n)'%2F%3E%3C%2Fsvg%3E");
}

.figure-print--standing::before {
  background-image:
    /* source hung just above the top edge, slightly behind the subject */
    radial-gradient(ellipse 42% 32% at 50% -8%,
      rgba(var(--fig-lit), 0.2),
      rgba(var(--fig-lit), 0) 70%),
    /* thin contour rim down the camera-left side of the body */
    radial-gradient(ellipse 13% 42% at 45% 50%,
      rgba(var(--fig-lit), 0) 58%,
      rgba(var(--fig-lit), 0.3) 72%,
      rgba(var(--fig-lit), 0) 87%),
    /* head */
    radial-gradient(ellipse 5.5% 5% at 50% 14%,
      rgba(var(--fig-mass), 0.97) 55%,
      rgba(var(--fig-mass), 0) 86%),
    /* torso */
    radial-gradient(ellipse 10.5% 21% at 50% 40%,
      rgba(var(--fig-mass), 0.96) 50%,
      rgba(var(--fig-mass), 0.4) 78%,
      rgba(var(--fig-mass), 0) 95%),
    /* legs, narrowing */
    radial-gradient(ellipse 7% 25% at 50% 74%,
      rgba(var(--fig-mass), 0.95) 45%,
      rgba(var(--fig-mass), 0.35) 75%,
      rgba(var(--fig-mass), 0) 95%),
    /* contact shadow at the feet */
    radial-gradient(ellipse 24% 4% at 50% 95%,
      rgba(var(--fig-mass), 0.85),
      rgba(var(--fig-mass), 0) 74%),
    /* pool of floor light the shadow sits in */
    radial-gradient(ellipse 56% 17% at 50% 98%,
      rgba(var(--fig-lit), 0.1),
      rgba(var(--fig-lit), 0) 80%),
    /* faint backdrop lift so the body has air to stand in */
    radial-gradient(ellipse 40% 60% at 50% 42%,
      rgba(var(--fig-lit), 0.1),
      rgba(var(--fig-lit), 0) 82%),
    /* vignette */
    radial-gradient(ellipse 74% 76% at 50% 48%,
      rgba(var(--fig-vig), 0) 40%,
      rgba(var(--fig-vig), var(--fig-vig-alpha)) 100%);
}

/* --- PROFILE :: hard key from camera-right, subject pushed to the right --- */
.figure-print--profile {
  --fig-grain-size: 235px;
  --fig-grain-offset: 88px 60px;
  --fig-grain: url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20width%3D'235'%20height%3D'235'%3E%3Cfilter%20id%3D'n'%3E%3CfeTurbulence%20type%3D'fractalNoise'%20baseFrequency%3D'0.88'%20numOctaves%3D'3'%20seed%3D'63'%20stitchTiles%3D'stitch'%2F%3E%3CfeColorMatrix%20type%3D'saturate'%20values%3D'0'%2F%3E%3C%2Ffilter%3E%3Crect%20width%3D'235'%20height%3D'235'%20filter%3D'url(%23n)'%2F%3E%3C%2Fsvg%3E");
}

.figure-print--profile::before {
  background-image:
    /* raking key just off the right edge of frame */
    radial-gradient(ellipse 56% 72% at 104% 28%,
      rgba(var(--fig-lit), 0.2),
      rgba(var(--fig-lit), 0) 66%),
    /* rim tracing the face contour — offset left of the skull mass */
    radial-gradient(ellipse 20% 19% at 66% 36%,
      rgba(var(--fig-lit), 0) 62%,
      rgba(var(--fig-lit), 0.5) 75%,
      rgba(var(--fig-lit), 0) 90%),
    /* skull mass */
    radial-gradient(ellipse 19% 18% at 71% 36%,
      rgba(var(--fig-mass), 0.97) 50%,
      rgba(var(--fig-mass), 0.5) 76%,
      rgba(var(--fig-mass), 0) 94%),
    /* jaw and neck */
    radial-gradient(ellipse 12% 15% at 76% 58%,
      rgba(var(--fig-mass), 0.95) 45%,
      rgba(var(--fig-mass), 0) 88%),
    /* shoulder anchoring the bottom-right corner */
    radial-gradient(ellipse 35% 27% at 81% 101%,
      rgba(var(--fig-mass), 0.98) 40%,
      rgba(var(--fig-mass), 0) 86%),
    /* the empty field, camera-left: lifted just enough to read as air */
    radial-gradient(ellipse 46% 56% at 16% 56%,
      rgba(var(--fig-lit), 0.075),
      rgba(var(--fig-lit), 0) 78%),
    /* vignette weighted to the left so the negative space stays quiet */
    radial-gradient(ellipse 82% 78% at 62% 46%,
      rgba(var(--fig-vig), 0) 42%,
      rgba(var(--fig-vig), var(--fig-vig-alpha)) 100%);
}

/* --- DETAIL :: hard raking light across an empty seamless, no subject ----- */
.figure-print--detail {
  --fig-grain-size: 175px;
  --fig-grain-offset: 26px 96px;
  --fig-grain-alpha: 0.105;
  --fig-grain-hover-alpha: 0.145;
  --fig-grain: url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20width%3D'175'%20height%3D'175'%3E%3Cfilter%20id%3D'n'%3E%3CfeTurbulence%20type%3D'fractalNoise'%20baseFrequency%3D'0.95'%20numOctaves%3D'4'%20seed%3D'97'%20stitchTiles%3D'stitch'%2F%3E%3CfeColorMatrix%20type%3D'saturate'%20values%3D'0'%2F%3E%3C%2Ffilter%3E%3Crect%20width%3D'175'%20height%3D'175'%20filter%3D'url(%23n)'%2F%3E%3C%2Fsvg%3E");
}

.figure-print--detail::before {
  background-image:
    /* the raking band itself, cutting the frame at 118deg */
    linear-gradient(118deg,
      rgba(var(--fig-lit), 0) 28%,
      rgba(var(--fig-lit), 0.13) 45%,
      rgba(var(--fig-lit), 0.025) 58%,
      rgba(var(--fig-lit), 0) 70%),
    /* hot spot where the source clips the top-right corner */
    radial-gradient(ellipse 62% 62% at 84% 6%,
      rgba(var(--fig-lit), 0.27),
      rgba(var(--fig-lit), 0.05) 45%,
      rgba(var(--fig-lit), 0) 73%),
    /* secondary bounce, low and centre-left */
    radial-gradient(ellipse 40% 30% at 22% 62%,
      rgba(var(--fig-lit), 0.07),
      rgba(var(--fig-lit), 0) 80%),
    /* falloff swallowing the lower-left corner */
    radial-gradient(ellipse 92% 82% at 8% 102%,
      rgba(var(--fig-mass), 0.9),
      rgba(var(--fig-mass), 0) 62%),
    /* vignette */
    radial-gradient(ellipse 86% 82% at 56% 42%,
      rgba(var(--fig-vig), 0) 48%,
      rgba(var(--fig-vig), var(--fig-vig-alpha)) 100%);
}


/* --------------------------------------------------------------------------
   3. LIGHT INVERSION
   Paper stock instead of a dark print. The masses stay dark (a figure on
   paper is ink), while everything the light touched drops to a warm-neutral
   gray so rims read as contour shading rather than glare. Grain switches to
   multiply so it prints as ink tooth rather than sitting on top as haze.
   Combine with any shape variant: .figure-print--portrait.figure-print--light
   -------------------------------------------------------------------------- */

.figure-print--light {
  --fig-ground-top: #f8f7f4;
  --fig-ground-bottom: #f0efec;   /* mean lands exactly on #f4f3f0 stock */
  --fig-lit: 104, 104, 104;       /* neutral; the paper carries the warmth */
  --fig-mass: 16, 16, 16;
  --fig-vig-alpha: 0.12;
  --fig-halftone: rgba(0, 0, 0, 0.55);
  --fig-grain-alpha: 0.085;
  --fig-grain-hover-alpha: 0.125;
  --fig-grain-blend: multiply;
  --fig-rule: rgba(0, 0, 0, 0.5);
  --fig-caption: rgba(0, 0, 0, 0.72);
  --fig-caption-shadow: rgba(255, 255, 255, 0.6);
}


/* --------------------------------------------------------------------------
   4. CAPTION SLATE
   Content comes from HTML — this is styling only.
   -------------------------------------------------------------------------- */

.figure-caption {
  position: absolute;
  z-index: 3;
  left: 0.9rem;
  bottom: 0.85rem;
  margin: 0;
  max-width: calc(100% - 1.8rem);
  font-size: 0.62rem;
  line-height: 1.2;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.2em;
  color: var(--fig-caption);
  text-shadow: 0 0 8px var(--fig-caption-shadow);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  pointer-events: none;
}


/* --------------------------------------------------------------------------
   5. CORNER BRACKETS
   Crop marks, top-left and bottom-right only — an asymmetric pair reads as
   a registration mark rather than a frame.
   -------------------------------------------------------------------------- */

.figure-frame-tag {
  position: absolute;
  z-index: 3;
  inset: 0.75rem;
  pointer-events: none;
}

.figure-frame-tag::before,
.figure-frame-tag::after {
  content: "";
  position: absolute;
  width: 18px;
  height: 18px;
}

.figure-frame-tag::before {
  top: 0;
  left: 0;
  border-top: 1px solid var(--fig-rule);
  border-left: 1px solid var(--fig-rule);
}

.figure-frame-tag::after {
  right: 0;
  bottom: 0;
  border-right: 1px solid var(--fig-rule);
  border-bottom: 1px solid var(--fig-rule);
}


/* --------------------------------------------------------------------------
   6. SIZING MODIFIERS
   -------------------------------------------------------------------------- */

/* A real photograph in the frame: the CSS massing plate switches off, the
   picture fills the frame in monochrome, and the grain screen + furniture
   stay on top so it sits in the same print world as the placeholders. */
.figure-print--photo::before { display: none; }
.figure-print--photo > img {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(1);
}
/* A quiet foot scrim under the caption so it reads on any photograph */
.figure-print--photo > img {
  mask-image: none;
}
.figure-print--photo .figure-caption {
  color: rgba(244, 243, 240, 0.92);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.55), 0 0 14px rgba(0, 0, 0, 0.45);
}

.figure-print--tall   { width: 100%; aspect-ratio: 3 / 4;   }
.figure-print--wide   { width: 100%; aspect-ratio: 16 / 10; }
.figure-print--square { width: 100%; aspect-ratio: 1 / 1;   }


/* --------------------------------------------------------------------------
   7. THE BREATHING PRINT
   On hover the emulsion lifts: grain gains a few points of density while the
   massing pushes 3% — slow enough (0.8s) to read as the print inhaling, not
   as a UI response.
   -------------------------------------------------------------------------- */

@media (hover: hover) and (pointer: fine) {
  .figure-print:hover::after {
    opacity: var(--fig-grain-hover-alpha);
  }

  .figure-print:hover::before {
    transform: scale(1.03);
  }
}

/* Reduced motion: keep the grain shift, drop the movement entirely. */
@media (prefers-reduced-motion: reduce) {
  .figure-print::before,
  .figure-print:hover::before {
    transform: none;
    transition: none;
  }

  .figure-print::after {
    transition: opacity 0.8s ease-out;
  }
}


/* ==========================================================================
   DEMO MARKUP — copy verbatim. Caption text is authored, not generated.

   <!-- portrait, tall -->
   <figure class="figure-print figure-print--portrait figure-print--tall">
     <span class="figure-frame-tag"></span>
     <figcaption class="figure-caption">SHOOT 01 &middot; PENDING</figcaption>
   </figure>

   <!-- standing, tall -->
   <figure class="figure-print figure-print--standing figure-print--tall">
     <span class="figure-frame-tag"></span>
     <figcaption class="figure-caption">SHOOT 02 &middot; PENDING</figcaption>
   </figure>

   <!-- profile, square -->
   <figure class="figure-print figure-print--profile figure-print--square">
     <span class="figure-frame-tag"></span>
     <figcaption class="figure-caption">SHOOT 03 &middot; PENDING</figcaption>
   </figure>

   <!-- detail crop, wide -->
   <figure class="figure-print figure-print--detail figure-print--wide">
     <span class="figure-frame-tag"></span>
     <figcaption class="figure-caption">PLATE 04 &middot; TEXTURE</figcaption>
   </figure>

   <!-- light inversion, for use on white sections -->
   <figure class="figure-print figure-print--portrait figure-print--light figure-print--square">
     <span class="figure-frame-tag"></span>
     <figcaption class="figure-caption">SHOOT 05 &middot; PENDING</figcaption>
   </figure>

   Notes for the page author:
   - Shape variant and size modifier are independent; combine freely.
   - --light is additive on top of any shape variant.
   - Both children are optional. Order does not matter.
   - Any extra content placed inside a .figure-print needs its own
     position:relative and z-index >= 3 to sit above the grain.
   ========================================================================== */
