
/* ============================================================
   THE ARCHIVES
   Premium rules of the room: one thing at a time, plenty of black
   around it, and nothing moves unless the visitor asked it to.
   ============================================================ */

.ar-hero{padding:clamp(56px,11vh,132px) 0 clamp(30px,5vh,56px)}
.ar-hero .lab{display:block;margin-bottom:clamp(16px,2.4vw,26px)}
.ar-hero .h-xl{margin-bottom:clamp(22px,3vw,38px)}
/* The second line sits in outline so the page has one accent and not two.
   -webkit-text-stroke is the only reliable outline text on the web; the
   colour fallback keeps it readable if a browser ignores the stroke. */
.ar-em{color:transparent;-webkit-text-stroke:2px var(--lime);
  paint-order:stroke fill}
@supports not (-webkit-text-stroke:1px red){ .ar-em{color:var(--lime)} }

/* ---------- filter rail ---------- */
/* The nav is already sticky at top:0, so the rail has to start where the nav
   ends or the two sit on top of each other. --nav-h is written by JS from the
   nav's real height, because the nav shrinks as you scroll; the 82px fallback
   is its measured height so the page is still correct with no JS at all. */
.ar-railwrap{position:sticky;top:var(--nav-h,82px);z-index:40;padding:14px 0 13px;
  background:rgba(5,5,5,.82);backdrop-filter:blur(16px);
  border-block:1px solid var(--line)}
.ar-rail{display:flex;flex-wrap:wrap;gap:clamp(6px,1.4vw,22px);align-items:center}
.ar-f{font-family:var(--lab);font-weight:700;text-transform:uppercase;
  letter-spacing:.2em;font-size:clamp(10px,.82vw,12px);color:var(--mute);
  font-stretch:72%;font-variation-settings:"wdth" var(--lab-wdth,72);
  padding:8px 2px 9px;position:relative;transition:color .3s var(--ease);white-space:nowrap}
.ar-f i{font-style:normal;font-size:.82em;opacity:.5;margin-left:.45em}
/* The underline is the whole interaction. It grows from the left so the
   rail reads as a rule being drawn rather than a button being pressed. */
.ar-f::after{content:"";position:absolute;left:0;right:0;bottom:0;height:2px;
  background:var(--c,var(--lime));transform:scaleX(0);transform-origin:left;
  transition:transform .42s var(--ease)}
.ar-f:hover{color:var(--bone)}
.ar-f.on{color:var(--bone)}
.ar-f.on::after{transform:scaleX(1)}
.ar-f.on i{opacity:.75}

/* ---------- the grid ---------- */
/* CSS columns rather than a row grid on purpose. A row grid leaves ragged
   gaps under short tiles; columns pack tight with no JS measuring and no
   layout thrash when the filter runs. Reading order goes down each column,
   which is the right order for a gallery and the wrong one for prose. */
.ar-wrap{padding:clamp(34px,6vw,76px) 0 clamp(60px,10vw,128px)}
.ar-grid{column-count:3;column-gap:clamp(22px,3.1vw,52px)}
.ar-t{display:block;width:100%;padding:0;margin:0 0 clamp(22px,3.1vw,52px);
  break-inside:avoid;position:relative;overflow:hidden;background:var(--panel);
  text-align:left;cursor:zoom-in;isolation:isolate}
.ar-t img{width:100%;height:auto;
  filter:saturate(.92) contrast(1.02);
  transform:scale(1.001);
  transition:transform .8s var(--ease),filter .5s var(--ease)}
.ar-t::after{content:"";position:absolute;inset:0;pointer-events:none;
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.07);
  transition:box-shadow .4s var(--ease)}
.ar-t:hover img,.ar-t:focus-visible img{transform:scale(1.035);filter:none}
.ar-t:hover::after,.ar-t:focus-visible::after{box-shadow:inset 0 0 0 1px var(--c,var(--lime))}

/* Caption rides in from under the frame. It carries the accent only on the
   project name so the tile never turns into a colour block. */
.ar-cap{position:absolute;left:0;right:0;bottom:0;z-index:1;
  padding:34px 16px 14px;display:block;
  background:linear-gradient(180deg,transparent,rgba(5,5,5,.92) 62%);
  transform:translateY(101%);opacity:0;
  transition:transform .5s var(--ease),opacity .4s var(--ease)}
.ar-t:hover .ar-cap,.ar-t:focus-visible .ar-cap{transform:none;opacity:1}
.ar-cap b{display:block;font-family:var(--lab);font-weight:700;text-transform:uppercase;
  letter-spacing:.18em;font-size:11px;color:var(--c,var(--lime));
  font-stretch:72%;font-variation-settings:"wdth" var(--lab-wdth,72)}
.ar-cap em{display:block;font-style:normal;font-size:14px;line-height:1.35;
  color:var(--bone);margin-top:4px}

.ar-t[hidden]{display:none}
.ar-empty{font-family:var(--lab);text-transform:uppercase;letter-spacing:.2em;
  font-size:12px;color:var(--mute);padding:60px 0;text-align:center;
  font-stretch:72%;font-variation-settings:"wdth" var(--lab-wdth,72)}
.ar-empty[hidden]{display:none}

/* ---------- closing ---------- */
.ar-cta{padding:clamp(56px,9vw,120px) 0 clamp(70px,11vw,150px);
  border-top:1px solid var(--line)}
.ar-cta .lede{margin:clamp(18px,2.4vw,30px) 0 clamp(26px,3.4vw,42px)}
.ar-ctabtns{display:flex;flex-wrap:wrap;gap:12px}

/* ---------- lightbox ---------- */
.ar-lb{position:fixed;inset:0;z-index:130;display:grid;place-items:center;
  padding:clamp(16px,4vw,58px)}
.ar-lb[hidden]{display:none}
.ar-lb-veil{position:absolute;inset:0;background:rgba(3,2,6,.94);
  backdrop-filter:blur(10px);opacity:0;transition:opacity .34s var(--ease)}
.ar-lb.on .ar-lb-veil{opacity:1}
.ar-lb-fig{position:relative;margin:0;max-width:100%;max-height:100%;
  display:flex;flex-direction:column;align-items:center;gap:14px;
  transform:scale(.975);opacity:0;transition:transform .4s var(--ease),opacity .32s var(--ease)}
.ar-lb.on .ar-lb-fig{transform:none;opacity:1}
.ar-lb-fig img{max-width:100%;max-height:78vh;width:auto;height:auto;
  box-shadow:0 40px 120px -40px rgba(0,0,0,.9)}
.ar-lb-cap{text-align:center}
.ar-lb-cap b{display:block;font-family:var(--lab);font-weight:700;text-transform:uppercase;
  letter-spacing:.2em;font-size:11px;color:var(--lime);
  font-stretch:72%;font-variation-settings:"wdth" var(--lab-wdth,72)}
.ar-lb-cap em{display:block;font-style:normal;font-size:15px;color:var(--mute);margin-top:5px}
.ar-lb-x{position:absolute;top:clamp(10px,2vw,22px);right:clamp(10px,2vw,22px);
  width:44px;height:44px;border:1px solid var(--line);border-radius:12px;
  display:grid;place-items:center;font-size:24px;line-height:1;color:var(--bone);
  background:rgba(5,5,5,.6);transition:.24s var(--ease);z-index:2}
.ar-lb-x:hover{background:var(--pink);color:#050505;border-color:var(--pink);transform:rotate(90deg)}
.ar-lb-nav{position:absolute;top:50%;margin-top:-26px;width:52px;height:52px;
  border:1px solid var(--line);border-radius:50%;display:grid;place-items:center;
  font-size:19px;color:var(--bone);background:rgba(5,5,5,.6);
  transition:.24s var(--ease);z-index:2}
.ar-lb-nav:hover{background:var(--lime);color:#050505;border-color:var(--lime)}
.ar-lb-nav.prev{left:clamp(8px,2vw,26px)}
.ar-lb-nav.next{right:clamp(8px,2vw,26px)}
.ar-lb-n{position:absolute;bottom:clamp(12px,2.4vw,26px);left:50%;transform:translateX(-50%);
  font-family:var(--lab);letter-spacing:.24em;font-size:11px;color:var(--mute);
  font-stretch:72%;font-variation-settings:"wdth" var(--lab-wdth,72);z-index:2}

/* ---------- narrower ---------- */
@media (max-width:1040px){
  .ar-grid{column-count:2}
}
@media (max-width:680px){
  /* One column on a phone. Two would make every piece too small to judge,
     which defeats the point of an archive. */
  .ar-grid{column-count:1}
  .ar-em{-webkit-text-stroke-width:1.5px}
  .ar-rail{flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none;
    -webkit-overflow-scrolling:touch;margin-inline:calc(var(--pad)*-1);
    padding-inline:var(--pad)}
  .ar-rail::-webkit-scrollbar{display:none}
  .ar-lb-nav{width:44px;height:44px;margin-top:-22px}
  .ar-lb-fig img{max-height:70vh}
}
/* No hover on touch, so the caption is simply always there. */
@media (hover:none){
  .ar-cap{transform:none;opacity:1;
    background:linear-gradient(180deg,transparent,rgba(5,5,5,.88) 58%)}
  .ar-t img{filter:none}
}
@media (prefers-reduced-motion:reduce){
  .ar-t img,.ar-cap,.ar-f::after,.ar-lb-veil,.ar-lb-fig{transition:none}
}

/* ---------- living background ---------- */
/* Fixed, so it sits still while the grid scrolls over it. That reads as
   depth: the work moves, the light behind it does not. z-index 0 with the
   grid at 1 keeps it behind every tile and in front of nothing else. */
.ar-plasma{position:fixed;inset:0;z-index:0;pointer-events:none;overflow:hidden}
.ar-plasma canvas{
  position:absolute;inset:-12%;width:124%;height:124%;
  /* The canvas is a tenth of screen size, so the browser's own bilinear
     upscale has already done most of the smoothing for free. A small blur
     finishes it. A big one looked no better and cost several times more,
     because a full viewport blur is the single most expensive thing you can
     ask a compositor for.
     No mix-blend-mode either. Over a #050505 page, screen blending is very
     nearly the same picture as plain alpha, and dropping it saves a whole
     compositing pass on every frame. */
  filter:blur(16px) saturate(1.3);
  opacity:var(--plasma-op,.44);
  transform:translateZ(0);
  will-change:opacity;
}
/* Marble gets veining laid over the colour field. The turbulence is a static
   SVG filter, so it costs nothing per frame; the plasma moving underneath is
   what makes the veins look like they are drifting. */
.ar-plasma[data-mode="marble"]::after{
  content:"";position:absolute;inset:0;
  background:url("data:image/svg+xml;utf8,\
<svg xmlns='http://www.w3.org/2000/svg' width='600' height='600'>\
<filter id='v'><feTurbulence type='fractalNoise' baseFrequency='0.009 0.017' numOctaves='4' seed='7'/>\
<feColorMatrix type='saturate' values='0'/>\
<feComponentTransfer><feFuncA type='table' tableValues='0 0.55 0 0.5 0'/></feComponentTransfer></filter>\
<rect width='600' height='600' filter='url(%23v)'/></svg>");
  background-size:900px 900px;mix-blend-mode:overlay;opacity:.5;
}

/* The grid has to sit above the light, and the tiles have to stay opaque so
   the plasma only ever shows in the gutters.
   .ar-railwrap is deliberately NOT in this list. It is position:sticky, and
   listing it here set position:relative instead, which silently un-stuck the
   filter bar: it scrolled away with the page instead of parking under the
   nav. Sticky makes its own stacking context, so it only needs the z-index,
   which it already has. */
.ar-wrap,.ar-hero,.ar-cta{position:relative;z-index:1}
.ar-t{background:var(--void)}

/* ---------- glowing rim ---------- */
/* Two layers doing two jobs. The inset line is the crisp edge that says
   "this one". The outer bloom is the glow, and because it is a box-shadow it
   spills past overflow:hidden, which a pseudo-element could not do. Each
   tile already carries its category colour in --c, so the rim is that
   category's colour with nothing extra to wire up. */
.ar-t{transition:box-shadow .45s var(--ease)}
.ar-t:hover,.ar-t:focus-visible{
  box-shadow:0 0 0 1px var(--c,var(--lime)),
             0 0 26px -2px var(--c,var(--lime)),
             0 0 62px -14px var(--c,var(--lime));
}
.ar-t::after{transition:box-shadow .45s var(--ease)}
.ar-t:hover::after,.ar-t:focus-visible::after{
  box-shadow:inset 0 0 0 1px var(--c,var(--lime)),
             inset 0 0 30px -16px var(--c,var(--lime));
}
/* While one tile is lit the rest step back, so the glow reads as a spotlight
   rather than everything competing at once. */
.ar-grid:hover .ar-t:not(:hover) img{opacity:.62;filter:saturate(.6) contrast(1.02)}
.ar-t img{transition:transform .8s var(--ease),filter .5s var(--ease),opacity .5s var(--ease)}

@media (prefers-reduced-motion:reduce){
  .ar-t,.ar-t::after,.ar-t img{transition:none}
}

/* ---------- hero art ---------- */
/* Four of her own marks, drifting at different rates. Each one is two copies
   of the same file stacked: a dim one that is always there, and a saturated
   one revealed only inside a circle that follows the cursor. That is the
   same flashlight the homepage uses, so the two pages feel related rather
   than merely similar.
   mix-blend-mode:screen is what cuts them out. Every one of these sits on a
   near-black background, and screen drops black to nothing, so they float
   with no masking work and no transparent PNGs to ship. */
.ar-art{position:absolute;inset:0;z-index:-1;pointer-events:none;overflow:hidden}
.ar-art i{position:absolute;display:block}
.ar-art img{position:absolute;inset:0;width:100%;height:100%;object-fit:contain}
/* mix-blend-mode:screen used to live here. It was how the artwork hid its own
   black background against the page. The art is cut out properly now, so the
   blend only served to wash the colour out against the plasma. */
.ar-art .a-dark{opacity:.2;filter:grayscale(.55) brightness(.85)}
.ar-art .a-lit{opacity:0;filter:saturate(1.3) contrast(1.05);
  -webkit-mask-image:radial-gradient(circle var(--hr,330px) at var(--hx,-999px) var(--hy,-999px),
    #000 0%,rgba(0,0,0,.7) 44%,transparent 72%);
  mask-image:radial-gradient(circle var(--hr,330px) at var(--hx,-999px) var(--hy,-999px),
    #000 0%,rgba(0,0,0,.7) 44%,transparent 72%);
  -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
  will-change:mask-position;transition:opacity .25s var(--ease)}
html.x-live .ar-art .a-lit{opacity:.92}

/* Placement. Kept to the right and the edges so the headline and the lede
   never have to compete with a wing. */
.ar-art .p1{right:4%;  top:2%;   width:min(30vw,320px);aspect-ratio:640/405;transform:rotate(-5deg)}
.ar-art .p2{right:24%; top:34%;  width:min(21vw,225px);aspect-ratio:450/541;transform:rotate(4deg)}
.ar-art .p3{right:2%;  bottom:-4%;width:min(25vw,270px);aspect-ratio:540/552;    transform:rotate(-8deg)}
.ar-art .p4{right:40%; top:8%;   width:min(15vw,160px);aspect-ratio:320/605;     transform:rotate(7deg);opacity:.75}

/* Parallax and fade, driven by the scroll position rather than a scroll
   event listener. The browser runs these off the main thread, so the hero
   stays smooth even with the plasma painting behind it. Each piece moves at
   its own rate, which is what makes it read as depth instead of a single
   sheet sliding. */
/* scroll() rather than view(). view() measures an element entering the
   viewport, and the hero is already in it when the page loads, so half the
   animation had run before anyone scrolled and the art started out sitting
   above the fold. scroll(root) measures the page scroll itself, which is the
   thing actually being reacted to: nothing at 0, gone by 620px. */
@supports ((animation-timeline: scroll()) and (animation-range: 0px 100px)){
  @media (prefers-reduced-motion: no-preference){
    .ar-art i{animation:linear both;animation-timeline:scroll(root block);animation-range:0 620px}
    .ar-art .p1{animation-name:artP1}
    .ar-art .p2{animation-name:artP2}
    .ar-art .p3{animation-name:artP3}
    .ar-art .p4{animation-name:artP4}
    @keyframes artP1{from{transform:translateY(0) rotate(-5deg) scale(1);opacity:1}
                     to  {transform:translateY(-190px) rotate(-1deg) scale(.9);opacity:0}}
    @keyframes artP2{from{transform:translateY(0) rotate(4deg) scale(1);opacity:1}
                     to  {transform:translateY(-320px) rotate(10deg) scale(.86);opacity:0}}
    @keyframes artP3{from{transform:translateY(0) rotate(-8deg) scale(1);opacity:1}
                     to  {transform:translateY(-120px) rotate(-3deg) scale(.94);opacity:0}}
    @keyframes artP4{from{transform:translateY(0) rotate(7deg) scale(1);opacity:.75}
                     to  {transform:translateY(-400px) rotate(16deg) scale(.8);opacity:0}}
    /* The words go with them, a little slower, so the whole header lifts
       away rather than the art leaving the type behind. */
    .ar-hero .shell{animation:heroLift linear both;animation-timeline:scroll(root block);
      animation-range:0 540px}
    @keyframes heroLift{from{transform:none;opacity:1}
                        to{transform:translateY(-64px);opacity:0}}
  }
}
@media (max-width:900px){
  .ar-art .p2,.ar-art .p4{display:none}
  .ar-art .p1{width:44vw;right:-4%;top:0}
  .ar-art .p3{width:38vw;right:-6%;bottom:-2%}
  .ar-art .a-dark{opacity:.15}
}
@media (prefers-reduced-motion: reduce){
  .ar-art .a-lit{display:none}
  .ar-art .a-dark{opacity:.14}
}

/* ---------- filter rail: docking ---------- */
/* Once the hero has gone, the rail joins the nav and the two read as one
   bar. The seam between them is what made it look like two floating strips
   before, so docking kills the rail's own top border and lets the nav's
   blur run straight through. A sentinel div above the rail tells JS when to
   flip the class, which is cheaper and steadier than measuring scroll. */
.ar-dock-sentinel{position:absolute;left:0;right:0;height:1px;pointer-events:none}
.ar-railwrap{transition:background .35s var(--ease),border-color .35s var(--ease),
  padding .3s var(--ease)}
.ar-railwrap.docked{
  background:rgba(5,5,5,.9);
  border-top-color:transparent;
  padding-top:9px;padding-bottom:10px;
  box-shadow:0 14px 34px -22px rgba(0,0,0,.9);
}
.ar-railwrap.docked .ar-f{font-size:clamp(10px,.78vw,11px)}
/* A hairline in the section's own colour, so the docked bar still tells you
   where you are once the big headline is off screen. */
.ar-railwrap.docked::after{content:"";position:absolute;left:0;bottom:0;height:2px;
  width:100%;background:linear-gradient(90deg,var(--lime),var(--pink),var(--cyan),
    var(--orange),var(--purple),var(--yellow));opacity:.5}

/* ---------- mobile: side rail instead of a scrolling strip ---------- */
/* A horizontal strip you have to swipe sideways hides its own contents, and
   people do not discover it. On a phone the sections move to a fixed column
   on the right, always visible, thumb-reachable, out of the way of the work. */
.ar-side{display:none}
@media (max-width:680px){
  .ar-railwrap{display:none}
  .ar-side{display:flex;position:fixed;right:8px;top:50%;transform:translateY(-50%);
    z-index:45;flex-direction:column;gap:5px;align-items:flex-end;
    padding:9px 7px;border-radius:16px;
    background:rgba(5,5,5,.72);backdrop-filter:blur(14px);
    border:1px solid var(--line)}
  .ar-side button{display:flex;align-items:center;gap:7px;padding:5px 3px 5px 8px;
    font-family:var(--lab);font-weight:700;text-transform:uppercase;
    letter-spacing:.14em;font-size:9px;color:var(--mute);
    font-stretch:72%;font-variation-settings:"wdth" 72;
    transition:color .25s var(--ease)}
  /* Label collapsed to nothing until the section is the active one, so the
     column stays a thin strip of dots and only the current one spells
     itself out. */
  .ar-side button em{font-style:normal;max-width:0;overflow:hidden;white-space:nowrap;
    opacity:0;transition:max-width .34s var(--ease),opacity .26s var(--ease)}
  .ar-side button i{display:block;width:9px;height:9px;border-radius:50%;flex:none;
    background:transparent;box-shadow:inset 0 0 0 1.5px var(--c,var(--mute));
    transition:background .25s var(--ease),box-shadow .25s var(--ease)}
  .ar-side button.on{color:var(--bone)}
  .ar-side button.on em{max-width:112px;opacity:1}
  .ar-side button.on i{background:var(--c,var(--lime));
    box-shadow:inset 0 0 0 1.5px var(--c,var(--lime)),0 0 12px -1px var(--c,var(--lime))}
  .ar-side button b{font-weight:700;font-size:8px;opacity:.5;margin-left:1px}
}
@media (prefers-reduced-motion:reduce){
  .ar-railwrap,.ar-side button em,.ar-side button i{transition:none}
}

/* ---------- deck tiles ---------- */
/* A deck is one tile, not twenty. The stack behind the cover is a pseudo
   element rather than real card divs: nothing to lay out, nothing to load,
   and it cannot fall out of step with the page count. */
.ar-deck{cursor:pointer}
.ar-stack{position:absolute;inset:0;pointer-events:none;z-index:0}
.ar-stack::before,.ar-stack::after{content:"";position:absolute;inset:0;
  background:var(--panel2);box-shadow:inset 0 0 0 1px rgba(255,255,255,.08);
  transition:transform .5s var(--ease)}
.ar-stack::before{transform:translate(7px,7px)}
.ar-stack::after{transform:translate(3.5px,3.5px)}
.ar-deck:hover .ar-stack::before{transform:translate(13px,13px)}
.ar-deck:hover .ar-stack::after{transform:translate(6.5px,6.5px)}
.ar-deck img{position:relative;z-index:1}

/* page count badge */
.ar-pg{position:absolute;top:10px;left:10px;z-index:3;
  font-family:var(--lab);font-weight:700;text-transform:uppercase;letter-spacing:.16em;
  font-size:10px;color:#050505;background:var(--c,var(--lime));padding:5px 9px 4px;
  font-stretch:72%;font-variation-settings:"wdth" var(--lab-wdth,72)}

/* The peek: three real pages sliding in along the bottom on hover, so you
   can tell a deck worth opening from one that is not before you open it. */
.ar-peek{position:absolute;left:0;right:0;bottom:0;z-index:2;display:flex;gap:5px;
  padding:9px;transform:translateY(102%);opacity:0;pointer-events:none;
  background:linear-gradient(180deg,transparent,rgba(5,5,5,.9) 44%);
  transition:transform .48s var(--ease),opacity .36s var(--ease)}
.ar-peek img{flex:1;min-width:0;height:62px;object-fit:cover;object-position:top center;
  box-shadow:0 0 0 1px rgba(255,255,255,.12)}
.ar-deck:hover .ar-peek,.ar-deck:focus-visible .ar-peek{transform:none;opacity:1}
/* The caption and the peek would land on top of each other, so on a deck the
   caption sits above the peek strip instead of at the bottom edge. */
.ar-deck .ar-cap{padding-bottom:88px}
@media (hover:none){
  .ar-peek{display:none}
  .ar-deck .ar-cap{padding-bottom:14px}
}

/* ---------- the stack reader ---------- */
.ar-sk{position:fixed;inset:0;z-index:135;display:grid;place-items:center;
  padding:clamp(12px,3vw,46px)}
.ar-sk[hidden]{display:none}
.ar-sk-veil{position:absolute;inset:0;background:rgba(3,2,6,.95);
  backdrop-filter:blur(12px);opacity:0;transition:opacity .34s var(--ease)}
.ar-sk.on .ar-sk-veil{opacity:1}

/* The cards live in one perspective box. Only a handful are in the DOM at a
   time; the rest are built as you reach them, because a 21 page deck at full
   size is not something to download so somebody can look at page one. */
.ar-sk-box{position:relative;width:min(1080px,100%);height:min(82vh,860px);
  perspective:1800px;transform-style:preserve-3d;
  opacity:0;transform:scale(.97);transition:opacity .3s var(--ease),transform .4s var(--ease)}
.ar-sk.on .ar-sk-box{opacity:1;transform:none}
.ar-sk-card{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  transition:transform .62s var(--ease),opacity .46s var(--ease),filter .5s var(--ease);
  will-change:transform,opacity}
.ar-sk-card img{max-width:100%;max-height:100%;width:auto;height:auto;
  box-shadow:0 34px 90px -34px rgba(0,0,0,.95),0 0 0 1px rgba(255,255,255,.07)}
/* Scrolling sends the top card to the back: it lifts, shrinks away from you
   and fades, then reappears at the bottom of the pile. The stack never
   empties, so you can keep going round. */
.ar-sk-card[data-s="0"]{transform:translate3d(0,0,0) scale(1);opacity:1;z-index:5}
.ar-sk-card[data-s="1"]{transform:translate3d(0,26px,-140px) scale(.94);opacity:.5;z-index:4;filter:blur(.6px)}
.ar-sk-card[data-s="2"]{transform:translate3d(0,48px,-270px) scale(.89);opacity:.26;z-index:3;filter:blur(1.4px)}
.ar-sk-card[data-s="3"]{transform:translate3d(0,66px,-390px) scale(.85);opacity:.11;z-index:2;filter:blur(2.2px)}
.ar-sk-card[data-s="gone"]{transform:translate3d(0,-120px,180px) scale(1.06);opacity:0;z-index:6}
.ar-sk-card[data-s="hide"]{opacity:0;z-index:1;pointer-events:none}

.ar-sk-bar{position:absolute;left:0;right:0;bottom:clamp(8px,2vw,20px);z-index:3;
  display:flex;align-items:center;justify-content:center;gap:16px}
.ar-sk-meta{text-align:center}
.ar-sk-meta b{display:block;font-family:var(--lab);font-weight:700;text-transform:uppercase;
  letter-spacing:.2em;font-size:11px;color:var(--lime);
  font-stretch:72%;font-variation-settings:"wdth" var(--lab-wdth,72)}
.ar-sk-meta em{display:block;font-style:normal;font-size:14px;color:var(--mute);margin-top:3px}
.ar-sk-n{font-family:var(--lab);letter-spacing:.2em;font-size:11px;color:var(--mute);
  font-stretch:72%;font-variation-settings:"wdth" var(--lab-wdth,72);min-width:62px;text-align:center}
.ar-sk-b{width:46px;height:46px;border:1px solid var(--line);border-radius:50%;
  display:grid;place-items:center;font-size:17px;color:var(--bone);
  background:rgba(5,5,5,.6);transition:.22s var(--ease)}
.ar-sk-b:hover{background:var(--lime);color:#050505;border-color:var(--lime)}
.ar-sk-x{position:absolute;top:clamp(8px,2vw,20px);right:clamp(8px,2vw,20px);z-index:4;
  width:44px;height:44px;border:1px solid var(--line);border-radius:12px;
  display:grid;place-items:center;font-size:24px;line-height:1;color:var(--bone);
  background:rgba(5,5,5,.6);transition:.22s var(--ease)}
.ar-sk-x:hover{background:var(--pink);color:#050505;border-color:var(--pink);transform:rotate(90deg)}
/* progress along the top */
.ar-sk-rail{position:absolute;left:0;right:0;top:0;height:2px;z-index:4;background:rgba(255,255,255,.1)}
.ar-sk-rail i{display:block;height:100%;width:0;background:var(--lime);
  transition:width .4s var(--ease)}
.ar-sk-hint{position:absolute;left:50%;top:clamp(14px,3vw,26px);transform:translateX(-50%);
  z-index:4;font-family:var(--lab);letter-spacing:.2em;font-size:10px;color:var(--mute);
  font-stretch:72%;font-variation-settings:"wdth" var(--lab-wdth,72);
  opacity:1;transition:opacity .5s var(--ease);pointer-events:none}
.ar-sk.moved .ar-sk-hint{opacity:0}

@media (max-width:680px){
  .ar-sk{padding:0}
  .ar-sk-box{width:100%;height:100%;border-radius:0}
  .ar-sk-card img{box-shadow:none}
  .ar-sk-bar{gap:10px}
  .ar-sk-meta em{display:none}
}
@media (prefers-reduced-motion:reduce){
  .ar-sk-card,.ar-sk-box,.ar-sk-veil,.ar-stack::before,.ar-stack::after,.ar-peek{transition:none}
  .ar-sk-card[data-s="1"],.ar-sk-card[data-s="2"],.ar-sk-card[data-s="3"]{filter:none}
}

/* ---------- storefront tiles ---------- */
/* Commerce leads with the store itself rather than loose screenshots. The
   tile is the logo on the brand's own ground; clicking it opens the whole
   storefront as one continuous scroll, the way a customer would meet it. */
.ar-store{background:var(--panel)}
.ar-store .ar-logo{position:relative;z-index:1;display:flex;align-items:center;
  justify-content:center;aspect-ratio:4/3;padding:12% 16%}
.ar-store .ar-logo img{width:100%;height:100%;object-fit:contain;
  filter:none;transform:none;transition:transform .7s var(--ease)}
.ar-store:hover .ar-logo img{transform:scale(1.05)}
.ar-store .ar-pg{background:var(--c,var(--lime))}
/* A hint of the pages waiting inside, stacked along the bottom edge. */
.ar-store .ar-strip{position:absolute;left:0;right:0;bottom:0;height:5px;z-index:2;
  display:flex;gap:2px;padding:0 10px 9px}
.ar-store .ar-strip i{flex:1;height:100%;background:var(--c,var(--lime));opacity:.3;
  transition:opacity .4s var(--ease)}
.ar-store:hover .ar-strip i{opacity:.85}
.ar-store .ar-strip i:nth-child(2){transition-delay:.04s}
.ar-store .ar-strip i:nth-child(3){transition-delay:.08s}
.ar-store .ar-strip i:nth-child(4){transition-delay:.12s}
.ar-store .ar-strip i:nth-child(5){transition-delay:.16s}
.ar-store .ar-strip i:nth-child(6){transition-delay:.2s}
.ar-store .ar-strip i:nth-child(7){transition-delay:.24s}

/* ---------- the storefront reader ---------- */
/* A browser inside a browser, on purpose. The chrome is what tells people
   they are looking at a real site rather than a tall picture, and it gives
   the page edges something to sit against. */
.ar-sc{position:fixed;inset:0;z-index:136;display:grid;place-items:center;
  padding:clamp(10px,2.4vw,38px)}
.ar-sc[hidden]{display:none}
.ar-sc-veil{position:absolute;inset:0;background:rgba(3,2,6,.95);backdrop-filter:blur(12px);
  opacity:0;transition:opacity .34s var(--ease)}
.ar-sc.on .ar-sc-veil{opacity:1}

.ar-sc-win{position:relative;width:min(1180px,100%);height:min(88vh,940px);
  display:flex;flex-direction:column;background:var(--panel);
  border:1px solid var(--line);border-radius:14px;overflow:hidden;
  box-shadow:0 46px 130px -40px rgba(0,0,0,.95);
  opacity:0;transform:translateY(12px) scale(.985);
  transition:opacity .3s var(--ease),transform .4s var(--ease)}
.ar-sc.on .ar-sc-win{opacity:1;transform:none}

.ar-sc-bar{flex:none;display:flex;align-items:center;gap:12px;padding:10px 12px;
  border-bottom:1px solid var(--line);background:var(--panel2)}
.ar-sc-dots{display:flex;gap:6px;flex:none}
.ar-sc-dots i{width:11px;height:11px;border-radius:50%;background:#2E2E2E}
.ar-sc-dots i:first-child{background:#FF5F57}
.ar-sc-dots i:nth-child(2){background:#FEBC2E}
.ar-sc-dots i:nth-child(3){background:#28C840}
.ar-sc-url{flex:1;min-width:0;text-align:center;font-family:var(--lab);
  letter-spacing:.14em;text-transform:uppercase;font-size:10px;color:var(--mute);
  font-stretch:72%;font-variation-settings:"wdth" var(--lab-wdth,72);
  background:#050505;border:1px solid var(--line);border-radius:7px;padding:6px 10px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ar-sc-x{flex:none;width:34px;height:34px;border:1px solid var(--line);border-radius:9px;
  display:grid;place-items:center;font-size:20px;line-height:1;color:var(--bone);
  transition:.22s var(--ease)}
.ar-sc-x:hover{background:var(--pink);color:#050505;border-color:var(--pink)}

/* page jump strip */
.ar-sc-tabs{flex:none;display:flex;gap:2px;overflow-x:auto;scrollbar-width:none;
  padding:8px 12px;border-bottom:1px solid var(--line);background:rgba(5,5,5,.7)}
.ar-sc-tabs::-webkit-scrollbar{display:none}
.ar-sc-tabs button{flex:none;font-family:var(--lab);font-weight:700;text-transform:uppercase;
  letter-spacing:.14em;font-size:10px;color:var(--mute);padding:6px 11px;border-radius:7px;
  font-stretch:72%;font-variation-settings:"wdth" var(--lab-wdth,72);
  transition:color .25s var(--ease),background .25s var(--ease);white-space:nowrap}
.ar-sc-tabs button:hover{color:var(--bone)}
.ar-sc-tabs button.on{color:#050505;background:var(--c,var(--lime))}

/* the scrolling page */
.ar-sc-view{flex:1;min-height:0;overflow-y:auto;overflow-x:hidden;background:#fff;
  scroll-behavior:smooth;overscroll-behavior:contain}
.ar-sc-view img{display:block;width:100%;height:auto}
/* A thin rule where one page ends and the next begins, so a seven page
   continuous scroll still reads as seven pages and not one endless one. */
.ar-sc-page{position:relative}
.ar-sc-page+.ar-sc-page::before{content:attr(data-label);position:sticky;top:0;z-index:2;
  display:block;font-family:var(--lab);font-weight:700;text-transform:uppercase;
  letter-spacing:.18em;font-size:10px;color:var(--bone);background:#050505;
  padding:7px 14px;font-stretch:72%;font-variation-settings:"wdth" var(--lab-wdth,72)}

.ar-sc-meta{flex:none;display:flex;align-items:center;justify-content:space-between;
  gap:14px;padding:9px 14px;border-top:1px solid var(--line);background:var(--panel2)}
.ar-sc-meta b{font-family:var(--lab);font-weight:700;text-transform:uppercase;
  letter-spacing:.18em;font-size:11px;color:var(--c,var(--lime));
  font-stretch:72%;font-variation-settings:"wdth" var(--lab-wdth,72)}
.ar-sc-meta span{font-size:12px;color:var(--mute);text-align:right}

@media (max-width:680px){
  .ar-sc{padding:0}
  .ar-sc-win{width:100%;height:100%;border-radius:0;border:0}
  .ar-sc-meta span{display:none}
}
@media (prefers-reduced-motion:reduce){
  .ar-sc-win,.ar-sc-veil,.ar-store .ar-logo img,.ar-store .ar-strip i{transition:none}
  .ar-sc-view{scroll-behavior:auto}
}

/* ============================================================
   CASE STUDIES
   Narrow, quiet, and built to be read rather than swiped through.
   Each one carries its project's accent in --c, set on the article,
   so nothing here needs to know which case study it is.
   ============================================================ */

.cs{--csw:980px}
.cs .shell{max-width:var(--csw)}

/* ---- hero ---- */
.cs-hero{padding:clamp(40px,8vh,96px) 0 clamp(30px,5vh,58px);position:relative}
.cs-back{display:inline-block;color:var(--mute);margin-bottom:clamp(22px,4vw,40px);
  transition:color .25s var(--ease)}
.cs-back:hover{color:var(--c,var(--lime))}
.cs-kick{display:block;color:var(--c,var(--lime));margin-bottom:14px}
.cs-hero .h-xl{font-size:clamp(40px,7.6vw,104px);margin-bottom:clamp(18px,2.6vw,30px)}
.cs-role{display:block;color:var(--mute);margin-top:clamp(18px,2.6vw,28px)}
/* A rule in the project's colour, so you know which case study you are in
   even after the title has scrolled away. */
.cs-hero::after{content:"";display:block;height:3px;background:var(--c,var(--lime));
  max-width:var(--csw);margin:clamp(26px,4vw,44px) auto 0;
  margin-inline:max(var(--pad),calc((100% - var(--csw))/2))}

/* ---- problem / what I did ---- */
.cs-body{padding:clamp(30px,5vw,58px) 0}
.cs-two{display:grid;grid-template-columns:1fr 1fr;gap:clamp(26px,4vw,60px);align-items:start}
.cs-h2{font-size:clamp(19px,1.7vw,26px);letter-spacing:-.02em;font-weight:800;
  margin:0 0 14px;color:var(--bone)}
.cs-h3{font-size:clamp(15px,1.25vw,19px);font-weight:800;letter-spacing:-.01em;
  margin:clamp(34px,4.5vw,54px) 0 16px;color:var(--c,var(--lime))}
.cs-two p{color:var(--mute);line-height:1.62;margin:0 0 13px;font-size:clamp(15px,1.05vw,17px)}
.cs-list{margin:0;padding:0;list-style:none}
.cs-list li{position:relative;padding-left:22px;margin-bottom:12px;color:var(--mute);
  line-height:1.55;font-size:clamp(14px,1vw,16px)}
.cs-list li::before{content:"";position:absolute;left:0;top:.62em;width:9px;height:1px;
  background:var(--c,var(--lime))}

/* ---- the work ---- */
.cs-work{padding:clamp(20px,3vw,40px) 0 clamp(40px,6vw,80px)}
.cs-grid{column-count:2;column-gap:clamp(14px,1.8vw,26px)}
.cs-f{margin:0 0 clamp(14px,1.8vw,26px);break-inside:avoid;position:relative;
  background:var(--panel);overflow:hidden}
.cs-f img{width:100%;height:auto;display:block}
.cs-f figcaption{padding:9px 12px 11px;font-size:12.5px;color:var(--mute);
  border-top:1px solid var(--line)}

/* decks and storefronts get a row each rather than a tile, because they are
   a door to somewhere else, not a picture to look at */
.cs-decks{display:grid;gap:10px}
.cs-deck{display:flex;align-items:center;gap:15px;padding:11px;background:var(--panel);
  box-shadow:inset 0 0 0 1px var(--line);transition:box-shadow .3s var(--ease),
  transform .3s var(--ease)}
.cs-deck img{width:86px;height:62px;object-fit:cover;object-position:top center;flex:none;
  background:var(--panel2)}
.cs-deck b{display:block;font-size:14.5px;color:var(--bone)}
.cs-deck em{display:block;font-style:normal;font-size:12px;color:var(--mute);margin-top:3px}
.cs-deck:hover{box-shadow:inset 0 0 0 1px var(--c,var(--lime));transform:translateX(3px)}

/* ---- before / after ---- */
.cs-ba{display:grid;grid-template-columns:1fr 1fr;gap:clamp(12px,2vw,22px)}
.cs-ba figure{margin:0;background:#fff;padding:clamp(18px,3vw,34px);text-align:center}
.cs-ba img{max-width:100%;height:auto;max-height:160px;width:auto;margin:0 auto;display:block}
.cs-ba figcaption{font-family:var(--lab);font-weight:700;text-transform:uppercase;
  letter-spacing:.2em;font-size:10px;color:#666;margin-top:14px;
  font-stretch:72%;font-variation-settings:"wdth" var(--lab-wdth,72)}

/* ---- numbered process ---- */
.cs-steps{margin:0;padding:0;list-style:none;counter-reset:s}
.cs-step{display:grid;grid-template-columns:auto 1fr;gap:clamp(14px,2.4vw,30px);
  padding-bottom:clamp(26px,4vw,46px);margin-bottom:clamp(26px,4vw,46px);
  border-bottom:1px solid var(--line)}
.cs-step:last-child{border-bottom:0;margin-bottom:0}
.cs-n{font-family:var(--lab);font-weight:800;font-size:clamp(20px,2.6vw,34px);
  color:var(--c,var(--lime));line-height:1;
  font-stretch:72%;font-variation-settings:"wdth" var(--lab-wdth,72)}
.cs-step h4{margin:0 0 6px;font-size:clamp(16px,1.35vw,21px);letter-spacing:-.015em}
.cs-step p{margin:0 0 15px;color:var(--mute);font-size:clamp(13.5px,.98vw,15.5px);
  line-height:1.55;max-width:56ch}
.cs-step img{width:100%;height:auto;display:block;box-shadow:0 0 0 1px var(--line)}

/* ---- the aside, for the finale ---- */
.cs-note{margin-top:clamp(30px,4vw,48px);padding:clamp(18px,2.6vw,28px);
  background:var(--panel);border-left:3px solid var(--c,var(--lime))}
.cs-note b{display:block;font-size:16px;margin-bottom:7px}
.cs-note p{margin:0 0 15px;color:var(--mute);font-size:14.5px;line-height:1.55;max-width:56ch}

/* ---- close ---- */
.cs-close{padding:clamp(40px,6vw,78px) 0 clamp(60px,9vw,110px);border-top:1px solid var(--line)}
.cs-quote{font-size:clamp(19px,2.2vw,31px);line-height:1.32;letter-spacing:-.025em;
  font-weight:600;color:var(--bone);max-width:24ch;margin:0 0 clamp(26px,4vw,42px)}
.cs-cta{display:flex;flex-wrap:wrap;gap:11px}

@media (max-width:820px){
  .cs-two{grid-template-columns:1fr;gap:30px}
  .cs-grid{column-count:1}
  .cs-step{grid-template-columns:1fr;gap:8px}
  .cs-ba{grid-template-columns:1fr}
  .cs-deck img{width:64px;height:48px}
}
@media (prefers-reduced-motion:reduce){ .cs-deck,.cs-back{transition:none} }

/* ---------- the 24px stripe ----------
   WordPress's flow layout gives every direct child of .entry-content a
   margin-top of 24px. Our sections carry their own spacing, so that margin
   showed up as a dead band between the hero and the filter rail, and again
   above the grid and the closing CTA. Measured on the live page: hero ended
   at 761, rail began at 785.
   WordPress sets it through :where(), which has no specificity, so a plain
   class selector is enough to win. */
.entry-content > [class^="ar-"],
.entry-content > [class*=" ar-"],
.entry-content > .ix,
.entry-content > .cs{margin-top:0;margin-block-start:0}
