/* ============================================================
   CHIGUO — BAUHAUS DESIGN BIBLE
   Dessau, 1919–1933. Form follows function; ornament is absent.

   FIVE COLOURS. No gradients, no shadows, no blur, no rounding
   (except true circles). One typeface: Jost*, a Futura descendant
   drawn in direct homage to the Bauhaus geometric sans.

   THE CODE — colour and shape carry MEANING, never decoration:
     ● RED CIRCLE    designer · imagination · UP
     ■ BLUE SQUARE   engineer · grounded    · DOWN
     ▲ YELLOW TRI    craft    · made by hand
   Every rule below serves that code.
   ============================================================ */
:root{
  --cell:clamp(48px,4vw,58px);
  --cap:clamp(150px,24vh,185px);          /* rail caption: 6/4 split, floored at real content height */                    /* card model band; the WebGL layer matches it */
  --film-h:clamp(180px,30vh,320px); /* media height in the overlay strips */                    /* card model band; the WebGL layer matches it */   /* shared width for right-edge control cells */
  --paper:#EDE6D8; --paper-2:#E3DACA; --ink:#14110F;
  --red:#D93A28; --blue:#1B4E8C; --yellow:#F2C230;
  --rule:2px; --rule-thick:4px;
  --gut:clamp(16px,2.4vw,32px);
  --font:'Jost','PingFang SC','Hiragino Sans GB','Microsoft YaHei',ui-sans-serif,system-ui,sans-serif;
  --font-cn-display:'Jost','Noto Sans SC','PingFang SC','Microsoft YaHei',sans-serif;
}
*,*::before,*::after{box-sizing:border-box}
html{scroll-behavior:smooth;background:var(--paper)}
body{margin:0;background:var(--paper);color:var(--ink);font-family:var(--font);font-weight:400;-webkit-font-smoothing:antialiased}
img{display:block;max-width:100%}
a{color:var(--ink);text-decoration:none}
a:hover{color:var(--red)}
::selection{background:var(--yellow);color:var(--ink)}

/* language visibility ------------------------------------------------ */
html[data-lang="en"] [data-lang="cn"],html[data-lang="cn"] [data-lang="en"]{display:none!important}

/* ---- primitives: the alphabet -------------------------------------- */
/* Two independent axes: SHAPE = discipline (circle design / square engineering /
   triangle personal), COLOUR = weight (red core / yellow notable / blue supporting).
   Each primitive takes an optional --c so any shape can carry any colour; the
   fallback keeps every existing decorative mark at its original hue. */
.bh-dot{display:block;border-radius:50%;background:var(--c,var(--red))}
.bh-sq{display:block;background:var(--c,var(--blue))}
.bh-tri{display:block;width:0;height:0;background:none;border-left:var(--s,18px) solid transparent;border-right:var(--s,18px) solid transparent;border-bottom:calc(var(--s,18px)*1.6) solid transparent;border-bottom-color:var(--c,var(--yellow))}
.bh-half{display:block;background:var(--red);border-radius:999px 999px 0 0}
.bh-arc{display:block;background:var(--blue);border-radius:100% 0 0 0}

/* ---- masthead ------------------------------------------------------ */
.bh-mast{position:fixed;inset:0 0 auto 0;z-index:80;display:flex;align-items:stretch;justify-content:space-between;height:56px;background:var(--paper);border-bottom:var(--rule) solid var(--ink)}
.bh-mast__mark{display:flex;align-items:center;gap:10px;padding:0 18px;border-right:var(--rule) solid var(--ink)}
.bh-mast__mark .bh-dot{width:14px;height:14px}
.bh-mast__mark .bh-sq{width:14px;height:14px}
.bh-mast__mark .bh-tri{--s:8px}
.bh-mast__name{font-weight:700;font-size:15px;letter-spacing:.22em;text-transform:uppercase;margin-left:6px}
.bh-mast__ver{display:flex;align-items:center;padding:0 16px;font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--ink);opacity:.55;border-right:var(--rule) solid var(--ink)}
.bh-mast__spacer{flex:1}
.bh-lang{display:flex;border-left:var(--rule) solid var(--ink)}
.bh-lang button{appearance:none;border:0;border-left:var(--rule) solid var(--ink);background:var(--paper);color:var(--ink);font-family:var(--font);font-weight:700;font-size:12px;letter-spacing:.14em;width:var(--cell);padding:0;cursor:pointer;display:flex;align-items:center;justify-content:center}
.bh-lang button:first-child{border-left:0}
.bh-lang button[aria-pressed="true"]{background:var(--ink);color:var(--paper)}
.bh-lang button:hover[aria-pressed="false"]{background:var(--yellow)}

/* ---- shared section frame ------------------------------------------ */
/* The fixed masthead is 56px; whatever sits at document top needs that offset.
   It used to live on .bh-hero, but the projects section moved above the hero. */
main{padding-top:56px}
.bh-sec{position:relative;z-index:2;background:var(--paper);border-bottom:var(--rule) solid var(--ink)}
.bh-sec[id],[id]{scroll-margin-top:58px}
.bh-label{display:flex;align-items:center;gap:12px;font-size:11px;font-weight:700;letter-spacing:.22em;text-transform:uppercase;padding:14px var(--gut);border-bottom:var(--rule) solid var(--ink)}
.bh-label .bh-dot,.bh-label .bh-sq{width:10px;height:10px}
.bh-label .bh-tri{--s:6px}
.bh-label b{font-weight:700}
.bh-label span{opacity:.5;font-weight:500}

/* ---- hero -----------------------------------------------------------
   Left column is identity (type over the turning figure). Right column is
   the WORK, above the fold — that was the whole point of the rebuild. */
.bh-hero-zone{position:relative}
.bh-hero{position:relative;z-index:1;display:grid;grid-template-columns:minmax(0,4fr) minmax(0,8fr);grid-template-rows:minmax(0,1fr) auto;height:calc(100vh - 56px);border-bottom:var(--rule) solid var(--ink)}
.bh-hero__left{grid-row:1;grid-column:1;display:flex;flex-direction:column;min-height:0;border-right:var(--rule) solid var(--ink);padding:clamp(20px,3vh,38px) var(--gut) 0}
.bh-hero__eyebrow{display:flex;align-items:center;gap:10px;font-size:11px;font-weight:700;letter-spacing:.24em;text-transform:uppercase;margin-bottom:clamp(12px,2vh,22px)}
.bh-hero__eyebrow .bh-dot{width:9px;height:9px}
.bh-hero h1{margin:0;font-weight:900;font-size:clamp(34px,min(5.4vw,9vh),86px);line-height:.86;letter-spacing:-.035em;text-transform:uppercase}
.bh-hero h1 .r{color:var(--red)}
.bh-hero h1 .b{color:var(--blue)}
.bh-hero__fig{position:relative;flex:1 0 62%;min-height:clamp(180px,26vh,340px);display:flex;align-items:flex-end;justify-content:center;overflow:hidden;margin-top:clamp(10px,2vh,20px)}
.bh-hero__fig canvas{position:relative;z-index:2;width:auto;height:100%;max-width:100%;aspect-ratio:660/880;object-fit:contain;object-position:center bottom}
.bh-hero__plate{position:absolute;z-index:0;width:104%;aspect-ratio:1;bottom:-40%;left:-26%;background:var(--yellow);border-radius:50%}
.bh-hero__stack{grid-row:1;grid-column:2;display:flex;flex-direction:column;min-height:0}
.bh-hero__foot{grid-row:2;grid-column:1/-1;display:block;border-top:var(--rule) solid var(--ink)}
.bh-hero__bio{padding:13px var(--gut);border-bottom:var(--rule) solid var(--ink)}
.bh-hero__bio p{margin:0;flex:1;min-width:0;font-size:clamp(13px,1vw,16px);line-height:1.55}
.bh-hero__bio em{font-style:normal;font-weight:700;background:none;padding:0;box-shadow:inset 0 -2px 0 var(--ink)}
.bh-hero__scroll{display:grid;grid-template-columns:1fr 1fr}
.bh-hero__scroll a{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:16px var(--gut);font-weight:700;font-size:clamp(12px,1.1vw,15px);letter-spacing:.06em;text-transform:uppercase}
.bh-hero__scroll a:first-child{border-right:var(--rule) solid var(--ink)}
.bh-hero__scroll a:hover{background:var(--yellow);color:var(--ink)}
.bh-hero__scroll .k{display:flex;align-items:center;gap:12px}
.bh-hero__scroll .bh-dot,.bh-hero__scroll .bh-sq{width:14px;height:14px}
.bh-hero__scroll .n{font-size:22px;line-height:1}

/* ---- project rail ---------------------------------------------------
   Cards are real HTML and always readable; the single WebGL canvas is
   pinned over the slot band and pans with scrollLeft, so each model sits
   on its own card without paying for one context per project. */
.bh-strip__bar{display:flex;align-items:stretch;gap:12px;padding:0 0 0 var(--gut);min-height:52px;border-bottom:var(--rule) solid var(--ink);font-size:11px;font-weight:700;letter-spacing:.2em;text-transform:uppercase;flex-wrap:wrap}
.bh-strip__bar .bh-dot,.bh-strip__bar .bh-sq{width:10px;height:10px;align-self:center}
.bh-strip__bar>b,.bh-strip__bar>span:not([class]){align-self:center}
.bh-strip__bar b{font-weight:700}
.bh-strip__bar>span:not([class]){opacity:.5;font-weight:500;letter-spacing:.1em;text-transform:none}
.bh-strip__nav{display:flex;gap:0;margin-left:auto;align-self:stretch}
.bh-strip__nav button{appearance:none;border:0;border-left:var(--rule) solid var(--ink);background:var(--paper);color:var(--ink);font-family:var(--font);font-size:0;font-weight:700;width:var(--cell);align-self:stretch;cursor:pointer;display:flex;align-items:center;justify-content:center}
.bh-strip__nav button:hover{background:var(--yellow)}
.bh-rail{position:relative;flex:1;min-height:0;overflow:hidden}
.bh-rail__gl{position:absolute;z-index:1;top:0;left:0;width:100%;height:calc(100% - var(--cap) - var(--rule));pointer-events:none}
.bh-rail__track{position:relative;z-index:2;height:100%;display:flex;column-gap:0;overflow-x:auto;overflow-y:hidden;scroll-snap-type:x mandatory;scrollbar-width:none}
.bh-rail__track::-webkit-scrollbar{display:none}
.bh-rcard{flex:0 0 clamp(190px,20vw,260px);scroll-snap-align:start;display:grid;grid-template-rows:minmax(0,1fr) var(--cap);border-right:var(--rule) solid var(--ink);background:none;appearance:none;padding:0;font-family:var(--font);color:inherit;text-align:left;cursor:pointer}
.bh-rcard__slot{position:relative;border-bottom:var(--rule) solid var(--ink)}
.bh-rcard__num{position:absolute;top:0;left:0;display:flex;align-items:center;justify-content:center;width:34px;height:34px;background:var(--ink);color:var(--paper);font-weight:700;font-size:12px}
.bh-rcard__mark{position:absolute;top:0;right:0;width:34px;height:34px;display:flex;align-items:center;justify-content:center;border-left:var(--rule) solid var(--ink);border-bottom:var(--rule) solid var(--ink)}
.bh-rcard__mark .bh-dot,.bh-rcard__mark .bh-sq{width:13px;height:13px}
.bh-rcard__mark .bh-tri{--s:7px}
.bh-rcard__txt{padding:11px var(--gut) 12px;display:flex;flex-direction:column;gap:3px;min-height:0}
.bh-rcard__txt h3{margin:0;font-weight:700;font-size:clamp(15px,1.35vw,22px);line-height:1.14;letter-spacing:-.012em}
.bh-rcard__sub{font-size:13px;line-height:1.4;opacity:.62}
.bh-rcard__role{margin-top:6px;padding-top:0;font-size:11px;font-weight:700;letter-spacing:.12em;text-transform:uppercase}
.bh-rcard:hover .bh-rcard__txt{background:var(--yellow)}
.bh-rcard:focus-visible{outline:var(--rule-thick) solid var(--blue);outline-offset:-4px}

/* ---- manifesto ------------------------------------------------------ */
.bh-mani{position:relative;z-index:2;background:var(--paper);display:grid;grid-template-columns:1fr 2fr;border-top:var(--rule) solid var(--ink);border-bottom:var(--rule) solid var(--ink)}
.bh-mani__art{position:relative;border-right:var(--rule) solid var(--ink);min-height:clamp(190px,24vw,300px);overflow:hidden}
.bh-mani__body{padding:clamp(24px,3.4vw,48px) var(--gut);display:flex;flex-direction:column;justify-content:center}
.bh-mani__k{display:flex;align-items:center;gap:12px;min-height:46px;font-size:11px;font-weight:700;letter-spacing:.24em;text-transform:uppercase;margin-bottom:clamp(14px,2vw,22px);padding:12px 0;border-bottom:var(--rule) solid var(--ink);color:#5b554c}
.bh-mani__k .bh-dot,.bh-mani__k .bh-sq{width:9px;height:9px}
.bh-mani__k .n{margin-left:auto;font-size:18px;line-height:1;letter-spacing:0}
.bh-mani__k:hover{color:var(--ink);background:var(--yellow)}
.bh-mani h2{margin:0 0 clamp(12px,1.6vw,18px);font-weight:900;font-size:clamp(28px,4vw,58px);line-height:1.02;letter-spacing:-.03em;text-transform:uppercase}
.bh-mani p{margin:0;font-size:clamp(16px,1.5vw,20px);line-height:1.5;max-width:52ch}
.bh-mani .cta{display:block;margin-top:14px;font-weight:700;font-size:clamp(18px,1.8vw,23px);line-height:1.2}
.bh-mani--up .bh-mani__art{background:var(--red)}
.bh-mani--up h2{color:var(--red)}
.bh-mani--up .bh-mani__art .bh-half{position:absolute;left:50%;top:0;bottom:auto;width:64%;aspect-ratio:2/1;transform:translateX(-50%);background:var(--paper);border-radius:0 0 999px 999px}
.bh-mani--down{grid-template-columns:2fr 1fr}
.bh-mani--down .bh-mani__body{grid-column:1;grid-row:1}
.bh-mani--down .bh-mani__art{grid-column:2;grid-row:1;background:var(--blue);border-right:0;border-left:var(--rule) solid var(--ink)}
.bh-mani--down h2{color:var(--blue)}
.bh-mani--down .bh-mani__art .bh-sq{position:absolute;left:50%;top:auto;bottom:-23%;width:46%;aspect-ratio:1;transform:translateX(-50%);background:var(--paper)}

/* ---- project grid --------------------------------------------------- */
.bh-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr))}
.bh-card{position:relative;display:flex;flex-direction:column;border-right:var(--rule) solid var(--ink);border-bottom:var(--rule) solid var(--ink);background:var(--paper);cursor:pointer;text-align:left;font-family:var(--font);appearance:none;padding:0;color:inherit}
.bh-card:nth-child(3n){border-right:0}
.bh-card__shot{position:relative;aspect-ratio:4/3;overflow:hidden;background:var(--paper-2);border-bottom:var(--rule) solid var(--ink)}
.bh-card__shot img{width:100%;height:100%;object-fit:cover;filter:saturate(.92)}
.bh-card__num{position:absolute;top:0;left:0;z-index:2;display:flex;align-items:center;justify-content:center;width:44px;height:44px;background:var(--ink);color:var(--paper);font-weight:700;font-size:13px;letter-spacing:.04em}
.bh-card__mark{position:absolute;top:0;right:0;z-index:2;width:44px;height:44px;display:flex;align-items:center;justify-content:center;background:var(--paper);border-left:var(--rule) solid var(--ink);border-bottom:var(--rule) solid var(--ink)}
.bh-card__mark .bh-dot,.bh-card__mark .bh-sq{width:16px;height:16px}
.bh-card__mark .bh-tri{--s:9px}
.bh-card__txt{padding:16px var(--gut) 20px;flex:1;display:flex;flex-direction:column;gap:6px}
.bh-card__txt h3{margin:0;font-weight:700;font-size:clamp(16px,1.5vw,22px);line-height:1.14;letter-spacing:-.012em}
.bh-card__sub{font-size:13px;line-height:1.45;opacity:.62}
.bh-card__role{margin-top:auto;padding-top:12px;font-size:11px;font-weight:700;letter-spacing:.12em;text-transform:uppercase}
.bh-card:hover .bh-card__shot img{filter:saturate(1)}
.bh-card:hover .bh-card__txt{background:var(--yellow)}
.bh-card:focus-visible{outline:var(--rule-thick) solid var(--blue);outline-offset:-4px}

/* geometric stand-in where no photograph exists — a composition, never a
   grey placeholder. Two primitives, one bled off the edge, per Bauhaus
   poster practice. */
.bh-card__shot--art{position:relative;overflow:hidden}
.bh-card__shot--art.art-dot{background:var(--red)}
.bh-card__shot--art.art-sq{background:var(--blue)}
.bh-card__shot--art.art-tri{background:var(--yellow)}
.bh-card__shot--art .a1{position:absolute;right:-14%;bottom:-18%;width:66%;aspect-ratio:1;background:var(--paper);border-radius:0}
.bh-card__shot--art.art-dot .a1{border-radius:50%}
.bh-card__shot--art .a2{position:absolute;left:12%;top:14%;width:26%;aspect-ratio:1}
.bh-card__shot--art .a2.bh-tri{width:0;aspect-ratio:auto;--s:26px}
.bh-ov__art{position:relative;height:clamp(220px,42vh,420px);overflow:hidden}
.bh-ov__art.art-dot{background:var(--red)}
.bh-ov__art.art-sq{background:var(--blue)}
.bh-ov__art.art-tri{background:var(--yellow)}
.bh-ov__art .a1{position:absolute;right:-10%;bottom:-14%;width:62%;aspect-ratio:1;background:var(--paper)}
.bh-ov__art.art-dot .a1{border-radius:50%}
.bh-ov__art .a2{position:absolute;left:14%;top:16%;width:22%;aspect-ratio:1}
.bh-ov__art .a2.bh-tri{width:0;aspect-ratio:auto;--s:40px}

/* ---- resume --------------------------------------------------------- */
.bh-res{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));align-items:stretch;background:linear-gradient(var(--ink),var(--ink)) 50% 0/var(--rule) 100% no-repeat}

.bh-res__h{display:flex;align-items:center;gap:10px;padding:14px var(--gut);font-size:11px;font-weight:700;letter-spacing:.22em;text-transform:uppercase;background:var(--ink);color:var(--paper)}
.bh-res__h .bh-dot,.bh-res__h .bh-sq{width:10px;height:10px}
.bh-res__h .bh-tri{--s:6px}
.bh-item{display:grid;grid-template-columns:auto 1fr;gap:0 16px;padding:18px var(--gut);border-bottom:var(--rule) solid var(--ink)}
.bh-item:last-child{border-bottom:0}
.bh-item__when{font-size:11px;font-weight:700;letter-spacing:.1em;padding-top:3px;white-space:nowrap;color:#5b554c}
.bh-item__what b{display:block;font-weight:700;font-size:clamp(15px,1.35vw,18px);line-height:1.22}
.bh-item__what span{display:block;margin-top:4px;font-size:13px;line-height:1.55;opacity:.66}
.bh-item__what ul{margin:8px 0 0;padding-left:15px}
.bh-item__what li{font-size:13px;line-height:1.6;opacity:.78;margin-bottom:3px}
.bh-item a{font-weight:700;border-bottom:var(--rule) solid var(--red)}

/* ---- footer --------------------------------------------------------- */
.bh-foot{display:grid;grid-template-columns:1fr 1fr 1fr 1fr}
.bh-foot__q{grid-column:1/4;padding:clamp(30px,5vw,64px) var(--gut);border-right:var(--rule) solid var(--ink)}
.bh-foot__q p{margin:0 0 clamp(18px,2.6vw,30px);font-weight:700;font-size:clamp(19px,2vw,28px);line-height:1.1;letter-spacing:-.02em;max-width:22ch}
.bh-foot__mail{display:inline-flex;align-items:center;gap:14px;font-weight:700;font-size:clamp(14px,1.4vw,19px);border-bottom:var(--rule-thick) solid var(--red);padding-bottom:4px}
.bh-foot__mail:hover{background:var(--yellow);color:var(--ink)}
.bh-foot__art{position:relative;overflow:hidden;background:var(--yellow);min-height:200px}
.bh-foot__art .bh-arc{position:absolute;right:0;bottom:0;width:78%;aspect-ratio:1}
.bh-foot__art .bh-dot{position:absolute;left:14%;top:14%;width:30%;aspect-ratio:1}
.bh-colophon{display:flex;flex-wrap:wrap;gap:8px 26px;padding:14px var(--gut);border-top:var(--rule) solid var(--ink);font-size:11px;letter-spacing:.14em;text-transform:uppercase;opacity:.6}
/* legend: the two-axis key, spelled out so the marks are readable, not decoration */
.bh-legend{display:flex;flex-wrap:wrap;gap:12px 48px;padding:18px var(--gut);border-top:var(--rule) solid var(--ink);font-size:11px;letter-spacing:.1em;text-transform:uppercase}
.bh-legend__ax{display:flex;align-items:center;gap:20px;flex-wrap:wrap}
.bh-legend__h{font-weight:700;opacity:.45}
.bh-legend__k{display:inline-flex;align-items:center;gap:9px;font-weight:700}
.bh-legend__k i{display:block;width:13px;height:13px;flex:none}
.bh-legend__k i.bh-tri{--s:7px;width:0;height:0}
.bh-legend__k i.bh-sw{width:15px;height:15px}

/* ---- project overlay ------------------------------------------------ */
.bh-ov{position:fixed;inset:0;z-index:120;display:none;background:var(--paper)}
.bh-ov.is-on{display:grid;grid-template-rows:56px 1fr}
.bh-ov__bar{display:flex;align-items:stretch;justify-content:space-between;border-bottom:var(--rule) solid var(--ink)}
.bh-ov__bar .t{display:flex;align-items:center;gap:12px;padding:0 var(--gut);font-weight:700;font-size:12px;letter-spacing:.2em;text-transform:uppercase}
.bh-ov__bar .t .bh-dot,.bh-ov__bar .t .bh-sq{width:11px;height:11px}
.bh-ov__bar .t .bh-tri{--s:7px}
.bh-ov__x{appearance:none;border:0;border-left:var(--rule) solid var(--ink);background:var(--paper);font-family:var(--font);font-size:20px;font-weight:500;width:56px;cursor:pointer;color:var(--ink)}
.bh-ov__x:hover{background:var(--red);color:var(--paper)}
.bh-ov__body{display:block;overflow-y:auto}
.bh-ov__banner{position:relative;border-bottom:var(--rule) solid var(--ink);background:var(--paper-2)}
.bh-ov__banner img{width:100%;height:clamp(220px,42vh,420px);object-fit:cover;display:block}
.bh-ov__banner[hidden]{display:none}
.bh-ov__txt{padding:clamp(24px,3vw,44px) var(--gut)}
.bh-ov__txt .role{display:flex;align-items:center;gap:14px;font-size:11px;letter-spacing:.2em;text-transform:uppercase;padding-bottom:9px;margin-bottom:20px;border-bottom:var(--rule) solid var(--ink)}
.bh-ov__txt .role::before{content:"";flex:none;width:9px;height:9px;background:var(--mark)}
.bh-ov__txt .role .k{font-weight:500;opacity:.55}
.bh-ov__txt .role .t{font-weight:700}
.bh-ov__txt .role .k + .t::before{content:"/";margin-right:14px;opacity:.35;font-weight:500}
.bh-ov__txt h2{margin:0 0 6px;font-weight:900;font-size:clamp(26px,3.2vw,46px);line-height:.98;letter-spacing:-.03em;text-transform:uppercase}
.bh-ov__txt .sub{font-size:13px;letter-spacing:.04em;opacity:.6;margin-bottom:20px}
.bh-ov__txt p{margin:0 0 16px;font-size:clamp(14px,1.05vw,16px);line-height:1.7;max-width:74ch}

/* filmstrip — the same horizontal mechanic as the hero rail, so the whole site
   has ONE way to move sideways through things. */
.bh-film{border-top:var(--rule) solid var(--ink)}
.bh-film[hidden]{display:none}
.bh-film__bar{display:flex;align-items:center;gap:12px;padding:12px var(--gut);border-bottom:var(--rule) solid var(--ink);font-size:11px;font-weight:700;letter-spacing:.2em;text-transform:uppercase}
.bh-film__bar .bh-sq,.bh-film__bar .bh-dot{width:10px;height:10px}
.bh-film__bar #ovCount{opacity:.5;font-weight:500;letter-spacing:.1em;text-transform:none}
.bh-film__bar .bh-strip__nav{margin-left:auto}
.bh-film__track{display:flex;overflow-x:auto;overflow-y:hidden;scroll-snap-type:x mandatory;scrollbar-width:none}
.bh-film__track::-webkit-scrollbar{display:none}
.bh-film__track figure{flex:0 0 clamp(280px,42vw,520px);scroll-snap-align:start;margin:0;display:flex;flex-direction:column;border-right:var(--rule) solid var(--ink)}
.bh-film__track img{width:100%;height:var(--film-h);object-fit:cover;display:block;border-bottom:var(--rule) solid var(--ink)}
.bh-film__track figcaption{padding:10px var(--gut);font-size:13px;line-height:1.5;opacity:.72;flex:1}
.bh-ov__txt .go{display:inline-flex;align-items:center;gap:12px;margin-top:8px;padding:14px 22px;background:var(--blue);color:var(--paper);font-weight:700;font-size:13px;letter-spacing:.14em;text-transform:uppercase}
.bh-ov__txt .go:hover{background:var(--red);color:var(--paper)}

/* ---- responsive ----------------------------------------------------- */
@media (max-width:1000px){
  .bh-hero{grid-template-columns:minmax(0,1fr);grid-template-rows:auto auto auto;height:auto}
  .bh-hero__stack,.bh-rail{min-width:0}
  .bh-hero__left{grid-row:1;grid-column:1;border-right:0;border-bottom:var(--rule) solid var(--ink);min-height:58vh}
  .bh-hero__stack{grid-row:3;grid-column:1;min-height:70vh}
  .bh-hero__foot{grid-row:2;grid-column:1}
  .bh-hero__fig{min-height:0;height:auto}
  .bh-hero__fig canvas{width:min(72%,460px,calc(52vh * 660 / 880));height:auto;max-height:none}
  .bh-hero__bio{border-right:0;border-bottom:var(--rule) solid var(--ink)}
  .bh-rcard{flex-basis:clamp(170px,30vw,220px)}
  .bh-grid{grid-template-columns:repeat(2,minmax(0,1fr))}
  .bh-card:nth-child(3n){border-right:var(--rule) solid var(--ink)}
  .bh-card:nth-child(2n){border-right:0}
}
@media (max-width:680px){
  .bh-hero__left{grid-row:1;grid-column:1;border-right:0;border-bottom:var(--rule) solid var(--ink);min-height:72vh}
  .bh-hero__fig{min-height:0;height:auto}
  .bh-hero__fig canvas{width:min(86%,380px,calc(56vh * 660 / 880));height:auto;max-height:none}
  .bh-hero__stack{grid-row:3;grid-column:1;min-height:74vh}
  .bh-hero__foot{grid-row:2;grid-column:1}
  /* the bio's row layout left the paragraph 213px beside the button — nine lines.
     Here the introduction is the first thing read, so it takes the full width. */
  .bh-hero__bio{flex-direction:column;align-items:flex-start;gap:12px}
  .bh-hero__bio{border-right:0;border-bottom:var(--rule) solid var(--ink)}
  .bh-rcard{flex-basis:76vw}
  .bh-strip__bar{font-size:10px;letter-spacing:.12em}
  .bh-strip__bar>span:not([class]){display:none}
  .bh-mast__ver{display:none}
  .bh-hero{grid-template-columns:minmax(0,1fr);grid-template-rows:auto auto auto;height:auto;min-height:0}
  .bh-mani{grid-template-columns:1fr}
  .bh-mani__art{border-right:0;border-bottom:var(--rule) solid var(--ink);min-height:150px}
  .bh-mani--down{grid-template-columns:1fr}
  .bh-mani--down .bh-mani__art{grid-column:1;grid-row:1;border-left:0;border-bottom:var(--rule) solid var(--ink)}
  .bh-mani--down .bh-mani__body{grid-column:1;grid-row:2}
  .bh-grid{grid-template-columns:1fr}
  .bh-card,.bh-card:nth-child(3n),.bh-card:nth-child(2n){border-right:0}
  /* single column: the container's centre divider has nothing to divide */
  .bh-res{grid-template-columns:1fr;background:none}
  .bh-res__col:not(:last-child){border-bottom:var(--rule) solid var(--ink)}
  .bh-foot{grid-template-columns:1fr}
  .bh-foot__q{grid-column:1/-1;border-right:0;border-bottom:var(--rule) solid var(--ink)}
  .bh-foot__art{min-height:150px}
}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}}

/* case-study beats — numbered, ruled, one idea per band. The number column is
   the Bauhaus device: order made visible instead of decorated. */
.bh-beat{display:grid;grid-template-columns:auto 1fr;gap:0 18px;padding:20px 0;border-top:var(--rule) solid var(--ink)}
.bh-beat:first-child{margin-top:8px}
.bh-beat__k{font-weight:900;font-size:15px;letter-spacing:.02em;color:var(--mark,var(--blue));padding-top:2px}
.bh-beat__b h3{margin:0 0 7px;font-weight:700;font-size:clamp(15px,1.35vw,19px);line-height:1.2;letter-spacing:-.01em}
.bh-beat__b p{margin:0;font-size:clamp(13px,1.02vw,15px);line-height:1.7}
#ovStudy{margin-bottom:24px}

/* ---- résumé download band ------------------------------------------
   Two equal cells, hard-ruled, no ornament. The mark block carries the
   colour code (■ engineer / ● designer) so the pair reads as one system
   rather than two buttons. This is the first thing a recruiter needs, so
   it sits above the résumé itself, at full width. */
.bh-dl{display:block;border-bottom:var(--rule) solid var(--ink)}
.bh-dl__card{display:grid;grid-template-columns:auto 1fr;align-items:center;gap:0 18px;padding:0;background:var(--paper);transition:background .15s ease}
.bh-dl__card:hover{background:var(--yellow);color:var(--ink)}

.bh-dl__mark{display:flex;align-items:center;justify-content:center;width:clamp(66px,7vw,94px);align-self:stretch;border-right:var(--rule) solid var(--ink)}
.bh-dl__mark{background:var(--yellow)}
/* the mark glyph is a triangle in both languages; clip-path rather than the
   border-triangle utility, whose zero height collapses inside a flex cell */
.bh-dl__mark .bh-sq,.bh-dl__mark .bh-dot{width:32px;height:28px;background:var(--paper);border-radius:0;clip-path:polygon(50% 0,100% 100%,0 100%)}
.bh-dl__body{display:flex;flex-direction:column;gap:4px;padding:26px 0}
.bh-dl__body b{font-weight:700;font-size:clamp(19px,1.9vw,26px);line-height:1.1;letter-spacing:-.015em}
.bh-dl__body em{font-style:normal;font-size:13.5px;line-height:1.4;opacity:.62}
.bh-dl__card:focus-visible{outline:var(--rule-thick) solid var(--ink);outline-offset:-4px}

/* ---- recruiter one-liner ------------------------------------------- */
.bh-pitch{border:var(--rule) solid var(--ink);padding:16px 18px;margin-bottom:clamp(20px,3vw,32px);max-width:64ch}
.bh-pitch__k{display:block;font-size:10.5px;font-weight:700;letter-spacing:.2em;text-transform:uppercase;opacity:.5;margin-bottom:8px}
.bh-pitch p{margin:0 0 12px;font-size:13px;line-height:1.62;font-weight:400;max-width:none}
.bh-pitch__copy{appearance:none;border:0;background:var(--ink);color:var(--paper);font-family:var(--font);font-weight:700;font-size:11px;letter-spacing:.16em;text-transform:uppercase;padding:8px 16px;cursor:pointer}
.bh-pitch__copy:hover{background:var(--red)}
.bh-pitch__copy.is-done{background:var(--blue)}

/* ---- masthead nav --------------------------------------------------- */
.bh-nav{display:flex}
.bh-nav a{display:flex;align-items:center;padding:0 18px;border-right:var(--rule) solid var(--ink);font-weight:700;font-size:11.5px;letter-spacing:.16em;text-transform:uppercase}
.bh-nav a:hover{background:var(--yellow);color:var(--ink)}

@media (max-width:680px){
  .bh-dl{grid-template-columns:1fr}
  .bh-dl__card{border-right:0;border-bottom:var(--rule) solid var(--ink)}
  .bh-dl__card:last-child{border-bottom:0}
  .bh-nav a{padding:0 12px;font-size:10.5px;letter-spacing:.1em}
}

/* Chinese headlines need room: the glyph box is full-height, so the tight
   Latin line-height collides. Applies to every display size on the page. */
html[data-lang="cn"] .bh-mani h2,html[data-lang="cn"] .bh-hero h1,
html[data-lang="cn"] .bh-ov__txt h2{line-height:1.14;letter-spacing:0}
html[data-lang="cn"] .bh-foot__q p{line-height:1.32}

/* role block — {project type} above {my title}, always two lines so the
   pairing reads the same on every card. Type is quieter; the title is the
   claim, so it carries the weight. */
.bh-rcard__role,.bh-card__role{display:flex;flex-direction:column;gap:2px}
.bh-rcard__role .k,.bh-card__role .k{font-weight:500;opacity:.55}
.bh-rcard__role .t,.bh-card__role .t{font-weight:700}

/* the hero bio IS the forwarding line now — one copy affordance, up top,
   where a recruiter meets it instead of hunting the footer for it. */
.bh-hero__bio{display:flex;flex-direction:row;align-items:center;gap:16px}
.bh-hero__bio .bh-pitch__copy{flex:0 0 auto}

/* short laptops: the foot row must not eat the rail. Bio and CTA share a line
   and the type steps down, instead of the hero growing past the fold. */
@media (max-height:700px) and (min-width:681px){
  .bh-hero__bio{padding:9px var(--gut);gap:12px}
  .bh-hero__bio p{font-size:11.5px;line-height:1.48}
  .bh-hero__bio .bh-pitch__copy{padding:12px 22px;font-size:10px}
  .bh-hero__scroll a{padding:10px var(--gut);font-size:12px}
  .bh-hero__eyebrow{margin-bottom:8px}
}
@media (max-width:680px){
  .bh-film__track figure{flex-basis:84vw}
  .bh-ov__banner img{height:clamp(180px,32vh,260px)}
}

/* rail arrows — solid triangles from the page's shape alphabet (● ■ ▲), drawn
   with borders so they stay crisp at any size and inherit the hover colour. */
.bh-strip__nav button::before{content:"";display:block;width:0;height:0;
  border-top:8px solid transparent;border-bottom:8px solid transparent}
.bh-strip__nav button[data-rail-step="-1"]::before,
.bh-strip__nav button[data-film-step="-1"]::before,
.bh-strip__nav button[data-clip-step="-1"]::before{border-right:11px solid var(--ink)}
.bh-strip__nav button[data-rail-step="1"]::before,
.bh-strip__nav button[data-film-step="1"]::before,
.bh-strip__nav button[data-clip-step="1"]::before{border-left:11px solid var(--ink)}
.bh-strip__nav button:hover{background:var(--ink)}
.bh-strip__nav button:hover[data-rail-step="-1"]::before,
.bh-strip__nav button:hover[data-film-step="-1"]::before,
.bh-strip__nav button:hover[data-clip-step="-1"]::before{border-right-color:var(--yellow)}
.bh-strip__nav button:hover[data-rail-step="1"]::before,
.bh-strip__nav button:hover[data-film-step="1"]::before,
.bh-strip__nav button:hover[data-clip-step="1"]::before{border-left-color:var(--yellow)}
.bh-film__bar{align-items:stretch;padding:0 0 0 var(--gut);min-height:48px}
.bh-film__bar .bh-sq,.bh-film__bar .bh-dot,.bh-film__bar>b,.bh-film__bar>span:not([class]){align-self:center}
.bh-film__bar .bh-strip__nav{align-self:stretch}

/* ---- social row -----------------------------------------------------
   Flush cells divided by single rules — the same cell grammar as the
   masthead language pair and the rail arrows. Mark above label, so the
   row reads without hovering. */
.bh-social{display:flex;border-top:var(--rule) solid var(--ink)}
.bh-social__cell{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:7px;padding:16px 8px;border-left:var(--rule) solid var(--ink)}
.bh-social__cell:first-child{border-left:0}
.bh-social__cell svg{width:22px;height:22px;display:block;stroke:var(--ink);stroke-width:1.75;fill:none}
.bh-social__cell span{font-size:10.5px;font-weight:700;letter-spacing:.16em;text-transform:uppercase}
.bh-social__cell:hover{background:var(--ink);color:var(--paper)}
.bh-social__cell:hover svg{stroke:var(--yellow)}
.bh-social__cell:focus-visible{outline:var(--rule-thick) solid var(--blue);outline-offset:-4px}
@media (max-width:680px){
  .bh-social__cell{padding:13px 4px;gap:5px}
  .bh-social__cell svg{width:19px;height:19px}
  .bh-social__cell span{font-size:8.5px}
  .bh-social__cell span{font-size:9px;letter-spacing:.1em}
}

/* video in the overlay — same box as an image so the banner and filmstrip do not
   reflow when an entry is a clip. */
.bh-ov__banner video,.bh-ov__banner img{width:100%;height:clamp(220px,42vh,420px);object-fit:cover;display:block}
.bh-film__track video{width:100%;height:var(--film-h);object-fit:cover;display:block;border-bottom:var(--rule) solid var(--ink);background:var(--ink)}
@media (max-width:680px){
  .bh-ov__banner video{height:clamp(180px,32vh,260px)}
}

/* tall character art in a wide band: crop from the TOP, not the centre. A 2:3
   figure in a 4:1 box cannot be contained without an 83% void, and a centred
   cover would keep only the skirt. */
.bh-ov__banner img.is-portrait{object-fit:cover;object-position:center 6%}
.bh-ov__banner img.is-bottom{object-position:right bottom}
.bh-ov__banner:has(img.is-portrait){height:clamp(360px,50vh,480px)}
.bh-ov__banner:has(img.is-portrait) img{height:100%}
.bh-film__track img.is-portrait{object-fit:cover;object-position:center 10%}
.bh-card__shot img.is-portrait,.bh-rcard__slot img.is-portrait{object-fit:cover;object-position:center 8%}

/* highlight list — one capability per ruled row. The rules do the separating, so
   the rows carry no marker. Scannable in a way a prose case study is not. */
.bh-hl{list-style:none;margin:18px 0 4px;padding:0;border-top:var(--rule) solid var(--ink)}
.bh-hl li{padding:12px 0;border-bottom:var(--rule) solid var(--ink);font-size:clamp(14px,1.05vw,16px);font-weight:400;line-height:1.4}

/* leave-a-note modal — the same ruled cells as the rest of the page, no rounding,
   no shadow.  */
.bh-pitch__copy--note{background:transparent;color:var(--ink);transition:background .15s ease,color .15s ease}
.bh-pitch__copy--note:hover{background:var(--yellow);color:var(--ink)}
.bh-note{position:fixed;inset:0;z-index:140;display:flex;align-items:center;justify-content:center;padding:var(--gut);background:rgba(20,17,15,.62)}
.bh-note[hidden]{display:none}
.bh-note__box{width:min(560px,100%);max-height:92vh;overflow:auto;background:var(--paper);border:var(--rule) solid var(--ink)}
.bh-note__bar{display:flex;align-items:stretch;justify-content:space-between;border-bottom:var(--rule) solid var(--ink)}
.bh-note__bar .t{display:flex;align-items:center;gap:12px;padding:0 var(--gut);font-weight:700;font-size:12px;letter-spacing:.2em;text-transform:uppercase}
.bh-note__bar .t .bh-dot{width:11px;height:11px}
.bh-note__body{padding:clamp(18px,2.4vw,28px) var(--gut)}
.bh-note__f{display:block;margin-bottom:16px}
.bh-note__f>span{display:block;font-size:10.5px;font-weight:700;letter-spacing:.2em;text-transform:uppercase;opacity:.55;margin-bottom:7px}
.bh-note__f input,.bh-note__f textarea{width:100%;font-family:var(--font);font-size:14px;color:var(--ink);background:var(--paper-2);border:var(--rule) solid var(--ink);border-radius:0;padding:11px 12px;outline:none;resize:vertical}
.bh-note__f input:focus,.bh-note__f textarea:focus{background:var(--paper);outline:var(--rule) solid var(--blue);outline-offset:-4px}
.bh-note__foot{display:flex;align-items:center;justify-content:space-between;gap:14px;flex-wrap:wrap;border-top:var(--rule) solid var(--ink);padding-top:16px}
.bh-note__to{font-size:12px;letter-spacing:.04em;opacity:.6}
.bh-note__foot .go{display:inline-flex;align-items:center;gap:10px;padding:13px 22px;background:var(--blue);color:var(--paper);border:0;font-family:var(--font);font-weight:700;font-size:13px;letter-spacing:.14em;text-transform:uppercase;cursor:pointer}
.bh-note__foot .go:hover{background:var(--red)}

/* second destination button — outlined so the primary link stays primary */
.bh-ov__txt .go[hidden]{display:none}
.bh-ov__txt .go--alt{margin-left:10px;background:var(--paper);color:var(--ink);box-shadow:inset 0 0 0 var(--rule) var(--ink)}
.bh-ov__txt .go--alt:hover{background:var(--ink);color:var(--paper)}

.bh-pitch__copy--note{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;gap:3px;padding:18px 34px;line-height:1.2;min-height:66px}
.bh-pitch__copy--note .l1{font-size:15px;letter-spacing:.16em}
.bh-pitch__copy--note .l2{font-size:11px;font-weight:500;letter-spacing:.12em;text-transform:lowercase;opacity:.7}

/* clip strip — a paused clip carries a play mark (the shape alphabet's triangle),
   so "click another one" is visible rather than implied. One plays at a time. */
.bh-film__track figure{position:relative}
.bh-film__track figure:has(video){cursor:pointer}
.bh-film__track figure:has(video)::after{content:"";position:absolute;left:50%;top:calc(var(--film-h) / 2);transform:translate(-50%,-50%);
  width:0;height:0;border-top:15px solid transparent;border-bottom:15px solid transparent;border-left:24px solid var(--paper);
  filter:drop-shadow(0 0 10px rgba(20,17,15,.55));pointer-events:none;transition:opacity .2s ease}
.bh-film__track figure.is-playing:has(video)::after{opacity:0}

/* One owner per boundary, by adjacency rather than by element: a manifesto draws
   its top rule only when it is first in its section. When anything precedes it,
   that element's own bottom rule is the boundary. */
* + .bh-mani{border-top:0}
.bh-mani:last-child{border-bottom:0}
/* the grid ends short when the card count is odd, so the following section
   supplies the closing rule across the full width */
.bh-grid + .bh-mani{border-top:var(--rule) solid var(--ink)}

/* per-clip fullscreen — a corner cell, separate from the play/pause tap so the
   two gestures never compete */
.bh-film__full{position:absolute;top:0;right:0;z-index:3;width:44px;height:44px;
  appearance:none;border:0;border-left:var(--rule) solid var(--ink);border-bottom:var(--rule) solid var(--ink);
  background:var(--paper);color:var(--ink);font-family:var(--font);font-size:17px;line-height:1;cursor:pointer}
.bh-film__full:hover{background:var(--yellow)}
.bh-film__full:focus-visible{outline:var(--rule-thick) solid var(--blue);outline-offset:-4px}

/* full-size still viewer — the same ruled, square language as the overlay */
.bh-lb{position:fixed;inset:0;z-index:160;display:none;align-items:center;justify-content:center;
  flex-direction:column;gap:0;padding:clamp(12px,3vw,40px);background:rgba(20,17,15,.9)}
.bh-lb.is-on{display:flex}
.bh-lb img{max-width:100%;max-height:82vh;object-fit:contain;border:var(--rule) solid var(--paper);background:var(--ink)}
.bh-lb__cap{margin-top:14px;max-width:74ch;font-size:13px;line-height:1.5;color:var(--paper);text-align:center}
.bh-lb__x{position:absolute;top:0;right:0;width:56px;height:56px;appearance:none;border:0;
  border-left:var(--rule) solid var(--paper);border-bottom:var(--rule) solid var(--paper);
  background:transparent;color:var(--paper);font-family:var(--font);font-size:20px;cursor:pointer}
.bh-lb__x:hover{background:var(--red)}

.bh-lb video{max-width:100%;max-height:82vh;border:var(--rule) solid var(--paper);background:var(--ink)}
.bh-lb img[hidden],.bh-lb video[hidden]{display:none}

/* phones: the language pair must never be the thing that overflows — it is the
   only control with no other route to it. Everything else yields first. */
.bh-lang{flex-shrink:0}
.bh-mast__mark,.bh-nav{min-width:0}
@media (max-width:560px){
  :root{--cell:44px}
  .bh-mast__mark{gap:0;padding:0 12px}
  .bh-mast__mark .bh-dot,.bh-mast__mark .bh-sq,.bh-mast__mark .bh-tri{display:none}
  .bh-mast__name{margin-left:0;font-size:13px;letter-spacing:.16em}
  .bh-nav a{padding:0 10px;font-size:10px;letter-spacing:.06em}
  .bh-lang button{font-size:11px;letter-spacing:.08em}
}

button.bh-social__cell{appearance:none;border-top:0;border-right:0;border-bottom:0;background:var(--paper);font-family:var(--font);color:var(--ink);cursor:pointer}
.bh-social__cell.is-copied{background:var(--blue);color:var(--paper)}
.bh-social__cell.is-copied svg{stroke:var(--yellow)}

/* Chinese display: Noto Sans SC Black (900) — a real heavy cut, not a browser
   faux-bold. Latin still resolves from Jost, which is listed first. */
html[data-lang="cn"] .bh-hero h1{font-family:var(--font-cn-display);letter-spacing:.005em;font-weight:900;line-height:.9}
html[data-lang="cn"] .bh-mani h2{font-family:var(--font-cn-display);letter-spacing:.01em;font-weight:900}
html[data-lang="cn"] .bh-ov__txt h2{font-family:var(--font-cn-display);font-weight:900}
html[data-lang="cn"] .bh-foot__q p{font-family:var(--font-cn-display);font-weight:900}

/* Only the 900 cut is downloaded; body CJK stays on the OS font, so micro labels
   must not ask for a weight that would pull another webfont in. */


/* figurine is a control: hover scales it up (like the rail GLBs), tap opens the key */
.bh-hero__fig canvas{cursor:pointer;transform-origin:center bottom;transition:transform .24s cubic-bezier(.2,.7,.2,1)}
.bh-hero__fig canvas:hover{transform:scale(1.07)}
.bh-hero__fig:hover .bh-hero__hint{opacity:1;transform:translateY(0)}
.bh-hero__hint{position:absolute;z-index:3;left:50%;bottom:8px;transform:translate(-50%,6px);pointer-events:none;font-size:11px;font-weight:700;letter-spacing:.18em;text-transform:uppercase;color:var(--paper);background:var(--ink);padding:5px 10px;opacity:0;transition:opacity .2s,transform .2s}
/* legend inside the key modal stacks, no footer border/padding */
.bh-legend--modal{padding:0;border-top:0;flex-direction:column;gap:16px}
.bh-key__note{margin:20px 0 0;font-size:13px;line-height:1.55;max-width:46ch;opacity:.7}
.bh-key__count{margin:18px 0 0;padding-top:14px;border-top:var(--rule) solid var(--ink);font-size:11px;letter-spacing:.06em;text-transform:uppercase;opacity:.55}
.bh-key__count b{font-weight:700;opacity:1}

/* ---- resolution hardening ------------------------------------------- */
/* 1. Short viewports (landscape phone, 13" laptop at 100% zoom): a 92vh box
   inside a var(--gut) padded overlay adds up to more than the screen, so the
   modal frame was clipped top and bottom. Subtract the padding it actually sits in. */
.bh-note__box{max-height:calc(100vh - var(--gut) * 2)}
.bh-lb img,.bh-lb video{max-height:calc(100vh - 150px)}

/* 2. Long titles in the project overlay bar collided with the close cell —
   "NANITE FOLIAGE SHADOW IMPOSTER" at .2em tracking is wider than a phone. */
.bh-ov__bar .t{min-width:0;flex:1;overflow:hidden}
.bh-ov__bar .t span:not([class]){overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bh-ov__x{flex:none}

/* 3. Control cells were pinned at 56px while the masthead steps down to 44px on
   phones, so the overlay bar and the top bar disagreed on the same screen. */
@media (max-width:560px){
  .bh-ov.is-on{grid-template-rows:var(--cell) 1fr}
  .bh-ov__x,.bh-lb__x{width:var(--cell);height:100%;align-self:stretch;font-size:17px}
  .bh-ov__bar .t{font-size:10.5px;letter-spacing:.12em;gap:8px}
  .bh-note__bar .t{font-size:10.5px;letter-spacing:.12em}
}

/* 4. Landscape phones: the key modal legend stacked to ~420px and the note plus
   counter pushed the close bar off. Two axes side by side reclaim the height. */
@media (max-height:520px) and (min-width:561px){
  .bh-legend--modal{flex-direction:row;gap:12px 40px}
  .bh-key__note{margin-top:14px;font-size:12px}
  .bh-key__count{margin-top:12px;padding-top:10px}
}
/* Shape placement follows the page's own gravity rule: the circle rises and bleeds
   off the TOP edge, the square lands and bleeds off the BOTTOM — each cut in half by
   the frame rather than floating free inside it. */
.bh-card__shot--art.art-dot .a1,.bh-ov__art.art-dot .a1{top:-33%;bottom:auto}
.bh-card__shot--art.art-sq .a1{bottom:-33%;top:auto;right:-14%}
.bh-ov__art.art-sq .a1{bottom:-31%;top:auto;right:-10%}
/* stills are their own control — no corner button, the picture opens full size */
#ovShots img,#ovBanner img{cursor:zoom-in}

/* detail block sits below the media strips: the reader sees the work, then reads
   what it is made of. Its own label bar keeps it from floating loose. */
.bh-ov__detail{border-top:var(--rule) solid var(--ink)}
.bh-ov__detail[hidden]{display:none}
.bh-ov__detail .bh-film__bar{border-top:0}
.bh-ov__detail .bh-ov__txt{padding-top:clamp(18px,2vw,28px)}


/* ---- responsive hardening (multi-resolution QA) --------------------- */
/* Mid-width band: the hero is still two columns here but the identity
   column is at its narrowest (33vw), so the display headline can collide
   with the rule. Ease the type down just in this range; wide screens keep
   the big headline, phones already stack to one column. */
@media (min-width:1001px) and (max-width:1300px){
  .bh-hero h1{font-size:clamp(34px,4.7vw,66px)}
}
/* Narrow phones: keep the enlarged résumé download row from crowding —
   the action cell and blurb step back so the three cells still fit 320px. */
@media (max-width:560px){
  .bh-dl__body{padding:18px 0}
  .bh-dl__body b{font-size:19px}
  .bh-dl__body em{font-size:12px}
  .bh-dl__mark{width:clamp(52px,14vw,64px)}
}
/* Never let a stray overflow introduce a horizontal scrollbar on the page
   itself; the rail and filmstrips keep their own internal x-scroll. */
body{overflow-x:hidden}


/* ---- compact project popup (WIP / under-wraps projects) --------------
   An in-development project shouldn't get the full-bleed project PAGE — it
   reads as a finished showcase. Instead the same overlay collapses into a
   centred modal card over a dimmed backdrop: present, but clearly a note,
   not a standalone piece. Triggered by data flag `compact:true`. */
.bh-ov--compact.is-on{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:0;background:rgba(20,17,15,.62);padding:clamp(16px,4vh,40px);grid-template-rows:none}
.bh-ov--compact .bh-ov__bar{width:min(600px,94vw);background:var(--paper);border:var(--rule) solid var(--ink)}
.bh-ov--compact .bh-ov__body{width:min(600px,94vw);max-height:min(76vh,700px);background:var(--paper);border:var(--rule) solid var(--ink);border-top:0;overflow:hidden}
.bh-ov--compact .bh-ov__banner img{height:clamp(150px,26vh,220px)}


/* compact popup with nothing to show yet: only the secret line, centred */
.bh-ov__secret{display:none;align-items:center;justify-content:center;min-height:clamp(160px,30vh,260px);padding:clamp(28px,6vh,56px);font-family:var(--display,inherit);font-weight:700;font-size:clamp(22px,3.4vw,38px);letter-spacing:-.01em;color:var(--ink);text-align:center}
.bh-ov--compact .bh-ov__banner,.bh-ov--compact #ovClips,.bh-ov--compact #ovFilm,.bh-ov--compact #ovDetail,.bh-ov--compact .bh-ov__txt{display:none!important}
.bh-ov--compact .bh-ov__secret{display:flex}

/* reserve the scrollbar track so locking scroll (opening an overlay) doesn't shift the page */
html{scrollbar-gutter:stable}


/* MSG-me note sits flush to the bio band's top and bottom rules, with a left
   rule — reads as a ruled cell, like the download button, not a floating chip. */
.bh-hero__bio .bh-pitch__copy--note{align-self:stretch;min-height:0;padding-top:0;padding-bottom:0;margin:-13px calc(var(--gut) * -1) -13px 0;border-left:var(--rule) solid var(--ink)}
@media (max-height:700px) and (min-width:681px){
  .bh-hero__bio .bh-pitch__copy--note{margin:-9px calc(var(--gut) * -1) -9px 0;padding-top:0;padding-bottom:0}
}
#ovDetailBar[hidden]{display:none}

/* phones: the bio stacks vertically, so the flush ruled-cell treatment (negative
   margins against the row) breaks — return the MSG button to a normal full-width
   ruled block under the paragraph. */
@media (max-width:680px){
  .bh-hero__bio .bh-pitch__copy--note{align-self:stretch;width:auto;margin:0 calc(var(--gut) * -1) -13px;border-left:0;border-top:var(--rule) solid var(--ink);padding:14px 22px;min-height:52px}
}


/* ---- project list rows (grid → horizontal strips) ------------------- */
.bh-grid{display:block}
.bh-row{position:relative;display:grid;grid-template-columns:var(--cell) clamp(150px,24vw,300px) minmax(0,1fr) var(--cell);align-items:stretch;width:100%;padding:0;margin:0;background:var(--paper);border:0;border-bottom:var(--rule) solid var(--ink);cursor:pointer;text-align:left;font:inherit;color:inherit}
.bh-grid .bh-card.bh-row{display:grid;border-right:0}
.bh-row[hidden],.bh-grid .bh-card.bh-row[hidden]{display:none}
.bh-row__num{display:flex;align-items:center;justify-content:center;background:var(--paper);color:var(--ink);font-weight:700;font-size:14px}
.bh-row__shot{position:relative;overflow:hidden;background:var(--paper-2);border-left:var(--rule) solid var(--ink);border-right:var(--rule) solid var(--ink);min-height:104px}
.bh-row__shot img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;filter:saturate(.92)}
.bh-row__txt{display:flex;flex-direction:column;gap:5px;padding:14px var(--gut)}
.bh-row__txt h3{margin:0;font-weight:700;font-size:clamp(16px,1.5vw,21px);line-height:1.14;letter-spacing:-.012em}
.bh-row__txt .bh-card__role{margin-top:auto;padding-top:10px;font-size:11px;font-weight:700;letter-spacing:.12em;text-transform:uppercase}
.bh-row__mark{display:flex;align-items:center;justify-content:center;border-left:var(--rule) solid var(--ink)}
.bh-row__mark .bh-dot,.bh-row__mark .bh-sq{width:16px;height:16px}
.bh-row__mark .bh-tri{--s:9px}
.bh-row:hover .bh-row__txt{background:var(--yellow)}
.bh-row:hover .bh-row__shot img{filter:saturate(1)}
.bh-row:focus-visible{outline:var(--rule-thick) solid var(--blue);outline-offset:-4px}
.bh-grid .bh-row:last-child{border-bottom:0}
.bh-row--toggle{grid-template-columns:var(--cell) minmax(0,1fr) var(--cell);min-height:56px}
.bh-row--toggle .bh-row__txt{justify-content:center}
.bh-row--toggle h3{margin:0;font-weight:700;font-size:13px;letter-spacing:.16em;text-transform:uppercase}
.bh-row--toggle .bh-row__num{font-size:20px}
.bh-row--toggle:hover .bh-row__txt{background:var(--yellow)}
@media (max-width:680px){
  .bh-row{grid-template-columns:var(--cell) clamp(110px,34vw,160px) minmax(0,1fr) var(--cell)}
  .bh-row__txt{padding:10px 14px}
  .bh-row__shot{min-height:88px}
  .bh-row--toggle{grid-template-columns:var(--cell) minmax(0,1fr) var(--cell)}
}


/* ---- overlay: downloads footer -------------------------------------- */
.bh-ov__dl{border-top:var(--rule) solid var(--ink)}
.bh-ov__dlList{display:flex;flex-direction:column}
.bh-ov__dlRow{display:grid;grid-template-columns:56px minmax(0,1fr) auto;align-items:stretch;text-decoration:none;color:inherit;border-bottom:var(--rule) solid var(--ink);background:var(--paper)}
.bh-ov__dlRow:last-child{border-bottom:0}
.bh-ov__dlMark{display:flex;align-items:center;justify-content:center;background:var(--ink);border-right:var(--rule) solid var(--ink)}
.bh-ov__dlMark .bh-tri{--s:9px;background:var(--paper)}
.bh-ov__dlTxt{display:flex;flex-direction:column;gap:3px;padding:14px var(--gut);min-width:0}
.bh-ov__dlTxt b{font-weight:700;font-size:15px;line-height:1.2;letter-spacing:-.01em}
.bh-ov__dlTxt em{font-style:normal;font-size:12px;line-height:1.4;opacity:.62;overflow-wrap:anywhere}
.bh-ov__dlAct{display:flex;align-items:center;padding:0 var(--gut);border-left:var(--rule) solid var(--ink);font-weight:700;font-size:13px;letter-spacing:.14em;text-transform:uppercase;white-space:nowrap}
.bh-ov__dlRow:hover .bh-ov__dlAct{background:var(--yellow)}
@media (max-width:560px){
  .bh-ov__dlRow{grid-template-columns:44px minmax(0,1fr) auto}
  .bh-ov__dlTxt{padding:12px 14px}
  .bh-ov__dlAct{padding:0 12px;font-size:11px;letter-spacing:.1em}
}


/* ---- write-up modal: in-site page viewer ---------------------------- */
.bh-wu{position:fixed;inset:0;z-index:200;display:flex;flex-direction:column;background:var(--paper)}
.bh-wu[hidden]{display:none}
.bh-wu__bar{display:flex;align-items:center;gap:14px;height:var(--cell);padding:0 0 0 var(--gut);border-bottom:var(--rule) solid var(--ink);background:var(--paper)}
.bh-wu__bar .t{display:flex;align-items:center;gap:10px;font-weight:700;font-size:13px;letter-spacing:.12em;text-transform:uppercase;min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;flex:1}
.bh-wu__bar .t .bh-sq{width:12px;height:12px;flex:none}
.bh-wu__open{display:flex;align-items:center;align-self:stretch;padding:0 18px;border-left:var(--rule) solid var(--ink);font-weight:700;font-size:12px;letter-spacing:.12em;text-transform:uppercase;text-decoration:none;color:inherit;white-space:nowrap}
.bh-wu__open:hover{background:var(--yellow);color:var(--ink)}
.bh-wu .bh-ov__x{align-self:stretch;height:auto}
.bh-wu__frame{flex:1;width:100%;border:0;background:var(--paper)}
.bh-ov__dlRow--doc .bh-ov__dlMark .bh-sq{width:12px;height:12px;background:var(--paper)}
@media (max-width:560px){.bh-wu__open span{display:none}.bh-wu__open::after{content:'↗'}}

.bh-hero__fig[hidden]{display:none}

/* ---- hero without the figurine: type column, headline anchored low ---- */
.bh-hero__left{position:relative;overflow:hidden;justify-content:space-between;padding-bottom:clamp(56px,13vh,150px)}
.bh-hero__left h1{position:relative;z-index:1}
.bh-hero__left h1[data-lang="en"]{font-size:clamp(38px,min(5.4vw,13vh),112px)}
.bh-hero__left h1[data-lang="cn"]{font-size:clamp(52px,min(8.4vw,16vh),156px);line-height:.94}
.bh-hero__disc{position:absolute;z-index:0;top:0;right:0;width:52%;aspect-ratio:1;border-radius:50%;background:var(--yellow);transform:translate(32%,-32%);pointer-events:none}
@media (max-width:1000px){
  .bh-hero__left{min-height:0;gap:clamp(28px,6vh,60px)}
  .bh-hero__left h1[data-lang="en"]{font-size:clamp(44px,13vw,96px)}
  .bh-hero__left h1[data-lang="cn"]{font-size:clamp(60px,19vw,132px)}
  .bh-hero__disc{width:min(40%,220px)}
}

/* ---- hero: the bio IS the statement (big headline + Msg Me removed) ---- */
.bh-hero__left .bh-hero__bio{position:relative;z-index:1;padding:0;border:0}
.bh-hero__left .bh-hero__bio p{font-size:clamp(19px,1.75vw,30px);line-height:1.38;letter-spacing:-.01em;font-weight:500;text-wrap:pretty}
.bh-hero__left .bh-hero__bio em{box-shadow:inset 0 -3px 0 var(--ink)}
@media (max-width:1000px){
  .bh-hero__left .bh-hero__bio p{font-size:clamp(18px,4.6vw,26px)}
  .bh-hero__left{padding-top:calc(min(26vw,150px) * .72)}
  .bh-hero__disc{width:min(26vw,150px)}
}

/* ---- hero identity: name + ruled credential cells ------------------- */
.bh-hero__left{padding-bottom:0}
.bh-hero__id{position:relative;z-index:1;display:flex;flex-direction:column;gap:clamp(18px,3vh,32px);margin:0 calc(-1 * var(--gut))}
.bh-hero__name{margin:0;padding:0 var(--gut);font-weight:900;text-transform:uppercase;letter-spacing:-.04em;line-height:.84}
.bh-hero__id[data-lang="en"] .bh-hero__name{font-size:clamp(56px,min(7.2vw,14vh),150px)}
.bh-hero__id[data-lang="cn"] .bh-hero__name{font-size:clamp(64px,min(8.4vw,16vh),168px);letter-spacing:-.02em;line-height:1}
.bh-hero__name .r{color:var(--red)}
.bh-cred{list-style:none;margin:0;padding:0;border-top:var(--rule) solid var(--ink)}
.bh-cred li{display:grid;grid-template-columns:var(--cell) minmax(0,1fr);border-bottom:var(--rule) solid var(--ink);min-height:clamp(56px,7.4vh,76px)}
.bh-cred li:last-child{border-bottom:0}
.bh-cred .m{display:flex;align-items:center;justify-content:center;border-right:var(--rule) solid var(--ink)}
.bh-cred .m i{display:block;width:16px;height:16px}
.bh-cred .m .c{border-radius:50%;background:var(--red)}
.bh-cred .m .s{background:var(--blue)}
.bh-cred .m .tr{width:18px;height:16px;background:var(--ink);clip-path:polygon(50% 0,100% 100%,0 100%)}
.bh-cred .t{display:flex;flex-direction:column;justify-content:center;gap:3px;padding:10px var(--gut);min-width:0}
.bh-cred .t b{font-weight:700;font-size:clamp(15px,1.15vw,19px);line-height:1.2;letter-spacing:-.005em}
.bh-cred .t em{font-style:normal;font-size:clamp(11px,.8vw,13px);font-weight:700;letter-spacing:.12em;text-transform:uppercase;opacity:.62}
.bh-hero__id[data-lang="cn"] .bh-cred .t em{letter-spacing:.06em}
@media (max-width:1000px){
  .bh-hero__id{margin-top:clamp(20px,4vh,40px)}
  .bh-hero__id[data-lang="en"] .bh-hero__name{font-size:clamp(56px,16vw,120px)}
  .bh-hero__id[data-lang="cn"] .bh-hero__name{font-size:clamp(64px,20vw,140px)}
  .bh-cred .t b{font-size:16px}.bh-cred .t em{font-size:11px}
}

/* ---- hero type: bigger small text ---- */
.bh-hero__eyebrow{font-size:clamp(14px,1.05vw,18px);letter-spacing:.18em;gap:12px}
.bh-hero__eyebrow .bh-dot{width:12px;height:12px}
.bh-cred li{min-height:clamp(64px,8.6vh,92px)}
.bh-cred .m i{width:20px;height:20px}
.bh-cred .m .tr{width:22px;height:19px}
.bh-cred .t{gap:5px}
.bh-cred .t b{font-size:clamp(18px,1.45vw,25px)}
.bh-cred .t em{font-size:clamp(13px,.95vw,16px)}
@media (max-width:1000px){.bh-hero__eyebrow{font-size:14px}.bh-cred .t b{font-size:19px}.bh-cred .t em{font-size:13px}}

.bh-hero__name .b{color:var(--blue)}.bh-hero__name .y{color:var(--yellow)}
.bh-cred .m .tr{background:var(--yellow)}

/* ---- compact hero: no disc, content packed from the top, cells fill ---- */
.bh-hero__disc{display:none}
.bh-hero__left{justify-content:flex-start;padding-bottom:0}
.bh-hero__eyebrow{margin-bottom:clamp(14px,2.4vh,26px)}
.bh-hero__id{flex:1;min-height:0}
.bh-cred{flex:1;display:flex;flex-direction:column}
.bh-cred li{flex:1}
@media (max-width:1000px){.bh-hero__left{padding-top:clamp(20px,3vh,38px)}.bh-hero__id{margin-top:0}}

/* ---- tighter hero: height follows the identity column, rail shrinks with it ---- */
@media (min-width:1001px){.bh-hero{height:auto;grid-template-rows:auto auto}}
.bh-hero__id{flex:none}
.bh-cred{flex:none;display:block}
.bh-cred li{flex:none;min-height:0}
.bh-cred .t{padding:9px var(--gut)}
.bh-cred .t{gap:2px}
.bh-hero__id{gap:clamp(14px,2.2vh,24px)}

/* ---- rail: header bar removed; a ruled scrollbar along the bottom instead ---- */
:root{--sb:12px}
.bh-rail__track{scrollbar-width:thin;scrollbar-color:var(--ink) var(--paper-2)}
.bh-rail__track::-webkit-scrollbar{display:block;height:var(--sb)}
.bh-rail__track::-webkit-scrollbar-track{background:var(--paper-2);border-top:var(--rule) solid var(--ink)}
.bh-rail__track::-webkit-scrollbar-thumb{background:var(--ink);border-radius:0}
.bh-rail__track::-webkit-scrollbar-thumb:hover{background:var(--blue)}
.bh-rail__gl{height:calc(100% - var(--cap) - var(--rule) - var(--sb))}

/* ---- rail scrollbar: bigger, ruled like the rest of the page ---- */
:root{--sb:22px}
.bh-rail__track{scrollbar-width:auto;scrollbar-color:var(--ink) var(--paper)}
.bh-rail__track::-webkit-scrollbar{height:var(--sb)}
.bh-rail__track::-webkit-scrollbar-track{background:var(--paper);border-top:var(--rule) solid var(--ink)}
.bh-rail__track::-webkit-scrollbar-thumb{background:var(--ink);border:0;border-top:var(--rule) solid var(--ink);border-radius:0;min-width:80px}
.bh-rail__track::-webkit-scrollbar-thumb:hover,.bh-rail__track::-webkit-scrollbar-thumb:active{background:var(--yellow);border-left:var(--rule) solid var(--ink);border-right:var(--rule) solid var(--ink)}
.bh-rail__track::-webkit-scrollbar-button{display:none}
.bh-rail__track::-webkit-scrollbar-corner{background:var(--paper)}

/* ---- resume download: label centered in its cell ---- */
.bh-dl__card{position:relative}
.bh-dl__body{flex:1;align-items:center;justify-content:center;text-align:center}

/* ---- modal action buttons: ruled cell, same as the rest of the page ---- */
.bh-note .go{appearance:none;display:inline-flex;align-items:center;justify-content:center;min-height:48px;padding:0 22px;background:var(--paper);color:var(--ink);border:var(--rule) solid var(--ink);border-radius:0;box-shadow:none;font-family:var(--font);font-weight:700;font-size:13px;letter-spacing:.14em;text-transform:uppercase;cursor:pointer;transition:background .15s ease}
.bh-note .go:hover,.bh-note .go:focus-visible{background:var(--yellow);color:var(--ink);outline:none}
.bh-note .go:active{background:var(--ink);color:var(--paper)}

/* ---- contact modals: centered, larger ink text ---- */
.bh-note .bh-note__body{display:flex;flex-direction:column;align-items:center;text-align:center}
.bh-note .bh-key__note{color:var(--ink);opacity:1;font-size:clamp(17px,1.4vw,21px);line-height:1.5}
.bh-note .bh-key__note b{color:var(--ink);font-weight:700}
.bh-note .bh-note__foot{display:flex;justify-content:center;width:100%}

/* ---- project rows: readable — left-aligned, vertically centered, larger type ---- */
.bh-row{grid-template-columns:52px clamp(200px,30vw,480px) minmax(0,1fr) 52px}
.bh-row__shot{min-height:clamp(120px,11vw,170px)}
.bh-row .bh-row__txt{justify-content:center;gap:8px;padding:18px clamp(24px,3vw,48px);max-width:72ch}
.bh-row .bh-row__txt h3{font-size:clamp(20px,1.8vw,28px)}
.bh-row .bh-row__txt .bh-card__sub{font-size:clamp(14px,1.05vw,16px);line-height:1.45;opacity:.78}
.bh-row .bh-row__txt .bh-card__role{margin-top:4px;padding-top:0;font-size:12px}
@media (max-width:680px){
  .bh-row{grid-template-columns:44px clamp(110px,34vw,160px) minmax(0,1fr) 44px}
  .bh-row__shot{min-height:96px}
  .bh-row .bh-row__txt{padding:12px 14px;gap:5px}
  .bh-row .bh-row__txt h3{font-size:18px}
  .bh-row .bh-row__txt .bh-card__sub{font-size:13px}
}

.bh-row.bh-row--toggle{grid-template-columns:52px minmax(0,1fr) 52px}
@media (max-width:680px){.bh-row.bh-row--toggle{grid-template-columns:44px minmax(0,1fr) 44px}}

/* ---- project rows: thumbnail's right rule lines up with the hero's column rule ---- */
@media (min-width:1001px){.bh-row{grid-template-columns:52px calc(100% / 3 - 52px) minmax(0,1fr) 52px}.bh-row.bh-row--toggle{grid-template-columns:52px minmax(0,1fr) 52px}}

/* ---- resume download: label centered on the page, not inside the leftover cell ---- */
.bh-dl__card{position:relative;min-height:clamp(66px,8vh,84px)}
.bh-dl__body{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;text-align:center;padding:0;pointer-events:none}

#ovCount,#ovClipCount{display:none}

/* ---- rail scrollbar: Chrome 121+ ignores ::-webkit-scrollbar once scrollbar-color/width
   are set, which is why it showed rounded with arrows. Standard props only for Firefox. ---- */
.bh-rail__track{scrollbar-width:unset;scrollbar-color:unset}
@supports (-moz-appearance:none){.bh-rail__track{scrollbar-width:auto;scrollbar-color:var(--ink) var(--paper)}}
.bh-rail__track::-webkit-scrollbar{display:block;height:var(--sb);background:var(--paper)}
.bh-rail__track::-webkit-scrollbar-track{background:var(--paper);border-top:var(--rule) solid var(--ink);border-radius:0}
.bh-rail__track::-webkit-scrollbar-thumb{background:var(--ink);border:0;border-radius:0}
.bh-rail__track::-webkit-scrollbar-thumb:hover,.bh-rail__track::-webkit-scrollbar-thumb:active{background:var(--ink)}
.bh-rail__track::-webkit-scrollbar-button{display:none;width:0;height:0}

/* ---- rail scrollbar: readable as a scrollbar — light channel, inset black slider ---- */
.bh-rail__track::-webkit-scrollbar{height:var(--sb);background:var(--paper-2)}
.bh-rail__track::-webkit-scrollbar-track{background:var(--paper-2);border-top:var(--rule) solid var(--ink);border-bottom:var(--rule) solid var(--ink)}
.bh-rail__track::-webkit-scrollbar-thumb{background:var(--ink);background-clip:padding-box;border:5px solid transparent;border-radius:0}
.bh-rail__track::-webkit-scrollbar-thumb:hover,.bh-rail__track::-webkit-scrollbar-thumb:active{background:var(--ink);background-clip:padding-box;border:4px solid transparent}
@supports (-moz-appearance:none){.bh-rail__track{scrollbar-color:var(--ink) var(--paper-2)}}
