/* ============================================================
   GRAPHICXO — WORK
   Loaded only by portfolio.php, on top of main.css + pages.css.

   The wall: one woven grid where every plate is the whole entry. The
   emphasis alternates wide / narrow and every other plate hangs lower,
   so the page reads as work hung on a wall rather than a product grid.
   Colour comes from the project — the ground under each plate, the tags,
   the glow on hover, and the page's ambient #pglow (app.js) all read the
   same --accent.
   ============================================================ */

.wk{position:relative}

/* ------------------------------------------------------------
   THE FIELD
   Fixed, and behind the wall. z-index:-1 keeps it under .main's in-flow
   content — which is the whole point: the plates are opaque and sit in
   front, so all you ever see of the swarm is the halo it forms in the
   gutters around each one. It sits after .pglow in the DOM so it paints
   over the ambient wash rather than under it.
   ------------------------------------------------------------ */
.wk-field{
  position:fixed;inset:0;z-index:-1;
  width:100%;height:100%;
  pointer-events:none;
  opacity:0;transition:opacity 1.6s var(--ease);
}
.wk-field.is-live{opacity:1}
@media (prefers-reduced-motion:reduce){ .wk-field{display:none} }

/* ------------------------------------------------------------
   HEAD
   ------------------------------------------------------------ */
.wk-head{position:relative;padding-top:clamp(9rem,18vh,13rem);padding-bottom:clamp(2.5rem,6vh,4rem)}
.wk-head__eyebrow{display:flex;align-items:center;gap:.9rem;margin-bottom:1.4rem}
.wk-head__eyebrow::before{content:"";width:40px;height:1px;background:var(--gold)}

.wk-head__title{font-family:var(--serif);font-size:clamp(2.8rem,10vw,9rem);line-height:.92;letter-spacing:-.03em}
.wk-head__title em{color:var(--gold);font-style:italic;font-weight:300}
/* Each line rises out of its own mask; the padding keeps the overflow from
   shaving descenders. */
.wk-head__mask{display:block;overflow:hidden;padding-bottom:.08em}
.wk-head__mask > span{display:block;transform:translateY(115%);transition:transform 1.05s var(--ease)}
.wk-head__title.is-in .wk-head__mask > span{transform:none}
.wk-head__title.is-in .wk-head__mask:nth-child(2) > span{transition-delay:.1s}

.wk-head__foot{
  display:flex;flex-wrap:wrap;align-items:flex-end;justify-content:space-between;
  gap:clamp(1.4rem,4vw,3rem);
  margin-top:2rem;padding-top:1.9rem;border-top:1px solid var(--line);
  opacity:0;transform:translateY(24px);
  transition:opacity 1s var(--ease) .22s, transform 1s var(--ease) .22s;
}
.wk-head__foot.is-in{opacity:1;transform:none}
.wk-head__desc{max-width:48ch;color:var(--grey);font-size:clamp(1rem,1.4vw,1.15rem);font-weight:300}

.wk-filter{display:flex;flex-wrap:wrap;gap:.5rem}
.wk-chip{
  font-family:var(--serif);font-size:.9rem;color:var(--grey-dim);
  border:1px solid var(--line);border-radius:100px;padding:.5rem 1.15rem;
  transition:color .4s,border-color .4s,background .4s;
}
@media (hover:hover){.wk-chip:hover{color:var(--white);border-color:rgba(247,247,247,.28)}}
.wk-chip.is-on{color:#0a0a0a;border-color:transparent;background:var(--gold)}
.wk-chip:focus-visible{outline:2px solid var(--gold-soft);outline-offset:3px}

/* ------------------------------------------------------------
   THE WALL
   ------------------------------------------------------------ */
/* ------------------------------------------------------------
   SECTIONS
   Two walls now — identities, then the built sites. Each gets a
   heading rail so the page announces the change of discipline
   rather than running twenty-two plates together.
   ------------------------------------------------------------ */
.wk-sec{position:relative;padding-bottom:clamp(4rem,10vh,8rem);scroll-margin-top:6rem}
.wk-sec--web{padding-top:clamp(2rem,6vh,5rem)}
.wk-sec__head{
  display:flex;flex-wrap:wrap;align-items:baseline;gap:.8rem 2.2rem;
  padding-bottom:clamp(1.6rem,4vh,2.6rem);
  margin-bottom:clamp(2rem,5vh,3.4rem);
  border-bottom:1px solid var(--line);
}
.wk-sec__title{
  font-family:var(--serif);
  font-size:clamp(1.7rem,4vw,3rem);
  letter-spacing:-.02em;
  display:flex;align-items:center;gap:1rem;
}
/* A short gold rule leading into the word, the same device the scene
   labels use on the homepage. */
.wk-sec__title::before{
  content:"";width:clamp(28px,5vw,64px);height:1px;
  background:linear-gradient(90deg,transparent,var(--gold));
  flex:none;
}
.wk-sec__note{color:var(--grey-dim);font-size:.92rem;font-weight:300;max-width:52ch}

/* ------------------------------------------------------------
   THE WALLS
   Both are auto-fit grids rather than the old 12-column weave.
   The weave varied each plate's aspect ratio by nth-child, which
   is what was slicing landscape logo crops into bands — a plate
   whose shape depends on its position cannot suit its contents.
   One shape per wall, and the artwork is CONTAINED rather than
   cropped: a mark that is cut off is not a mark.
   ------------------------------------------------------------ */
.wk-wall{
  display:grid;
  gap:clamp(1.8rem,3.5vw,3rem) clamp(1.4rem,2.6vw,2.4rem);
  align-items:start;
}
.wk-wall--logo{grid-template-columns:repeat(auto-fill,minmax(clamp(260px,30vw,380px),1fr))}
.wk-wall--web{grid-template-columns:repeat(auto-fill,minmax(clamp(300px,44vw,540px),1fr))}

/* Every other plate hangs a little lower — enough to keep it a wall
   rather than a spreadsheet, small enough that the rows still read
   as rows. */
.wk-wall--logo > .wk-plate:nth-child(even){margin-top:clamp(.8rem,2.5vw,2.4rem)}

/* ---- The concept band ----
   Two cards on their own full-width row, inside the wall rather than
   beside it. 1 / -1 spans whatever the auto-fill grid resolved to at
   this viewport — two, three or four columns — so the band is one row
   at every width without the wall's own tracks being fixed.

   The plates inside are half the wall instead of a third, which is the
   whole point: these two are full systems with chaptered case studies,
   and they get the room to say so. No stagger on them — a deliberate
   pair reads as a pair only if both sit on the same line. */
.wk-pair{
  grid-column:1 / -1;
  display:grid;
  /* Two per row, always, however many concept projects there are — a third
     wraps to a second row of the band rather than squeezing three across.
     Half the wall is the size these cards are worth: at a third they sit at
     the same width as the client plates around them and stop reading as a
     band at all, which is the whole reason they are lifted out of the wall.
     An auto-fit here would quietly do exactly that the moment a third
     arrived. */
  grid-template-columns:repeat(2,minmax(0,1fr));
  gap:clamp(1.4rem,2.6vw,2.4rem);
  align-items:start;
}
.wk-pair > .wk-plate{margin-top:0}

/* The year filter empties plates with [hidden] rather than removing them.
   A band whose plates are all hidden would otherwise hold a full-width
   row of nothing. Dormant while every project's year is NULL and the
   control does not render — see the note in tools/seed-work.php — and
   ignored outright by a browser without :has(), which lands back on
   exactly today's behaviour. */
.wk-pair:not(:has(> .wk-plate:not([hidden]))){display:none}

.wk-plate.reveal:nth-child(even){transition-delay:.12s}
.wk-plate{scroll-margin-top:7rem}   /* deep links land clear of the fixed nav */

/* The title carries the link; its ::after is stretched over the whole plate so
   the cover and the copy are click targets too. position:relative on the plate
   is what that absolute box resolves against, and z-index keeps it above the
   frame's own veil. */
.wk-plate{position:relative}
.wk-plate__title a{color:inherit;transition:color .35s var(--ease)}
.wk-plate__title a::after{content:"";position:absolute;inset:0;z-index:3}
@media (hover:hover){
  .wk-plate__title a:hover{color:var(--accent)}
}
.wk-plate__title a:focus-visible{outline:2px solid var(--gold-soft);outline-offset:4px}

/* ---- The frame ---- */
.wk-plate__frame{
  position:relative;overflow:hidden;
  aspect-ratio:4/3;
  border-radius:18px;
  border:1px solid var(--line);
  /* The project's colour IS the ground; the artwork on top is drawn in
     white, so one plate reads correctly against any accent in the table. */
  background:
    radial-gradient(120% 92% at 18% 6%, rgba(var(--accent-rgb),.44), transparent 64%),
    linear-gradient(158deg, rgba(var(--accent-rgb),.24), #0a0a0b 70%);
  transition:transform .9s var(--ease), border-color .6s var(--ease), box-shadow .9s var(--ease);
}
/* One shape for every identity plate. The source crops run from 16:9
   to 2:1, so 16:10 wastes the least room around them. */
.wk-plate--logo .wk-plate__frame{aspect-ratio:16/10;padding:clamp(.7rem,1.8vw,1.4rem)}

@media (hover:hover){.wk-plate:hover .wk-plate__frame{
  transform:translateY(-10px);
  border-color:rgba(var(--accent-rgb),.55);
  box-shadow:0 44px 90px -50px rgba(var(--accent-rgb),.95);
}}

.wk-plate__art{position:absolute;inset:0}
.plate{
  position:absolute;inset:0;width:100%;height:100%;display:block;
  /* The compositions carry their own per-shape opacity, so a flat white
     currentColor gives the full range without a second palette. */
  color:#fff;
  transition:transform 1.3s var(--ease);
}
@media (hover:hover){.wk-plate:hover .plate{transform:scale(1.05)}}
.plate--photo{object-fit:cover}
/* CONTAIN on a real plate, not cover. These are logos: cropping one to
   fill a box cuts the mark in half, which is exactly what the wall was
   doing to the landscape crops. The accent gradient behind is the
   ground the letterboxing sits on, so it reads as a mount. */
.wk-plate--logo .plate--photo{
  position:relative;inset:auto;
  width:100%;height:100%;
  object-fit:contain;
  border-radius:8px;
}

/* Grounds the year chip and stops a bright plate running to the edge. */
.wk-plate__veil{
  position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(180deg,rgba(6,6,8,.34) 0%,transparent 38%,transparent 58%,rgba(6,6,8,.66) 100%);
}

.wk-plate__year{
  position:absolute;top:1rem;right:1.1rem;z-index:2;
  font-family:var(--serif);font-size:.84rem;line-height:1;
  color:rgba(255,255,255,.8);
  padding:.42rem .8rem;
  border:1px solid rgba(255,255,255,.2);border-radius:100px;
  backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);
  transition:border-color .5s,color .5s;
}
@media (hover:hover){.wk-plate:hover .wk-plate__year{border-color:rgba(255,255,255,.42);color:#fff}}
.wk-plate__year:empty{display:none}

/* ---- The entry ---- */
.wk-plate__body{padding-top:1.35rem}
.wk-plate__title{
  font-family:var(--serif);
  font-size:clamp(1.5rem,2.7vw,2.5rem);
  line-height:1.04;letter-spacing:-.022em;
  color:var(--white);
}
.wk-plate__tags{list-style:none;display:flex;flex-wrap:wrap;gap:.4rem .45rem;margin-top:.85rem}
.wk-plate__tags li{
  font-size:.68rem;font-weight:500;letter-spacing:.12em;text-transform:uppercase;
  color:var(--grey-dim);
  border:1px solid var(--line);border-radius:100px;padding:.28rem .7rem;
  transition:color .45s,border-color .45s,background .45s;
}
@media (hover:hover){.wk-plate:hover .wk-plate__tags li{color:var(--accent);border-color:rgba(var(--accent-rgb),.42);background:rgba(var(--accent-rgb),.07)}}
.wk-plate__line{margin-top:1.05rem;max-width:46ch;color:var(--grey);font-size:.95rem;font-weight:300;line-height:1.72}

/* ---- Filtering ----
   While a year is selected the woven rhythm stands down: with plates
   removed from the flow, alternating 7/5 spans leave holes rather than a
   pattern. Equal columns keep the result composed. */
.wk-wall.is-filtered .wk-plate,
.wk-wall.is-filtered .wk-plate:last-child:nth-child(odd){grid-column:span 6}
.wk-wall.is-filtered .wk-plate .wk-plate__frame{aspect-ratio:4/3}
.wk-wall.is-filtered .wk-plate{margin-top:0}
.wk-plate[hidden]{display:none}

.wk-empty{
  margin-top:2rem;
  font-family:var(--serif);font-size:1.1rem;font-style:italic;color:var(--grey-dim);
}
.wk-empty[hidden]{display:none}

/* ------------------------------------------------------------
   RESPONSIVE
   Equal-specificity overrides, later in the file — no !important needed.
   ------------------------------------------------------------ */
@media (max-width:1080px){
  .wk-wall{grid-template-columns:repeat(2,1fr)}
  .wk-wall .wk-plate,
  .wk-wall .wk-plate:last-child{grid-column:auto}
  .wk-wall .wk-plate .wk-plate__frame{aspect-ratio:4/3}
  .wk-wall .wk-plate:nth-child(even){margin-top:clamp(1rem,4vw,2.5rem)}
}
@media (max-width:700px){
  .wk-wall{grid-template-columns:1fr}
  /* One card per row everywhere else on the wall, so the band stops being
     a band — two half-width plates on a phone are two thumbnails. */
  .wk-pair{grid-template-columns:minmax(0,1fr)}
  .wk-wall .wk-plate:nth-child(even){margin-top:0}
  .wk-head__foot{flex-direction:column;align-items:stretch}
  /* Five stacked blurred chips is not worth the GPU on a phone. */
  .wk-plate__year{backdrop-filter:none;-webkit-backdrop-filter:none;background:rgba(6,6,8,.5)}
}

/* ------------------------------------------------------------
   REDUCED MOTION
   ------------------------------------------------------------ */
@media (prefers-reduced-motion:reduce){
  .wk-head__mask > span,.wk-head__foot{opacity:1;transform:none;transition:none}
  .wk-plate__frame,.plate{transition:none}
  @media (hover:hover){.wk-plate:hover .wk-plate__frame{transform:none}}
  @media (hover:hover){.wk-plate:hover .plate{transform:none}}
}

/* ============================================================
   WEBSITE PLATES — the browser frame
   Drawn, not an image: a chrome rail with three dots and the slug
   in an address pill, then the screenshot below it. It costs
   nothing, inherits the project accent, and makes every site card
   the same object whether its screenshot was captured with a real
   address bar in frame or not.
   ============================================================ */
.wk-plate__browser{
  position:relative;
  border-radius:14px;
  overflow:hidden;
  border:1px solid var(--line);
  background:#0a0a0b;
  box-shadow:0 30px 70px -46px rgba(0,0,0,.9);
  transition:transform .9s var(--ease),border-color .6s var(--ease),box-shadow .9s var(--ease);
}
@media (hover:hover){
  .wk-plate--web:hover .wk-plate__browser{
    transform:translateY(-10px);
    border-color:rgba(var(--accent-rgb),.55);
    box-shadow:0 44px 90px -46px rgba(var(--accent-rgb),.9);
  }
}

.wk-plate__chrome{
  display:flex;align-items:center;gap:.4rem;
  height:34px;padding:0 .8rem;
  background:linear-gradient(180deg,#1a1a1c,#141416);
  border-bottom:1px solid rgba(255,255,255,.06);
}
.wk-plate__chrome i{
  width:9px;height:9px;border-radius:50%;flex:none;
  background:rgba(255,255,255,.16);
}
/* The leftmost dot takes the project's colour — the one place the
   frame is not neutral, and enough to tie it to the plate. */
.wk-plate__chrome i:first-child{background:var(--accent)}

.wk-plate__url{
  flex:1;min-width:0;
  margin-left:.5rem;
  padding:.2rem .7rem;
  border-radius:100px;
  background:rgba(255,255,255,.05);
  color:var(--grey-dim);
  font-size:.66rem;letter-spacing:.06em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}

/* No fixed aspect: the screen is as tall as its screenshot. A set box
   meant either cropping the sides off a 2.26:1 capture or leaving a
   band of dead space under it, and the captures are close enough in
   proportion that the cards still line up. */
.wk-plate__screen{
  position:relative;
  overflow:hidden;
  background:#0a0a0b;
}
/* CONTAIN, not cover. The screenshots run about 2:1 and the frame is
   16:10, so cover was slicing roughly a fifth off each side — on Apical
   that ate the "W" of "Welcome". Letterboxed inside a browser frame
   reads as the browser's own background, which is what it is. */
.wk-plate__screen .plate--photo{
  position:relative;inset:auto;
  display:block;
  width:100%;height:auto;
  transition:transform 1.3s var(--ease);
}
@media (hover:hover){
  .wk-plate--web:hover .wk-plate__screen .plate--photo{transform:scale(1.03)}
}

/* ============================================================
   HEAD TALLY
   Counts derived in portfolio.php, never typed. Doubles as the
   jump nav to the two sections.
   ============================================================ */
.wk-tally{display:flex;flex-wrap:wrap;gap:1.6rem 2.6rem;align-items:flex-end}
.wk-tally__cell{display:flex;align-items:baseline;gap:.6rem}
.wk-tally dt{order:2}
.wk-tally dt a{
  font-size:.72rem;font-weight:600;letter-spacing:.2em;text-transform:uppercase;
  color:var(--grey-dim);
  transition:color .35s var(--ease);
}
@media (hover:hover){ .wk-tally dt a:hover{color:var(--gold)} }
.wk-tally dd{
  order:1;
  font-family:var(--serif);
  font-size:clamp(1.8rem,4vw,2.8rem);
  line-height:1;
  color:var(--gold);
}

@media (max-width:720px){
  .wk-wall--logo,.wk-wall--web{grid-template-columns:1fr}
  .wk-wall--logo > .wk-plate:nth-child(even){margin-top:0}
  .wk-plate__chrome{height:30px}
}

@media (prefers-reduced-motion:reduce){
  @media (hover:hover){
    .wk-plate--web:hover .wk-plate__browser{transform:none}
    .wk-plate--web:hover .wk-plate__screen .plate--photo{transform:none}
  }
}
