/* ==========================================================================
   R9h — REBUILT TO THE PAGE'S OWN STYLE, by direction: "refer the page style
   from hero to the section above the plate, redo everything after it."

   THE SOURCE IS THE BUILT PAGE (§2–§6), NOT THE DOCUMENTS. What §2–§6
   actually do, read off the stylesheets rather than the plan:

     ground      #000000, always
     container   --color-surface-panel #171717, SQUARE, no border
     accent      violet #6146ED — filled banners, filled circles, 2px rules
                 gold #BE9D4A for the negative side only
     headings    Loos 500, white, section titles CENTRED
     body        Mundial, weight 300, --color-text-body
     rules       1px --color-border-strong
     radius      0 everywhere; 50% only where a circle has no corners
     gradients   NONE. §2–§6 carry no blend shape and no flat fill.

   Every change below follows from that list.
   ========================================================================== */

/* ==========================================================================
   11 — BUILD RELATIONSHIPS WITH PEERS
   Contained · three scrolling rails · NO blend shape ·
   SIGNATURE: the rails, middle one running the other way.

   R11c — REBUILT AGAIN TO A REFERENCE, by direction: "copy the exact same
   style and sizing of people cards, without rounded corners; people's image
   in a circle with a name tag; scrolling away in either direction."

   WHAT REPLACED WHAT. R11a/R11b's hairline lattice with faces fading in and
   out is GONE — grid, cells, the swap script and its --duration-wall-hold
   token with it. A field that fades and a rail that scrolls are two different
   answers to the same brief, and keeping both would have given one section
   two signature interactions.

   THE RAIL IS THE HERO'S COMPONENT, unchanged except for one modifier. Three
   .marquee instances, the middle one reversed. Nothing here re-implements the
   loop: the seam arithmetic lives in marquee.css and is hard enough to get
   right once.

   ⚠ THE PAGE NOW CARRIES FIVE RAILS — Hero, §8, and three here — plus the
   Hero's slider. §16's stated motion character is "precise and mechanical;
   nothing drifts in from far away, things arrive in position", and six
   continuously-moving elements is not that character. Each one is permitted
   individually and the total is the thing to watch. See the R11c amendment.

   THE CHIP IS A PLACEHOLDER, END TO END. A grey circle where a face goes, a
   [NAME REQUIRED] where a name goes. See the note on .wall__name.
   ========================================================================== */

/* ⚠ THE GLOW IS WIDER THAN ITS CONTAINER, so something has to clip it.
   .wall__glow sits at `inset: -60% -15%` — 15% of this box beyond each side,
   which at a 390px viewport is roughly 51px past each edge and about 27px
   past the VIEWPORT. That was real horizontal overflow on every phone, hidden
   only by the `overflow-x: hidden` base.css used to carry on <body> — the
   same declaration that was breaking §10's sticky stack.

   IT IS CLIPPED AT THE SECTION, NOT HERE. Clipping on .wall__rails would cut
   the glow at the rails' own edge and give a soft radial a hard vertical
   border. .wall is full-bleed, so clipping there trims it at the viewport
   edge instead — where the gradient has already fallen close to zero and the
   cut does not read. */
.wall {
  overflow: hidden;
}

.wall__rails {
  position: relative;
  /* Confines the grain's `overlay` blend to the glow, exactly as .u-grain's
     own note argues: without it the blend reaches whatever is beneath in the
     nearest stacking context, and the compositor has to keep that backdrop
     live. Here it also gives the glow's negative z-index a floor to sit on,
     so it lands under the chips and not under the section. */
  isolation: isolate;
  display: grid;
  /* Tight. The three rails are one object — a crowd — and a generous gap
     would read as three separate strips that happen to be stacked.
     R11d — 12 -> 16, by direction. ONE STEP IS THE WHOLE ADJUSTMENT
     AVAILABLE: §4's scale runs 8 · 12 · 16 · 24, so "slightly more" between
     12 and 24 has exactly one legal value in it. */
  gap: var(--space-sm);
}

/* The component's own gap is --space-2xl (48px), set for logo plates that
   need air around them. Chips are a crowd and 48px between them reads as a
   queue, so the rail takes the same interval the rows are stacked at — one
   value in both axes, 16px since R11d.

   ⚠ THE GAP IS ALSO THE SPEED. The track travels (group + gap) in
   --duration-marquee, so widening the gap makes the rail move very slightly
   faster. 4px against a track of roughly 1500px is about a quarter of one
   percent — below noticing, and worth stating because a larger change to
   this value would be a speed change disguised as a spacing change.

   ⚠ IT MUST OUT-SPECIFY THE COMPONENT. --marquee-gap is declared ON
   .marquee__track (0,1,0), and a declaration on the element beats an
   inherited custom property no matter where it is set. .wall__rail
   .marquee__track is (0,2,0), which is the only reason this lands. The
   keyframe reads the same property, so the seam corrects itself. */
.wall__rail .marquee__track { --marquee-gap: var(--space-sm); }

/* --------------------------------------------------------------------------
   THE GLOW — R11e, by direction: "a subtle dark purple glow (radial gradient)
   from behind the cards strip".

   ⚠ WHAT IT COSTS, all four stated in the R11e amendment: a seventh gradient
   against §9's five; the first radial on a page of linears; a gradient field
   in a section the budget lists at zero; and §17's "NO BLEND SHAPE. The
   density is the effect" no longer describing this section.

   NO mix-blend-mode, AND THAT IS NOT AN OVERSIGHT. §6's blend-shape spec says
   hard-light, and hard-light would erase this: with a blend layer darker than
   50% the formula reduces to multiply against the backdrop, and the backdrop
   is #000000. Every pixel would come back black. A glow on pure black can
   only be painted normally — which is also why the stops carry their own
   alpha instead of relying on a blend to do the mixing.

   IT OVERHANGS ON PURPOSE, the one part of the blend-shape spec that does
   apply: a glow whose falloff ends inside its own box has a visible edge.
   -15% inline / -60% block puts the falloff outside the rails entirely, so
   only the middle of it is ever on screen.
   -------------------------------------------------------------------------- */
.wall__glow {
  /* ⚠ THIS OVERRIDES .u-grain's OWN `position: relative` at EQUAL SPECIFICITY
     — both are (0,1,0), and it lands only because base.css is linked before
     the section stylesheets. Move wall.css above base.css and the glow snaps
     into flow as a zero-height block and disappears. */
  position: absolute;
  inset: -60% -15%;
  /* Under the chips, above nothing — .wall__rails' isolation is what keeps
     this from sliding behind the section ground. */
  z-index: -1;
  background-image: var(--gradient-glow-violet);
  /* §9 — a blend shape is never between the reader and a control. Nothing
     here is interactive today; this is what keeps that true if it ever is. */
  pointer-events: none;
}

/* --------------------------------------------------------------------------
   THE CHIP — R21a, REBUILT TO A SUPPLIED REFERENCE: "each of the attendee
   card will be designed exactly as attached." Circular face at the left,
   name over institution, a hairline you can see. R21b squared the corner and
   R21c made the ground glass; both are noted where they land.

   ⚠⚠ THE CORNER IS SQUARE AND THE ROUND ONE IS NOT COMING BACK BY ACCIDENT.
   R21a gave this chip a fourth radius (--radius-chip, 12px) to match the
   reference; R21b removed it by direction one revision later. THAT IS THE
   SECOND TIME A FOURTH RADIUS HAS BEEN ADDED AND GIVEN BACK — §9's photo
   tiles were the first. R11c's note stood in this exact spot saying the
   reference's round corner was "the one thing not copied", and after two
   round trips that is again the standing answer. The page has three radius
   values. Do not propose a fourth for this chip a third time without saying
   out loud that it has already failed twice.

   NOTHING ELSE HERE IS A PICKED NUMBER. The avatar is still R11d's calc over
   the two font sizes and the body leading (44.4px today); the chip height is
   that plus padding. Both re-derive if the type scale moves.

   THE PROPORTIONS ARE READ OFF THE REFERENCE, not off taste:
     avatar : chip height    0.60 there → 0.58 here (44.4 / 76.4)
     left padding : height   0.15 there → 0.16 here (12 / 76.4)
   The corner (R21b) and the ground (R21c) are the two things NOT taken from
   it. The proportions above survived both.

   ⚠ CONTRAST, MEASURED PER TEXT BOX AGAINST THE WORST CASE, and the worst
   case is not the flat ground — it is the brightest pixel of .wall__glow
   showing THROUGH the glass. That is the token's 30% #6146ED centre, run
   through saturate(200%) and then under 45% black: #11093F.
       name  #FFFFFF on #11093F   18.5:1  ✓
       org   #B4B4B4 on #11093F    8.92:1 ✓
   Both are BETTER than the #171717 ground they replaced (17.9:1 / 8.64:1) —
   45% black over a dark glow is darker than the panel step was. The
   @supports fallback ground #121212 measures 18.7:1 / 9.03:1, so no path
   through this rule is worse than what it replaced.

   ⚠ RE-MEASURE IF --color-surface-glass, --saturate-glass OR
   --gradient-glow-violet MOVES. Three tokens feed this number and two of
   them belong to other components.
   -------------------------------------------------------------------------- */
.wall__person {
  flex: none;
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  /* Asymmetric by construction: the avatar brings its own visual padding as
     a circle in a square box, so an equal inline-end would look larger than
     the start. R21a — 8/24 → 12/24, and the block padding 8 → 16, both
     opening the box out to the reference's proportions above. */
  padding-block: var(--space-sm);
  padding-inline: var(--space-xs) var(--space-md);
  /* R21c — GLASS, by direction: "instead of the gradient style background,
     the cards will be glassmorphic style exactly like the sticky header."
     This is .nav__inner's recipe, token for token: --color-surface-glass
     (45% black) + blur + saturate + a hairline. Nothing new is declared.

     WHAT WENT: R21a's per-chip violet halo, the "gradient style background"
     being replaced. It is not kept alongside the glass — the section's own
     glow now reaches the type THROUGH the chip, which is the same violet
     from the same token doing the same job with one layer instead of two.

     ⚠ THE BLUR IS ALMOST DECORATIVE HERE AND THE TRANSLUCENCY IS THE EFFECT.
     .wall__rails carries `isolation: isolate`, which makes it a BACKDROP
     ROOT — so each chip samples only what is painted inside .wall__rails
     behind it, which is .wall__glow and nothing else. A 40px blur over a
     smooth radial has essentially nothing to smear; what the reader actually
     sees is the glow coming through 45% black. The blur earns its place by
     removing .u-grain's texture from behind the chips, and that is all it
     does. Kept because the direction was "exactly like the sticky header".

     ⚠⚠ COST, AND IT IS NOT SMALL: 36 backdrop-filter layers inside a track
     that is transformed continuously and never stops. The blurred backdrop
     of every chip is recomputed every frame for the life of the page, and
     backdrop-filter is the most expensive compositing operation on it. If
     §11 ever profiles badly, DELETE THE TWO backdrop-filter LINES FIRST —
     by the paragraph above, the chips will look very nearly identical. */
  background-color: var(--color-surface-glass);
  border-radius: var(--radius-control);
  /* Blur AND saturate, .nav__inner's reasoning unchanged: the blur is what
     makes the ground read as passing behind the chip, the saturation is what
     stops the 45% scrim greying the violet into a smudge. */
  -webkit-backdrop-filter: blur(var(--blur-glass)) saturate(var(--saturate-glass));
          backdrop-filter: blur(var(--blur-glass)) saturate(var(--saturate-glass));
  /* R21a — border-default (0.10) → border-strong (0.20). The reference's chip
     has an edge you can see: 0.10 resolves to about #2E2E2E over this ground
     and reads as a soft join, 0.20 to about #3D3D3D and reads as a drawn line.

     ⚠ STILL A box-shadow AND NOT A border. These chips are auto-width flex
     items, so `border-box` has no declared width to subtract from — a real
     1px border would add 2px to every chip AND to the marquee group's
     measured width. An inset shadow follows border-radius and costs no
     layout. (The loop itself is percentage-based, so a width change is
     self-correcting either way; this is about not making the chips wider
     than they were drawn.)

     ⚠ THE ONE PLACE THIS DEPARTS FROM .nav__inner, deliberately. The nav's
     hairline is --color-border-default (0.10) because the bar is large and
     the blur already gives it an edge. 0.10 over this ground is about 1.3:1
     — §3 says in so many words not to use it for a rule that must read — and
     a 76px chip has no size to spare. 0.20 keeps the chip a drawn object
     rather than a soft patch. Say the word and it matches the nav exactly. */
  box-shadow: inset 0 0 0 var(--border-hairline) var(--color-border-strong);
}

/* NO BACKDROP-FILTER SUPPORT → CLOSE THE GLASS, exactly as nav.css does and
   for the same reason: without the blur the ground is a flat 45% black and
   the glow runs through it unsoftened. The fallback is the opaque card
   surface — it gives up the effect and keeps the chip a solid object.

   ⚠ THIS IS NOT --color-surface-panel, the chip's ground before R21c. It is
   --color-surface-card (#121212), because that is what the nav falls back to
   and the two are meant to be one treatment. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .wall__person { background-color: var(--color-surface-card); }
}

/* THE FACE — R21d. Twelve real attendee photographs landed and replaced the
   #CCCCCC placeholder disc; --color-surface-light-block loses its §11
   consumer and keeps only §4's.

   NO PRE-LOAD GROUND, DELIBERATELY. The old #CCCCCC fill would now be a
   bright disc flashing in every chip while twelve lazy images decode — the
   single brightest object in the section, arriving and leaving. With no
   background the chip simply shows its own glass until the face paints.

   overflow: hidden is what makes the circle a circle: the radius is on this
   box and the <img> is clipped by it.

   --radius-avatar is the documented carve-out from "everything is square":
   a circle has no corners to square.

   THE SIZE IS §6'S CALCULATION, not a new number — see --avatar-size on
   .wall__person above. ⚠ IT DEPENDS ON THE LINE-HEIGHT BEING INHERITED, the
   same dependency members.css carries. Neither .wall__name nor .wall__org
   sets one, so both take --line-height-body from base.css. Give either its
   own and this calc has to be updated with it. */
.wall__avatar {
  flex: none;
  --avatar-size: calc((var(--font-size-small) + var(--font-size-meta)) * var(--line-height-body));
  overflow: hidden;
  inline-size: var(--avatar-size);
  block-size: var(--avatar-size);
  border-radius: var(--radius-avatar);
}

/* THE FILES ARE ALL EXACTLY 500x500, so `cover` has nothing to crop and no
   object-position is needed — unlike §10's 2:3 cutouts, where the anchor is
   load-bearing and a shorter frame silently cuts off the top of a head. If a
   non-square attendee file is ever added, THAT stops being true and this
   needs an object-position chosen against the actual crops.

   ⚠⚠ COLOUR AT REST, WHICH §11 OF design-rules.md PROHIBITS BY DEFAULT.
   Amended at R21d for this section, on the same grounds §10 was amended at
   R19t: these rails carry no hover and never will — they are aria-hidden
   decoration on a timer — so `grayscale` here would not be "a treatment that
   returns on hover", it would be permanent, and the rule's own justification
   ("nothing is lost if the hover never fires") has nothing to hang on.

   `display: block` kills the inline baseline gap under the image, which at
   this size would push the face off-centre in its own circle. */
.wall__face {
  display: block;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
}

/* Zero gap, exactly as .members__author-text sets it (R9t): the two lines
   carry their own leading and the scale's smallest step, 8px, was already
   too much between a name and the institution under it. */
.wall__id {
  display: flex;
  flex-direction: column;
  gap: 0;
}

/* ⚠ [NAME REQUIRED] IS A LIVE BLOCKER, and it costs this section its rhythm.
   The reference's rails read as a crowd because every name is a different
   length, so the chips are irregular and the row never falls into a pattern.
   Thirty-six identical strings make thirty-six identical chips — a regular
   tick where the reference has a texture. NOTHING IN CSS CAN FIX THAT; only
   real names can. Do not fake it with varied placeholder strings: invented
   names in an attendee wall are the one thing on this page that would be
   read as a factual claim about who is coming.

   16px/400 Mundial: a name is not a heading and not metadata. white-space:
   nowrap because a chip that wraps stops being a chip. */
.wall__name {
  font-size: var(--font-size-small);
  /* R11d — 400 -> 600, matching .members__name. The chip now carries two
     lines and needs the same weight difference the testimonial uses to
     separate them; at 400 over 400 the institution would read as a
     continuation of the name rather than a second field. */
  font-weight: var(--font-weight-semibold);
  color: var(--color-text-heading);
  white-space: nowrap;
}

/* .members__role's values, and its reasoning: --color-text-body at 8.65:1
   rather than --color-text-muted at 5.19:1, because this is the smallest
   type in the smallest container on the page. */
.wall__org {
  font-size: var(--font-size-meta);
  color: var(--color-text-body);
  white-space: nowrap;
}

/* --------------------------------------------------------------------------
   REDUCED MOTION
   marquee.css already turns each rail into a wrapping row and drops the
   duplicate group, so all six chips of each rail stay visible with nothing
   moving. The rails just become three wrapped rows of chips — which is a
   legitimate static reading of the section, not a degraded one.
   -------------------------------------------------------------------------- */

/* R17i — lifted out of a style="" attribute. §11 puts its heading and its
   rails in two separate .container elements, so layout.css's
   `.section__title + *` never reached the rails — the title is not their
   sibling, it sits inside the container before them. This supplies the same
   heading-to-content interval that rule would have. */
.wall__rails-wrap { margin-block-start: var(--gap-heading-to-content); }
