/* ============================================================
   JWRC — About / portfolio page
   Loaded ONLY by about.html. Every selector here is namespaced to
   this page so no other page can be affected by anything below.
   Tokens, type and components come from style.css unchanged.
   ============================================================ */

/* ---------- chapter marker ----------
   The homepage defines this in its own page-scoped <style>, so this page
   needs its own copy rather than reaching into another page's styles. */
.chapter { display: flex; align-items: baseline; gap: 22px; margin-bottom: 44px; }
.chapter .no { font-family: var(--display); font-size: clamp(36px,4.4vw,62px); font-weight: 600;
  line-height: .82; color: var(--acc); letter-spacing: -.04em; }
.chapter .lbl { font: 600 11px/1 var(--body); letter-spacing: .3em; text-transform: uppercase;
  color: var(--ink-faint); }
.dark .chapter .lbl, .deep .chapter .lbl { color: rgba(252,248,240,.5); }
.chapter .rule { flex: 1; height: 1px; background: var(--line); align-self: center; }
.dark .chapter .rule, .deep .chapter .rule { background: var(--line-lt); }

/* ---------- portrait hero ---------- */
.ph {
  position: relative; overflow: hidden; color: var(--ivory);
  background:
    radial-gradient(120% 100% at 14% 0%, rgba(35,64,107,.68), transparent 58%),
    radial-gradient(100% 90% at 92% 10%, rgba(232,70,28,.32), transparent 60%),
    var(--band-2);
  padding-block: clamp(56px,6.5vw,96px) clamp(48px,5.5vw,84px);
}
.ph::before {
  content: ""; position: absolute; inset: 0; opacity: .055; background-size: 48px 48px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='48' height='48'%3E%3Cg fill='none' stroke='%23FCF8F0' stroke-width='1'%3E%3Cpath d='M24 1l23 23-23 23L1 24z'/%3E%3Ccircle cx='24' cy='24' r='7.6'/%3E%3C/g%3E%3C/svg%3E");
}
.ph .wrap { position: relative; z-index: 2; }
.ph-grid { display: grid; grid-template-columns: 1fr 340px; gap: clamp(32px,4.5vw,72px); align-items: center; }
.ph h1 { color: var(--ivory); max-width: 12ch; }
.ph .role {
  font: 600 11.5px/1 var(--body); letter-spacing: .2em; text-transform: uppercase;
  color: rgba(252,248,240,.6);
}
.ph .portrait-frame { position: relative; }
.ph .portrait-frame .portrait { display: block; }
.ph .badge {
  display: inline-flex; align-items: center; gap: 9px; padding: 10px 16px; border-radius: 999px;
  background: linear-gradient(135deg, var(--gold), var(--gold-lt)); color: #2B1F05;
  font: 700 11px/1 var(--body); letter-spacing: .12em; text-transform: uppercase;
}

/* ---------- pinned aside quote ---------- */
.aside-quote {
  margin: clamp(32px, 4vw, 54px) 0 0; padding: 0 0 0 clamp(18px, 2vw, 28px);
  border-left: 2px solid var(--flame);
  font-family: var(--display); font-style: italic; font-weight: 400;
  font-size: clamp(19px, 1.7vw, 25px); line-height: 1.42;
  color: var(--ink); max-width: 22ch; text-wrap: balance;
}
.aside-quote cite {
  display: block; margin-top: 16px;
  font: 600 11px/1 var(--body); font-style: normal;
  letter-spacing: .2em; text-transform: uppercase; color: var(--ink-faint);
}

/* ---------- credential strip ---------- */
.creds-row { display: grid; grid-template-columns: repeat(4,1fr); gap: 1px; background: var(--line-lt); }
.creds-row > div { background: var(--band); padding: 26px 22px; }
.creds-row .n {
  font-family: var(--display); font-size: clamp(28px,3vw,42px); font-weight: 600;
  color: var(--acc-gold); line-height: 1; font-variant-numeric: tabular-nums;
}
.creds-row .k {
  font: 500 10.5px/1.5 var(--body); letter-spacing: .17em; text-transform: uppercase;
  color: rgba(252,248,240,.55); margin-top: 10px;
}

/* ---------- roles / recognition ---------- */
.roles { display: grid; grid-template-columns: repeat(3,1fr); gap: 20px; }
.role-card { padding: 28px 26px 30px; border: 1px solid var(--line); border-radius: 4px;
  background: var(--bg); box-shadow: var(--sh-1); }
.role-card .t { font: 600 11px/1 var(--body); letter-spacing: .2em; text-transform: uppercase;
  color: var(--acc-sm); margin-bottom: 14px; display: block; }
.role-card h3 { font-size: 20px; line-height: 1.28; margin-bottom: 8px; }
.role-card p { font-size: 14.5px; color: var(--ink-soft); }

.bodies-grid { display: grid; grid-template-columns: repeat(6,1fr); gap: 1px; background: var(--line-lt); }
.bodies-grid > div { background: var(--band); padding: 30px 14px; text-align: center;
  font: 600 12.5px/1.4 var(--body); color: rgba(252,248,240,.84); transition: background .4s var(--ease); }
.bodies-grid > div:hover { background: #212B3F; }
.bodies-grid span { display: block; font-weight: 500; font-size: 10px; letter-spacing: .15em;
  text-transform: uppercase; color: var(--acc-gold); margin-top: 8px; font-size: 10.5px; }

/* ---------- featured carousel ----------
   The track is twice the content and drifts continuously; the mask fades
   both edges so cards enter and leave rather than being cut off. */
.rail-mask {
  position: relative; overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
}
.rail-scroll {
  display: flex; gap: 20px; width: max-content; padding-block: 26px 30px;
  will-change: transform;
}
.rail-scroll.is-static { width: auto; overflow-x: auto; }

.rail-item {
  /* A flex column, not a block. As a block the whitespace between the img
     and the caption in the template became anonymous line boxes, which put
     a phantom 12px above the photograph and pushed the card's content past
     its own height — so every card with a long title was clipped by its own
     overflow:hidden, at every width including desktop. Flex layout ignores
     whitespace-only text nodes. */
  display: flex; flex-direction: column;
  flex: none; width: clamp(240px, 26vw, 340px);
  border-radius: 5px; overflow: hidden; border: 1px solid var(--line);
  background: var(--bg); position: relative; cursor: pointer;
  padding: 0; text-align: left;
  transform: translateY(calc(var(--lift, 0px) * -1)) scale(var(--scale, 1));
  box-shadow: 0 calc(6px + var(--glow, 0) * 22px) calc(18px + var(--glow, 0) * 40px)
              -14px rgba(70,46,26, calc(.18 + var(--glow, 0) * .30));
  transition: border-color .4s var(--ease);
}
.rail-item:hover, .rail-item:focus-visible { border-color: rgba(232,70,28,.55); }
.rail-item:focus-visible { outline: 2px solid var(--flame); outline-offset: 3px; }

.rail-item .scene, .rail-item img {
  aspect-ratio: 4/3; width: 100%; object-fit: cover; display: block;
  filter: saturate(calc(.88 + var(--glow, 0) * .22));
  transition: filter .5s var(--ease);
}
.rail-item .meta { padding: 16px 18px 20px; flex: 1; }
/* The cards sit in a flex row and are stretched to a common height, so a
   long record title overflowed the card it belonged to and was cut off by
   the card's own overflow:hidden — at every width, desktop included.
   Clamping the title keeps the card's promise: two lines, then an ellipsis. */
.rail-item .meta b {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  overflow: hidden;
  font-family: var(--display); font-size: 17px; font-weight: 600;
  line-height: 1.28;
}
.rail-item .meta > span {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  overflow: hidden;
  font-size: 12.5px; line-height: 1.5; color: var(--ink-faint);
  margin-top: 8px;
}
/* a hairline that fills as the card reaches the middle */
.rail-item::after {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 3px;
  background: linear-gradient(90deg, var(--flame), var(--gold));
  transform: scaleX(var(--glow, 0)); transform-origin: left;
}

/* ---------- archive controls ---------- */
.gal-bar {
  position: sticky; top: var(--nav-h); z-index: 600; background: var(--bg);
  border-block: 1px solid var(--line); padding-block: 16px; margin-bottom: 30px;
}
.gal-bar .row { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }
.gal-search { position: relative; flex: 1; min-width: 220px; }
.gal-search input {
  width: 100%; padding: 12px 16px 12px 40px; border-radius: 999px; font: 400 14px/1 var(--body);
  border: 1px solid var(--line); background: var(--bg-2); color: var(--ink);
  transition: border-color .3s, box-shadow .3s;
}
.gal-search input:focus { border-color: var(--flame-deep); box-shadow: 0 0 0 3px rgba(232,70,28,.15); }
.gal-search svg { position: absolute; left: 15px; top: 50%; transform: translateY(-50%);
  width: 15px; height: 15px; stroke: var(--ink-faint); fill: none; stroke-width: 1.8; }
.gal-select {
  padding: 12px 16px; border-radius: 999px; border: 1px solid var(--line);
  background: var(--bg-2); font: 600 12.5px/1 var(--body); color: var(--ink-soft);
}
.gal-count { font: 500 12px/1 var(--body); letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-faint); margin-left: auto; }
.gal-chips { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 14px; }
.gal-chips button {
  display: inline-flex; align-items: center;
  min-height: max(38px, var(--tap-min));
  padding: 0 18px; border-radius: 999px; border: 1px solid var(--line); background: transparent;
  font: 600 11.5px/1 var(--body); color: var(--ink-soft);
  transition: color .3s var(--ease), border-color .3s var(--ease), background-color .3s var(--ease);
}
.gal-chips button:hover { border-color: var(--flame-deep); color: var(--acc-sm); }
.gal-chips button.on { background: var(--band); border-color: var(--band); color: var(--ivory); }
.gal-chips button em { font-style: normal; opacity: .55; margin-left: 6px; font-size: 10.5px; }

/* ---------- virtualised masonry ---------- */
.gal-viewport { position: relative; width: 100%; }
.gal-sizer { width: 100%; pointer-events: none; }
.gal-tile {
  position: absolute; top: 0; left: 0; padding: 0; border: 0; background: var(--bg-3);
  border-radius: 3px; overflow: hidden; cursor: pointer; will-change: transform;
  contain: layout paint style;
}
.gal-tile .gal-ph { position: absolute; inset: 0; display: block; }
.gal-tile .gal-ph .scene { width: 100%; height: 100%; }
.gal-tile .gal-ph .scene svg { width: 100%; height: 100%; }
.gal-tile img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block;
  opacity: 0; transform: scale(1.03);
  transition: opacity .55s var(--ease-out), transform .8s var(--ease-out);
}
.gal-tile.is-ready img { opacity: 1; transform: none; }
.gal-tile .gal-cap {
  position: absolute; inset: auto 0 0 0; z-index: 3; padding: 34px 14px 12px;
  font: 500 10px/1.4 var(--body); letter-spacing: .1em; text-transform: uppercase;
  color: rgba(252,248,240,.9); text-align: left;
  background: linear-gradient(transparent, rgba(8,12,20,.85));
  opacity: 0; transform: translateY(6px);
  transition: opacity .4s var(--ease), transform .4s var(--ease);
}
.gal-tile:hover .gal-cap, .gal-tile:focus-visible .gal-cap { opacity: 1; transform: none; }
.gal-tile::after {
  content: ""; position: absolute; inset: 0; box-shadow: inset 0 0 0 0 var(--flame);
  transition: box-shadow .35s var(--ease); pointer-events: none;
}
.gal-tile:hover::after, .gal-tile:focus-visible::after { box-shadow: inset 0 0 0 2px var(--flame); }
.gal-empty { padding: 80px 0; text-align: center; color: var(--ink-faint); display: none; }
.gal-empty.on { display: block; }

/* ---------- timeline view ---------- */
.years { display: grid; gap: 2px; background: var(--line); }
.year-band { background: var(--bg); }
.year-band summary {
  list-style: none; cursor: pointer; padding: 24px 0; display: flex; align-items: baseline;
  gap: 20px; transition: color .3s;
}
.year-band summary::-webkit-details-marker { display: none; }
.year-band summary:hover { color: var(--acc); }
.year-band .y { font-family: var(--display); font-size: clamp(28px,3.4vw,46px); font-weight: 600;
  line-height: 1; color: var(--acc); letter-spacing: -.03em; }
.year-band .lbl { font: 600 11px/1 var(--body); letter-spacing: .2em; text-transform: uppercase;
  color: var(--ink-faint); }
.year-band .rule { flex: 1; height: 1px; background: var(--line); }
.year-band .n { font: 600 11px/1 var(--body); letter-spacing: .14em; color: var(--ink-faint); }
.year-band summary i { font-style: normal; color: var(--acc); font-size: 20px; line-height: 1;
  transition: transform .4s var(--ease); }
.year-band[open] summary i { transform: rotate(45deg); }
.year-strip { display: flex; gap: 12px; overflow-x: auto; padding: 0 0 22px; scroll-snap-type: x proximity; }
.year-strip .ys {
  flex: none; width: 210px; aspect-ratio: 4/3; border-radius: 3px; overflow: hidden;
  scroll-snap-align: start; border: 0; padding: 0; cursor: pointer; position: relative;
  background: var(--bg-3); transition: transform .45s var(--ease-out);
}
.year-strip .ys:hover { transform: translateY(-4px); }
.year-strip .ys .scene, .year-strip .ys img { width: 100%; height: 100%; object-fit: cover; display: block; }
.year-strip .more {
  flex: none; width: 210px; display: grid; place-items: center; border: 1px dashed var(--line);
  border-radius: 3px; font: 600 12px/1.4 var(--body); color: var(--ink-soft); background: transparent;
  text-align: center; padding: 20px;
}

/* ---------- view switch ---------- */
.viewswitch { display: inline-flex; border: 1px solid var(--line); border-radius: 999px; overflow: hidden; }
.viewswitch button { padding: 10px 18px; border: 0; background: transparent;
  font: 600 11.5px/1 var(--body); letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-faint); transition: all .3s var(--ease); }
.viewswitch button.on { background: var(--flame); color: #fff; }

/* ---------- lightbox ---------- */
.lb {
  position: fixed; inset: 0; z-index: 9995; display: grid;
  grid-template-rows: auto 1fr auto; background: rgba(8,11,18,.96);
  opacity: 0; visibility: hidden; transition: opacity .4s var(--ease), visibility .4s;
}
.lb.open { opacity: 1; visibility: visible; }
.lb-top { display: flex; justify-content: space-between; align-items: center; gap: 20px;
  padding: 18px clamp(16px,3vw,34px); color: rgba(252,248,240,.7); }
.lb-count { font: 600 11.5px/1 var(--body); letter-spacing: .16em; }
.lb-close, .lb-prev, .lb-next {
  width: 46px; height: 46px; border-radius: 50%; border: 1px solid rgba(252,248,240,.24);
  background: transparent; color: var(--ivory); display: grid; place-items: center;
  transition: background .3s, border-color .3s, transform .3s var(--ease-out);
}
.lb-close:hover, .lb-prev:hover, .lb-next:hover { background: var(--flame); border-color: var(--flame); }
.lb-close:hover { transform: rotate(90deg); }
.lb-body { position: relative; display: grid; grid-template-columns: 64px 1fr 64px;
  align-items: center; gap: 12px; padding-inline: clamp(10px,2vw,26px); min-height: 0; }
.lb-stage { height: 100%; display: grid; place-items: center; min-height: 0; }
.lb-stage img { max-width: 100%; max-height: 74vh; object-fit: contain; border-radius: 3px;
  box-shadow: 0 40px 90px -40px #000; }
.lb-art { width: min(100%, 1100px); aspect-ratio: 3/2; border-radius: 3px; overflow: hidden; }
.lb-art .scene, .lb-art .scene svg { width: 100%; height: 100%; }
.lb-foot { padding: 18px clamp(16px,3vw,34px) 26px; text-align: center; }
.lb-cap { font-family: var(--display); font-size: clamp(17px,1.8vw,22px); color: var(--ivory);
  font-style: italic; }
.lb-meta { font: 500 10.5px/1 var(--body); letter-spacing: .17em; text-transform: uppercase;
  color: var(--acc-gold); margin-top: 10px; }

/* ---------- responsive ---------- */
@media (max-width: 1080px) {
  body .ph-grid { grid-template-columns: 1fr 260px; }
  body .creds-row { grid-template-columns: repeat(2,1fr); }
  body .roles { grid-template-columns: repeat(2,1fr); }
  body .bodies-grid { grid-template-columns: repeat(3,1fr); }
}
@media (max-width: 760px) {
  body .ph-grid { grid-template-columns: 1fr; }
  body .ph .portrait-frame { max-width: 240px; }
  body .roles { grid-template-columns: 1fr; }
  body .bodies-grid { grid-template-columns: repeat(2,1fr); }
  body .gal-bar { position: static; }
  body .gal-count { margin-left: 0; width: 100%; }
  body .lb-body { grid-template-columns: 1fr; }
  body .lb-prev, body .lb-next { position: absolute; top: 50%; transform: translateY(-50%); z-index: 3; }
  body .lb-prev { left: 8px; } body .lb-next { right: 8px; }
}

/* ---------- record ledger ---------- */
.ledger { list-style: none; margin: 0; padding: 0; }
.rec-row {
  display: grid; grid-template-columns: 210px minmax(0,1fr); gap: 40px; align-items: baseline;
  padding: 30px 0; border-top: 1px solid var(--line-lt);
  transition: background .4s var(--ease);
}
.rec-row:last-child { border-bottom: 1px solid var(--line-lt); }
.rec-row:hover { background: rgba(232,70,28,.05); }
.rec-n { display: block; }
.rec-n b {
  display: block; font-family: var(--display); font-weight: 600; line-height: .95;
  font-size: clamp(30px,3.4vw,50px); letter-spacing: -.035em; color: var(--acc-gold);
  font-variant-numeric: tabular-nums;
}
.rec-row:hover .rec-n b { color: var(--acc); }
.rec-n em {
  display: block; font-style: normal; margin-top: 9px;
  font: 600 11px/1 var(--body); letter-spacing: .2em; text-transform: uppercase;
  color: rgba(252,248,240,.62);
}
.rec-b h3 { font-size: clamp(19px,1.9vw,24px); line-height: 1.28; margin-bottom: 8px; }
.rec-b p { font-size: 14.5px; color: rgba(252,248,240,.64); margin: 0; }
.rec-b p em { color: var(--acc-gold); font-style: italic; }
/* ---------- housing ---------- */
.housing { display: grid; grid-template-columns: repeat(3,1fr); gap: 1px; background: var(--line); }
.housing .h-stat { background: var(--bg-2); padding: 34px 28px 38px; }
.housing b {
  display: block; font-family: var(--display); font-weight: 600; line-height: 1;
  font-size: clamp(34px,3.8vw,54px); letter-spacing: -.035em; color: var(--acc);
  font-variant-numeric: tabular-nums;
}
.housing span { display: block; margin-top: 14px; font-size: 14.5px; color: var(--ink-soft); }

.schemes .lbl {
  display: block; font: 600 10.5px/1 var(--body); letter-spacing: .2em;
  text-transform: uppercase; color: var(--ink-faint); margin-bottom: 16px;
}
.withwho-x { display: flex; flex-wrap: wrap; gap: 10px; }
.withwho-x span {
  padding: 12px 20px; border: 1px solid var(--line); border-radius: 999px;
  font: 500 13.5px/1 var(--body); color: var(--ink-soft);
  transition: border-color .35s, color .35s, transform .35s var(--ease-out);
}
.withwho-x span:hover { border-color: var(--flame); color: var(--acc); transform: translateY(-2px); }

@media (max-width: 1080px) {
  body .rec-row { grid-template-columns: 170px minmax(0,1fr); row-gap: 16px; }
  body .housing { grid-template-columns: 1fr; }
}
@media (max-width: 620px) {
  body .rec-row { grid-template-columns: 1fr; gap: 14px; }
}

/* ---------- hero portrait (real photograph) ---------- */
/* The frame is 3:4 but the photograph is a wide stage shot, so a centred
   crop puts the banner in the middle and his head near the bottom edge.
   Biasing the crop upward and slightly left keeps the face in the upper
   third, where a portrait wants it. */
.portrait-photo {
  width: 100%; height: auto; display: block;
  aspect-ratio: 3/4; object-fit: cover; object-position: 42% 26%;
}

/* ---------- archive entrance ----------
   Tiles settle into place the first time they are seen. The delay is set
   per tile by the engine, capped so a full page never feels slow. */
.gal-tile { transition: transform .55s var(--ease-out), opacity .55s var(--ease-out); }
.gal-tile.is-entering {
  opacity: 0;
  transform: translate3d(var(--tx,0), calc(var(--ty,0px) + 34px), 0) scale(.92) !important;
  transition-delay: var(--enter-delay, 0ms);
}
.no-motion .gal-tile.is-entering { opacity: 1; transform: none !important; }

/* ---------- pagination ---------- */
.gal-pager {
  display: flex; justify-content: center; align-items: center; gap: 6px;
  flex-wrap: wrap; margin-top: 42px;
}
.gal-pager:empty { display: none; }
.gal-pager button {
  min-width: var(--tap); min-height: var(--tap); padding: 0 12px; border-radius: 999px;
  border: 1px solid var(--line); background: transparent; color: var(--ink-soft);
  font: 600 13.5px/1 var(--body); font-variant-numeric: tabular-nums;
  transition: color .3s var(--ease), border-color .3s var(--ease), background-color .3s var(--ease);
}
.gal-pager button:hover:not(:disabled) { border-color: var(--flame-deep); color: var(--acc-sm); }
.gal-pager button.on {
  background: var(--flame-btn); border-color: var(--flame-btn); color: #fff;
  box-shadow: 0 8px 20px -10px rgba(201,58,21,.9);
}
.gal-pager button:disabled { opacity: .3; cursor: not-allowed; }
.gal-pager .pg-arrow { font-size: 20px; line-height: 1; }
.gal-pager .pg-gap { color: var(--ink-faint); padding: 0 4px; }

/* Photographs uncover rather than fade: the image slides up from behind
   its own frame and settles from a slight scale.

   This was written with clip-path first, which was a mistake twice over.
   Animating clip-path repaints rather than composites — on full-bleed
   images it cost about 30fps of scrolling — and Chrome's
   IntersectionObserver counts clip-path as visibility, so an element
   hidden that way never reports as intersecting and never triggers the
   reveal that would have shown it. Transform and opacity have neither
   problem: the container clips, the image only ever moves. */
[data-reveal] { overflow: hidden; }
[data-reveal] img {
  transform: translateY(14%) scale(1.06);
  opacity: 0;
  will-change: transform, opacity;
}
[data-reveal].is-shown img {
  transform: translateY(0) scale(1);
  opacity: 1;
  transition: transform 1.05s var(--ease-out), opacity .75s var(--ease);
}
/* released once it has played, so nothing keeps a layer it no longer needs */
[data-reveal].is-done img { will-change: auto; }

/* the role cards lean toward the cursor, like the carnival page's */
/* the 3D context is created on enter and dropped on leave, rather than
   sitting on every card for the whole page's life */
.role-card { transition: transform .5s var(--ease-out), box-shadow .5s var(--ease); }
.role-card.is-tilting {
  transform: perspective(900px)
             rotateX(calc(var(--ry, 0) * -1deg))
             rotateY(calc(var(--rx, 0) * 1deg))
             translateY(-4px);
  box-shadow: var(--sh-2); will-change: transform;
}

@media (prefers-reduced-motion: reduce) {
  [data-reveal] img { transform: none; opacity: 1; transition: none; }
  .role-card.is-tilting { transform: none; }
}
@media (hover: none) { .role-card { transform: none; } }
