/* ==========================================================================
   PORTRAIT FRAME
   The module that holds a person. A rectangle whose four corners are cut by
   a TWO-STEP staircase, so the silhouette reads as a pixel-drawn frame:

           ┌────────────┐
        ┌──┘            └──┐
     ┌──┘                  └──┐
     │                        │
     │                        │
     └──┐                  ┌──┘
        └──┐            ┌──┘
           └────────────┘

   Every step is square and every corner is identical — the shape is
   symmetric about both axes. This supersedes the single-corner notch in
   design-rules.md §11; see the R3 amendment there.

   THREE LAYERS, bottom to top:
     1. the ground — one of the brand gradients, contained by the frame
     2. grain      — low opacity, because gradient never appears without it
     3. the subject — a background-removed portrait, grayscale at rest

   The gradient is visible only where the subject is not. It is read as the
   light behind a person, which is why a flat fill is permitted here and not
   as section atmosphere.

   `clip-path` is correct here and wrong for the eyebrow box: here it cuts a
   FILL, which is exactly what clip-path does well. The eyebrow needed a 1px
   outline, which clip-path cannot cut without changing stroke thickness.
   ========================================================================== */

.portrait {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.portrait__frame {
  /* Local shorthand. The staircase is two steps deep, so the corner is
     inset by 2 × step on both axes. */
  --step: var(--portrait-step);
  --step-2: calc(var(--portrait-step) * 2);

  position: relative;
  aspect-ratio: var(--portrait-ratio);

  /* R10f — THE DEFAULT IS A FALLBACK, NOT A DECLARATION, and the difference
     is the whole bug it fixes.

     This used to read `--portrait-ground: var(--gradient-g1)` as its own
     declaration on the frame. A custom property set on an ANCESTOR is
     inherited — but a declaration ON the element beats an inherited value, so
     the frame overwrote anything a parent tried to give it. §10's figure had
     been setting --portrait-ground for the whole build and it had never once
     taken effect; every portrait on the page rendered G1, including the
     Speakers' which §11a assigns G4.

     It failed silently in the worst way: a valid property, a valid value, a
     gradient on screen, and nothing to suggest it was the wrong one.

     As a fallback the frame still defaults to G1 when nobody sets a ground,
     and a parent — or the --supporting variant below — can now actually
     change it. */
  background-image: var(--portrait-ground, var(--gradient-g1));
  border-radius: var(--radius-none);

  /* Twenty points, clockwise from the left end of the top edge.
     clip-path clips the whole subtree, so the ground, the grain and the
     subject are all cut by the same silhouette. */
  clip-path: polygon(
    var(--step-2)                 0,
    calc(100% - var(--step-2))    0,
    calc(100% - var(--step-2))    var(--step),
    calc(100% - var(--step))      var(--step),
    calc(100% - var(--step))      var(--step-2),
    100%                          var(--step-2),
    100%                          calc(100% - var(--step-2)),
    calc(100% - var(--step))      calc(100% - var(--step-2)),
    calc(100% - var(--step))      calc(100% - var(--step)),
    calc(100% - var(--step-2))    calc(100% - var(--step)),
    calc(100% - var(--step-2))    100%,
    var(--step-2)                 100%,
    var(--step-2)                 calc(100% - var(--step)),
    var(--step)                   calc(100% - var(--step)),
    var(--step)                   calc(100% - var(--step-2)),
    0                             calc(100% - var(--step-2)),
    0                             var(--step-2),
    var(--step)                   var(--step-2),
    var(--step)                   var(--step),
    var(--step-2)                 var(--step)
  );
}

/* Grain. Gradient never appears without it (design-rules §12.4). Sits above
   the ground and below the subject. */
.portrait__frame::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: var(--texture-grain);
  opacity: var(--texture-grain-opacity);
  pointer-events: none;
}

/* The subject. A background-removed cutout, so the ground reads through. */
.portrait__img {
  position: absolute;
  inset: 0;
  z-index: var(--layer-raised);
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  object-position: center bottom;
  /* design-rules §11a — grayscale at rest, colour on interaction, one at a
     time. Colour is a treatment, never a meaning. */
  filter: grayscale(1);
  transition: filter var(--duration-base) var(--ease-standard);
}

.portrait:hover .portrait__img,
.portrait:focus-within .portrait__img { filter: grayscale(0); }
