/* work.css — work-build-260913. /work, /work/<tag>, /work/<slug>.
   Loads AFTER home.css and adds nothing home.css already says: the tile, the caption bar,
   the chevron and the chip pill all come from there unchanged.
   What is here is the grid the tiles sit in, the filter row, and the piece page. */
.vh{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
/* round4e-260918 D24: the .phnote placeholder block is removed with the mechanism. */

/* the strip: same type as Home, less air above it — /work is a listing, not an entrance */
.wstrip{padding-bottom:clamp(28px,4vw,44px)}
.wintro{font-size:17px;line-height:1.6;color:var(--muted-sm);max-width:62ch;margin:1.1em 0 0}
@media(min-width:1024px){.wstrip .wintro{grid-column:2;grid-row:2;margin-top:1.1em}}

/* the filter row. Sticky under the 80px header so a filter is always in reach on a long
   grid; it collapses to a scrollable row on a phone rather than stacking four lines. */
.wfilters{position:sticky;top:80px;z-index:30;background:var(--paper);border-top:1px solid var(--hair);border-bottom:1px solid var(--hair);padding:12px var(--pad);display:flex;align-items:center;gap:14px 20px;flex-wrap:wrap}
.wfilters .chips{margin:0;flex:1 1 auto;gap:8px}
/* round4c B2: 11px, not 13px - WF-3 v2 `.chip{font:400 11px/1 "Inter Tight";...;text-transform:uppercase}`
   and the ticket's B2 line (chip and label are the same 11px caps label). */
.chip{display:inline-flex;align-items:center;min-height:44px;padding:0 16px;border:1px solid var(--hair);border-radius:999px;font-size:11px;letter-spacing:.06em;text-transform:uppercase;text-decoration:none;color:var(--ink);background:var(--paper)}
.chip:hover{border-color:var(--green);background:rgba(101,231,130,.1)}
.chip.on{background:var(--ink);color:var(--paper);border-color:var(--ink)}
.chip.on:hover{background:var(--ink);color:var(--paper)}
.chips .sep{width:1px;align-self:stretch;background:var(--hair);margin:0 6px}
/* the pill shape that actually ships is ~390 lines below (WF-2 v8 `.clr`, built in B3): it sets
 * border-bottom:0 and the hairline pill border, so the green underline that used to sit here
 * has never rendered since. Removed rather than left in place -- a declaration that contradicts
 * the one that wins is exactly what cost two hours in B2 and B4b. No rendering change. */
.clr{font-size:13px;letter-spacing:.06em;text-transform:uppercase;color:var(--ink);text-decoration:none;display:inline-flex;align-items:center;min-height:44px;white-space:nowrap}
.clr.off{display:none}
.wcount{font-size:12px;letter-spacing:.1em;text-transform:uppercase;color:var(--muted-sm);margin:0;white-space:nowrap}

/* the grid. One column on a phone, two from 900px: the tile is the Home tile, so it keeps
   its 16:9 stage and its caption bar; only the width changes. */
.wsec{padding:0 0 clamp(30px,5vw,54px)}
/* round4c B5 / J4, J6 + WF-1 v9: the heading is a baseline row and the brand link is
   pushed to its right end by margin-left:auto - the drawing writes the link INSIDE the h2.
   Size stays clamp(26px,2.2vw,30px): WF-1 v9 says 34px but WF-3 v2 / WF-4 v3.2 are the
   later approved drawings and both say .sec 300 30px / 26px at 390, which is what the
   canon asserts. */
.wsh{font-family:Newsreader,Georgia,serif;font-weight:300;font-size:clamp(26px,2.2vw,30px);line-height:1.15;margin:clamp(30px,4vw,48px) var(--pad) 14px;color:var(--ink);display:flex;align-items:baseline;gap:18px;flex-wrap:wrap}
.wshl{font:400 13px/1 "Inter Tight",system-ui,sans-serif;letter-spacing:.06em;text-transform:uppercase;color:var(--ink);text-decoration:none;border-bottom:1px solid var(--green);margin-left:auto;white-space:nowrap}
.wshl:hover{color:var(--green)}
/* J5: Related is 2-across at every width above the single-column breakpoint. Needs to beat
   the 3-across .wgrid rule further down this file, hence the section-scoped selector. */
.wsec[data-cols="2"] .wgrid{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
/* round4b-260916 launch: minmax(0,1fr), never a bare 1fr. A bare 1fr is minmax(auto,1fr) and its
   min track is the item's MIN-CONTENT, so one long client name in a caption pushed the whole grid
   wider than the phone viewport (measured: /work 441px, /work/sports 404px, /capabilities/casting
   493px at a 390 viewport). Sizing, not design: no ruled element changes. */
.wgrid{display:grid;grid-template-columns:minmax(0,1fr);gap:0}
/* D17: the results grid is 2-across under 480, never 3. It was one column on a phone, so
   /work read as a single tall stack of 16:9 tiles. Scoped to <480 exactly as ruled - the
   480-899 band keeps the single column it has today, which is NOT part of this ruling and is
   filed as a proposed register entry rather than "improved" here (RULE 0). */
@media(max-width:479px){.wgrid{grid-template-columns:repeat(2,minmax(0,1fr))}}
.wtile{border-bottom:1px solid var(--hair)}
.wtile .cap{cursor:default}
.wgo{display:block;text-decoration:none;color:inherit}
.wgo .stage{display:block;position:relative;width:100%;aspect-ratio:16/9;background:#0d0d0d;overflow:hidden}
.wgo .stage img,.wgo .stage video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
/* assets-260914 step 0: letterboxed loop scaled to fill the tile -- see home.css and build.mjs LETTERBOX */
.wgo .stage .loop.lb{transform:scale(var(--lb,1))}
.wtile:hover .mark{opacity:1;transform:translate(-50%,-50%) scale(1)}
.wtile .capgo{flex-wrap:nowrap}
.wsec[hidden]{display:none}
.wtile[hidden]{display:none}
@media(min-width:900px){
.wgrid{grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:0 1px;background:var(--hair)}
.wtile{background:var(--paper);border-bottom:1px solid var(--hair)}
}
/* body.snap — same one line of behaviour as Home: ?snap=1 and nothing else. */
body.snap .wgrid{scroll-snap-type:y proximity}
body.snap .wtile{scroll-snap-align:start}

/* the empty state: a filter combination with nothing in it says so, in place. */
.wempty{margin:0 var(--pad) 40px;font-size:17px;color:var(--muted-sm)}
.wempty[hidden]{display:none}

/* the piece page */
.crumbs{padding:18px var(--pad) 0;font-size:13px;letter-spacing:.06em;text-transform:uppercase;color:var(--muted-sm)}
.crumbs a{color:var(--ink);text-decoration:none;border-bottom:1px solid var(--hair)}
.crumbs a:hover{border-color:var(--green)}
.crumbs span{color:var(--muted-sm)}
.piece{padding:0 0 clamp(20px,3vw,34px)}
.pstage{margin-top:18px;background:#0d0d0d}
.phero{width:100%;height:auto;aspect-ratio:16/9;object-fit:contain;background:#0d0d0d}
.piece h1{font-family:Newsreader,Georgia,serif;font-weight:300;font-size:clamp(30px,4vw,44px);line-height:1.1;margin:clamp(26px,3.4vw,40px) var(--pad) 0;max-width:22ch}
.piece h1 .ttl{color:var(--muted)}
.pline{font-size:19px;line-height:1.62;color:var(--ink);max-width:62ch;margin:.9em var(--pad) 0}

/* round4c B5 J10 -- the film's own site. It had NO rule at all, so an unstyled <p> sat at
 * x=0: outside the page margin every other element on the page shares (rule 1, one left
 * edge) and clipped at 390. Same margin as the h1 and the lede above it. */
.pfilmlink{margin:1.4em var(--pad) 0;font-size:15px}
.pfilmlink a{color:var(--ink);text-decoration:none;border-bottom:1px solid var(--hair)}
.pfilmlink a:hover{border-color:var(--green)}
.pcred{display:flex;flex-wrap:wrap;gap:10px 44px;margin:clamp(26px,3.4vw,40px) var(--pad) 0;padding-top:18px;border-top:1px solid var(--hair)}
.pcred dt{font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:var(--muted-sm)}
.pcred dd{margin:4px 0 0;font-size:17px;line-height:1.4;color:var(--ink)}
.ptags{margin:24px var(--pad) 0;gap:8px}
/* round4c B5 J11 -- the last section on a job page sat directly on the footer's green rule
 * with zero space below it (yard-sale's "More photos (57)" button). One rule on the page,
 * so it cannot come back on whichever section happens to be last. */
.pmain{padding-bottom:clamp(44px,6vw,80px)}
.pmain .wsh{margin-top:clamp(34px,5vw,60px);padding-top:clamp(20px,3vw,30px);border-top:1px solid var(--hair)}
video.phero::cue{font-family:"Inter Tight",sans-serif;font-size:20px;line-height:24px;color:#fff;background:rgba(56,54,54,.85)}
@media(prefers-reduced-motion:reduce){.mark{transition:none}}
/* thom-rulings-260913 — visible CC control under the job player. .ccbar itself is styled in
   home.css (job pages load home.css first), so the control is identical on the wall and here. */
.pherow{display:flex;flex-direction:column;gap:0}
.pherobar{display:flex;justify-content:flex-end;align-items:center;gap:8px;padding:8px 0 0}
.pherobar .ccbar{margin-left:0}
/* nav-glass3-260914 STEP 0(b) — the job-page CC control sits on the #0d0d0d player, so the
   inherited ink (#383636) foreground measured 1.61:1 (axe RED, 14 nodes). Light foreground in
   BOTH states; aria-pressed keeps its filled-when-on affordance, inverted to paper/ink. */
.pherobar .ccbar{color:var(--paper);border-color:var(--paper)}
.pherobar .ccbar[aria-pressed="true"]{background:var(--paper);color:var(--ink)}
.pherobar .ccbar:focus-visible{outline:3px solid var(--paper);outline-offset:2px}

/* ---- verticals-copy-260914: "work first, words below, nothing hidden from the DOM" ----
   The locked vertical + capability pages (Thom 9/14). H1 is a short LABEL over the grid,
   so it takes the listing size, not the piece-page size; the paragraph, the pull-quote and
   the FAQ sit in one band under the work. The FAQ is a plain <dl>: every answer is visible
   text with no disclosure to open, which is the point of these pages. */
.vhead{padding-bottom:clamp(18px,2.4vw,26px)}
.vhead h1{font-family:Newsreader,Georgia,serif;font-weight:300;font-size:clamp(30px,4vw,44px);line-height:1.12;margin:.28em 0 0;max-width:22ch;color:var(--ink)}
.vlock .crumbs{padding-left:0;padding-right:0}
/* round4c-260917 B6 / P1, second half. .strip turns into a two-column grid at desktop
 * (home.css:176, for Home's H1-beside-lede band). The vertical and capability heads inherited it,
 * so the crumb was auto-placed into column 2 and rendered at x=682 -- the "crumb floated right"
 * in the defect, which was never a float at all. /work escapes it through .wstrip1{display:block};
 * these heads get the same treatment, so the crumb and the H1 stack on the one shared left edge
 * (canon geometry.left_edge). Measured, not assumed: crumb and H1 both land on var(--pad). */
.vhead{display:block}
.words{margin:clamp(40px,5.5vw,72px) var(--pad) clamp(30px,4vw,52px);padding-top:clamp(26px,3.2vw,38px);border-top:1px solid var(--hair);max-width:70ch}
.words .wpara{font-size:18px;line-height:1.65;color:var(--ink);margin:0 0 1.05em;max-width:66ch}
.words .wpara:last-of-type{margin-bottom:0}
.pquote{margin:clamp(26px,3.2vw,40px) 0;padding-left:18px;border-left:2px solid var(--green);max-width:60ch}
.pquote blockquote{margin:0}
.pquote blockquote p{font-family:Newsreader,Georgia,serif;font-weight:300;font-size:clamp(19px,2.2vw,24px);line-height:1.42;color:var(--ink);margin:0}
.pquote figcaption{margin-top:12px;font-size:13px;letter-spacing:.06em;text-transform:uppercase;color:var(--muted-sm)}
.pquote cite{font-style:normal}
.fqh{font-family:Newsreader,Georgia,serif;font-weight:300;font-size:clamp(22px,2.8vw,28px);line-height:1.15;margin:clamp(30px,3.6vw,44px) 0 0;color:var(--ink)}
.faq{margin:1.1em 0 0}
.faq dt{font-size:17px;line-height:1.45;font-weight:500;color:var(--ink);margin-top:1.5em;padding-top:1.5em;border-top:1px solid var(--hair)}
.faq dt:first-of-type{margin-top:1em;padding-top:0;border-top:0}
.faq dd{margin:.5em 0 0;font-size:17px;line-height:1.62;color:var(--ink);max-width:64ch}
.fnlinks{margin:clamp(28px,3.4vw,40px) 0 0;font-size:13px;letter-spacing:.06em;text-transform:uppercase;color:var(--muted-sm)}
.fnlinks a{color:var(--ink);text-decoration:none;border-bottom:1px solid var(--green)}
.caplock .capall{margin:0 var(--pad) clamp(40px,5vw,64px)}
@media(max-width:767px){.words{max-width:none}.words .wpara,.faq dd{font-size:16px}}
/* round2-260915 A3: active ?brand= filter pill above the grid (Thom 10:35 AM).
   Existing GB tokens only -- paper/ink/hair/muted-sm -- no new colour. */
.bpill{display:inline-flex;align-items:center;gap:10px;min-height:44px;margin:0 var(--pad) 18px;padding:0 6px 0 16px;border:1px solid var(--hair);border-radius:999px;background:var(--paper);font-size:13px;letter-spacing:.06em;text-transform:uppercase;color:var(--ink)}
.bpill[hidden]{display:none}
.bpill .bpl{white-space:nowrap}
.bpill .bpx{display:inline-flex;align-items:center;justify-content:center;width:32px;min-height:32px;border-radius:999px;text-decoration:none;font-size:17px;line-height:1;color:var(--muted-sm)}
.bpill .bpx:hover,.bpill .bpx:focus-visible{color:var(--ink)}

/* ---- round3b-260916 B3 + B4 ------------------------------------------------------------
   B4 search: sits with the Format row -- to its right at desktop, on its own line at phone,
   which is what `.cgrp-f` being a flex row that wraps gives for free. type=search with an
   explicit x, because iOS Safari renders no native clear control and a search you cannot
   clear without selecting the text is a phone defect.
   B3 Load more: a real button under the grid, full-bleed to the grid's own gutters so it
   reads as part of the grid and not as a footer link. Hidden by build.mjs until work.js has
   a window to grow, so with JS off it never appears.                                      */
.cgrp-f{display:flex;flex-wrap:wrap;align-items:center;gap:8px 16px}
.cgrp-f .cgh{flex:0 0 100%}
.cgrp-f .chips{flex:1 1 auto}
.wsearch{position:relative;display:flex;align-items:center;flex:0 0 auto}
.wq{font:400 14px/1 "Inter Tight",system-ui,sans-serif;color:var(--ink);background:var(--paper);border:1px solid var(--hair);border-radius:0;padding:10px 30px 10px 12px;min-height:44px;min-width:180px;-webkit-appearance:none;appearance:none}
.wq:focus{outline:2px solid var(--green);outline-offset:1px;border-color:var(--green)}
.wq::-webkit-search-cancel-button{display:none}
.wqx{position:absolute;right:2px;top:50%;transform:translateY(-50%);width:28px;height:28px;display:inline-flex;align-items:center;justify-content:center;border:0;background:none;color:var(--muted-sm);font-size:18px;line-height:1;cursor:pointer}
.wqx:hover{color:var(--ink)}
.wqx[hidden]{display:none}
.wmorewrap{margin:0;padding:18px var(--pad) 0;text-align:center}
.wmore{font:400 13px/1 "Inter Tight",system-ui,sans-serif;letter-spacing:.14em;text-transform:uppercase;color:var(--ink);background:var(--paper);border:1px solid var(--hair);padding:0 22px;min-height:48px;cursor:pointer}
.wmore:hover{border-color:var(--green)}
.wmore:focus-visible{outline:2px solid var(--green);outline-offset:2px}
.wmore[hidden]{display:none}
@media(max-width:767px){
.wsearch{flex:1 1 100%}
.wq{width:100%}
}

/* ===== round4b-260916 B4 -- the job card (WF-1-job-card-260916.html v9) ================
   Every rule below carries its drawing number. Nothing here is a preference: the drawing
   is scope-locked and Karmen holds the kill-pass on it.                                */

/* rule 2/4 -- the credits row. `grid-auto-flow:column` with two rows puts every LABEL on
   row one and every VALUE on row two, so the labels sit on ONE baseline by construction
   rather than by matched padding (Thom's v5 approval condition). The old .pcred flex row
   is still used by nothing else, so it is left alone and .jcred overrides it. */
.jcred{display:grid;grid-auto-flow:column;grid-template-rows:auto auto;justify-content:start;column-gap:clamp(24px,3vw,44px);row-gap:6px;flex-wrap:nowrap}
.jcred dt.jc{font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--muted-sm);white-space:nowrap}
.jcred dd.jc{margin:0;font-size:16px;line-height:1.35;color:var(--ink);white-space:nowrap}
.jcred dd.jc a{color:inherit;text-decoration:none;border-bottom:1px solid var(--hair)}
.jcred dd.jc a:hover{border-color:var(--green)}
/* rule 4 -- the above-the-line credits carry the green dot. It hangs off the LABEL, so a
   job with no DP simply has no column and nothing shifts. */
/* round4c R-F: "Green dots on credits: none." Rule 2's 6px green marker before Director /
   DP / Photographer is removed - the amendment wins over the drawing, which still draws it.
   The green line now lives only on the Home wall bar's client name (R-E), one accent per
   screen. dt.atl keeps the flex row so the label sits on the same baseline as the others. */
.jcred dt.atl{display:flex;align-items:center}

/* rule 3 -- the tags row. Square (3px), three kind tints, "->" on hover. These are objects,
   not controls: no selected state, no x, and no aria-pressed anywhere (qa/media.mjs REDs
   on one). Round pills stay reserved for the /work filter, where you ARE selecting. */
.ptags{margin:clamp(20px,2.6vw,28px) var(--pad) 0}
.ptags .chip{border-radius:3px;border:0;display:inline-flex;align-items:center;gap:0;padding:7px 12px;font-size:11px;line-height:1;color:var(--ink);text-decoration:none;min-height:32px}
.ptags .chip.k-i{background:#EFECE9}
.ptags .chip.k-f{background:#E7E9EC}
.ptags .chip.k-s{background:#E6EFE8}
.ptags .chip .arw{display:inline-block;width:0;overflow:hidden;opacity:0;transition:width .14s,opacity .14s,margin-left .14s}
.ptags .chip:hover .arw,.ptags .chip:focus-visible .arw{width:1em;opacity:1;margin-left:6px}
.ptags .chip:focus-visible{outline:2px solid var(--ink);outline-offset:2px}

/* rules 5 + 6 -- the stage. Two PEER 16:9 rectangles with a gutter; the key video is not
   bigger than the key photo and neither is full-bleed. A single-asset job (or the filtered
   state of a mixed one) renders ONE rectangle capped at 960px -- the ruled default. */
.jstage{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:clamp(12px,1.6vw,22px);margin:clamp(26px,3.4vw,40px) var(--pad) 0}
.jstage.one{grid-template-columns:minmax(0,1fr);max-width:960px}
.jvid,.jphoto{display:block;margin:0;min-width:0}
.jvid video,.jphoto img{display:block;width:100%;height:auto;aspect-ratio:16/9;object-fit:cover;background:#000}
.jphoto{cursor:zoom-in}

/* round4c B5 J1 -- WF-1 v9 .pkey. The key player's resting frame carries our own controls:
 * a 74px play mark dead centre, the label chip at bottom-left and CC at bottom-right, all ON
 * the frame. job.js hands the video native `controls` only once it is playing, and hides this
 * overlay for the duration, so the two control sets are never both on screen. */
.pkey{position:relative}
.jplay{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:74px;height:74px;border-radius:50%;border:0;background:rgba(251,250,248,.9);color:var(--ink);display:flex;align-items:center;justify-content:center;cursor:pointer;padding:0}
.jplayi{font-size:22px;line-height:1;margin-left:3px}
.jplay:hover{background:var(--paper)}
.jplay:focus-visible{outline:3px solid var(--green);outline-offset:3px}
.jvlabel{position:absolute;left:14px;bottom:12px;font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:#fff;background:rgba(13,13,13,.6);padding:8px 10px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:calc(100% - 92px)}
/* D6: the frame CC overlay. Renamed off `ccbar` (the gate proves no .ccbar survives on any
   surface) and, more importantly, re-timed: display:none at rest, revealed by .playing. It is
   the ONLY CC control on the page - the wall bar's second one is deleted in build.mjs. */
.pkey .jcc{display:none}
.pkey.playing .jcc{display:inline-flex}
.pkey .jcc{position:absolute;right:12px;bottom:12px;margin:0;font-size:11px;letter-spacing:.1em;color:#fff;background:transparent;border:1px solid #fff;border-radius:0;padding:7px 9px;min-height:0;cursor:pointer}
.pkey .jcc[aria-pressed="true"]{background:#fff;color:var(--ink)}
.pkey .jcc:focus-visible{outline:3px solid var(--green);outline-offset:2px}
.pkey.playing .jplay,.pkey.playing .jvlabel{display:none}

/* J9 -- a master delivered with black bars baked into the frame. The bars are cropped by
 * scaling the picture inside the 16:9 box, exactly as the wall loops already do; the .mp4 is
 * never re-encoded and the scale is the measured one from content/master-meta.json. */
.lbv{overflow:hidden}
.lbv video,.lbv img{transform:scale(var(--lb,1))}
.jstage [hidden]{display:none}

/* rule 7 -- All / Video / Photo. This IS a selecting surface, so the pill is round. */
.jview{display:flex;gap:8px;margin:clamp(18px,2.4vw,26px) var(--pad) 0}
/* J16 -- WF-1 v9 .chip: 12px caps with the sans tracking, not 13px sentence case. */
.jv{border-radius:999px;border:1px solid var(--hair);background:transparent;padding:0 14px;min-height:36px;font:400 12px/1 "Inter Tight",system-ui,sans-serif;letter-spacing:.06em;text-transform:uppercase;color:var(--muted-sm);cursor:pointer}
.jv:hover{color:var(--ink);border-color:var(--ink)}
.jv.on,.jv[aria-pressed="true"]{background:var(--ink);color:var(--paper);border-color:var(--ink)}
.jv:focus-visible{outline:2px solid var(--green);outline-offset:2px}

/* rule 8 -- the alt row. auto-fit from 300px: 3-across at 1440, 4 when the job has 4.
   Hidden entirely when the job has one video (the section is not emitted at all). */
.jalt{margin:clamp(26px,3.4vw,40px) var(--pad) 0}
/* J3, J8 -- WF-1 v9 .psh: a serif section heading with a small-caps count beside it, where
 * round4b had an 11px all-caps eyebrow. Sized to the LATER approved section-heading type
 * (WF-3 v2 / WF-4 v3.2 `.sec` 300 30px, 26px at 390) rather than WF-1's own
 * clamp(22px,2.8vw,30px), so the job page carries ONE section-heading size that agrees with
 * .wsh above it and with the approved canon. Declared in the conformance sheet. */
.psh{display:flex;align-items:baseline;gap:14px;flex-wrap:wrap;font-family:Newsreader,Georgia,serif;font-weight:300;font-size:clamp(26px,2.2vw,30px);line-height:1.15;letter-spacing:normal;text-transform:none;color:var(--ink);margin:0 0 14px}
.psh small{font:400 12px/1 "Inter Tight",system-ui,sans-serif;letter-spacing:.12em;text-transform:uppercase;color:var(--muted-sm)}
.jalth{margin:0 0 14px}
/* D2: the spot in the key player is not "more from this campaign", so it is hidden here;
   and the column count is chosen by the build so the last row is never a single orphan
   (4 -> 2x2, 5 -> 3+2). Scoped to >=768 so the <=480 two-across rule below still wins on
   a phone. */
.jaltg > li[data-playing]{display:none}
/* round4e D30 (Thom: "equal to the 2x2 size with just white space next to it so it's clear it's
   related but not equal"): an alt tile is ALWAYS the 2-up size, whatever the count. data-cols
   used to widen the tile to fill the row - one alt rendered 1360px, wider than its own key player
   (960px on that layout), which is the defect. Two columns at every count means one alt sits in
   the left half with white space beside it, three wrap 2 + 1, and every tile measures the same
   669px at 1440. data-cols stays on the element: work.js writes it and the count is still
   readable, it just no longer drives the column count. */
@media(min-width:768px){
  .jaltg,
  .jaltg[data-cols="1"],
  .jaltg[data-cols="2"],
  .jaltg[data-cols="3"]{grid-template-columns:repeat(2,minmax(0,1fr))}
}
.jaltg{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:clamp(12px,1.6vw,22px);list-style:none;margin:0;padding:0}
.jaltb{display:block;width:100%;padding:0;border:0;background:transparent;text-align:left;cursor:pointer}
/* J8 -- the label is a chip ON the frame (WF-1 .palt .l), and the tile playing in the key
 * player above says so. The tile is the positioning context, so .jaltp keeps the picture. */
.jaltb{position:relative}
.jaltp{display:block}
.jaltp img{display:block;width:100%;height:auto;aspect-ratio:16/9;object-fit:cover;background:#000}
/* R-D: the chip is a label on one line, so it truncates with an ellipsis and never wraps to a
 * second line inside the frame. WF-1 leaves .palt .l unconstrained because the drawing's own
 * labels are short; the amendment wins, and at 390 a long label plus " . playing" truncates
 * rather than stacking. The green outline and aria-pressed carry the state either way. */
.jaltl{position:absolute;left:12px;bottom:10px;font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:#fff;background:rgba(13,13,13,.6);padding:7px 9px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:calc(100% - 24px)}
.jaltb[aria-pressed="true"]{outline:2px solid var(--green);outline-offset:-2px}
.jaltb[aria-pressed="true"] .jaltl::after{content:" · playing"}
.jaltb:focus-visible{outline:2px solid var(--ink);outline-offset:3px}

/* rule 9 -- Photography . n photos, then "More photos (n)" in place. */
.pgaln{color:var(--muted-sm)}
.pmorewrap{margin:clamp(18px,2.4vw,26px) 0 0}
.pmore{border:1px solid var(--hair);background:transparent;padding:0 18px;min-height:44px;font:400 14px/1 "Inter Tight",system-ui,sans-serif;color:var(--ink);cursor:pointer;border-radius:2px}
.pmore:hover{border-color:var(--ink)}
.pmore:focus-visible{outline:2px solid var(--green);outline-offset:2px}
/* Gutters inside a job only (rule 9); /work and Related grids keep their hairline. */
.jobcard .pgrid{grid-template-columns:repeat(3,minmax(0,1fr));gap:clamp(12px,1.6vw,22px)}
/* round4c B5 G13 -- WF-1 v9 `.pgrid figure{aspect-ratio:3/2}`. The cells were uniform in WIDTH
 * already; each picture kept its own intrinsic height, so a portrait next to a landscape left
 * the ragged rows and the large white holes in the defect (rule 9's 3-across / 2-across grid
 * with gutters). The ratio is put on the IMG, not the figure, so a photo that carries a caption
 * still flows it underneath instead of overflowing a fixed-height box. The crop is the grid's
 * only: `data-full` is untouched, so the lightbox still opens the full frame (rule 5). */
.jobcard .pgrid figure img{aspect-ratio:3/2;width:100%;height:auto;object-fit:cover;display:block}
.jobcard .pgal{margin:clamp(34px,5vw,60px) var(--pad) 0}
.jobcard .pgal[hidden],.jobcard .jalt[hidden]{display:none}

/* rule 10 -- "All <brand> work ->" under Related. */
.wallbrand{margin:clamp(18px,2.4vw,26px) var(--pad) 0}
.wallbrand a{font-size:14px;color:var(--ink);text-decoration:none;border-bottom:1px solid var(--hair)}
.wallbrand a:hover{border-color:var(--green)}

@media(max-width:767px){
.jstage{grid-template-columns:minmax(0,1fr)}
.jobcard .pgrid{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media(max-width:480px){
/* WF-1 v9 (Thom, 390): the credits row is a TWO-COLUMN grid at phone width -- every label
   on one left edge, every value on the other, left-aligned, no wiggle and no centring. */
/* J15 -- WF-1 v9 at 390 is a TWO-COLUMN grid of label-over-value pairs sitting on two fixed
 * left edges, not a label column beside a value column. Each dt starts its own pair: the dt
 * spans nothing and the dd sits directly under it, two pairs per row. */
.jcred{display:grid;grid-auto-flow:row;grid-template-rows:none;grid-template-columns:repeat(2,minmax(0,1fr));column-gap:20px;row-gap:6px;align-items:start}
.jcred dt.jc,.jcred dd.jc{white-space:normal;min-width:0}
.jcred dt.jc:nth-of-type(odd),.jcred dd.jc:nth-of-type(odd){grid-column:1}
.jcred dt.jc:nth-of-type(even),.jcred dd.jc:nth-of-type(even){grid-column:2}
.jcred dt.jc:nth-of-type(n+3){margin-top:10px}
.jcred dt.jc:nth-of-type(1),.jcred dt.jc:nth-of-type(2){grid-row:1}
.jcred dd.jc:nth-of-type(1),.jcred dd.jc:nth-of-type(2){grid-row:2}
.jcred dt.jc:nth-of-type(3),.jcred dt.jc:nth-of-type(4){grid-row:3}
.jcred dd.jc:nth-of-type(3),.jcred dd.jc:nth-of-type(4){grid-row:4}
.jcred dt.jc:nth-of-type(5),.jcred dt.jc:nth-of-type(6){grid-row:5}
.jcred dd.jc:nth-of-type(5),.jcred dd.jc:nth-of-type(6){grid-row:6}
.jcred dt.jc:nth-of-type(7),.jcred dt.jc:nth-of-type(8){grid-row:7}
.jcred dd.jc:nth-of-type(7),.jcred dd.jc:nth-of-type(8){grid-row:8}
/* round4e D30: "at 390 full-width like the key". This was two tiles across on a phone, which is
   the one width where the key player is full-bleed - a related-work tile at half the key's width
   read as a thumbnail grid, not as more of the same campaign. One column, same width as the key. */
.jaltg{grid-template-columns:minmax(0,1fr)}
}

/* ===== round4b-260916 B4 -- /work, the filter bar (WF-2-filter-bar-260916.html v8) ======
   One bar, three rows, the chip IS the pill. No separate "active filters" row, no hidden
   groups, no "Showing 1 of 38". Numbers below are the drawing's.                        */

/* rule 1 -- H1 and lede share ONE column, so the headline no longer runs wider than the copy
   under it. The second paragraph is not rendered (build.mjs workBody).
   round4c B3 / R-G + WF-3 v2 Board A: that column is 2/3 of the page width on the page's own
   left edge, not a 760px centred block (`h1{max-width:66.6%}` / `.lede{max-width:66.6%}` in the
   drawing), and the gap under the nav is 20px, not 36px. At 390 the 2/3 cap is released - a
   two-thirds measure on a 390 screen is a 260px column. */
.wstrip1{display:block;padding-top:20px}
.wstrip1 h1,.wstrip1 .lede{max-width:66.6%}
.wstrip1 .lede{margin-top:1.1em}
@media(max-width:767px){.wstrip1{padding-top:16px}.wstrip1 h1,.wstrip1 .lede{max-width:none}}

/* ---- round4c B3 / R-G: the explore strip (WF-3 v2 Board A, rule 1) ----
   Values are the drawing's own: `.strip` is a wrapping flex row with a hairline top and bottom,
   `.lbl` is the 11px caps label, the dashed chip is `.chip.more`, `Filters` is the ink-outlined
   pill, search is the underline field. The strip sits on the same left edge as everything else
   (var(--pad)), which is why it uses margin rather than padding for the inset. */
.wexp{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:18px var(--pad) 0;padding:14px 0;border-top:1px solid var(--hair);border-bottom:1px solid var(--hair)}
.xlbl{font-family:"Inter Tight",system-ui,sans-serif;font-weight:500;font-size:11px;line-height:1;letter-spacing:.12em;text-transform:uppercase;color:var(--muted);margin-right:6px}
.xchips{display:flex;align-items:center;gap:10px;flex-wrap:wrap;list-style:none;margin:0;padding:0}
.xspacer{flex:1}
/* R-D: the dashed "+ n" is one line and truncates - it must never push Filters off the row. */
/* R-D truncation, but the cap has to be wide enough that the drawing's own label fits: at 1440
   "+ 8 industries · formats · services" is the full string in WF-3 Board A, and a 42ch cap was
   cutting it to "+ 8 INDUSTRIES · FORMATS · SERVI...". The ellipsis is the last resort for a
   narrow viewport, not the normal rendering. */
.xmore{border-style:dashed;color:var(--muted);background:var(--paper);cursor:pointer;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:inline-block}
.xfilters{display:inline-flex;align-items:center;gap:6px;min-height:44px;padding:0 16px;border:1px solid var(--ink);border-radius:999px;font-family:"Inter Tight",system-ui,sans-serif;font-weight:500;font-size:11px;line-height:1;letter-spacing:.08em;text-transform:uppercase;color:var(--ink);background:var(--paper);cursor:pointer;white-space:nowrap}
.xcar{display:inline-block;transition:transform .16s ease}
/* WF-3 Board A: five industries at 1440, three at 390. One set of chips, the last two hidden at
   390; one "+ n" label per width because the number is in the text. */
.xmore390{display:none}
@media(max-width:767px){.xhide390{display:none}.xmore1440{display:none}.xmore390{display:inline-block}}
.xfilters[aria-expanded="true"] .xcar{transform:rotate(180deg)}
.wexp .wsearch{margin:0}
/* The bar is closed by default and opens in place. `data-closed` is the server's opening state
   (R-G: closed unless a filter is already on, in which case the page opens with it visible);
   work.js flips it. No display:none on a no-JS page: without JS the attribute is still there,
   so the rule below would hide the chips from a reader who cannot open them. The guard is
   `html.js` - set by work.js the moment it runs - so no-JS keeps the full bar visible. */
.js .wfilters[data-closed]{display:none}
@media(max-width:767px){
.wexp{margin:14px var(--pad) 0;gap:8px}
.xlbl{width:100%;margin:0 0 6px}
.wexp .wsearch{flex:0 0 100%;width:100%}
.xfilters{margin-left:auto}
}

/* ---- round4c B3 / R-H, WF-3 v2 Board C: the result page ----
   The heading is the filter's name (work.js), and this is the muted count line under it with
   the way back. `.sub` in the drawing: 12px caps soft, pulled up under the heading. */
/* round4e D38: this line IS the results line - count then the reset, left-aligned, directly
   under the bar and above the grid. It is a flex row so the reset sits on the count's
   baseline row instead of wrapping under it. */
.wsub{font-family:"Inter Tight",system-ui,sans-serif;font-weight:400;font-size:12px;line-height:1;letter-spacing:.1em;text-transform:uppercase;color:var(--muted);margin:-6px var(--pad) 14px;display:flex;align-items:center;gap:8px}
.wsub a{color:inherit;text-decoration:none;border-bottom:1px solid var(--hair)}
.wsub a:hover,.wsub a:focus-visible{border-color:var(--green)}
/* round4e D38: the reset control takes the results line's type, not the 44px pill it wore in
   the Service row - a pill at 44px inside a 12px line would be the loudest thing on the page
   and D38 draws the line as "8 campaigns \00b7 Clear all \00d7". 6px of vertical padding keeps the
   pointer target at 24px for WCAG 2.5.8 AA while the text stays inline. */
.wsub .clr{display:inline-flex;align-items:center;min-height:0;padding:6px 0;border:0;border-radius:0;background:transparent;color:inherit;border-bottom:1px solid var(--hair)}
.wsub .clr.on,.wsub .clr.off{display:inline-flex;background:transparent;color:inherit;border:0;border-bottom:1px solid var(--hair)}
.wsub .clr:hover,.wsub .clr:focus-visible,.wsub .clr.on:hover,.wsub .clr.off:hover{border-color:var(--green)}
.wsubdot{color:var(--muted)}

/* The grid IS the count under six matches: 1 -> one tile at 1/3, 2 -> two at 2/3, 3-5 -> the
   normal 3-across. No empty cell, no placeholder tile. Six or more keeps the unfiltered grid,
   so there is no rule for it here. At 390 every result grid is one tile per row (WF-3's 390
   board), which is what the base grid already does, so the caps are released. */
/* minmax(0,1fr), not 1fr, for the reason measured on the wall at B4b: `1fr` is
   minmax(auto,1fr), so a long one-line nowrap caption widens its own column and the tiles
   in a result row come out two different sizes. R-C says same tile size; R-D says the
   label truncates instead. */
.wgrid[data-n="1"]{grid-template-columns:minmax(0,1fr);max-width:33.3%}
.wgrid[data-n="2"]{grid-template-columns:repeat(2,minmax(0,1fr));max-width:66.6%}
.wgrid[data-n="3"],.wgrid[data-n="4"],.wgrid[data-n="5"]{grid-template-columns:repeat(3,minmax(0,1fr))}
@media(max-width:767px){.wgrid[data-n]{max-width:none}}

/* rule 8 -- NOT sticky. Three rows would eat 160px of every scroll; the 44px recap below
   does that job instead. This overrides the round3 sticky bar deliberately. */
/* round4e D37: ONE hairline under the search field, not two. The field lives in .wexp, which
   carries border-top AND border-bottom; .wfilters carried a border-top of its own, so the
   boundary between the field and the INDUSTRY row drew two hairlines 15px apart. .wexp's
   bottom is the single line (it is also the only line when the bar is closed); .wfilters
   keeps its border-bottom, which is the line under the whole bar.
   round4e D37, part 2: the gap field->INDUSTRY label measured 64px against a 25px inter-row
   gap (12px cgrp padding each side + 1px hairline) - 2.5x, which read as a break in the bar
   rather than one more row. 14px .wexp padding + 1px hairline + 6px here + 4px on the first
   cgrp = 25px, equal to the inter-row gap. The 30px .chipgrps margin is home.css's global
   strip rule and is zeroed inside the bar rather than changed globally. */
.wfilters{position:static;top:auto;z-index:auto;display:block;padding:6px var(--pad) 10px;border-top:0}
/* rule 2 -- three labelled rows, the label ABOVE its chips, a hairline between groups. */
.wfilters .chipgrps{display:block;margin-top:0}
.wfilters .cgrp{padding:12px 0;border-top:1px solid var(--hair)}
.wfilters .cgrp:first-child{border-top:0;padding-top:4px}
.wfilters .cgh{display:block;margin:0 0 8px}
.wfilters .chips{display:flex;flex-wrap:wrap;gap:8px;margin:0}

/* rule 6 -- the active chip flips in place: ink fill, and it carries its OWN x to drop
   itself. The x is in the markup on every chip and is revealed by .on, so removing a filter
   never needs an element to be built and a no-JS reader is never shown a dead control. */
.chip .cx{display:none;margin-left:8px;font-size:15px;line-height:1}
.chip.on .cx{display:inline}
.chip.on{background:var(--ink);color:var(--paper);border-color:var(--ink)}

/* rule 6 -- the reset control is ALWAYS present at the row end. Two states, not two
   existences: muted when nothing is on, filled the moment something is. */
/* round4c fix r1 F3 (W5, rule 15): Service is a flex row whose last line carries the count
   and the reset at its end. The label keeps its own full-width line (flex 0 0 100%) - that
   shape passed review and is not what W5 was about. .chips is 0 1 auto so the ul sizes to its
   five pills instead of claiming the whole line and pushing .fend onto the next one. */
.cgrp-s{display:flex;flex-wrap:wrap;align-items:center;gap:10px 16px}
.cgrp-s .cgh{flex:0 0 100%;margin-bottom:0}
.cgrp-s .chips{flex:0 1 auto}
/* round4e D38: .fend is retired - the count and the reset left the Service row for the
   results line (build.mjs grid(), .wsub). The rule is kept as a no-op comment rather than
   silently deleted so the WF-2 v8 rule-15 lineage stays readable in the file. */
/* .fend{display:flex;align-items:center;gap:16px;margin-left:auto} */
.clrwrap{margin:0}
.clr{border-bottom:0;padding:0 14px;min-height:44px;border:1px solid var(--hair);border-radius:999px}
.clr.off{display:inline-flex;color:var(--muted-sm);border-color:var(--hair);background:transparent}
.clr.off:hover{color:var(--ink);border-color:var(--ink)}
.clr.on{background:var(--ink);color:var(--paper);border-color:var(--ink)}

/* rule 5 -- "n jobs": the number in view, one word. */
.wcount{margin:0}

/* rule 8 -- the 44px recap, under the 80px header, only once the bar has scrolled off. */
.wrecap{position:sticky;top:80px;z-index:30;display:flex;align-items:center;gap:12px;min-height:44px;padding:0 var(--pad);background:var(--paper);border-bottom:1px solid var(--hair);font-size:12px;letter-spacing:.06em;text-transform:uppercase;color:var(--muted-sm)}
.wrecap[hidden]{display:none}
.wrchip{display:inline-flex;align-items:center;padding:0 10px;height:26px;border-radius:999px;background:var(--ink);color:var(--paper);margin-right:6px}
.wrcount{margin-left:auto;white-space:nowrap}
/* round4e D38: the recap keeps count + Clear all (WF-2 rule 18). Same inline treatment as
   the results line; hidden by work.js while nothing is on. */
.wrclr{color:var(--ink);text-decoration:none;border-bottom:1px solid var(--hair);white-space:nowrap;padding:6px 0;display:inline-flex;align-items:center;margin-left:12px}
.wrclr[hidden]{display:none}
.wrclr:hover,.wrclr:focus-visible{border-color:var(--green)}
.wrup{color:var(--ink);text-decoration:none;border-bottom:1px solid var(--hair);white-space:nowrap}
.wrup:hover{border-color:var(--green)}

/* rule 5 -- the grid below: the six flagged tiles, 3 x 2 at desktop, then Load more (6). */
@media(min-width:1200px){
.wgrid{grid-template-columns:repeat(3,minmax(0,1fr));gap:0 1px}
}
@media(max-width:767px){
/* 390: the first chips plus a DASHED "+ n more" that opens in place. No swiping -- the row
   folds and unfolds, it never scrolls sideways. Active chips are sorted to the front of
   their row by work.js, so a filter that is on is never parked behind the fold. */
.wfilters .chips{flex-wrap:wrap;overflow:visible}
.chip.more{border-style:dashed;text-transform:none;letter-spacing:.02em}
.clr{width:auto}
}
