/* ==========================================================================
   AMIN APAC — profile.css
   The full-profile page reached from index.html's focus panel. Additive: loads
   on top of base.css (tokens, buttons, tiles, the profile body) and
   immersive-hero.css (the transparent header over a dark stage). Nothing in here
   is needed by any other page.

   Three heroes share one page. body[data-hero] picks which one renders:
     a  the plate     — the member's country as an extruded relief plate,
                        the map from index.html landing on one country
     b  the picture   — full-bleed member imagery, or the rendered network
                        map cropped to their corner of it when none is held
     c  the type      — no picture; the name, the services, the coordinates,
                        on the member's own accent colour

   Contents
   01. Page shell, header, sticky bar
   02. Hero, shared: stage, copy, data rail, entrance
   03. Hero A: the plate
   04. Hero B: the picture
   05. Hero C: the type
   06. Body additions (directory rail, closer)
   07. Responsive
   08. Reduced motion
   ========================================================================== */

/* ==========================================================================
   01. Page shell
   ========================================================================== */
body.pf{background:var(--white)}
/* The header from index-v6 - absolute, transparent, inverted wordmark - is
   what immersive-hero.css gives body.v2. All three heroes are dark, so it holds. */
body.pf .site-header .btn{margin-left:auto}

/* Sticky bar. Appears once the hero has scrolled away, so the name, the
   clock and the two actions never leave the screen. Real markup filled by
   script; without the script it stays hidden rather than half-built. */
.pf-bar{
  position:fixed;top:0;left:0;right:0;z-index:30;
  background:rgb(255 255 255 / .86);
  -webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);
  border-bottom:1px solid var(--line);
  transform:translateY(-100%);opacity:0;
  transition:transform .32s cubic-bezier(.2,.7,.2,1),opacity .28s ease;
  pointer-events:none;
}
.pf-bar.is-on{transform:none;opacity:1;pointer-events:auto}
.pf-bar .wrap{min-height:60px;display:flex;align-items:center;gap:var(--s4)}
.pf-bar-id{display:flex;align-items:center;gap:var(--s3);min-width:0}
.pf-bar-id b{font-weight:500;font-size:16px;color:var(--black);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pf-bar-id span{color:var(--gray);font-size:13px;white-space:nowrap}
.pf-bar-clock{margin-left:auto;display:flex;align-items:baseline;gap:6px;color:var(--gray);font-size:13px;white-space:nowrap}
.pf-bar-clock b{font-family:var(--mono);font-weight:600;font-size:14px;color:var(--black);font-variant-numeric:tabular-nums}
.pf-bar .btn{padding:8px 18px;font-size:14px}

/* --- The member switcher -------------------------------------------------
   The bar's identity, made a disclosure button. It has to read as the same
   lockup it replaced when it is resting - the bar's job is to say who you are
   reading, not to advertise a control - and only declare itself as pressable
   on hover, focus and while open. Hence no border and no fill at rest, and a
   caret rather than a chevron button: one small mark is enough to say there is
   more here, next to a name that is already the subject. */
.pf-switch-wrap{position:relative;min-width:0}
.pf-switch{
  display:flex;align-items:center;gap:var(--s3);min-width:0;
  margin:0;padding:6px 10px 6px 6px;
  border:0;border-radius:10px;background:transparent;
  font:inherit;color:inherit;text-align:left;cursor:pointer;
  transition:background-color 160ms ease-in-out;
}
.pf-switch:hover,.pf-switch[aria-expanded="true"]{background:var(--pale)}
.pf-switch:focus-visible{outline:var(--focus-w) solid var(--purple);outline-offset:var(--focus-off)}
/* Name over city, so the button stays the height of the tile rather than
   setting the bar's height from a single long line. */
.pf-switch-id{display:grid;min-width:0}
.pf-switch-id b{
  font-weight:500;font-size:16px;line-height:20px;color:var(--black);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.pf-switch-id span{
  color:var(--gray);font-size:13px;line-height:18px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.pf-switch-caret{
  flex:none;width:8px;height:8px;margin-left:2px;
  border-right:1.5px solid var(--ash);border-bottom:1.5px solid var(--ash);
  transform:translateY(-2px) rotate(45deg);
  transition:transform 200ms cubic-bezier(.2,.7,.3,1);
}
.pf-switch:hover .pf-switch-caret{border-color:var(--plum)}
.pf-switch[aria-expanded="true"] .pf-switch-caret{transform:translateY(2px) rotate(225deg)}

/* The panel. Hung off the switcher rather than the bar, so it stays under the
   name it belongs to instead of under the whole window. */
.pf-dir{
  position:absolute;top:calc(100% + 8px);left:0;z-index:2;
  width:320px;max-width:calc(100vw - var(--s5) * 2);
  padding:var(--s4);
  background:var(--white);border:1px solid var(--line);border-radius:16px;
  box-shadow:0 18px 44px rgb(20 22 26 / .16), 0 2px 8px rgb(20 22 26 / .06);
}
.pf-dir[hidden]{display:none}
.pf-dir .dir-h{
  margin:0 0 var(--s3);padding:0 var(--s3);
  font-size:15px;font-weight:600;line-height:22px;color:var(--black);
}
/* The list keeps base.css's cap and its own scroll: the panel hangs from a
   fixed bar, so its height is the window's to give, not the page's.

   The fade is doing real work here, not decoration. The panel opens centred on
   the member you are reading, so it almost always opens mid-list with a row cut
   across the top and bottom edges - and a name sliced clean through by a hard
   border reads as a rendering fault rather than as more list. Masked, the same
   cut row reads as continuing past the edge, which is what it does. Eleven rows
   never fit the cap, so there is no state where this dims a list that has
   nothing hidden. */
.pf-dir .dirlist{
  max-height:min(60vh,360px);
  -webkit-mask-image:linear-gradient(180deg,transparent 0,#000 16px,#000 calc(100% - 16px),transparent 100%);
  mask-image:linear-gradient(180deg,transparent 0,#000 16px,#000 calc(100% - 16px),transparent 100%);
}
/* .pf-dir-map - the "View the network map" footer link - is gone (2026-09-03).
   The panel is a switcher: you open it to change which member you are reading,
   and every one of the eleven rows does that. A twelfth action that leaves the
   page entirely, sitting under a hairline where the list ends, read as the
   list's conclusion rather than as a separate offer, and the map is already
   reachable from the masthead's Members link. The list now runs to the panel's
   own padding, which is also what makes the bottom fade legible as "more
   list". */

/* --- The directory, A to Z ------------------------------------------------
   Shared by the bar's panel and the gutter rail: one builder writes this
   markup into both, so the two can never say different things.

   It was grouped by city, west to east, on a hairline with a stop per city -
   the same figure index.html's hero rail draws over the map. On the map that
   axis is the argument. In a sidebar of eleven names it was ten headings
   wrapped around eleven rows, and the reader who opens this list is looking a
   name up, not reading the geography again. The line, the stops and the city
   headings go with it; the row itself now carries the whole interaction. */
.dirglist{position:relative}

/* The row, one line. It drops the city for the same reason it always has: the
   name is what is being scanned for, and a second line under each of eleven
   rows doubles the list to restate a fact the profile opens with. base.css
   spans the tile across two rows, which is why this resets the span as well as
   the columns. */
.dirrow-flat{
  grid-template-columns:26px minmax(0,1fr) auto;
  align-items:center;gap:0 var(--s3);
  padding:7px var(--s3);
  transition:background-color 180ms ease-in-out,transform 180ms cubic-bezier(.22,.68,.28,1);
}
.dirrow-flat + .dirrow-flat{margin-top:3px}
.dirrow-flat .tile{
  grid-column:1;grid-row:1;width:26px;height:26px;font-size:10px;
  transition:transform 180ms cubic-bezier(.22,.68,.28,1);
}
/* Wraps, never truncates. base.css clips .dirrow b to one line because those
   rows have a city underneath to keep clear of; these have nothing below them
   to protect. "Span Media Communicat..." is the whole name minus the part that
   identifies it. */
.dirrow-flat b{
  grid-column:2;font-size:14px;line-height:20px;letter-spacing:-.005em;
  white-space:normal;overflow:visible;text-overflow:clip;
}
/* Hover: the fill from base.css, and the row steps toward the pointer with the
   mark a shade ahead of the name. Two pixels - enough to register as picked
   up, not enough to reflow the column next to it. */
a.dirrow-flat:hover{transform:translateX(2px)}
a.dirrow-flat:hover .tile{transform:scale(1.06)}
a.dirrow-flat:active{transform:translateX(1px)}
.dirg-now{
  grid-column:3;
  color:var(--ac,var(--plum));font-size:11px;font-style:normal;font-weight:500;
  letter-spacing:.04em;text-transform:uppercase;white-space:nowrap;
}
@media (prefers-reduced-motion:reduce){
  a.dirrow-flat:hover,a.dirrow-flat:hover .tile,a.dirrow-flat:active{transform:none}
}

/* --- The gutter rail ------------------------------------------------------
   The wrap is 1400px wide, this column is 216px, and it has to clear the wrap
   on both sides or it lands on the reading column - which is 1400 + 2*(216+20)
   = 1872px of window before it can exist at all. Below that it is not shown
   and the bar's panel is the whole mechanism. That is a real limit, not a
   preference: there is no width between "fits" and "overlaps the text". */
.pf-gutter{display:none}

@media (min-width:1880px){
  .pf-gutter{
    display:block;position:fixed;z-index:20;
    /* 248 = the rail's own 216 plus the 56px gap the columns inside the wrap now
       use, less the wrap's 24px padding. The rail sits outside the container, so
       nothing lines it up automatically - this is what keeps its distance from
       the text equal to the text's distance from the sidebar. */
    left:max(var(--s6), calc((100vw - 1400px) / 2 - 248px));
    top:50%;translate:0 -50%;
    width:216px;
    max-height:calc(100vh - 140px);overflow-y:auto;overscroll-behavior:contain;
    scrollbar-width:none;
    opacity:0;transform:translateX(-8px);pointer-events:none;
    /* visibility, not opacity alone. At opacity:0 the rail is still a layer -
       it answers hit-tests to anything that asks, and it is still "visible" to
       anything reasoning about the page. Delayed on the way out so the fade
       still plays, instant on the way in. */
    visibility:hidden;
    transition:opacity .3s ease,transform .34s cubic-bezier(.22,.68,.28,1),visibility 0s linear .3s;
  }
  .pf-gutter::-webkit-scrollbar{width:0}
  .pf-gutter.is-on{
    opacity:1;transform:none;pointer-events:auto;
    visibility:visible;transition-delay:0s,0s,0s;
  }
  .pf-gutter-h{
    display:flex;flex-direction:column;gap:2px;
    margin:0 0 var(--s4);padding-left:var(--s2);
    color:var(--ash);font-size:11px;font-weight:500;
    letter-spacing:.08em;text-transform:uppercase;line-height:16px;
  }
  /* Marks out here too. They were dropped when this column was 180px: a 24px
     tile and its gap took a third of the line and pushed the long names onto
     two lines, and a rail running two lines an agency is 21 lines deep and
     loses Auckland off the bottom of the window. The column pays for them
     instead - 216px, which is 22px of mark, 10px of gap and 160px of name,
     enough for "Communications" on its own second line and no more. The extra
     36px comes off the margin, not the reading column: the rail only ever
     appears on windows that already had it spare.

     The name wraps rather than truncating when it must: a rail reading "Span
     Media Communi…" has failed at the one job it has. */
  .pf-gutter .dirrow-flat{
    grid-template-columns:22px minmax(0,1fr);
    gap:0 10px;padding:6px var(--s3);
  }
  .pf-gutter .dirrow-flat + .dirrow-flat{margin-top:2px}
  .pf-gutter .dirrow-flat .tile{
    grid-column:1;grid-row:1;width:22px;height:22px;font-size:9px;
    align-self:start;margin-top:1px;
  }
  .pf-gutter .dirrow-flat b{grid-column:2;font-size:13px;line-height:19px}
  .pf-gutter .dirg-now{grid-column:2;grid-row:2;font-size:10px}
}

@media (max-width:900px){
  /* Under the bar edge to edge. At this width the wrap's padding is the only
     thing between the panel and the window, and a 320px card floating inside
     it reads as detached from the bar it belongs to. */
  .pf-switch-wrap{position:static}
  .pf-dir{
    top:calc(100% + 1px);left:0;right:0;width:auto;max-width:none;
    border-radius:0 0 16px 16px;border-left:0;border-right:0;
  }
}

/* ==========================================================================
   02. Hero, shared
   ========================================================================== */
.pf-hero{
  position:relative;isolation:isolate;overflow:hidden;
  min-height:100vh;min-height:100svh;
  display:grid;align-items:end;
  color:var(--white);
  background:#14161A;
}
.pf-hero::after{
  /* The ramp closes the hero the way it closes the masthead and the footer. */
  content:"";position:absolute;left:0;right:0;bottom:0;height:3px;background:var(--ramp);z-index:5;
}
.pf-stage{position:absolute;inset:0;z-index:0;overflow:hidden}
.pf-scrim{position:absolute;inset:0;z-index:1;pointer-events:none}

/* The country as a word. Behind everything, enormous, nearly invisible - it
   is the environment the name stands in, not a second title. */
/* --len is the country's character count, set by the script. A word set in
   vw alone overflows the window the moment the country has a long name -
   AUSTRALIA lost its A and NEW ZEALAND lost NEW - so the size is also capped
   at the width one line of --len characters can actually occupy. 0.70em is
   the measured average advance for this face at this weight and tracking. */
.pf-ghost{
  position:absolute;z-index:1;left:50%;top:44%;transform:translate(-50%,-50%);
  margin:0;white-space:nowrap;pointer-events:none;user-select:none;
  font-size:min(clamp(64px,17vw,260px), calc(92vw / (var(--len,9) * .70)));
  font-weight:600;line-height:1;
  letter-spacing:.06em;text-transform:uppercase;
  color:transparent;
  -webkit-text-stroke:1px rgb(255 255 255 / .16);
  opacity:0;transition:opacity 1.2s ease .4s;
}
.pf-hero.is-in .pf-ghost{opacity:1}

/* The copy. Anchored to the foot of the hero, left, like the page's own h1. */
.pf-copy{position:relative;z-index:2;width:100%;padding-top:140px;padding-bottom:clamp(40px,7vh,72px)}
.pf-copy .wrap{display:grid;gap:var(--s5)}
.pf-eyebrow{
  display:flex;flex-wrap:wrap;align-items:center;gap:var(--s3) var(--s5);
  margin:0;font-size:12px;font-weight:600;letter-spacing:.16em;text-transform:uppercase;color:var(--lavender);
}

.pf-id{display:flex;align-items:flex-end;gap:var(--s5);min-width:0}
.pf-id .tile{flex:none;width:72px;height:72px;font-size:24px;box-shadow:0 12px 40px rgb(0 0 0 / .5)}
.pf-name{
  margin:0;color:var(--white);
  font-size:clamp(48px,8.4vw,132px);font-weight:500;line-height:.94;letter-spacing:-.02em;
  text-wrap:balance;max-width:11ch;
}
/* Each word rises on its own line-box so the entrance can stagger them. */
.pf-name .w{display:inline-block;overflow:hidden;vertical-align:bottom;padding-bottom:.06em;margin-bottom:-.06em}
.pf-name .w i{display:inline-block;font-style:normal;transform:translateY(110%);transition:transform .9s cubic-bezier(.2,.8,.2,1)}
.pf-hero.is-in .pf-name .w i{transform:none}
.pf-tagline{margin:0;max-width:44ch;font-size:clamp(17px,1.6vw,22px);line-height:1.45;color:rgb(255 255 255 / .82)}

/* The data rail: one line of the facts a stranger asks first. */
.pf-rail{
  display:flex;flex-wrap:wrap;align-items:center;gap:var(--s3) var(--s6);
  margin:0;padding:var(--s4) 0 0;list-style:none;
  border-top:1px solid rgb(255 255 255 / .14);
  font-size:14px;color:rgb(255 255 255 / .74);
}
.pf-rail li{display:inline-flex;align-items:baseline;gap:7px;white-space:nowrap}
.pf-rail li b{color:var(--white);font-weight:500}
.pf-rail li.mono{
  align-items:center;gap:10px;
  font-size:13px;line-height:20px;letter-spacing:.01em;
  font-variant-numeric:tabular-nums;
}
.pf-rail li.mono b{font-family:var(--mono);font-size:13px;letter-spacing:.01em}
.pf-rail li.mono span{font-size:12px;color:rgb(255 255 255 / .6)}
.pf-rail li.pf-rail-disc{gap:8px}
.pf-rail .chip{
  display:inline-block;padding:7px 15px;border-radius:999px;
  /* Filled to match the actions below it: this chip sat outlined a few pixels
     from two buttons that are now solid, and it was the last keyline in the
     hero. The 1px is paid back in the padding, so the height is unchanged. */
  border:0;background:rgb(255 255 255 / .16);color:var(--white);
  font-size:13px;font-weight:500;line-height:18px;letter-spacing:.005em;
}
.pf-rail .pf-rail-loc{margin-left:auto}
.pf-actions{display:flex;flex-wrap:wrap;gap:var(--s3);margin-top:var(--s2)}
/* No background override here any more: .btn-on-dark-ghost carries its own
   translucent fill now, and re-transparenting it would put the one outline-less
   invisible button back on the darkest surface on the site. */

/* Entrance: staged so the picture arrives before the words. */
.pf-copy > .wrap > *{opacity:0;transform:translateY(14px);transition:opacity .7s ease,transform .8s cubic-bezier(.2,.8,.2,1)}
.pf-hero.is-in .pf-copy > .wrap > *{opacity:1;transform:none}
.pf-hero.is-in .pf-copy > .wrap > :nth-child(1){transition-delay:.35s}
.pf-hero.is-in .pf-copy > .wrap > :nth-child(2){transition-delay:.45s}
.pf-hero.is-in .pf-copy > .wrap > :nth-child(3){transition-delay:.62s}
.pf-hero.is-in .pf-copy > .wrap > :nth-child(4){transition-delay:.78s}
.pf-hero.is-in .pf-copy > .wrap > :nth-child(5){transition-delay:.9s}
/* The name is the exception: its box shows at once, its words rise inside it. */
.pf-hero .pf-id{opacity:1!important;transform:none!important}
.pf-hero .pf-id .tile{opacity:0;transform:scale(.8);transition:opacity .6s ease .5s,transform .7s cubic-bezier(.2,.8,.2,1) .5s}
.pf-hero.is-in .pf-id .tile{opacity:1;transform:none}
.pf-hero.is-in .pf-name .w:nth-child(1) i{transition-delay:.25s}
.pf-hero.is-in .pf-name .w:nth-child(2) i{transition-delay:.33s}
.pf-hero.is-in .pf-name .w:nth-child(3) i{transition-delay:.41s}
.pf-hero.is-in .pf-name .w:nth-child(4) i{transition-delay:.49s}
.pf-hero.is-in .pf-name .w:nth-child(n+5) i{transition-delay:.57s}

/* Scroll cue: the page below is the real profile, so say so. */
.pf-cue{
  position:absolute;right:var(--s6);bottom:var(--s6);z-index:3;
  display:inline-flex;align-items:center;gap:10px;
  color:rgb(255 255 255 / .7);font-size:12px;letter-spacing:.12em;text-transform:uppercase;text-decoration:none;
}
.pf-cue i{width:1px;height:36px;background:linear-gradient(to bottom,transparent,var(--white));animation:pfCue 1.8s ease-in-out infinite}
.pf-cue:hover{color:var(--white)}
@keyframes pfCue{0%{transform:scaleY(0);transform-origin:top}50%{transform:scaleY(1);transform-origin:top}51%{transform-origin:bottom}100%{transform:scaleY(0);transform-origin:bottom}}

/* ==========================================================================
   03. Hero A: the plate
   ========================================================================== */
.pf-hero-a .pf-stage{
  perspective:2600px;perspective-origin:50% 40%;
  background:
    radial-gradient(120% 80% at 50% 16%, #2A2E36 0%, transparent 62%),
    radial-gradient(80% 55% at 62% 92%, #23262D 0%, transparent 72%),
    #14161A;
}
/* Ground: a graticule that shares the plate's tilt, so the plate reads as
   standing on something rather than pasted on a gradient. */
.pf-ground{
  position:absolute;left:50%;top:52%;width:200vw;height:120vh;
  transform:translate(-50%,-50%) rotateX(var(--tilt,58deg)) rotateZ(var(--spin,-8deg));
  background-image:
    linear-gradient(rgb(255 255 255 / .05) 1px, transparent 1px),
    linear-gradient(90deg, rgb(255 255 255 / .05) 1px, transparent 1px);
  background-size:120px 120px;
  -webkit-mask-image:radial-gradient(60% 55% at 50% 50%, #000 20%, transparent 80%);
  mask-image:radial-gradient(60% 55% at 50% 50%, #000 20%, transparent 80%);
  opacity:0;transition:opacity 1.6s ease .2s;
}
.pf-hero.is-in .pf-ground{opacity:1}

/* The plate: right of centre, so the copy on the left and the country on the
   right make one composition; the scroll parallax lifts it up and away. */
.pf-plate{
  position:absolute;left:62%;top:46%;
  width:min(58vw,1000px,150vh);
  transform:
    translate(-50%,-50%)
    translateY(calc(var(--sy,0) * -1px))
    rotateX(var(--tilt,58deg)) rotateZ(var(--spin,-8deg))
    scale(var(--zoom,1));
  transform-style:preserve-3d;
  opacity:0;transition:opacity 1.1s ease .1s;
}
.pf-hero.is-in .pf-plate{opacity:1}
/* The drift is on an inner wrapper: the outer transform is the pose and the
   parallax, and animating it would fight both. */
.pf-plate-in{
  position:relative;width:100%;transform-style:preserve-3d;
  animation:pfDrift 9s ease-in-out infinite alternate;
}
@keyframes pfDrift{from{transform:translateZ(0) translateY(0)}to{transform:translateZ(14px) translateY(-8px)}}
.pf-plate-svg{display:block;width:100%;height:auto;overflow:visible}
.pf-plate-svg svg{display:block;width:100%;height:100%;overflow:visible;isolation:isolate}

.pf-ctx use{fill:url(#pfCtx);stroke:#4A505B;stroke-width:.6;vector-effect:non-scaling-stroke}
.pf-shadow{filter:url(#pfSoft);opacity:.55}
.pf-shadow use{fill:#000}
.pf-walls use{stroke:none}
.pf-face use{fill:url(#pfFace)}
.pf-relief{mix-blend-mode:overlay;opacity:.88;pointer-events:none}
.pf-inner use{fill:none;vector-effect:none;filter:url(#pfInner)}
.pf-inner .pf-in-lo{stroke:#1C0A3A;stroke-opacity:.55}
.pf-inner .pf-in-hi{stroke:#fff;stroke-opacity:.38}
.pf-edge use{
  fill:none;stroke:#fff;stroke-width:1.5;stroke-linejoin:round;
  vector-effect:non-scaling-stroke;filter:url(#pfGlow);
  stroke-dasharray:1;stroke-dashoffset:1;
  transition:stroke-dashoffset 1.6s cubic-bezier(.4,0,.2,1) .35s;
}
.pf-hero.is-in .pf-edge use{stroke-dashoffset:0}

/* The pin sits in the plate's space: it tilts with the country it marks. */
.pf-pins{position:absolute;inset:0;transform-style:preserve-3d;pointer-events:none}
.pf-pin{
  position:absolute;transform:translate(-50%,-50%);
  display:flex;align-items:center;gap:8px;
  opacity:0;transition:opacity .6s ease 1.5s;
}
.pf-hero.is-in .pf-pin{opacity:1}
.pf-pin-dot{
  position:relative;width:12px;height:12px;border-radius:50%;
  background:#2FE39B;box-shadow:0 0 0 3px rgb(47 227 155 / .28),0 0 18px rgb(47 227 155 / .8);
}
.pf-pin-dot::after{
  content:"";position:absolute;inset:-8px;border-radius:50%;
  border:1.5px solid rgb(47 227 155 / .6);animation:pfPulse 2.2s ease-out infinite;
}
@keyframes pfPulse{from{transform:scale(.5);opacity:1}to{transform:scale(1.8);opacity:0}}
.pf-pin-label{
  padding:5px 11px;border-radius:999px;
  background:#2FE39B;color:#04140D;font-size:13px;font-weight:600;letter-spacing:.01em;white-space:nowrap;
  box-shadow:0 6px 18px rgb(0 0 0 / .45);
}
.pf-hero-a .pf-scrim{
  background:
    linear-gradient(20deg, rgba(20,22,26,.96) 0%, rgba(20,22,26,.7) 28%, transparent 56%),
    linear-gradient(180deg, rgba(20,22,26,.55) 0%, transparent 30%);
}
/* Right-aligned rather than centred: the copy owns the left of this hero, so
   the word runs out from behind the plate instead of under the headline. */
.pf-hero-a .pf-ghost{left:auto;right:4vw;transform:translateY(-50%);top:38%}

/* ==========================================================================
   04. Hero B: the picture
   ========================================================================== */
.pf-hero-b .pf-stage{background:#0E0720}
.pf-img{
  position:absolute;inset:0;overflow:hidden;
  transform:translateY(calc(var(--sy,0) * .35px));
  transition:opacity 1.4s ease;opacity:0;
}
.pf-hero.is-in .pf-img{opacity:1}
/* object-position alone could not crop this: the network map is 1400x768 and
   the stage is about the same shape, so cover scaled it to fit and there was
   no overflow left to shift - every member got the whole of Asia-Pacific
   rather than their corner of it. --zoom does the cropping and the origin
   says which corner, so object-position is only the fallback for a real
   photograph, where a crop is not wanted. */
.pf-img img{
  display:block;width:100%;height:100%;object-fit:cover;object-position:var(--pos,50% 50%);
  transform-origin:var(--pos,50% 50%);
  --z:var(--zoom,1.06);
  animation:pfBurns 26s ease-in-out infinite alternate;
  filter:saturate(.85) contrast(1.05);
}
@keyframes pfBurns{
  from{transform:scale(var(--z))}
  to{transform:scale(calc(var(--z) * 1.08))}
}
/* The grade. Every picture, whoever supplied it, is brought onto the brand:
   a plum multiply to sink the shadows, a purple screen to lift the highlights,
   and a lavender wash on top so the type sits on one colour family rather
   than on whatever the photograph happens to be. */
.pf-img::before{
  content:"";position:absolute;inset:0;
  background:linear-gradient(160deg, #3A2364 0%, #1A0E33 60%, #0E0720 100%);
  mix-blend-mode:multiply;opacity:.72;
}
.pf-img::after{
  content:"";position:absolute;inset:0;
  background:radial-gradient(70% 70% at 70% 30%, rgb(144 79 255 / .55) 0%, transparent 70%);
  mix-blend-mode:screen;opacity:.8;
}
/* Three layers, and the middle one is the one that matters. The copy here is
   centred, so it lands wherever the picture happens to be brightest - on the
   Tokyo shot that is a glass tower directly behind the eyebrow, and the line
   became unreadable. The first layer is a pool under the copy column that
   travels with it, so every picture, bright or dark, hands the type a ground. */
.pf-hero-b .pf-scrim{
  background:
    radial-gradient(58% 42% at 50% 62%, rgba(14,7,32,.78) 0%, rgba(14,7,32,.45) 55%, transparent 100%),
    linear-gradient(180deg, rgba(14,7,32,.6) 0%, transparent 26%, transparent 44%, rgba(14,7,32,.94) 100%),
    linear-gradient(90deg, rgba(14,7,32,.45) 0%, transparent 45%, rgba(14,7,32,.45) 100%);
}
/* The reference's stack, refitted: the country above, hollow; the name below,
   solid. It sits well clear of the eyebrow - at 38% the two lines landed on
   top of each other - and the wide tracking gets its own advance in the fit. */
.pf-hero-b .pf-ghost{
  top:24%;left:50%;transform:translate(-50%,-50%);
  font-weight:400;letter-spacing:.32em;
  -webkit-text-stroke:1px rgb(255 255 255 / .55);
  font-size:min(clamp(28px,6vw,86px), calc(88vw / (var(--len,9) * .95)));
}
.pf-hero-b .pf-copy .wrap{justify-items:center;text-align:center}
.pf-hero-b .pf-eyebrow{justify-content:center;width:100%}
.pf-hero-b .pf-id{flex-direction:column;align-items:center;gap:var(--s5)}
.pf-hero-b .pf-name{max-width:14ch;text-align:center;font-weight:600;font-size:clamp(52px,9.6vw,152px)}
.pf-hero-b .pf-tagline{text-align:center;max-width:52ch}
.pf-hero-b .pf-rail{justify-content:center;width:min(100%,900px)}
.pf-hero-b .pf-rail .pf-rail-loc{margin-left:0}
.pf-hero-b .pf-actions{justify-content:center}
.pf-credit{
  position:absolute;left:var(--s6);bottom:var(--s6);z-index:3;margin:0;
  color:rgb(255 255 255 / .5);font-size:11px;letter-spacing:.08em;text-transform:uppercase;
}
.pf-credit:empty{display:none}

/* ==========================================================================
   05. Hero C: the type
   ========================================================================== */
.pf-hero-c{background:var(--ac,#3A2364)}
.pf-hero-c .pf-stage{
  background:
    radial-gradient(90% 70% at 85% 10%, rgb(255 255 255 / .14) 0%, transparent 60%),
    radial-gradient(70% 60% at 10% 100%, rgb(0 0 0 / .45) 0%, transparent 65%),
    linear-gradient(180deg, color-mix(in srgb, var(--ac,#3A2364) 84%, #fff) 0%, var(--ac,#3A2364) 45%, color-mix(in srgb, var(--ac,#3A2364) 55%, #000) 100%);
}
/* A dot field, drifting: the constellation this network is drawn as. */
.pf-dots{
  position:absolute;inset:-20%;
  background-image:radial-gradient(rgb(255 255 255 / .22) 1.2px, transparent 1.6px);
  background-size:34px 34px;
  transform:translateY(calc(var(--sy,0) * .25px)) rotate(8deg);
  -webkit-mask-image:radial-gradient(60% 60% at 70% 40%, #000 0%, transparent 100%);
  mask-image:radial-gradient(60% 60% at 70% 40%, #000 0%, transparent 100%);
  animation:pfDots 40s linear infinite;
}
@keyframes pfDots{from{background-position:0 0}to{background-position:340px 340px}}
/* The monogram, enormous, as a watermark - the member's initials rather than
   their logo. Blowing a logo out to white produced a smear rather than a mark
   (every agency draws for a light ground, and brightness(10) is not a
   recolour), and it collided with a long name. Initials scale, stay legible
   at any size, and are the same letters the tile shows. Top right, well above
   the name's line, and behind everything. */
.pf-mark{
  position:absolute;right:3vw;top:16%;
  display:grid;place-items:center;
  opacity:0;transition:opacity 1.2s ease .3s;
  pointer-events:none;
}
.pf-hero.is-in .pf-mark{opacity:1}
.pf-mark i{
  font-style:normal;font-size:clamp(120px,22vw,340px);font-weight:600;line-height:.8;
  letter-spacing:-.05em;
  color:transparent;-webkit-text-stroke:1.5px rgb(255 255 255 / .2);
}
.pf-hero-c .pf-scrim{background:linear-gradient(180deg, rgba(0,0,0,.25) 0%, transparent 30%, transparent 60%, rgba(0,0,0,.35) 100%)}
.pf-hero-c .pf-ghost{display:none}
.pf-hero-c .pf-name{font-weight:600;font-size:clamp(56px,10.5vw,168px);letter-spacing:-.035em}
.pf-hero-c .pf-id .tile{display:none}
/* The service ticker: one discipline at a time, the way a wordmark cycles. */
.pf-ticker{
  display:flex;align-items:baseline;gap:var(--s3);margin:0;
  font-size:clamp(20px,2.4vw,32px);font-weight:400;color:rgb(255 255 255 / .9);line-height:1.2;
}
.pf-ticker .pf-tk-l{color:rgb(255 255 255 / .55)}
.pf-ticker .pf-tk{position:relative;display:inline-grid;min-width:8ch}
.pf-ticker .pf-tk span{
  grid-area:1/1;white-space:nowrap;font-weight:600;
  opacity:0;transform:translateY(60%);
  transition:opacity .45s ease,transform .55s cubic-bezier(.2,.8,.2,1);
}
.pf-ticker .pf-tk span.is-on{opacity:1;transform:none}
.pf-ticker .pf-tk span.is-off{opacity:0;transform:translateY(-60%)}
.pf-coords{
  margin:0;font-family:var(--mono);font-size:13px;letter-spacing:.12em;color:rgb(255 255 255 / .65);
}
.pf-hero-c .pf-rail{border-top-color:rgb(255 255 255 / .22)}
.pf-hero-c .btn-on-dark{background:var(--white);color:var(--ac,#3A2364)}
.pf-hero-c .btn-on-dark:hover{background:var(--pale)}

/* ==========================================================================
   06. Body additions
   ========================================================================== */
/* The strip under the hero sits on white; its counted figures read fine there. */
.pf .statbar-plain{border-top:0}
/* The directory's max-height override lived here, to un-cap the list inside the
   sidebar card. The list is in the switcher panel now and the cap is what keeps
   that panel inside the window, so base.css's is left to stand. */
/* The closer: brief them, or keep walking the network. */
/* The newsletter band that briefly lived in this section moved into the footer,
   where index.html keeps its copy - see footer.css for the treatment. The rules
   that dressed it here went with it. .pf-closer itself stays: nothing on the
   profile uses it today, and it is the closing block's styling, not the
   closing block. */

.pf-closer{background:var(--plum);color:var(--white);position:relative;overflow:hidden}
.pf-closer::before{content:"";position:absolute;left:0;right:0;top:0;height:3px;background:var(--ramp)}
.pf-closer .wrap{padding-top:var(--sec-lg);padding-bottom:var(--sec-lg);display:grid;grid-template-columns:1.2fr 1fr;gap:var(--s10);align-items:center}
.pf-closer h2{margin:0;color:var(--white);font-size:clamp(28px,3.4vw,44px);font-weight:500;line-height:1.1;letter-spacing:-.01em}
.pf-closer p{margin:var(--s4) 0 0;color:var(--lavender);font-size:17px;line-height:1.55;max-width:48ch}
.pf-closer .pf-closer-cta{margin-top:var(--s6);display:flex;flex-wrap:wrap;gap:var(--s3)}
.pf-step{display:grid;gap:var(--s3)}
.pf-step a{
  display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:var(--s4);
  padding:var(--s4) var(--s5);border-radius:var(--r-md,12px);
  background:rgb(255 255 255 / .06);border:1px solid rgb(255 255 255 / .12);
  color:var(--white);text-decoration:none;transition:background .2s ease,border-color .2s ease,transform .2s ease;
}
.pf-step a:hover{background:rgb(255 255 255 / .11);border-color:rgb(255 255 255 / .28);transform:translateY(-1px)}
.pf-step .pf-step-k{font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--lavender)}
.pf-step .pf-step-t{display:grid;min-width:0}
.pf-step .pf-step-t b{font-weight:500;font-size:16px}
.pf-step .pf-step-t span{font-size:13px;color:var(--lavender)}
.pf-step .tile{box-shadow:none}
.pf-step .pf-step-go{font-size:18px;color:var(--lavender)}

/* ==========================================================================
   07. Responsive
   ========================================================================== */
@media (max-width:1100px){
  .pf-plate{left:60%;width:min(70vw,900px)}
}
@media (max-width:900px){
  .pf-copy{padding-top:110px}
  .pf-hero-a .pf-plate{left:50%;top:34%;width:min(96vw,760px)}
  .pf-hero-a .pf-copy{padding-top:min(70vh,520px)}
  .pf-hero-a .pf-scrim{background:linear-gradient(180deg, transparent 30%, rgba(20,22,26,.85) 62%, rgba(20,22,26,.98) 100%)}
  .pf-hero-a .pf-ghost{right:auto;left:50%;top:22%;transform:translate(-50%,-50%);font-size:clamp(48px,14vw,120px)}
  .pf-rail .pf-rail-loc{margin-left:0}
  .pf-mark{right:-20vw;top:30%;width:70vw}
  .pf-closer .wrap{grid-template-columns:1fr}
  /* The clock goes; the button stays. It used to be the outlined Visit that
     was dropped here, because the filled Brief beside it kept the bar useful
     without it. Brief is gone, so dropping this one now would leave the bar
     with no action at all on the widths that have the least room for a second
     route to it. */
  .pf-bar .pf-bar-clock{display:none}
  .pf-cue{display:none}
}
@media (max-width:600px){
  .pf-id .tile{width:52px;height:52px;font-size:18px}
  .pf-name{font-size:clamp(40px,12vw,64px)}
  .pf-rail{gap:var(--s2) var(--s4);font-size:13px}
}

/* ==========================================================================
   08. Reduced motion
   ========================================================================== */
@media (prefers-reduced-motion:reduce){
  .pf-plate-in,.pf-img img,.pf-dots,.pf-pin-dot::after,.pf-cue i{animation:none}
  .pf-hero *{transition-duration:.01ms!important;transition-delay:0s!important}
  .pf-edge use{stroke-dashoffset:0}
  .pf-plate,.pf-img,.pf-dots{transform:none}
}

/* ==========================================================================
   The work viewer
   Built by js/work-lightbox.js. Three 4:3 crops are a sample of the work; the
   same three uncropped are the work. Nothing here is loaded that the grid did
   not already load.
   ========================================================================== */
/* The thumbnail is a button now, so it has to stop looking like one. */
.work-open{
  display:block;padding:0;width:100%;text-align:left;
  font:inherit;color:inherit;cursor:zoom-in;
  appearance:none;
}
.work-open:focus-visible{outline:var(--focus-w) solid var(--purple);outline-offset:var(--focus-off)}

.lbx{
  position:fixed;inset:0;z-index:60;
  display:grid;place-items:center;
  padding:clamp(16px,4vw,56px);
  opacity:0;transition:opacity .2s ease;
}
.lbx.is-on{opacity:1}
.lbx-scrim{
  position:absolute;inset:0;cursor:zoom-out;
  background:rgb(14 15 19 / .92);
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
}
.lbx-fig{
  position:relative;margin:0;display:grid;gap:var(--s4);
  justify-items:center;max-width:min(1200px,100%);
}
.lbx-img{
  display:block;max-width:100%;
  /* Room for the caption and the close control, whichever way the picture is
     shaped. object-fit:contain is the whole point of the viewer - the grid
     already has the cropped reading. */
  max-height:calc(100vh - 220px);
  width:auto;height:auto;object-fit:contain;
  border-radius:var(--r-md);
  box-shadow:0 40px 90px -40px rgb(0 0 0 / .9);
  transform:scale(.985);transition:transform .24s cubic-bezier(.2,.8,.2,1);
}
.lbx.is-on .lbx-img{transform:none}
.lbx-cap{
  display:grid;gap:6px;justify-items:center;text-align:center;
  max-width:64ch;color:rgb(255 255 255 / .82);font-size:15px;line-height:1.5;
}
.lbx-meta{
  display:flex;gap:var(--s3);align-items:baseline;
  font-size:12px;letter-spacing:.1em;text-transform:uppercase;
  color:rgb(255 255 255 / .45);
}
.lbx-case{
  margin-top:2px;color:var(--lavender);font-size:14px;
  text-decoration:none;border-bottom:1px solid rgb(211 185 255 / .4);
  padding-bottom:1px;
}
.lbx-case:hover{border-bottom-color:var(--lavender)}
.lbx-case:focus-visible{outline:var(--focus-w) solid var(--lavender);outline-offset:var(--focus-off)}
.lbx-case[hidden]{display:none}

.lbx-btn{
  position:absolute;z-index:2;
  width:48px;height:48px;border-radius:50%;
  display:grid;place-items:center;cursor:pointer;
  font-size:20px;line-height:1;
  /* Filled, no keyline. The disc is 48px of translucent white over a dimmed
     photograph - the fill is what makes it a target, and the hairline round it
     was a second edge saying the same thing. .16 rest, .28 hover: the same
     ladder .btn-on-dark-ghost uses on the other dark surfaces. */
  color:var(--white);background:rgb(255 255 255 / .16);
  border:0;
  transition:background .18s ease;
}
.lbx-btn:hover{background:rgb(255 255 255 / .28)}
.lbx-btn:focus-visible{outline:var(--focus-w) solid var(--lavender);outline-offset:var(--focus-off)}
.lbx-prev{left:clamp(8px,2vw,28px);top:50%;transform:translateY(-50%)}
.lbx-next{right:clamp(8px,2vw,28px);top:50%;transform:translateY(-50%)}
.lbx-close{right:clamp(8px,2vw,28px);top:clamp(8px,2vw,28px)}

/* The page behind does not scroll while the viewer is open. */
body.has-lbx{overflow:hidden}

@media (max-width:640px){
  .lbx-img{max-height:calc(100vh - 260px)}
  .lbx-prev{left:8px}
  .lbx-next{right:8px}
  .lbx-case{
  margin-top:2px;color:var(--lavender);font-size:14px;
  text-decoration:none;border-bottom:1px solid rgb(211 185 255 / .4);
  padding-bottom:1px;
}
.lbx-case:hover{border-bottom-color:var(--lavender)}
.lbx-case:focus-visible{outline:var(--focus-w) solid var(--lavender);outline-offset:var(--focus-off)}
.lbx-case[hidden]{display:none}

.lbx-btn{width:42px;height:42px}
}
@media (prefers-reduced-motion:reduce){
  .lbx,.lbx-img{transition:none}
  .lbx-img{transform:none}
}
